1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26
27
28 #include "winmtf.hxx"
29 #include <vcl/metaact.hxx>
30 #include <vcl/metric.hxx>
31 #include <rtl/tencinfo.h>
32 #include <vcl/svapp.hxx>
33 #include <vcl/virdev.hxx>
34 #include <vos/mutex.hxx>
35
36 // ------------------------------------------------------------------------
37
38 #define WIN_MTF_MAX_CLIP_DEPTH 16
39
ImpUpdateType()40 void WinMtfClipPath::ImpUpdateType()
41 {
42 if ( !aPolyPoly.Count() )
43 eType = EMPTY;
44 else if ( aPolyPoly.IsRect() )
45 eType = RECTANGLE;
46 else
47 eType = COMPLEX;
48
49 bNeedsUpdate = sal_True;
50 }
51
IntersectClipRect(const Rectangle & rRect)52 void WinMtfClipPath::IntersectClipRect( const Rectangle& rRect )
53 {
54 if ( !aPolyPoly.Count() )
55 aPolyPoly = Polygon( rRect );
56 else if ( nDepth < WIN_MTF_MAX_CLIP_DEPTH )
57 {
58 Polygon aPolygon( rRect );
59 PolyPolygon aIntersection;
60 PolyPolygon aPolyPolyRect( aPolygon );
61 aPolyPoly.GetIntersection( aPolyPolyRect, aIntersection );
62 aPolyPoly = aIntersection;
63 nDepth++;
64 }
65 ImpUpdateType();
66 }
67
ExcludeClipRect(const Rectangle & rRect)68 void WinMtfClipPath::ExcludeClipRect( const Rectangle& rRect )
69 {
70 if ( aPolyPoly.Count() && ( nDepth < WIN_MTF_MAX_CLIP_DEPTH ) )
71 {
72 Polygon aPolygon( rRect );
73 PolyPolygon aPolyPolyRect( aPolygon );
74 PolyPolygon aDifference;
75 aPolyPoly.GetDifference( aPolyPolyRect, aDifference );
76 aPolyPoly = aDifference;
77 nDepth++;
78 }
79 ImpUpdateType();
80 }
81
SetClipPath(const PolyPolygon & rPolyPolygon,sal_Int32 nClippingMode)82 void WinMtfClipPath::SetClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode )
83 {
84 PolyPolygon aSimplePoly;
85 if ( rPolyPolygon.Count() && rPolyPolygon[ 0 ].HasFlags() )
86 rPolyPolygon.AdaptiveSubdivide( aSimplePoly, 100 );
87 if ( !aSimplePoly.Count() )
88 aPolyPoly = aSimplePoly;
89 else if ( nDepth < WIN_MTF_MAX_CLIP_DEPTH )
90 {
91 nDepth++;
92
93 PolyPolygon aNewClipPath;
94
95 // #115345# Watch out for empty aPolyPoly here - conceptually,
96 // an empty clip path is a rectangle of infinite size, but it
97 // is represented by an empty aPolyPoly. When intersecting
98 // rPolyPolygon with this _empty_ aPolyPoly, set algebra
99 // guarantees wrong results.
100 switch ( nClippingMode )
101 {
102 case RGN_OR :
103 // #115345# clip stays empty, when ORing an arbitrary
104 // rPolyPolygon. Thus, we can save us the unnecessary
105 // clipper call.
106 if( aPolyPoly.Count() )
107 aPolyPoly.GetUnion( aSimplePoly, aNewClipPath );
108 break;
109 case RGN_XOR :
110 // TODO:
111 // #115345# Cannot handle this case, for the time being
112 aPolyPoly.GetXOR( aSimplePoly, aNewClipPath );
113 break;
114 case RGN_DIFF :
115 // TODO:
116 // #115345# Cannot handle this case, for the time being
117 aPolyPoly.GetDifference( aSimplePoly, aNewClipPath );
118 break;
119 case RGN_AND :
120 // #115345# Clip becomes rPolyPolygon, when ANDing
121 // with an arbitrary rPolyPolygon
122 if( aPolyPoly.Count() )
123 aPolyPoly.GetIntersection( aSimplePoly, aNewClipPath );
124 else
125 aNewClipPath = aSimplePoly;
126 break;
127 case RGN_COPY :
128 aNewClipPath = aSimplePoly;
129 break;
130 }
131 aPolyPoly = aNewClipPath;
132 }
133 ImpUpdateType();
134 }
135
MoveClipRegion(const Size & rSize)136 void WinMtfClipPath::MoveClipRegion( const Size& rSize )
137 {
138 aPolyPoly.Move( rSize.Width(), rSize.Height() );
139 bNeedsUpdate = sal_True;
140 }
141
142 // ------------------------------------------------------------------------
143
AddPoint(const Point & rPoint)144 void WinMtfPathObj::AddPoint( const Point& rPoint )
145 {
146 if ( bClosed )
147 Insert( Polygon(), POLYPOLY_APPEND );
148 Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ];
149 rPoly.Insert( rPoly.GetSize(), rPoint, POLY_NORMAL );
150 bClosed = sal_False;
151 }
152
AddPolyLine(const Polygon & rPolyLine)153 void WinMtfPathObj::AddPolyLine( const Polygon& rPolyLine )
154 {
155 if ( bClosed )
156 Insert( Polygon(), POLYPOLY_APPEND );
157 Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ];
158 rPoly.Insert( rPoly.GetSize(), rPolyLine );
159 bClosed = sal_False;
160 }
161
AddPolygon(const Polygon & rPoly)162 void WinMtfPathObj::AddPolygon( const Polygon& rPoly )
163 {
164 Insert( rPoly, POLYPOLY_APPEND );
165 bClosed = sal_True;
166 }
167
AddPolyPolygon(const PolyPolygon & rPolyPoly)168 void WinMtfPathObj::AddPolyPolygon( const PolyPolygon& rPolyPoly )
169 {
170 sal_uInt16 i, nCount = rPolyPoly.Count();
171 for ( i = 0; i < nCount; i++ )
172 Insert( rPolyPoly[ i ], POLYPOLY_APPEND );
173 bClosed = sal_True;
174 }
175
ClosePath()176 void WinMtfPathObj::ClosePath()
177 {
178 if ( Count() )
179 {
180 Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ];
181 if ( rPoly.GetSize() > 2 )
182 {
183 Point aFirst( rPoly[ 0 ] );
184 if ( aFirst != rPoly[ rPoly.GetSize() - 1 ] )
185 rPoly.Insert( rPoly.GetSize(), aFirst, POLY_NORMAL );
186 }
187 }
188 bClosed = sal_True;
189 }
190
191 // ------------------------------------------------------------------------
192
WinMtfFontStyle(LOGFONTW & rFont)193 WinMtfFontStyle::WinMtfFontStyle( LOGFONTW& rFont )
194 {
195 CharSet eCharSet;
196 if ( ( rFont.lfCharSet == OEM_CHARSET ) || ( rFont.lfCharSet == DEFAULT_CHARSET ) )
197 eCharSet = gsl_getSystemTextEncoding();
198 else
199 eCharSet = rtl_getTextEncodingFromWindowsCharset( rFont.lfCharSet );
200 if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
201 eCharSet = gsl_getSystemTextEncoding();
202 aFont.SetCharSet( eCharSet );
203 aFont.SetName( rFont.alfFaceName );
204 FontFamily eFamily;
205 switch ( rFont.lfPitchAndFamily & 0xf0 )
206 {
207 case FF_ROMAN:
208 eFamily = FAMILY_ROMAN;
209 break;
210
211 case FF_SWISS:
212 eFamily = FAMILY_SWISS;
213 break;
214
215 case FF_MODERN:
216 eFamily = FAMILY_MODERN;
217 break;
218
219 case FF_SCRIPT:
220 eFamily = FAMILY_SCRIPT;
221 break;
222
223 case FF_DECORATIVE:
224 eFamily = FAMILY_DECORATIVE;
225 break;
226
227 default:
228 eFamily = FAMILY_DONTKNOW;
229 break;
230 }
231 aFont.SetFamily( eFamily );
232
233 FontPitch ePitch;
234 switch ( rFont.lfPitchAndFamily & 0x0f )
235 {
236 case FIXED_PITCH:
237 ePitch = PITCH_FIXED;
238 break;
239
240 case DEFAULT_PITCH:
241 case VARIABLE_PITCH:
242 default:
243 ePitch = PITCH_VARIABLE;
244 break;
245 }
246 aFont.SetPitch( ePitch );
247
248 FontWeight eWeight;
249 if( rFont.lfWeight <= FW_THIN )
250 eWeight = WEIGHT_THIN;
251 else if( rFont.lfWeight <= FW_ULTRALIGHT )
252 eWeight = WEIGHT_ULTRALIGHT;
253 else if( rFont.lfWeight <= FW_LIGHT )
254 eWeight = WEIGHT_LIGHT;
255 else if( rFont.lfWeight < FW_MEDIUM )
256 eWeight = WEIGHT_NORMAL;
257 else if( rFont.lfWeight == FW_MEDIUM )
258 eWeight = WEIGHT_MEDIUM;
259 else if( rFont.lfWeight <= FW_SEMIBOLD )
260 eWeight = WEIGHT_SEMIBOLD;
261 else if( rFont.lfWeight <= FW_BOLD )
262 eWeight = WEIGHT_BOLD;
263 else if( rFont.lfWeight <= FW_ULTRABOLD )
264 eWeight = WEIGHT_ULTRABOLD;
265 else
266 eWeight = WEIGHT_BLACK;
267 aFont.SetWeight( eWeight );
268
269 if( rFont.lfItalic )
270 aFont.SetItalic( ITALIC_NORMAL );
271
272 if( rFont.lfUnderline )
273 aFont.SetUnderline( UNDERLINE_SINGLE );
274
275 if( rFont.lfStrikeOut )
276 aFont.SetStrikeout( STRIKEOUT_SINGLE );
277
278 if ( rFont.lfOrientation )
279 aFont.SetOrientation( (short)rFont.lfOrientation );
280 else
281 aFont.SetOrientation( (short)rFont.lfEscapement );
282
283 Size aFontSize( Size( rFont.lfWidth, rFont.lfHeight ) );
284 if ( rFont.lfHeight > 0 )
285 {
286 // #117968# VirtualDevice is not thread safe, but filter is used in multithreading
287 vos::OGuard aGuard( Application::GetSolarMutex() );
288 VirtualDevice aVDev;
289
290 // converting the cell height into a font height
291 aFont.SetSize( aFontSize );
292 aVDev.SetFont( aFont );
293 FontMetric aMetric( aVDev.GetFontMetric() );
294 long nHeight = aMetric.GetAscent() + aMetric.GetDescent();
295 if ( nHeight )
296 {
297 double fHeight = ((double)aFontSize.Height() * rFont.lfHeight ) / nHeight;
298 aFontSize.Height() = (sal_Int32)( fHeight + 0.5 );
299 }
300 }
301 else if ( aFontSize.Height() < 0 )
302 aFontSize.Height() *= -1;
303
304 if ( !rFont.lfWidth )
305 {
306 // #117968# VirtualDevice is not thread safe, but filter is used in multithreading
307 vos::OGuard aGuard( Application::GetSolarMutex() );
308 VirtualDevice aVDev;
309
310 aFont.SetSize( aFontSize );
311 aVDev.SetFont( aFont );
312 FontMetric aMetric( aVDev.GetFontMetric() );
313 aFontSize.Width() = aMetric.GetWidth();
314 }
315
316 aFont.SetSize( aFontSize );
317 };
318
319 // ------------------------------------------------------------------------
320
321 #ifdef WIN_MTF_ASSERT
WinMtfAssertHandler(const sal_Char * pAction,sal_uInt32 nFlags)322 void WinMtfAssertHandler( const sal_Char* pAction, sal_uInt32 nFlags )
323 {
324 static sal_Bool bOnlyOnce;
325 static sal_Int32 nAssertCount;
326
327 if ( nFlags & WIN_MTF_ASSERT_INIT )
328 nAssertCount = 0;
329 if ( nFlags & WIN_MTF_ASSERT_ONCE )
330 bOnlyOnce = sal_True;
331 if ( nFlags & WIN_MTF_ASSERT_MIFE )
332 {
333 if ( ( nAssertCount == 0 ) || ( bOnlyOnce == sal_False ) )
334 {
335 ByteString aText( "WMF/EMF Import: " );
336 if ( pAction )
337 {
338 ByteString aAction( pAction );
339 aText.Append( aAction );
340 }
341 aText.Append( " needs to be implemented (SJ)" );
342 DBG_ASSERT( 0, aText.GetBuffer() );
343 }
344 nAssertCount++;
345 }
346 }
347 #endif
348
349 // ------------------------------------------------------------------------
350
WinMtf(WinMtfOutput * pWinMtfOutput,SvStream & rStreamWMF,FilterConfigItem * pConfigItem)351 WinMtf::WinMtf( WinMtfOutput* pWinMtfOutput, SvStream& rStreamWMF, FilterConfigItem* pConfigItem ) :
352 pOut ( pWinMtfOutput ),
353 pWMF ( &rStreamWMF ),
354 pFilterConfigItem ( pConfigItem )
355 {
356 #ifdef WIN_MTF_ASSERT
357 // we want to assert not implemented features, but we do this
358 // only once, so that nobody is handicaped by getting too much assertions
359 // I hope this will bring more testdocuments, without support of these
360 // testdocuments the implementation of missing features won't be possible. (SJ)
361 WinMtfAssertHandler( NULL, WIN_MTF_ASSERT_INIT | WIN_MTF_ASSERT_ONCE );
362 #endif
363
364 SvLockBytes *pLB = pWMF->GetLockBytes();
365 if ( pLB )
366 pLB->SetSynchronMode( sal_True );
367
368 nStartPos = pWMF->Tell();
369
370 pOut->SetDevOrg( Point() );
371 if ( pFilterConfigItem )
372 {
373 xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
374 if ( xStatusIndicator.is() )
375 {
376 rtl::OUString aMsg;
377 xStatusIndicator->start( aMsg, 100 );
378 }
379 }
380 }
381
382 // ------------------------------------------------------------------------
383
~WinMtf()384 WinMtf::~WinMtf()
385 {
386 delete pOut;
387
388 if ( xStatusIndicator.is() )
389 xStatusIndicator->end();
390 }
391
392 // ------------------------------------------------------------------------
393
Callback(sal_uInt16 nPercent)394 void WinMtf::Callback( sal_uInt16 nPercent )
395 {
396 if ( xStatusIndicator.is() )
397 xStatusIndicator->setValue( nPercent );
398 }
399
400 // ------------------------------------------------------------------------
401
ReadColor()402 Color WinMtf::ReadColor()
403 {
404 sal_uInt32 nColor;
405 *pWMF >> nColor;
406 return Color( (sal_uInt8)nColor, (sal_uInt8)( nColor >> 8 ), (sal_uInt8)( nColor >> 16 ) );
407 };
408
409 //-----------------------------------------------------------------------------------
410 //-----------------------------------------------------------------------------------
411 //-----------------------------------------------------------------------------------
412
ImplMap(const Point & rPt)413 Point WinMtfOutput::ImplMap( const Point& rPt )
414 {
415 if ( mnWinExtX && mnWinExtY )
416 {
417 double fX2, fX = rPt.X();
418 double fY2, fY = rPt.Y();
419
420 fX2 = fX * maXForm.eM11 + fY * maXForm.eM21 + maXForm.eDx;
421 fY2 = fX * maXForm.eM12 + fY * maXForm.eM22 + maXForm.eDy;
422
423 if ( mnGfxMode == GM_COMPATIBLE )
424 {
425 switch( mnMapMode )
426 {
427 case MM_LOENGLISH :
428 {
429 fX2 -= mnWinOrgX;
430 fY2 = mnWinOrgY-fY2;
431 fX2 *= 25.40;
432 fY2 *= 25.40;
433 fX2 += mnDevOrgX;
434 fY2 += mnDevOrgY;
435 }
436 break;
437 case MM_HIENGLISH :
438 {
439 fX2 -= mnWinOrgX;
440 fY2 = mnWinOrgY-fY2;
441 fX2 *= 2.540;
442 fY2 *= 2.540;
443 fX2 += mnDevOrgX;
444 fY2 += mnDevOrgY;
445 }
446 break;
447 case MM_LOMETRIC :
448 {
449 fX2 -= mnWinOrgX;
450 fY2 = mnWinOrgY-fY2;
451 fX2 *= 10;
452 fY2 *= 10;
453 fX2 += mnDevOrgX;
454 fY2 += mnDevOrgY;
455 }
456 break;
457 case MM_HIMETRIC :
458 {
459 fX2 -= mnWinOrgX;
460 fY2 = mnWinOrgY-fY2;
461 fX2 += mnDevOrgX;
462 fY2 += mnDevOrgY;
463 }
464 break;
465 default :
466 {
467 fX2 -= mnWinOrgX;
468 fY2 -= mnWinOrgY;
469 fX2 /= mnWinExtX;
470 fY2 /= mnWinExtY;
471 fX2 *= mnDevWidth;
472 fY2 *= mnDevHeight;
473 fX2 += mnDevOrgX;
474 fY2 += mnDevOrgY; // fX2, fY2 now in device units
475 fX2 *= (double)mnMillX * 100.0 / (double)mnPixX;
476 fY2 *= (double)mnMillY * 100.0 / (double)mnPixY;
477 }
478 break;
479 }
480 fX2 -= mrclFrame.Left();
481 fY2 -= mrclFrame.Top();
482 }
483 return Point( FRound( fX2 ), FRound( fY2 ) );
484 }
485 else
486 return Point();
487 };
488
489 // ------------------------------------------------------------------------
490
ImplMap(const Size & rSz)491 Size WinMtfOutput::ImplMap( const Size& rSz )
492 {
493 if ( mnWinExtX && mnWinExtY )
494 {
495 // #121382# apply the whole WorldTransform, else a rotation will be misinterpreted
496 double fWidth = rSz.Width() * maXForm.eM11 + rSz.Height() * maXForm.eM21;
497 double fHeight = rSz.Width() * maXForm.eM12 + rSz.Height() * maXForm.eM22;
498
499 if ( mnGfxMode == GM_COMPATIBLE )
500 {
501 switch( mnMapMode )
502 {
503 case MM_LOENGLISH :
504 {
505 fWidth *= 25.40;
506 fHeight*=-25.40;
507 }
508 break;
509 case MM_HIENGLISH :
510 {
511 fWidth *= 2.540;
512 fHeight*=-2.540;
513 }
514 break;
515 case MM_LOMETRIC :
516 {
517 fWidth *= 10;
518 fHeight*=-10;
519 }
520 break;
521 case MM_HIMETRIC :
522 {
523 fHeight *= -1;
524 }
525 break;
526 default :
527 {
528 fWidth /= mnWinExtX;
529 fHeight /= mnWinExtY;
530 fWidth *= mnDevWidth;
531 fHeight *= mnDevHeight;
532 fWidth *= (double)mnMillX * 100 / (double)mnPixX;
533 fHeight *= (double)mnMillY * 100 / (double)mnPixY;
534 }
535 break;
536 }
537 }
538 return Size( FRound( fWidth ), FRound( fHeight ) );
539 }
540 else
541 return Size();
542 }
543
544 //-----------------------------------------------------------------------------------
545
ImplMap(const Rectangle & rRect)546 Rectangle WinMtfOutput::ImplMap( const Rectangle& rRect )
547 {
548 return Rectangle( ImplMap( rRect.TopLeft() ), ImplMap( rRect.GetSize() ) );
549 }
550
551 //-----------------------------------------------------------------------------------
552
ImplMap(Font & rFont)553 void WinMtfOutput::ImplMap( Font& rFont )
554 {
555 // !!! HACK: Wir setzen die Breite jetzt immer auf Null,
556 // da OS die Breite unterschiedlich interpretieren;
557 // muss spaeter in SV portabel gemacht werden ( KA 08.02.96 )
558 Size aFontSize = ImplMap ( rFont.GetSize() );
559
560 if( aFontSize.Height() < 0 )
561 aFontSize.Height() *= -1;
562
563 rFont.SetSize( aFontSize );
564
565 if( ( mnWinExtX * mnWinExtY ) < 0 )
566 rFont.SetOrientation( 3600 - rFont.GetOrientation() );
567 }
568
569 //-----------------------------------------------------------------------------------
570
ImplMap(Polygon & rPolygon)571 Polygon& WinMtfOutput::ImplMap( Polygon& rPolygon )
572 {
573 sal_uInt16 nPoints = rPolygon.GetSize();
574 for ( sal_uInt16 i = 0; i < nPoints; i++ )
575 {
576 rPolygon[ i ] = ImplMap( rPolygon[ i ] );
577 }
578 return rPolygon;
579 }
580
581 //-----------------------------------------------------------------------------------
582
ImplMap(PolyPolygon & rPolyPolygon)583 PolyPolygon& WinMtfOutput::ImplMap( PolyPolygon& rPolyPolygon )
584 {
585 sal_uInt16 nPolys = rPolyPolygon.Count();
586 for ( sal_uInt16 i = 0; i < nPolys; ImplMap( rPolyPolygon[ i++ ] ) ) ;
587 return rPolyPolygon;
588 }
589
590 //-----------------------------------------------------------------------------------
591
SelectObject(sal_Int32 nIndex)592 void WinMtfOutput::SelectObject( sal_Int32 nIndex )
593 {
594 GDIObj* pGDIObj = NULL;
595
596 if ( nIndex & ENHMETA_STOCK_OBJECT )
597 pGDIObj = new GDIObj();
598 else
599 {
600 nIndex &= 0xffff; // zur Sicherheit: mehr als 65535 nicht zulassen
601
602 if ( (sal_uInt32)nIndex < vGDIObj.size() )
603 pGDIObj = vGDIObj[ nIndex ];
604 }
605
606 if( pGDIObj == NULL )
607 return;
608
609 if ( nIndex & ENHMETA_STOCK_OBJECT )
610 {
611 sal_uInt16 nStockId = (sal_uInt8)nIndex;
612 switch( nStockId )
613 {
614 case WHITE_BRUSH :
615 {
616 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ) ) );
617 }
618 break;
619 case LTGRAY_BRUSH :
620 {
621 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_LIGHTGRAY ) ) );
622 }
623 break;
624 case GRAY_BRUSH :
625 case DKGRAY_BRUSH :
626 {
627 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_GRAY ) ) );
628 }
629 break;
630 case BLACK_BRUSH :
631 {
632 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_BLACK ) ) );
633 }
634 break;
635 case NULL_BRUSH :
636 {
637 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_TRANSPARENT ), sal_True ) );
638 }
639 break;
640 case WHITE_PEN :
641 {
642 pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_WHITE ) ) );
643 }
644 break;
645 case BLACK_PEN :
646 {
647 pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_BLACK ) ) );
648 }
649 break;
650 case NULL_PEN :
651 {
652 pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_TRANSPARENT ), sal_True ) );
653 }
654 break;
655 default:
656 break;
657 }
658 }
659 if ( pGDIObj->pStyle )
660 {
661 switch( pGDIObj->eType )
662 {
663 case GDI_PEN :
664 maLineStyle = (WinMtfLineStyle*)pGDIObj->pStyle;
665 break;
666 case GDI_BRUSH :
667 {
668 maFillStyle = (WinMtfFillStyle*)pGDIObj->pStyle;
669 mbFillStyleSelected = sal_True;
670 }
671 break;
672 case GDI_FONT :
673 maFont = ((WinMtfFontStyle*)pGDIObj->pStyle)->aFont;
674 break;
675 default:
676 break; // -Wall many options not handled.
677 }
678 }
679 if ( nIndex & ENHMETA_STOCK_OBJECT )
680 delete pGDIObj;
681 }
682
683 //-----------------------------------------------------------------------------------
684
SetFont(const Font & rFont)685 void WinMtfOutput::SetFont( const Font& rFont )
686 {
687 maFont = rFont;
688 }
689
690 //-----------------------------------------------------------------------------------
691
GetFont() const692 const Font& WinMtfOutput::GetFont() const
693 {
694 return maFont;
695 }
696
697 //-----------------------------------------------------------------------------------
698
SetTextLayoutMode(const sal_uInt32 nTextLayoutMode)699 void WinMtfOutput::SetTextLayoutMode( const sal_uInt32 nTextLayoutMode )
700 {
701 mnTextLayoutMode = nTextLayoutMode;
702 }
703
704 //-----------------------------------------------------------------------------------
705
GetTextLayoutMode() const706 sal_uInt32 WinMtfOutput::GetTextLayoutMode() const
707 {
708 return mnTextLayoutMode;
709 }
710
711 //-----------------------------------------------------------------------------------
712
SetBkMode(sal_uInt32 nMode)713 void WinMtfOutput::SetBkMode( sal_uInt32 nMode )
714 {
715 mnBkMode = nMode;
716 }
717
718 //-----------------------------------------------------------------------------------
719
SetBkColor(const Color & rColor)720 void WinMtfOutput::SetBkColor( const Color& rColor )
721 {
722 maBkColor = rColor;
723 }
724
725 //-----------------------------------------------------------------------------------
726
SetTextColor(const Color & rColor)727 void WinMtfOutput::SetTextColor( const Color& rColor )
728 {
729 maTextColor = rColor;
730 }
731
732 //-----------------------------------------------------------------------------------
733
SetTextAlign(sal_uInt32 nAlign)734 void WinMtfOutput::SetTextAlign( sal_uInt32 nAlign )
735 {
736 mnTextAlign = nAlign;
737 }
738
739 //-----------------------------------------------------------------------------------
740
ImplResizeObjectArry(sal_uInt32 nNewEntrys)741 void WinMtfOutput::ImplResizeObjectArry( sal_uInt32 nNewEntrys )
742 {
743 sal_uInt32 i = vGDIObj.size();
744 vGDIObj.resize( nNewEntrys );
745 for ( ; i < nNewEntrys ; i++ )
746 vGDIObj[ i ] = NULL;
747 }
748
749 //-----------------------------------------------------------------------------------
750
ImplDrawClippedPolyPolygon(const PolyPolygon & rPolyPoly)751 void WinMtfOutput::ImplDrawClippedPolyPolygon( const PolyPolygon& rPolyPoly )
752 {
753 if ( rPolyPoly.Count() )
754 {
755 ImplSetNonPersistentLineColorTransparenz();
756 if ( rPolyPoly.Count() == 1 )
757 {
758 if ( rPolyPoly.IsRect() )
759 mpGDIMetaFile->AddAction( new MetaRectAction( rPolyPoly.GetBoundRect() ) );
760 else
761 {
762 Polygon aPoly( rPolyPoly[ 0 ] );
763 sal_uInt16 nCount = aPoly.GetSize();
764 if ( nCount )
765 {
766 if ( aPoly[ nCount - 1 ] != aPoly[ 0 ] )
767 {
768 Point aPoint( aPoly[ 0 ] );
769 aPoly.Insert( nCount, aPoint );
770 }
771 mpGDIMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
772 }
773 }
774 }
775 else
776 mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) );
777 }
778 }
779
780
781 //-----------------------------------------------------------------------------------
782
CreateObject(GDIObjectType eType,void * pStyle)783 void WinMtfOutput::CreateObject( GDIObjectType eType, void* pStyle )
784 {
785 if ( pStyle )
786 {
787 if ( eType == GDI_FONT )
788 {
789 ImplMap( ((WinMtfFontStyle*)pStyle)->aFont );
790 if (!((WinMtfFontStyle*)pStyle)->aFont.GetHeight() )
791 ((WinMtfFontStyle*)pStyle)->aFont.SetHeight( 423 ); // defaulting to 12pt
792 }
793 else if ( eType == GDI_PEN )
794 {
795 Size aSize( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetWidth(), 0 );
796 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetWidth( ImplMap( aSize ).Width() );
797 if ( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetStyle() == LINE_DASH )
798 {
799 aSize.Width() += 1;
800 long nDotLen = ImplMap( aSize ).Width();
801 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDistance( nDotLen );
802 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDotLen( nDotLen );
803 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDashLen( nDotLen * 4 );
804 }
805 }
806 }
807 sal_uInt32 nIndex;
808 for ( nIndex = 0; nIndex < vGDIObj.size(); nIndex++ )
809 {
810 if ( vGDIObj[ nIndex ] == NULL )
811 break;
812 }
813 if ( nIndex == vGDIObj.size() )
814 ImplResizeObjectArry( vGDIObj.size() + 16 );
815
816 vGDIObj[ nIndex ] = new GDIObj( eType, pStyle );
817 }
818
819 //-----------------------------------------------------------------------------------
820
CreateObject(sal_Int32 nIndex,GDIObjectType eType,void * pStyle)821 void WinMtfOutput::CreateObject( sal_Int32 nIndex, GDIObjectType eType, void* pStyle )
822 {
823 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
824 {
825 nIndex &= 0xffff; // zur Sicherheit: mehr als 65535 nicht zulassen
826 if ( pStyle )
827 {
828 if ( eType == GDI_FONT )
829 ImplMap( ((WinMtfFontStyle*)pStyle)->aFont );
830 else if ( eType == GDI_PEN )
831 {
832 Size aSize( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetWidth(), 0 );
833 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetWidth( ImplMap( aSize ).Width() );
834 if ( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetStyle() == LINE_DASH )
835 {
836 aSize.Width() += 1;
837 long nDotLen = ImplMap( aSize ).Width();
838 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDistance( nDotLen );
839 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDotLen( nDotLen );
840 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDashLen( nDotLen * 4 );
841 }
842 }
843 }
844 if ( (sal_uInt32)nIndex >= vGDIObj.size() )
845 ImplResizeObjectArry( nIndex + 16 );
846
847 if ( vGDIObj[ nIndex ] != NULL )
848 delete vGDIObj[ nIndex ];
849
850 vGDIObj[ nIndex ] = new GDIObj( eType, pStyle );
851 }
852 else
853 {
854 switch ( eType )
855 {
856 case GDI_PEN :
857 delete (WinMtfLineStyle*)pStyle;
858 break;
859 case GDI_BRUSH :
860 delete (WinMtfFillStyle*)pStyle;
861 break;
862 case GDI_FONT :
863 delete (WinMtfFontStyle*)pStyle;
864 break;
865
866 default:
867 DBG_ERROR( "unsupported style not deleted" );
868 break;
869 }
870 }
871 }
872
873 //-----------------------------------------------------------------------------------
874
DeleteObject(sal_Int32 nIndex)875 void WinMtfOutput::DeleteObject( sal_Int32 nIndex )
876 {
877 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
878 {
879 if ( (sal_uInt32)nIndex < vGDIObj.size() )
880 {
881 delete vGDIObj[ nIndex ];
882 vGDIObj[ nIndex ] = NULL;
883 }
884 }
885 }
886
887 //-----------------------------------------------------------------------------------
888
IntersectClipRect(const Rectangle & rRect)889 void WinMtfOutput::IntersectClipRect( const Rectangle& rRect )
890 {
891 aClipPath.IntersectClipRect( ImplMap( rRect ) );
892 }
893
894 //-----------------------------------------------------------------------------------
895
ExcludeClipRect(const Rectangle & rRect)896 void WinMtfOutput::ExcludeClipRect( const Rectangle& rRect )
897 {
898 aClipPath.ExcludeClipRect( ImplMap( rRect ) );
899 }
900
901 //-----------------------------------------------------------------------------------
902
MoveClipRegion(const Size & rSize)903 void WinMtfOutput::MoveClipRegion( const Size& rSize )
904 {
905 aClipPath.MoveClipRegion( ImplMap( rSize ) );
906 }
907
SetClipPath(const PolyPolygon & rPolyPolygon,sal_Int32 nClippingMode,sal_Bool bIsMapped)908 void WinMtfOutput::SetClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode, sal_Bool bIsMapped )
909 {
910 if ( bIsMapped )
911 aClipPath.SetClipPath( rPolyPolygon, nClippingMode );
912 else
913 {
914 PolyPolygon aPP( rPolyPolygon );
915 aClipPath.SetClipPath( ImplMap( aPP ), nClippingMode );
916 }
917 }
918
919 //-----------------------------------------------------------------------------------
920 //-----------------------------------------------------------------------------------
921 //-----------------------------------------------------------------------------------
922
WinMtfOutput(GDIMetaFile & rGDIMetaFile)923 WinMtfOutput::WinMtfOutput( GDIMetaFile& rGDIMetaFile ) :
924 mnLatestTextAlign ( 0 ),
925 mnTextAlign ( TA_LEFT | TA_TOP | TA_NOUPDATECP ),
926 maLatestBkColor ( 0x12345678 ),
927 maBkColor ( COL_WHITE ),
928 mnLatestTextLayoutMode( TEXT_LAYOUT_DEFAULT ),
929 mnTextLayoutMode ( TEXT_LAYOUT_DEFAULT ),
930 mnLatestBkMode ( 0 ),
931 mnBkMode ( OPAQUE ),
932 meLatestRasterOp ( ROP_INVERT ),
933 meRasterOp ( ROP_OVERPAINT ),
934 maActPos ( Point() ),
935 mbNopMode ( sal_False ),
936 mbFillStyleSelected ( sal_False ),
937 mnGfxMode ( GM_COMPATIBLE ),
938 mnMapMode ( MM_TEXT ),
939 mnDevOrgX ( 0 ),
940 mnDevOrgY ( 0 ),
941 mnDevWidth ( 1 ),
942 mnDevHeight ( 1 ),
943 mnWinOrgX ( 0 ),
944 mnWinOrgY ( 0 ),
945 mnWinExtX ( 1 ),
946 mnWinExtY ( 1 ),
947 mnPixX ( 100 ),
948 mnPixY ( 100 ),
949 mnMillX ( 1 ),
950 mnMillY ( 1 ),
951 mpGDIMetaFile ( &rGDIMetaFile )
952 {
953 mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_CLIPREGION ) ); // The original clipregion has to be on top
954 // of the stack so it can always be restored
955 // this is necessary to be able to support
956 // SetClipRgn( NULL ) and similar ClipRgn actions (SJ)
957
958 maFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "Arial" )) ); // sj: #i57205#, we do have some scaling problems if using
959 maFont.SetCharSet( gsl_getSystemTextEncoding() ); // the default font then most times a x11 font is used, we
960 maFont.SetHeight( 423 ); // will prevent this defining a font
961
962 maLatestLineStyle.aLineColor = Color( 0x12, 0x34, 0x56 );
963 maLatestFillStyle.aFillColor = Color( 0x12, 0x34, 0x56 );
964
965 mnRop = R2_BLACK + 1;
966 SetRasterOp( R2_BLACK );
967 };
968
969 //-----------------------------------------------------------------------------------
970
~WinMtfOutput()971 WinMtfOutput::~WinMtfOutput()
972 {
973 mpGDIMetaFile->AddAction( new MetaPopAction() );
974 mpGDIMetaFile->SetPrefMapMode( MAP_100TH_MM );
975 if ( mrclFrame.IsEmpty() )
976 mpGDIMetaFile->SetPrefSize( Size( mnDevWidth, mnDevHeight ) );
977 else
978 mpGDIMetaFile->SetPrefSize( mrclFrame.GetSize() );
979
980 for ( sal_uInt32 i = 0; i < vGDIObj.size(); i++ )
981 delete vGDIObj[ i ];
982 };
983
984 //-----------------------------------------------------------------------------------
985
UpdateClipRegion()986 void WinMtfOutput::UpdateClipRegion()
987 {
988 if ( aClipPath.bNeedsUpdate )
989 {
990 aClipPath.bNeedsUpdate = sal_False;
991
992 mpGDIMetaFile->AddAction( new MetaPopAction() ); // taking the orignal clipregion
993 mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_CLIPREGION ) ); //
994
995 switch ( aClipPath.GetType() )
996 {
997 case RECTANGLE :
998 case COMPLEX :
999 {
1000 // we will not generate a RegionClipRegion Action, because this action
1001 // cannot be saved to the wmf format - saving to wmf always happens
1002 // if the placeholder graphic for ole objects is generated. (SJ)
1003
1004 // Region aClipRegion( aClipPath.GetClipPath() );
1005 // mpGDIMetaFile->AddAction( new MetaISectRegionClipRegionAction( aClipRegion ) );
1006
1007 Rectangle aClipRect( aClipPath.GetClipPath().GetBoundRect() );
1008 mpGDIMetaFile->AddAction( new MetaISectRectClipRegionAction( aClipRect ) );
1009 }
1010 break;
1011 case EMPTY:
1012 break; // -Wall not handled.
1013 }
1014 }
1015 }
1016
1017 //-----------------------------------------------------------------------------------
1018
ImplSetNonPersistentLineColorTransparenz()1019 void WinMtfOutput::ImplSetNonPersistentLineColorTransparenz()
1020 {
1021 Color aColor( COL_TRANSPARENT);
1022 WinMtfLineStyle aTransparentLine( aColor, sal_True );
1023 if ( ! ( maLatestLineStyle == aTransparentLine ) )
1024 {
1025 maLatestLineStyle = aTransparentLine;
1026 mpGDIMetaFile->AddAction( new MetaLineColorAction( aTransparentLine.aLineColor, !aTransparentLine.bTransparent ) );
1027 }
1028 }
1029
1030 //-----------------------------------------------------------------------------------
1031
UpdateLineStyle()1032 void WinMtfOutput::UpdateLineStyle()
1033 {
1034 if (!( maLatestLineStyle == maLineStyle ) )
1035 {
1036 maLatestLineStyle = maLineStyle;
1037 mpGDIMetaFile->AddAction( new MetaLineColorAction( maLineStyle.aLineColor, !maLineStyle.bTransparent ) );
1038 }
1039 }
1040
1041 //-----------------------------------------------------------------------------------
1042
UpdateFillStyle()1043 void WinMtfOutput::UpdateFillStyle()
1044 {
1045 if ( !mbFillStyleSelected ) // SJ: #i57205# taking care of bkcolor if no brush is selected
1046 maFillStyle = WinMtfFillStyle( maBkColor, mnBkMode == TRANSPARENT );
1047 if (!( maLatestFillStyle == maFillStyle ) )
1048 {
1049 maLatestFillStyle = maFillStyle;
1050 mpGDIMetaFile->AddAction( new MetaFillColorAction( maFillStyle.aFillColor, !maFillStyle.bTransparent ) );
1051 }
1052 }
1053
1054 //-----------------------------------------------------------------------------------
1055
SetRasterOp(sal_uInt32 nRasterOp)1056 sal_uInt32 WinMtfOutput::SetRasterOp( sal_uInt32 nRasterOp )
1057 {
1058 sal_uInt32 nRetROP = mnRop;
1059 if ( nRasterOp != mnRop )
1060 {
1061 mnRop = nRasterOp;
1062 static WinMtfFillStyle aNopFillStyle;
1063 static WinMtfLineStyle aNopLineStyle;
1064
1065 if ( mbNopMode && ( nRasterOp != R2_NOP ) )
1066 { // beim uebergang von R2_NOP auf anderen Modus
1067 // gesetzten Pen und Brush aktivieren
1068 maFillStyle = aNopFillStyle;
1069 maLineStyle = aNopLineStyle;
1070 mbNopMode = sal_False;
1071 }
1072 switch( nRasterOp )
1073 {
1074 case R2_NOT:
1075 meRasterOp = ROP_INVERT;
1076 break;
1077
1078 case R2_XORPEN:
1079 meRasterOp = ROP_XOR;
1080 break;
1081
1082 case R2_NOP:
1083 {
1084 meRasterOp = ROP_OVERPAINT;
1085 if( mbNopMode == sal_False )
1086 {
1087 aNopFillStyle = maFillStyle;
1088 aNopLineStyle = maLineStyle;
1089 maFillStyle = WinMtfFillStyle( Color( COL_TRANSPARENT ), sal_True );
1090 maLineStyle = WinMtfLineStyle( Color( COL_TRANSPARENT ), sal_True );
1091 mbNopMode = sal_True;
1092 }
1093 }
1094 break;
1095
1096 default:
1097 meRasterOp = ROP_OVERPAINT;
1098 break;
1099 }
1100 }
1101 if ( nRetROP != nRasterOp )
1102 mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
1103 return nRetROP;
1104 };
1105
1106 //-----------------------------------------------------------------------------------
1107
StrokeAndFillPath(sal_Bool bStroke,sal_Bool bFill)1108 void WinMtfOutput::StrokeAndFillPath( sal_Bool bStroke, sal_Bool bFill )
1109 {
1110 if ( aPathObj.Count() )
1111 {
1112 UpdateClipRegion();
1113 UpdateLineStyle();
1114 UpdateFillStyle();
1115 if ( bFill )
1116 {
1117 if ( !bStroke )
1118 {
1119 mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
1120 mpGDIMetaFile->AddAction( new MetaLineColorAction( Color(), sal_False ) );
1121 }
1122 if ( aPathObj.Count() == 1 )
1123 mpGDIMetaFile->AddAction( new MetaPolygonAction( aPathObj.GetObject( 0 ) ) );
1124 else
1125 mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aPathObj ) );
1126
1127 if ( !bStroke )
1128 mpGDIMetaFile->AddAction( new MetaPopAction() );
1129 }
1130 else
1131 {
1132 sal_uInt16 i, nCount = aPathObj.Count();
1133 for ( i = 0; i < nCount; i++ )
1134 mpGDIMetaFile->AddAction( new MetaPolyLineAction( aPathObj[ i ], maLineStyle.aLineInfo ) );
1135 }
1136 ClearPath();
1137 }
1138 }
1139
1140 //-----------------------------------------------------------------------------------
1141
DrawPixel(const Point & rSource,const Color & rColor)1142 void WinMtfOutput::DrawPixel( const Point& rSource, const Color& rColor )
1143 {
1144 mpGDIMetaFile->AddAction( new MetaPixelAction( ImplMap( rSource), rColor ) );
1145 }
1146
1147 //-----------------------------------------------------------------------------------
1148
MoveTo(const Point & rPoint,sal_Bool bRecordPath)1149 void WinMtfOutput::MoveTo( const Point& rPoint, sal_Bool bRecordPath )
1150 {
1151 Point aDest( ImplMap( rPoint ) );
1152 if ( bRecordPath )
1153 aPathObj.AddPoint( aDest );
1154 maActPos = aDest;
1155 }
1156
1157 //-----------------------------------------------------------------------------------
1158
LineTo(const Point & rPoint,sal_Bool bRecordPath)1159 void WinMtfOutput::LineTo( const Point& rPoint, sal_Bool bRecordPath )
1160 {
1161 UpdateClipRegion();
1162
1163 Point aDest( ImplMap( rPoint ) );
1164 if ( bRecordPath )
1165 aPathObj.AddPoint( aDest );
1166 else
1167 {
1168 UpdateLineStyle();
1169 mpGDIMetaFile->AddAction( new MetaLineAction( maActPos, aDest, maLineStyle.aLineInfo ) );
1170 }
1171 maActPos = aDest;
1172 }
1173
1174 //-----------------------------------------------------------------------------------
1175
DrawLine(const Point & rSource,const Point & rDest)1176 void WinMtfOutput::DrawLine( const Point& rSource, const Point& rDest )
1177 {
1178 UpdateClipRegion();
1179 UpdateLineStyle();
1180 mpGDIMetaFile->AddAction( new MetaLineAction( ImplMap( rSource), ImplMap( rDest ), maLineStyle.aLineInfo ) );
1181 }
1182
1183 //-----------------------------------------------------------------------------------
1184
DrawRect(const Rectangle & rRect,sal_Bool bEdge)1185 void WinMtfOutput::DrawRect( const Rectangle& rRect, sal_Bool bEdge )
1186 {
1187 UpdateClipRegion();
1188 UpdateFillStyle();
1189
1190 if ( aClipPath.GetType() == COMPLEX )
1191 {
1192 Polygon aPoly( ImplMap( rRect ) );
1193 PolyPolygon aPolyPolyRect( aPoly );
1194 PolyPolygon aDest;
1195 aClipPath.GetClipPath().GetIntersection( aPolyPolyRect, aDest );
1196 ImplDrawClippedPolyPolygon( aDest );
1197 }
1198 else
1199 {
1200 if ( bEdge )
1201 {
1202 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
1203 {
1204 ImplSetNonPersistentLineColorTransparenz();
1205 mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
1206 UpdateLineStyle();
1207 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( ImplMap( rRect ) ),maLineStyle.aLineInfo ) );
1208 }
1209 else
1210 {
1211 UpdateLineStyle();
1212 mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
1213 }
1214 }
1215 else
1216 {
1217 ImplSetNonPersistentLineColorTransparenz();
1218 mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
1219 }
1220 }
1221 }
1222
1223 //-----------------------------------------------------------------------------------
1224
DrawRoundRect(const Rectangle & rRect,const Size & rSize)1225 void WinMtfOutput::DrawRoundRect( const Rectangle& rRect, const Size& rSize )
1226 {
1227 UpdateClipRegion();
1228 UpdateLineStyle();
1229 UpdateFillStyle();
1230 mpGDIMetaFile->AddAction( new MetaRoundRectAction( ImplMap( rRect ), labs( ImplMap( rSize ).Width() ), labs( ImplMap( rSize ).Height() ) ) );
1231 }
1232
1233 //-----------------------------------------------------------------------------------
1234
DrawEllipse(const Rectangle & rRect)1235 void WinMtfOutput::DrawEllipse( const Rectangle& rRect )
1236 {
1237 UpdateClipRegion();
1238 UpdateFillStyle();
1239
1240 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
1241 {
1242 Point aCenter( ImplMap( rRect.Center() ) );
1243 Size aRad( ImplMap( Size( rRect.GetWidth() / 2, rRect.GetHeight() / 2 ) ) );
1244
1245 ImplSetNonPersistentLineColorTransparenz();
1246 mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
1247 UpdateLineStyle();
1248 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
1249 }
1250 else
1251 {
1252 UpdateLineStyle();
1253 mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
1254 }
1255 }
1256
1257 //-----------------------------------------------------------------------------------
1258
DrawArc(const Rectangle & rRect,const Point & rStart,const Point & rEnd,sal_Bool bTo)1259 void WinMtfOutput::DrawArc( const Rectangle& rRect, const Point& rStart, const Point& rEnd, sal_Bool bTo )
1260 {
1261 UpdateClipRegion();
1262 UpdateLineStyle();
1263 UpdateFillStyle();
1264
1265 Rectangle aRect( ImplMap( rRect ) );
1266 Point aStart( ImplMap( rStart ) );
1267 Point aEnd( ImplMap( rEnd ) );
1268
1269 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
1270 {
1271 if ( aStart == aEnd )
1272 { // SJ: #i53768# if start & end is identical, then we have to draw a full ellipse
1273 Point aCenter( aRect.Center() );
1274 Size aRad( aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
1275
1276 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
1277 }
1278 else
1279 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_ARC ), maLineStyle.aLineInfo ) );
1280 }
1281 else
1282 mpGDIMetaFile->AddAction( new MetaArcAction( aRect, aStart, aEnd ) );
1283
1284 if ( bTo )
1285 maActPos = aEnd;
1286 }
1287
1288 //-----------------------------------------------------------------------------------
1289
DrawPie(const Rectangle & rRect,const Point & rStart,const Point & rEnd)1290 void WinMtfOutput::DrawPie( const Rectangle& rRect, const Point& rStart, const Point& rEnd )
1291 {
1292 UpdateClipRegion();
1293 UpdateFillStyle();
1294
1295 Rectangle aRect( ImplMap( rRect ) );
1296 Point aStart( ImplMap( rStart ) );
1297 Point aEnd( ImplMap( rEnd ) );
1298
1299 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
1300 {
1301 ImplSetNonPersistentLineColorTransparenz();
1302 mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
1303 UpdateLineStyle();
1304 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_PIE ), maLineStyle.aLineInfo ) );
1305 }
1306 else
1307 {
1308 UpdateLineStyle();
1309 mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
1310 }
1311 }
1312
1313 //-----------------------------------------------------------------------------------
1314
DrawChord(const Rectangle & rRect,const Point & rStart,const Point & rEnd)1315 void WinMtfOutput::DrawChord( const Rectangle& rRect, const Point& rStart, const Point& rEnd )
1316 {
1317 UpdateClipRegion();
1318 UpdateFillStyle();
1319
1320 Rectangle aRect( ImplMap( rRect ) );
1321 Point aStart( ImplMap( rStart ) );
1322 Point aEnd( ImplMap( rEnd ) );
1323
1324 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
1325 {
1326 ImplSetNonPersistentLineColorTransparenz();
1327 mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
1328 UpdateLineStyle();
1329 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_CHORD ), maLineStyle.aLineInfo ) );
1330 }
1331 else
1332 {
1333 UpdateLineStyle();
1334 mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
1335 }
1336 }
1337
1338 //-----------------------------------------------------------------------------------
1339
DrawPolygon(Polygon & rPolygon,sal_Bool bRecordPath)1340 void WinMtfOutput::DrawPolygon( Polygon& rPolygon, sal_Bool bRecordPath )
1341 {
1342 UpdateClipRegion();
1343 ImplMap( rPolygon );
1344 if ( bRecordPath )
1345 aPathObj.AddPolygon( rPolygon );
1346 else
1347 {
1348 UpdateFillStyle();
1349
1350 if ( aClipPath.GetType() == COMPLEX )
1351 {
1352 PolyPolygon aPolyPoly( rPolygon );
1353 PolyPolygon aDest;
1354 aClipPath.GetClipPath().GetIntersection( aPolyPoly, aDest );
1355 ImplDrawClippedPolyPolygon( aDest );
1356 }
1357 else
1358 {
1359 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
1360 {
1361 sal_uInt16 nCount = rPolygon.GetSize();
1362 if ( nCount )
1363 {
1364 if ( rPolygon[ nCount - 1 ] != rPolygon[ 0 ] )
1365 {
1366 Point aPoint( rPolygon[ 0 ] );
1367 rPolygon.Insert( nCount, aPoint );
1368 }
1369 }
1370 ImplSetNonPersistentLineColorTransparenz();
1371 mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
1372 UpdateLineStyle();
1373 mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
1374 }
1375 else
1376 {
1377 UpdateLineStyle();
1378 mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
1379 }
1380 }
1381 }
1382 }
1383
1384 //-----------------------------------------------------------------------------------
1385
DrawPolyPolygon(PolyPolygon & rPolyPolygon,sal_Bool bRecordPath)1386 void WinMtfOutput::DrawPolyPolygon( PolyPolygon& rPolyPolygon, sal_Bool bRecordPath )
1387 {
1388 UpdateClipRegion();
1389
1390 ImplMap( rPolyPolygon );
1391
1392 if ( bRecordPath )
1393 aPathObj.AddPolyPolygon( rPolyPolygon );
1394 else
1395 {
1396 UpdateFillStyle();
1397
1398 if ( aClipPath.GetType() == COMPLEX )
1399 {
1400 PolyPolygon aDest;
1401 aClipPath.GetClipPath().GetIntersection( rPolyPolygon, aDest );
1402 ImplDrawClippedPolyPolygon( aDest );
1403 }
1404 else
1405 {
1406 UpdateLineStyle();
1407 mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPolygon ) );
1408 }
1409 }
1410 }
1411
1412 //-----------------------------------------------------------------------------------
1413
DrawPolyLine(Polygon & rPolygon,sal_Bool bTo,sal_Bool bRecordPath)1414 void WinMtfOutput::DrawPolyLine( Polygon& rPolygon, sal_Bool bTo, sal_Bool bRecordPath )
1415 {
1416 UpdateClipRegion();
1417
1418 ImplMap( rPolygon );
1419 if ( bTo )
1420 {
1421 rPolygon[ 0 ] = maActPos;
1422 maActPos = rPolygon[ rPolygon.GetSize() - 1 ];
1423 }
1424 if ( bRecordPath )
1425 aPathObj.AddPolyLine( rPolygon );
1426 else
1427 {
1428 UpdateLineStyle();
1429 mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
1430 }
1431 }
1432
1433 //-----------------------------------------------------------------------------------
1434
DrawPolyBezier(Polygon & rPolygon,sal_Bool bTo,sal_Bool bRecordPath)1435 void WinMtfOutput::DrawPolyBezier( Polygon& rPolygon, sal_Bool bTo, sal_Bool bRecordPath )
1436 {
1437 UpdateClipRegion();
1438
1439 sal_uInt16 nPoints = rPolygon.GetSize();
1440 if ( ( nPoints >= 4 ) && ( ( ( nPoints - 4 ) % 3 ) == 0 ) )
1441 {
1442 ImplMap( rPolygon );
1443 if ( bTo )
1444 {
1445 rPolygon[ 0 ] = maActPos;
1446 maActPos = rPolygon[ nPoints - 1 ];
1447 }
1448 sal_uInt16 i;
1449 for ( i = 0; ( i + 2 ) < nPoints; )
1450 {
1451 rPolygon.SetFlags( i++, POLY_NORMAL );
1452 rPolygon.SetFlags( i++, POLY_CONTROL );
1453 rPolygon.SetFlags( i++, POLY_CONTROL );
1454 }
1455 if ( bRecordPath )
1456 aPathObj.AddPolyLine( rPolygon );
1457 else
1458 {
1459 UpdateLineStyle();
1460 mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
1461 }
1462 }
1463 }
1464
1465 //-----------------------------------------------------------------------------------
1466
DrawText(Point & rPosition,String & rText,sal_Int32 * pDXArry,sal_Bool bRecordPath,sal_Int32 nGfxMode)1467 void WinMtfOutput::DrawText( Point& rPosition, String& rText, sal_Int32* pDXArry, sal_Bool bRecordPath, sal_Int32 nGfxMode )
1468 {
1469 UpdateClipRegion();
1470 rPosition = ImplMap( rPosition );
1471 sal_Int32 nOldGfxMode = GetGfxMode();
1472 SetGfxMode( GM_COMPATIBLE );
1473
1474 if ( pDXArry )
1475 {
1476 sal_Int32 i, nSum, nLen = rText.Len();
1477
1478 for( i = 0, nSum = 0; i < nLen; i++ )
1479 {
1480 // #121382# Map DXArray using WorldTransform
1481 const Size aSize(ImplMap(Size( pDXArry[i], 0)));
1482 const basegfx::B2DVector aVector(aSize.Width(), aSize.Height());
1483 const sal_Int32 nTemp(basegfx::fround(aVector.getLength()));
1484 nSum += nTemp;
1485 pDXArry[ i ] = nSum;
1486 }
1487 }
1488 if ( mnLatestTextLayoutMode != mnTextLayoutMode )
1489 {
1490 mnLatestTextLayoutMode = mnTextLayoutMode;
1491 mpGDIMetaFile->AddAction( new MetaLayoutModeAction( mnTextLayoutMode ) );
1492 }
1493 SetGfxMode( nGfxMode );
1494 sal_Bool bChangeFont = sal_False;
1495 if ( mnLatestTextAlign != mnTextAlign )
1496 {
1497 bChangeFont = sal_True;
1498 mnLatestTextAlign = mnTextAlign;
1499 TextAlign eTextAlign;
1500 if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE )
1501 eTextAlign = ALIGN_BASELINE;
1502 else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM )
1503 eTextAlign = ALIGN_BOTTOM;
1504 else
1505 eTextAlign = ALIGN_TOP;
1506 mpGDIMetaFile->AddAction( new MetaTextAlignAction( eTextAlign ) );
1507 }
1508 if ( maLatestTextColor != maTextColor )
1509 {
1510 bChangeFont = sal_True;
1511 maLatestTextColor = maTextColor;
1512 mpGDIMetaFile->AddAction( new MetaTextColorAction( maTextColor ) );
1513 }
1514 sal_Bool bChangeFillColor = sal_False;
1515 if ( maLatestBkColor != maBkColor )
1516 {
1517 bChangeFillColor = sal_True;
1518 maLatestBkColor = maBkColor;
1519 }
1520 if ( mnLatestBkMode != mnBkMode )
1521 {
1522 bChangeFillColor = sal_True;
1523 mnLatestBkMode = mnBkMode;
1524 }
1525 if ( bChangeFillColor )
1526 {
1527 bChangeFont = sal_True;
1528 mpGDIMetaFile->AddAction( new MetaTextFillColorAction( maFont.GetFillColor(), !maFont.IsTransparent() ) );
1529 }
1530 Font aTmp( maFont );
1531 aTmp.SetColor( maTextColor );
1532 aTmp.SetFillColor( maBkColor );
1533
1534 if( mnBkMode == TRANSPARENT )
1535 aTmp.SetTransparent( sal_True );
1536 else
1537 aTmp.SetTransparent( sal_False );
1538
1539 if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE )
1540 aTmp.SetAlign( ALIGN_BASELINE );
1541 else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM )
1542 aTmp.SetAlign( ALIGN_BOTTOM );
1543 else
1544 aTmp.SetAlign( ALIGN_TOP );
1545
1546 if ( nGfxMode == GM_ADVANCED )
1547 {
1548 // check whether there is a font rotation applied via transformation
1549 Point aP1( ImplMap( Point() ) );
1550 Point aP2( ImplMap( Point( 0, 100 ) ) );
1551 aP2.X() -= aP1.X();
1552 aP2.Y() -= aP1.Y();
1553 double fX = aP2.X();
1554 double fY = aP2.Y();
1555 if ( fX )
1556 {
1557 double fOrientation = acos( fX / sqrt( fX * fX + fY * fY ) ) * 57.29577951308;
1558 if ( fY > 0 )
1559 fOrientation = 360 - fOrientation;
1560 fOrientation += 90;
1561 fOrientation *= 10;
1562 fOrientation += aTmp.GetOrientation();
1563 aTmp.SetOrientation( sal_Int16( fOrientation ) );
1564 }
1565 }
1566
1567 if( mnTextAlign & ( TA_UPDATECP | TA_RIGHT_CENTER ) )
1568 {
1569 // #117968# VirtualDevice is not thread safe, but filter is used in multithreading
1570 vos::OGuard aGuard( Application::GetSolarMutex() );
1571 VirtualDevice aVDev;
1572 sal_Int32 nTextWidth;
1573
1574 aVDev.SetMapMode( MapMode( MAP_100TH_MM ) );
1575 aVDev.SetFont( maFont );
1576
1577 if( pDXArry )
1578 {
1579 sal_uInt32 nLen = rText.Len();
1580 nTextWidth = aVDev.GetTextWidth( rText.GetChar( (sal_uInt16)( nLen - 1 ) ) );
1581 if( nLen > 1 )
1582 nTextWidth += pDXArry[ nLen - 2 ];
1583 }
1584 else
1585 nTextWidth = aVDev.GetTextWidth( rText );
1586
1587 if( mnTextAlign & TA_UPDATECP )
1588 rPosition = maActPos;
1589
1590 if ( mnTextAlign & TA_RIGHT_CENTER )
1591 {
1592 double fLenght = ( ( mnTextAlign & TA_RIGHT_CENTER ) == TA_RIGHT ) ? nTextWidth : nTextWidth >> 1;
1593 rPosition.X() -= (sal_Int32)( fLenght * cos( maFont.GetOrientation() * F_PI1800 ) );
1594 rPosition.Y() -= (sal_Int32)(-( fLenght * sin( maFont.GetOrientation() * F_PI1800 ) ) );
1595 }
1596
1597 if( mnTextAlign & TA_UPDATECP )
1598 maActPos.X() = rPosition.X() + nTextWidth;
1599 }
1600 if ( bChangeFont || ( maLatestFont != aTmp ) )
1601 {
1602 maLatestFont = aTmp;
1603 mpGDIMetaFile->AddAction( new MetaFontAction( aTmp ) );
1604 mpGDIMetaFile->AddAction( new MetaTextAlignAction( aTmp.GetAlign() ) );
1605 mpGDIMetaFile->AddAction( new MetaTextColorAction( aTmp.GetColor() ) );
1606 mpGDIMetaFile->AddAction( new MetaTextFillColorAction( aTmp.GetFillColor(), !aTmp.IsTransparent() ) );
1607 }
1608 if ( bRecordPath )
1609 {
1610 // ToDo
1611 }
1612 else
1613 {
1614 /* because text without dx array is badly scaled, we
1615 will create such an array if necessary */
1616 sal_Int32* pDX = pDXArry;
1617 if ( !pDXArry )
1618 {
1619 // #117968# VirtualDevice is not thread safe, but filter is used in multithreading
1620 vos::OGuard aGuard( Application::GetSolarMutex() );
1621 VirtualDevice aVDev;
1622
1623 pDX = new sal_Int32[ rText.Len() ];
1624 aVDev.SetMapMode( MAP_100TH_MM );
1625 aVDev.SetFont( maLatestFont );
1626 aVDev.GetTextArray( rText, pDX, 0, STRING_LEN );
1627 }
1628 mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition, rText, pDX, 0, STRING_LEN ) );
1629 if ( !pDXArry ) // this means we have created our own array
1630 delete[] pDX; // which must be deleted
1631 }
1632 SetGfxMode( nOldGfxMode );
1633 }
1634
1635 //-----------------------------------------------------------------------------------
1636
ImplDrawBitmap(const Point & rPos,const Size & rSize,const BitmapEx rBitmap)1637 void WinMtfOutput::ImplDrawBitmap( const Point& rPos, const Size& rSize, const BitmapEx rBitmap )
1638 {
1639 BitmapEx aBmpEx( rBitmap );
1640 if ( aClipPath.GetType() == COMPLEX )
1641 {
1642 VirtualDevice aVDev;
1643 MapMode aMapMode( MAP_100TH_MM );
1644 aMapMode.SetOrigin( Point( -rPos.X(), -rPos.Y() ) );
1645 const Size aOutputSizePixel( aVDev.LogicToPixel( rSize, aMapMode ) );
1646 const Size aSizePixel( rBitmap.GetSizePixel() );
1647 if ( aOutputSizePixel.Width() && aOutputSizePixel.Height() )
1648 {
1649 aMapMode.SetScaleX( Fraction( aSizePixel.Width(), aOutputSizePixel.Width() ) );
1650 aMapMode.SetScaleY( Fraction( aSizePixel.Height(), aOutputSizePixel.Height() ) );
1651 }
1652 aVDev.SetMapMode( aMapMode );
1653 aVDev.SetOutputSizePixel( aSizePixel );
1654 aVDev.SetFillColor( Color( COL_BLACK ) );
1655 const PolyPolygon aClip( aClipPath.GetClipPath() );
1656 aVDev.DrawPolyPolygon( aClip );
1657 const Point aEmptyPoint;
1658
1659 // #i50672# Extract whole VDev content (to match size of rBitmap)
1660 aVDev.EnableMapMode( sal_False );
1661 Bitmap aMask( aVDev.GetBitmap( aEmptyPoint, aSizePixel ).CreateMask( Color( COL_WHITE ) ) );
1662
1663 if ( aBmpEx.IsTransparent() )
1664 {
1665 if ( rBitmap.GetTransparentColor() == Color( COL_WHITE ) )
1666 aMask.CombineSimple( rBitmap.GetMask(), BMP_COMBINE_OR );
1667 else
1668 aMask.CombineSimple( rBitmap.GetMask(), BMP_COMBINE_AND );
1669 aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask );
1670 }
1671 else
1672 aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask );
1673 }
1674 if ( aBmpEx.IsTransparent() )
1675 mpGDIMetaFile->AddAction( new MetaBmpExScaleAction( rPos, rSize, aBmpEx ) );
1676 else
1677 mpGDIMetaFile->AddAction( new MetaBmpScaleAction( rPos, rSize, aBmpEx.GetBitmap() ) );
1678 }
1679
1680 //-----------------------------------------------------------------------------------
1681
ResolveBitmapActions(List & rSaveList)1682 void WinMtfOutput::ResolveBitmapActions( List& rSaveList )
1683 {
1684 UpdateClipRegion();
1685
1686 sal_uInt32 nObjects = rSaveList.Count();
1687 sal_uInt32 nObjectsLeft = nObjects;
1688
1689 while ( nObjectsLeft )
1690 {
1691 sal_uInt32 i, nObjectsOfSameSize = 0;
1692 sal_uInt32 nObjectStartIndex = nObjects - nObjectsLeft;
1693
1694 BSaveStruct* pSave = (BSaveStruct*)rSaveList.GetObject( nObjectStartIndex );
1695 Rectangle aRect( pSave->aOutRect );
1696
1697 for ( i = nObjectStartIndex; i < nObjects; )
1698 {
1699 nObjectsOfSameSize++;
1700 if ( ++i < nObjects )
1701 {
1702 pSave = (BSaveStruct*)rSaveList.GetObject( i );
1703 if ( pSave->aOutRect != aRect )
1704 break;
1705 }
1706 }
1707 Point aPos( ImplMap( aRect.TopLeft() ) );
1708 Size aSize( ImplMap( aRect.GetSize() ) );
1709
1710 for ( i = nObjectStartIndex; i < ( nObjectStartIndex + nObjectsOfSameSize ); i++ )
1711 {
1712 pSave = (BSaveStruct*)rSaveList.GetObject( i );
1713
1714 sal_uInt32 nWinRop = pSave->nWinRop;
1715 sal_uInt8 nRasterOperation = (sal_uInt8)( nWinRop >> 16 );
1716
1717 sal_uInt32 nUsed = 0;
1718 if ( ( nRasterOperation & 0xf ) != ( nRasterOperation >> 4 ) )
1719 nUsed |= 1; // pattern is used
1720 if ( ( nRasterOperation & 0x33 ) != ( ( nRasterOperation & 0xcc ) >> 2 ) )
1721 nUsed |= 2; // source is used
1722 if ( ( nRasterOperation & 0xaa ) != ( ( nRasterOperation & 0x55 ) << 1 ) )
1723 nUsed |= 4; // destination is used
1724
1725 if ( (nUsed & 1) && (( nUsed & 2 ) == 0) )
1726 { // patterns aren't well supported yet
1727 sal_uInt32 nOldRop = SetRasterOp( ROP_OVERPAINT ); // in this case nRasterOperation is either 0 or 0xff
1728 UpdateFillStyle();
1729 DrawRect( aRect, sal_False );
1730 SetRasterOp( nOldRop );
1731 }
1732 else
1733 {
1734 sal_Bool bDrawn = sal_False;
1735
1736 if ( i == nObjectStartIndex ) // optimizing, sometimes it is possible to create just one transparent bitmap
1737 {
1738 if ( nObjectsOfSameSize == 2 )
1739 {
1740 BSaveStruct* pSave2 = (BSaveStruct*)rSaveList.GetObject( i + 1 );
1741 if ( ( pSave->aBmp.GetPrefSize() == pSave2->aBmp.GetPrefSize() ) &&
1742 ( pSave->aBmp.GetPrefMapMode() == pSave2->aBmp.GetPrefMapMode() ) )
1743 {
1744 // TODO: Strictly speaking, we should
1745 // check whether mask is monochrome, and
1746 // whether image is black (upper branch)
1747 // or white (lower branch). Otherwise, the
1748 // effect is not the same as a masked
1749 // bitmap.
1750 if ( ( nWinRop == SRCPAINT ) && ( pSave2->nWinRop == SRCAND ) )
1751 {
1752 Bitmap aMask( pSave->aBmp ); aMask.Invert();
1753 BitmapEx aBmpEx( pSave2->aBmp, aMask );
1754 ImplDrawBitmap( aPos, aSize, aBmpEx );
1755 bDrawn = sal_True;
1756 i++;
1757 }
1758 // #i20085# This is just the other way
1759 // around as above. Only difference: mask
1760 // is inverted
1761 else if ( ( nWinRop == SRCAND ) && ( pSave2->nWinRop == SRCPAINT ) )
1762 {
1763 Bitmap aMask( pSave->aBmp );
1764 BitmapEx aBmpEx( pSave2->aBmp, aMask );
1765 ImplDrawBitmap( aPos, aSize, aBmpEx );
1766 bDrawn = sal_True;
1767 i++;
1768 }
1769 }
1770 }
1771 }
1772
1773 if ( !bDrawn )
1774 {
1775 Push();
1776 sal_uInt32 nOldRop = SetRasterOp( R2_COPYPEN );
1777 Bitmap aBitmap( pSave->aBmp );
1778 sal_uInt32 nOperation = ( nRasterOperation & 0xf );
1779 switch( nOperation )
1780 {
1781 case 0x1 :
1782 case 0xe :
1783 {
1784 SetRasterOp( R2_XORPEN );
1785 ImplDrawBitmap( aPos, aSize, aBitmap );
1786 SetRasterOp( R2_COPYPEN );
1787 Bitmap aMask( aBitmap );
1788 aMask.Invert();
1789 BitmapEx aBmpEx( aBitmap, aMask );
1790 ImplDrawBitmap( aPos, aSize, aBmpEx );
1791 if ( nOperation == 0x1 )
1792 {
1793 SetRasterOp( R2_NOT );
1794 DrawRect( aRect, sal_False );
1795 }
1796 }
1797 break;
1798 case 0x7 :
1799 case 0x8 :
1800 {
1801 Bitmap aMask( aBitmap );
1802 if ( ( nUsed & 1 ) && ( nRasterOperation & 0xb0 ) == 0xb0 ) // pattern used
1803 {
1804 aBitmap.Convert( BMP_CONVERSION_24BIT );
1805 aBitmap.Erase( maFillStyle.aFillColor );
1806 }
1807 BitmapEx aBmpEx( aBitmap, aMask );
1808 ImplDrawBitmap( aPos, aSize, aBmpEx );
1809 if ( nOperation == 0x7 )
1810 {
1811 SetRasterOp( R2_NOT );
1812 DrawRect( aRect, sal_False );
1813 }
1814 }
1815 break;
1816
1817 case 0x4 :
1818 case 0xb :
1819 {
1820 SetRasterOp( R2_NOT );
1821 DrawRect( aRect, sal_False );
1822 SetRasterOp( R2_COPYPEN );
1823 Bitmap aMask( aBitmap );
1824 aBitmap.Invert();
1825 BitmapEx aBmpEx( aBitmap, aMask );
1826 ImplDrawBitmap( aPos, aSize, aBmpEx );
1827 SetRasterOp( R2_XORPEN );
1828 ImplDrawBitmap( aPos, aSize, aBitmap );
1829 if ( nOperation == 0xb )
1830 {
1831 SetRasterOp( R2_NOT );
1832 DrawRect( aRect, sal_False );
1833 }
1834 }
1835 break;
1836
1837 case 0x2 :
1838 case 0xd :
1839 {
1840 Bitmap aMask( aBitmap );
1841 aMask.Invert();
1842 BitmapEx aBmpEx( aBitmap, aMask );
1843 ImplDrawBitmap( aPos, aSize, aBmpEx );
1844 SetRasterOp( R2_XORPEN );
1845 ImplDrawBitmap( aPos, aSize, aBitmap );
1846 if ( nOperation == 0xd )
1847 {
1848 SetRasterOp( R2_NOT );
1849 DrawRect( aRect, sal_False );
1850 }
1851 }
1852 break;
1853 case 0x6 :
1854 case 0x9 :
1855 {
1856 SetRasterOp( R2_XORPEN );
1857 ImplDrawBitmap( aPos, aSize, aBitmap );
1858 if ( nOperation == 0x9 )
1859 {
1860 SetRasterOp( R2_NOT );
1861 DrawRect( aRect, sal_False );
1862 }
1863 }
1864 break;
1865
1866 case 0x0 : // WHITENESS
1867 case 0xf : // BLACKNESS
1868 { // in this case nRasterOperation is either 0 or 0xff
1869 maFillStyle = WinMtfFillStyle( Color( nRasterOperation, nRasterOperation, nRasterOperation ) );
1870 UpdateFillStyle();
1871 DrawRect( aRect, sal_False );
1872 }
1873 break;
1874
1875 case 0x3 : // only source is used
1876 case 0xc :
1877 {
1878 if ( nRasterOperation == 0x33 )
1879 aBitmap.Invert();
1880 ImplDrawBitmap( aPos, aSize, aBitmap );
1881 }
1882 break;
1883
1884 case 0x5 : // only destination is used
1885 {
1886 SetRasterOp( R2_NOT );
1887 DrawRect( aRect, sal_False );
1888 }
1889 case 0xa : // no operation
1890 break;
1891 }
1892 SetRasterOp( nOldRop );
1893 Pop();
1894 }
1895 }
1896 }
1897 nObjectsLeft -= nObjectsOfSameSize;
1898 }
1899
1900 void* pPtr;
1901 for ( pPtr = rSaveList.First(); pPtr; pPtr = rSaveList.Next() )
1902 delete (BSaveStruct*)pPtr;
1903 rSaveList.Clear();
1904 }
1905
1906 //-----------------------------------------------------------------------------------
1907
SetDevOrg(const Point & rPoint)1908 void WinMtfOutput::SetDevOrg( const Point& rPoint )
1909 {
1910 mnDevOrgX = rPoint.X();
1911 mnDevOrgY = rPoint.Y();
1912 }
1913
1914 //-----------------------------------------------------------------------------------
1915
SetDevOrgOffset(sal_Int32 nXAdd,sal_Int32 nYAdd)1916 void WinMtfOutput::SetDevOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
1917 {
1918 mnDevOrgX += nXAdd;
1919 mnDevOrgY += nYAdd;
1920 }
1921
1922 //-----------------------------------------------------------------------------------
1923
SetDevExt(const Size & rSize)1924 void WinMtfOutput::SetDevExt( const Size& rSize )
1925 {
1926 if ( rSize.Width() && rSize.Height() )
1927 {
1928 switch( mnMapMode )
1929 {
1930 case MM_ISOTROPIC :
1931 case MM_ANISOTROPIC :
1932 {
1933 mnDevWidth = rSize.Width();
1934 mnDevHeight = rSize.Height();
1935 }
1936 }
1937 }
1938 }
1939
1940 //-----------------------------------------------------------------------------------
1941
ScaleDevExt(double fX,double fY)1942 void WinMtfOutput::ScaleDevExt( double fX, double fY )
1943 {
1944 mnDevWidth = FRound( mnDevWidth * fX );
1945 mnDevHeight = FRound( mnDevHeight * fY );
1946 }
1947
1948 //-----------------------------------------------------------------------------------
1949
SetWinOrg(const Point & rPoint)1950 void WinMtfOutput::SetWinOrg( const Point& rPoint )
1951 {
1952 mnWinOrgX = rPoint.X();
1953 mnWinOrgY = rPoint.Y();
1954 }
1955
1956 //-----------------------------------------------------------------------------------
1957
SetWinOrgOffset(sal_Int32 nXAdd,sal_Int32 nYAdd)1958 void WinMtfOutput::SetWinOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
1959 {
1960 mnWinOrgX += nXAdd;
1961 mnWinOrgY += nYAdd;
1962 }
1963
1964 //-----------------------------------------------------------------------------------
1965
SetWinExt(const Size & rSize)1966 void WinMtfOutput::SetWinExt( const Size& rSize )
1967 {
1968
1969 if( rSize.Width() && rSize.Height() )
1970 {
1971 switch( mnMapMode )
1972 {
1973 case MM_ISOTROPIC :
1974 case MM_ANISOTROPIC :
1975 {
1976 mnWinExtX = rSize.Width();
1977 mnWinExtY = rSize.Height();
1978 }
1979 }
1980 }
1981 }
1982
1983 //-----------------------------------------------------------------------------------
1984
ScaleWinExt(double fX,double fY)1985 void WinMtfOutput::ScaleWinExt( double fX, double fY )
1986 {
1987 mnWinExtX = FRound( mnWinExtX * fX );
1988 mnWinExtY = FRound( mnWinExtY * fY );
1989 }
1990
1991 //-----------------------------------------------------------------------------------
1992
SetrclBounds(const Rectangle & rRect)1993 void WinMtfOutput::SetrclBounds( const Rectangle& rRect )
1994 {
1995 mrclBounds = rRect;
1996 }
1997
1998 //-----------------------------------------------------------------------------------
1999
SetrclFrame(const Rectangle & rRect)2000 void WinMtfOutput::SetrclFrame( const Rectangle& rRect )
2001 {
2002 mrclFrame = rRect;
2003 }
2004
2005 //-----------------------------------------------------------------------------------
2006
SetRefPix(const Size & rSize)2007 void WinMtfOutput::SetRefPix( const Size& rSize )
2008 {
2009 mnPixX = rSize.Width();
2010 mnPixY = rSize.Height();
2011 }
2012
2013 //-----------------------------------------------------------------------------------
2014
SetRefMill(const Size & rSize)2015 void WinMtfOutput::SetRefMill( const Size& rSize )
2016 {
2017 mnMillX = rSize.Width();
2018 mnMillY = rSize.Height();
2019 }
2020
2021 //-----------------------------------------------------------------------------------
2022
SetMapMode(sal_uInt32 nMapMode)2023 void WinMtfOutput::SetMapMode( sal_uInt32 nMapMode )
2024 {
2025 mnMapMode = nMapMode;
2026 if ( nMapMode == MM_TEXT )
2027 {
2028 mnWinExtX = mnDevWidth;
2029 mnWinExtY = mnDevHeight;
2030 }
2031 else if ( mnMapMode == MM_HIMETRIC )
2032 {
2033 mnWinExtX = mnMillX * 100;
2034 mnWinExtY = mnMillY * 100;
2035 }
2036 }
2037
2038 //-----------------------------------------------------------------------------------
2039
SetWorldTransform(const XForm & rXForm)2040 void WinMtfOutput::SetWorldTransform( const XForm& rXForm )
2041 {
2042 maXForm.eM11 = rXForm.eM11;
2043 maXForm.eM12 = rXForm.eM12;
2044 maXForm.eM21 = rXForm.eM21;
2045 maXForm.eM22 = rXForm.eM22;
2046 maXForm.eDx = rXForm.eDx;
2047 maXForm.eDy = rXForm.eDy;
2048 }
2049
2050 //-----------------------------------------------------------------------------------
2051
ModifyWorldTransform(const XForm & rXForm,sal_uInt32 nMode)2052 void WinMtfOutput::ModifyWorldTransform( const XForm& rXForm, sal_uInt32 nMode )
2053 {
2054 switch( nMode )
2055 {
2056 case MWT_IDENTITY :
2057 {
2058 maXForm.eM11 = maXForm.eM22 = 1.0f;
2059 maXForm.eM12 = maXForm.eM21 = maXForm.eDx = maXForm.eDy = 0.0f;
2060 break;
2061 }
2062
2063 case MWT_RIGHTMULTIPLY :
2064 case MWT_LEFTMULTIPLY :
2065 {
2066 const XForm* pLeft;
2067 const XForm* pRight;
2068
2069 if ( nMode == MWT_LEFTMULTIPLY )
2070 {
2071 pLeft = &rXForm;
2072 pRight = &maXForm;
2073 }
2074 else
2075 {
2076 pLeft = &maXForm;
2077 pRight = &rXForm;
2078 }
2079
2080 float aF[3][3];
2081 float bF[3][3];
2082 float cF[3][3];
2083
2084 aF[0][0] = pLeft->eM11;
2085 aF[0][1] = pLeft->eM12;
2086 aF[0][2] = 0;
2087 aF[1][0] = pLeft->eM21;
2088 aF[1][1] = pLeft->eM22;
2089 aF[1][2] = 0;
2090 aF[2][0] = pLeft->eDx;
2091 aF[2][1] = pLeft->eDy;
2092 aF[2][2] = 1;
2093
2094 bF[0][0] = pRight->eM11;
2095 bF[0][1] = pRight->eM12;
2096 bF[0][2] = 0;
2097 bF[1][0] = pRight->eM21;
2098 bF[1][1] = pRight->eM22;
2099 bF[1][2] = 0;
2100 bF[2][0] = pRight->eDx;
2101 bF[2][1] = pRight->eDy;
2102 bF[2][2] = 1;
2103
2104 int i, j, k;
2105 for ( i = 0; i < 3; i++ )
2106 {
2107 for ( j = 0; j < 3; j++ )
2108 {
2109 cF[i][j] = 0;
2110 for ( k = 0; k < 3; k++ )
2111 cF[i][j] += aF[i][k] * bF[k][j];
2112 }
2113 }
2114 maXForm.eM11 = cF[0][0];
2115 maXForm.eM12 = cF[0][1];
2116 maXForm.eM21 = cF[1][0];
2117 maXForm.eM22 = cF[1][1];
2118 maXForm.eDx = cF[2][0];
2119 maXForm.eDy = cF[2][1];
2120 break;
2121 }
2122 case MWT_SET:
2123 {
2124 SetWorldTransform(rXForm);
2125 break;
2126 }
2127 }
2128 }
2129
2130 //-----------------------------------------------------------------------------------
2131
Push()2132 void WinMtfOutput::Push() // !! to be able to access the original ClipRegion it
2133 { // is not allowed to use the MetaPushAction()
2134 UpdateClipRegion(); // (the original clip region is on top of the stack) (SJ)
2135 SaveStructPtr pSave( new SaveStruct );
2136
2137 pSave->aLineStyle = maLineStyle;
2138 pSave->aFillStyle = maFillStyle;
2139
2140 pSave->aFont = maFont;
2141 pSave->aTextColor = maTextColor;
2142 pSave->nTextAlign = mnTextAlign;
2143 pSave->nTextLayoutMode = mnTextLayoutMode;
2144 pSave->nMapMode = mnMapMode;
2145 pSave->nGfxMode = mnGfxMode;
2146 pSave->nBkMode = mnBkMode;
2147 pSave->aBkColor = maBkColor;
2148 pSave->bFillStyleSelected = mbFillStyleSelected;
2149
2150 pSave->aActPos = maActPos;
2151 pSave->aXForm = maXForm;
2152 pSave->eRasterOp = meRasterOp;
2153
2154 pSave->nWinOrgX = mnWinOrgX;
2155 pSave->nWinOrgY = mnWinOrgY;
2156 pSave->nWinExtX = mnWinExtX;
2157 pSave->nWinExtY = mnWinExtY;
2158 pSave->nDevOrgX = mnDevOrgX;
2159 pSave->nDevOrgY = mnDevOrgY;
2160 pSave->nDevWidth = mnDevWidth;
2161 pSave->nDevHeight = mnDevHeight;
2162
2163 pSave->aPathObj = aPathObj;
2164 pSave->aClipPath = aClipPath;
2165
2166 vSaveStack.push_back( pSave );
2167 }
2168
2169 //-----------------------------------------------------------------------------------
2170
Pop()2171 void WinMtfOutput::Pop()
2172 {
2173 // Die aktuellen Daten vom Stack holen
2174 if( vSaveStack.size() )
2175 {
2176 // Die aktuelle Daten auf dem Stack sichern
2177 SaveStructPtr pSave( vSaveStack.back() );
2178
2179 maLineStyle = pSave->aLineStyle;
2180 maFillStyle = pSave->aFillStyle;
2181
2182 maFont = pSave->aFont;
2183 maTextColor = pSave->aTextColor;
2184 mnTextAlign = pSave->nTextAlign;
2185 mnTextLayoutMode = pSave->nTextLayoutMode;
2186 mnBkMode = pSave->nBkMode;
2187 mnGfxMode = pSave->nGfxMode;
2188 mnMapMode = pSave->nMapMode;
2189 maBkColor = pSave->aBkColor;
2190 mbFillStyleSelected = pSave->bFillStyleSelected;
2191
2192 maActPos = pSave->aActPos;
2193 maXForm = pSave->aXForm;
2194 meRasterOp = pSave->eRasterOp;
2195
2196 mnWinOrgX = pSave->nWinOrgX;
2197 mnWinOrgY = pSave->nWinOrgY;
2198 mnWinExtX = pSave->nWinExtX;
2199 mnWinExtY = pSave->nWinExtY;
2200 mnDevOrgX = pSave->nDevOrgX;
2201 mnDevOrgY = pSave->nDevOrgY;
2202 mnDevWidth = pSave->nDevWidth;
2203 mnDevHeight = pSave->nDevHeight;
2204
2205 aPathObj = pSave->aPathObj;
2206 if ( ! ( aClipPath == pSave->aClipPath ) )
2207 {
2208 aClipPath = pSave->aClipPath;
2209 aClipPath.bNeedsUpdate = sal_True;
2210 }
2211 if ( meLatestRasterOp != meRasterOp )
2212 mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
2213 vSaveStack.pop_back();
2214 }
2215 }
2216
AddFromGDIMetaFile(GDIMetaFile & rGDIMetaFile)2217 void WinMtfOutput::AddFromGDIMetaFile( GDIMetaFile& rGDIMetaFile )
2218 {
2219 rGDIMetaFile.Play( *mpGDIMetaFile, 0xFFFFFFFF );
2220 }
2221