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