LCOV - code coverage report
Current view: top level - sdext/source/presenter - PresenterTextView.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1 516 0.2 %
Date: 2012-08-25 Functions: 2 59 3.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 589 0.3 %

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

Generated by: LCOV version 1.10