GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / svtools / source / control / scriptedtext.cxx
blob29eab5febe7e157455fe0ccd9bb768e549a6d1d1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
30 using namespace ::std;
31 using namespace ::rtl;
32 using namespace ::com::sun::star;
35 //_____________________________________________________________________________
37 class SvtScriptedTextHelper_Impl
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.
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.
52 /** Assignment operator not implemented to prevent usage. */
53 SvtScriptedTextHelper_Impl& operator=( const SvtScriptedTextHelper_Impl& );
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 inline void SetOutDevFont( sal_uInt16 _nScript )
59 { 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 );
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();
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 );
88 /** Returns a size struct containing the width and height of the text in the current output device. */
89 const Size& GetTextSize() const;
91 /** Draws the text in the current output device. */
92 void DrawText( const Point& _rPos );
96 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 maDefltFont( _rOutDevice.GetFont() )
107 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 maTextSize( _rCopy.maTextSize )
121 SvtScriptedTextHelper_Impl::~SvtScriptedTextHelper_Impl()
125 const Font& SvtScriptedTextHelper_Impl::GetFont( sal_uInt16 _nScript ) const
127 switch( _nScript )
129 case i18n::ScriptType::LATIN: return maLatinFont;
130 case i18n::ScriptType::ASIAN: return maAsianFont;
131 case i18n::ScriptType::COMPLEX: return maCmplxFont;
133 return maDefltFont;
136 void SvtScriptedTextHelper_Impl::CalculateSizes()
138 maTextSize.Width() = maTextSize.Height() = 0;
139 maDefltFont = mrOutDevice.GetFont();
141 // calculate text portion widths and total width
142 maWidthVec.clear();
143 if( !maPosVec.empty() )
145 DBG_ASSERT( maPosVec.size() - 1 == maScriptVec.size(),
146 "SvtScriptedTextHelper_Impl::CalculateWidth - invalid vectors" );
148 sal_Int32 nThisPos = maPosVec[ 0 ];
149 sal_Int32 nNextPos;
150 sal_Int32 nPosVecSize = maPosVec.size();
151 sal_Int32 nPosVecIndex = 1;
153 sal_Int16 nScript;
154 sal_Int32 nScriptVecIndex = 0;
156 sal_Int32 nCurrWidth;
158 while( nPosVecIndex < nPosVecSize )
160 nNextPos = maPosVec[ nPosVecIndex++ ];
161 nScript = maScriptVec[ nScriptVecIndex++ ];
163 SetOutDevFont( nScript );
164 nCurrWidth = mrOutDevice.GetTextWidth( maText, nThisPos, nNextPos - nThisPos );
165 maWidthVec.push_back( nCurrWidth );
166 maTextSize.Width() += nCurrWidth;
167 nThisPos = nNextPos;
171 // calculate maximum font height
172 SetOutDevFont( i18n::ScriptType::LATIN );
173 maTextSize.Height() = std::max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
174 SetOutDevFont( i18n::ScriptType::ASIAN );
175 maTextSize.Height() = std::max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
176 SetOutDevFont( i18n::ScriptType::COMPLEX );
177 maTextSize.Height() = std::max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
179 mrOutDevice.SetFont( maDefltFont );
182 void SvtScriptedTextHelper_Impl::CalculateBreaks( const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
184 maPosVec.clear();
185 maScriptVec.clear();
187 DBG_ASSERT( _xBreakIter.is(), "SvtScriptedTextHelper_Impl::CalculateBreaks - no break iterator" );
189 sal_Int32 nLen = maText.getLength();
190 if( nLen )
192 if( _xBreakIter.is() )
194 sal_Int32 nThisPos = 0; // first position of this portion
195 sal_Int32 nNextPos = 0; // first position of next portion
196 sal_Int16 nPortScript; // script type of this portion
199 nPortScript = _xBreakIter->getScriptType( maText, nThisPos );
200 nNextPos = _xBreakIter->endOfScript( maText, nThisPos, nPortScript );
202 switch( nPortScript )
204 case i18n::ScriptType::LATIN:
205 case i18n::ScriptType::ASIAN:
206 case i18n::ScriptType::COMPLEX:
207 maPosVec.push_back( nThisPos );
208 maScriptVec.push_back( nPortScript );
209 break;
210 default:
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 if( maPosVec.empty() )
217 sal_Int32 nCharIx = 0;
218 sal_Int32 nNextCharIx = 0;
219 sal_Int16 nScript;
222 nScript = i18n::ScriptType::LATIN;
223 while( (nScript != i18n::ScriptType::WEAK) && (nCharIx == nNextCharIx) )
225 nNextCharIx = mrOutDevice.HasGlyphs( GetFont( nScript ), maText, sal::static_int_cast< sal_uInt16 >(nCharIx), sal::static_int_cast< sal_uInt16 >(nNextPos - nCharIx) );
226 if( nCharIx == nNextCharIx )
227 ++nScript;
229 if( nNextCharIx == nCharIx )
230 ++nNextCharIx;
232 maPosVec.push_back( nCharIx );
233 maScriptVec.push_back( nScript );
234 nCharIx = nNextCharIx;
236 while( nCharIx < nNextPos );
238 // nothing to do for following portions
241 nThisPos = nNextPos;
243 while( (0 <= nThisPos) && (nThisPos < nLen) );
245 else // no break iterator: whole text LATIN
247 maPosVec.push_back( 0 );
248 maScriptVec.push_back( i18n::ScriptType::LATIN );
251 // push end position of last portion
252 if( !maPosVec.empty() )
253 maPosVec.push_back( nLen );
255 CalculateSizes();
258 void SvtScriptedTextHelper_Impl::SetFonts( Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont )
260 maLatinFont = _pLatinFont ? *_pLatinFont : maDefltFont;
261 maAsianFont = _pAsianFont ? *_pAsianFont : maDefltFont;
262 maCmplxFont = _pCmplxFont ? *_pCmplxFont : maDefltFont;
263 CalculateSizes();
266 void SvtScriptedTextHelper_Impl::SetText( const OUString& _rText, const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
268 maText = _rText;
269 CalculateBreaks( _xBreakIter );
272 const Size& SvtScriptedTextHelper_Impl::GetTextSize() const
274 return maTextSize;
277 void SvtScriptedTextHelper_Impl::DrawText( const Point& _rPos )
279 if( maText.isEmpty() || maPosVec.empty() )
280 return;
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" );
285 maDefltFont = mrOutDevice.GetFont();
286 Point aCurrPos( _rPos );
287 sal_Int32 nThisPos = maPosVec[ 0 ];
288 sal_Int32 nNextPos;
289 sal_Int32 nPosVecSize = maPosVec.size();
290 sal_Int32 nPosVecIndex = 1;
292 sal_Int16 nScript;
293 sal_Int32 nVecIndex = 0;
295 while( nPosVecIndex < nPosVecSize )
297 nNextPos = maPosVec[ nPosVecIndex++ ];
298 nScript = maScriptVec[ nVecIndex ];
300 SetOutDevFont( nScript );
301 mrOutDevice.DrawText( aCurrPos, maText, nThisPos, nNextPos - nThisPos );
302 aCurrPos.X() += maWidthVec[ nVecIndex++ ];
303 aCurrPos.X() += mrOutDevice.GetTextHeight() / 5; // add 20% of font height as portion spacing
304 nThisPos = nNextPos;
306 mrOutDevice.SetFont( maDefltFont );
310 //_____________________________________________________________________________
312 SvtScriptedTextHelper::SvtScriptedTextHelper( OutputDevice& _rOutDevice ) :
313 mpImpl( new SvtScriptedTextHelper_Impl( _rOutDevice, NULL, NULL, NULL ) )
317 SvtScriptedTextHelper::SvtScriptedTextHelper( const SvtScriptedTextHelper& _rCopy ) :
318 mpImpl( new SvtScriptedTextHelper_Impl( *_rCopy.mpImpl ) )
322 SvtScriptedTextHelper::~SvtScriptedTextHelper()
324 delete mpImpl;
327 void SvtScriptedTextHelper::SetFonts( Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont )
329 mpImpl->SetFonts( _pLatinFont, _pAsianFont, _pCmplxFont );
332 void SvtScriptedTextHelper::SetDefaultFont()
334 mpImpl->SetFonts( NULL, NULL, NULL );
337 void SvtScriptedTextHelper::SetText( const OUString& _rText, const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
339 mpImpl->SetText( _rText, _xBreakIter );
342 const Size& SvtScriptedTextHelper::GetTextSize() const
344 return mpImpl->GetTextSize();
347 void SvtScriptedTextHelper::DrawText( const Point& _rPos )
349 mpImpl->DrawText( _rPos );
353 //_____________________________________________________________________________
355 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */