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