LibreOffice Module svtools (master) 1
scriptedtext.cxx
Go to the documentation of this file.
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
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#include <com/sun/star/i18n/XBreakIterator.hpp>
29
30
31using namespace ::com::sun::star;
32
33
35{
36private:
42 OUString maText;
43
44 std::vector< sal_Int32 > maPosVec;
45 std::vector< sal_Int16 > maScriptVec;
46 std::vector< sal_Int32 > maWidthVec;
48
50 const vcl::Font& GetFont( sal_uInt16 _nScript ) const;
52 void SetOutDevFont( sal_uInt16 _nScript )
53 { mrOutDevice.SetFont( GetFont( _nScript ) ); }
56 void CalculateSizes();
59 void CalculateBreaks(
60 const uno::Reference< i18n::XBreakIterator >& _xBreakIter );
61
62public:
65 OutputDevice& _rOutDevice );
66
68 void SetFonts( vcl::Font const * _pLatinFont, vcl::Font const * _pAsianFont, vcl::Font const * _pCmplxFont );
70 void SetText(
71 const OUString& _rText,
72 const uno::Reference< i18n::XBreakIterator >& _xBreakIter );
73
75 const Size& GetTextSize() const { return maTextSize;}
76
78 void DrawText( const Point& _rPos );
79};
80
81
83 OutputDevice& _rOutDevice ) :
84 mrOutDevice( _rOutDevice ),
85 maLatinFont( _rOutDevice.GetFont() ),
86 maAsianFont( _rOutDevice.GetFont() ),
87 maCmplxFont( _rOutDevice.GetFont() ),
88 maDefltFont( _rOutDevice.GetFont() )
89{
90}
91
92const vcl::Font& SvtScriptedTextHelper_Impl::GetFont( sal_uInt16 _nScript ) const
93{
94 switch( _nScript )
95 {
96 case i18n::ScriptType::LATIN: return maLatinFont;
97 case i18n::ScriptType::ASIAN: return maAsianFont;
98 case i18n::ScriptType::COMPLEX: return maCmplxFont;
99 }
100 return maDefltFont;
101}
102
104{
108
109 // calculate text portion widths and total width
110 maWidthVec.clear();
111 if( !maPosVec.empty() )
112 {
113 DBG_ASSERT( maPosVec.size() - 1 == maScriptVec.size(),
114 "SvtScriptedTextHelper_Impl::CalculateWidth - invalid std::vectors" );
115
116 sal_Int32 nThisPos = maPosVec[ 0 ];
117 sal_Int32 nNextPos;
118 sal_Int32 nPosVecSize = maPosVec.size();
119 sal_Int32 nPosVecIndex = 1;
120
121 sal_Int16 nScript;
122 sal_Int32 nScriptVecIndex = 0;
123
124 sal_Int32 nCurrWidth;
125
126 while( nPosVecIndex < nPosVecSize )
127 {
128 nNextPos = maPosVec[ nPosVecIndex++ ];
129 nScript = maScriptVec[ nScriptVecIndex++ ];
130
131 SetOutDevFont( nScript );
132 nCurrWidth = mrOutDevice.GetTextWidth( maText, nThisPos, nNextPos - nThisPos );
133 maWidthVec.push_back( nCurrWidth );
134 maTextSize.AdjustWidth(nCurrWidth );
135 nThisPos = nNextPos;
136 }
137 }
138
139 // calculate maximum font height
140 SetOutDevFont( i18n::ScriptType::LATIN );
142 SetOutDevFont( i18n::ScriptType::ASIAN );
144 SetOutDevFont( i18n::ScriptType::COMPLEX );
146
148}
149
150void SvtScriptedTextHelper_Impl::CalculateBreaks( const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
151{
152 maPosVec.clear();
153 maScriptVec.clear();
154
155 DBG_ASSERT( _xBreakIter.is(), "SvtScriptedTextHelper_Impl::CalculateBreaks - no break iterator" );
156
157 sal_Int32 nLen = maText.getLength();
158 if( nLen )
159 {
160 if( _xBreakIter.is() )
161 {
162 sal_Int32 nThisPos = 0; // first position of this portion
163 sal_Int32 nNextPos = 0; // first position of next portion
164 sal_Int16 nPortScript; // script type of this portion
165 do
166 {
167 nPortScript = _xBreakIter->getScriptType( maText, nThisPos );
168 nNextPos = _xBreakIter->endOfScript( maText, nThisPos, nPortScript );
169
170 switch( nPortScript )
171 {
172 case i18n::ScriptType::LATIN:
173 case i18n::ScriptType::ASIAN:
174 case i18n::ScriptType::COMPLEX:
175 maPosVec.push_back( nThisPos );
176 maScriptVec.push_back( nPortScript );
177 break;
178 default:
179 {
180/* *** handling of weak characters ***
181- first portion is weak: Use OutputDevice::HasGlyphs() to find the correct font
182- weak portion follows another portion: Script type of preceding portion is used */
183 if( maPosVec.empty() )
184 {
185 sal_Int32 nCharIx = 0;
186 sal_Int32 nNextCharIx = 0;
187 sal_Int16 nScript;
188 do
189 {
190 nScript = i18n::ScriptType::LATIN;
191 while( (nScript != i18n::ScriptType::WEAK) && (nCharIx == nNextCharIx) )
192 {
193 nNextCharIx = mrOutDevice.HasGlyphs( GetFont( nScript ), maText, nCharIx, nNextPos - nCharIx );
194 if( nCharIx == nNextCharIx )
195 ++nScript;
196 }
197 if( nNextCharIx == nCharIx )
198 ++nNextCharIx;
199
200 maPosVec.push_back( nCharIx );
201 maScriptVec.push_back( nScript );
202 nCharIx = nNextCharIx;
203 }
204 while( nCharIx < nNextPos && nCharIx != -1 );
205 }
206 // nothing to do for following portions
207 }
208 }
209 nThisPos = nNextPos;
210 }
211 while( (0 <= nThisPos) && (nThisPos < nLen) );
212 }
213 else // no break iterator: whole text LATIN
214 {
215 maPosVec.push_back( 0 );
216 maScriptVec.push_back( i18n::ScriptType::LATIN );
217 }
218
219 // push end position of last portion
220 if( !maPosVec.empty() )
221 maPosVec.push_back( nLen );
222 }
224}
225
226void SvtScriptedTextHelper_Impl::SetFonts( vcl::Font const * _pLatinFont, vcl::Font const * _pAsianFont, vcl::Font const * _pCmplxFont )
227{
228 maLatinFont = _pLatinFont ? *_pLatinFont : maDefltFont;
229 maAsianFont = _pAsianFont ? *_pAsianFont : maDefltFont;
230 maCmplxFont = _pCmplxFont ? *_pCmplxFont : maDefltFont;
232}
233
234void SvtScriptedTextHelper_Impl::SetText( const OUString& _rText, const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
235{
236 maText = _rText;
237 CalculateBreaks( _xBreakIter );
238}
239
240
242{
243 if( maText.isEmpty() || maPosVec.empty() )
244 return;
245
246 DBG_ASSERT( maPosVec.size() - 1 == maScriptVec.size(), "SvtScriptedTextHelper_Impl::DrawText - invalid std::vectors" );
247 DBG_ASSERT( maScriptVec.size() == maWidthVec.size(), "SvtScriptedTextHelper_Impl::DrawText - invalid std::vectors" );
248
250
251 Point aCurrPos( _rPos );
252 sal_Int32 nThisPos = maPosVec[ 0 ];
253 sal_Int32 nNextPos;
254 sal_Int32 nPosVecSize = maPosVec.size();
255 sal_Int32 nPosVecIndex = 1;
256
257 sal_Int16 nScript;
258 sal_Int32 nVecIndex = 0;
259
260 while( nPosVecIndex < nPosVecSize )
261 {
262 nNextPos = maPosVec[ nPosVecIndex++ ];
263 nScript = maScriptVec[ nVecIndex ];
264 vcl::Font aFont = GetFont( nScript );
265 mrOutDevice.SetFont( aFont );
266 if (aFont.GetColor() == COL_AUTO)
268 mrOutDevice.DrawText( aCurrPos, maText, nThisPos, nNextPos - nThisPos );
269 aCurrPos.AdjustX(maWidthVec[ nVecIndex++ ] );
270 aCurrPos.AdjustX(mrOutDevice.GetTextHeight() / 5 ); // add 20% of font height as portion spacing
271 nThisPos = nNextPos;
272 }
273
275}
276
277
279 mpImpl( new SvtScriptedTextHelper_Impl( _rOutDevice ) )
280{
281}
282
284 mpImpl( new SvtScriptedTextHelper_Impl( *_rCopy.mpImpl ) )
285{
286}
287
289{
290}
291
292void SvtScriptedTextHelper::SetFonts( vcl::Font const * _pLatinFont, vcl::Font const * _pAsianFont, vcl::Font const * _pCmplxFont )
293{
294 mpImpl->SetFonts( _pLatinFont, _pAsianFont, _pCmplxFont );
295}
296
298{
299 mpImpl->SetFonts( nullptr, nullptr, nullptr );
300}
301
302void SvtScriptedTextHelper::SetText( const OUString& _rText, const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
303{
304 mpImpl->SetText( _rText, _xBreakIter );
305}
306
308{
309 return mpImpl->GetTextSize();
310}
311
313{
314 mpImpl->DrawText( _rPos );
315}
316
317
318/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsDark() const
void SetFont(const vcl::Font &rNewFont)
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
void SetTextColor(const Color &rColor)
sal_Int32 HasGlyphs(const vcl::Font &rFont, std::u16string_view rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1) const
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
tools::Long GetTextHeight() const
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
const Color & GetFillColor() const
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long Height() const
void setWidth(tools::Long nWidth)
tools::Long AdjustWidth(tools::Long n)
void setHeight(tools::Long nHeight)
vcl::Font maLatinFont
The output device for drawing the text.
void CalculateBreaks(const uno::Reference< i18n::XBreakIterator > &_xBreakIter)
Fills maPosVec with positions of all changes of script type and maScriptVec with the script type of e...
vcl::Font maAsianFont
The font for latin text portions.
Size maTextSize
The output width of each text portion.
std::vector< sal_Int16 > maScriptVec
The start position of each text portion.
vcl::Font maCmplxFont
The font for asian text portions.
std::vector< sal_Int32 > maWidthVec
The script type of each text portion.
const Size & GetTextSize() const
Returns a size struct containing the width and height of the text in the current output device.
OUString maText
The default font of the output device.
SvtScriptedTextHelper_Impl(OutputDevice &_rOutDevice)
This constructor sets an output device and fonts for all script types.
void SetText(const OUString &_rText, const uno::Reference< i18n::XBreakIterator > &_xBreakIter)
Sets a new text and calculates all script breaks and the text width.
const vcl::Font & GetFont(sal_uInt16 _nScript) const
The size the text will take in the current output device.
std::vector< sal_Int32 > maPosVec
The text.
void DrawText(const Point &_rPos)
Draws the text in the current output device.
void SetOutDevFont(sal_uInt16 _nScript)
Sets a font on the output device depending on the script type.
void CalculateSizes()
Fills maPosVec with positions of all changes of script type.
vcl::Font maDefltFont
The font for complex text portions.
void SetFonts(vcl::Font const *_pLatinFont, vcl::Font const *_pAsianFont, vcl::Font const *_pCmplxFont)
Sets new fonts and recalculates the text width.
This class provides drawing text with different script types on any output devices.
void SetDefaultFont()
Sets the default font of the current output device to all script types.
const Size & GetTextSize() const
Returns a size struct containing the width and height of the text in the current output device.
void SetText(const OUString &_rText, const css::uno::Reference< css::i18n::XBreakIterator > &_xBreakIter)
Sets a new text and calculates all script breaks and the text width.
void DrawText(const Point &_rPos)
Draws the text in the current output device.
std::unique_ptr< SvtScriptedTextHelper_Impl > mpImpl
~SvtScriptedTextHelper()
Destructor.
SvtScriptedTextHelper(OutputDevice &_rOutDevice)
Constructor sets an output device and no fonts.
void SetFonts(vcl::Font const *_pLatinFont, vcl::Font const *_pAsianFont, vcl::Font const *_pCmplxFont)
Sets new fonts and recalculates the text width.
const Color & GetColor() const
constexpr ::Color COL_WHITE(0xFF, 0xFF, 0xFF)
constexpr ::Color COL_AUTO(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
#define DBG_ASSERT(sCon, aError)
vcl::Font GetFont(vcl::Font const &rFont, DrawModeFlags nDrawMode, StyleSettings const &rStyleSettings)