LCOV - code coverage report
Current view: top level - svtools/source/control - scriptedtext.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1 131 0.8 %
Date: 2014-11-03 Functions: 2 22 9.1 %
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 <svtools/scriptedtext.hxx>
      21             : #include <vector>
      22             : #include <rtl/ustring.hxx>
      23             : #include <vcl/outdev.hxx>
      24             : #include <vcl/font.hxx>
      25             : #include <tools/debug.hxx>
      26             : #include <tools/gen.hxx>
      27             : #include <com/sun/star/i18n/ScriptType.hpp>
      28             : 
      29             : 
      30             : using namespace ::std;
      31             : using namespace ::com::sun::star;
      32             : 
      33             : 
      34             : 
      35             : 
      36             : class SvtScriptedTextHelper_Impl
      37             : {
      38             : private:
      39             :     OutputDevice&               mrOutDevice;        /// The output device for drawing the text.
      40             :     vcl::Font                   maLatinFont;        /// The font for latin text portions.
      41             :     vcl::Font                   maAsianFont;        /// The font for asian text portions.
      42             :     vcl::Font                   maCmplxFont;        /// The font for complex text portions.
      43             :     vcl::Font                   maDefltFont;        /// The default font of the output device.
      44             :     OUString                    maText;             /// The text.
      45             : 
      46             :     vector< sal_Int32 >         maPosVec;           /// The start position of each text portion.
      47             :     vector< sal_Int16 >         maScriptVec;        /// The script type of each text portion.
      48             :     vector< sal_Int32 >         maWidthVec;         /// The output width of each text portion.
      49             :     Size                        maTextSize;         /// The size the text will take in the current output device.
      50             : 
      51             :                                 /** Assignment operator not implemented to prevent usage. */
      52             :     SvtScriptedTextHelper_Impl& operator=( const SvtScriptedTextHelper_Impl& ) SAL_DELETED_FUNCTION;
      53             : 
      54             :                                 /** Gets the font of the given script type. */
      55             :     const vcl::Font&            GetFont( sal_uInt16 _nScript ) const;
      56             :                                 /** Sets a font on the output device depending on the script type. */
      57           0 :     inline void                 SetOutDevFont( sal_uInt16 _nScript )
      58           0 :                                     { mrOutDevice.SetFont( GetFont( _nScript ) ); }
      59             :                                 /** Fills maPosVec with positions of all changes of script type.
      60             :                                     This method expects correctly initialized maPosVec and maScriptVec. */
      61             :     void                        CalculateSizes();
      62             :                                 /** Fills maPosVec with positions of all changes of script type and
      63             :                                     maScriptVec with the script type of each portion. */
      64             :     void                        CalculateBreaks(
      65             :                                     const uno::Reference< i18n::XBreakIterator >& _xBreakIter );
      66             : 
      67             : public:
      68             :                                 /** This constructor sets an output device and fonts for all script types. */
      69             :                                 SvtScriptedTextHelper_Impl(
      70             :                                     OutputDevice& _rOutDevice,
      71             :                                     vcl::Font* _pLatinFont,
      72             :                                     vcl::Font* _pAsianFont,
      73             :                                     vcl::Font* _pCmplxFont );
      74             :                                 /** Copy constructor. */
      75             :                                 SvtScriptedTextHelper_Impl(
      76             :                                     const SvtScriptedTextHelper_Impl& _rCopy );
      77             :                                 /** Destructor. */
      78             :                                 ~SvtScriptedTextHelper_Impl();
      79             : 
      80             :                                 /** Sets new fonts and recalculates the text width. */
      81             :     void                        SetFonts( vcl::Font* _pLatinFont, vcl::Font* _pAsianFont, vcl::Font* _pCmplxFont );
      82             :                                 /** Sets a new text and calculates all script breaks and the text width. */
      83             :     void                        SetText(
      84             :                                     const OUString& _rText,
      85             :                                     const uno::Reference< i18n::XBreakIterator >& _xBreakIter );
      86             : 
      87             :                                 /** Returns a size struct containing the width and height of the text in the current output device. */
      88           0 :     const Size&                 GetTextSize() const { return maTextSize;}
      89             : 
      90             :                                 /** Draws the text in the current output device. */
      91             :     void                        DrawText( const Point& _rPos );
      92             : };
      93             : 
      94             : 
      95           0 : SvtScriptedTextHelper_Impl::SvtScriptedTextHelper_Impl(
      96             :         OutputDevice& _rOutDevice,
      97             :         vcl::Font* _pLatinFont, vcl::Font* _pAsianFont, vcl::Font* _pCmplxFont ) :
      98             :     mrOutDevice( _rOutDevice ),
      99             :     maLatinFont( _pLatinFont ? *_pLatinFont : _rOutDevice.GetFont() ),
     100             :     maAsianFont( _pAsianFont ? *_pAsianFont : _rOutDevice.GetFont() ),
     101             :     maCmplxFont( _pCmplxFont ? *_pCmplxFont : _rOutDevice.GetFont() ),
     102           0 :     maDefltFont( _rOutDevice.GetFont() )
     103             : {
     104           0 : }
     105             : 
     106           0 : SvtScriptedTextHelper_Impl::SvtScriptedTextHelper_Impl( const SvtScriptedTextHelper_Impl& _rCopy ) :
     107             :     mrOutDevice( _rCopy.mrOutDevice ),
     108             :     maLatinFont( _rCopy.maLatinFont ),
     109             :     maAsianFont( _rCopy.maAsianFont ),
     110             :     maCmplxFont( _rCopy.maCmplxFont ),
     111             :     maDefltFont( _rCopy.maDefltFont ),
     112             :     maText( _rCopy.maText ),
     113             :     maPosVec( _rCopy.maPosVec ),
     114             :     maScriptVec( _rCopy.maScriptVec ),
     115             :     maWidthVec( _rCopy.maWidthVec ),
     116           0 :     maTextSize( _rCopy.maTextSize )
     117             : {
     118           0 : }
     119             : 
     120           0 : SvtScriptedTextHelper_Impl::~SvtScriptedTextHelper_Impl()
     121             : {
     122           0 : }
     123             : 
     124           0 : const vcl::Font& SvtScriptedTextHelper_Impl::GetFont( sal_uInt16 _nScript ) const
     125             : {
     126           0 :     switch( _nScript )
     127             :     {
     128           0 :         case i18n::ScriptType::LATIN:       return maLatinFont;
     129           0 :         case i18n::ScriptType::ASIAN:       return maAsianFont;
     130           0 :         case i18n::ScriptType::COMPLEX:     return maCmplxFont;
     131             :     }
     132           0 :     return maDefltFont;
     133             : }
     134             : 
     135           0 : void SvtScriptedTextHelper_Impl::CalculateSizes()
     136             : {
     137           0 :     maTextSize.Width() = maTextSize.Height() = 0;
     138           0 :     maDefltFont = mrOutDevice.GetFont();
     139             : 
     140             :     // calculate text portion widths and total width
     141           0 :     maWidthVec.clear();
     142           0 :     if( !maPosVec.empty() )
     143             :     {
     144             :         DBG_ASSERT( maPosVec.size() - 1 == maScriptVec.size(),
     145             :             "SvtScriptedTextHelper_Impl::CalculateWidth - invalid vectors" );
     146             : 
     147           0 :         sal_Int32 nThisPos = maPosVec[ 0 ];
     148             :         sal_Int32 nNextPos;
     149           0 :         sal_Int32 nPosVecSize = maPosVec.size();
     150           0 :         sal_Int32 nPosVecIndex = 1;
     151             : 
     152             :         sal_Int16 nScript;
     153           0 :         sal_Int32 nScriptVecIndex = 0;
     154             : 
     155             :         sal_Int32 nCurrWidth;
     156             : 
     157           0 :         while( nPosVecIndex < nPosVecSize )
     158             :         {
     159           0 :             nNextPos = maPosVec[ nPosVecIndex++ ];
     160           0 :             nScript = maScriptVec[ nScriptVecIndex++ ];
     161             : 
     162           0 :             SetOutDevFont( nScript );
     163           0 :             nCurrWidth = mrOutDevice.GetTextWidth( maText, nThisPos, nNextPos - nThisPos );
     164           0 :             maWidthVec.push_back( nCurrWidth );
     165           0 :             maTextSize.Width() += nCurrWidth;
     166           0 :             nThisPos = nNextPos;
     167             :         }
     168             :     }
     169             : 
     170             :     // calculate maximum font height
     171           0 :     SetOutDevFont( i18n::ScriptType::LATIN );
     172           0 :     maTextSize.Height() = std::max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
     173           0 :     SetOutDevFont( i18n::ScriptType::ASIAN );
     174           0 :     maTextSize.Height() = std::max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
     175           0 :     SetOutDevFont( i18n::ScriptType::COMPLEX );
     176           0 :     maTextSize.Height() = std::max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
     177             : 
     178           0 :     mrOutDevice.SetFont( maDefltFont );
     179           0 : }
     180             : 
     181           0 : void SvtScriptedTextHelper_Impl::CalculateBreaks( const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
     182             : {
     183           0 :     maPosVec.clear();
     184           0 :     maScriptVec.clear();
     185             : 
     186             :     DBG_ASSERT( _xBreakIter.is(), "SvtScriptedTextHelper_Impl::CalculateBreaks - no break iterator" );
     187             : 
     188           0 :     sal_Int32 nLen = maText.getLength();
     189           0 :     if( nLen )
     190             :     {
     191           0 :         if( _xBreakIter.is() )
     192             :         {
     193           0 :             sal_Int32 nThisPos = 0;         // first position of this portion
     194           0 :             sal_Int32 nNextPos = 0;         // first position of next portion
     195             :             sal_Int16 nPortScript;          // script type of this portion
     196           0 :             do
     197             :             {
     198           0 :                 nPortScript = _xBreakIter->getScriptType( maText, nThisPos );
     199           0 :                 nNextPos = _xBreakIter->endOfScript( maText, nThisPos, nPortScript );
     200             : 
     201           0 :                 switch( nPortScript )
     202             :                 {
     203             :                     case i18n::ScriptType::LATIN:
     204             :                     case i18n::ScriptType::ASIAN:
     205             :                     case i18n::ScriptType::COMPLEX:
     206           0 :                         maPosVec.push_back( nThisPos );
     207           0 :                         maScriptVec.push_back( nPortScript );
     208           0 :                     break;
     209             :                     default:
     210             :                     {
     211             : /* *** handling of weak characters ***
     212             : - first portion is weak: Use OutputDevice::HasGlyphs() to find the correct font
     213             : - weak portion follows another portion: Script type of preceding portion is used */
     214           0 :                         if( maPosVec.empty() )
     215             :                         {
     216           0 :                             sal_Int32 nCharIx = 0;
     217           0 :                             sal_Int32 nNextCharIx = 0;
     218             :                             sal_Int16 nScript;
     219           0 :                             do
     220             :                             {
     221           0 :                                 nScript = i18n::ScriptType::LATIN;
     222           0 :                                 while( (nScript != i18n::ScriptType::WEAK) && (nCharIx == nNextCharIx) )
     223             :                                 {
     224           0 :                                     nNextCharIx = mrOutDevice.HasGlyphs( GetFont( nScript ), maText, nCharIx, nNextPos - nCharIx );
     225           0 :                                     if( nCharIx == nNextCharIx )
     226           0 :                                         ++nScript;
     227             :                                 }
     228           0 :                                 if( nNextCharIx == nCharIx )
     229           0 :                                     ++nNextCharIx;
     230             : 
     231           0 :                                 maPosVec.push_back( nCharIx );
     232           0 :                                 maScriptVec.push_back( nScript );
     233           0 :                                 nCharIx = nNextCharIx;
     234             :                             }
     235           0 :                             while( nCharIx < nNextPos && nCharIx != -1 );
     236             :                         }
     237             :                         // nothing to do for following portions
     238             :                     }
     239             :                 }
     240           0 :                 nThisPos = nNextPos;
     241             :             }
     242           0 :             while( (0 <= nThisPos) && (nThisPos < nLen) );
     243             :         }
     244             :         else            // no break iterator: whole text LATIN
     245             :         {
     246           0 :             maPosVec.push_back( 0 );
     247           0 :             maScriptVec.push_back( i18n::ScriptType::LATIN );
     248             :         }
     249             : 
     250             :         // push end position of last portion
     251           0 :         if( !maPosVec.empty() )
     252           0 :             maPosVec.push_back( nLen );
     253             :     }
     254           0 :     CalculateSizes();
     255           0 : }
     256             : 
     257           0 : void SvtScriptedTextHelper_Impl::SetFonts( vcl::Font* _pLatinFont, vcl::Font* _pAsianFont, vcl::Font* _pCmplxFont )
     258             : {
     259           0 :     maLatinFont = _pLatinFont ? *_pLatinFont : maDefltFont;
     260           0 :     maAsianFont = _pAsianFont ? *_pAsianFont : maDefltFont;
     261           0 :     maCmplxFont = _pCmplxFont ? *_pCmplxFont : maDefltFont;
     262           0 :     CalculateSizes();
     263           0 : }
     264             : 
     265           0 : void SvtScriptedTextHelper_Impl::SetText( const OUString& _rText, const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
     266             : {
     267           0 :     maText = _rText;
     268           0 :     CalculateBreaks( _xBreakIter );
     269           0 : }
     270             : 
     271             : 
     272           0 : void SvtScriptedTextHelper_Impl::DrawText( const Point& _rPos )
     273             : {
     274           0 :     if( maText.isEmpty() || maPosVec.empty() )
     275           0 :         return;
     276             : 
     277             :     DBG_ASSERT( maPosVec.size() - 1 == maScriptVec.size(), "SvtScriptedTextHelper_Impl::DrawText - invalid vectors" );
     278             :     DBG_ASSERT( maScriptVec.size() == maWidthVec.size(), "SvtScriptedTextHelper_Impl::DrawText - invalid vectors" );
     279             : 
     280           0 :     maDefltFont = mrOutDevice.GetFont();
     281           0 :     Point aCurrPos( _rPos );
     282           0 :     sal_Int32 nThisPos = maPosVec[ 0 ];
     283             :     sal_Int32 nNextPos;
     284           0 :     sal_Int32 nPosVecSize = maPosVec.size();
     285           0 :     sal_Int32 nPosVecIndex = 1;
     286             : 
     287             :     sal_Int16 nScript;
     288           0 :     sal_Int32 nVecIndex = 0;
     289             : 
     290           0 :     while( nPosVecIndex < nPosVecSize )
     291             :     {
     292           0 :         nNextPos = maPosVec[ nPosVecIndex++ ];
     293           0 :         nScript = maScriptVec[ nVecIndex ];
     294             : 
     295           0 :         SetOutDevFont( nScript );
     296           0 :         mrOutDevice.DrawText( aCurrPos, maText, nThisPos, nNextPos - nThisPos );
     297           0 :         aCurrPos.X() += maWidthVec[ nVecIndex++ ];
     298           0 :         aCurrPos.X() += mrOutDevice.GetTextHeight() / 5;   // add 20% of font height as portion spacing
     299           0 :         nThisPos = nNextPos;
     300             :     }
     301           0 :     mrOutDevice.SetFont( maDefltFont );
     302             : }
     303             : 
     304             : 
     305             : 
     306             : 
     307           0 : SvtScriptedTextHelper::SvtScriptedTextHelper( OutputDevice& _rOutDevice ) :
     308           0 :     mpImpl( new SvtScriptedTextHelper_Impl( _rOutDevice, NULL, NULL, NULL ) )
     309             : {
     310           0 : }
     311             : 
     312           0 : SvtScriptedTextHelper::SvtScriptedTextHelper( const SvtScriptedTextHelper& _rCopy ) :
     313           0 :     mpImpl( new SvtScriptedTextHelper_Impl( *_rCopy.mpImpl ) )
     314             : {
     315           0 : }
     316             : 
     317           0 : SvtScriptedTextHelper::~SvtScriptedTextHelper()
     318             : {
     319           0 :     delete mpImpl;
     320           0 : }
     321             : 
     322           0 : void SvtScriptedTextHelper::SetFonts( vcl::Font* _pLatinFont, vcl::Font* _pAsianFont, vcl::Font* _pCmplxFont )
     323             : {
     324           0 :     mpImpl->SetFonts( _pLatinFont, _pAsianFont, _pCmplxFont );
     325           0 : }
     326             : 
     327           0 : void SvtScriptedTextHelper::SetDefaultFont()
     328             : {
     329           0 :     mpImpl->SetFonts( NULL, NULL, NULL );
     330           0 : }
     331             : 
     332           0 : void SvtScriptedTextHelper::SetText( const OUString& _rText, const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
     333             : {
     334           0 :     mpImpl->SetText( _rText, _xBreakIter );
     335           0 : }
     336             : 
     337           0 : const Size& SvtScriptedTextHelper::GetTextSize() const
     338             : {
     339           0 :     return mpImpl->GetTextSize();
     340             : }
     341             : 
     342           0 : void SvtScriptedTextHelper::DrawText( const Point& _rPos )
     343             : {
     344           0 :     mpImpl->DrawText( _rPos );
     345        1227 : }
     346             : 
     347             : 
     348             : 
     349             : 
     350             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10