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

Generated by: LCOV version 1.10