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