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 "atrhndl.hxx"
21 #include <svl/itemiter.hxx>
22 #include <vcl/outdev.hxx>
23 #include <editeng/cmapitem.hxx>
24 #include <editeng/colritem.hxx>
25 #include <editeng/contouritem.hxx>
26 #include <editeng/crossedoutitem.hxx>
27 #include <editeng/escapementitem.hxx>
28 #include <editeng/fontitem.hxx>
29 #include <editeng/fhgtitem.hxx>
30 #include <editeng/kernitem.hxx>
31 #include <editeng/charreliefitem.hxx>
32 #include <editeng/langitem.hxx>
33 #include <editeng/postitem.hxx>
34 #include <editeng/shdditem.hxx>
35 #include <editeng/udlnitem.hxx>
36 #include <editeng/wghtitem.hxx>
37 #include <editeng/wrlmitem.hxx>
38 #include <editeng/autokernitem.hxx>
39 #include <editeng/blinkitem.hxx>
40 #include <editeng/charrotateitem.hxx>
41 #include <editeng/emphasismarkitem.hxx>
42 #include <editeng/charscaleitem.hxx>
43 #include <editeng/twolinesitem.hxx>
44 #include <editeng/charhiddenitem.hxx>
45 #include <editeng/boxitem.hxx>
46 #include <editeng/shaditem.hxx>
47 #include <viewopt.hxx>
48 #include <charfmt.hxx>
49 #include <fchrfmt.hxx>
50 #include <fmtautofmt.hxx>
51 #include <editeng/brushitem.hxx>
52 #include <fmtinfmt.hxx>
53 #include <txtinet.hxx>
54 #include <IDocumentSettingAccess.hxx>
55 #include <viewsh.hxx>
56
57 /**
58 * Attribute to Stack Mapping
59 *
60 * Attributes applied to a text are pushed on different stacks. For each
61 * stack, the top most attribute on the stack is valid. Because some
62 * kinds of attributes have to be pushed to the same stacks we map their
63 * ids to stack ids
64 * Attention: The first NUM_DEFAULT_VALUES ( defined in swfntcch.hxx )
65 * are stored in the defaultitem-cache, if you add one, you have to increase
66 * NUM_DEFAULT_VALUES.
67 * Also adjust NUM_ATTRIBUTE_STACKS in atrhndl.hxx.
68 */
69 const sal_uInt8 StackPos[ RES_TXTATR_WITHEND_END - RES_CHRATR_BEGIN + 1 ] =
70 {
71 0, // // 0
72 1, // RES_CHRATR_CASEMAP = RES_CHRATR_BEGIN // 1
73 0, // RES_CHRATR_CHARSETCOLOR, // 2
74 2, // RES_CHRATR_COLOR, // 3
75 3, // RES_CHRATR_CONTOUR, // 4
76 4, // RES_CHRATR_CROSSEDOUT, // 5
77 5, // RES_CHRATR_ESCAPEMENT, // 6
78 6, // RES_CHRATR_FONT, // 7
79 7, // RES_CHRATR_FONTSIZE, // 8
80 8, // RES_CHRATR_KERNING, // 9
81 9, // RES_CHRATR_LANGUAGE, // 10
82 10, // RES_CHRATR_POSTURE, // 11
83 0, // RES_CHRATR_UNUSED1, // 12
84 11, // RES_CHRATR_SHADOWED, // 13
85 12, // RES_CHRATR_UNDERLINE, // 14
86 13, // RES_CHRATR_WEIGHT, // 15
87 14, // RES_CHRATR_WORDLINEMODE, // 16
88 15, // RES_CHRATR_AUTOKERN, // 17
89 16, // RES_CHRATR_BLINK, // 18
90 17, // RES_CHRATR_NOHYPHEN, // 19
91 0, // RES_CHRATR_UNUSED2, // 20
92 18, // RES_CHRATR_BACKGROUND, // 21
93 19, // RES_CHRATR_CJK_FONT, // 22
94 20, // RES_CHRATR_CJK_FONTSIZE, // 23
95 21, // RES_CHRATR_CJK_LANGUAGE, // 24
96 22, // RES_CHRATR_CJK_POSTURE, // 25
97 23, // RES_CHRATR_CJK_WEIGHT, // 26
98 24, // RES_CHRATR_CTL_FONT, // 27
99 25, // RES_CHRATR_CTL_FONTSIZE, // 28
100 26, // RES_CHRATR_CTL_LANGUAGE, // 29
101 27, // RES_CHRATR_CTL_POSTURE, // 30
102 28, // RES_CHRATR_CTL_WEIGHT, // 31
103 29, // RES_CHRATR_ROTATE, // 32
104 30, // RES_CHRATR_EMPHASIS_MARK, // 33
105 31, // RES_CHRATR_TWO_LINES, // 34
106 32, // RES_CHRATR_SCALEW, // 35
107 33, // RES_CHRATR_RELIEF, // 36
108 34, // RES_CHRATR_HIDDEN, // 37
109 35, // RES_CHRATR_OVERLINE, // 38
110 0, // RES_CHRATR_RSID, // 39
111 36, // RES_CHRATR_BOX, // 40
112 37, // RES_CHRATR_SHADOW, // 41
113 38, // RES_CHRATR_HIGHLIGHT, // 42
114 0, // RES_CHRATR_GRABBAG, // 43
115 0, // RES_CHRATR_BIDIRTL, // 44
116 0, // RES_CHRATR_IDCTHINT, // 45
117 39, // RES_TXTATR_REFMARK, // 46
118 40, // RES_TXTATR_TOXMARK, // 47
119 41, // RES_TXTATR_META, // 48
120 41, // RES_TXTATR_METAFIELD, // 49
121 0, // RES_TXTATR_AUTOFMT, // 50
122 0, // RES_TXTATR_INETFMT // 51
123 0, // RES_TXTATR_CHARFMT, // 52
124 42, // RES_TXTATR_CJK_RUBY, // 53
125 0, // RES_TXTATR_UNKNOWN_CONTAINER, // 54
126 43, // RES_TXTATR_INPUTFIELD // 55
127 };
128
129 namespace CharFormat
130 {
131
132 /// Returns the item set associated with a character/inet/auto style
GetItemSet(const SfxPoolItem & rAttr)133 const SfxItemSet* GetItemSet( const SfxPoolItem& rAttr )
134 {
135 const SfxItemSet* pSet = nullptr;
136
137 if ( RES_TXTATR_AUTOFMT == rAttr.Which() )
138 {
139 pSet = static_cast<const SwFormatAutoFormat&>(rAttr).GetStyleHandle().get();
140 }
141 else
142 {
143 // Get the attributes from the template
144 const SwCharFormat* pFormat = RES_TXTATR_INETFMT == rAttr.Which() ?
145 static_cast<const SwFormatINetFormat&>(rAttr).GetTextINetFormat()->GetCharFormat() :
146 static_cast<const SwFormatCharFormat&>(rAttr).GetCharFormat();
147 if( pFormat )
148 {
149 pSet = &pFormat->GetAttrSet();
150 }
151 }
152
153 return pSet;
154 }
155
156 /// Extracts pool item of type nWhich from rAttr
GetItem(const SwTextAttr & rAttr,sal_uInt16 nWhich)157 const SfxPoolItem* GetItem( const SwTextAttr& rAttr, sal_uInt16 nWhich )
158 {
159 if ( RES_TXTATR_INETFMT == rAttr.Which() ||
160 RES_TXTATR_CHARFMT == rAttr.Which() ||
161 RES_TXTATR_AUTOFMT == rAttr.Which() )
162 {
163 const SfxItemSet* pSet = CharFormat::GetItemSet( rAttr.GetAttr() );
164 if ( !pSet ) return nullptr;
165
166 bool bInParent = RES_TXTATR_AUTOFMT != rAttr.Which();
167 const SfxPoolItem* pItem;
168 bool bRet = SfxItemState::SET == pSet->GetItemState( nWhich, bInParent, &pItem );
169
170 return bRet ? pItem : nullptr;
171 }
172
173 return ( nWhich == rAttr.Which() ) ? &rAttr.GetAttr() : nullptr;
174 }
175
176 /// Checks if item is included in character/inet/auto style
IsItemIncluded(const sal_uInt16 nWhich,const SwTextAttr * pAttr)177 bool IsItemIncluded( const sal_uInt16 nWhich, const SwTextAttr *pAttr )
178 {
179 bool bRet = false;
180
181 const SfxItemSet* pItemSet = CharFormat::GetItemSet( pAttr->GetAttr() );
182 if ( pItemSet )
183 bRet = SfxItemState::SET == pItemSet->GetItemState( nWhich );
184
185 return bRet;
186 }
187 }
188
189 /**
190 * The color of hyperlinks is taken from the associated character attribute,
191 * depending on its 'visited' state. There are actually two cases, which
192 * should override the colors from the character attribute:
193 * 1. We never take the 'visited' color during printing/pdf export/preview
194 * 2. The user has chosen to override these colors in the view options
195 */
lcl_ChgHyperLinkColor(const SwTextAttr & rAttr,const SfxPoolItem & rItem,const SwViewShell * pShell,Color * pColor)196 static bool lcl_ChgHyperLinkColor( const SwTextAttr& rAttr,
197 const SfxPoolItem& rItem,
198 const SwViewShell* pShell,
199 Color* pColor )
200 {
201 if ( !pShell ||
202 RES_TXTATR_INETFMT != rAttr.Which() ||
203 RES_CHRATR_COLOR != rItem.Which() )
204 return false;
205
206 // #i15455#
207 // 1. case:
208 // We do not want to show visited links:
209 // (printing, pdf export, page preview)
210
211 SwTextINetFormat & rINetAttr(const_cast<SwTextINetFormat&>(
212 static_txtattr_cast<SwTextINetFormat const&>(rAttr)));
213 if ( pShell->GetOut()->GetOutDevType() == OUTDEV_PRINTER ||
214 pShell->GetViewOptions()->IsPDFExport() ||
215 pShell->GetViewOptions()->IsPagePreview() )
216 {
217 if (rINetAttr.IsVisited())
218 {
219 if ( pColor )
220 {
221 // take color from character format 'unvisited link'
222 rINetAttr.SetVisited(false);
223 const SwCharFormat* pTmpFormat = rINetAttr.GetCharFormat();
224 const SfxPoolItem* pItem;
225 if (SfxItemState::SET == pTmpFormat->GetItemState(RES_CHRATR_COLOR, true, &pItem))
226 *pColor = static_cast<const SvxColorItem*>(pItem)->GetValue();
227 rINetAttr.SetVisited(true);
228 }
229 return true;
230 }
231
232 return false;
233 }
234
235 // 2. case:
236 // We do not want to apply the color set in the hyperlink
237 // attribute, instead we take the colors from the view options:
238
239 if ( pShell->GetWin() &&
240 (
241 (rINetAttr.IsVisited() && SwViewOption::IsVisitedLinks()) ||
242 (!rINetAttr.IsVisited() && SwViewOption::IsLinks())
243 )
244 )
245 {
246 if ( pColor )
247 {
248 if (rINetAttr.IsVisited())
249 {
250 // take color from view option 'visited link color'
251 *pColor = SwViewOption::GetVisitedLinksColor();
252 }
253 else
254 {
255 // take color from view option 'unvisited link color'
256 *pColor = SwViewOption::GetLinksColor();
257 }
258 }
259 return true;
260 }
261
262 return false;
263 }
264
SwAttrHandler()265 SwAttrHandler::SwAttrHandler()
266 : m_pIDocumentSettingAccess(nullptr)
267 , m_pShell(nullptr)
268 , m_bVertLayout(false)
269 , m_bVertLayoutLRBT(false)
270 {
271 memset( m_pDefaultArray, 0, NUM_DEFAULT_VALUES * sizeof(SfxPoolItem*) );
272 }
273
~SwAttrHandler()274 SwAttrHandler::~SwAttrHandler()
275 {
276 }
277
Init(const SwAttrSet & rAttrSet,const IDocumentSettingAccess & rIDocumentSettingAcces)278 void SwAttrHandler::Init( const SwAttrSet& rAttrSet,
279 const IDocumentSettingAccess& rIDocumentSettingAcces )
280 {
281 m_pIDocumentSettingAccess = &rIDocumentSettingAcces;
282 m_pShell = nullptr;
283
284 for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++ )
285 m_pDefaultArray[ StackPos[ i ] ] = &rAttrSet.Get( i );
286 }
287
Init(const SfxPoolItem ** pPoolItem,const SwAttrSet * pAS,const IDocumentSettingAccess & rIDocumentSettingAcces,const SwViewShell * pSh,SwFont & rFnt,bool bVL,bool bVertLayoutLRBT)288 void SwAttrHandler::Init( const SfxPoolItem** pPoolItem, const SwAttrSet* pAS,
289 const IDocumentSettingAccess& rIDocumentSettingAcces,
290 const SwViewShell* pSh,
291 SwFont& rFnt, bool bVL, bool bVertLayoutLRBT )
292 {
293 // initialize default array
294 memcpy( m_pDefaultArray, pPoolItem,
295 NUM_DEFAULT_VALUES * sizeof(SfxPoolItem*) );
296
297 m_pIDocumentSettingAccess = &rIDocumentSettingAcces;
298 m_pShell = pSh;
299
300 // do we have to apply additional paragraph attributes?
301 m_bVertLayout = bVL;
302 m_bVertLayoutLRBT = bVertLayoutLRBT;
303
304 if ( pAS && pAS->Count() )
305 {
306 SfxItemIter aIter( *pAS );
307 sal_uInt16 nWhich;
308 const SfxPoolItem* pItem = aIter.GetCurItem();
309 do
310 {
311 nWhich = pItem->Which();
312 if (isCHRATR(nWhich))
313 {
314 m_pDefaultArray[ StackPos[ nWhich ] ] = pItem;
315 FontChg( *pItem, rFnt, true );
316 }
317
318 pItem = aIter.NextItem();
319 } while (pItem);
320 }
321
322 // It is possible, that Init is called more than once, e.g., in a
323 // SwTextFrame::FormatOnceMore situation or (since sw_redlinehide)
324 // from SwAttrIter::Seek(); in the latter case SwTextSizeInfo::m_pFnt
325 // is an alias of m_pFnt so it must not be deleted!
326 if (m_pFnt)
327 {
328 *m_pFnt = rFnt;
329 }
330 else
331 {
332 m_pFnt.reset(new SwFont(rFnt));
333 }
334 }
335
Reset()336 void SwAttrHandler::Reset( )
337 {
338 for (auto& i : m_aAttrStack)
339 i.clear();
340 }
341
PushAndChg(const SwTextAttr & rAttr,SwFont & rFnt)342 void SwAttrHandler::PushAndChg( const SwTextAttr& rAttr, SwFont& rFnt )
343 {
344 // these special attributes in fact represent a collection of attributes
345 // they have to be pushed to each stack they belong to
346 if ( RES_TXTATR_INETFMT == rAttr.Which() ||
347 RES_TXTATR_CHARFMT == rAttr.Which() ||
348 RES_TXTATR_AUTOFMT == rAttr.Which() )
349 {
350 const SfxItemSet* pSet = CharFormat::GetItemSet( rAttr.GetAttr() );
351 if ( !pSet ) return;
352
353 for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++)
354 {
355 const SfxPoolItem* pItem;
356 bool bRet = SfxItemState::SET == pSet->GetItemState( i, rAttr.Which() != RES_TXTATR_AUTOFMT, &pItem );
357
358 if ( bRet )
359 {
360 // we push rAttr onto the appropriate stack
361 if ( Push( rAttr, *pItem ) )
362 {
363 // we let pItem change rFnt
364 Color aColor;
365 if (lcl_ChgHyperLinkColor(rAttr, *pItem, m_pShell, &aColor))
366 {
367 SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR );
368 FontChg( aItemNext, rFnt, true );
369 }
370 else
371 FontChg( *pItem, rFnt, true );
372 }
373 }
374 }
375 }
376 // this is the usual case, we have a basic attribute, push it onto the
377 // stack and change the font
378 else
379 {
380 if ( Push( rAttr, rAttr.GetAttr() ) )
381 // we let pItem change rFnt
382 FontChg( rAttr.GetAttr(), rFnt, true );
383 }
384 }
385
GetTop(sal_uInt16 nStack)386 const SwTextAttr* SwAttrHandler::GetTop(sal_uInt16 nStack)
387 {
388 return m_aAttrStack[nStack].empty() ? nullptr : m_aAttrStack[nStack].back();
389 }
390
Push(const SwTextAttr & rAttr,const SfxPoolItem & rItem)391 bool SwAttrHandler::Push( const SwTextAttr& rAttr, const SfxPoolItem& rItem )
392 {
393 OSL_ENSURE( rItem.Which() < RES_TXTATR_WITHEND_END,
394 "I do not want this attribute, nWhich >= RES_TXTATR_WITHEND_END" );
395
396 // robust
397 if ( RES_TXTATR_WITHEND_END <= rItem.Which() )
398 return false;
399
400 const sal_uInt16 nStack = StackPos[ rItem.Which() ];
401
402 // attributes originating from redlining have highest priority
403 // second priority are hyperlink attributes, which have a color replacement
404 const SwTextAttr* pTopAttr = GetTop(nStack);
405 if ( !pTopAttr
406 || rAttr.IsPriorityAttr()
407 || ( !pTopAttr->IsPriorityAttr()
408 && !lcl_ChgHyperLinkColor(*pTopAttr, rItem, m_pShell, nullptr)))
409 {
410 m_aAttrStack[nStack].push_back(&rAttr);
411 return true;
412 }
413
414 const auto it = m_aAttrStack[nStack].end() - 1;
415 m_aAttrStack[nStack].insert(it, &rAttr);
416 return false;
417 }
418
RemoveFromStack(sal_uInt16 nWhich,const SwTextAttr & rAttr)419 void SwAttrHandler::RemoveFromStack(sal_uInt16 nWhich, const SwTextAttr& rAttr)
420 {
421 auto& rStack = m_aAttrStack[StackPos[nWhich]];
422 const auto it = std::find(rStack.begin(), rStack.end(), &rAttr);
423 if (it != rStack.end())
424 rStack.erase(it);
425 }
426
PopAndChg(const SwTextAttr & rAttr,SwFont & rFnt)427 void SwAttrHandler::PopAndChg( const SwTextAttr& rAttr, SwFont& rFnt )
428 {
429 if ( RES_TXTATR_WITHEND_END <= rAttr.Which() )
430 return; // robust
431
432 // these special attributes in fact represent a collection of attributes
433 // they have to be removed from each stack they belong to
434 if ( RES_TXTATR_INETFMT == rAttr.Which() ||
435 RES_TXTATR_CHARFMT == rAttr.Which() ||
436 RES_TXTATR_AUTOFMT == rAttr.Which() )
437 {
438 const SfxItemSet* pSet = CharFormat::GetItemSet( rAttr.GetAttr() );
439 if ( !pSet ) return;
440
441 for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++)
442 {
443 const SfxPoolItem* pItem;
444 bool bRet = SfxItemState::SET == pSet->GetItemState( i, RES_TXTATR_AUTOFMT != rAttr.Which(), &pItem );
445 if ( bRet )
446 {
447 // we remove rAttr from the appropriate stack
448 RemoveFromStack(i, rAttr);
449 // reset font according to attribute on top of stack
450 // or default value
451 ActivateTop( rFnt, i );
452 }
453 }
454 }
455 // this is the usual case, we have a basic attribute, remove it from the
456 // stack and reset the font
457 else
458 {
459 RemoveFromStack(rAttr.Which(), rAttr);
460 // reset font according to attribute on top of stack
461 // or default value
462 ActivateTop( rFnt, rAttr.Which() );
463 }
464 }
465
466 /// Only used during redlining
Pop(const SwTextAttr & rAttr)467 void SwAttrHandler::Pop( const SwTextAttr& rAttr )
468 {
469 OSL_ENSURE( rAttr.Which() < RES_TXTATR_WITHEND_END,
470 "I do not have this attribute, nWhich >= RES_TXTATR_WITHEND_END" );
471
472 if ( rAttr.Which() < RES_TXTATR_WITHEND_END )
473 {
474 RemoveFromStack(rAttr.Which(), rAttr);
475 }
476 }
477
ActivateTop(SwFont & rFnt,const sal_uInt16 nAttr)478 void SwAttrHandler::ActivateTop( SwFont& rFnt, const sal_uInt16 nAttr )
479 {
480 OSL_ENSURE( nAttr < RES_TXTATR_WITHEND_END,
481 "I cannot activate this attribute, nWhich >= RES_TXTATR_WITHEND_END" );
482
483 const sal_uInt16 nStackPos = StackPos[ nAttr ];
484 const SwTextAttr* pTopAt = GetTop(nStackPos);
485 if ( pTopAt )
486 {
487 const SfxPoolItem* pItemNext(nullptr);
488
489 // check if top attribute is collection of attributes
490 if ( RES_TXTATR_INETFMT == pTopAt->Which() ||
491 RES_TXTATR_CHARFMT == pTopAt->Which() ||
492 RES_TXTATR_AUTOFMT == pTopAt->Which() )
493 {
494 const SfxItemSet* pSet = CharFormat::GetItemSet( pTopAt->GetAttr() );
495 if (pSet)
496 pSet->GetItemState( nAttr, RES_TXTATR_AUTOFMT != pTopAt->Which(), &pItemNext );
497 }
498
499 if (pItemNext)
500 {
501 Color aColor;
502 if (lcl_ChgHyperLinkColor(*pTopAt, *pItemNext, m_pShell, &aColor))
503 {
504 SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR );
505 FontChg( aItemNext, rFnt, false );
506 }
507 else
508 FontChg( *pItemNext, rFnt, false );
509 }
510 else
511 FontChg( pTopAt->GetAttr(), rFnt, false );
512 }
513
514 // default value has to be set, we only have default values for char attribs
515 else if ( nStackPos < NUM_DEFAULT_VALUES )
516 FontChg( *m_pDefaultArray[ nStackPos ], rFnt, false );
517 else if ( RES_TXTATR_REFMARK == nAttr )
518 rFnt.GetRef()--;
519 else if ( RES_TXTATR_TOXMARK == nAttr )
520 rFnt.GetTox()--;
521 else if ( (RES_TXTATR_META == nAttr) || (RES_TXTATR_METAFIELD == nAttr) )
522 {
523 rFnt.GetMeta()--;
524 }
525 else if ( RES_TXTATR_CJK_RUBY == nAttr )
526 {
527 // ruby stack has no more attributes
528 // check, if a rotation attribute has to be applied
529 const sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ];
530 bool bTwoLineAct = false;
531 const SwTextAttr* pTwoLineAttr = GetTop(nTwoLineStack);
532
533 if ( pTwoLineAttr )
534 {
535 const SfxPoolItem* pTwoLineItem = CharFormat::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES );
536 bTwoLineAct = static_cast<const SvxTwoLinesItem*>(pTwoLineItem)->GetValue();
537 }
538 else
539 bTwoLineAct =
540 static_cast<const SvxTwoLinesItem*>(m_pDefaultArray[ nTwoLineStack ])->GetValue();
541
542 if ( bTwoLineAct )
543 return;
544
545 // eventually, a rotate attribute has to be activated
546 const sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ];
547 const SwTextAttr* pRotateAttr = GetTop(nRotateStack);
548
549 if ( pRotateAttr )
550 {
551 const SfxPoolItem* pRotateItem = CharFormat::GetItem( *pRotateAttr, RES_CHRATR_ROTATE );
552 rFnt.SetVertical( static_cast<const SvxCharRotateItem*>(pRotateItem)->GetValue(),
553 m_bVertLayout );
554 }
555 else
556 rFnt.SetVertical(
557 static_cast<const SvxCharRotateItem*>(m_pDefaultArray[ nRotateStack ])->GetValue(),
558 m_bVertLayout
559 );
560 }
561 else if ( RES_TXTATR_INPUTFIELD == nAttr )
562 rFnt.GetInputField()--;
563 }
564
565 /**
566 * When popping an attribute from the stack, the top more remaining
567 * attribute in the stack becomes valid. The following function change
568 * a font depending on the stack id.
569 */
FontChg(const SfxPoolItem & rItem,SwFont & rFnt,bool bPush)570 void SwAttrHandler::FontChg(const SfxPoolItem& rItem, SwFont& rFnt, bool bPush )
571 {
572 switch ( rItem.Which() )
573 {
574 case RES_CHRATR_CASEMAP :
575 rFnt.SetCaseMap( static_cast<const SvxCaseMapItem&>(rItem).GetCaseMap() );
576 break;
577 case RES_CHRATR_COLOR :
578 rFnt.SetColor( static_cast<const SvxColorItem&>(rItem).GetValue() );
579 break;
580 case RES_CHRATR_CONTOUR :
581 rFnt.SetOutline( static_cast<const SvxContourItem&>(rItem).GetValue() );
582 break;
583 case RES_CHRATR_CROSSEDOUT :
584 rFnt.SetStrikeout( static_cast<const SvxCrossedOutItem&>(rItem).GetStrikeout() );
585 break;
586 case RES_CHRATR_ESCAPEMENT :
587 rFnt.SetEscapement( static_cast<const SvxEscapementItem&>(rItem).GetEsc() );
588 rFnt.SetProportion( static_cast<const SvxEscapementItem&>(rItem).GetProportionalHeight() );
589 break;
590 case RES_CHRATR_FONT :
591 rFnt.SetName( static_cast<const SvxFontItem&>(rItem).GetFamilyName(), SwFontScript::Latin );
592 rFnt.SetStyleName( static_cast<const SvxFontItem&>(rItem).GetStyleName(), SwFontScript::Latin );
593 rFnt.SetFamily( static_cast<const SvxFontItem&>(rItem).GetFamily(), SwFontScript::Latin );
594 rFnt.SetPitch( static_cast<const SvxFontItem&>(rItem).GetPitch(), SwFontScript::Latin );
595 rFnt.SetCharSet( static_cast<const SvxFontItem&>(rItem).GetCharSet(), SwFontScript::Latin );
596 break;
597 case RES_CHRATR_FONTSIZE :
598 rFnt.SetSize(Size(0,static_cast<const SvxFontHeightItem&>(rItem).GetHeight() ), SwFontScript::Latin );
599 break;
600 case RES_CHRATR_KERNING :
601 rFnt.SetFixKerning( static_cast<const SvxKerningItem&>(rItem).GetValue() );
602 break;
603 case RES_CHRATR_LANGUAGE :
604 rFnt.SetLanguage( static_cast<const SvxLanguageItem&>(rItem).GetLanguage(), SwFontScript::Latin );
605 break;
606 case RES_CHRATR_POSTURE :
607 rFnt.SetItalic( static_cast<const SvxPostureItem&>(rItem).GetPosture(), SwFontScript::Latin );
608 break;
609 case RES_CHRATR_SHADOWED :
610 rFnt.SetShadow( static_cast<const SvxShadowedItem&>(rItem).GetValue() );
611 break;
612 case RES_CHRATR_UNDERLINE :
613 {
614 const sal_uInt16 nStackPos = StackPos[ RES_CHRATR_HIDDEN ];
615 const SwTextAttr* pTopAt = GetTop(nStackPos);
616
617 const SfxPoolItem* pTmpItem = pTopAt ?
618 CharFormat::GetItem( *pTopAt, RES_CHRATR_HIDDEN ) :
619 m_pDefaultArray[ nStackPos ];
620
621 if ((m_pShell && !m_pShell->GetWin()) ||
622 (pTmpItem && !static_cast<const SvxCharHiddenItem*>(pTmpItem)->GetValue()) )
623 {
624 rFnt.SetUnderline( static_cast<const SvxUnderlineItem&>(rItem).GetLineStyle() );
625 rFnt.SetUnderColor( static_cast<const SvxUnderlineItem&>(rItem).GetColor() );
626 }
627 break;
628 }
629 case RES_CHRATR_BOX:
630 {
631 const SvxBoxItem& aBoxItem = static_cast<const SvxBoxItem&>(rItem);
632 rFnt.SetTopBorder( aBoxItem.GetTop() );
633 rFnt.SetBottomBorder( aBoxItem.GetBottom() );
634 rFnt.SetRightBorder( aBoxItem.GetRight() );
635 rFnt.SetLeftBorder( aBoxItem.GetLeft() );
636 rFnt.SetTopBorderDist( aBoxItem.GetDistance(SvxBoxItemLine::TOP) );
637 rFnt.SetBottomBorderDist( aBoxItem.GetDistance(SvxBoxItemLine::BOTTOM) );
638 rFnt.SetRightBorderDist( aBoxItem.GetDistance(SvxBoxItemLine::RIGHT) );
639 rFnt.SetLeftBorderDist( aBoxItem.GetDistance(SvxBoxItemLine::LEFT) );
640 break;
641 }
642 case RES_CHRATR_SHADOW:
643 {
644 const SvxShadowItem& aShadowItem = static_cast<const SvxShadowItem&>(rItem);
645 rFnt.SetShadowColor( aShadowItem.GetColor() );
646 rFnt.SetShadowWidth( aShadowItem.GetWidth() );
647 rFnt.SetShadowLocation( aShadowItem.GetLocation() );
648 break;
649 }
650 case RES_CHRATR_OVERLINE :
651 rFnt.SetOverline( static_cast<const SvxOverlineItem&>(rItem).GetLineStyle() );
652 rFnt.SetOverColor( static_cast<const SvxOverlineItem&>(rItem).GetColor() );
653 break;
654 case RES_CHRATR_WEIGHT :
655 rFnt.SetWeight( static_cast<const SvxWeightItem&>(rItem).GetWeight(), SwFontScript::Latin );
656 break;
657 case RES_CHRATR_WORDLINEMODE :
658 rFnt.SetWordLineMode( static_cast<const SvxWordLineModeItem&>(rItem).GetValue() );
659 break;
660 case RES_CHRATR_AUTOKERN :
661 if( static_cast<const SvxAutoKernItem&>(rItem).GetValue() )
662 {
663 rFnt.SetAutoKern( (!m_pIDocumentSettingAccess ||
664 !m_pIDocumentSettingAccess->get(DocumentSettingId::KERN_ASIAN_PUNCTUATION)) ?
665 FontKerning::FontSpecific :
666 FontKerning::Asian );
667 }
668 else
669 rFnt.SetAutoKern( FontKerning::NONE );
670 break;
671 case RES_CHRATR_BLINK :
672 rFnt.SetBlink( static_cast<const SvxBlinkItem&>(rItem).GetValue() );
673 break;
674 case RES_CHRATR_BACKGROUND :
675 rFnt.SetBackColor(new Color( static_cast<const SvxBrushItem&>(rItem).GetColor() ) );
676 break;
677 case RES_CHRATR_HIGHLIGHT :
678 rFnt.SetHighlightColor( static_cast<const SvxBrushItem&>(rItem).GetColor() );
679 break;
680 case RES_CHRATR_CJK_FONT :
681 rFnt.SetName( static_cast<const SvxFontItem&>(rItem).GetFamilyName(), SwFontScript::CJK );
682 rFnt.SetStyleName( static_cast<const SvxFontItem&>(rItem).GetStyleName(), SwFontScript::CJK );
683 rFnt.SetFamily( static_cast<const SvxFontItem&>(rItem).GetFamily(), SwFontScript::CJK );
684 rFnt.SetPitch( static_cast<const SvxFontItem&>(rItem).GetPitch(), SwFontScript::CJK );
685 rFnt.SetCharSet( static_cast<const SvxFontItem&>(rItem).GetCharSet(), SwFontScript::CJK );
686 break;
687 case RES_CHRATR_CJK_FONTSIZE :
688 rFnt.SetSize(Size( 0, static_cast<const SvxFontHeightItem&>(rItem).GetHeight()), SwFontScript::CJK);
689 break;
690 case RES_CHRATR_CJK_LANGUAGE :
691 rFnt.SetLanguage( static_cast<const SvxLanguageItem&>(rItem).GetLanguage(), SwFontScript::CJK );
692 break;
693 case RES_CHRATR_CJK_POSTURE :
694 rFnt.SetItalic( static_cast<const SvxPostureItem&>(rItem).GetPosture(), SwFontScript::CJK );
695 break;
696 case RES_CHRATR_CJK_WEIGHT :
697 rFnt.SetWeight( static_cast<const SvxWeightItem&>(rItem).GetWeight(), SwFontScript::CJK );
698 break;
699 case RES_CHRATR_CTL_FONT :
700 rFnt.SetName( static_cast<const SvxFontItem&>(rItem).GetFamilyName(), SwFontScript::CTL );
701 rFnt.SetStyleName( static_cast<const SvxFontItem&>(rItem).GetStyleName(), SwFontScript::CTL );
702 rFnt.SetFamily( static_cast<const SvxFontItem&>(rItem).GetFamily(), SwFontScript::CTL );
703 rFnt.SetPitch( static_cast<const SvxFontItem&>(rItem).GetPitch(), SwFontScript::CTL );
704 rFnt.SetCharSet( static_cast<const SvxFontItem&>(rItem).GetCharSet(), SwFontScript::CTL );
705 break;
706 case RES_CHRATR_CTL_FONTSIZE :
707 rFnt.SetSize(Size(0, static_cast<const SvxFontHeightItem&>(rItem).GetHeight() ), SwFontScript::CTL);
708 break;
709 case RES_CHRATR_CTL_LANGUAGE :
710 rFnt.SetLanguage( static_cast<const SvxLanguageItem&>(rItem).GetLanguage(), SwFontScript::CTL );
711 break;
712 case RES_CHRATR_CTL_POSTURE :
713 rFnt.SetItalic( static_cast<const SvxPostureItem&>(rItem).GetPosture(), SwFontScript::CTL );
714 break;
715 case RES_CHRATR_CTL_WEIGHT :
716 rFnt.SetWeight( static_cast<const SvxWeightItem&>(rItem).GetWeight(), SwFontScript::CTL );
717 break;
718 case RES_CHRATR_EMPHASIS_MARK :
719 rFnt.SetEmphasisMark(
720 static_cast<const SvxEmphasisMarkItem&>(rItem).GetEmphasisMark()
721 );
722 break;
723 case RES_CHRATR_SCALEW :
724 rFnt.SetPropWidth( static_cast<const SvxCharScaleWidthItem&>(rItem).GetValue() );
725 break;
726 case RES_CHRATR_RELIEF :
727 rFnt.SetRelief( static_cast<const SvxCharReliefItem&>(rItem).GetValue() );
728 break;
729 case RES_CHRATR_HIDDEN :
730 if (m_pShell && m_pShell->GetWin())
731 {
732 if ( static_cast<const SvxCharHiddenItem&>(rItem).GetValue() )
733 rFnt.SetUnderline( LINESTYLE_DOTTED );
734 else
735 ActivateTop( rFnt, RES_CHRATR_UNDERLINE );
736 }
737 break;
738 case RES_CHRATR_ROTATE :
739 {
740 // rotate attribute is applied, when:
741 // 1. ruby stack is empty and
742 // 2. top of two line stack ( or default attribute )is an
743 // deactivated two line attribute
744 const bool bRuby =
745 0 != m_aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].size();
746
747 if ( bRuby )
748 break;
749
750 const sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ];
751 bool bTwoLineAct = false;
752 const SwTextAttr* pTwoLineAttr = GetTop(nTwoLineStack);
753
754 if ( pTwoLineAttr )
755 {
756 const SfxPoolItem* pTwoLineItem = CharFormat::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES );
757 bTwoLineAct = static_cast<const SvxTwoLinesItem*>(pTwoLineItem)->GetValue();
758 }
759 else
760 bTwoLineAct =
761 static_cast<const SvxTwoLinesItem*>(m_pDefaultArray[ nTwoLineStack ])->GetValue();
762
763 if ( !bTwoLineAct )
764 rFnt.SetVertical( static_cast<const SvxCharRotateItem&>(rItem).GetValue(),
765 m_bVertLayout, m_bVertLayoutLRBT );
766
767 break;
768 }
769 case RES_CHRATR_TWO_LINES :
770 {
771 bool bRuby = 0 !=
772 m_aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].size();
773
774 // two line is activated, if
775 // 1. no ruby attribute is set and
776 // 2. attribute is active
777 if ( !bRuby && static_cast<const SvxTwoLinesItem&>(rItem).GetValue() )
778 {
779 rFnt.SetVertical( 0, m_bVertLayout );
780 break;
781 }
782
783 // a deactivating two line attribute is on top of stack,
784 // check if rotate attribute has to be enabled
785 if ( bRuby )
786 break;
787
788 const sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ];
789 const SwTextAttr* pRotateAttr = GetTop(nRotateStack);
790
791 if ( pRotateAttr )
792 {
793 const SfxPoolItem* pRotateItem = CharFormat::GetItem( *pRotateAttr, RES_CHRATR_ROTATE );
794 rFnt.SetVertical( static_cast<const SvxCharRotateItem*>(pRotateItem)->GetValue(),
795 m_bVertLayout );
796 }
797 else
798 rFnt.SetVertical(
799 static_cast<const SvxCharRotateItem*>(m_pDefaultArray[ nRotateStack ])->GetValue(),
800 m_bVertLayout
801 );
802 break;
803 }
804 case RES_TXTATR_CJK_RUBY :
805 rFnt.SetVertical( 0, m_bVertLayout );
806 break;
807 case RES_TXTATR_REFMARK :
808 if ( bPush )
809 rFnt.GetRef()++;
810 else
811 rFnt.GetRef()--;
812 break;
813 case RES_TXTATR_TOXMARK :
814 if ( bPush )
815 rFnt.GetTox()++;
816 else
817 rFnt.GetTox()--;
818 break;
819 case RES_TXTATR_META:
820 case RES_TXTATR_METAFIELD:
821 if ( bPush )
822 rFnt.GetMeta()++;
823 else
824 rFnt.GetMeta()--;
825 break;
826 case RES_TXTATR_INPUTFIELD :
827 if ( bPush )
828 rFnt.GetInputField()++;
829 else
830 rFnt.GetInputField()--;
831 break;
832 }
833 }
834
835 /// Takes the default font and calculated the ascent and height
GetDefaultAscentAndHeight(SwViewShell const * pShell,OutputDevice const & rOut,sal_uInt16 & nAscent,sal_uInt16 & nHeight) const836 void SwAttrHandler::GetDefaultAscentAndHeight( SwViewShell const * pShell, OutputDevice const & rOut,
837 sal_uInt16& nAscent, sal_uInt16& nHeight ) const
838 {
839 OSL_ENSURE(m_pFnt, "No font available for GetDefaultAscentAndHeight");
840
841 if (m_pFnt)
842 {
843 SwFont aFont( *m_pFnt );
844 nHeight = aFont.GetHeight( pShell, rOut );
845 nAscent = aFont.GetAscent( pShell, rOut );
846 }
847 }
848
849 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
850