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