xref: /AOO41X/main/sdext/source/presenter/PresenterTextView.cxx (revision 79aad27f7f29270c03e208e3d687e8e3850af11d)
1*c142477cSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*c142477cSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*c142477cSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*c142477cSAndrew Rist  * distributed with this work for additional information
6*c142477cSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*c142477cSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*c142477cSAndrew Rist  * "License"); you may not use this file except in compliance
9*c142477cSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*c142477cSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*c142477cSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*c142477cSAndrew Rist  * software distributed under the License is distributed on an
15*c142477cSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*c142477cSAndrew Rist  * KIND, either express or implied.  See the License for the
17*c142477cSAndrew Rist  * specific language governing permissions and limitations
18*c142477cSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*c142477cSAndrew Rist  *************************************************************/
21*c142477cSAndrew Rist 
22*c142477cSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "precompiled_sdext.hxx"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include "PresenterTextView.hxx"
27cdf0e10cSrcweir #include "PresenterCanvasHelper.hxx"
28cdf0e10cSrcweir #include "PresenterGeometryHelper.hxx"
29cdf0e10cSrcweir #include "PresenterTimer.hxx"
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <cmath>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <com/sun/star/accessibility/AccessibleTextType.hpp>
34cdf0e10cSrcweir #include <com/sun/star/container/XEnumerationAccess.hpp>
35cdf0e10cSrcweir #include <com/sun/star/i18n/CharType.hpp>
36cdf0e10cSrcweir #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
37cdf0e10cSrcweir #include <com/sun/star/i18n/CTLScriptType.hpp>
38cdf0e10cSrcweir #include <com/sun/star/i18n/ScriptDirection.hpp>
39cdf0e10cSrcweir #include <com/sun/star/i18n/WordType.hpp>
40cdf0e10cSrcweir #include <com/sun/star/rendering/CompositeOperation.hpp>
41cdf0e10cSrcweir #include <com/sun/star/rendering/TextDirection.hpp>
42cdf0e10cSrcweir #include <com/sun/star/text/WritingMode2.hpp>
43cdf0e10cSrcweir #include <boost/bind.hpp>
44cdf0e10cSrcweir 
45cdf0e10cSrcweir using namespace ::com::sun::star;
46cdf0e10cSrcweir using namespace ::com::sun::star::accessibility;
47cdf0e10cSrcweir using namespace ::com::sun::star::uno;
48cdf0e10cSrcweir 
49cdf0e10cSrcweir #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
50cdf0e10cSrcweir 
51cdf0e10cSrcweir const static sal_Int64 CaretBlinkIntervall = 500 * 1000 * 1000;
52cdf0e10cSrcweir 
53cdf0e10cSrcweir //#define SHOW_CHARACTER_BOXES
54cdf0e10cSrcweir 
55cdf0e10cSrcweir namespace {
Signum(const sal_Int32 nValue)56cdf0e10cSrcweir     sal_Int32 Signum (const sal_Int32 nValue)
57cdf0e10cSrcweir     {
58cdf0e10cSrcweir         if (nValue < 0)
59cdf0e10cSrcweir             return -1;
60cdf0e10cSrcweir         else if (nValue > 0)
61cdf0e10cSrcweir             return +1;
62cdf0e10cSrcweir         else
63cdf0e10cSrcweir             return 0;
64cdf0e10cSrcweir     }
65cdf0e10cSrcweir }
66cdf0e10cSrcweir 
67cdf0e10cSrcweir namespace sdext { namespace presenter {
68cdf0e10cSrcweir 
69cdf0e10cSrcweir 
70cdf0e10cSrcweir //===== PresenterTextView =====================================================
71cdf0e10cSrcweir 
PresenterTextView(const Reference<XComponentContext> & rxContext,const Reference<rendering::XCanvas> & rxCanvas,const::boost::function<void (const::css::awt::Rectangle &)> & rInvalidator)72cdf0e10cSrcweir PresenterTextView::PresenterTextView (
73cdf0e10cSrcweir     const Reference<XComponentContext>& rxContext,
74cdf0e10cSrcweir     const Reference<rendering::XCanvas>& rxCanvas,
75cdf0e10cSrcweir     const ::boost::function<void(const ::css::awt::Rectangle&)>& rInvalidator)
76cdf0e10cSrcweir     : mxCanvas(rxCanvas),
77cdf0e10cSrcweir       mbDoOuput(true),
78cdf0e10cSrcweir       mxBreakIterator(),
79cdf0e10cSrcweir       mxScriptTypeDetector(),
80cdf0e10cSrcweir       maLocation(0,0),
81cdf0e10cSrcweir       maSize(0,0),
82cdf0e10cSrcweir       mpFont(),
83cdf0e10cSrcweir       maParagraphs(),
84cdf0e10cSrcweir       mpCaret(new PresenterTextCaret(
85cdf0e10cSrcweir           ::boost::bind(&PresenterTextView::GetCaretBounds, this, _1, _2),
86cdf0e10cSrcweir           rInvalidator)),
87cdf0e10cSrcweir       mnLeftOffset(0),
88cdf0e10cSrcweir       mnTopOffset(0),
89cdf0e10cSrcweir       maInvalidator(rInvalidator),
90cdf0e10cSrcweir       mbIsFormatPending(false),
91cdf0e10cSrcweir       mnCharacterCount(-1),
92cdf0e10cSrcweir       maTextChangeBroadcaster()
93cdf0e10cSrcweir {
94cdf0e10cSrcweir     Reference<lang::XMultiComponentFactory> xFactory (
95cdf0e10cSrcweir         rxContext->getServiceManager(), UNO_QUERY);
96cdf0e10cSrcweir     if ( ! xFactory.is())
97cdf0e10cSrcweir         return;
98cdf0e10cSrcweir 
99cdf0e10cSrcweir     // Create the break iterator that we use to break text into lines.
100cdf0e10cSrcweir     mxBreakIterator = Reference<i18n::XBreakIterator>(
101cdf0e10cSrcweir         xFactory->createInstanceWithContext(
102cdf0e10cSrcweir             A2S("com.sun.star.i18n.BreakIterator"),
103cdf0e10cSrcweir             rxContext),
104cdf0e10cSrcweir         UNO_QUERY_THROW);
105cdf0e10cSrcweir 
106cdf0e10cSrcweir     // Create the script type detector that is used to split paragraphs into
107cdf0e10cSrcweir     // portions of the same text direction.
108cdf0e10cSrcweir     mxScriptTypeDetector = Reference<i18n::XScriptTypeDetector>(
109cdf0e10cSrcweir         xFactory->createInstanceWithContext(
110cdf0e10cSrcweir             A2S("com.sun.star.i18n.ScriptTypeDetector"),
111cdf0e10cSrcweir             rxContext),
112cdf0e10cSrcweir         UNO_QUERY_THROW);
113cdf0e10cSrcweir }
114cdf0e10cSrcweir 
115cdf0e10cSrcweir 
116cdf0e10cSrcweir 
117cdf0e10cSrcweir 
PresenterTextView(const Reference<XComponentContext> & rxContext,const Reference<rendering::XCanvas> & rxCanvas)118cdf0e10cSrcweir PresenterTextView::PresenterTextView (
119cdf0e10cSrcweir     const Reference<XComponentContext>& rxContext,
120cdf0e10cSrcweir     const Reference<rendering::XCanvas>& rxCanvas)
121cdf0e10cSrcweir     : mxCanvas(rxCanvas),
122cdf0e10cSrcweir       mbDoOuput(false),
123cdf0e10cSrcweir       mxBreakIterator(),
124cdf0e10cSrcweir       mxScriptTypeDetector(),
125cdf0e10cSrcweir       maLocation(0,0),
126cdf0e10cSrcweir       maSize(0,0),
127cdf0e10cSrcweir       mpFont(),
128cdf0e10cSrcweir       maParagraphs(),
129cdf0e10cSrcweir       mpCaret(new PresenterTextCaret(
130cdf0e10cSrcweir           ::boost::bind(&PresenterTextView::GetCaretBounds, this, _1, _2),
131cdf0e10cSrcweir           ::boost::function<void(const css::awt::Rectangle&)>())),
132cdf0e10cSrcweir       mnLeftOffset(0),
133cdf0e10cSrcweir       mnTopOffset(0),
134cdf0e10cSrcweir       maInvalidator(),
135cdf0e10cSrcweir       mbIsFormatPending(false),
136cdf0e10cSrcweir       mnCharacterCount(-1),
137cdf0e10cSrcweir       maTextChangeBroadcaster()
138cdf0e10cSrcweir {
139cdf0e10cSrcweir     Reference<lang::XMultiComponentFactory> xFactory (
140cdf0e10cSrcweir         rxContext->getServiceManager(), UNO_QUERY);
141cdf0e10cSrcweir     if ( ! xFactory.is())
142cdf0e10cSrcweir         return;
143cdf0e10cSrcweir 
144cdf0e10cSrcweir     // Create the break iterator that we use to break text into lines.
145cdf0e10cSrcweir     mxBreakIterator = Reference<i18n::XBreakIterator>(
146cdf0e10cSrcweir         xFactory->createInstanceWithContext(
147cdf0e10cSrcweir             A2S("com.sun.star.i18n.BreakIterator"),
148cdf0e10cSrcweir             rxContext),
149cdf0e10cSrcweir         UNO_QUERY_THROW);
150cdf0e10cSrcweir 
151cdf0e10cSrcweir     // Create the script type detector that is used to split paragraphs into
152cdf0e10cSrcweir     // portions of the same text direction.
153cdf0e10cSrcweir     mxScriptTypeDetector = Reference<i18n::XScriptTypeDetector>(
154cdf0e10cSrcweir         xFactory->createInstanceWithContext(
155cdf0e10cSrcweir             A2S("com.sun.star.i18n.ScriptTypeDetector"),
156cdf0e10cSrcweir             rxContext),
157cdf0e10cSrcweir         UNO_QUERY_THROW);
158cdf0e10cSrcweir }
159cdf0e10cSrcweir 
160cdf0e10cSrcweir 
161cdf0e10cSrcweir 
162cdf0e10cSrcweir 
SetText(const Reference<text::XText> & rxText)163cdf0e10cSrcweir void PresenterTextView::SetText (const Reference<text::XText>& rxText)
164cdf0e10cSrcweir {
165cdf0e10cSrcweir     maParagraphs.clear();
166cdf0e10cSrcweir     mnCharacterCount = -1;
167cdf0e10cSrcweir 
168cdf0e10cSrcweir     Reference<container::XEnumerationAccess> xParagraphAccess (rxText, UNO_QUERY);
169cdf0e10cSrcweir     if ( ! xParagraphAccess.is())
170cdf0e10cSrcweir         return;
171cdf0e10cSrcweir 
172cdf0e10cSrcweir     Reference<container::XEnumeration> xParagraphs (
173cdf0e10cSrcweir         xParagraphAccess->createEnumeration() , UNO_QUERY);
174cdf0e10cSrcweir     if ( ! xParagraphs.is())
175cdf0e10cSrcweir         return;
176cdf0e10cSrcweir 
177cdf0e10cSrcweir     if ( ! mpFont || ! mpFont->PrepareFont(mxCanvas))
178cdf0e10cSrcweir         return;
179cdf0e10cSrcweir 
180cdf0e10cSrcweir     sal_Int32 nCharacterCount (0);
181cdf0e10cSrcweir     while (xParagraphs->hasMoreElements())
182cdf0e10cSrcweir     {
183cdf0e10cSrcweir         SharedPresenterTextParagraph pParagraph (new PresenterTextParagraph(
184cdf0e10cSrcweir             maParagraphs.size(),
185cdf0e10cSrcweir             mxBreakIterator,
186cdf0e10cSrcweir             mxScriptTypeDetector,
187cdf0e10cSrcweir             Reference<text::XTextRange>(xParagraphs->nextElement(), UNO_QUERY),
188cdf0e10cSrcweir             mpCaret));
189cdf0e10cSrcweir         pParagraph->SetupCellArray(mpFont);
190cdf0e10cSrcweir         pParagraph->SetCharacterOffset(nCharacterCount);
191cdf0e10cSrcweir         nCharacterCount += pParagraph->GetCharacterCount();
192cdf0e10cSrcweir         maParagraphs.push_back(pParagraph);
193cdf0e10cSrcweir     }
194cdf0e10cSrcweir 
195cdf0e10cSrcweir     if (mpCaret)
196cdf0e10cSrcweir         mpCaret->HideCaret();
197cdf0e10cSrcweir 
198cdf0e10cSrcweir     RequestFormat();
199cdf0e10cSrcweir }
200cdf0e10cSrcweir 
201cdf0e10cSrcweir 
202cdf0e10cSrcweir 
203cdf0e10cSrcweir 
SetText(const::rtl::OUString & rsText)204cdf0e10cSrcweir void PresenterTextView::SetText (const ::rtl::OUString& rsText)
205cdf0e10cSrcweir {
206cdf0e10cSrcweir     maParagraphs.clear();
207cdf0e10cSrcweir     mnCharacterCount = -1;
208cdf0e10cSrcweir 
209cdf0e10cSrcweir     if ( ! mpFont || ! mpFont->PrepareFont(mxCanvas))
210cdf0e10cSrcweir         return;
211cdf0e10cSrcweir 
212cdf0e10cSrcweir     sal_Int32 nCharacterCount (0);
213cdf0e10cSrcweir 
214cdf0e10cSrcweir     SharedPresenterTextParagraph pParagraph (new PresenterTextParagraph(
215cdf0e10cSrcweir         0,
216cdf0e10cSrcweir         mxBreakIterator,
217cdf0e10cSrcweir         mxScriptTypeDetector,
218cdf0e10cSrcweir         rsText,
219cdf0e10cSrcweir         mpCaret));
220cdf0e10cSrcweir     pParagraph->SetupCellArray(mpFont);
221cdf0e10cSrcweir     pParagraph->SetCharacterOffset(nCharacterCount);
222cdf0e10cSrcweir     nCharacterCount += pParagraph->GetCharacterCount();
223cdf0e10cSrcweir     maParagraphs.push_back(pParagraph);
224cdf0e10cSrcweir 
225cdf0e10cSrcweir     if (mpCaret)
226cdf0e10cSrcweir         mpCaret->HideCaret();
227cdf0e10cSrcweir 
228cdf0e10cSrcweir     RequestFormat();
229cdf0e10cSrcweir }
230cdf0e10cSrcweir 
231cdf0e10cSrcweir 
232cdf0e10cSrcweir 
233cdf0e10cSrcweir 
SetTextChangeBroadcaster(const::boost::function<void (void)> & rBroadcaster)234cdf0e10cSrcweir void PresenterTextView::SetTextChangeBroadcaster (
235cdf0e10cSrcweir     const ::boost::function<void(void)>& rBroadcaster)
236cdf0e10cSrcweir {
237cdf0e10cSrcweir     maTextChangeBroadcaster = rBroadcaster;
238cdf0e10cSrcweir }
239cdf0e10cSrcweir 
240cdf0e10cSrcweir 
241cdf0e10cSrcweir 
242cdf0e10cSrcweir 
SetLocation(const css::geometry::RealPoint2D & rLocation)243cdf0e10cSrcweir void PresenterTextView::SetLocation (const css::geometry::RealPoint2D& rLocation)
244cdf0e10cSrcweir {
245cdf0e10cSrcweir     maLocation = rLocation;
246cdf0e10cSrcweir 
247cdf0e10cSrcweir     for (::std::vector<SharedPresenterTextParagraph>::iterator
248cdf0e10cSrcweir              iParagraph(maParagraphs.begin()),
249cdf0e10cSrcweir              iEnd(maParagraphs.end());
250cdf0e10cSrcweir          iParagraph!=iEnd;
251cdf0e10cSrcweir          ++iParagraph)
252cdf0e10cSrcweir     {
253cdf0e10cSrcweir         (*iParagraph)->SetOrigin(
254cdf0e10cSrcweir             maLocation.X - mnLeftOffset,
255cdf0e10cSrcweir             maLocation.Y - mnTopOffset);
256cdf0e10cSrcweir     }
257cdf0e10cSrcweir }
258cdf0e10cSrcweir 
259cdf0e10cSrcweir 
260cdf0e10cSrcweir 
261cdf0e10cSrcweir 
SetSize(const css::geometry::RealSize2D & rSize)262cdf0e10cSrcweir void PresenterTextView::SetSize (const css::geometry::RealSize2D& rSize)
263cdf0e10cSrcweir {
264cdf0e10cSrcweir     maSize = rSize;
265cdf0e10cSrcweir     RequestFormat();
266cdf0e10cSrcweir }
267cdf0e10cSrcweir 
268cdf0e10cSrcweir 
269cdf0e10cSrcweir 
270cdf0e10cSrcweir 
GetTotalTextHeight(void)271cdf0e10cSrcweir double PresenterTextView::GetTotalTextHeight (void)
272cdf0e10cSrcweir {
273cdf0e10cSrcweir     double nTotalHeight (0);
274cdf0e10cSrcweir 
275cdf0e10cSrcweir     if (mbIsFormatPending)
276cdf0e10cSrcweir     {
277cdf0e10cSrcweir         if ( ! mpFont->PrepareFont(mxCanvas))
278cdf0e10cSrcweir             return 0;
279cdf0e10cSrcweir         Format();
280cdf0e10cSrcweir     }
281cdf0e10cSrcweir 
282cdf0e10cSrcweir     for (::std::vector<SharedPresenterTextParagraph>::iterator
283cdf0e10cSrcweir              iParagraph(maParagraphs.begin()),
284cdf0e10cSrcweir              iEnd(maParagraphs.end());
285cdf0e10cSrcweir          iParagraph!=iEnd;
286cdf0e10cSrcweir          ++iParagraph)
287cdf0e10cSrcweir     {
288cdf0e10cSrcweir         nTotalHeight += (*iParagraph)->GetTotalTextHeight();
289cdf0e10cSrcweir     }
290cdf0e10cSrcweir 
291cdf0e10cSrcweir     return nTotalHeight;
292cdf0e10cSrcweir }
293cdf0e10cSrcweir 
294cdf0e10cSrcweir 
295cdf0e10cSrcweir 
296cdf0e10cSrcweir 
SetFont(const PresenterTheme::SharedFontDescriptor & rpFont)297cdf0e10cSrcweir void PresenterTextView::SetFont (const PresenterTheme::SharedFontDescriptor& rpFont)
298cdf0e10cSrcweir {
299cdf0e10cSrcweir     mpFont = rpFont;
300cdf0e10cSrcweir     RequestFormat();
301cdf0e10cSrcweir }
302cdf0e10cSrcweir 
303cdf0e10cSrcweir 
304cdf0e10cSrcweir 
305cdf0e10cSrcweir 
SetOffset(const double nLeft,const double nTop)306cdf0e10cSrcweir void PresenterTextView::SetOffset(
307cdf0e10cSrcweir     const double nLeft,
308cdf0e10cSrcweir     const double nTop)
309cdf0e10cSrcweir {
310cdf0e10cSrcweir     mnLeftOffset = nLeft;
311cdf0e10cSrcweir     mnTopOffset = nTop;
312cdf0e10cSrcweir 
313cdf0e10cSrcweir     // Trigger an update of the text origin stored at the individual paragraphs.
314cdf0e10cSrcweir     SetLocation(maLocation);
315cdf0e10cSrcweir }
316cdf0e10cSrcweir 
317cdf0e10cSrcweir 
318cdf0e10cSrcweir 
MoveCaret(const sal_Int32 nDistance,const sal_Int16 nTextType)319cdf0e10cSrcweir void PresenterTextView::MoveCaret (
320cdf0e10cSrcweir     const sal_Int32 nDistance,
321cdf0e10cSrcweir     const sal_Int16 nTextType)
322cdf0e10cSrcweir {
323cdf0e10cSrcweir     if ( ! mpCaret)
324cdf0e10cSrcweir         return;
325cdf0e10cSrcweir 
326cdf0e10cSrcweir     // When the caret has not been visible yet then move it to the beginning
327cdf0e10cSrcweir     // of the text.
328cdf0e10cSrcweir     if (mpCaret->GetParagraphIndex() < 0)
329cdf0e10cSrcweir     {
330cdf0e10cSrcweir         mpCaret->SetPosition(0,0);
331cdf0e10cSrcweir         return;
332cdf0e10cSrcweir     }
333cdf0e10cSrcweir 
334cdf0e10cSrcweir     sal_Int32 nParagraphIndex (mpCaret->GetParagraphIndex());
335cdf0e10cSrcweir     sal_Int32 nCharacterIndex (mpCaret->GetCharacterIndex());
336cdf0e10cSrcweir     switch (nTextType)
337cdf0e10cSrcweir     {
338cdf0e10cSrcweir         default:
339cdf0e10cSrcweir         case AccessibleTextType::CHARACTER:
340cdf0e10cSrcweir             nCharacterIndex += nDistance;
341cdf0e10cSrcweir             break;
342cdf0e10cSrcweir 
343cdf0e10cSrcweir         case AccessibleTextType::WORD:
344cdf0e10cSrcweir         {
345cdf0e10cSrcweir             sal_Int32 nRemainingDistance (nDistance);
346cdf0e10cSrcweir             while (nRemainingDistance != 0)
347cdf0e10cSrcweir             {
348cdf0e10cSrcweir                 SharedPresenterTextParagraph pParagraph (GetParagraph(nParagraphIndex));
349cdf0e10cSrcweir                 if (pParagraph)
350cdf0e10cSrcweir                 {
351cdf0e10cSrcweir                     const sal_Int32 nDelta (Signum(nDistance));
352cdf0e10cSrcweir                     nCharacterIndex = pParagraph->GetWordBoundary(nCharacterIndex, nDelta);
353cdf0e10cSrcweir                     if (nCharacterIndex < 0)
354cdf0e10cSrcweir                     {
355cdf0e10cSrcweir                         // Go to previous or next paragraph.
356cdf0e10cSrcweir                         nParagraphIndex += nDelta;
357cdf0e10cSrcweir                         if (nParagraphIndex < 0)
358cdf0e10cSrcweir                         {
359cdf0e10cSrcweir                             nParagraphIndex = 0;
360cdf0e10cSrcweir                             nCharacterIndex = 0;
361cdf0e10cSrcweir                             nRemainingDistance = 0;
362cdf0e10cSrcweir                         }
363cdf0e10cSrcweir                         else if (sal_uInt32(nParagraphIndex) >= maParagraphs.size())
364cdf0e10cSrcweir                         {
365cdf0e10cSrcweir                             nParagraphIndex = maParagraphs.size()-1;
366cdf0e10cSrcweir                             pParagraph = GetParagraph(nParagraphIndex);
367cdf0e10cSrcweir                             if (pParagraph)
368cdf0e10cSrcweir                                 nCharacterIndex = pParagraph->GetCharacterCount();
369cdf0e10cSrcweir                             nRemainingDistance = 0;
370cdf0e10cSrcweir                         }
371cdf0e10cSrcweir                         else
372cdf0e10cSrcweir                         {
373cdf0e10cSrcweir                             nRemainingDistance -= nDelta;
374cdf0e10cSrcweir 
375cdf0e10cSrcweir                             // Move caret one character to the end of
376cdf0e10cSrcweir                             // the previous or the start of the next paragraph.
377cdf0e10cSrcweir                             pParagraph = GetParagraph(nParagraphIndex);
378cdf0e10cSrcweir                             if (pParagraph)
379cdf0e10cSrcweir                             {
380cdf0e10cSrcweir                                 if (nDistance<0)
381cdf0e10cSrcweir                                     nCharacterIndex = pParagraph->GetCharacterCount();
382cdf0e10cSrcweir                                 else
383cdf0e10cSrcweir                                     nCharacterIndex = 0;
384cdf0e10cSrcweir                             }
385cdf0e10cSrcweir                         }
386cdf0e10cSrcweir                     }
387cdf0e10cSrcweir                     else
388cdf0e10cSrcweir                         nRemainingDistance -= nDelta;
389cdf0e10cSrcweir                 }
390cdf0e10cSrcweir                 else
391cdf0e10cSrcweir                     break;
392cdf0e10cSrcweir             }
393cdf0e10cSrcweir             break;
394cdf0e10cSrcweir         }
395cdf0e10cSrcweir     }
396cdf0e10cSrcweir 
397cdf0e10cSrcweir     // Move the caret to the new position.
398cdf0e10cSrcweir     mpCaret->SetPosition(nParagraphIndex, nCharacterIndex);
399cdf0e10cSrcweir }
400cdf0e10cSrcweir 
401cdf0e10cSrcweir 
402cdf0e10cSrcweir 
403cdf0e10cSrcweir 
Paint(const css::awt::Rectangle & rUpdateBox)404cdf0e10cSrcweir void PresenterTextView::Paint (
405cdf0e10cSrcweir     const css::awt::Rectangle& rUpdateBox)
406cdf0e10cSrcweir {
407cdf0e10cSrcweir     if ( ! mbDoOuput)
408cdf0e10cSrcweir         return;
409cdf0e10cSrcweir     if ( ! mxCanvas.is())
410cdf0e10cSrcweir         return;
411cdf0e10cSrcweir     if ( ! mpFont->PrepareFont(mxCanvas))
412cdf0e10cSrcweir         return;
413cdf0e10cSrcweir 
414cdf0e10cSrcweir     if (mbIsFormatPending)
415cdf0e10cSrcweir         Format();
416cdf0e10cSrcweir 
417cdf0e10cSrcweir     // Setup the clipping rectangle.  Horizontally we make it a little
418cdf0e10cSrcweir     // larger to allow characters (and the caret) to stick out of their
419cdf0e10cSrcweir     // bounding boxes.  This can happen on some characters (like the
420cdf0e10cSrcweir     // uppercase J) for typographical reasons.
421cdf0e10cSrcweir     const sal_Int32 nAdditionalLeftBorder (10);
422cdf0e10cSrcweir     const sal_Int32 nAdditionalRightBorder (5);
423cdf0e10cSrcweir     double nX (maLocation.X - mnLeftOffset);
424cdf0e10cSrcweir     double nY (maLocation.Y - mnTopOffset);
425cdf0e10cSrcweir     const sal_Int32 nClipLeft (::std::max(
426cdf0e10cSrcweir         PresenterGeometryHelper::Round(maLocation.X)-nAdditionalLeftBorder, rUpdateBox.X));
427cdf0e10cSrcweir     const sal_Int32 nClipTop (::std::max(
428cdf0e10cSrcweir         PresenterGeometryHelper::Round(maLocation.Y), rUpdateBox.Y));
429cdf0e10cSrcweir     const sal_Int32 nClipRight (::std::min(
430cdf0e10cSrcweir         PresenterGeometryHelper::Round(maLocation.X+maSize.Width)+nAdditionalRightBorder, rUpdateBox.X+rUpdateBox.Width));
431cdf0e10cSrcweir     const sal_Int32 nClipBottom (::std::min(
432cdf0e10cSrcweir         PresenterGeometryHelper::Round(maLocation.Y+maSize.Height), rUpdateBox.Y+rUpdateBox.Height));
433cdf0e10cSrcweir     if (nClipLeft>=nClipRight || nClipTop>=nClipBottom)
434cdf0e10cSrcweir         return;
435cdf0e10cSrcweir 
436cdf0e10cSrcweir     const awt::Rectangle aClipBox(
437cdf0e10cSrcweir         nClipLeft,
438cdf0e10cSrcweir         nClipTop,
439cdf0e10cSrcweir         nClipRight - nClipLeft,
440cdf0e10cSrcweir         nClipBottom - nClipTop);
441cdf0e10cSrcweir     Reference<rendering::XPolyPolygon2D> xClipPolygon (
442cdf0e10cSrcweir         PresenterGeometryHelper::CreatePolygon(aClipBox, mxCanvas->getDevice()));
443cdf0e10cSrcweir 
444cdf0e10cSrcweir     const rendering::ViewState aViewState(
445cdf0e10cSrcweir         geometry::AffineMatrix2D(1,0,0, 0,1,0),
446cdf0e10cSrcweir         xClipPolygon);
447cdf0e10cSrcweir 
448cdf0e10cSrcweir     rendering::RenderState aRenderState (
449cdf0e10cSrcweir         geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
450cdf0e10cSrcweir         NULL,
451cdf0e10cSrcweir         Sequence<double>(4),
452cdf0e10cSrcweir         rendering::CompositeOperation::SOURCE);
453cdf0e10cSrcweir     PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
454cdf0e10cSrcweir 
455cdf0e10cSrcweir     for (::std::vector<SharedPresenterTextParagraph>::const_iterator
456cdf0e10cSrcweir              iParagraph(maParagraphs.begin()),
457cdf0e10cSrcweir              iEnd(maParagraphs.end());
458cdf0e10cSrcweir          iParagraph!=iEnd;
459cdf0e10cSrcweir          ++iParagraph)
460cdf0e10cSrcweir     {
461cdf0e10cSrcweir         (*iParagraph)->Paint(
462cdf0e10cSrcweir             mxCanvas,
463cdf0e10cSrcweir             maSize,
464cdf0e10cSrcweir             mpFont,
465cdf0e10cSrcweir             aViewState,
466cdf0e10cSrcweir             aRenderState,
467cdf0e10cSrcweir             mnTopOffset,
468cdf0e10cSrcweir             nClipTop,
469cdf0e10cSrcweir             nClipBottom);
470cdf0e10cSrcweir     }
471cdf0e10cSrcweir 
472cdf0e10cSrcweir     aRenderState.AffineTransform.m02 = 0;
473cdf0e10cSrcweir     aRenderState.AffineTransform.m12 = 0;
474cdf0e10cSrcweir 
475cdf0e10cSrcweir #ifdef SHOW_CHARACTER_BOXES
476cdf0e10cSrcweir     PresenterCanvasHelper::SetDeviceColor(aRenderState, 0x00808080);
477cdf0e10cSrcweir     for (sal_Int32 nParagraphIndex(0), nParagraphCount(GetParagraphCount());
478cdf0e10cSrcweir          nParagraphIndex<nParagraphCount;
479cdf0e10cSrcweir          ++nParagraphIndex)
480cdf0e10cSrcweir     {
481cdf0e10cSrcweir         const SharedPresenterTextParagraph pParagraph (GetParagraph(nParagraphIndex));
482cdf0e10cSrcweir         if ( ! pParagraph)
483cdf0e10cSrcweir             continue;
484cdf0e10cSrcweir         for (sal_Int32 nCharacterIndex(0),nCharacterCount(pParagraph->GetCharacterCount());
485cdf0e10cSrcweir              nCharacterIndex<nCharacterCount; ++nCharacterIndex)
486cdf0e10cSrcweir         {
487cdf0e10cSrcweir             const awt::Rectangle aBox (pParagraph->GetCharacterBounds(nCharacterIndex, false));
488cdf0e10cSrcweir             mxCanvas->drawPolyPolygon (
489cdf0e10cSrcweir                 PresenterGeometryHelper::CreatePolygon(
490cdf0e10cSrcweir                     aBox,
491cdf0e10cSrcweir                     mxCanvas->getDevice()),
492cdf0e10cSrcweir                 aViewState,
493cdf0e10cSrcweir                 aRenderState);
494cdf0e10cSrcweir         }
495cdf0e10cSrcweir     }
496cdf0e10cSrcweir     PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
497cdf0e10cSrcweir #endif
498cdf0e10cSrcweir 
499cdf0e10cSrcweir     if (mpCaret && mpCaret->IsVisible())
500cdf0e10cSrcweir     {
501cdf0e10cSrcweir         mxCanvas->fillPolyPolygon (
502cdf0e10cSrcweir             PresenterGeometryHelper::CreatePolygon(
503cdf0e10cSrcweir                 mpCaret->GetBounds(),
504cdf0e10cSrcweir                 mxCanvas->getDevice()),
505cdf0e10cSrcweir             aViewState,
506cdf0e10cSrcweir             aRenderState);
507cdf0e10cSrcweir     }
508cdf0e10cSrcweir }
509cdf0e10cSrcweir 
510cdf0e10cSrcweir 
511cdf0e10cSrcweir 
512cdf0e10cSrcweir 
GetCaret(void) const513cdf0e10cSrcweir SharedPresenterTextCaret PresenterTextView::GetCaret (void) const
514cdf0e10cSrcweir {
515cdf0e10cSrcweir     return mpCaret;
516cdf0e10cSrcweir }
517cdf0e10cSrcweir 
518cdf0e10cSrcweir 
519cdf0e10cSrcweir 
520cdf0e10cSrcweir 
GetCharacterOffset(const sal_Int32 nParagraphIndex) const521cdf0e10cSrcweir sal_Int32 PresenterTextView::GetCharacterOffset (const sal_Int32 nParagraphIndex) const
522cdf0e10cSrcweir {
523cdf0e10cSrcweir     sal_Int32 nCharacterOffset (0);
524cdf0e10cSrcweir     for (sal_Int32 nIndex=0; nIndex<nParagraphIndex; ++nIndex)
525cdf0e10cSrcweir         nCharacterOffset += maParagraphs[nIndex]->GetCharacterCount();
526cdf0e10cSrcweir     return nCharacterOffset;
527cdf0e10cSrcweir }
528cdf0e10cSrcweir 
529cdf0e10cSrcweir 
530cdf0e10cSrcweir 
531cdf0e10cSrcweir 
GetCaretBounds(sal_Int32 nParagraphIndex,const sal_Int32 nCharacterIndex) const532cdf0e10cSrcweir awt::Rectangle PresenterTextView::GetCaretBounds (
533cdf0e10cSrcweir     sal_Int32 nParagraphIndex,
534cdf0e10cSrcweir     const sal_Int32 nCharacterIndex) const
535cdf0e10cSrcweir {
536cdf0e10cSrcweir     SharedPresenterTextParagraph pParagraph (GetParagraph(nParagraphIndex));
537cdf0e10cSrcweir 
538cdf0e10cSrcweir     if (pParagraph)
539cdf0e10cSrcweir         return pParagraph->GetCharacterBounds(nCharacterIndex, true);
540cdf0e10cSrcweir     else
541cdf0e10cSrcweir         return awt::Rectangle(0,0,0,0);
542cdf0e10cSrcweir }
543cdf0e10cSrcweir 
544cdf0e10cSrcweir 
545cdf0e10cSrcweir 
546cdf0e10cSrcweir 
547cdf0e10cSrcweir //----- private ---------------------------------------------------------------
548cdf0e10cSrcweir 
RequestFormat(void)549cdf0e10cSrcweir void PresenterTextView::RequestFormat (void)
550cdf0e10cSrcweir {
551cdf0e10cSrcweir     mbIsFormatPending = true;
552cdf0e10cSrcweir }
553cdf0e10cSrcweir 
554cdf0e10cSrcweir 
555cdf0e10cSrcweir 
556cdf0e10cSrcweir 
Format(void)557cdf0e10cSrcweir void PresenterTextView::Format (void)
558cdf0e10cSrcweir {
559cdf0e10cSrcweir     mbIsFormatPending = false;
560cdf0e10cSrcweir 
561cdf0e10cSrcweir     double nY (0);
562cdf0e10cSrcweir     for (::std::vector<SharedPresenterTextParagraph>::const_iterator
563cdf0e10cSrcweir              iParagraph(maParagraphs.begin()),
564cdf0e10cSrcweir              iEnd(maParagraphs.end());
565cdf0e10cSrcweir          iParagraph!=iEnd;
566cdf0e10cSrcweir          ++iParagraph)
567cdf0e10cSrcweir     {
568cdf0e10cSrcweir         (*iParagraph)->Format(nY, maSize.Width, mpFont);
569cdf0e10cSrcweir         nY += (*iParagraph)->GetTotalTextHeight();
570cdf0e10cSrcweir     }
571cdf0e10cSrcweir 
572cdf0e10cSrcweir     if (maTextChangeBroadcaster)
573cdf0e10cSrcweir         maTextChangeBroadcaster();
574cdf0e10cSrcweir }
575cdf0e10cSrcweir 
576cdf0e10cSrcweir 
577cdf0e10cSrcweir 
578cdf0e10cSrcweir 
GetParagraphCount(void) const579cdf0e10cSrcweir sal_Int32 PresenterTextView::GetParagraphCount (void) const
580cdf0e10cSrcweir {
581cdf0e10cSrcweir     return maParagraphs.size();
582cdf0e10cSrcweir }
583cdf0e10cSrcweir 
584cdf0e10cSrcweir 
585cdf0e10cSrcweir 
586cdf0e10cSrcweir 
GetParagraph(const sal_Int32 nParagraphIndex) const587cdf0e10cSrcweir SharedPresenterTextParagraph PresenterTextView::GetParagraph (
588cdf0e10cSrcweir     const sal_Int32 nParagraphIndex) const
589cdf0e10cSrcweir {
590cdf0e10cSrcweir     if (nParagraphIndex < 0)
591cdf0e10cSrcweir         return SharedPresenterTextParagraph();
592cdf0e10cSrcweir     else if (nParagraphIndex>=sal_Int32(maParagraphs.size()))
593cdf0e10cSrcweir         return SharedPresenterTextParagraph();
594cdf0e10cSrcweir     else
595cdf0e10cSrcweir         return maParagraphs[nParagraphIndex];
596cdf0e10cSrcweir }
597cdf0e10cSrcweir 
598cdf0e10cSrcweir 
599cdf0e10cSrcweir 
600cdf0e10cSrcweir 
601cdf0e10cSrcweir //===== PresenterTextParagraph ================================================
602cdf0e10cSrcweir 
PresenterTextParagraph(const sal_Int32 nParagraphIndex,const Reference<i18n::XBreakIterator> & rxBreakIterator,const Reference<i18n::XScriptTypeDetector> & rxScriptTypeDetector,const Reference<text::XTextRange> & rxTextRange,const SharedPresenterTextCaret & rpCaret)603cdf0e10cSrcweir PresenterTextParagraph::PresenterTextParagraph (
604cdf0e10cSrcweir     const sal_Int32 nParagraphIndex,
605cdf0e10cSrcweir     const Reference<i18n::XBreakIterator>& rxBreakIterator,
606cdf0e10cSrcweir     const Reference<i18n::XScriptTypeDetector>& rxScriptTypeDetector,
607cdf0e10cSrcweir     const Reference<text::XTextRange>& rxTextRange,
608cdf0e10cSrcweir     const SharedPresenterTextCaret& rpCaret)
609cdf0e10cSrcweir     : msParagraphText(),
610cdf0e10cSrcweir       mnParagraphIndex(nParagraphIndex),
611cdf0e10cSrcweir       mpCaret(rpCaret),
612cdf0e10cSrcweir       mxBreakIterator(rxBreakIterator),
613cdf0e10cSrcweir       mxScriptTypeDetector(rxScriptTypeDetector),
614cdf0e10cSrcweir       maLines(),
615cdf0e10cSrcweir       mnVerticalOffset(0),
616cdf0e10cSrcweir       mnXOrigin(0),
617cdf0e10cSrcweir       mnYOrigin(0),
618cdf0e10cSrcweir       mnWidth(0),
619cdf0e10cSrcweir       mnAscent(0),
620cdf0e10cSrcweir       mnDescent(0),
621cdf0e10cSrcweir       mnLineHeight(-1),
622cdf0e10cSrcweir       meAdjust(style::ParagraphAdjust_LEFT),
623cdf0e10cSrcweir       mnWritingMode (text::WritingMode2::LR_TB),
624cdf0e10cSrcweir       mnCharacterOffset(0),
625cdf0e10cSrcweir       maCells()
626cdf0e10cSrcweir {
627cdf0e10cSrcweir     if (rxTextRange.is())
628cdf0e10cSrcweir     {
629cdf0e10cSrcweir         Reference<beans::XPropertySet> xProperties (rxTextRange, UNO_QUERY);
630cdf0e10cSrcweir         lang::Locale aLocale;
631cdf0e10cSrcweir         try
632cdf0e10cSrcweir         {
633cdf0e10cSrcweir             xProperties->getPropertyValue(A2S("CharLocale")) >>= aLocale;
634cdf0e10cSrcweir         }
635cdf0e10cSrcweir         catch(beans::UnknownPropertyException&)
636cdf0e10cSrcweir         {
637cdf0e10cSrcweir             // Ignore the exception.  Use the default value.
638cdf0e10cSrcweir         }
639cdf0e10cSrcweir         try
640cdf0e10cSrcweir         {
641cdf0e10cSrcweir             xProperties->getPropertyValue(A2S("ParaAdjust")) >>= meAdjust;
642cdf0e10cSrcweir         }
643cdf0e10cSrcweir         catch(beans::UnknownPropertyException&)
644cdf0e10cSrcweir         {
645cdf0e10cSrcweir             // Ignore the exception.  Use the default value.
646cdf0e10cSrcweir         }
647cdf0e10cSrcweir         try
648cdf0e10cSrcweir         {
649cdf0e10cSrcweir             xProperties->getPropertyValue(A2S("WritingMode")) >>= mnWritingMode;
650cdf0e10cSrcweir         }
651cdf0e10cSrcweir         catch(beans::UnknownPropertyException&)
652cdf0e10cSrcweir         {
653cdf0e10cSrcweir             // Ignore the exception.  Use the default value.
654cdf0e10cSrcweir         }
655cdf0e10cSrcweir 
656cdf0e10cSrcweir         msParagraphText = rxTextRange->getString();
657cdf0e10cSrcweir     }
658cdf0e10cSrcweir }
659cdf0e10cSrcweir 
660cdf0e10cSrcweir 
661cdf0e10cSrcweir 
662cdf0e10cSrcweir 
PresenterTextParagraph(const sal_Int32 nParagraphIndex,const Reference<i18n::XBreakIterator> & rxBreakIterator,const Reference<i18n::XScriptTypeDetector> & rxScriptTypeDetector,const::rtl::OUString & rsText,const SharedPresenterTextCaret & rpCaret)663cdf0e10cSrcweir PresenterTextParagraph::PresenterTextParagraph (
664cdf0e10cSrcweir     const sal_Int32 nParagraphIndex,
665cdf0e10cSrcweir     const Reference<i18n::XBreakIterator>& rxBreakIterator,
666cdf0e10cSrcweir     const Reference<i18n::XScriptTypeDetector>& rxScriptTypeDetector,
667cdf0e10cSrcweir     const ::rtl::OUString& rsText,
668cdf0e10cSrcweir     const SharedPresenterTextCaret& rpCaret)
669cdf0e10cSrcweir     : msParagraphText(rsText),
670cdf0e10cSrcweir       mnParagraphIndex(nParagraphIndex),
671cdf0e10cSrcweir       mpCaret(rpCaret),
672cdf0e10cSrcweir       mxBreakIterator(rxBreakIterator),
673cdf0e10cSrcweir       mxScriptTypeDetector(rxScriptTypeDetector),
674cdf0e10cSrcweir       maLines(),
675cdf0e10cSrcweir       mnVerticalOffset(0),
676cdf0e10cSrcweir       mnXOrigin(0),
677cdf0e10cSrcweir       mnYOrigin(0),
678cdf0e10cSrcweir       mnWidth(0),
679cdf0e10cSrcweir       mnAscent(0),
680cdf0e10cSrcweir       mnDescent(0),
681cdf0e10cSrcweir       mnLineHeight(-1),
682cdf0e10cSrcweir       meAdjust(style::ParagraphAdjust_LEFT),
683cdf0e10cSrcweir       mnWritingMode (text::WritingMode2::LR_TB),
684cdf0e10cSrcweir       mnCharacterOffset(0),
685cdf0e10cSrcweir       maCells()
686cdf0e10cSrcweir {
687cdf0e10cSrcweir }
688cdf0e10cSrcweir 
689cdf0e10cSrcweir 
690cdf0e10cSrcweir 
691cdf0e10cSrcweir 
Paint(const Reference<rendering::XCanvas> & rxCanvas,const geometry::RealSize2D & rSize,const PresenterTheme::SharedFontDescriptor & rpFont,const rendering::ViewState & rViewState,rendering::RenderState & rRenderState,const double nTopOffset,const double nClipTop,const double nClipBottom)692cdf0e10cSrcweir void PresenterTextParagraph::Paint (
693cdf0e10cSrcweir     const Reference<rendering::XCanvas>& rxCanvas,
694cdf0e10cSrcweir     const geometry::RealSize2D& rSize,
695cdf0e10cSrcweir     const PresenterTheme::SharedFontDescriptor& rpFont,
696cdf0e10cSrcweir     const rendering::ViewState& rViewState,
697cdf0e10cSrcweir     rendering::RenderState& rRenderState,
698cdf0e10cSrcweir     const double nTopOffset,
699cdf0e10cSrcweir     const double nClipTop,
700cdf0e10cSrcweir     const double nClipBottom)
701cdf0e10cSrcweir {
702cdf0e10cSrcweir     if (mnLineHeight <= 0)
703cdf0e10cSrcweir         return;
704cdf0e10cSrcweir 
705cdf0e10cSrcweir     sal_Int8 nTextDirection (GetTextDirection());
706cdf0e10cSrcweir 
707cdf0e10cSrcweir     const double nSavedM12 (rRenderState.AffineTransform.m12);
708cdf0e10cSrcweir 
709cdf0e10cSrcweir     if ( ! IsTextReferencePointLeft())
710cdf0e10cSrcweir         rRenderState.AffineTransform.m02 += rSize.Width;
711cdf0e10cSrcweir 
712cdf0e10cSrcweir 
713cdf0e10cSrcweir #ifdef SHOW_CHARACTER_BOXES
714cdf0e10cSrcweir     for (sal_Int32 nIndex=0,nCount=maLines.size();
715cdf0e10cSrcweir          nIndex<nCount;
716cdf0e10cSrcweir          ++nIndex)
717cdf0e10cSrcweir     {
718cdf0e10cSrcweir         Line& rLine (maLines[nIndex]);
719cdf0e10cSrcweir         rLine.ProvideLayoutedLine(msParagraphText, rpFont, nTextDirection);
720cdf0e10cSrcweir     }
721cdf0e10cSrcweir #endif
722cdf0e10cSrcweir 
723cdf0e10cSrcweir     for (sal_Int32 nIndex=0,nCount=maLines.size();
724cdf0e10cSrcweir          nIndex<nCount;
725cdf0e10cSrcweir          ++nIndex, rRenderState.AffineTransform.m12 += mnLineHeight)
726cdf0e10cSrcweir     {
727cdf0e10cSrcweir         Line& rLine (maLines[nIndex]);
728cdf0e10cSrcweir 
729cdf0e10cSrcweir         // Paint only visible lines.
730cdf0e10cSrcweir         const double nLineTop = rLine.mnBaseLine - mnAscent - nTopOffset;
731cdf0e10cSrcweir         if (nLineTop + mnLineHeight< nClipTop)
732cdf0e10cSrcweir             continue;
733cdf0e10cSrcweir         else if (nLineTop > nClipBottom)
734cdf0e10cSrcweir             break;
735cdf0e10cSrcweir         rLine.ProvideLayoutedLine(msParagraphText, rpFont, nTextDirection);
736cdf0e10cSrcweir 
737cdf0e10cSrcweir         rRenderState.AffineTransform.m12 = nSavedM12 + rLine.mnBaseLine;
738cdf0e10cSrcweir 
739cdf0e10cSrcweir         rxCanvas->drawTextLayout (
740cdf0e10cSrcweir             rLine.mxLayoutedLine,
741cdf0e10cSrcweir             rViewState,
742cdf0e10cSrcweir             rRenderState);
743cdf0e10cSrcweir     }
744cdf0e10cSrcweir     rRenderState.AffineTransform.m12 = nSavedM12;
745cdf0e10cSrcweir 
746cdf0e10cSrcweir     if ( ! IsTextReferencePointLeft())
747cdf0e10cSrcweir         rRenderState.AffineTransform.m02 -= rSize.Width;
748cdf0e10cSrcweir }
749cdf0e10cSrcweir 
750cdf0e10cSrcweir 
751cdf0e10cSrcweir 
752cdf0e10cSrcweir 
Format(const double nY,const double nWidth,const PresenterTheme::SharedFontDescriptor & rpFont)753cdf0e10cSrcweir void PresenterTextParagraph::Format (
754cdf0e10cSrcweir     const double nY,
755cdf0e10cSrcweir     const double nWidth,
756cdf0e10cSrcweir     const PresenterTheme::SharedFontDescriptor& rpFont)
757cdf0e10cSrcweir {
758cdf0e10cSrcweir     // Make sure that the text view is in a valid and sane state.
759cdf0e10cSrcweir     if ( ! mxBreakIterator.is() || ! mxScriptTypeDetector.is())
760cdf0e10cSrcweir         return;
761cdf0e10cSrcweir     if (nWidth<=0)
762cdf0e10cSrcweir         return;
763cdf0e10cSrcweir     if ( ! rpFont || ! rpFont->mxFont.is())
764cdf0e10cSrcweir         return;
765cdf0e10cSrcweir 
766cdf0e10cSrcweir     sal_Int32 nPosition (0);
767cdf0e10cSrcweir 
768cdf0e10cSrcweir     mnWidth = nWidth;
769cdf0e10cSrcweir     maLines.clear();
770cdf0e10cSrcweir     mnLineHeight = 0;
771cdf0e10cSrcweir     mnAscent = 0;
772cdf0e10cSrcweir     mnDescent = 0;
773cdf0e10cSrcweir     mnVerticalOffset = nY;
774cdf0e10cSrcweir     maWordBoundaries.clear();
775cdf0e10cSrcweir     maWordBoundaries.push_back(0);
776cdf0e10cSrcweir 
777cdf0e10cSrcweir     const rendering::FontMetrics aMetrics (rpFont->mxFont->getFontMetrics());
778cdf0e10cSrcweir     mnAscent = aMetrics.Ascent;
779cdf0e10cSrcweir     mnDescent = aMetrics.Descent;
780cdf0e10cSrcweir     mnLineHeight = aMetrics.Ascent + aMetrics.Descent + aMetrics.ExternalLeading;
781cdf0e10cSrcweir     nPosition = 0;
782cdf0e10cSrcweir     i18n::Boundary aCurrentLine(0,0);
783cdf0e10cSrcweir     while (true)
784cdf0e10cSrcweir     {
785cdf0e10cSrcweir         const i18n::Boundary aWordBoundary = mxBreakIterator->nextWord(
786cdf0e10cSrcweir             msParagraphText,
787cdf0e10cSrcweir             nPosition,
788cdf0e10cSrcweir             lang::Locale(),
789cdf0e10cSrcweir             i18n::WordType::ANYWORD_IGNOREWHITESPACES);
790cdf0e10cSrcweir         AddWord(nWidth, aCurrentLine, aWordBoundary.startPos, rpFont);
791cdf0e10cSrcweir 
792cdf0e10cSrcweir         // Remember the new word boundary for caret travelling by words.
793cdf0e10cSrcweir         // Prevent duplicates.
794cdf0e10cSrcweir         if (aWordBoundary.startPos > maWordBoundaries.back())
795cdf0e10cSrcweir             maWordBoundaries.push_back(aWordBoundary.startPos);
796cdf0e10cSrcweir 
797cdf0e10cSrcweir         if (aWordBoundary.endPos>aWordBoundary.startPos)
798cdf0e10cSrcweir             AddWord(nWidth, aCurrentLine, aWordBoundary.endPos, rpFont);
799cdf0e10cSrcweir 
800cdf0e10cSrcweir         if (aWordBoundary.startPos<0 || aWordBoundary.endPos<0)
801cdf0e10cSrcweir             break;
802cdf0e10cSrcweir         if (nPosition >= aWordBoundary.endPos)
803cdf0e10cSrcweir             break;
804cdf0e10cSrcweir         nPosition = aWordBoundary.endPos;
805cdf0e10cSrcweir     }
806cdf0e10cSrcweir 
807cdf0e10cSrcweir     if (aCurrentLine.endPos>aCurrentLine.startPos)
808cdf0e10cSrcweir         AddLine(aCurrentLine);
809cdf0e10cSrcweir 
810cdf0e10cSrcweir }
811cdf0e10cSrcweir 
812cdf0e10cSrcweir 
813cdf0e10cSrcweir 
814cdf0e10cSrcweir 
GetWordBoundary(const sal_Int32 nLocalCharacterIndex,const sal_Int32 nDistance)815cdf0e10cSrcweir sal_Int32 PresenterTextParagraph::GetWordBoundary(
816cdf0e10cSrcweir     const sal_Int32 nLocalCharacterIndex,
817cdf0e10cSrcweir     const sal_Int32 nDistance)
818cdf0e10cSrcweir {
819cdf0e10cSrcweir     OSL_ASSERT(nDistance==-1 || nDistance==+1);
820cdf0e10cSrcweir 
821cdf0e10cSrcweir     if (nLocalCharacterIndex < 0)
822cdf0e10cSrcweir     {
823cdf0e10cSrcweir         // The caller asked for the start or end position of the paragraph.
824cdf0e10cSrcweir         if (nDistance < 0)
825cdf0e10cSrcweir             return 0;
826cdf0e10cSrcweir         else
827cdf0e10cSrcweir             return GetCharacterCount();
828cdf0e10cSrcweir     }
829cdf0e10cSrcweir 
830cdf0e10cSrcweir     sal_Int32 nIndex (0);
831cdf0e10cSrcweir     for (sal_Int32 nCount (maWordBoundaries.size()); nIndex<nCount; ++nIndex)
832cdf0e10cSrcweir     {
833cdf0e10cSrcweir         if (maWordBoundaries[nIndex] >= nLocalCharacterIndex)
834cdf0e10cSrcweir         {
835cdf0e10cSrcweir             // When inside the word (not at its start or end) then
836cdf0e10cSrcweir             // first move to the start or end before going the previous or
837cdf0e10cSrcweir             // next word.
838cdf0e10cSrcweir             if (maWordBoundaries[nIndex] > nLocalCharacterIndex)
839cdf0e10cSrcweir                 if (nDistance > 0)
840cdf0e10cSrcweir                     --nIndex;
841cdf0e10cSrcweir             break;
842cdf0e10cSrcweir         }
843cdf0e10cSrcweir     }
844cdf0e10cSrcweir 
845cdf0e10cSrcweir     nIndex += nDistance;
846cdf0e10cSrcweir 
847cdf0e10cSrcweir     if (nIndex < 0)
848cdf0e10cSrcweir         return -1;
849cdf0e10cSrcweir     else if (sal_uInt32(nIndex)>=maWordBoundaries.size())
850cdf0e10cSrcweir         return -1;
851cdf0e10cSrcweir     else
852cdf0e10cSrcweir         return maWordBoundaries[nIndex];
853cdf0e10cSrcweir }
854cdf0e10cSrcweir 
855cdf0e10cSrcweir 
856cdf0e10cSrcweir 
857cdf0e10cSrcweir 
GetCaretPosition(void) const858cdf0e10cSrcweir sal_Int32 PresenterTextParagraph::GetCaretPosition (void) const
859cdf0e10cSrcweir {
860cdf0e10cSrcweir     if (mpCaret && mpCaret->GetParagraphIndex()==mnParagraphIndex)
861cdf0e10cSrcweir         return mpCaret->GetCharacterIndex();
862cdf0e10cSrcweir     else
863cdf0e10cSrcweir         return -1;
864cdf0e10cSrcweir }
865cdf0e10cSrcweir 
866cdf0e10cSrcweir 
867cdf0e10cSrcweir 
868cdf0e10cSrcweir 
SetCaretPosition(const sal_Int32 nPosition) const869cdf0e10cSrcweir void PresenterTextParagraph::SetCaretPosition (const sal_Int32 nPosition) const
870cdf0e10cSrcweir {
871cdf0e10cSrcweir     if (mpCaret && mpCaret->GetParagraphIndex()==mnParagraphIndex)
872cdf0e10cSrcweir         return mpCaret->SetPosition(mnParagraphIndex, nPosition);
873cdf0e10cSrcweir }
874cdf0e10cSrcweir 
875cdf0e10cSrcweir 
876cdf0e10cSrcweir 
877cdf0e10cSrcweir 
SetOrigin(const double nXOrigin,const double nYOrigin)878cdf0e10cSrcweir void PresenterTextParagraph::SetOrigin (const double nXOrigin, const double nYOrigin)
879cdf0e10cSrcweir {
880cdf0e10cSrcweir     mnXOrigin = nXOrigin;
881cdf0e10cSrcweir     mnYOrigin = nYOrigin;
882cdf0e10cSrcweir }
883cdf0e10cSrcweir 
884cdf0e10cSrcweir 
885cdf0e10cSrcweir 
886cdf0e10cSrcweir 
GetRelativeLocation(void) const887cdf0e10cSrcweir awt::Point PresenterTextParagraph::GetRelativeLocation (void) const
888cdf0e10cSrcweir {
889cdf0e10cSrcweir     return awt::Point(
890cdf0e10cSrcweir         sal_Int32(mnXOrigin),
891cdf0e10cSrcweir         sal_Int32(mnYOrigin + mnVerticalOffset));
892cdf0e10cSrcweir }
893cdf0e10cSrcweir 
894cdf0e10cSrcweir 
895cdf0e10cSrcweir 
896cdf0e10cSrcweir 
GetSize(void)897cdf0e10cSrcweir awt::Size PresenterTextParagraph::GetSize (void)
898cdf0e10cSrcweir {
899cdf0e10cSrcweir     return awt::Size(
900cdf0e10cSrcweir         sal_Int32(mnWidth),
901cdf0e10cSrcweir         sal_Int32(GetTotalTextHeight()));
902cdf0e10cSrcweir }
903cdf0e10cSrcweir 
904cdf0e10cSrcweir 
905cdf0e10cSrcweir 
906cdf0e10cSrcweir 
AddWord(const double nWidth,i18n::Boundary & rCurrentLine,const sal_Int32 nWordBoundary,const PresenterTheme::SharedFontDescriptor & rpFont)907cdf0e10cSrcweir void PresenterTextParagraph::AddWord (
908cdf0e10cSrcweir     const double nWidth,
909cdf0e10cSrcweir     i18n::Boundary& rCurrentLine,
910cdf0e10cSrcweir     const sal_Int32 nWordBoundary,
911cdf0e10cSrcweir     const PresenterTheme::SharedFontDescriptor& rpFont)
912cdf0e10cSrcweir {
913cdf0e10cSrcweir     sal_Int32 nLineStart (0);
914cdf0e10cSrcweir     sal_Int32 nLineEnd (0);
915cdf0e10cSrcweir     if ( ! maLines.empty())
916cdf0e10cSrcweir     {
917cdf0e10cSrcweir         nLineStart = rCurrentLine.startPos;
918cdf0e10cSrcweir         nLineEnd = rCurrentLine.endPos;
919cdf0e10cSrcweir     }
920cdf0e10cSrcweir 
921cdf0e10cSrcweir     const ::rtl::OUString sLineCandidate (
922cdf0e10cSrcweir         msParagraphText.copy(nLineStart, nWordBoundary-nLineStart));
923cdf0e10cSrcweir 
924cdf0e10cSrcweir     css::geometry::RealRectangle2D aLineBox (
925cdf0e10cSrcweir         PresenterCanvasHelper::GetTextBoundingBox (
926cdf0e10cSrcweir             rpFont->mxFont,
927cdf0e10cSrcweir             sLineCandidate,
928cdf0e10cSrcweir             mnWritingMode));
929cdf0e10cSrcweir     const double nLineWidth (aLineBox.X2 - aLineBox.X1);
930cdf0e10cSrcweir 
931cdf0e10cSrcweir     if (nLineWidth >= nWidth)
932cdf0e10cSrcweir     {
933cdf0e10cSrcweir         // Add new line with a single word (so far).
934cdf0e10cSrcweir         AddLine(rCurrentLine);
935cdf0e10cSrcweir     }
936cdf0e10cSrcweir     rCurrentLine.endPos = nWordBoundary;
937cdf0e10cSrcweir }
938cdf0e10cSrcweir 
939cdf0e10cSrcweir 
940cdf0e10cSrcweir 
941cdf0e10cSrcweir 
AddLine(i18n::Boundary & rCurrentLine)942cdf0e10cSrcweir void PresenterTextParagraph::AddLine (
943cdf0e10cSrcweir     i18n::Boundary& rCurrentLine)
944cdf0e10cSrcweir {
945cdf0e10cSrcweir     Line aLine (rCurrentLine.startPos, rCurrentLine.endPos);
946cdf0e10cSrcweir 
947cdf0e10cSrcweir     // Find the start and end of the line with respect to cells.
948cdf0e10cSrcweir     if (maLines.size() > 0)
949cdf0e10cSrcweir     {
950cdf0e10cSrcweir         aLine.mnLineStartCellIndex = maLines.back().mnLineEndCellIndex;
951cdf0e10cSrcweir         aLine.mnBaseLine = maLines.back().mnBaseLine + mnLineHeight;
952cdf0e10cSrcweir     }
953cdf0e10cSrcweir     else
954cdf0e10cSrcweir     {
955cdf0e10cSrcweir         aLine.mnLineStartCellIndex = 0;
956cdf0e10cSrcweir         aLine.mnBaseLine = mnVerticalOffset + mnAscent;
957cdf0e10cSrcweir     }
958cdf0e10cSrcweir     sal_Int32 nCellIndex (aLine.mnLineStartCellIndex);
959cdf0e10cSrcweir     double nWidth (0);
960cdf0e10cSrcweir     for ( ; nCellIndex<sal_Int32(maCells.size()); ++nCellIndex)
961cdf0e10cSrcweir     {
962cdf0e10cSrcweir         const Cell& rCell (maCells[nCellIndex]);
963cdf0e10cSrcweir         if (rCell.mnCharacterIndex+rCell.mnCharacterCount > aLine.mnLineEndCharacterIndex)
964cdf0e10cSrcweir             break;
965cdf0e10cSrcweir         nWidth += rCell.mnCellWidth;
966cdf0e10cSrcweir     }
967cdf0e10cSrcweir     aLine.mnLineEndCellIndex = nCellIndex;
968cdf0e10cSrcweir     aLine.mnWidth = nWidth;
969cdf0e10cSrcweir 
970cdf0e10cSrcweir     maLines.push_back(aLine);
971cdf0e10cSrcweir 
972cdf0e10cSrcweir     rCurrentLine.startPos = rCurrentLine.endPos;
973cdf0e10cSrcweir }
974cdf0e10cSrcweir 
975cdf0e10cSrcweir 
976cdf0e10cSrcweir 
977cdf0e10cSrcweir 
GetParagraphIndex(void) const978cdf0e10cSrcweir sal_Int32 PresenterTextParagraph::GetParagraphIndex (void) const
979cdf0e10cSrcweir {
980cdf0e10cSrcweir     return mnParagraphIndex;
981cdf0e10cSrcweir }
982cdf0e10cSrcweir 
983cdf0e10cSrcweir 
984cdf0e10cSrcweir 
985cdf0e10cSrcweir 
GetTotalTextHeight(void)986cdf0e10cSrcweir double PresenterTextParagraph::GetTotalTextHeight (void)
987cdf0e10cSrcweir {
988cdf0e10cSrcweir     return maLines.size() * mnLineHeight;
989cdf0e10cSrcweir }
990cdf0e10cSrcweir 
991cdf0e10cSrcweir 
992cdf0e10cSrcweir 
993cdf0e10cSrcweir 
GetCharacterOffset(void) const994cdf0e10cSrcweir sal_Int32 PresenterTextParagraph::GetCharacterOffset (void) const
995cdf0e10cSrcweir {
996cdf0e10cSrcweir     return mnCharacterOffset;
997cdf0e10cSrcweir }
998cdf0e10cSrcweir 
999cdf0e10cSrcweir 
1000cdf0e10cSrcweir 
1001cdf0e10cSrcweir 
SetCharacterOffset(const sal_Int32 nCharacterOffset)1002cdf0e10cSrcweir void PresenterTextParagraph::SetCharacterOffset (const sal_Int32 nCharacterOffset)
1003cdf0e10cSrcweir {
1004cdf0e10cSrcweir     mnCharacterOffset = nCharacterOffset;
1005cdf0e10cSrcweir }
1006cdf0e10cSrcweir 
1007cdf0e10cSrcweir 
1008cdf0e10cSrcweir 
1009cdf0e10cSrcweir 
GetCharacterCount(void) const1010cdf0e10cSrcweir sal_Int32 PresenterTextParagraph::GetCharacterCount (void) const
1011cdf0e10cSrcweir {
1012cdf0e10cSrcweir     return msParagraphText.getLength();
1013cdf0e10cSrcweir }
1014cdf0e10cSrcweir 
1015cdf0e10cSrcweir 
1016cdf0e10cSrcweir 
1017cdf0e10cSrcweir 
GetCharacter(const sal_Int32 nGlobalCharacterIndex) const1018cdf0e10cSrcweir sal_Unicode PresenterTextParagraph::GetCharacter (
1019cdf0e10cSrcweir     const sal_Int32 nGlobalCharacterIndex) const
1020cdf0e10cSrcweir {
1021cdf0e10cSrcweir     if (nGlobalCharacterIndex<mnCharacterOffset
1022cdf0e10cSrcweir         || nGlobalCharacterIndex>=mnCharacterOffset+msParagraphText.getLength())
1023cdf0e10cSrcweir     {
1024cdf0e10cSrcweir         return sal_Unicode();
1025cdf0e10cSrcweir     }
1026cdf0e10cSrcweir     else
1027cdf0e10cSrcweir     {
1028cdf0e10cSrcweir         return msParagraphText.getStr()[nGlobalCharacterIndex - mnCharacterOffset];
1029cdf0e10cSrcweir     }
1030cdf0e10cSrcweir }
1031cdf0e10cSrcweir 
1032cdf0e10cSrcweir 
1033cdf0e10cSrcweir 
1034cdf0e10cSrcweir 
GetText(void) const1035cdf0e10cSrcweir ::rtl::OUString PresenterTextParagraph::GetText (void) const
1036cdf0e10cSrcweir {
1037cdf0e10cSrcweir     return msParagraphText;
1038cdf0e10cSrcweir }
1039cdf0e10cSrcweir 
1040cdf0e10cSrcweir 
1041cdf0e10cSrcweir 
1042cdf0e10cSrcweir 
GetTextSegment(const sal_Int32 nOffset,const sal_Int32 nIndex,const sal_Int16 nTextType) const1043cdf0e10cSrcweir TextSegment PresenterTextParagraph::GetTextSegment (
1044cdf0e10cSrcweir     const sal_Int32 nOffset,
1045cdf0e10cSrcweir     const sal_Int32 nIndex,
1046cdf0e10cSrcweir     const sal_Int16 nTextType) const
1047cdf0e10cSrcweir {
1048cdf0e10cSrcweir     switch(nTextType)
1049cdf0e10cSrcweir     {
1050cdf0e10cSrcweir         case AccessibleTextType::PARAGRAPH:
1051cdf0e10cSrcweir             return TextSegment(
1052cdf0e10cSrcweir                 msParagraphText,
1053cdf0e10cSrcweir                 mnCharacterOffset,
1054cdf0e10cSrcweir                 mnCharacterOffset+msParagraphText.getLength());
1055cdf0e10cSrcweir 
1056cdf0e10cSrcweir         case AccessibleTextType::SENTENCE:
1057cdf0e10cSrcweir             if (mxBreakIterator.is())
1058cdf0e10cSrcweir             {
1059cdf0e10cSrcweir                 const sal_Int32 nStart (mxBreakIterator->beginOfSentence(
1060cdf0e10cSrcweir                     msParagraphText, nIndex-mnCharacterOffset, lang::Locale()));
1061cdf0e10cSrcweir                 const sal_Int32 nEnd (mxBreakIterator->endOfSentence(
1062cdf0e10cSrcweir                     msParagraphText, nIndex-mnCharacterOffset, lang::Locale()));
1063cdf0e10cSrcweir                 if (nStart < nEnd)
1064cdf0e10cSrcweir                     return TextSegment(
1065cdf0e10cSrcweir                         msParagraphText.copy(nStart, nEnd-nStart),
1066cdf0e10cSrcweir                         nStart+mnCharacterOffset,
1067cdf0e10cSrcweir                         nEnd+mnCharacterOffset);
1068cdf0e10cSrcweir             }
1069cdf0e10cSrcweir             break;
1070cdf0e10cSrcweir 
1071cdf0e10cSrcweir         case AccessibleTextType::WORD:
1072cdf0e10cSrcweir             if (mxBreakIterator.is())
1073cdf0e10cSrcweir                 return GetWordTextSegment(nOffset, nIndex);
1074cdf0e10cSrcweir             break;
1075cdf0e10cSrcweir 
1076cdf0e10cSrcweir         case AccessibleTextType::LINE:
1077cdf0e10cSrcweir         {
1078cdf0e10cSrcweir             for (::std::vector<Line>::const_iterator
1079cdf0e10cSrcweir                      iLine(maLines.begin()),
1080cdf0e10cSrcweir                      iEnd(maLines.end());
1081cdf0e10cSrcweir                  iLine!=iEnd;
1082cdf0e10cSrcweir                  ++iLine)
1083cdf0e10cSrcweir             {
1084cdf0e10cSrcweir                 if (nIndex < iLine->mnLineEndCharacterIndex)
1085cdf0e10cSrcweir                 {
1086cdf0e10cSrcweir                     return TextSegment(
1087cdf0e10cSrcweir                         msParagraphText.copy(
1088cdf0e10cSrcweir                             iLine->mnLineStartCharacterIndex,
1089cdf0e10cSrcweir                             iLine->mnLineEndCharacterIndex - iLine->mnLineStartCharacterIndex),
1090cdf0e10cSrcweir                         iLine->mnLineStartCharacterIndex,
1091cdf0e10cSrcweir                         iLine->mnLineEndCharacterIndex);
1092cdf0e10cSrcweir                 }
1093cdf0e10cSrcweir             }
1094cdf0e10cSrcweir         }
1095cdf0e10cSrcweir         break;
1096cdf0e10cSrcweir 
1097cdf0e10cSrcweir         // Handle GLYPH and ATTRIBUTE_RUN like CHARACTER because we can not
1098cdf0e10cSrcweir         // do better at the moment.
1099cdf0e10cSrcweir         case AccessibleTextType::CHARACTER:
1100cdf0e10cSrcweir         case AccessibleTextType::GLYPH:
1101cdf0e10cSrcweir         case AccessibleTextType::ATTRIBUTE_RUN:
1102cdf0e10cSrcweir             return CreateTextSegment(nIndex+nOffset, nIndex+nOffset+1);
1103cdf0e10cSrcweir     }
1104cdf0e10cSrcweir 
1105cdf0e10cSrcweir     return TextSegment(::rtl::OUString(), 0,0);
1106cdf0e10cSrcweir }
1107cdf0e10cSrcweir 
1108cdf0e10cSrcweir 
1109cdf0e10cSrcweir 
1110cdf0e10cSrcweir 
GetWordTextSegment(const sal_Int32 nOffset,const sal_Int32 nIndex) const1111cdf0e10cSrcweir TextSegment PresenterTextParagraph::GetWordTextSegment (
1112cdf0e10cSrcweir     const sal_Int32 nOffset,
1113cdf0e10cSrcweir     const sal_Int32 nIndex) const
1114cdf0e10cSrcweir {
1115cdf0e10cSrcweir     sal_Int32 nCurrentOffset (nOffset);
1116cdf0e10cSrcweir     sal_Int32 nCurrentIndex (nIndex);
1117cdf0e10cSrcweir 
1118cdf0e10cSrcweir     i18n::Boundary aWordBoundary;
1119cdf0e10cSrcweir     if (nCurrentOffset == 0)
1120cdf0e10cSrcweir         aWordBoundary = mxBreakIterator->getWordBoundary(
1121cdf0e10cSrcweir             msParagraphText,
1122cdf0e10cSrcweir             nIndex,
1123cdf0e10cSrcweir             lang::Locale(),
1124cdf0e10cSrcweir             i18n::WordType::ANYWORD_IGNOREWHITESPACES,
1125cdf0e10cSrcweir             sal_True);
1126cdf0e10cSrcweir     else if (nCurrentOffset < 0)
1127cdf0e10cSrcweir     {
1128cdf0e10cSrcweir         while (nCurrentOffset<0 && nCurrentIndex>0)
1129cdf0e10cSrcweir         {
1130cdf0e10cSrcweir             aWordBoundary = mxBreakIterator->previousWord(
1131cdf0e10cSrcweir                 msParagraphText,
1132cdf0e10cSrcweir                 nCurrentIndex,
1133cdf0e10cSrcweir                 lang::Locale(),
1134cdf0e10cSrcweir                 i18n::WordType::ANYWORD_IGNOREWHITESPACES);
1135cdf0e10cSrcweir             nCurrentIndex = aWordBoundary.startPos;
1136cdf0e10cSrcweir             ++nCurrentOffset;
1137cdf0e10cSrcweir         }
1138cdf0e10cSrcweir     }
1139cdf0e10cSrcweir     else
1140cdf0e10cSrcweir     {
1141cdf0e10cSrcweir         while (nCurrentOffset>0 && nCurrentIndex<=GetCharacterCount())
1142cdf0e10cSrcweir         {
1143cdf0e10cSrcweir             aWordBoundary = mxBreakIterator->nextWord(
1144cdf0e10cSrcweir                 msParagraphText,
1145cdf0e10cSrcweir                 nCurrentIndex,
1146cdf0e10cSrcweir                 lang::Locale(),
1147cdf0e10cSrcweir                 i18n::WordType::ANYWORD_IGNOREWHITESPACES);
1148cdf0e10cSrcweir             nCurrentIndex = aWordBoundary.endPos;
1149cdf0e10cSrcweir             --nCurrentOffset;
1150cdf0e10cSrcweir         }
1151cdf0e10cSrcweir     }
1152cdf0e10cSrcweir 
1153cdf0e10cSrcweir     return CreateTextSegment(aWordBoundary.startPos, aWordBoundary.endPos);
1154cdf0e10cSrcweir }
1155cdf0e10cSrcweir 
1156cdf0e10cSrcweir 
1157cdf0e10cSrcweir 
1158cdf0e10cSrcweir 
CreateTextSegment(sal_Int32 nStartIndex,sal_Int32 nEndIndex) const1159cdf0e10cSrcweir TextSegment PresenterTextParagraph::CreateTextSegment (
1160cdf0e10cSrcweir     sal_Int32 nStartIndex,
1161cdf0e10cSrcweir     sal_Int32 nEndIndex) const
1162cdf0e10cSrcweir {
1163cdf0e10cSrcweir     if (nEndIndex <= nStartIndex)
1164cdf0e10cSrcweir         return TextSegment(
1165cdf0e10cSrcweir             ::rtl::OUString(),
1166cdf0e10cSrcweir             nStartIndex,
1167cdf0e10cSrcweir             nEndIndex);
1168cdf0e10cSrcweir     else
1169cdf0e10cSrcweir         return TextSegment(
1170cdf0e10cSrcweir             msParagraphText.copy(nStartIndex, nEndIndex-nStartIndex),
1171cdf0e10cSrcweir             nStartIndex,
1172cdf0e10cSrcweir             nEndIndex);
1173cdf0e10cSrcweir }
1174cdf0e10cSrcweir 
1175cdf0e10cSrcweir 
1176cdf0e10cSrcweir 
1177cdf0e10cSrcweir 
GetCharacterBounds(sal_Int32 nGlobalCharacterIndex,const bool bCaretBox)1178cdf0e10cSrcweir awt::Rectangle PresenterTextParagraph::GetCharacterBounds (
1179cdf0e10cSrcweir     sal_Int32 nGlobalCharacterIndex,
1180cdf0e10cSrcweir     const bool bCaretBox)
1181cdf0e10cSrcweir {
1182cdf0e10cSrcweir     // Find the line that contains the requested character and accumulate
1183cdf0e10cSrcweir     // the previous line heights.
1184cdf0e10cSrcweir     sal_Int32 nFirstCharacterIndex (0);
1185cdf0e10cSrcweir     sal_Int32 nEndCharacterIndex (0);
1186cdf0e10cSrcweir     double nX (mnXOrigin);
1187cdf0e10cSrcweir     double nY (mnYOrigin + mnVerticalOffset + mnAscent);
1188cdf0e10cSrcweir     const sal_Int8 nTextDirection (GetTextDirection());
1189cdf0e10cSrcweir     for (sal_Int32 nLineIndex=0,nLineCount=maLines.size();
1190cdf0e10cSrcweir          nLineIndex<nLineCount;
1191cdf0e10cSrcweir          ++nLineIndex, nFirstCharacterIndex=nEndCharacterIndex, nY+=mnLineHeight)
1192cdf0e10cSrcweir     {
1193cdf0e10cSrcweir         Line& rLine (maLines[nLineIndex]);
1194cdf0e10cSrcweir         // Skip lines before the indexed character.
1195cdf0e10cSrcweir         if (nGlobalCharacterIndex >= rLine.mnLineEndCharacterIndex)
1196cdf0e10cSrcweir             // When in the last line then allow the index past the last char.
1197cdf0e10cSrcweir             if (nLineIndex<nLineCount-1)
1198cdf0e10cSrcweir                 continue;
1199cdf0e10cSrcweir 
1200cdf0e10cSrcweir         rLine.ProvideCellBoxes();
1201cdf0e10cSrcweir 
1202cdf0e10cSrcweir         const sal_Int32 nCellIndex (nGlobalCharacterIndex - rLine.mnLineStartCharacterIndex);
1203cdf0e10cSrcweir 
1204cdf0e10cSrcweir         // The cell bounding box is defined relative to the origin of
1205cdf0e10cSrcweir         // the current line.  Therefore we have to add the absolute
1206cdf0e10cSrcweir         // position of the line.
1207cdf0e10cSrcweir         geometry::RealRectangle2D rCellBox (rLine.maCellBoxes[
1208cdf0e10cSrcweir             ::std::min(nCellIndex, rLine.maCellBoxes.getLength()-1)]);
1209cdf0e10cSrcweir 
1210cdf0e10cSrcweir         double nLeft = nX + rCellBox.X1;
1211cdf0e10cSrcweir         double nRight = nX + rCellBox.X2;
1212cdf0e10cSrcweir         if (nTextDirection == rendering::TextDirection::WEAK_RIGHT_TO_LEFT)
1213cdf0e10cSrcweir         {
1214cdf0e10cSrcweir             const double nOldRight (nRight);
1215cdf0e10cSrcweir             nRight = rLine.mnWidth - nLeft;
1216cdf0e10cSrcweir             nLeft = rLine.mnWidth - nOldRight;
1217cdf0e10cSrcweir         }
1218cdf0e10cSrcweir         double nTop (nY + rCellBox.Y1);
1219cdf0e10cSrcweir         double nBottom (nY + rCellBox.Y2);
1220cdf0e10cSrcweir         if (bCaretBox)
1221cdf0e10cSrcweir         {
1222cdf0e10cSrcweir             nTop = nTop - rCellBox.Y1 - mnAscent;
1223cdf0e10cSrcweir             nBottom = nTop + mnLineHeight;
1224cdf0e10cSrcweir             if (nCellIndex >= rLine.maCellBoxes.getLength())
1225cdf0e10cSrcweir                 nLeft = nRight-2;
1226cdf0e10cSrcweir             if (nLeft < nX)
1227cdf0e10cSrcweir                 nLeft = nX;
1228cdf0e10cSrcweir             nRight = nLeft+2;
1229cdf0e10cSrcweir         }
1230cdf0e10cSrcweir         else
1231cdf0e10cSrcweir         {
1232cdf0e10cSrcweir             nTop = nTop - rCellBox.Y1 - mnAscent;
1233cdf0e10cSrcweir             nBottom = nTop + mnAscent + mnDescent;
1234cdf0e10cSrcweir         }
1235cdf0e10cSrcweir         const sal_Int32 nX1 = sal_Int32(floor(nLeft));
1236cdf0e10cSrcweir         const sal_Int32 nY1 = sal_Int32(floor(nTop));
1237cdf0e10cSrcweir         const sal_Int32 nX2 = sal_Int32(ceil(nRight));
1238cdf0e10cSrcweir         const sal_Int32 nY2 = sal_Int32(ceil(nBottom));
1239cdf0e10cSrcweir 
1240cdf0e10cSrcweir         return awt::Rectangle(nX1,nY1,nX2-nX1+1,nY2-nY1+1);
1241cdf0e10cSrcweir     }
1242cdf0e10cSrcweir 
1243cdf0e10cSrcweir     // We are still here.  That means that the given index lies past the
1244cdf0e10cSrcweir     // last character in the paragraph.
1245cdf0e10cSrcweir     // Return an empty box that lies past the last character.  Better than nothing.
1246cdf0e10cSrcweir     return awt::Rectangle(sal_Int32(nX+0.5), sal_Int32(nY+0.5), 0, 0);
1247cdf0e10cSrcweir }
1248cdf0e10cSrcweir 
1249cdf0e10cSrcweir 
1250cdf0e10cSrcweir 
1251cdf0e10cSrcweir 
GetIndexAtPoint(const awt::Point & rPoint) const1252cdf0e10cSrcweir sal_Int32 PresenterTextParagraph::GetIndexAtPoint (const awt::Point& rPoint) const
1253cdf0e10cSrcweir {
1254cdf0e10cSrcweir     (void)rPoint;
1255cdf0e10cSrcweir     return -1;
1256cdf0e10cSrcweir }
1257cdf0e10cSrcweir 
1258cdf0e10cSrcweir 
1259cdf0e10cSrcweir 
1260cdf0e10cSrcweir 
GetTextDirection(void) const1261cdf0e10cSrcweir sal_Int8 PresenterTextParagraph::GetTextDirection (void) const
1262cdf0e10cSrcweir {
1263cdf0e10cSrcweir     // Find first portion that has a non-neutral text direction.
1264cdf0e10cSrcweir     sal_Int32 nPosition (0);
1265cdf0e10cSrcweir     sal_Int32 nTextLength (msParagraphText.getLength());
1266cdf0e10cSrcweir     while (nPosition < nTextLength)
1267cdf0e10cSrcweir     {
1268cdf0e10cSrcweir         const sal_Int16 nScriptDirection (
1269cdf0e10cSrcweir             mxScriptTypeDetector->getScriptDirection(
1270cdf0e10cSrcweir                 msParagraphText, nPosition, i18n::ScriptDirection::NEUTRAL));
1271cdf0e10cSrcweir         switch (nScriptDirection)
1272cdf0e10cSrcweir         {
1273cdf0e10cSrcweir             case i18n::ScriptDirection::NEUTRAL:
1274cdf0e10cSrcweir                 // continue looping.
1275cdf0e10cSrcweir                 break;
1276cdf0e10cSrcweir             case i18n::ScriptDirection::LEFT_TO_RIGHT:
1277cdf0e10cSrcweir                 return rendering::TextDirection::WEAK_LEFT_TO_RIGHT;
1278cdf0e10cSrcweir 
1279cdf0e10cSrcweir             case i18n::ScriptDirection::RIGHT_TO_LEFT:
1280cdf0e10cSrcweir                 return rendering::TextDirection::WEAK_RIGHT_TO_LEFT;
1281cdf0e10cSrcweir         }
1282cdf0e10cSrcweir 
1283cdf0e10cSrcweir         nPosition = mxScriptTypeDetector->endOfScriptDirection(
1284cdf0e10cSrcweir             msParagraphText, nPosition, nScriptDirection);
1285cdf0e10cSrcweir     }
1286cdf0e10cSrcweir 
1287cdf0e10cSrcweir     // All text in paragraph is neutral.  Fall back on writing mode taken
1288cdf0e10cSrcweir     // from the XText (which may not be properly initialized.)
1289cdf0e10cSrcweir     sal_Int8 nTextDirection(rendering::TextDirection::WEAK_LEFT_TO_RIGHT);
1290cdf0e10cSrcweir     switch(mnWritingMode)
1291cdf0e10cSrcweir     {
1292cdf0e10cSrcweir         case text::WritingMode2::LR_TB:
1293cdf0e10cSrcweir             nTextDirection = rendering::TextDirection::WEAK_LEFT_TO_RIGHT;
1294cdf0e10cSrcweir             break;
1295cdf0e10cSrcweir 
1296cdf0e10cSrcweir         case text::WritingMode2::RL_TB:
1297cdf0e10cSrcweir             nTextDirection = rendering::TextDirection::WEAK_RIGHT_TO_LEFT;
1298cdf0e10cSrcweir             break;
1299cdf0e10cSrcweir 
1300cdf0e10cSrcweir         default:
1301cdf0e10cSrcweir         case text::WritingMode2::TB_RL:
1302cdf0e10cSrcweir         case text::WritingMode2::TB_LR:
1303cdf0e10cSrcweir             // Can not handle this.  Use default and hope for the best.
1304cdf0e10cSrcweir             break;
1305cdf0e10cSrcweir     }
1306cdf0e10cSrcweir     return nTextDirection;
1307cdf0e10cSrcweir }
1308cdf0e10cSrcweir 
1309cdf0e10cSrcweir 
1310cdf0e10cSrcweir 
1311cdf0e10cSrcweir 
IsTextReferencePointLeft(void) const1312cdf0e10cSrcweir bool PresenterTextParagraph::IsTextReferencePointLeft (void) const
1313cdf0e10cSrcweir {
1314cdf0e10cSrcweir     return mnWritingMode != text::WritingMode2::RL_TB;
1315cdf0e10cSrcweir }
1316cdf0e10cSrcweir 
1317cdf0e10cSrcweir 
1318cdf0e10cSrcweir 
1319cdf0e10cSrcweir 
SetupCellArray(const PresenterTheme::SharedFontDescriptor & rpFont)1320cdf0e10cSrcweir void PresenterTextParagraph::SetupCellArray (
1321cdf0e10cSrcweir     const PresenterTheme::SharedFontDescriptor& rpFont)
1322cdf0e10cSrcweir {
1323cdf0e10cSrcweir     maCells.clear();
1324cdf0e10cSrcweir 
1325cdf0e10cSrcweir     if ( ! rpFont || ! rpFont->mxFont.is())
1326cdf0e10cSrcweir         return;
1327cdf0e10cSrcweir 
1328cdf0e10cSrcweir     sal_Int32 nPosition (0);
1329cdf0e10cSrcweir     sal_Int32 nIndex (0);
1330cdf0e10cSrcweir     const sal_Int32 nTextLength (msParagraphText.getLength());
1331cdf0e10cSrcweir     const sal_Int8 nTextDirection (GetTextDirection());
1332cdf0e10cSrcweir     while (nPosition < nTextLength)
1333cdf0e10cSrcweir     {
1334cdf0e10cSrcweir         const sal_Int32 nNewPosition (mxBreakIterator->nextCharacters(
1335cdf0e10cSrcweir             msParagraphText,
1336cdf0e10cSrcweir             nPosition,
1337cdf0e10cSrcweir             lang::Locale(),
1338cdf0e10cSrcweir             i18n::CharacterIteratorMode::SKIPCELL,
1339cdf0e10cSrcweir             1,
1340cdf0e10cSrcweir             nIndex));
1341cdf0e10cSrcweir 
1342cdf0e10cSrcweir         rendering::StringContext aContext (msParagraphText, nPosition, nNewPosition-nPosition);
1343cdf0e10cSrcweir         Reference<rendering::XTextLayout> xLayout (
1344cdf0e10cSrcweir             rpFont->mxFont->createTextLayout(aContext, nTextDirection, 0));
1345cdf0e10cSrcweir         css::geometry::RealRectangle2D aCharacterBox (xLayout->queryTextBounds());
1346cdf0e10cSrcweir 
1347cdf0e10cSrcweir         maCells.push_back(Cell(
1348cdf0e10cSrcweir             nPosition,
1349cdf0e10cSrcweir             nNewPosition-nPosition,
1350cdf0e10cSrcweir             aCharacterBox.X2-aCharacterBox.X1));
1351cdf0e10cSrcweir 
1352cdf0e10cSrcweir         nPosition = nNewPosition;
1353cdf0e10cSrcweir     }
1354cdf0e10cSrcweir }
1355cdf0e10cSrcweir 
1356cdf0e10cSrcweir 
1357cdf0e10cSrcweir 
1358cdf0e10cSrcweir 
1359cdf0e10cSrcweir //===== PresenterTextCaret ================================================----
1360cdf0e10cSrcweir 
PresenterTextCaret(const::boost::function<css::awt::Rectangle (const sal_Int32,const sal_Int32)> & rCharacterBoundsAccess,const::boost::function<void (const css::awt::Rectangle &)> & rInvalidator)1361cdf0e10cSrcweir PresenterTextCaret::PresenterTextCaret (
1362cdf0e10cSrcweir     const ::boost::function<css::awt::Rectangle(const sal_Int32,const sal_Int32)>& rCharacterBoundsAccess,
1363cdf0e10cSrcweir     const ::boost::function<void(const css::awt::Rectangle&)>& rInvalidator)
1364cdf0e10cSrcweir     : mnParagraphIndex(-1),
1365cdf0e10cSrcweir       mnCharacterIndex(-1),
1366cdf0e10cSrcweir       mnCaretBlinkTaskId(0),
1367cdf0e10cSrcweir       mbIsCaretVisible(false),
1368cdf0e10cSrcweir       maCharacterBoundsAccess(rCharacterBoundsAccess),
1369cdf0e10cSrcweir       maInvalidator(rInvalidator),
1370cdf0e10cSrcweir       maBroadcaster(),
1371cdf0e10cSrcweir       maCaretBounds()
1372cdf0e10cSrcweir {
1373cdf0e10cSrcweir }
1374cdf0e10cSrcweir 
1375cdf0e10cSrcweir 
1376cdf0e10cSrcweir 
1377cdf0e10cSrcweir 
~PresenterTextCaret(void)1378cdf0e10cSrcweir PresenterTextCaret::~PresenterTextCaret (void)
1379cdf0e10cSrcweir {
1380cdf0e10cSrcweir     HideCaret();
1381cdf0e10cSrcweir }
1382cdf0e10cSrcweir 
1383cdf0e10cSrcweir 
1384cdf0e10cSrcweir 
1385cdf0e10cSrcweir 
ShowCaret(void)1386cdf0e10cSrcweir void PresenterTextCaret::ShowCaret (void)
1387cdf0e10cSrcweir {
1388cdf0e10cSrcweir     if (mnCaretBlinkTaskId == 0)
1389cdf0e10cSrcweir     {
1390cdf0e10cSrcweir         mnCaretBlinkTaskId = PresenterTimer::ScheduleRepeatedTask (
1391cdf0e10cSrcweir             ::boost::bind(&PresenterTextCaret::InvertCaret, this),
1392cdf0e10cSrcweir             CaretBlinkIntervall,
1393cdf0e10cSrcweir             CaretBlinkIntervall);
1394cdf0e10cSrcweir     }
1395cdf0e10cSrcweir     mbIsCaretVisible = true;
1396cdf0e10cSrcweir }
1397cdf0e10cSrcweir 
1398cdf0e10cSrcweir 
1399cdf0e10cSrcweir 
1400cdf0e10cSrcweir 
HideCaret(void)1401cdf0e10cSrcweir void PresenterTextCaret::HideCaret (void)
1402cdf0e10cSrcweir {
1403cdf0e10cSrcweir     if (mnCaretBlinkTaskId != 0)
1404cdf0e10cSrcweir     {
1405cdf0e10cSrcweir         PresenterTimer::CancelTask(mnCaretBlinkTaskId);
1406cdf0e10cSrcweir         mnCaretBlinkTaskId = 0;
1407cdf0e10cSrcweir     }
1408cdf0e10cSrcweir     mbIsCaretVisible = false;
1409cdf0e10cSrcweir     // Reset the caret position.
1410cdf0e10cSrcweir     mnParagraphIndex = -1;
1411cdf0e10cSrcweir     mnCharacterIndex = -1;
1412cdf0e10cSrcweir }
1413cdf0e10cSrcweir 
1414cdf0e10cSrcweir 
1415cdf0e10cSrcweir 
1416cdf0e10cSrcweir 
GetParagraphIndex(void) const1417cdf0e10cSrcweir sal_Int32 PresenterTextCaret::GetParagraphIndex (void) const
1418cdf0e10cSrcweir {
1419cdf0e10cSrcweir     return mnParagraphIndex;
1420cdf0e10cSrcweir }
1421cdf0e10cSrcweir 
1422cdf0e10cSrcweir 
1423cdf0e10cSrcweir 
1424cdf0e10cSrcweir 
GetCharacterIndex(void) const1425cdf0e10cSrcweir sal_Int32 PresenterTextCaret::GetCharacterIndex (void) const
1426cdf0e10cSrcweir {
1427cdf0e10cSrcweir     return mnCharacterIndex;
1428cdf0e10cSrcweir }
1429cdf0e10cSrcweir 
1430cdf0e10cSrcweir 
1431cdf0e10cSrcweir 
1432cdf0e10cSrcweir 
SetPosition(const sal_Int32 nParagraphIndex,const sal_Int32 nCharacterIndex)1433cdf0e10cSrcweir void PresenterTextCaret::SetPosition (
1434cdf0e10cSrcweir     const sal_Int32 nParagraphIndex,
1435cdf0e10cSrcweir     const sal_Int32 nCharacterIndex)
1436cdf0e10cSrcweir {
1437cdf0e10cSrcweir     if (mnParagraphIndex != nParagraphIndex
1438cdf0e10cSrcweir         || mnCharacterIndex != nCharacterIndex)
1439cdf0e10cSrcweir     {
1440cdf0e10cSrcweir         if (mnParagraphIndex >= 0)
1441cdf0e10cSrcweir             maInvalidator(maCaretBounds);
1442cdf0e10cSrcweir 
1443cdf0e10cSrcweir         const sal_Int32 nOldParagraphIndex (mnParagraphIndex);
1444cdf0e10cSrcweir         const sal_Int32 nOldCharacterIndex (mnCharacterIndex);
1445cdf0e10cSrcweir         mnParagraphIndex = nParagraphIndex;
1446cdf0e10cSrcweir         mnCharacterIndex = nCharacterIndex;
1447cdf0e10cSrcweir         maCaretBounds = maCharacterBoundsAccess(mnParagraphIndex, mnCharacterIndex);
1448cdf0e10cSrcweir         if (mnParagraphIndex >= 0)
1449cdf0e10cSrcweir             ShowCaret();
1450cdf0e10cSrcweir         else
1451cdf0e10cSrcweir             HideCaret();
1452cdf0e10cSrcweir 
1453cdf0e10cSrcweir         if (mnParagraphIndex >= 0)
1454cdf0e10cSrcweir             maInvalidator(maCaretBounds);
1455cdf0e10cSrcweir 
1456cdf0e10cSrcweir         if (maBroadcaster)
1457cdf0e10cSrcweir             maBroadcaster(
1458cdf0e10cSrcweir                 nOldParagraphIndex,
1459cdf0e10cSrcweir                 nOldCharacterIndex,
1460cdf0e10cSrcweir                 mnParagraphIndex,
1461cdf0e10cSrcweir                 mnCharacterIndex);
1462cdf0e10cSrcweir 
1463cdf0e10cSrcweir     }
1464cdf0e10cSrcweir }
1465cdf0e10cSrcweir 
1466cdf0e10cSrcweir 
1467cdf0e10cSrcweir 
1468cdf0e10cSrcweir 
IsVisible(void) const1469cdf0e10cSrcweir bool PresenterTextCaret::IsVisible (void) const
1470cdf0e10cSrcweir {
1471cdf0e10cSrcweir     return mbIsCaretVisible;
1472cdf0e10cSrcweir }
1473cdf0e10cSrcweir 
1474cdf0e10cSrcweir 
1475cdf0e10cSrcweir 
1476cdf0e10cSrcweir 
SetCaretMotionBroadcaster(const::boost::function<void (sal_Int32,sal_Int32,sal_Int32,sal_Int32)> & rBroadcaster)1477cdf0e10cSrcweir void PresenterTextCaret::SetCaretMotionBroadcaster (
1478cdf0e10cSrcweir     const ::boost::function<void(sal_Int32,sal_Int32,sal_Int32,sal_Int32)>& rBroadcaster)
1479cdf0e10cSrcweir {
1480cdf0e10cSrcweir     maBroadcaster = rBroadcaster;
1481cdf0e10cSrcweir }
1482cdf0e10cSrcweir 
1483cdf0e10cSrcweir 
1484cdf0e10cSrcweir 
1485cdf0e10cSrcweir 
GetBounds(void) const1486cdf0e10cSrcweir css::awt::Rectangle PresenterTextCaret::GetBounds (void) const
1487cdf0e10cSrcweir {
1488cdf0e10cSrcweir     return maCaretBounds;
1489cdf0e10cSrcweir }
1490cdf0e10cSrcweir 
1491cdf0e10cSrcweir 
1492cdf0e10cSrcweir 
1493cdf0e10cSrcweir 
InvertCaret(void)1494cdf0e10cSrcweir void PresenterTextCaret::InvertCaret (void)
1495cdf0e10cSrcweir {
1496cdf0e10cSrcweir     mbIsCaretVisible = !mbIsCaretVisible;
1497cdf0e10cSrcweir     if (mnParagraphIndex >= 0)
1498cdf0e10cSrcweir         maInvalidator(maCaretBounds);
1499cdf0e10cSrcweir }
1500cdf0e10cSrcweir 
1501cdf0e10cSrcweir 
1502cdf0e10cSrcweir 
1503cdf0e10cSrcweir 
1504cdf0e10cSrcweir 
1505cdf0e10cSrcweir 
1506cdf0e10cSrcweir 
1507cdf0e10cSrcweir //===== PresenterTextParagraph::Cell ==========================================
1508cdf0e10cSrcweir 
Cell(const sal_Int32 nCharacterIndex,const sal_Int32 nCharacterCount,const double nCellWidth)1509cdf0e10cSrcweir PresenterTextParagraph::Cell::Cell (
1510cdf0e10cSrcweir     const sal_Int32 nCharacterIndex,
1511cdf0e10cSrcweir     const sal_Int32 nCharacterCount,
1512cdf0e10cSrcweir     const double nCellWidth)
1513cdf0e10cSrcweir     : mnCharacterIndex(nCharacterIndex),
1514cdf0e10cSrcweir       mnCharacterCount(nCharacterCount),
1515cdf0e10cSrcweir       mnCellWidth(nCellWidth)
1516cdf0e10cSrcweir {
1517cdf0e10cSrcweir }
1518cdf0e10cSrcweir 
1519cdf0e10cSrcweir 
1520cdf0e10cSrcweir 
1521cdf0e10cSrcweir 
1522cdf0e10cSrcweir //===== PresenterTextParagraph::Line ==========================================
1523cdf0e10cSrcweir 
Line(const sal_Int32 nLineStartCharacterIndex,const sal_Int32 nLineEndCharacterIndex)1524cdf0e10cSrcweir PresenterTextParagraph::Line::Line (
1525cdf0e10cSrcweir     const sal_Int32 nLineStartCharacterIndex,
1526cdf0e10cSrcweir     const sal_Int32 nLineEndCharacterIndex)
1527cdf0e10cSrcweir     : mnLineStartCharacterIndex(nLineStartCharacterIndex),
1528cdf0e10cSrcweir       mnLineEndCharacterIndex(nLineEndCharacterIndex),
1529cdf0e10cSrcweir       mnLineStartCellIndex(-1), mnLineEndCellIndex(-1),
1530cdf0e10cSrcweir       mxLayoutedLine(),
1531cdf0e10cSrcweir       mnBaseLine(0), mnWidth(0),
1532cdf0e10cSrcweir       maCellBoxes()
1533cdf0e10cSrcweir {
1534cdf0e10cSrcweir }
1535cdf0e10cSrcweir 
1536cdf0e10cSrcweir 
1537cdf0e10cSrcweir 
1538cdf0e10cSrcweir 
GetLength(void) const1539cdf0e10cSrcweir sal_Int32 PresenterTextParagraph::Line::GetLength (void) const
1540cdf0e10cSrcweir {
1541cdf0e10cSrcweir     return mnLineEndCharacterIndex-mnLineStartCharacterIndex;
1542cdf0e10cSrcweir }
1543cdf0e10cSrcweir 
1544cdf0e10cSrcweir 
1545cdf0e10cSrcweir 
1546cdf0e10cSrcweir 
ProvideCellBoxes(void)1547cdf0e10cSrcweir void PresenterTextParagraph::Line::ProvideCellBoxes (void)
1548cdf0e10cSrcweir {
1549cdf0e10cSrcweir     if ( ! IsEmpty() && maCellBoxes.getLength()==0)
1550cdf0e10cSrcweir     {
1551cdf0e10cSrcweir         if (mxLayoutedLine.is())
1552cdf0e10cSrcweir             maCellBoxes = mxLayoutedLine->queryInkMeasures();
1553cdf0e10cSrcweir         else
1554cdf0e10cSrcweir         {
1555cdf0e10cSrcweir             OSL_ASSERT(mxLayoutedLine.is());
1556cdf0e10cSrcweir         }
1557cdf0e10cSrcweir     }
1558cdf0e10cSrcweir }
1559cdf0e10cSrcweir 
1560cdf0e10cSrcweir 
1561cdf0e10cSrcweir 
1562cdf0e10cSrcweir 
ProvideLayoutedLine(const::rtl::OUString & rsParagraphText,const PresenterTheme::SharedFontDescriptor & rpFont,const sal_Int8 nTextDirection)1563cdf0e10cSrcweir void PresenterTextParagraph::Line::ProvideLayoutedLine (
1564cdf0e10cSrcweir     const ::rtl::OUString& rsParagraphText,
1565cdf0e10cSrcweir     const PresenterTheme::SharedFontDescriptor& rpFont,
1566cdf0e10cSrcweir     const sal_Int8 nTextDirection)
1567cdf0e10cSrcweir {
1568cdf0e10cSrcweir     if ( ! mxLayoutedLine.is())
1569cdf0e10cSrcweir     {
1570cdf0e10cSrcweir         const rendering::StringContext aContext (
1571cdf0e10cSrcweir             rsParagraphText,
1572cdf0e10cSrcweir             mnLineStartCharacterIndex,
1573cdf0e10cSrcweir             mnLineEndCharacterIndex - mnLineStartCharacterIndex);
1574cdf0e10cSrcweir 
1575cdf0e10cSrcweir         mxLayoutedLine = rpFont->mxFont->createTextLayout(
1576cdf0e10cSrcweir             aContext,
1577cdf0e10cSrcweir             nTextDirection,
1578cdf0e10cSrcweir             0);
1579cdf0e10cSrcweir     }
1580cdf0e10cSrcweir }
1581cdf0e10cSrcweir 
1582cdf0e10cSrcweir 
1583cdf0e10cSrcweir 
1584cdf0e10cSrcweir 
IsEmpty(void) const1585cdf0e10cSrcweir bool PresenterTextParagraph::Line::IsEmpty (void) const
1586cdf0e10cSrcweir {
1587cdf0e10cSrcweir     return mnLineStartCharacterIndex >= mnLineEndCharacterIndex;
1588cdf0e10cSrcweir }
1589cdf0e10cSrcweir 
1590cdf0e10cSrcweir 
1591cdf0e10cSrcweir 
1592cdf0e10cSrcweir 
1593cdf0e10cSrcweir } } // end of namespace ::sdext::presenter
1594