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