update dev300-m58
[ooovba.git] / svtools / source / control / scriptedtext.cxx
blob1e7de40ff89e022193181e034b2e578a6dcbf14f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: scriptedtext.cxx,v $
10 * $Revision: 1.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
33 #include "scriptedtext.hxx"
35 #ifndef __SGI_STL_VECTOR
36 #include <vector>
37 #endif
38 #include <rtl/ustring.hxx>
39 #include <vcl/outdev.hxx>
40 #include <vcl/font.hxx>
41 #include <tools/debug.hxx>
42 #include <com/sun/star/i18n/ScriptType.hpp>
45 using namespace ::std;
46 using namespace ::rtl;
47 using namespace ::com::sun::star;
50 //_____________________________________________________________________________
52 class SvtScriptedTextHelper_Impl
54 private:
55 OutputDevice& mrOutDevice; /// The output device for drawing the text.
56 Font maLatinFont; /// The font for latin text portions.
57 Font maAsianFont; /// The font for asian text portions.
58 Font maCmplxFont; /// The font for complex text portions.
59 Font maDefltFont; /// The default font of the output device.
60 OUString maText; /// The text.
62 vector< sal_Int32 > maPosVec; /// The start position of each text portion.
63 vector< sal_Int16 > maScriptVec; /// The script type of each text portion.
64 vector< sal_Int32 > maWidthVec; /// The output width of each text portion.
65 Size maTextSize; /// The size the text will take in the current output device.
67 /** Assignment operator not implemented to prevent usage. */
68 SvtScriptedTextHelper_Impl& operator=( const SvtScriptedTextHelper_Impl& );
70 /** Gets the font of the given script type. */
71 const Font& GetFont( sal_uInt16 _nScript ) const;
72 /** Sets a font on the output device depending on the script type. */
73 inline void SetOutDevFont( sal_uInt16 _nScript )
74 { mrOutDevice.SetFont( GetFont( _nScript ) ); }
75 /** Fills maPosVec with positions of all changes of script type.
76 This method expects correctly initialized maPosVec and maScriptVec. */
77 void CalculateSizes();
78 /** Fills maPosVec with positions of all changes of script type and
79 maScriptVec with the script type of each portion. */
80 void CalculateBreaks(
81 const uno::Reference< i18n::XBreakIterator >& _xBreakIter );
83 public:
84 /** This constructor sets an output device and fonts for all script types. */
85 SvtScriptedTextHelper_Impl(
86 OutputDevice& _rOutDevice,
87 Font* _pLatinFont,
88 Font* _pAsianFont,
89 Font* _pCmplxFont );
90 /** Copy constructor. */
91 SvtScriptedTextHelper_Impl(
92 const SvtScriptedTextHelper_Impl& _rCopy );
93 /** Destructor. */
94 ~SvtScriptedTextHelper_Impl();
96 /** Sets new fonts and recalculates the text width. */
97 void SetFonts( Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont );
98 /** Sets a new text and calculates all script breaks and the text width. */
99 void SetText(
100 const OUString& _rText,
101 const uno::Reference< i18n::XBreakIterator >& _xBreakIter );
103 /** Returns the previously set text. */
104 const OUString& GetText() const;
105 /** Returns a size struct containing the width and height of the text in the current output device. */
106 const Size& GetTextSize() const;
108 /** Draws the text in the current output device. */
109 void DrawText( const Point& _rPos );
113 SvtScriptedTextHelper_Impl::SvtScriptedTextHelper_Impl(
114 OutputDevice& _rOutDevice,
115 Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont ) :
116 mrOutDevice( _rOutDevice ),
117 maLatinFont( _pLatinFont ? *_pLatinFont : _rOutDevice.GetFont() ),
118 maAsianFont( _pAsianFont ? *_pAsianFont : _rOutDevice.GetFont() ),
119 maCmplxFont( _pCmplxFont ? *_pCmplxFont : _rOutDevice.GetFont() ),
120 maDefltFont( _rOutDevice.GetFont() )
124 SvtScriptedTextHelper_Impl::SvtScriptedTextHelper_Impl( const SvtScriptedTextHelper_Impl& _rCopy ) :
125 mrOutDevice( _rCopy.mrOutDevice ),
126 maLatinFont( _rCopy.maLatinFont ),
127 maAsianFont( _rCopy.maAsianFont ),
128 maCmplxFont( _rCopy.maCmplxFont ),
129 maDefltFont( _rCopy.maDefltFont ),
130 maText( _rCopy.maText ),
131 maPosVec( _rCopy.maPosVec ),
132 maScriptVec( _rCopy.maScriptVec ),
133 maWidthVec( _rCopy.maWidthVec ),
134 maTextSize( _rCopy.maTextSize )
138 SvtScriptedTextHelper_Impl::~SvtScriptedTextHelper_Impl()
142 const Font& SvtScriptedTextHelper_Impl::GetFont( sal_uInt16 _nScript ) const
144 switch( _nScript )
146 case i18n::ScriptType::LATIN: return maLatinFont;
147 case i18n::ScriptType::ASIAN: return maAsianFont;
148 case i18n::ScriptType::COMPLEX: return maCmplxFont;
150 return maDefltFont;
153 void SvtScriptedTextHelper_Impl::CalculateSizes()
155 maTextSize.Width() = maTextSize.Height() = 0;
156 maDefltFont = mrOutDevice.GetFont();
158 // calculate text portion widths and total width
159 maWidthVec.clear();
160 if( !maPosVec.empty() )
162 DBG_ASSERT( maPosVec.size() - 1 == maScriptVec.size(),
163 "SvtScriptedTextHelper_Impl::CalculateWidth - invalid vectors" );
165 xub_StrLen nThisPos = static_cast< xub_StrLen >( maPosVec[ 0 ] );
166 xub_StrLen nNextPos;
167 sal_Int32 nPosVecSize = maPosVec.size();
168 sal_Int32 nPosVecIndex = 1;
170 sal_Int16 nScript;
171 sal_Int32 nScriptVecIndex = 0;
173 sal_Int32 nCurrWidth;
175 while( nPosVecIndex < nPosVecSize )
177 nNextPos = static_cast< xub_StrLen >( maPosVec[ nPosVecIndex++ ] );
178 nScript = maScriptVec[ nScriptVecIndex++ ];
180 SetOutDevFont( nScript );
181 nCurrWidth = mrOutDevice.GetTextWidth( maText, nThisPos, nNextPos - nThisPos );
182 maWidthVec.push_back( nCurrWidth );
183 maTextSize.Width() += nCurrWidth;
184 nThisPos = nNextPos;
188 // calculate maximum font height
189 SetOutDevFont( i18n::ScriptType::LATIN );
190 maTextSize.Height() = Max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
191 SetOutDevFont( i18n::ScriptType::ASIAN );
192 maTextSize.Height() = Max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
193 SetOutDevFont( i18n::ScriptType::COMPLEX );
194 maTextSize.Height() = Max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
196 mrOutDevice.SetFont( maDefltFont );
199 void SvtScriptedTextHelper_Impl::CalculateBreaks( const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
201 maPosVec.clear();
202 maScriptVec.clear();
204 DBG_ASSERT( _xBreakIter.is(), "SvtScriptedTextHelper_Impl::CalculateBreaks - no break iterator" );
206 sal_Int32 nLen = maText.getLength();
207 if( nLen )
209 if( _xBreakIter.is() )
211 sal_Int32 nThisPos = 0; // first position of this portion
212 sal_Int32 nNextPos = 0; // first position of next portion
213 sal_Int16 nPortScript; // script type of this portion
216 nPortScript = _xBreakIter->getScriptType( maText, nThisPos );
217 nNextPos = _xBreakIter->endOfScript( maText, nThisPos, nPortScript );
219 switch( nPortScript )
221 case i18n::ScriptType::LATIN:
222 case i18n::ScriptType::ASIAN:
223 case i18n::ScriptType::COMPLEX:
224 maPosVec.push_back( nThisPos );
225 maScriptVec.push_back( nPortScript );
226 break;
227 default:
229 /* *** handling of weak characters ***
230 - first portion is weak: Use OutputDevice::HasGlyphs() to find the correct font
231 - weak portion follows another portion: Script type of preceding portion is used */
232 if( maPosVec.empty() )
234 sal_Int32 nCharIx = 0;
235 sal_Int32 nNextCharIx = 0;
236 sal_Int16 nScript;
239 nScript = i18n::ScriptType::LATIN;
240 while( (nScript != i18n::ScriptType::WEAK) && (nCharIx == nNextCharIx) )
242 nNextCharIx = mrOutDevice.HasGlyphs( GetFont( nScript ), maText, sal::static_int_cast< USHORT >(nCharIx), sal::static_int_cast< USHORT >(nNextPos - nCharIx) );
243 if( nCharIx == nNextCharIx )
244 ++nScript;
246 if( nNextCharIx == nCharIx )
247 ++nNextCharIx;
249 maPosVec.push_back( nCharIx );
250 maScriptVec.push_back( nScript );
251 nCharIx = nNextCharIx;
253 while( nCharIx < nNextPos );
255 // nothing to do for following portions
258 nThisPos = nNextPos;
260 while( (0 <= nThisPos) && (nThisPos < nLen) );
262 else // no break iterator: whole text LATIN
264 maPosVec.push_back( 0 );
265 maScriptVec.push_back( i18n::ScriptType::LATIN );
268 // push end position of last portion
269 if( !maPosVec.empty() )
270 maPosVec.push_back( nLen );
272 CalculateSizes();
275 void SvtScriptedTextHelper_Impl::SetFonts( Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont )
277 maLatinFont = _pLatinFont ? *_pLatinFont : maDefltFont;
278 maAsianFont = _pAsianFont ? *_pAsianFont : maDefltFont;
279 maCmplxFont = _pCmplxFont ? *_pCmplxFont : maDefltFont;
280 CalculateSizes();
283 void SvtScriptedTextHelper_Impl::SetText( const OUString& _rText, const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
285 maText = _rText;
286 CalculateBreaks( _xBreakIter );
289 const OUString& SvtScriptedTextHelper_Impl::GetText() const
291 return maText;
294 const Size& SvtScriptedTextHelper_Impl::GetTextSize() const
296 return maTextSize;
299 void SvtScriptedTextHelper_Impl::DrawText( const Point& _rPos )
301 if( !maText.getLength() || maPosVec.empty() )
302 return;
304 DBG_ASSERT( maPosVec.size() - 1 == maScriptVec.size(), "SvtScriptedTextHelper_Impl::DrawText - invalid vectors" );
305 DBG_ASSERT( maScriptVec.size() == maWidthVec.size(), "SvtScriptedTextHelper_Impl::DrawText - invalid vectors" );
307 maDefltFont = mrOutDevice.GetFont();
308 Point aCurrPos( _rPos );
309 xub_StrLen nThisPos = static_cast< xub_StrLen >( maPosVec[ 0 ] );
310 xub_StrLen nNextPos;
311 sal_Int32 nPosVecSize = maPosVec.size();
312 sal_Int32 nPosVecIndex = 1;
314 sal_Int16 nScript;
315 sal_Int32 nVecIndex = 0;
317 while( nPosVecIndex < nPosVecSize )
319 nNextPos = static_cast< xub_StrLen >( maPosVec[ nPosVecIndex++ ] );
320 nScript = maScriptVec[ nVecIndex ];
322 SetOutDevFont( nScript );
323 mrOutDevice.DrawText( aCurrPos, maText, nThisPos, nNextPos - nThisPos );
324 aCurrPos.X() += maWidthVec[ nVecIndex++ ];
325 aCurrPos.X() += mrOutDevice.GetTextHeight() / 5; // add 20% of font height as portion spacing
326 nThisPos = nNextPos;
328 mrOutDevice.SetFont( maDefltFont );
332 //_____________________________________________________________________________
334 SvtScriptedTextHelper::SvtScriptedTextHelper( OutputDevice& _rOutDevice ) :
335 mpImpl( new SvtScriptedTextHelper_Impl( _rOutDevice, NULL, NULL, NULL ) )
339 SvtScriptedTextHelper::SvtScriptedTextHelper(
340 OutputDevice& _rOutDevice,
341 Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont ) :
342 mpImpl( new SvtScriptedTextHelper_Impl( _rOutDevice, _pLatinFont, _pAsianFont, _pCmplxFont ) )
346 SvtScriptedTextHelper::SvtScriptedTextHelper( const SvtScriptedTextHelper& _rCopy ) :
347 mpImpl( new SvtScriptedTextHelper_Impl( *_rCopy.mpImpl ) )
351 SvtScriptedTextHelper::~SvtScriptedTextHelper()
353 delete mpImpl;
356 void SvtScriptedTextHelper::SetFonts( Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont )
358 mpImpl->SetFonts( _pLatinFont, _pAsianFont, _pCmplxFont );
361 void SvtScriptedTextHelper::SetDefaultFont()
363 mpImpl->SetFonts( NULL, NULL, NULL );
366 void SvtScriptedTextHelper::SetText( const OUString& _rText, const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
368 mpImpl->SetText( _rText, _xBreakIter );
371 const OUString& SvtScriptedTextHelper::GetText() const
373 return mpImpl->GetText();
376 sal_Int32 SvtScriptedTextHelper::GetTextWidth() const
378 return mpImpl->GetTextSize().Width();
381 sal_Int32 SvtScriptedTextHelper::GetTextHeight() const
383 return mpImpl->GetTextSize().Height();
386 const Size& SvtScriptedTextHelper::GetTextSize() const
388 return mpImpl->GetTextSize();
391 void SvtScriptedTextHelper::DrawText( const Point& _rPos )
393 mpImpl->DrawText( _rPos );
397 //_____________________________________________________________________________