LCOV - code coverage report
Current view: top level - libreoffice/svtools/source/control - scriptedtext.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 130 0.0 %
Date: 2012-12-27 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 <com/sun/star/i18n/ScriptType.hpp>
      27             : 
      28             : 
      29             : using namespace ::std;
      30             : using namespace ::rtl;
      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             :     Font                        maLatinFont;        /// The font for latin text portions.
      41             :     Font                        maAsianFont;        /// The font for asian text portions.
      42             :     Font                        maCmplxFont;        /// The font for complex text portions.
      43             :     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& );
      53             : 
      54             :                                 /** Gets the font of the given script type. */
      55             :     const 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             :                                     Font* _pLatinFont,
      72             :                                     Font* _pAsianFont,
      73             :                                     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( Font* _pLatinFont, Font* _pAsianFont, 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             :     const Size&                 GetTextSize() const;
      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             :         Font* _pLatinFont, Font* _pAsianFont, 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 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 :         xub_StrLen nThisPos = static_cast< xub_StrLen >( maPosVec[ 0 ] );
     148             :         xub_StrLen 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 = static_cast< xub_StrLen >( 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() = Max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
     173           0 :     SetOutDevFont( i18n::ScriptType::ASIAN );
     174           0 :     maTextSize.Height() = Max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
     175           0 :     SetOutDevFont( i18n::ScriptType::COMPLEX );
     176           0 :     maTextSize.Height() = 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, sal::static_int_cast< sal_uInt16 >(nCharIx), sal::static_int_cast< sal_uInt16 >(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             :                             while( nCharIx < nNextPos );
     236             :                         }
     237             :                         // nothing to do for following portions
     238             :                     }
     239             :                 }
     240           0 :                 nThisPos = nNextPos;
     241             :             }
     242             :             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( Font* _pLatinFont, Font* _pAsianFont, 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           0 : const Size& SvtScriptedTextHelper_Impl::GetTextSize() const
     272             : {
     273           0 :     return maTextSize;
     274             : }
     275             : 
     276           0 : void SvtScriptedTextHelper_Impl::DrawText( const Point& _rPos )
     277             : {
     278           0 :     if( maText.isEmpty() || maPosVec.empty() )
     279           0 :         return;
     280             : 
     281             :     DBG_ASSERT( maPosVec.size() - 1 == maScriptVec.size(), "SvtScriptedTextHelper_Impl::DrawText - invalid vectors" );
     282             :     DBG_ASSERT( maScriptVec.size() == maWidthVec.size(), "SvtScriptedTextHelper_Impl::DrawText - invalid vectors" );
     283             : 
     284           0 :     maDefltFont = mrOutDevice.GetFont();
     285           0 :     Point aCurrPos( _rPos );
     286           0 :     xub_StrLen nThisPos = static_cast< xub_StrLen >( maPosVec[ 0 ] );
     287             :     xub_StrLen nNextPos;
     288           0 :     sal_Int32 nPosVecSize = maPosVec.size();
     289           0 :     sal_Int32 nPosVecIndex = 1;
     290             : 
     291             :     sal_Int16 nScript;
     292           0 :     sal_Int32 nVecIndex = 0;
     293             : 
     294           0 :     while( nPosVecIndex < nPosVecSize )
     295             :     {
     296           0 :         nNextPos = static_cast< xub_StrLen >( maPosVec[ nPosVecIndex++ ] );
     297           0 :         nScript = maScriptVec[ nVecIndex ];
     298             : 
     299           0 :         SetOutDevFont( nScript );
     300           0 :         mrOutDevice.DrawText( aCurrPos, maText, nThisPos, nNextPos - nThisPos );
     301           0 :         aCurrPos.X() += maWidthVec[ nVecIndex++ ];
     302           0 :         aCurrPos.X() += mrOutDevice.GetTextHeight() / 5;   // add 20% of font height as portion spacing
     303           0 :         nThisPos = nNextPos;
     304             :     }
     305           0 :     mrOutDevice.SetFont( maDefltFont );
     306             : }
     307             : 
     308             : 
     309             : //_____________________________________________________________________________
     310             : 
     311           0 : SvtScriptedTextHelper::SvtScriptedTextHelper( OutputDevice& _rOutDevice ) :
     312           0 :     mpImpl( new SvtScriptedTextHelper_Impl( _rOutDevice, NULL, NULL, NULL ) )
     313             : {
     314           0 : }
     315             : 
     316           0 : SvtScriptedTextHelper::SvtScriptedTextHelper( const SvtScriptedTextHelper& _rCopy ) :
     317           0 :     mpImpl( new SvtScriptedTextHelper_Impl( *_rCopy.mpImpl ) )
     318             : {
     319           0 : }
     320             : 
     321           0 : SvtScriptedTextHelper::~SvtScriptedTextHelper()
     322             : {
     323           0 :     delete mpImpl;
     324           0 : }
     325             : 
     326           0 : void SvtScriptedTextHelper::SetFonts( Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont )
     327             : {
     328           0 :     mpImpl->SetFonts( _pLatinFont, _pAsianFont, _pCmplxFont );
     329           0 : }
     330             : 
     331           0 : void SvtScriptedTextHelper::SetDefaultFont()
     332             : {
     333           0 :     mpImpl->SetFonts( NULL, NULL, NULL );
     334           0 : }
     335             : 
     336           0 : void SvtScriptedTextHelper::SetText( const OUString& _rText, const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
     337             : {
     338           0 :     mpImpl->SetText( _rText, _xBreakIter );
     339           0 : }
     340             : 
     341           0 : const Size& SvtScriptedTextHelper::GetTextSize() const
     342             : {
     343           0 :     return mpImpl->GetTextSize();
     344             : }
     345             : 
     346           0 : void SvtScriptedTextHelper::DrawText( const Point& _rPos )
     347             : {
     348           0 :     mpImpl->DrawText( _rPos );
     349           0 : }
     350             : 
     351             : 
     352             : //_____________________________________________________________________________
     353             : 
     354             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10