LCOV - code coverage report
Current view: top level - libreoffice/drawinglayer/source/primitive2d - textbreakuphelper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 109 0.0 %
Date: 2012-12-27 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <drawinglayer/primitive2d/textbreakuphelper.hxx>
      21             : #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
      22             : #include <com/sun/star/i18n/XBreakIterator.hpp>
      23             : #include <comphelper/processfactory.hxx>
      24             : #include <com/sun/star/i18n/CharacterIteratorMode.hdl>
      25             : #include <com/sun/star/i18n/WordType.hpp>
      26             : #include <com/sun/star/i18n/CharType.hpp>
      27             : 
      28             : //////////////////////////////////////////////////////////////////////////////
      29             : 
      30             : namespace drawinglayer
      31             : {
      32             :     namespace primitive2d
      33             :     {
      34           0 :         TextBreakupHelper::TextBreakupHelper(const TextSimplePortionPrimitive2D& rSource)
      35             :         :   mrSource(rSource),
      36             :             mxResult(),
      37             :             maTextLayouter(),
      38             :             maDecTrans(),
      39           0 :             mbNoDXArray(false)
      40             :         {
      41             :             OSL_ENSURE(dynamic_cast< const TextSimplePortionPrimitive2D* >(&mrSource), "TextBreakupHelper with illegal primitive created (!)");
      42           0 :             maDecTrans = mrSource.getTextTransform();
      43           0 :             mbNoDXArray = mrSource.getDXArray().empty();
      44             : 
      45           0 :             if(mbNoDXArray)
      46             :             {
      47             :                 // init TextLayouter when no dxarray
      48             :                 maTextLayouter.setFontAttribute(
      49           0 :                     mrSource.getFontAttribute(),
      50           0 :                     maDecTrans.getScale().getX(),
      51           0 :                     maDecTrans.getScale().getY(),
      52           0 :                     mrSource.getLocale());
      53             :             }
      54           0 :         }
      55             : 
      56           0 :         TextBreakupHelper::~TextBreakupHelper()
      57             :         {
      58           0 :         }
      59             : 
      60           0 :         void TextBreakupHelper::breakupPortion(Primitive2DVector& rTempResult, sal_uInt32 nIndex, sal_uInt32 nLength, bool bWordLineMode)
      61             :         {
      62           0 :             if(nLength && !(nIndex == mrSource.getTextPosition() && nLength == mrSource.getTextLength()))
      63             :             {
      64             :                 // prepare values for new portion
      65           0 :                 basegfx::B2DHomMatrix aNewTransform;
      66           0 :                 ::std::vector< double > aNewDXArray;
      67           0 :                 const bool bNewStartIsNotOldStart(nIndex > mrSource.getTextPosition());
      68             : 
      69           0 :                 if(!mbNoDXArray)
      70             :                 {
      71             :                     // prepare new DXArray for the single word
      72             :                     aNewDXArray = ::std::vector< double >(
      73           0 :                         mrSource.getDXArray().begin() + (nIndex - mrSource.getTextPosition()),
      74           0 :                         mrSource.getDXArray().begin() + ((nIndex + nLength) - mrSource.getTextPosition()));
      75             :                 }
      76             : 
      77           0 :                 if(bNewStartIsNotOldStart)
      78             :                 {
      79             :                     // needs to be moved to a new start position
      80           0 :                     double fOffset(0.0);
      81             : 
      82           0 :                     if(mbNoDXArray)
      83             :                     {
      84             :                         // evaluate using TextLayouter
      85           0 :                         fOffset = maTextLayouter.getTextWidth(mrSource.getText(), mrSource.getTextPosition(), nIndex);
      86             :                     }
      87             :                     else
      88             :                     {
      89             :                         // get from DXArray
      90           0 :                         const sal_uInt32 nIndex2(static_cast< sal_uInt32 >(nIndex - mrSource.getTextPosition()));
      91           0 :                         fOffset = mrSource.getDXArray()[nIndex2 - 1];
      92             :                     }
      93             : 
      94             :                     // need offset without FontScale for building the new transformation. The
      95             :                     // new transformation will be multiplied with the current text transformation
      96             :                     // so FontScale would be double
      97           0 :                     double fOffsetNoScale(fOffset);
      98           0 :                     const double fFontScaleX(maDecTrans.getScale().getX());
      99             : 
     100           0 :                     if(!basegfx::fTools::equal(fFontScaleX, 1.0)
     101           0 :                         && !basegfx::fTools::equalZero(fFontScaleX))
     102             :                     {
     103           0 :                         fOffsetNoScale /= fFontScaleX;
     104             :                     }
     105             : 
     106             :                     // apply needed offset to transformation
     107           0 :                     aNewTransform.translate(fOffsetNoScale, 0.0);
     108             : 
     109           0 :                     if(!mbNoDXArray)
     110             :                     {
     111             :                         // DXArray values need to be corrected with the offset, too. Here,
     112             :                         // take the scaled offset since the DXArray is scaled
     113           0 :                         const sal_uInt32 nArraySize(aNewDXArray.size());
     114             : 
     115           0 :                         for(sal_uInt32 a(0); a < nArraySize; a++)
     116             :                         {
     117           0 :                             aNewDXArray[a] -= fOffset;
     118             :                         }
     119             :                     }
     120             :                 }
     121             : 
     122             :                 // add text transformation to new transformation
     123           0 :                 aNewTransform = maDecTrans.getB2DHomMatrix() * aNewTransform;
     124             : 
     125             :                 // callback to allow evtl. changes
     126           0 :                 const bool bCreate(allowChange(rTempResult.size(), aNewTransform, nIndex, nLength));
     127             : 
     128           0 :                 if(bCreate)
     129             :                 {
     130             :                     // check if we have a decorated primitive as source
     131             :                     const TextDecoratedPortionPrimitive2D* pTextDecoratedPortionPrimitive2D =
     132           0 :                         dynamic_cast< const TextDecoratedPortionPrimitive2D* >(&mrSource);
     133             : 
     134           0 :                     if(pTextDecoratedPortionPrimitive2D)
     135             :                     {
     136             :                         // create a TextDecoratedPortionPrimitive2D
     137             :                         rTempResult.push_back(
     138             :                             new TextDecoratedPortionPrimitive2D(
     139             :                                 aNewTransform,
     140           0 :                                 mrSource.getText(),
     141             :                                 nIndex,
     142             :                                 nLength,
     143             :                                 aNewDXArray,
     144           0 :                                 mrSource.getFontAttribute(),
     145           0 :                                 mrSource.getLocale(),
     146           0 :                                 mrSource.getFontColor(),
     147             : 
     148             :                                 pTextDecoratedPortionPrimitive2D->getOverlineColor(),
     149             :                                 pTextDecoratedPortionPrimitive2D->getTextlineColor(),
     150             :                                 pTextDecoratedPortionPrimitive2D->getFontOverline(),
     151             :                                 pTextDecoratedPortionPrimitive2D->getFontUnderline(),
     152           0 :                                 pTextDecoratedPortionPrimitive2D->getUnderlineAbove(),
     153             :                                 pTextDecoratedPortionPrimitive2D->getTextStrikeout(),
     154             : 
     155             :                                 // reset WordLineMode when BreakupUnit_word is executed; else copy original
     156           0 :                                 bWordLineMode ? false : pTextDecoratedPortionPrimitive2D->getWordLineMode(),
     157             : 
     158             :                                 pTextDecoratedPortionPrimitive2D->getTextEmphasisMark(),
     159           0 :                                 pTextDecoratedPortionPrimitive2D->getEmphasisMarkAbove(),
     160           0 :                                 pTextDecoratedPortionPrimitive2D->getEmphasisMarkBelow(),
     161             :                                 pTextDecoratedPortionPrimitive2D->getTextRelief(),
     162           0 :                                 pTextDecoratedPortionPrimitive2D->getShadow()));
     163             :                     }
     164             :                     else
     165             :                     {
     166             :                         // create a SimpleTextPrimitive
     167             :                         rTempResult.push_back(
     168             :                             new TextSimplePortionPrimitive2D(
     169             :                                 aNewTransform,
     170           0 :                                 mrSource.getText(),
     171             :                                 nIndex,
     172             :                                 nLength,
     173             :                                 aNewDXArray,
     174           0 :                                 mrSource.getFontAttribute(),
     175           0 :                                 mrSource.getLocale(),
     176           0 :                                 mrSource.getFontColor()));
     177             :                     }
     178           0 :                 }
     179             :             }
     180           0 :         }
     181             : 
     182           0 :         bool TextBreakupHelper::allowChange(sal_uInt32 /*nCount*/, basegfx::B2DHomMatrix& /*rNewTransform*/, sal_uInt32 /*nIndex*/, sal_uInt32 /*nLength*/)
     183             :         {
     184           0 :             return true;
     185             :         }
     186             : 
     187           0 :         void TextBreakupHelper::breakup(BreakupUnit aBreakupUnit)
     188             :         {
     189           0 :             if(mrSource.getTextLength())
     190             :             {
     191           0 :                 Primitive2DVector aTempResult;
     192           0 :                 static ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > xBreakIterator;
     193             : 
     194           0 :                 if(!xBreakIterator.is())
     195             :                 {
     196           0 :                     ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory());
     197           0 :                     xBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), ::com::sun::star::uno::UNO_QUERY);
     198             :                 }
     199             : 
     200           0 :                 if(xBreakIterator.is())
     201             :                 {
     202           0 :                     const rtl::OUString& rTxt = mrSource.getText();
     203           0 :                     const sal_Int32 nTextLength(mrSource.getTextLength());
     204           0 :                     const ::com::sun::star::lang::Locale& rLocale = mrSource.getLocale();
     205           0 :                     const sal_Int32 nTextPosition(mrSource.getTextPosition());
     206           0 :                     sal_Int32 nCurrent(nTextPosition);
     207             : 
     208           0 :                     switch(aBreakupUnit)
     209             :                     {
     210             :                         case BreakupUnit_character:
     211             :                         {
     212             :                             sal_Int32 nDone;
     213           0 :                             sal_Int32 nNextCellBreak(xBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone));
     214           0 :                             sal_Int32 a(nTextPosition);
     215             : 
     216           0 :                             for(; a < nTextPosition + nTextLength; a++)
     217             :                             {
     218           0 :                                 if(a == nNextCellBreak)
     219             :                                 {
     220           0 :                                     breakupPortion(aTempResult, nCurrent, a - nCurrent, false);
     221           0 :                                     nCurrent = a;
     222           0 :                                     nNextCellBreak = xBreakIterator->nextCharacters(rTxt, a, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
     223             :                                 }
     224             :                             }
     225             : 
     226           0 :                             breakupPortion(aTempResult, nCurrent, a - nCurrent, false);
     227             :                             break;
     228             :                         }
     229             :                         case BreakupUnit_word:
     230             :                         {
     231           0 :                             ::com::sun::star::i18n::Boundary nNextWordBoundary(xBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True));
     232           0 :                             sal_Int32 a(nTextPosition);
     233             : 
     234           0 :                             for(; a < nTextPosition + nTextLength; a++)
     235             :                             {
     236           0 :                                 if(a == nNextWordBoundary.endPos)
     237             :                                 {
     238           0 :                                     if(a > nCurrent)
     239             :                                     {
     240           0 :                                         breakupPortion(aTempResult, nCurrent, a - nCurrent, true);
     241             :                                     }
     242             : 
     243           0 :                                     nCurrent = a;
     244             : 
     245             :                                     // skip spaces (maybe enhanced with a bool later if needed)
     246             :                                     {
     247           0 :                                         const sal_Int32 nEndOfSpaces(xBreakIterator->endOfCharBlock(rTxt, a, rLocale, ::com::sun::star::i18n::CharType::SPACE_SEPARATOR));
     248             : 
     249           0 :                                         if(nEndOfSpaces > a)
     250             :                                         {
     251           0 :                                             nCurrent = nEndOfSpaces;
     252             :                                         }
     253             :                                     }
     254             : 
     255           0 :                                     nNextWordBoundary = xBreakIterator->getWordBoundary(rTxt, a + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True);
     256             :                                 }
     257             :                             }
     258             : 
     259           0 :                             if(a > nCurrent)
     260             :                             {
     261           0 :                                 breakupPortion(aTempResult, nCurrent, a - nCurrent, true);
     262             :                             }
     263             :                             break;
     264             :                         }
     265             :                         case BreakupUnit_sentence:
     266             :                         {
     267           0 :                             sal_Int32 nNextSentenceBreak(xBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale));
     268           0 :                             sal_Int32 a(nTextPosition);
     269             : 
     270           0 :                             for(; a < nTextPosition + nTextLength; a++)
     271             :                             {
     272           0 :                                 if(a == nNextSentenceBreak)
     273             :                                 {
     274           0 :                                     breakupPortion(aTempResult, nCurrent, a - nCurrent, false);
     275           0 :                                     nCurrent = a;
     276           0 :                                     nNextSentenceBreak = xBreakIterator->endOfSentence(rTxt, a + 1, rLocale);
     277             :                                 }
     278             :                             }
     279             : 
     280           0 :                             breakupPortion(aTempResult, nCurrent, a - nCurrent, false);
     281           0 :                             break;
     282             :                         }
     283           0 :                     }
     284             :                 }
     285             : 
     286           0 :                 mxResult = Primitive2DVectorToPrimitive2DSequence(aTempResult);
     287             :             }
     288           0 :         }
     289             : 
     290           0 :         const Primitive2DSequence& TextBreakupHelper::getResult(BreakupUnit aBreakupUnit) const
     291             :         {
     292           0 :             if(!mxResult.hasElements())
     293             :             {
     294           0 :                 const_cast< TextBreakupHelper* >(this)->breakup(aBreakupUnit);
     295             :             }
     296             : 
     297           0 :             return mxResult;
     298             :         }
     299             : 
     300             :     } // end of namespace primitive2d
     301             : } // end of namespace drawinglayer
     302             : 
     303             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10