1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: scriptedtext.cxx,v $
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
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
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. */
81 const uno::Reference
< i18n::XBreakIterator
>& _xBreakIter
);
84 /** This constructor sets an output device and fonts for all script types. */
85 SvtScriptedTextHelper_Impl(
86 OutputDevice
& _rOutDevice
,
90 /** Copy constructor. */
91 SvtScriptedTextHelper_Impl(
92 const SvtScriptedTextHelper_Impl
& _rCopy
);
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. */
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
146 case i18n::ScriptType::LATIN
: return maLatinFont
;
147 case i18n::ScriptType::ASIAN
: return maAsianFont
;
148 case i18n::ScriptType::COMPLEX
: return maCmplxFont
;
153 void SvtScriptedTextHelper_Impl::CalculateSizes()
155 maTextSize
.Width() = maTextSize
.Height() = 0;
156 maDefltFont
= mrOutDevice
.GetFont();
158 // calculate text portion widths and total width
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 ] );
167 sal_Int32 nPosVecSize
= maPosVec
.size();
168 sal_Int32 nPosVecIndex
= 1;
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
;
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
)
204 DBG_ASSERT( _xBreakIter
.is(), "SvtScriptedTextHelper_Impl::CalculateBreaks - no break iterator" );
206 sal_Int32 nLen
= maText
.getLength();
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
);
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;
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
)
246 if( nNextCharIx
== nCharIx
)
249 maPosVec
.push_back( nCharIx
);
250 maScriptVec
.push_back( nScript
);
251 nCharIx
= nNextCharIx
;
253 while( nCharIx
< nNextPos
);
255 // nothing to do for following portions
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
);
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
;
283 void SvtScriptedTextHelper_Impl::SetText( const OUString
& _rText
, const uno::Reference
< i18n::XBreakIterator
>& _xBreakIter
)
286 CalculateBreaks( _xBreakIter
);
289 const OUString
& SvtScriptedTextHelper_Impl::GetText() const
294 const Size
& SvtScriptedTextHelper_Impl::GetTextSize() const
299 void SvtScriptedTextHelper_Impl::DrawText( const Point
& _rPos
)
301 if( !maText
.getLength() || maPosVec
.empty() )
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 ] );
311 sal_Int32 nPosVecSize
= maPosVec
.size();
312 sal_Int32 nPosVecIndex
= 1;
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
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()
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 //_____________________________________________________________________________