LCOV - code coverage report
Current view: top level - drawinglayer/source/primitive2d - textbreakuphelper.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 110 0.0 %
Date: 2014-04-14 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/BreakIterator.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_Int32 nIndex, sal_Int32 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           0 :                     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_Int32 nIndex2(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::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
     197           0 :                     xBreakIterator = ::com::sun::star::i18n::BreakIterator::create(xContext);
     198             :                 }
     199             : 
     200           0 :                 const OUString& rTxt = mrSource.getText();
     201           0 :                 const sal_Int32 nTextLength(mrSource.getTextLength());
     202           0 :                 const ::com::sun::star::lang::Locale& rLocale = mrSource.getLocale();
     203           0 :                 const sal_Int32 nTextPosition(mrSource.getTextPosition());
     204           0 :                 sal_Int32 nCurrent(nTextPosition);
     205             : 
     206           0 :                 switch(aBreakupUnit)
     207             :                 {
     208             :                     case BreakupUnit_character:
     209             :                     {
     210             :                         sal_Int32 nDone;
     211           0 :                         sal_Int32 nNextCellBreak(xBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone));
     212           0 :                         sal_Int32 a(nTextPosition);
     213             : 
     214           0 :                         for(; a < nTextPosition + nTextLength; a++)
     215             :                         {
     216           0 :                             if(a == nNextCellBreak)
     217             :                             {
     218           0 :                                 breakupPortion(aTempResult, nCurrent, a - nCurrent, false);
     219           0 :                                 nCurrent = a;
     220           0 :                                 nNextCellBreak = xBreakIterator->nextCharacters(rTxt, a, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
     221             :                             }
     222             :                         }
     223             : 
     224           0 :                         breakupPortion(aTempResult, nCurrent, a - nCurrent, false);
     225           0 :                         break;
     226             :                     }
     227             :                     case BreakupUnit_word:
     228             :                     {
     229           0 :                         ::com::sun::star::i18n::Boundary nNextWordBoundary(xBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True));
     230           0 :                         sal_Int32 a(nTextPosition);
     231             : 
     232           0 :                         for(; a < nTextPosition + nTextLength; a++)
     233             :                         {
     234           0 :                             if(a == nNextWordBoundary.endPos)
     235             :                             {
     236           0 :                                 if(a > nCurrent)
     237             :                                 {
     238           0 :                                     breakupPortion(aTempResult, nCurrent, a - nCurrent, true);
     239             :                                 }
     240             : 
     241           0 :                                 nCurrent = a;
     242             : 
     243             :                                 // skip spaces (maybe enhanced with a bool later if needed)
     244             :                                 {
     245           0 :                                     const sal_Int32 nEndOfSpaces(xBreakIterator->endOfCharBlock(rTxt, a, rLocale, ::com::sun::star::i18n::CharType::SPACE_SEPARATOR));
     246             : 
     247           0 :                                     if(nEndOfSpaces > a)
     248             :                                     {
     249           0 :                                         nCurrent = nEndOfSpaces;
     250             :                                     }
     251             :                                 }
     252             : 
     253           0 :                                 nNextWordBoundary = xBreakIterator->getWordBoundary(rTxt, a + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True);
     254             :                             }
     255             :                         }
     256             : 
     257           0 :                         if(a > nCurrent)
     258             :                         {
     259           0 :                             breakupPortion(aTempResult, nCurrent, a - nCurrent, true);
     260             :                         }
     261           0 :                         break;
     262             :                     }
     263             :                     case BreakupUnit_sentence:
     264             :                     {
     265           0 :                         sal_Int32 nNextSentenceBreak(xBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale));
     266           0 :                         sal_Int32 a(nTextPosition);
     267             : 
     268           0 :                         for(; a < nTextPosition + nTextLength; a++)
     269             :                         {
     270           0 :                             if(a == nNextSentenceBreak)
     271             :                             {
     272           0 :                                 breakupPortion(aTempResult, nCurrent, a - nCurrent, false);
     273           0 :                                 nCurrent = a;
     274           0 :                                 nNextSentenceBreak = xBreakIterator->endOfSentence(rTxt, a + 1, rLocale);
     275             :                             }
     276             :                         }
     277             : 
     278           0 :                         breakupPortion(aTempResult, nCurrent, a - nCurrent, false);
     279           0 :                         break;
     280             :                     }
     281             :                 }
     282             : 
     283           0 :                 mxResult = Primitive2DVectorToPrimitive2DSequence(aTempResult);
     284             :             }
     285           0 :         }
     286             : 
     287           0 :         const Primitive2DSequence& TextBreakupHelper::getResult(BreakupUnit aBreakupUnit) const
     288             :         {
     289           0 :             if(!mxResult.hasElements())
     290             :             {
     291           0 :                 const_cast< TextBreakupHelper* >(this)->breakup(aBreakupUnit);
     292             :             }
     293             : 
     294           0 :             return mxResult;
     295             :         }
     296             : 
     297             :     } // end of namespace primitive2d
     298             : } // end of namespace drawinglayer
     299             : 
     300             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10