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 <hintids.hxx>
21
22 #include <com/sun/star/i18n/ScriptType.hpp>
23 #include <vcl/outdev.hxx>
24 #include <editeng/brushitem.hxx>
25 #include <editeng/wrlmitem.hxx>
26 #include <editeng/kernitem.hxx>
27 #include <editeng/cmapitem.hxx>
28 #include <editeng/langitem.hxx>
29 #include <editeng/escapementitem.hxx>
30 #include <editeng/autokernitem.hxx>
31 #include <editeng/shdditem.hxx>
32 #include <editeng/charreliefitem.hxx>
33 #include <editeng/contouritem.hxx>
34 #include <editeng/colritem.hxx>
35 #include <editeng/crossedoutitem.hxx>
36 #include <editeng/udlnitem.hxx>
37 #include <editeng/wghtitem.hxx>
38 #include <editeng/postitem.hxx>
39 #include <editeng/fhgtitem.hxx>
40 #include <editeng/fontitem.hxx>
41 #include <editeng/emphasismarkitem.hxx>
42 #include <editeng/charscaleitem.hxx>
43 #include <editeng/charrotateitem.hxx>
44 #include <editeng/twolinesitem.hxx>
45 #include <editeng/charhiddenitem.hxx>
46 #include <editeng/boxitem.hxx>
47 #include <editeng/shaditem.hxx>
48 #include <IDocumentSettingAccess.hxx>
49 #include <charatr.hxx>
50 #include <viewsh.hxx>
51 #include <swfont.hxx>
52 #include <fntcache.hxx>
53 #include <txtfrm.hxx>
54 #include <scriptinfo.hxx>
55
56 #ifdef DBG_UTIL
57 // global Variable
58 SvStatistics g_SvStat;
59 #endif
60
61 using namespace ::com::sun::star;
62
63 // set background brush, depending on character formatting
SetBackColor(std::optional<Color> xNewColor)64 void SwFont::SetBackColor( std::optional<Color> xNewColor )
65 {
66 mxBackColor = xNewColor;
67 m_bFontChg = true;
68 m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
69 }
70
SetTopBorder(const editeng::SvxBorderLine * pTopBorder)71 void SwFont::SetTopBorder( const editeng::SvxBorderLine* pTopBorder )
72 {
73 if( pTopBorder )
74 m_aTopBorder = *pTopBorder;
75 else
76 {
77 m_aTopBorder.reset();
78 m_nTopBorderDist = 0;
79 }
80 m_bFontChg = true;
81 m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
82 }
83
SetBottomBorder(const editeng::SvxBorderLine * pBottomBorder)84 void SwFont::SetBottomBorder( const editeng::SvxBorderLine* pBottomBorder )
85 {
86 if( pBottomBorder )
87 m_aBottomBorder = *pBottomBorder;
88 else
89 {
90 m_aBottomBorder.reset();
91 m_nBottomBorderDist = 0;
92 }
93 m_bFontChg = true;
94 m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
95 }
96
SetRightBorder(const editeng::SvxBorderLine * pRightBorder)97 void SwFont::SetRightBorder( const editeng::SvxBorderLine* pRightBorder )
98 {
99 if( pRightBorder )
100 m_aRightBorder = *pRightBorder;
101 else
102 {
103 m_aRightBorder.reset();
104 m_nRightBorderDist = 0;
105 }
106 m_bFontChg = true;
107 m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
108 }
109
SetLeftBorder(const editeng::SvxBorderLine * pLeftBorder)110 void SwFont::SetLeftBorder( const editeng::SvxBorderLine* pLeftBorder )
111 {
112 if( pLeftBorder )
113 m_aLeftBorder = *pLeftBorder;
114 else
115 {
116 m_aLeftBorder.reset();
117 m_nLeftBorderDist = 0;
118 }
119 m_bFontChg = true;
120 m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
121 }
122
123 const std::optional<editeng::SvxBorderLine>&
GetAbsTopBorder(const bool bVertLayout,const bool bVertLayoutLRBT) const124 SwFont::GetAbsTopBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const
125 {
126 switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
127 {
128 case 0 :
129 return m_aTopBorder;
130 case 900 :
131 return m_aRightBorder;
132 case 1800 :
133 return m_aBottomBorder;
134 case 2700 :
135 return m_aLeftBorder;
136 default :
137 assert(false);
138 return m_aTopBorder;
139 }
140 }
141
142 const std::optional<editeng::SvxBorderLine>&
GetAbsBottomBorder(const bool bVertLayout,const bool bVertLayoutLRBT) const143 SwFont::GetAbsBottomBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const
144 {
145 switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
146 {
147 case 0 :
148 return m_aBottomBorder;
149 case 900 :
150 return m_aLeftBorder;
151 case 1800 :
152 return m_aTopBorder;
153 case 2700 :
154 return m_aRightBorder;
155 default :
156 assert(false);
157 return m_aBottomBorder;
158 }
159 }
160
161 const std::optional<editeng::SvxBorderLine>&
GetAbsLeftBorder(const bool bVertLayout,const bool bVertLayoutLRBT) const162 SwFont::GetAbsLeftBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const
163 {
164 switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
165 {
166 case 0 :
167 return m_aLeftBorder;
168 case 900 :
169 return m_aTopBorder;
170 case 1800 :
171 return m_aRightBorder;
172 case 2700 :
173 return m_aBottomBorder;
174 default :
175 assert(false);
176 return m_aLeftBorder;
177 }
178 }
179
180 const std::optional<editeng::SvxBorderLine>&
GetAbsRightBorder(const bool bVertLayout,const bool bVertLayoutLRBT) const181 SwFont::GetAbsRightBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const
182 {
183 switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
184 {
185 case 0 :
186 return m_aRightBorder;
187 case 900 :
188 return m_aBottomBorder;
189 case 1800 :
190 return m_aLeftBorder;
191 case 2700 :
192 return m_aTopBorder;
193 default :
194 assert(false);
195 return m_aRightBorder;
196 }
197 }
198
GetAbsShadowLocation(const bool bVertLayout,const bool bVertLayoutLRBT) const199 SvxShadowLocation SwFont::GetAbsShadowLocation(const bool bVertLayout,
200 const bool bVertLayoutLRBT) const
201 {
202 SvxShadowLocation aLocation = SvxShadowLocation::NONE;
203 switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
204 {
205 case 0:
206 aLocation = m_aShadowLocation;
207 break;
208
209 case 900:
210 switch ( m_aShadowLocation )
211 {
212 case SvxShadowLocation::TopLeft:
213 aLocation = SvxShadowLocation::BottomLeft;
214 break;
215 case SvxShadowLocation::TopRight:
216 aLocation = SvxShadowLocation::TopLeft;
217 break;
218 case SvxShadowLocation::BottomLeft:
219 aLocation = SvxShadowLocation::BottomRight;
220 break;
221 case SvxShadowLocation::BottomRight:
222 aLocation = SvxShadowLocation::TopRight;
223 break;
224 case SvxShadowLocation::NONE:
225 case SvxShadowLocation::End:
226 aLocation = m_aShadowLocation;
227 break;
228 }
229 break;
230
231 case 1800:
232 switch ( m_aShadowLocation )
233 {
234 case SvxShadowLocation::TopLeft:
235 aLocation = SvxShadowLocation::BottomRight;
236 break;
237 case SvxShadowLocation::TopRight:
238 aLocation = SvxShadowLocation::BottomLeft;
239 break;
240 case SvxShadowLocation::BottomLeft:
241 aLocation = SvxShadowLocation::TopRight;
242 break;
243 case SvxShadowLocation::BottomRight:
244 aLocation = SvxShadowLocation::TopLeft;
245 break;
246 case SvxShadowLocation::NONE:
247 case SvxShadowLocation::End:
248 aLocation = m_aShadowLocation;
249 break;
250 }
251 break;
252
253 case 2700:
254 switch ( m_aShadowLocation )
255 {
256 case SvxShadowLocation::TopLeft:
257 aLocation = SvxShadowLocation::TopRight;
258 break;
259 case SvxShadowLocation::TopRight:
260 aLocation = SvxShadowLocation::BottomRight;
261 break;
262 case SvxShadowLocation::BottomLeft:
263 aLocation = SvxShadowLocation::TopLeft;
264 break;
265 case SvxShadowLocation::BottomRight:
266 aLocation = SvxShadowLocation::BottomLeft;
267 break;
268 case SvxShadowLocation::NONE:
269 case SvxShadowLocation::End:
270 aLocation = m_aShadowLocation;
271 break;
272 }
273 break;
274
275 default:
276 assert(false);
277 break;
278 }
279 return aLocation;
280 }
281
CalcShadowSpace(const SvxShadowItemSide nShadow,const bool bVertLayout,const bool bVertLayoutLRBT,const bool bSkipLeft,const bool bSkipRight) const282 sal_uInt16 SwFont::CalcShadowSpace(const SvxShadowItemSide nShadow, const bool bVertLayout,
283 const bool bVertLayoutLRBT, const bool bSkipLeft,
284 const bool bSkipRight) const
285 {
286 sal_uInt16 nSpace = 0;
287 const Degree10 nOrient = GetOrientation(bVertLayout, bVertLayoutLRBT);
288 const SvxShadowLocation aLoc = GetAbsShadowLocation(bVertLayout, bVertLayoutLRBT);
289 switch( nShadow )
290 {
291 case SvxShadowItemSide::TOP:
292 if(( aLoc == SvxShadowLocation::TopLeft ||
293 aLoc == SvxShadowLocation::TopRight ) &&
294 ( nOrient == 0_deg10 || nOrient == 1800_deg10 ||
295 ( nOrient == 900_deg10 && !bSkipRight ) ||
296 ( nOrient == 2700_deg10 && !bSkipLeft )))
297 {
298 nSpace = m_nShadowWidth;
299 }
300 break;
301
302 case SvxShadowItemSide::BOTTOM:
303 if(( aLoc == SvxShadowLocation::BottomLeft ||
304 aLoc == SvxShadowLocation::BottomRight ) &&
305 ( nOrient == 0_deg10 || nOrient == 1800_deg10 ||
306 ( nOrient == 900_deg10 && !bSkipLeft ) ||
307 ( nOrient == 2700_deg10 && !bSkipRight )))
308 {
309 nSpace = m_nShadowWidth;
310 }
311 break;
312
313 case SvxShadowItemSide::LEFT:
314 if(( aLoc == SvxShadowLocation::TopLeft ||
315 aLoc == SvxShadowLocation::BottomLeft ) &&
316 ( nOrient == 900_deg10 || nOrient == 2700_deg10 ||
317 ( nOrient == 0_deg10 && !bSkipLeft ) ||
318 ( nOrient == 1800_deg10 && !bSkipRight )))
319 {
320 nSpace = m_nShadowWidth;
321 }
322 break;
323
324 case SvxShadowItemSide::RIGHT:
325 if(( aLoc == SvxShadowLocation::TopRight ||
326 aLoc == SvxShadowLocation::BottomRight ) &&
327 ( nOrient == 900_deg10 || nOrient == 2700_deg10 ||
328 ( nOrient == 0_deg10 && !bSkipRight ) ||
329 ( nOrient == 1800_deg10 && !bSkipLeft )))
330 {
331 nSpace = m_nShadowWidth;
332 }
333 break;
334 default:
335 assert(false);
336 break;
337 }
338
339 return nSpace;
340 }
341
342 // maps directions for vertical layout
MapDirection(Degree10 nDir,const bool bVertFormat,const bool bVertFormatLRBT)343 static Degree10 MapDirection(Degree10 nDir, const bool bVertFormat, const bool bVertFormatLRBT)
344 {
345 if ( bVertFormat )
346 {
347 switch ( nDir.get() )
348 {
349 case 0 :
350 if (bVertFormatLRBT)
351 nDir = 900_deg10;
352 else
353 nDir = 2700_deg10;
354 break;
355 case 900 :
356 nDir = 0_deg10;
357 break;
358 case 2700 :
359 nDir = 1800_deg10;
360 break;
361 #if OSL_DEBUG_LEVEL > 0
362 default :
363 OSL_FAIL( "Unsupported direction" );
364 break;
365 #endif
366 }
367 }
368 return nDir;
369 }
370
371 // maps the absolute direction set at the font to its logical counterpart
372 // in the rotated environment
UnMapDirection(Degree10 nDir,const bool bVertFormat,const bool bVertFormatLRBT)373 Degree10 UnMapDirection(Degree10 nDir, const bool bVertFormat, const bool bVertFormatLRBT)
374 {
375 if (bVertFormatLRBT)
376 {
377 switch (nDir.get())
378 {
379 case 900:
380 nDir = 0_deg10;
381 break;
382 default:
383 SAL_WARN("sw.core", "unsupported direction for VertLRBT");
384 break;
385 }
386 return nDir;
387 }
388
389 if ( bVertFormat )
390 {
391 switch ( nDir.get() )
392 {
393 case 0 :
394 nDir = 900_deg10;
395 break;
396 case 1800 :
397 nDir = 2700_deg10;
398 break;
399 case 2700 :
400 nDir = 0_deg10;
401 break;
402 #if OSL_DEBUG_LEVEL > 0
403 default :
404 OSL_FAIL( "Unsupported direction" );
405 break;
406 #endif
407 }
408 }
409 return nDir;
410 }
411
GetOrientation(const bool bVertFormat,const bool bVertFormatLRBT) const412 Degree10 SwFont::GetOrientation(const bool bVertFormat, const bool bVertFormatLRBT) const
413 {
414 return UnMapDirection(m_aSub[m_nActual].GetOrientation(), bVertFormat, bVertFormatLRBT);
415 }
416
SetVertical(Degree10 nDir,const bool bVertFormat,const bool bVertLayoutLRBT)417 void SwFont::SetVertical(Degree10 nDir, const bool bVertFormat, const bool bVertLayoutLRBT)
418 {
419 // map direction if frame has vertical layout
420 nDir = MapDirection(nDir, bVertFormat, bVertLayoutLRBT);
421
422 if( nDir != m_aSub[SwFontScript::Latin].GetOrientation() )
423 {
424 m_bFontChg = true;
425 bool bVertical = bVertFormat && !bVertLayoutLRBT;
426 m_aSub[SwFontScript::Latin].SetVertical(nDir, bVertical);
427 m_aSub[SwFontScript::CJK].SetVertical(nDir, bVertical);
428 m_aSub[SwFontScript::CTL].SetVertical(nDir, bVertical);
429 }
430 }
431
432 /*
433 Escapement:
434 frEsc: Fraction, ratio of Escapements
435 Esc = resulting Escapement
436 A1 = original Ascent (nOrgAscent)
437 A2 = shrunk Ascent (nEscAscent)
438 Ax = resulting Ascent (GetAscent())
439 H1 = original Height (nOrgHeight)
440 H2 = shrunk Height (nEscHeight)
441 Hx = resulting Height (GetHeight())
442 Bx = resulting Baseline for Text (CalcPos())
443 (Attention: Y - A1!)
444
445 Escapement:
446 Esc = H1 * frEsc;
447
448 Superscript:
449 Ax = A2 + Esc;
450 Hx = H2 + Esc;
451 Bx = A1 - Esc;
452
453 Subscript:
454 Ax = A1;
455 Hx = A1 + Esc + (H2 - A2);
456 Bx = A1 + Esc;
457 */
458
459 // nEsc is the percentage
CalcEscAscent(const sal_uInt16 nOldAscent) const460 sal_uInt16 SwSubFont::CalcEscAscent( const sal_uInt16 nOldAscent ) const
461 {
462 if( DFLT_ESC_AUTO_SUPER != GetEscapement() &&
463 DFLT_ESC_AUTO_SUB != GetEscapement() )
464 {
465 const tools::Long nAscent = nOldAscent +
466 ( static_cast<tools::Long>(m_nOrgHeight) * GetEscapement() ) / 100;
467 if ( nAscent>0 )
468 return std::max<sal_uInt16>( nAscent, m_nOrgAscent );
469 }
470 return m_nOrgAscent;
471 }
472
SetDiffFnt(const SfxItemSet * pAttrSet,const IDocumentSettingAccess * pIDocumentSettingAccess)473 void SwFont::SetDiffFnt( const SfxItemSet *pAttrSet,
474 const IDocumentSettingAccess *pIDocumentSettingAccess )
475 {
476 mxBackColor.reset();
477
478 if( pAttrSet )
479 {
480 const SfxPoolItem* pItem;
481 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_FONT,
482 true, &pItem ))
483 {
484 const SvxFontItem *pFont = static_cast<const SvxFontItem *>(pItem);
485 m_aSub[SwFontScript::Latin].SetFamily( pFont->GetFamily() );
486 m_aSub[SwFontScript::Latin].Font::SetFamilyName( pFont->GetFamilyName() );
487 m_aSub[SwFontScript::Latin].Font::SetStyleName( pFont->GetStyleName() );
488 m_aSub[SwFontScript::Latin].Font::SetPitch( pFont->GetPitch() );
489 m_aSub[SwFontScript::Latin].Font::SetCharSet( pFont->GetCharSet() );
490 }
491 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_FONTSIZE,
492 true, &pItem ))
493 {
494 const SvxFontHeightItem *pHeight = static_cast<const SvxFontHeightItem *>(pItem);
495 m_aSub[SwFontScript::Latin].SvxFont::SetPropr( 100 );
496 m_aSub[SwFontScript::Latin].m_aSize = m_aSub[SwFontScript::Latin].Font::GetFontSize();
497 Size aTmpSize = m_aSub[SwFontScript::Latin].m_aSize;
498 aTmpSize.setHeight( pHeight->GetHeight() );
499 m_aSub[SwFontScript::Latin].SetSize( aTmpSize );
500 }
501 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_POSTURE,
502 true, &pItem ))
503 m_aSub[SwFontScript::Latin].Font::SetItalic( static_cast<const SvxPostureItem*>(pItem)->GetPosture() );
504 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_WEIGHT,
505 true, &pItem ))
506 m_aSub[SwFontScript::Latin].Font::SetWeight( static_cast<const SvxWeightItem*>(pItem)->GetWeight() );
507 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_LANGUAGE,
508 true, &pItem ))
509 m_aSub[SwFontScript::Latin].SetLanguage( static_cast<const SvxLanguageItem*>(pItem)->GetLanguage() );
510
511 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_FONT,
512 true, &pItem ))
513 {
514 const SvxFontItem *pFont = static_cast<const SvxFontItem *>(pItem);
515 m_aSub[SwFontScript::CJK].SetFamily( pFont->GetFamily() );
516 m_aSub[SwFontScript::CJK].Font::SetFamilyName( pFont->GetFamilyName() );
517 m_aSub[SwFontScript::CJK].Font::SetStyleName( pFont->GetStyleName() );
518 m_aSub[SwFontScript::CJK].Font::SetPitch( pFont->GetPitch() );
519 m_aSub[SwFontScript::CJK].Font::SetCharSet( pFont->GetCharSet() );
520 }
521 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_FONTSIZE,
522 true, &pItem ))
523 {
524 const SvxFontHeightItem *pHeight = static_cast<const SvxFontHeightItem *>(pItem);
525 m_aSub[SwFontScript::CJK].SvxFont::SetPropr( 100 );
526 m_aSub[SwFontScript::CJK].m_aSize = m_aSub[SwFontScript::CJK].Font::GetFontSize();
527 Size aTmpSize = m_aSub[SwFontScript::CJK].m_aSize;
528 aTmpSize.setHeight( pHeight->GetHeight() );
529 m_aSub[SwFontScript::CJK].SetSize( aTmpSize );
530 }
531 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_POSTURE,
532 true, &pItem ))
533 m_aSub[SwFontScript::CJK].Font::SetItalic( static_cast<const SvxPostureItem*>(pItem)->GetPosture() );
534 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_WEIGHT,
535 true, &pItem ))
536 m_aSub[SwFontScript::CJK].Font::SetWeight( static_cast<const SvxWeightItem*>(pItem)->GetWeight() );
537 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_LANGUAGE,
538 true, &pItem ))
539 {
540 LanguageType eNewLang = static_cast<const SvxLanguageItem*>(pItem)->GetLanguage();
541 m_aSub[SwFontScript::CJK].SetLanguage( eNewLang );
542 m_aSub[SwFontScript::Latin].SetCJKContextLanguage( eNewLang );
543 m_aSub[SwFontScript::CJK].SetCJKContextLanguage( eNewLang );
544 m_aSub[SwFontScript::CTL].SetCJKContextLanguage( eNewLang );
545 }
546
547 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CTL_FONT,
548 true, &pItem ))
549 {
550 const SvxFontItem *pFont = static_cast<const SvxFontItem *>(pItem);
551 m_aSub[SwFontScript::CTL].SetFamily( pFont->GetFamily() );
552 m_aSub[SwFontScript::CTL].Font::SetFamilyName( pFont->GetFamilyName() );
553 m_aSub[SwFontScript::CTL].Font::SetStyleName( pFont->GetStyleName() );
554 m_aSub[SwFontScript::CTL].Font::SetPitch( pFont->GetPitch() );
555 m_aSub[SwFontScript::CTL].Font::SetCharSet( pFont->GetCharSet() );
556 }
557 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CTL_FONTSIZE,
558 true, &pItem ))
559 {
560 const SvxFontHeightItem *pHeight = static_cast<const SvxFontHeightItem *>(pItem);
561 m_aSub[SwFontScript::CTL].SvxFont::SetPropr( 100 );
562 m_aSub[SwFontScript::CTL].m_aSize = m_aSub[SwFontScript::CTL].Font::GetFontSize();
563 Size aTmpSize = m_aSub[SwFontScript::CTL].m_aSize;
564 aTmpSize.setHeight( pHeight->GetHeight() );
565 m_aSub[SwFontScript::CTL].SetSize( aTmpSize );
566 }
567 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CTL_POSTURE,
568 true, &pItem ))
569 m_aSub[SwFontScript::CTL].Font::SetItalic( static_cast<const SvxPostureItem*>(pItem)->GetPosture() );
570 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CTL_WEIGHT,
571 true, &pItem ))
572 m_aSub[SwFontScript::CTL].Font::SetWeight( static_cast<const SvxWeightItem*>(pItem)->GetWeight() );
573 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CTL_LANGUAGE,
574 true, &pItem ))
575 m_aSub[SwFontScript::CTL].SetLanguage( static_cast<const SvxLanguageItem*>(pItem)->GetLanguage() );
576
577 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_UNDERLINE,
578 true, &pItem ))
579 {
580 SetUnderline( static_cast<const SvxUnderlineItem*>(pItem)->GetLineStyle() );
581 SetUnderColor( static_cast<const SvxUnderlineItem*>(pItem)->GetColor() );
582 }
583 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_OVERLINE,
584 true, &pItem ))
585 {
586 SetOverline( static_cast<const SvxOverlineItem*>(pItem)->GetLineStyle() );
587 SetOverColor( static_cast<const SvxOverlineItem*>(pItem)->GetColor() );
588 }
589 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CROSSEDOUT,
590 true, &pItem ))
591 SetStrikeout( static_cast<const SvxCrossedOutItem*>(pItem)->GetStrikeout() );
592 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_COLOR,
593 true, &pItem ))
594 SetColor( static_cast<const SvxColorItem*>(pItem)->GetValue() );
595 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_EMPHASIS_MARK,
596 true, &pItem ))
597 SetEmphasisMark( static_cast<const SvxEmphasisMarkItem*>(pItem)->GetEmphasisMark() );
598
599 SetTransparent( true );
600 SetAlign( ALIGN_BASELINE );
601 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CONTOUR,
602 true, &pItem ))
603 SetOutline( static_cast<const SvxContourItem*>(pItem)->GetValue() );
604 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_SHADOWED,
605 true, &pItem ))
606 SetShadow( static_cast<const SvxShadowedItem*>(pItem)->GetValue() );
607 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_RELIEF,
608 true, &pItem ))
609 SetRelief( static_cast<const SvxCharReliefItem*>(pItem)->GetValue() );
610 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_SHADOWED,
611 true, &pItem ))
612 SetPropWidth(static_cast<const SvxShadowedItem*>(pItem)->GetValue() ? 50 : 100 );
613 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_AUTOKERN,
614 true, &pItem ))
615 {
616 if( static_cast<const SvxAutoKernItem*>(pItem)->GetValue() )
617 {
618 SetAutoKern( ( !pIDocumentSettingAccess ||
619 !pIDocumentSettingAccess->get(DocumentSettingId::KERN_ASIAN_PUNCTUATION) ) ?
620 FontKerning::FontSpecific :
621 FontKerning::Asian );
622 }
623 else
624 SetAutoKern( FontKerning::NONE );
625 }
626 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_WORDLINEMODE,
627 true, &pItem ))
628 SetWordLineMode( static_cast<const SvxWordLineModeItem*>(pItem)->GetValue() );
629
630 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_ESCAPEMENT,
631 true, &pItem ))
632 {
633 const SvxEscapementItem *pEsc = static_cast<const SvxEscapementItem *>(pItem);
634 SetEscapement( pEsc->GetEsc() );
635 if( m_aSub[SwFontScript::Latin].IsEsc() )
636 SetProportion( pEsc->GetProportionalHeight() );
637 }
638 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CASEMAP,
639 true, &pItem ))
640 SetCaseMap( static_cast<const SvxCaseMapItem*>(pItem)->GetCaseMap() );
641 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_KERNING,
642 true, &pItem ))
643 SetFixKerning( static_cast<const SvxKerningItem*>(pItem)->GetValue() );
644 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_ROTATE,
645 true, &pItem ))
646 SetVertical( static_cast<const SvxCharRotateItem*>(pItem)->GetValue() );
647 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_BACKGROUND,
648 true, &pItem ))
649 mxBackColor = static_cast<const SvxBrushItem*>(pItem)->GetColor();
650 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_HIGHLIGHT,
651 true, &pItem ))
652 SetHighlightColor(static_cast<const SvxBrushItem*>(pItem)->GetColor());
653 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_BOX,
654 true, &pItem ))
655 {
656 const SvxBoxItem* pBoxItem = static_cast<const SvxBoxItem*>(pItem);
657 SetTopBorder(pBoxItem->GetTop());
658 SetBottomBorder(pBoxItem->GetBottom());
659 SetRightBorder(pBoxItem->GetRight());
660 SetLeftBorder(pBoxItem->GetLeft());
661 SetTopBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::TOP));
662 SetBottomBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::BOTTOM));
663 SetRightBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::RIGHT));
664 SetLeftBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::LEFT));
665 }
666 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_SHADOW,
667 true, &pItem ))
668 {
669 const SvxShadowItem* pShadowItem = static_cast<const SvxShadowItem*>(pItem);
670 SetShadowColor(pShadowItem->GetColor());
671 SetShadowWidth(pShadowItem->GetWidth());
672 SetShadowLocation(pShadowItem->GetLocation());
673 }
674 const SfxPoolItem* pTwoLinesItem = nullptr;
675 if( SfxItemState::SET ==
676 pAttrSet->GetItemState( RES_CHRATR_TWO_LINES, true, &pTwoLinesItem ))
677 if ( static_cast<const SvxTwoLinesItem*>(pTwoLinesItem)->GetValue() )
678 SetVertical( 0_deg10 );
679 }
680 else
681 {
682 Invalidate();
683 }
684 m_bPaintBlank = false;
685 OSL_ENSURE( m_aSub[SwFontScript::Latin].IsTransparent(), "SwFont: Transparent revolution" );
686 }
687
SwFont(const SwFont & rFont)688 SwFont::SwFont( const SwFont &rFont )
689 : m_aSub(rFont.m_aSub)
690 {
691 m_nActual = rFont.m_nActual;
692 mxBackColor = rFont.mxBackColor;
693 m_aHighlightColor = rFont.m_aHighlightColor;
694 m_aTopBorder = rFont.m_aTopBorder;
695 m_aBottomBorder = rFont.m_aBottomBorder;
696 m_aRightBorder = rFont.m_aRightBorder;
697 m_aLeftBorder = rFont.m_aLeftBorder;
698 m_nTopBorderDist = rFont.m_nTopBorderDist;
699 m_nBottomBorderDist = rFont.m_nBottomBorderDist;
700 m_nRightBorderDist = rFont.m_nRightBorderDist;
701 m_nLeftBorderDist = rFont.m_nLeftBorderDist;
702 m_aShadowColor = rFont.m_aShadowColor;
703 m_nShadowWidth = rFont.m_nShadowWidth;
704 m_aShadowLocation = rFont.m_aShadowLocation;
705 m_aUnderColor = rFont.GetUnderColor();
706 m_aOverColor = rFont.GetOverColor();
707 m_nToxCount = 0;
708 m_nRefCount = 0;
709 m_nMetaCount = 0;
710 m_nInputFieldCount = 0;
711 m_bFontChg = rFont.m_bFontChg;
712 m_bOrgChg = rFont.m_bOrgChg;
713 m_bPaintBlank = rFont.m_bPaintBlank;
714 m_bGreyWave = rFont.m_bGreyWave;
715 }
716
SwFont(const SwAttrSet * pAttrSet,const IDocumentSettingAccess * pIDocumentSettingAccess)717 SwFont::SwFont( const SwAttrSet* pAttrSet,
718 const IDocumentSettingAccess* pIDocumentSettingAccess )
719 : m_aSub()
720 {
721 m_nActual = SwFontScript::Latin;
722 m_nToxCount = 0;
723 m_nRefCount = 0;
724 m_nMetaCount = 0;
725 m_nInputFieldCount = 0;
726 m_bPaintBlank = false;
727 m_bGreyWave = false;
728 m_bOrgChg = true;
729 {
730 const SvxFontItem& rFont = pAttrSet->GetFont();
731 m_aSub[SwFontScript::Latin].SetFamily( rFont.GetFamily() );
732 m_aSub[SwFontScript::Latin].SetFamilyName( rFont.GetFamilyName() );
733 m_aSub[SwFontScript::Latin].SetStyleName( rFont.GetStyleName() );
734 m_aSub[SwFontScript::Latin].SetPitch( rFont.GetPitch() );
735 m_aSub[SwFontScript::Latin].SetCharSet( rFont.GetCharSet() );
736 m_aSub[SwFontScript::Latin].SvxFont::SetPropr( 100 ); // 100% of FontSize
737 Size aTmpSize = m_aSub[SwFontScript::Latin].m_aSize;
738 aTmpSize.setHeight( pAttrSet->GetSize().GetHeight() );
739 m_aSub[SwFontScript::Latin].SetSize( aTmpSize );
740 m_aSub[SwFontScript::Latin].SetItalic( pAttrSet->GetPosture().GetPosture() );
741 m_aSub[SwFontScript::Latin].SetWeight( pAttrSet->GetWeight().GetWeight() );
742 m_aSub[SwFontScript::Latin].SetLanguage( pAttrSet->GetLanguage().GetLanguage() );
743 }
744
745 {
746 const SvxFontItem& rFont = pAttrSet->GetCJKFont();
747 m_aSub[SwFontScript::CJK].SetFamily( rFont.GetFamily() );
748 m_aSub[SwFontScript::CJK].SetFamilyName( rFont.GetFamilyName() );
749 m_aSub[SwFontScript::CJK].SetStyleName( rFont.GetStyleName() );
750 m_aSub[SwFontScript::CJK].SetPitch( rFont.GetPitch() );
751 m_aSub[SwFontScript::CJK].SetCharSet( rFont.GetCharSet() );
752 m_aSub[SwFontScript::CJK].SvxFont::SetPropr( 100 ); // 100% of FontSize
753 Size aTmpSize = m_aSub[SwFontScript::CJK].m_aSize;
754 aTmpSize.setHeight( pAttrSet->GetCJKSize().GetHeight() );
755 m_aSub[SwFontScript::CJK].SetSize( aTmpSize );
756 m_aSub[SwFontScript::CJK].SetItalic( pAttrSet->GetCJKPosture().GetPosture() );
757 m_aSub[SwFontScript::CJK].SetWeight( pAttrSet->GetCJKWeight().GetWeight() );
758 LanguageType eNewLang = pAttrSet->GetCJKLanguage().GetLanguage();
759 m_aSub[SwFontScript::CJK].SetLanguage( eNewLang );
760 m_aSub[SwFontScript::Latin].SetCJKContextLanguage( eNewLang );
761 m_aSub[SwFontScript::CJK].SetCJKContextLanguage( eNewLang );
762 m_aSub[SwFontScript::CTL].SetCJKContextLanguage( eNewLang );
763 }
764
765 {
766 const SvxFontItem& rFont = pAttrSet->GetCTLFont();
767 m_aSub[SwFontScript::CTL].SetFamily( rFont.GetFamily() );
768 m_aSub[SwFontScript::CTL].SetFamilyName( rFont.GetFamilyName() );
769 m_aSub[SwFontScript::CTL].SetStyleName( rFont.GetStyleName() );
770 m_aSub[SwFontScript::CTL].SetPitch( rFont.GetPitch() );
771 m_aSub[SwFontScript::CTL].SetCharSet( rFont.GetCharSet() );
772 m_aSub[SwFontScript::CTL].SvxFont::SetPropr( 100 ); // 100% of FontSize
773 Size aTmpSize = m_aSub[SwFontScript::CTL].m_aSize;
774 aTmpSize.setHeight( pAttrSet->GetCTLSize().GetHeight() );
775 m_aSub[SwFontScript::CTL].SetSize( aTmpSize );
776 m_aSub[SwFontScript::CTL].SetItalic( pAttrSet->GetCTLPosture().GetPosture() );
777 m_aSub[SwFontScript::CTL].SetWeight( pAttrSet->GetCTLWeight().GetWeight() );
778 m_aSub[SwFontScript::CTL].SetLanguage( pAttrSet->GetCTLLanguage().GetLanguage() );
779 }
780 if ( pAttrSet->GetCharHidden().GetValue() )
781 SetUnderline( LINESTYLE_DOTTED );
782 else
783 SetUnderline( pAttrSet->GetUnderline().GetLineStyle() );
784 SetUnderColor( pAttrSet->GetUnderline().GetColor() );
785 SetOverline( pAttrSet->GetOverline().GetLineStyle() );
786 SetOverColor( pAttrSet->GetOverline().GetColor() );
787 SetEmphasisMark( pAttrSet->GetEmphasisMark().GetEmphasisMark() );
788 SetStrikeout( pAttrSet->GetCrossedOut().GetStrikeout() );
789 SetColor( pAttrSet->GetColor().GetValue() );
790 SetTransparent( true );
791 SetAlign( ALIGN_BASELINE );
792 SetOutline( pAttrSet->GetContour().GetValue() );
793 SetShadow( pAttrSet->GetShadowed().GetValue() );
794 SetPropWidth( pAttrSet->GetCharScaleW().GetValue() );
795 SetRelief( pAttrSet->GetCharRelief().GetValue() );
796 if( pAttrSet->GetAutoKern().GetValue() )
797 {
798 SetAutoKern( ( !pIDocumentSettingAccess ||
799 !pIDocumentSettingAccess->get(DocumentSettingId::KERN_ASIAN_PUNCTUATION) ) ?
800 FontKerning::FontSpecific :
801 FontKerning::Asian );
802 }
803 else
804 SetAutoKern( FontKerning::NONE );
805 SetWordLineMode( pAttrSet->GetWordLineMode().GetValue() );
806 const SvxEscapementItem &rEsc = pAttrSet->GetEscapement();
807 SetEscapement( rEsc.GetEsc() );
808 if( m_aSub[SwFontScript::Latin].IsEsc() )
809 SetProportion( rEsc.GetProportionalHeight() );
810 SetCaseMap( pAttrSet->GetCaseMap().GetCaseMap() );
811 SetFixKerning( pAttrSet->GetKerning().GetValue() );
812 const SfxPoolItem* pItem;
813 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_BACKGROUND,
814 true, &pItem ))
815 mxBackColor = static_cast<const SvxBrushItem*>(pItem)->GetColor();
816 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_HIGHLIGHT,
817 true, &pItem ))
818 SetHighlightColor(static_cast<const SvxBrushItem*>(pItem)->GetColor());
819 else
820 SetHighlightColor(COL_TRANSPARENT);
821 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_BOX,
822 true, &pItem ))
823 {
824 const SvxBoxItem* pBoxItem = static_cast<const SvxBoxItem*>(pItem);
825 SetTopBorder(pBoxItem->GetTop());
826 SetBottomBorder(pBoxItem->GetBottom());
827 SetRightBorder(pBoxItem->GetRight());
828 SetLeftBorder(pBoxItem->GetLeft());
829 SetTopBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::TOP));
830 SetBottomBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::BOTTOM));
831 SetRightBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::RIGHT));
832 SetLeftBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::LEFT));
833 }
834 else
835 {
836 SetTopBorder(nullptr);
837 SetBottomBorder(nullptr);
838 SetRightBorder(nullptr);
839 SetLeftBorder(nullptr);
840 SetTopBorderDist(0);
841 SetBottomBorderDist(0);
842 SetRightBorderDist(0);
843 SetLeftBorderDist(0);
844 }
845
846 if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_SHADOW,
847 true, &pItem ))
848 {
849 const SvxShadowItem* pShadowItem = static_cast<const SvxShadowItem*>(pItem);
850 SetShadowColor(pShadowItem->GetColor());
851 SetShadowWidth(pShadowItem->GetWidth());
852 SetShadowLocation(pShadowItem->GetLocation());
853 }
854 else
855 {
856 SetShadowColor(COL_TRANSPARENT);
857 SetShadowWidth(0);
858 SetShadowLocation(SvxShadowLocation::NONE);
859 }
860
861 const SvxTwoLinesItem& rTwoLinesItem = pAttrSet->Get2Lines();
862 if ( ! rTwoLinesItem.GetValue() )
863 SetVertical( pAttrSet->GetCharRotate().GetValue() );
864 else
865 SetVertical( 0_deg10 );
866 if( pIDocumentSettingAccess && pIDocumentSettingAccess->get( DocumentSettingId::SMALL_CAPS_PERCENTAGE_66 ))
867 {
868 m_aSub[ SwFontScript::Latin ].m_bSmallCapsPercentage66 = true;
869 m_aSub[ SwFontScript::CJK ].m_bSmallCapsPercentage66 = true;
870 m_aSub[ SwFontScript::CTL ].m_bSmallCapsPercentage66 = true;
871 }
872 }
873
~SwFont()874 SwFont::~SwFont()
875 {
876 }
877
operator =(const SwFont & rFont)878 SwFont& SwFont::operator=( const SwFont &rFont )
879 {
880 if (this != &rFont)
881 {
882 m_aSub[SwFontScript::Latin] = rFont.m_aSub[SwFontScript::Latin];
883 m_aSub[SwFontScript::CJK] = rFont.m_aSub[SwFontScript::CJK];
884 m_aSub[SwFontScript::CTL] = rFont.m_aSub[SwFontScript::CTL];
885 m_nActual = rFont.m_nActual;
886 mxBackColor = rFont.mxBackColor;
887 m_aHighlightColor = rFont.m_aHighlightColor;
888 m_aTopBorder = rFont.m_aTopBorder;
889 m_aBottomBorder = rFont.m_aBottomBorder;
890 m_aRightBorder = rFont.m_aRightBorder;
891 m_aLeftBorder = rFont.m_aLeftBorder;
892 m_nTopBorderDist = rFont.m_nTopBorderDist;
893 m_nBottomBorderDist = rFont.m_nBottomBorderDist;
894 m_nRightBorderDist = rFont.m_nRightBorderDist;
895 m_nLeftBorderDist = rFont.m_nLeftBorderDist;
896 m_aShadowColor = rFont.m_aShadowColor;
897 m_nShadowWidth = rFont.m_nShadowWidth;
898 m_aShadowLocation = rFont.m_aShadowLocation;
899 m_aUnderColor = rFont.GetUnderColor();
900 m_aOverColor = rFont.GetOverColor();
901 m_nToxCount = 0;
902 m_nRefCount = 0;
903 m_nMetaCount = 0;
904 m_nInputFieldCount = 0;
905 m_bFontChg = rFont.m_bFontChg;
906 m_bOrgChg = rFont.m_bOrgChg;
907 m_bPaintBlank = rFont.m_bPaintBlank;
908 m_bGreyWave = rFont.m_bGreyWave;
909 }
910 return *this;
911 }
912
AllocFontCacheId(SwViewShell const * pSh,SwFontScript nWhich)913 void SwFont::AllocFontCacheId( SwViewShell const *pSh, SwFontScript nWhich )
914 {
915 SwFntAccess aFntAccess( m_aSub[nWhich].m_nFontCacheId, m_aSub[nWhich].m_nFontIndex,
916 &m_aSub[nWhich], pSh, true );
917 }
918
IsSymbol(SwViewShell const * pSh)919 bool SwSubFont::IsSymbol( SwViewShell const *pSh )
920 {
921 SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh, false );
922 return aFntAccess.Get()->IsSymbol();
923 }
924
ChgFnt(SwViewShell const * pSh,OutputDevice & rOut)925 bool SwSubFont::ChgFnt( SwViewShell const *pSh, OutputDevice& rOut )
926 {
927 if ( pLastFont )
928 pLastFont->Unlock();
929 SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh, true );
930 SV_STAT( nChangeFont );
931
932 pLastFont = aFntAccess.Get();
933
934 pLastFont->SetDevFont( pSh, rOut );
935
936 pLastFont->Lock();
937 return LINESTYLE_NONE != GetUnderline() ||
938 LINESTYLE_NONE != GetOverline() ||
939 STRIKEOUT_NONE != GetStrikeout();
940 }
941
ChgPhysFnt(SwViewShell const * pSh,OutputDevice & rOut)942 void SwFont::ChgPhysFnt( SwViewShell const *pSh, OutputDevice& rOut )
943 {
944 if( m_bOrgChg && m_aSub[m_nActual].IsEsc() )
945 {
946 const sal_uInt8 nOldProp = m_aSub[m_nActual].GetPropr();
947 SetProportion( 100 );
948 ChgFnt( pSh, rOut );
949 SwFntAccess aFntAccess( m_aSub[m_nActual].m_nFontCacheId, m_aSub[m_nActual].m_nFontIndex,
950 &m_aSub[m_nActual], pSh );
951 m_aSub[m_nActual].m_nOrgHeight = aFntAccess.Get()->GetFontHeight( pSh, rOut );
952 m_aSub[m_nActual].m_nOrgAscent = aFntAccess.Get()->GetFontAscent( pSh, rOut );
953 SetProportion( nOldProp );
954 m_bOrgChg = false;
955 }
956
957 if( m_bFontChg )
958 {
959 ChgFnt( pSh, rOut );
960 m_bFontChg = m_bOrgChg;
961 }
962 if( rOut.GetTextLineColor() != m_aUnderColor )
963 rOut.SetTextLineColor( m_aUnderColor );
964 if( rOut.GetOverlineColor() != m_aOverColor )
965 rOut.SetOverlineColor( m_aOverColor );
966 }
967
968 // Height = MaxAscent + MaxDescent
969 // MaxAscent = Max (T1_ascent, T2_ascent + (Esc * T1_height) );
970 // MaxDescent = Max (T1_height-T1_ascent,
971 // T2_height-T2_ascent - (Esc * T1_height)
CalcEscHeight(const sal_uInt16 nOldHeight,const sal_uInt16 nOldAscent) const972 sal_uInt16 SwSubFont::CalcEscHeight( const sal_uInt16 nOldHeight,
973 const sal_uInt16 nOldAscent ) const
974 {
975 if( DFLT_ESC_AUTO_SUPER != GetEscapement() &&
976 DFLT_ESC_AUTO_SUB != GetEscapement() )
977 {
978 tools::Long nDescent = nOldHeight - nOldAscent -
979 ( static_cast<tools::Long>(m_nOrgHeight) * GetEscapement() ) / 100;
980 const sal_uInt16 nDesc = nDescent>0
981 ? std::max<sal_uInt16>( nDescent, m_nOrgHeight - m_nOrgAscent)
982 : m_nOrgHeight - m_nOrgAscent;
983 return ( nDesc + CalcEscAscent( nOldAscent ) );
984 }
985 return m_nOrgHeight;
986 }
987
CheckKerning_()988 short SwSubFont::CheckKerning_( )
989 {
990 short nKernx = - short( Font::GetFontSize().Height() / 6 );
991
992 if ( nKernx < GetFixKerning() )
993 return GetFixKerning();
994 return nKernx;
995 }
996
GetAscent(SwViewShell const * pSh,const OutputDevice & rOut)997 sal_uInt16 SwSubFont::GetAscent( SwViewShell const *pSh, const OutputDevice& rOut )
998 {
999 SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh );
1000 const sal_uInt16 nAscent = aFntAccess.Get()->GetFontAscent( pSh, rOut );
1001 return GetEscapement() ? CalcEscAscent( nAscent ) : nAscent;
1002 }
1003
GetHeight(SwViewShell const * pSh,const OutputDevice & rOut)1004 sal_uInt16 SwSubFont::GetHeight( SwViewShell const *pSh, const OutputDevice& rOut )
1005 {
1006 SV_STAT( nGetTextSize );
1007 SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh );
1008 const sal_uInt16 nHeight = aFntAccess.Get()->GetFontHeight( pSh, rOut );
1009 if ( GetEscapement() )
1010 {
1011 const sal_uInt16 nAscent = aFntAccess.Get()->GetFontAscent( pSh, rOut );
1012 return CalcEscHeight( nHeight, nAscent ); // + nLeading;
1013 }
1014 return nHeight; // + nLeading;
1015 }
1016
GetTextSize_(SwDrawTextInfo & rInf)1017 Size SwSubFont::GetTextSize_( SwDrawTextInfo& rInf )
1018 {
1019 // Robust: the font is supposed to be set already, but better safe than
1020 // sorry...
1021 if ( !pLastFont || pLastFont->GetOwner() != reinterpret_cast<const void*>(m_nFontCacheId) ||
1022 !IsSameInstance( rInf.GetpOut()->GetFont() ) )
1023 ChgFnt( rInf.GetShell(), rInf.GetOut() );
1024
1025 SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
1026
1027 Size aTextSize;
1028 TextFrameIndex const nLn = rInf.GetLen() == TextFrameIndex(COMPLETE_STRING)
1029 ? TextFrameIndex(rInf.GetText().getLength())
1030 : rInf.GetLen();
1031 rInf.SetLen( nLn );
1032 if( IsCapital() && nLn )
1033 aTextSize = GetCapitalSize( rInf );
1034 else
1035 {
1036 SV_STAT( nGetTextSize );
1037 tools::Long nOldKern = rInf.GetKern();
1038 const OUString oldText = rInf.GetText();
1039 rInf.SetKern( CheckKerning() );
1040 if ( !IsCaseMap() )
1041 aTextSize = pLastFont->GetTextSize( rInf );
1042 else
1043 {
1044 const OUString aTmp = CalcCaseMap( rInf.GetText() );
1045 const OUString oldStr = rInf.GetText();
1046 bool bCaseMapLengthDiffers(aTmp.getLength() != oldStr.getLength());
1047
1048 if(bCaseMapLengthDiffers && rInf.GetLen())
1049 {
1050 // If the length of the original string and the CaseMapped one
1051 // are different, it is necessary to handle the given text part as
1052 // a single snippet since its size may differ, too.
1053 TextFrameIndex const nOldIdx(rInf.GetIdx());
1054 TextFrameIndex const nOldLen(rInf.GetLen());
1055 const OUString aSnippet(oldStr.copy(sal_Int32(nOldIdx), sal_Int32(nOldLen)));
1056 const OUString aNewText(CalcCaseMap(aSnippet));
1057
1058 rInf.SetText( aNewText );
1059 rInf.SetIdx( TextFrameIndex(0) );
1060 rInf.SetLen( TextFrameIndex(aNewText.getLength()) );
1061
1062 aTextSize = pLastFont->GetTextSize( rInf );
1063
1064 rInf.SetIdx( nOldIdx );
1065 rInf.SetLen( nOldLen );
1066 }
1067 else
1068 {
1069 rInf.SetText( aTmp );
1070 aTextSize = pLastFont->GetTextSize( rInf );
1071 }
1072
1073 rInf.SetText(oldStr);
1074 }
1075 rInf.SetKern( nOldKern );
1076 rInf.SetText(oldText);
1077 // A word that's longer than one line, with escapement at the line
1078 // break, must report its effective height.
1079 if( GetEscapement() )
1080 {
1081 const sal_uInt16 nAscent = pLastFont->GetFontAscent( rInf.GetShell(),
1082 rInf.GetOut() );
1083 aTextSize.setHeight(
1084 static_cast<tools::Long>(CalcEscHeight( o3tl::narrowing<sal_uInt16>(aTextSize.Height()), nAscent)) );
1085 }
1086 }
1087
1088 if (TextFrameIndex(1) == rInf.GetLen()
1089 && CH_TXT_ATR_FIELDSTART == rInf.GetText()[sal_Int32(rInf.GetIdx())])
1090 {
1091 assert(!"this is presumably dead code");
1092 TextFrameIndex const nOldIdx(rInf.GetIdx());
1093 TextFrameIndex const nOldLen(rInf.GetLen());
1094 const OUString aNewText(CH_TXT_ATR_SUBST_FIELDSTART);
1095 rInf.SetText( aNewText );
1096 rInf.SetIdx( TextFrameIndex(0) );
1097 rInf.SetLen( TextFrameIndex(aNewText.getLength()) );
1098 aTextSize = pLastFont->GetTextSize( rInf );
1099 rInf.SetIdx( nOldIdx );
1100 rInf.SetLen( nOldLen );
1101 }
1102 else if (TextFrameIndex(1) == rInf.GetLen()
1103 && CH_TXT_ATR_FIELDEND == rInf.GetText()[sal_Int32(rInf.GetIdx())])
1104 {
1105 assert(!"this is presumably dead code");
1106 TextFrameIndex const nOldIdx(rInf.GetIdx());
1107 TextFrameIndex const nOldLen(rInf.GetLen());
1108 const OUString aNewText(CH_TXT_ATR_SUBST_FIELDEND);
1109 rInf.SetText( aNewText );
1110 rInf.SetIdx( TextFrameIndex(0) );
1111 rInf.SetLen( TextFrameIndex(aNewText.getLength()) );
1112 aTextSize = pLastFont->GetTextSize( rInf );
1113 rInf.SetIdx( nOldIdx );
1114 rInf.SetLen( nOldLen );
1115 }
1116
1117 return aTextSize;
1118 }
1119
DrawText_(SwDrawTextInfo & rInf,const bool bGrey)1120 void SwSubFont::DrawText_( SwDrawTextInfo &rInf, const bool bGrey )
1121 {
1122 rInf.SetGreyWave( bGrey );
1123 TextFrameIndex const nLn(rInf.GetText().getLength());
1124 if( !rInf.GetLen() || !nLn )
1125 return;
1126 if (TextFrameIndex(COMPLETE_STRING) == rInf.GetLen())
1127 rInf.SetLen( nLn );
1128
1129 FontLineStyle nOldUnder = LINESTYLE_NONE;
1130 SwUnderlineFont* pUnderFnt = nullptr;
1131
1132 if( rInf.GetUnderFnt() )
1133 {
1134 nOldUnder = GetUnderline();
1135 SetUnderline( LINESTYLE_NONE );
1136 pUnderFnt = rInf.GetUnderFnt();
1137 }
1138
1139 if( !pLastFont || pLastFont->GetOwner() != reinterpret_cast<const void*>(m_nFontCacheId) )
1140 ChgFnt( rInf.GetShell(), rInf.GetOut() );
1141
1142 SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
1143
1144 const Point aOldPos(rInf.GetPos());
1145 Point aPos( rInf.GetPos() );
1146
1147 if( GetEscapement() )
1148 CalcEsc( rInf, aPos );
1149
1150 rInf.SetPos( aPos );
1151 rInf.SetKern( CheckKerning() + rInf.GetSperren() / SPACING_PRECISION_FACTOR );
1152
1153 if( IsCapital() )
1154 DrawCapital( rInf );
1155 else
1156 {
1157 SV_STAT( nDrawText );
1158 if ( !IsCaseMap() )
1159 pLastFont->DrawText( rInf );
1160 else
1161 {
1162 const OUString oldStr = rInf.GetText();
1163 const OUString aString( CalcCaseMap(oldStr) );
1164 bool bCaseMapLengthDiffers(aString.getLength() != oldStr.getLength());
1165
1166 if(bCaseMapLengthDiffers && rInf.GetLen())
1167 {
1168 // If the length of the original string and the CaseMapped one
1169 // are different, it is necessary to handle the given text part as
1170 // a single snippet since its size may differ, too.
1171 TextFrameIndex const nOldIdx(rInf.GetIdx());
1172 TextFrameIndex const nOldLen(rInf.GetLen());
1173 const OUString aSnippet(oldStr.copy(sal_Int32(nOldIdx), sal_Int32(nOldLen)));
1174 const OUString aNewText = CalcCaseMap(aSnippet);
1175
1176 rInf.SetText( aNewText );
1177 rInf.SetIdx( TextFrameIndex(0) );
1178 rInf.SetLen( TextFrameIndex(aNewText.getLength()) );
1179
1180 pLastFont->DrawText( rInf );
1181
1182 rInf.SetIdx( nOldIdx );
1183 rInf.SetLen( nOldLen );
1184 }
1185 else
1186 {
1187 rInf.SetText( aString );
1188 pLastFont->DrawText( rInf );
1189 }
1190
1191 rInf.SetText(oldStr);
1192 }
1193 }
1194
1195 if( pUnderFnt && nOldUnder != LINESTYLE_NONE )
1196 {
1197 Size aFontSize = GetTextSize_( rInf );
1198 const OUString oldStr = rInf.GetText();
1199
1200 TextFrameIndex const nOldIdx = rInf.GetIdx();
1201 TextFrameIndex const nOldLen = rInf.GetLen();
1202 tools::Long nSpace = 0;
1203 if( rInf.GetSpace() )
1204 {
1205 TextFrameIndex nTmpEnd = nOldIdx + nOldLen;
1206 if (nTmpEnd > TextFrameIndex(oldStr.getLength()))
1207 nTmpEnd = TextFrameIndex(oldStr.getLength());
1208
1209 const SwScriptInfo* pSI = rInf.GetScriptInfo();
1210
1211 const bool bAsianFont =
1212 ( rInf.GetFont() && SwFontScript::CJK == rInf.GetFont()->GetActual() );
1213 for (TextFrameIndex nTmp = nOldIdx; nTmp < nTmpEnd; ++nTmp)
1214 {
1215 if (CH_BLANK == oldStr[sal_Int32(nTmp)] || bAsianFont ||
1216 (nTmp + TextFrameIndex(1) < TextFrameIndex(oldStr.getLength())
1217 && pSI
1218 && i18n::ScriptType::ASIAN == pSI->ScriptType(nTmp + TextFrameIndex(1))))
1219 {
1220 ++nSpace;
1221 }
1222 }
1223
1224 // if next portion if a hole portion we do not consider any
1225 // extra space added because the last character was ASIAN
1226 if ( nSpace && rInf.IsSpaceStop() && bAsianFont )
1227 --nSpace;
1228
1229 nSpace *= rInf.GetSpace() / SPACING_PRECISION_FACTOR;
1230 }
1231
1232 rInf.SetWidth( sal_uInt16(aFontSize.Width() + nSpace) );
1233 rInf.SetText( " " );
1234 rInf.SetIdx( TextFrameIndex(0) );
1235 rInf.SetLen( TextFrameIndex(2) );
1236 SetUnderline( nOldUnder );
1237 rInf.SetUnderFnt( nullptr );
1238
1239 // set position for underline font
1240 rInf.SetPos( pUnderFnt->GetPos() );
1241
1242 pUnderFnt->GetFont().DrawStretchText_( rInf );
1243
1244 rInf.SetUnderFnt( pUnderFnt );
1245 rInf.SetText(oldStr);
1246 rInf.SetIdx( nOldIdx );
1247 rInf.SetLen( nOldLen );
1248 }
1249
1250 rInf.SetPos(aOldPos);
1251 }
1252
DrawStretchText_(SwDrawTextInfo & rInf)1253 void SwSubFont::DrawStretchText_( SwDrawTextInfo &rInf )
1254 {
1255 if( !rInf.GetLen() || !rInf.GetText().getLength() )
1256 return;
1257
1258 FontLineStyle nOldUnder = LINESTYLE_NONE;
1259 SwUnderlineFont* pUnderFnt = nullptr;
1260
1261 if( rInf.GetUnderFnt() )
1262 {
1263 nOldUnder = GetUnderline();
1264 SetUnderline( LINESTYLE_NONE );
1265 pUnderFnt = rInf.GetUnderFnt();
1266 }
1267
1268 if ( !pLastFont || pLastFont->GetOwner() != reinterpret_cast<const void*>(m_nFontCacheId) )
1269 ChgFnt( rInf.GetShell(), rInf.GetOut() );
1270
1271 SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
1272
1273 rInf.ApplyAutoColor();
1274
1275 const Point aOldPos(rInf.GetPos());
1276 Point aPos( rInf.GetPos() );
1277
1278 if( GetEscapement() )
1279 CalcEsc( rInf, aPos );
1280
1281 rInf.SetKern( CheckKerning() + rInf.GetSperren() / SPACING_PRECISION_FACTOR );
1282 rInf.SetPos( aPos );
1283
1284 if( IsCapital() )
1285 DrawStretchCapital( rInf );
1286 else
1287 {
1288 SV_STAT( nDrawStretchText );
1289
1290 if ( rInf.GetFrame() )
1291 {
1292 if ( rInf.GetFrame()->IsRightToLeft() )
1293 rInf.GetFrame()->SwitchLTRtoRTL( aPos );
1294
1295 if ( rInf.GetFrame()->IsVertical() )
1296 rInf.GetFrame()->SwitchHorizontalToVertical( aPos );
1297
1298 rInf.SetPos( aPos );
1299 }
1300
1301 if ( !IsCaseMap() )
1302 rInf.GetOut().DrawStretchText( aPos, rInf.GetWidth(),
1303 rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
1304 else
1305 rInf.GetOut().DrawStretchText( aPos, rInf.GetWidth(),
1306 CalcCaseMap(rInf.GetText()),
1307 sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
1308 }
1309
1310 if( pUnderFnt && nOldUnder != LINESTYLE_NONE )
1311 {
1312 const OUString oldStr = rInf.GetText();
1313 TextFrameIndex const nOldIdx = rInf.GetIdx();
1314 TextFrameIndex const nOldLen = rInf.GetLen();
1315 rInf.SetText( " " );
1316 rInf.SetIdx( TextFrameIndex(0) );
1317 rInf.SetLen( TextFrameIndex(2) );
1318 SetUnderline( nOldUnder );
1319 rInf.SetUnderFnt( nullptr );
1320
1321 // set position for underline font
1322 rInf.SetPos( pUnderFnt->GetPos() );
1323
1324 pUnderFnt->GetFont().DrawStretchText_( rInf );
1325
1326 rInf.SetUnderFnt( pUnderFnt );
1327 rInf.SetText(oldStr);
1328 rInf.SetIdx( nOldIdx );
1329 rInf.SetLen( nOldLen );
1330 }
1331
1332 rInf.SetPos(aOldPos);
1333 }
1334
GetModelPositionForViewPoint_(SwDrawTextInfo & rInf)1335 TextFrameIndex SwSubFont::GetModelPositionForViewPoint_( SwDrawTextInfo& rInf )
1336 {
1337 if ( !pLastFont || pLastFont->GetOwner() != reinterpret_cast<const void*>(m_nFontCacheId) )
1338 ChgFnt( rInf.GetShell(), rInf.GetOut() );
1339
1340 SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
1341
1342 TextFrameIndex const nLn = rInf.GetLen() == TextFrameIndex(COMPLETE_STRING)
1343 ? TextFrameIndex(rInf.GetText().getLength())
1344 : rInf.GetLen();
1345 rInf.SetLen( nLn );
1346 TextFrameIndex nCursor(0);
1347 if( IsCapital() && nLn )
1348 nCursor = GetCapitalCursorOfst( rInf );
1349 else
1350 {
1351 const OUString oldText = rInf.GetText();
1352 tools::Long nOldKern = rInf.GetKern();
1353 rInf.SetKern( CheckKerning() );
1354 SV_STAT( nGetTextSize );
1355 if ( !IsCaseMap() )
1356 nCursor = pLastFont->GetModelPositionForViewPoint( rInf );
1357 else
1358 {
1359 rInf.SetText( CalcCaseMap( rInf.GetText() ) );
1360 nCursor = pLastFont->GetModelPositionForViewPoint( rInf );
1361 }
1362 rInf.SetKern( nOldKern );
1363 rInf.SetText(oldText);
1364 }
1365 return nCursor;
1366 }
1367
CalcEsc(SwDrawTextInfo const & rInf,Point & rPos)1368 void SwSubFont::CalcEsc( SwDrawTextInfo const & rInf, Point& rPos )
1369 {
1370 tools::Long nOfst;
1371
1372 bool bVert = false;
1373 bool bVertLRBT = false;
1374 if (rInf.GetFrame())
1375 {
1376 bVert = rInf.GetFrame()->IsVertical();
1377 bVertLRBT = rInf.GetFrame()->IsVertLRBT();
1378 }
1379 const Degree10 nDir = UnMapDirection(GetOrientation(), bVert, bVertLRBT);
1380
1381 switch ( GetEscapement() )
1382 {
1383 case DFLT_ESC_AUTO_SUB :
1384 nOfst = m_nOrgHeight - m_nOrgAscent -
1385 pLastFont->GetFontHeight( rInf.GetShell(), rInf.GetOut() ) +
1386 pLastFont->GetFontAscent( rInf.GetShell(), rInf.GetOut() );
1387
1388 switch ( nDir.get() )
1389 {
1390 case 0 :
1391 rPos.AdjustY(nOfst );
1392 break;
1393 case 900 :
1394 rPos.AdjustX(nOfst );
1395 break;
1396 case 2700 :
1397 rPos.AdjustX( -nOfst );
1398 break;
1399 }
1400
1401 break;
1402 case DFLT_ESC_AUTO_SUPER :
1403 nOfst = pLastFont->GetFontAscent( rInf.GetShell(), rInf.GetOut() ) -
1404 m_nOrgAscent;
1405
1406 switch ( nDir.get() )
1407 {
1408 case 0 :
1409 rPos.AdjustY(nOfst );
1410 break;
1411 case 900 :
1412 rPos.AdjustX(nOfst );
1413 break;
1414 case 2700 :
1415 rPos.AdjustX( -nOfst );
1416 break;
1417 }
1418
1419 break;
1420 default :
1421 nOfst = (static_cast<tools::Long>(m_nOrgHeight) * GetEscapement()) / 100;
1422
1423 switch ( nDir.get() )
1424 {
1425 case 0 :
1426 rPos.AdjustY( -nOfst );
1427 break;
1428 case 900 :
1429 rPos.AdjustX( -nOfst );
1430 break;
1431 case 2700 :
1432 rPos.AdjustX(nOfst );
1433 break;
1434 }
1435 }
1436 }
1437
1438 // used during painting of small capitals
Shift(Degree10 nDir)1439 void SwDrawTextInfo::Shift( Degree10 nDir )
1440 {
1441 #ifdef DBG_UTIL
1442 OSL_ENSURE( m_bPos, "DrawTextInfo: Undefined Position" );
1443 OSL_ENSURE( m_bSize, "DrawTextInfo: Undefined Width" );
1444 #endif
1445
1446 const bool bBidiPor = ( GetFrame() && GetFrame()->IsRightToLeft() ) !=
1447 ( ComplexTextLayoutFlags::Default != ( ComplexTextLayoutFlags::BiDiRtl & GetpOut()->GetLayoutMode() ) );
1448
1449 bool bVert = false;
1450 bool bVertLRBT = false;
1451 if (GetFrame())
1452 {
1453 bVert = GetFrame()->IsVertical();
1454 bVertLRBT = GetFrame()->IsVertLRBT();
1455 }
1456 nDir = bBidiPor ? 1800_deg10 : UnMapDirection(nDir, bVert, bVertLRBT);
1457
1458 switch ( nDir.get() )
1459 {
1460 case 0 :
1461 m_aPos.AdjustX(GetSize().Width() );
1462 break;
1463 case 900 :
1464 OSL_ENSURE( m_aPos.Y() >= GetSize().Width(), "Going underground" );
1465 m_aPos.AdjustY( -(GetSize().Width()) );
1466 break;
1467 case 1800 :
1468 m_aPos.AdjustX( -(GetSize().Width()) );
1469 break;
1470 case 2700 :
1471 m_aPos.AdjustY(GetSize().Width() );
1472 break;
1473 }
1474 }
1475
1476 /**
1477 * @note Used for the "continuous underline" feature.
1478 **/
SwUnderlineFont(SwFont & rFnt,TextFrameIndex const nEnd,const Point & rPoint)1479 SwUnderlineFont::SwUnderlineFont(SwFont& rFnt, TextFrameIndex const nEnd, const Point& rPoint)
1480 : m_aPos( rPoint ), m_nEnd( nEnd ), m_pFont( &rFnt )
1481 {
1482 };
1483
~SwUnderlineFont()1484 SwUnderlineFont::~SwUnderlineFont()
1485 {
1486 }
1487
1488 /// Helper for filters to find true lineheight of a font
AttrSetToLineHeight(const IDocumentSettingAccess & rIDocumentSettingAccess,const SwAttrSet & rSet,const vcl::RenderContext & rOut,sal_Int16 nScript)1489 tools::Long AttrSetToLineHeight( const IDocumentSettingAccess& rIDocumentSettingAccess,
1490 const SwAttrSet &rSet,
1491 const vcl::RenderContext &rOut, sal_Int16 nScript)
1492 {
1493 SwFont aFont(&rSet, &rIDocumentSettingAccess);
1494 SwFontScript nActual;
1495 switch (nScript)
1496 {
1497 default:
1498 case i18n::ScriptType::LATIN:
1499 nActual = SwFontScript::Latin;
1500 break;
1501 case i18n::ScriptType::ASIAN:
1502 nActual = SwFontScript::CJK;
1503 break;
1504 case i18n::ScriptType::COMPLEX:
1505 nActual = SwFontScript::CTL;
1506 break;
1507 }
1508 aFont.SetActual(nActual);
1509
1510 vcl::RenderContext &rMutableOut = const_cast<vcl::RenderContext &>(rOut);
1511 const vcl::Font aOldFont(rMutableOut.GetFont());
1512
1513 rMutableOut.SetFont(aFont.GetActualFont());
1514 tools::Long nHeight = rMutableOut.GetTextHeight();
1515
1516 rMutableOut.SetFont(aOldFont);
1517 return nHeight;
1518 }
1519
1520 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1521