merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / filter.vcl / wmf / winmtf.cxx
blobc8519f35dce2cab8e71fc19cf1c129dc46400b27
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: winmtf.cxx,v $
10 * $Revision: 1.54.136.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
35 #include "winmtf.hxx"
36 #include <vcl/metaact.hxx>
37 #include <vcl/graphictools.hxx>
38 #include <vcl/metric.hxx>
39 #include <rtl/tencinfo.h>
41 // ------------------------------------------------------------------------
43 #define EMFP_DEBUG(x)
44 //#define EMFP_DEBUG(x) x
46 #define WIN_MTF_MAX_POLYPOLYCOUNT 16
48 void WinMtfClipPath::ImpUpdateType()
50 if ( !aPolyPoly.Count() )
51 eType = EMPTY;
52 else if ( aPolyPoly.IsRect() )
53 eType = RECTANGLE;
54 else
55 eType = COMPLEX;
57 bNeedsUpdate = sal_True;
60 void WinMtfClipPath::IntersectClipRect( const Rectangle& rRect )
62 if ( !aPolyPoly.Count() )
63 aPolyPoly = Polygon( rRect );
64 else if ( aPolyPoly.Count() < WIN_MTF_MAX_POLYPOLYCOUNT )
66 Polygon aPolygon( rRect );
67 PolyPolygon aIntersection;
68 PolyPolygon aPolyPolyRect( aPolygon );
69 aPolyPoly.GetIntersection( aPolyPolyRect, aIntersection );
70 aPolyPoly = aIntersection;
72 ImpUpdateType();
75 void WinMtfClipPath::ExcludeClipRect( const Rectangle& rRect )
77 if ( aPolyPoly.Count() && ( aPolyPoly.Count() < WIN_MTF_MAX_POLYPOLYCOUNT ) )
79 Polygon aPolygon( rRect );
80 PolyPolygon aPolyPolyRect( aPolygon );
81 PolyPolygon aDifference;
82 aPolyPoly.GetDifference( aPolyPolyRect, aDifference );
83 aPolyPoly = aDifference;
85 ImpUpdateType();
88 void WinMtfClipPath::SetClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode )
90 if ( !rPolyPolygon.Count() )
91 aPolyPoly = rPolyPolygon;
92 else if ( rPolyPolygon.Count() < WIN_MTF_MAX_POLYPOLYCOUNT )
94 PolyPolygon aNewClipPath;
96 // #115345# Watch out for empty aPolyPoly here - conceptually,
97 // an empty clip path is a rectangle of infinite size, but it
98 // is represented by an empty aPolyPoly. When intersecting
99 // rPolyPolygon with this _empty_ aPolyPoly, set algebra
100 // guarantees wrong results.
101 switch ( nClippingMode )
103 case RGN_OR :
104 // #115345# clip stays empty, when ORing an arbitrary
105 // rPolyPolygon. Thus, we can save us the unnecessary
106 // clipper call.
107 if( aPolyPoly.Count() )
108 aPolyPoly.GetUnion( rPolyPolygon, aNewClipPath );
109 break;
110 case RGN_XOR :
111 // TODO:
112 // #115345# Cannot handle this case, for the time being
113 aPolyPoly.GetXOR( rPolyPolygon, aNewClipPath );
114 break;
115 case RGN_DIFF :
116 // TODO:
117 // #115345# Cannot handle this case, for the time being
118 aPolyPoly.GetDifference( rPolyPolygon, aNewClipPath );
119 break;
120 case RGN_AND :
121 // #115345# Clip becomes rPolyPolygon, when ANDing
122 // with an arbitrary rPolyPolygon
123 if( aPolyPoly.Count() )
124 aPolyPoly.GetIntersection( rPolyPolygon, aNewClipPath );
125 else
126 aNewClipPath = rPolyPolygon;
127 break;
128 case RGN_COPY :
129 aNewClipPath = rPolyPolygon;
130 break;
132 aPolyPoly = aNewClipPath;
134 ImpUpdateType();
137 void WinMtfClipPath::MoveClipRegion( const Size& rSize )
139 aPolyPoly.Move( rSize.Width(), rSize.Height() );
140 bNeedsUpdate = sal_True;
143 // ------------------------------------------------------------------------
145 void WinMtfPathObj::AddPoint( const Point& rPoint )
147 if ( bClosed )
148 Insert( Polygon(), POLYPOLY_APPEND );
149 Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ];
150 rPoly.Insert( rPoly.GetSize(), rPoint, POLY_NORMAL );
151 bClosed = sal_False;
154 void WinMtfPathObj::AddPolyLine( const Polygon& rPolyLine )
156 if ( bClosed )
157 Insert( Polygon(), POLYPOLY_APPEND );
158 Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ];
159 rPoly.Insert( rPoly.GetSize(), rPolyLine );
160 bClosed = sal_False;
163 void WinMtfPathObj::AddPolygon( const Polygon& rPoly )
165 Insert( rPoly, POLYPOLY_APPEND );
166 bClosed = sal_True;
169 void WinMtfPathObj::AddPolyPolygon( const PolyPolygon& rPolyPoly )
171 sal_uInt16 i, nCount = rPolyPoly.Count();
172 for ( i = 0; i < nCount; i++ )
173 Insert( rPolyPoly[ i ], POLYPOLY_APPEND );
174 bClosed = sal_True;
177 void WinMtfPathObj::ClosePath()
179 if ( Count() )
181 Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ];
182 if ( rPoly.GetSize() > 2 )
184 Point aFirst( rPoly[ 0 ] );
185 if ( aFirst != rPoly[ rPoly.GetSize() - 1 ] )
186 rPoly.Insert( rPoly.GetSize(), aFirst, POLY_NORMAL );
189 bClosed = sal_True;
192 // ------------------------------------------------------------------------
194 WinMtfFontStyle::WinMtfFontStyle( LOGFONTW& rFont )
196 CharSet eCharSet;
197 if ( ( rFont.lfCharSet == OEM_CHARSET ) || ( rFont.lfCharSet == DEFAULT_CHARSET ) )
198 eCharSet = gsl_getSystemTextEncoding();
199 else
200 eCharSet = rtl_getTextEncodingFromWindowsCharset( rFont.lfCharSet );
201 if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
202 eCharSet = gsl_getSystemTextEncoding();
203 aFont.SetCharSet( eCharSet );
204 aFont.SetName( rFont.alfFaceName );
205 FontFamily eFamily;
206 switch ( rFont.lfPitchAndFamily & 0xf0 )
208 case FF_ROMAN:
209 eFamily = FAMILY_ROMAN;
210 break;
212 case FF_SWISS:
213 eFamily = FAMILY_SWISS;
214 break;
216 case FF_MODERN:
217 eFamily = FAMILY_MODERN;
218 break;
220 case FF_SCRIPT:
221 eFamily = FAMILY_SCRIPT;
222 break;
224 case FF_DECORATIVE:
225 eFamily = FAMILY_DECORATIVE;
226 break;
228 default:
229 eFamily = FAMILY_DONTKNOW;
230 break;
232 aFont.SetFamily( eFamily );
234 FontPitch ePitch;
235 switch ( rFont.lfPitchAndFamily & 0x0f )
237 case FIXED_PITCH:
238 ePitch = PITCH_FIXED;
239 break;
241 case DEFAULT_PITCH:
242 case VARIABLE_PITCH:
243 default:
244 ePitch = PITCH_VARIABLE;
245 break;
247 aFont.SetPitch( ePitch );
249 FontWeight eWeight;
250 if( rFont.lfWeight <= FW_THIN )
251 eWeight = WEIGHT_THIN;
252 else if( rFont.lfWeight <= FW_ULTRALIGHT )
253 eWeight = WEIGHT_ULTRALIGHT;
254 else if( rFont.lfWeight <= FW_LIGHT )
255 eWeight = WEIGHT_LIGHT;
256 else if( rFont.lfWeight < FW_MEDIUM )
257 eWeight = WEIGHT_NORMAL;
258 else if( rFont.lfWeight == FW_MEDIUM )
259 eWeight = WEIGHT_MEDIUM;
260 else if( rFont.lfWeight <= FW_SEMIBOLD )
261 eWeight = WEIGHT_SEMIBOLD;
262 else if( rFont.lfWeight <= FW_BOLD )
263 eWeight = WEIGHT_BOLD;
264 else if( rFont.lfWeight <= FW_ULTRABOLD )
265 eWeight = WEIGHT_ULTRABOLD;
266 else
267 eWeight = WEIGHT_BLACK;
268 aFont.SetWeight( eWeight );
270 if( rFont.lfItalic )
271 aFont.SetItalic( ITALIC_NORMAL );
273 if( rFont.lfUnderline )
274 aFont.SetUnderline( UNDERLINE_SINGLE );
276 if( rFont.lfStrikeOut )
277 aFont.SetStrikeout( STRIKEOUT_SINGLE );
279 if ( rFont.lfOrientation )
280 aFont.SetOrientation( (short)rFont.lfOrientation );
281 else
282 aFont.SetOrientation( (short)rFont.lfEscapement );
284 Size aFontSize( Size( rFont.lfWidth, rFont.lfHeight ) );
285 if ( rFont.lfHeight > 0 )
287 // converting the cell height into a font height
288 VirtualDevice aVDev;
289 aFont.SetSize( aFontSize );
290 aVDev.SetFont( aFont );
291 FontMetric aMetric( aVDev.GetFontMetric() );
292 long nHeight = aMetric.GetAscent() + aMetric.GetDescent();
293 if ( nHeight )
295 double fHeight = ((double)aFontSize.Height() * rFont.lfHeight ) / nHeight;
296 aFontSize.Height() = (sal_Int32)( fHeight + 0.5 );
299 else if ( aFontSize.Height() < 0 )
300 aFontSize.Height() *= -1;
302 if ( !rFont.lfWidth )
304 VirtualDevice aVDev;
305 aFont.SetSize( aFontSize );
306 aVDev.SetFont( aFont );
307 FontMetric aMetric( aVDev.GetFontMetric() );
308 aFontSize.Width() = aMetric.GetWidth();
311 aFont.SetSize( aFontSize );
314 // ------------------------------------------------------------------------
316 #ifdef WIN_MTF_ASSERT
317 void WinMtfAssertHandler( const sal_Char* pAction, sal_uInt32 nFlags )
319 static sal_Bool bOnlyOnce;
320 static sal_Int32 nAssertCount;
322 if ( nFlags & WIN_MTF_ASSERT_INIT )
323 nAssertCount = 0;
324 if ( nFlags & WIN_MTF_ASSERT_ONCE )
325 bOnlyOnce = sal_True;
326 if ( nFlags & WIN_MTF_ASSERT_MIFE )
328 if ( ( nAssertCount == 0 ) || ( bOnlyOnce == sal_False ) )
330 ByteString aText( "WMF/EMF Import: " );
331 if ( pAction )
333 ByteString aAction( pAction );
334 aText.Append( aAction );
336 aText.Append( " needs to be implemented (SJ)" );
337 DBG_ASSERT( 0, aText.GetBuffer() );
339 nAssertCount++;
342 #endif
344 // ------------------------------------------------------------------------
346 WinMtf::WinMtf( WinMtfOutput* pWinMtfOutput, SvStream& rStreamWMF, FilterConfigItem* pConfigItem ) :
347 pOut ( pWinMtfOutput ),
348 pWMF ( &rStreamWMF ),
349 pFilterConfigItem ( pConfigItem )
351 #ifdef WIN_MTF_ASSERT
352 // we want to assert not implemented features, but we do this
353 // only once, so that nobody is handicaped by getting too much assertions
354 // I hope this will bring more testdocuments, without support of these
355 // testdocuments the implementation of missing features won't be possible. (SJ)
356 WinMtfAssertHandler( NULL, WIN_MTF_ASSERT_INIT | WIN_MTF_ASSERT_ONCE );
357 #endif
359 SvLockBytes *pLB = pWMF->GetLockBytes();
360 if ( pLB )
361 pLB->SetSynchronMode( TRUE );
363 nStartPos = pWMF->Tell();
365 pOut->SetDevOrg( Point() );
366 if ( pFilterConfigItem )
368 xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
369 if ( xStatusIndicator.is() )
371 rtl::OUString aMsg;
372 xStatusIndicator->start( aMsg, 100 );
377 // ------------------------------------------------------------------------
379 WinMtf::~WinMtf()
381 delete pOut;
383 if ( xStatusIndicator.is() )
384 xStatusIndicator->end();
387 // ------------------------------------------------------------------------
389 void WinMtf::Callback( USHORT nPercent )
391 if ( xStatusIndicator.is() )
392 xStatusIndicator->setValue( nPercent );
395 // ------------------------------------------------------------------------
397 Color WinMtf::ReadColor()
399 UINT32 nColor;
400 *pWMF >> nColor;
401 return Color( (BYTE)nColor, (BYTE)( nColor >> 8 ), (BYTE)( nColor >> 16 ) );
404 //-----------------------------------------------------------------------------------
405 //-----------------------------------------------------------------------------------
406 //-----------------------------------------------------------------------------------
408 Point WinMtfOutput::ImplMap( const Point& rPt )
410 if ( mnWinExtX && mnWinExtY )
412 double fX2, fX = rPt.X();
413 double fY2, fY = rPt.Y();
415 fX2 = fX * maXForm.eM11 + fY * maXForm.eM21 + maXForm.eDx;
416 fY2 = fX * maXForm.eM12 + fY * maXForm.eM22 + maXForm.eDy;
418 if ( mnGfxMode == GM_COMPATIBLE )
420 switch( mnMapMode )
422 case MM_TEXT:
423 fX2 -= mnWinOrgX;
424 fY2 -= mnWinOrgY;
425 if( mnDevWidth != 1 || mnDevHeight != 1 ) {
426 fX2 *= 2540.0/mnUnitsPerInch;
427 fY2 *= 2540.0/mnUnitsPerInch;
429 fX2 += mnDevOrgX;
430 fY2 += mnDevOrgY;
431 fX2 *= (double)mnMillX * 100.0 / (double)mnPixX;
432 fY2 *= (double)mnMillY * 100.0 / (double)mnPixY;
434 break;
435 case MM_LOENGLISH :
437 fX2 -= mnWinOrgX;
438 fY2 = mnWinOrgY-fY2;
439 fX2 *= 25.40;
440 fY2 *= 25.40;
441 fX2 += mnDevOrgX;
442 fY2 += mnDevOrgY;
444 break;
445 case MM_HIENGLISH :
447 fX2 -= mnWinOrgX;
448 fY2 = mnWinOrgY-fY2;
449 fX2 *= 2.540;
450 fY2 *= 2.540;
451 fX2 += mnDevOrgX;
452 fY2 += mnDevOrgY;
454 break;
455 case MM_LOMETRIC :
457 fX2 -= mnWinOrgX;
458 fY2 = mnWinOrgY-fY2;
459 fX2 *= 10;
460 fY2 *= 10;
461 fX2 += mnDevOrgX;
462 fY2 += mnDevOrgY;
464 break;
465 case MM_HIMETRIC :
467 fX2 -= mnWinOrgX;
468 fY2 = mnWinOrgY-fY2;
469 fX2 += mnDevOrgX;
470 fY2 += mnDevOrgY;
472 break;
473 default :
475 fX2 -= mnWinOrgX;
476 fY2 -= mnWinOrgY;
477 fX2 /= mnWinExtX;
478 fY2 /= mnWinExtY;
479 fX2 *= mnDevWidth;
480 fY2 *= mnDevHeight;
481 fX2 += mnDevOrgX;
482 fY2 += mnDevOrgY; // fX2, fY2 now in device units
483 fX2 *= (double)mnMillX * 100.0 / (double)mnPixX;
484 fY2 *= (double)mnMillY * 100.0 / (double)mnPixY;
486 break;
488 fX2 -= mrclFrame.Left();
489 fY2 -= mrclFrame.Top();
491 return Point( FRound( fX2 ), FRound( fY2 ) );
493 else
494 return Point();
497 // ------------------------------------------------------------------------
499 Size WinMtfOutput::ImplMap( const Size& rSz )
501 if ( mnWinExtX && mnWinExtY )
503 double fWidth = rSz.Width() * maXForm.eM11;
504 double fHeight = rSz.Height() * maXForm.eM22;
506 if ( mnGfxMode == GM_COMPATIBLE )
508 switch( mnMapMode )
510 case MM_TEXT:
511 if( mnDevWidth != 1 && mnDevHeight != 1 ) {
512 fWidth *= 2540.0/mnUnitsPerInch;
513 fHeight*= 2540.0/mnUnitsPerInch;
514 } else {
515 fWidth *= (double)mnMillX * 100 / (double)mnPixX;
516 fHeight *= (double)mnMillY * 100 / (double)mnPixY;
518 break;
519 case MM_LOENGLISH :
521 fWidth *= 25.40;
522 fHeight*=-25.40;
524 break;
525 case MM_HIENGLISH :
527 fWidth *= 2.540;
528 fHeight*=-2.540;
530 break;
531 case MM_LOMETRIC :
533 fWidth *= 10;
534 fHeight*=-10;
536 break;
537 case MM_HIMETRIC :
539 fHeight *= -1;
541 break;
542 default :
544 fWidth /= mnWinExtX;
545 fHeight /= mnWinExtY;
546 fWidth *= mnDevWidth;
547 fHeight *= mnDevHeight;
548 fWidth *= (double)mnMillX * 100 / (double)mnPixX;
549 fHeight *= (double)mnMillY * 100 / (double)mnPixY;
551 break;
554 return Size( FRound( fWidth ), FRound( fHeight ) );
556 else
557 return Size();
560 //-----------------------------------------------------------------------------------
562 Rectangle WinMtfOutput::ImplMap( const Rectangle& rRect )
564 return Rectangle( ImplMap( rRect.TopLeft() ), ImplMap( rRect.GetSize() ) );
567 //-----------------------------------------------------------------------------------
569 void WinMtfOutput::ImplMap( Font& rFont )
571 // !!! HACK: Wir setzen die Breite jetzt immer auf Null,
572 // da OS die Breite unterschiedlich interpretieren;
573 // muss spaeter in SV portabel gemacht werden ( KA 08.02.96 )
574 Size aFontSize = ImplMap ( rFont.GetSize() );
576 if( aFontSize.Height() < 0 )
577 aFontSize.Height() *= -1;
579 rFont.SetSize( aFontSize );
581 if( ( mnWinExtX * mnWinExtY ) < 0 )
582 rFont.SetOrientation( 3600 - rFont.GetOrientation() );
585 //-----------------------------------------------------------------------------------
587 Polygon& WinMtfOutput::ImplMap( Polygon& rPolygon )
589 UINT16 nPoints = rPolygon.GetSize();
590 for ( UINT16 i = 0; i < nPoints; i++ )
592 rPolygon[ i ] = ImplMap( rPolygon[ i ] );
594 return rPolygon;
597 //-----------------------------------------------------------------------------------
599 PolyPolygon& WinMtfOutput::ImplMap( PolyPolygon& rPolyPolygon )
601 UINT16 nPolys = rPolyPolygon.Count();
602 for ( UINT16 i = 0; i < nPolys; ImplMap( rPolyPolygon[ i++ ] ) ) ;
603 return rPolyPolygon;
606 //-----------------------------------------------------------------------------------
608 void WinMtfOutput::SelectObject( INT32 nIndex )
610 GDIObj* pGDIObj = NULL;
612 if ( nIndex & ENHMETA_STOCK_OBJECT )
613 pGDIObj = new GDIObj();
614 else
616 nIndex &= 0xffff; // zur Sicherheit: mehr als 65535 nicht zulassen
618 if ( (UINT32)nIndex < vGDIObj.size() )
619 pGDIObj = vGDIObj[ nIndex ];
622 if( pGDIObj == NULL )
623 return;
625 if ( nIndex & ENHMETA_STOCK_OBJECT )
627 UINT16 nStockId = (BYTE)nIndex;
628 switch( nStockId )
630 case WHITE_BRUSH :
632 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ) ) );
634 break;
635 case LTGRAY_BRUSH :
637 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_LIGHTGRAY ) ) );
639 break;
640 case GRAY_BRUSH :
641 case DKGRAY_BRUSH :
643 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_GRAY ) ) );
645 break;
646 case BLACK_BRUSH :
648 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_BLACK ) ) );
650 break;
651 case NULL_BRUSH :
653 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_TRANSPARENT ), TRUE ) );
655 break;
656 case WHITE_PEN :
658 pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_WHITE ) ) );
660 break;
661 case BLACK_PEN :
663 pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_BLACK ) ) );
665 break;
666 case NULL_PEN :
668 pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_TRANSPARENT ), TRUE ) );
670 break;
671 default:
672 break;
675 if ( pGDIObj->pStyle )
677 switch( pGDIObj->eType )
679 case GDI_PEN :
680 maLineStyle = (WinMtfLineStyle*)pGDIObj->pStyle;
681 break;
682 case GDI_BRUSH :
684 maFillStyle = (WinMtfFillStyle*)pGDIObj->pStyle;
685 mbFillStyleSelected = sal_True;
687 break;
688 case GDI_FONT :
689 maFont = ((WinMtfFontStyle*)pGDIObj->pStyle)->aFont;
690 break;
691 default:
692 break; // -Wall many options not handled.
695 if ( nIndex & ENHMETA_STOCK_OBJECT )
696 delete pGDIObj;
699 //-----------------------------------------------------------------------------------
701 void WinMtfOutput::SetFont( const Font& rFont )
703 maFont = rFont;
706 //-----------------------------------------------------------------------------------
708 const Font& WinMtfOutput::GetFont() const
710 return maFont;
713 //-----------------------------------------------------------------------------------
715 void WinMtfOutput::SetTextLayoutMode( const sal_uInt32 nTextLayoutMode )
717 mnTextLayoutMode = nTextLayoutMode;
720 //-----------------------------------------------------------------------------------
722 sal_uInt32 WinMtfOutput::GetTextLayoutMode() const
724 return mnTextLayoutMode;
727 //-----------------------------------------------------------------------------------
729 void WinMtfOutput::SetBkMode( UINT32 nMode )
731 mnBkMode = nMode;
734 //-----------------------------------------------------------------------------------
736 void WinMtfOutput::SetBkColor( const Color& rColor )
738 maBkColor = rColor;
741 //-----------------------------------------------------------------------------------
743 void WinMtfOutput::SetTextColor( const Color& rColor )
745 maTextColor = rColor;
748 //-----------------------------------------------------------------------------------
750 void WinMtfOutput::SetTextAlign( UINT32 nAlign )
752 mnTextAlign = nAlign;
755 //-----------------------------------------------------------------------------------
757 void WinMtfOutput::ImplResizeObjectArry( UINT32 nNewEntrys )
759 sal_uInt32 i = vGDIObj.size();
760 vGDIObj.resize( nNewEntrys );
761 for ( ; i < nNewEntrys ; i++ )
762 vGDIObj[ i ] = NULL;
765 //-----------------------------------------------------------------------------------
767 void WinMtfOutput::ImplDrawClippedPolyPolygon( const PolyPolygon& rPolyPoly )
769 if ( rPolyPoly.Count() )
771 ImplSetNonPersistentLineColorTransparenz();
772 if ( rPolyPoly.Count() == 1 )
774 if ( rPolyPoly.IsRect() )
775 mpGDIMetaFile->AddAction( new MetaRectAction( rPolyPoly.GetBoundRect() ) );
776 else
778 Polygon aPoly( rPolyPoly[ 0 ] );
779 sal_uInt16 nCount = aPoly.GetSize();
780 if ( nCount )
782 if ( aPoly[ nCount - 1 ] != aPoly[ 0 ] )
784 Point aPoint( aPoly[ 0 ] );
785 aPoly.Insert( nCount, aPoint );
787 mpGDIMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
791 else
792 mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) );
797 //-----------------------------------------------------------------------------------
799 void WinMtfOutput::CreateObject( GDIObjectType eType, void* pStyle )
801 if ( pStyle )
803 if ( eType == GDI_FONT )
805 ImplMap( ((WinMtfFontStyle*)pStyle)->aFont );
806 if (!((WinMtfFontStyle*)pStyle)->aFont.GetHeight() )
807 ((WinMtfFontStyle*)pStyle)->aFont.SetHeight( 423 ); // defaulting to 12pt
809 else if ( eType == GDI_PEN )
811 Size aSize( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetWidth(), 0 );
812 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetWidth( ImplMap( aSize ).Width() );
813 if ( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetStyle() == LINE_DASH )
815 aSize.Width() += 1;
816 long nDotLen = ImplMap( aSize ).Width();
817 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDistance( nDotLen );
818 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDotLen( nDotLen );
819 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDashLen( nDotLen * 4 );
823 UINT32 nIndex;
824 for ( nIndex = 0; nIndex < vGDIObj.size(); nIndex++ )
826 if ( vGDIObj[ nIndex ] == NULL )
827 break;
829 if ( nIndex == vGDIObj.size() )
830 ImplResizeObjectArry( vGDIObj.size() + 16 );
832 vGDIObj[ nIndex ] = new GDIObj( eType, pStyle );
835 //-----------------------------------------------------------------------------------
837 void WinMtfOutput::CreateObject( INT32 nIndex, GDIObjectType eType, void* pStyle )
839 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
841 nIndex &= 0xffff; // zur Sicherheit: mehr als 65535 nicht zulassen
842 if ( pStyle )
844 if ( eType == GDI_FONT )
845 ImplMap( ((WinMtfFontStyle*)pStyle)->aFont );
846 else if ( eType == GDI_PEN )
848 Size aSize( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetWidth(), 0 );
849 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetWidth( ImplMap( aSize ).Width() );
850 if ( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetStyle() == LINE_DASH )
852 aSize.Width() += 1;
853 long nDotLen = ImplMap( aSize ).Width();
854 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDistance( nDotLen );
855 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDotLen( nDotLen );
856 ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDashLen( nDotLen * 4 );
860 if ( (UINT32)nIndex >= vGDIObj.size() )
861 ImplResizeObjectArry( nIndex + 16 );
863 if ( vGDIObj[ nIndex ] != NULL )
864 delete vGDIObj[ nIndex ];
866 vGDIObj[ nIndex ] = new GDIObj( eType, pStyle );
868 else
870 switch ( eType )
872 case GDI_PEN :
873 delete (WinMtfLineStyle*)pStyle;
874 break;
875 case GDI_BRUSH :
876 delete (WinMtfFillStyle*)pStyle;
877 break;
878 case GDI_FONT :
879 delete (WinMtfFontStyle*)pStyle;
880 break;
882 default:
883 DBG_ERROR( "unsupported style not deleted" );
884 break;
889 //-----------------------------------------------------------------------------------
891 void WinMtfOutput::DeleteObject( sal_Int32 nIndex )
893 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
895 if ( (sal_uInt32)nIndex < vGDIObj.size() )
897 delete vGDIObj[ nIndex ];
898 vGDIObj[ nIndex ] = NULL;
903 //-----------------------------------------------------------------------------------
905 void WinMtfOutput::IntersectClipRect( const Rectangle& rRect )
907 aClipPath.IntersectClipRect( ImplMap( rRect ) );
910 //-----------------------------------------------------------------------------------
912 void WinMtfOutput::ExcludeClipRect( const Rectangle& rRect )
914 aClipPath.ExcludeClipRect( ImplMap( rRect ) );
917 //-----------------------------------------------------------------------------------
919 void WinMtfOutput::MoveClipRegion( const Size& rSize )
921 aClipPath.MoveClipRegion( ImplMap( rSize ) );
924 void WinMtfOutput::SetClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode, sal_Bool bIsMapped )
926 if ( bIsMapped )
927 aClipPath.SetClipPath( rPolyPolygon, nClippingMode );
928 else
930 PolyPolygon aPP( rPolyPolygon );
931 aClipPath.SetClipPath( ImplMap( aPP ), nClippingMode );
935 //-----------------------------------------------------------------------------------
936 //-----------------------------------------------------------------------------------
937 //-----------------------------------------------------------------------------------
939 WinMtfOutput::WinMtfOutput( GDIMetaFile& rGDIMetaFile ) :
940 mnLatestTextAlign ( 0 ),
941 mnTextAlign ( TA_LEFT | TA_TOP | TA_NOUPDATECP ),
942 maLatestBkColor ( 0x12345678 ),
943 maBkColor ( COL_WHITE ),
944 mnLatestTextLayoutMode( TEXT_LAYOUT_DEFAULT ),
945 mnTextLayoutMode ( TEXT_LAYOUT_DEFAULT ),
946 mnLatestBkMode ( 0 ),
947 mnBkMode ( OPAQUE ),
948 meLatestRasterOp ( ROP_INVERT ),
949 meRasterOp ( ROP_OVERPAINT ),
950 maActPos ( Point() ),
951 mbNopMode ( sal_False ),
952 mbFillStyleSelected ( sal_False ),
953 mnGfxMode ( GM_COMPATIBLE ),
954 mnMapMode ( MM_TEXT ),
955 mnUnitsPerInch ( 96 ),
956 mnDevOrgX ( 0 ),
957 mnDevOrgY ( 0 ),
958 mnDevWidth ( 1 ),
959 mnDevHeight ( 1 ),
960 mnWinOrgX ( 0 ),
961 mnWinOrgY ( 0 ),
962 mnWinExtX ( 1 ),
963 mnWinExtY ( 1 ),
964 mnPixX ( 100 ),
965 mnPixY ( 100 ),
966 mnMillX ( 1 ),
967 mnMillY ( 1 ),
968 mpGDIMetaFile ( &rGDIMetaFile )
970 mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_CLIPREGION ) ); // The original clipregion has to be on top
971 // of the stack so it can always be restored
972 // this is necessary to be able to support
973 // SetClipRgn( NULL ) and similar ClipRgn actions (SJ)
975 maFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "Arial" )) ); // sj: #i57205#, we do have some scaling problems if using
976 maFont.SetCharSet( gsl_getSystemTextEncoding() ); // the default font then most times a x11 font is used, we
977 maFont.SetHeight( 423 ); // will prevent this defining a font
979 maLatestLineStyle.aLineColor = Color( 0x12, 0x34, 0x56 );
980 maLatestFillStyle.aFillColor = Color( 0x12, 0x34, 0x56 );
982 mnRop = R2_BLACK + 1;
983 SetRasterOp( R2_BLACK );
986 //-----------------------------------------------------------------------------------
988 WinMtfOutput::~WinMtfOutput()
990 mpGDIMetaFile->AddAction( new MetaPopAction() );
991 mpGDIMetaFile->SetPrefMapMode( MAP_100TH_MM );
992 if ( mrclFrame.IsEmpty() )
993 mpGDIMetaFile->SetPrefSize( Size( mnDevWidth, mnDevHeight ) );
994 else
995 mpGDIMetaFile->SetPrefSize( mrclFrame.GetSize() );
997 for ( UINT32 i = 0; i < vGDIObj.size(); i++ )
998 delete vGDIObj[ i ];
1001 //-----------------------------------------------------------------------------------
1003 void WinMtfOutput::UpdateClipRegion()
1005 if ( aClipPath.bNeedsUpdate )
1007 aClipPath.bNeedsUpdate = sal_False;
1009 mpGDIMetaFile->AddAction( new MetaPopAction() ); // taking the orignal clipregion
1010 mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_CLIPREGION ) ); //
1012 switch ( aClipPath.GetType() )
1014 case RECTANGLE :
1015 case COMPLEX :
1017 // we will not generate a RegionClipRegion Action, because this action
1018 // cannot be saved to the wmf format - saving to wmf always happens
1019 // if the placeholder graphic for ole objects is generated. (SJ)
1021 // Region aClipRegion( aClipPath.GetClipPath() );
1022 // mpGDIMetaFile->AddAction( new MetaISectRegionClipRegionAction( aClipRegion ) );
1024 Rectangle aClipRect( aClipPath.GetClipPath().GetBoundRect() );
1025 mpGDIMetaFile->AddAction( new MetaISectRectClipRegionAction( aClipRect ) );
1027 break;
1028 case EMPTY:
1029 break; // -Wall not handled.
1034 //-----------------------------------------------------------------------------------
1036 void WinMtfOutput::ImplSetNonPersistentLineColorTransparenz()
1038 Color aColor( COL_TRANSPARENT);
1039 WinMtfLineStyle aTransparentLine( aColor, TRUE );
1040 if ( ! ( maLatestLineStyle == aTransparentLine ) )
1042 maLatestLineStyle = aTransparentLine;
1043 mpGDIMetaFile->AddAction( new MetaLineColorAction( aTransparentLine.aLineColor, !aTransparentLine.bTransparent ) );
1047 //-----------------------------------------------------------------------------------
1049 void WinMtfOutput::UpdateLineStyle()
1051 if (!( maLatestLineStyle == maLineStyle ) )
1053 maLatestLineStyle = maLineStyle;
1054 mpGDIMetaFile->AddAction( new MetaLineColorAction( maLineStyle.aLineColor, !maLineStyle.bTransparent ) );
1058 //-----------------------------------------------------------------------------------
1060 void WinMtfOutput::UpdateFillStyle()
1062 if ( !mbFillStyleSelected ) // SJ: #i57205# taking care of bkcolor if no brush is selected
1063 maFillStyle = WinMtfFillStyle( maBkColor, mnBkMode == TRANSPARENT );
1064 if (!( maLatestFillStyle == maFillStyle ) )
1066 maLatestFillStyle = maFillStyle;
1067 if (maFillStyle.aType == FillStyleSolid)
1068 mpGDIMetaFile->AddAction( new MetaFillColorAction( maFillStyle.aFillColor, !maFillStyle.bTransparent ) );
1072 //-----------------------------------------------------------------------------------
1074 sal_uInt32 WinMtfOutput::SetRasterOp( UINT32 nRasterOp )
1076 sal_uInt32 nRetROP = mnRop;
1077 if ( nRasterOp != mnRop )
1079 mnRop = nRasterOp;
1080 static WinMtfFillStyle aNopFillStyle;
1081 static WinMtfLineStyle aNopLineStyle;
1083 if ( mbNopMode && ( nRasterOp != R2_NOP ) )
1084 { // beim uebergang von R2_NOP auf anderen Modus
1085 // gesetzten Pen und Brush aktivieren
1086 maFillStyle = aNopFillStyle;
1087 maLineStyle = aNopLineStyle;
1088 mbNopMode = sal_False;
1090 switch( nRasterOp )
1092 case R2_NOT:
1093 meRasterOp = ROP_INVERT;
1094 break;
1096 case R2_XORPEN:
1097 meRasterOp = ROP_XOR;
1098 break;
1100 case R2_NOP:
1102 meRasterOp = ROP_OVERPAINT;
1103 if( mbNopMode == sal_False )
1105 aNopFillStyle = maFillStyle;
1106 aNopLineStyle = maLineStyle;
1107 maFillStyle = WinMtfFillStyle( Color( COL_TRANSPARENT ), TRUE );
1108 maLineStyle = WinMtfLineStyle( Color( COL_TRANSPARENT ), TRUE );
1109 mbNopMode = sal_True;
1112 break;
1114 default:
1115 meRasterOp = ROP_OVERPAINT;
1116 break;
1119 if ( nRetROP != nRasterOp )
1120 mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
1121 return nRetROP;
1124 //-----------------------------------------------------------------------------------
1126 void WinMtfOutput::StrokeAndFillPath( sal_Bool bStroke, sal_Bool bFill )
1128 if ( aPathObj.Count() )
1130 UpdateClipRegion();
1131 UpdateLineStyle();
1132 UpdateFillStyle();
1133 if ( bFill )
1135 if ( !bStroke )
1137 mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
1138 mpGDIMetaFile->AddAction( new MetaLineColorAction( Color(), FALSE ) );
1140 if ( aPathObj.Count() == 1 )
1141 mpGDIMetaFile->AddAction( new MetaPolygonAction( aPathObj.GetObject( 0 ) ) );
1142 else
1143 mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aPathObj ) );
1145 if ( !bStroke )
1146 mpGDIMetaFile->AddAction( new MetaPopAction() );
1148 else
1150 sal_uInt16 i, nCount = aPathObj.Count();
1151 for ( i = 0; i < nCount; i++ )
1152 mpGDIMetaFile->AddAction( new MetaPolyLineAction( aPathObj[ i ], maLineStyle.aLineInfo ) );
1154 ClearPath();
1158 //-----------------------------------------------------------------------------------
1160 void WinMtfOutput::DrawPixel( const Point& rSource, const Color& rColor )
1162 mpGDIMetaFile->AddAction( new MetaPixelAction( ImplMap( rSource), rColor ) );
1165 //-----------------------------------------------------------------------------------
1167 void WinMtfOutput::MoveTo( const Point& rPoint, sal_Bool bRecordPath )
1169 Point aDest( ImplMap( rPoint ) );
1170 if ( bRecordPath )
1171 aPathObj.AddPoint( aDest );
1172 maActPos = aDest;
1175 //-----------------------------------------------------------------------------------
1177 void WinMtfOutput::LineTo( const Point& rPoint, sal_Bool bRecordPath )
1179 UpdateClipRegion();
1181 Point aDest( ImplMap( rPoint ) );
1182 if ( bRecordPath )
1183 aPathObj.AddPoint( aDest );
1184 else
1186 UpdateLineStyle();
1187 mpGDIMetaFile->AddAction( new MetaLineAction( maActPos, aDest, maLineStyle.aLineInfo ) );
1189 maActPos = aDest;
1192 //-----------------------------------------------------------------------------------
1194 void WinMtfOutput::DrawLine( const Point& rSource, const Point& rDest )
1196 UpdateClipRegion();
1197 UpdateLineStyle();
1198 mpGDIMetaFile->AddAction( new MetaLineAction( ImplMap( rSource), ImplMap( rDest ), maLineStyle.aLineInfo ) );
1201 //-----------------------------------------------------------------------------------
1203 void WinMtfOutput::DrawRect( const Rectangle& rRect, BOOL bEdge )
1205 UpdateClipRegion();
1206 UpdateFillStyle();
1208 if ( aClipPath.GetType() == COMPLEX )
1210 Polygon aPoly( ImplMap( rRect ) );
1211 PolyPolygon aPolyPolyRect( aPoly );
1212 PolyPolygon aDest;
1213 aClipPath.GetClipPath().GetIntersection( aPolyPolyRect, aDest );
1214 ImplDrawClippedPolyPolygon( aDest );
1216 else
1218 if ( bEdge )
1220 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
1222 ImplSetNonPersistentLineColorTransparenz();
1223 mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
1224 UpdateLineStyle();
1225 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( ImplMap( rRect ) ),maLineStyle.aLineInfo ) );
1227 else
1229 UpdateLineStyle();
1230 mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
1233 else
1235 ImplSetNonPersistentLineColorTransparenz();
1236 mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
1241 //-----------------------------------------------------------------------------------
1243 void WinMtfOutput::DrawRoundRect( const Rectangle& rRect, const Size& rSize )
1245 UpdateClipRegion();
1246 UpdateLineStyle();
1247 UpdateFillStyle();
1248 mpGDIMetaFile->AddAction( new MetaRoundRectAction( ImplMap( rRect ), labs( ImplMap( rSize ).Width() ), labs( ImplMap( rSize ).Height() ) ) );
1251 //-----------------------------------------------------------------------------------
1253 void WinMtfOutput::DrawEllipse( const Rectangle& rRect )
1255 UpdateClipRegion();
1256 UpdateFillStyle();
1258 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
1260 Point aCenter( ImplMap( rRect.Center() ) );
1261 Size aRad( ImplMap( Size( rRect.GetWidth() / 2, rRect.GetHeight() / 2 ) ) );
1263 ImplSetNonPersistentLineColorTransparenz();
1264 mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
1265 UpdateLineStyle();
1266 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
1268 else
1270 UpdateLineStyle();
1271 mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
1275 //-----------------------------------------------------------------------------------
1277 void WinMtfOutput::DrawArc( const Rectangle& rRect, const Point& rStart, const Point& rEnd, BOOL bTo )
1279 UpdateClipRegion();
1280 UpdateLineStyle();
1281 UpdateFillStyle();
1283 Rectangle aRect( ImplMap( rRect ) );
1284 Point aStart( ImplMap( rStart ) );
1285 Point aEnd( ImplMap( rEnd ) );
1287 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
1289 if ( aStart == aEnd )
1290 { // SJ: #i53768# if start & end is identical, then we have to draw a full ellipse
1291 Point aCenter( aRect.Center() );
1292 Size aRad( aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
1294 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
1296 else
1297 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_ARC ), maLineStyle.aLineInfo ) );
1299 else
1300 mpGDIMetaFile->AddAction( new MetaArcAction( aRect, aStart, aEnd ) );
1302 if ( bTo )
1303 maActPos = aEnd;
1306 //-----------------------------------------------------------------------------------
1308 void WinMtfOutput::DrawPie( const Rectangle& rRect, const Point& rStart, const Point& rEnd )
1310 UpdateClipRegion();
1311 UpdateFillStyle();
1313 Rectangle aRect( ImplMap( rRect ) );
1314 Point aStart( ImplMap( rStart ) );
1315 Point aEnd( ImplMap( rEnd ) );
1317 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
1319 ImplSetNonPersistentLineColorTransparenz();
1320 mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
1321 UpdateLineStyle();
1322 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_PIE ), maLineStyle.aLineInfo ) );
1324 else
1326 UpdateLineStyle();
1327 mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
1331 //-----------------------------------------------------------------------------------
1333 void WinMtfOutput::DrawChord( const Rectangle& rRect, const Point& rStart, const Point& rEnd )
1335 UpdateClipRegion();
1336 UpdateFillStyle();
1338 Rectangle aRect( ImplMap( rRect ) );
1339 Point aStart( ImplMap( rStart ) );
1340 Point aEnd( ImplMap( rEnd ) );
1342 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
1344 ImplSetNonPersistentLineColorTransparenz();
1345 mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
1346 UpdateLineStyle();
1347 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_CHORD ), maLineStyle.aLineInfo ) );
1349 else
1351 UpdateLineStyle();
1352 mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
1356 //-----------------------------------------------------------------------------------
1358 void WinMtfOutput::DrawPolygon( Polygon& rPolygon, sal_Bool bRecordPath )
1360 UpdateClipRegion();
1361 ImplMap( rPolygon );
1362 if ( bRecordPath )
1363 aPathObj.AddPolygon( rPolygon );
1364 else
1366 UpdateFillStyle();
1368 if ( aClipPath.GetType() == COMPLEX )
1370 PolyPolygon aPolyPoly( rPolygon );
1371 PolyPolygon aDest;
1372 aClipPath.GetClipPath().GetIntersection( aPolyPoly, aDest );
1373 ImplDrawClippedPolyPolygon( aDest );
1375 else
1377 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
1379 USHORT nCount = rPolygon.GetSize();
1380 if ( nCount )
1382 if ( rPolygon[ nCount - 1 ] != rPolygon[ 0 ] )
1384 Point aPoint( rPolygon[ 0 ] );
1385 rPolygon.Insert( nCount, aPoint );
1388 ImplSetNonPersistentLineColorTransparenz();
1389 mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
1390 UpdateLineStyle();
1391 mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
1393 else
1395 UpdateLineStyle();
1397 if (maLatestFillStyle.aType != FillStylePattern)
1398 mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
1399 else {
1400 SvtGraphicFill aFill = SvtGraphicFill( PolyPolygon( rPolygon ),
1401 Color(),
1402 0.0,
1403 SvtGraphicFill::fillNonZero,
1404 SvtGraphicFill::fillTexture,
1405 SvtGraphicFill::Transform(),
1406 true,
1407 SvtGraphicFill::hatchSingle,
1408 Color(),
1409 SvtGraphicFill::gradientLinear,
1410 Color(),
1411 Color(),
1413 Graphic (maLatestFillStyle.aBmp) );
1415 SvMemoryStream aMemStm;
1417 aMemStm << aFill;
1419 mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1420 static_cast<const BYTE*>(aMemStm.GetData()),
1421 aMemStm.Seek( STREAM_SEEK_TO_END ) ) );
1422 mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_END" ) );
1430 //-----------------------------------------------------------------------------------
1432 void WinMtfOutput::DrawPolyPolygon( PolyPolygon& rPolyPolygon, sal_Bool bRecordPath )
1434 UpdateClipRegion();
1436 ImplMap( rPolyPolygon );
1438 if ( bRecordPath )
1439 aPathObj.AddPolyPolygon( rPolyPolygon );
1440 else
1442 UpdateFillStyle();
1444 if ( aClipPath.GetType() == COMPLEX )
1446 PolyPolygon aDest;
1447 aClipPath.GetClipPath().GetIntersection( rPolyPolygon, aDest );
1448 ImplDrawClippedPolyPolygon( aDest );
1450 else
1452 UpdateLineStyle();
1453 mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPolygon ) );
1458 //-----------------------------------------------------------------------------------
1460 void WinMtfOutput::DrawPolyLine( Polygon& rPolygon, sal_Bool bTo, sal_Bool bRecordPath )
1462 UpdateClipRegion();
1464 ImplMap( rPolygon );
1465 if ( bTo )
1467 rPolygon[ 0 ] = maActPos;
1468 maActPos = rPolygon[ rPolygon.GetSize() - 1 ];
1470 if ( bRecordPath )
1471 aPathObj.AddPolyLine( rPolygon );
1472 else
1474 UpdateLineStyle();
1475 mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
1479 //-----------------------------------------------------------------------------------
1481 void WinMtfOutput::DrawPolyBezier( Polygon& rPolygon, sal_Bool bTo, sal_Bool bRecordPath )
1483 UpdateClipRegion();
1485 sal_uInt16 nPoints = rPolygon.GetSize();
1486 if ( ( nPoints >= 4 ) && ( ( ( nPoints - 4 ) % 3 ) == 0 ) )
1488 ImplMap( rPolygon );
1489 if ( bTo )
1491 rPolygon[ 0 ] = maActPos;
1492 maActPos = rPolygon[ nPoints - 1 ];
1494 sal_uInt16 i;
1495 for ( i = 0; ( i + 2 ) < nPoints; )
1497 rPolygon.SetFlags( i++, POLY_NORMAL );
1498 rPolygon.SetFlags( i++, POLY_CONTROL );
1499 rPolygon.SetFlags( i++, POLY_CONTROL );
1501 if ( bRecordPath )
1502 aPathObj.AddPolyLine( rPolygon );
1503 else
1505 UpdateLineStyle();
1506 mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
1511 //-----------------------------------------------------------------------------------
1513 void WinMtfOutput::DrawText( Point& rPosition, String& rText, sal_Int32* pDXArry, sal_Bool bRecordPath, sal_Int32 nGfxMode )
1515 UpdateClipRegion();
1517 VirtualDevice* pVDev = NULL;
1519 rPosition = ImplMap( rPosition );
1521 sal_Int32 nOldGfxMode = GetGfxMode();
1522 SetGfxMode( GM_COMPATIBLE );
1523 if ( pDXArry )
1525 sal_Int32 i, nSum, nLen = rText.Len();
1527 for( i = 0, nSum = 0; i < nLen; i++ )
1529 sal_Int32 nTemp = ImplMap( Size( pDXArry[ i ], 0 ) ).Width();
1530 nSum += nTemp;
1531 pDXArry[ i ] = nSum;
1534 if ( mnLatestTextLayoutMode != mnTextLayoutMode )
1536 mnLatestTextLayoutMode = mnTextLayoutMode;
1537 mpGDIMetaFile->AddAction( new MetaLayoutModeAction( mnTextLayoutMode ) );
1539 SetGfxMode( nGfxMode );
1540 sal_Bool bChangeFont = sal_False;
1541 if ( mnLatestTextAlign != mnTextAlign )
1543 bChangeFont = sal_True;
1544 mnLatestTextAlign = mnTextAlign;
1545 TextAlign eTextAlign;
1546 if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE )
1547 eTextAlign = ALIGN_BASELINE;
1548 else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM )
1549 eTextAlign = ALIGN_BOTTOM;
1550 else
1551 eTextAlign = ALIGN_TOP;
1552 mpGDIMetaFile->AddAction( new MetaTextAlignAction( eTextAlign ) );
1554 if ( maLatestTextColor != maTextColor )
1556 bChangeFont = sal_True;
1557 maLatestTextColor = maTextColor;
1558 mpGDIMetaFile->AddAction( new MetaTextColorAction( maTextColor ) );
1560 sal_Bool bChangeFillColor = sal_False;
1561 if ( maLatestBkColor != maBkColor )
1563 bChangeFillColor = sal_True;
1564 maLatestBkColor = maBkColor;
1566 if ( mnLatestBkMode != mnBkMode )
1568 bChangeFillColor = sal_True;
1569 mnLatestBkMode = mnBkMode;
1571 if ( bChangeFillColor )
1573 bChangeFont = sal_True;
1574 mpGDIMetaFile->AddAction( new MetaTextFillColorAction( maFont.GetFillColor(), !maFont.IsTransparent() ) );
1576 Font aTmp( maFont );
1577 aTmp.SetColor( maTextColor );
1578 aTmp.SetFillColor( maBkColor );
1580 if( mnBkMode == TRANSPARENT )
1581 maFont.SetTransparent( sal_True );
1582 else
1583 maFont.SetTransparent( sal_False );
1585 if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE )
1586 aTmp.SetAlign( ALIGN_BASELINE );
1587 else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM )
1588 aTmp.SetAlign( ALIGN_BOTTOM );
1589 else
1590 aTmp.SetAlign( ALIGN_TOP );
1592 if ( nGfxMode == GM_ADVANCED )
1594 // check whether there is a font rotation applied via transformation
1595 Point aP1( ImplMap( Point() ) );
1596 Point aP2( ImplMap( Point( 0, 100 ) ) );
1597 aP2.X() -= aP1.X();
1598 aP2.Y() -= aP1.Y();
1599 double fX = aP2.X();
1600 double fY = aP2.Y();
1601 if ( fX )
1603 double fOrientation = acos( fX / sqrt( fX * fX + fY * fY ) ) * 57.29577951308;
1604 if ( fY > 0 )
1605 fOrientation = 360 - fOrientation;
1606 fOrientation += 90;
1607 fOrientation *= 10;
1608 fOrientation += aTmp.GetOrientation();
1609 aTmp.SetOrientation( sal_Int16( fOrientation ) );
1613 if( mnTextAlign & ( TA_UPDATECP | TA_RIGHT_CENTER ) )
1615 if ( !pVDev )
1616 pVDev = new VirtualDevice;
1617 sal_Int32 nTextWidth;
1618 pVDev->SetMapMode( MapMode( MAP_100TH_MM ) );
1619 pVDev->SetFont( maFont );
1620 if( pDXArry )
1622 UINT32 nLen = rText.Len();
1623 nTextWidth = pVDev->GetTextWidth( rText.GetChar( (sal_uInt16)( nLen - 1 ) ) );
1624 if( nLen > 1 )
1625 nTextWidth += pDXArry[ nLen - 2 ];
1627 else
1628 nTextWidth = pVDev->GetTextWidth( rText );
1630 if( mnTextAlign & TA_UPDATECP )
1631 rPosition = maActPos;
1633 if ( mnTextAlign & TA_RIGHT_CENTER )
1635 double fLenght = ( ( mnTextAlign & TA_RIGHT_CENTER ) == TA_RIGHT ) ? nTextWidth : nTextWidth >> 1;
1636 rPosition.X() -= (sal_Int32)( fLenght * cos( maFont.GetOrientation() * F_PI1800 ) );
1637 rPosition.Y() -= (sal_Int32)(-( fLenght * sin( maFont.GetOrientation() * F_PI1800 ) ) );
1640 if( mnTextAlign & TA_UPDATECP )
1641 maActPos.X() = rPosition.X() + nTextWidth;
1643 if ( bChangeFont || ( maLatestFont != aTmp ) )
1645 maLatestFont = aTmp;
1646 mpGDIMetaFile->AddAction( new MetaFontAction( aTmp ) );
1647 mpGDIMetaFile->AddAction( new MetaTextAlignAction( aTmp.GetAlign() ) );
1648 mpGDIMetaFile->AddAction( new MetaTextColorAction( aTmp.GetColor() ) );
1649 mpGDIMetaFile->AddAction( new MetaTextFillColorAction( aTmp.GetFillColor(), !aTmp.IsTransparent() ) );
1651 if ( bRecordPath )
1653 // ToDo
1655 else
1657 /* because text without dx array is badly scaled, we
1658 will create such an array if necessary */
1659 sal_Int32* pDX = pDXArry;
1660 if ( !pDXArry )
1662 pDX = new sal_Int32[ rText.Len() ];
1663 if ( !pVDev )
1664 pVDev = new VirtualDevice;
1665 pVDev->SetMapMode( MAP_100TH_MM );
1666 pVDev->SetFont( maLatestFont );
1667 pVDev->GetTextArray( rText, pDX, 0, STRING_LEN );
1669 mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition, rText, pDX, 0, STRING_LEN ) );
1670 if ( !pDXArry ) // this means we have created our own array
1671 delete[] pDX; // which must be deleted
1673 SetGfxMode( nOldGfxMode );
1674 delete pVDev;
1677 //-----------------------------------------------------------------------------------
1679 void WinMtfOutput::ImplDrawBitmap( const Point& rPos, const Size& rSize, const BitmapEx rBitmap )
1681 BitmapEx aBmpEx( rBitmap );
1682 if ( aClipPath.GetType() == COMPLEX )
1684 VirtualDevice aVDev;
1685 MapMode aMapMode( MAP_100TH_MM );
1686 aMapMode.SetOrigin( Point( -rPos.X(), -rPos.Y() ) );
1687 const Size aOutputSizePixel( aVDev.LogicToPixel( rSize, aMapMode ) );
1688 const Size aSizePixel( rBitmap.GetSizePixel() );
1689 if ( aOutputSizePixel.Width() && aOutputSizePixel.Height() )
1691 aMapMode.SetScaleX( Fraction( aSizePixel.Width(), aOutputSizePixel.Width() ) );
1692 aMapMode.SetScaleY( Fraction( aSizePixel.Height(), aOutputSizePixel.Height() ) );
1694 aVDev.SetMapMode( aMapMode );
1695 aVDev.SetOutputSizePixel( aSizePixel );
1696 aVDev.SetFillColor( Color( COL_BLACK ) );
1697 const PolyPolygon aClip( aClipPath.GetClipPath() );
1698 aVDev.DrawPolyPolygon( aClip );
1699 const Point aEmptyPoint;
1701 // #i50672# Extract whole VDev content (to match size of rBitmap)
1702 aVDev.EnableMapMode( FALSE );
1703 Bitmap aMask( aVDev.GetBitmap( aEmptyPoint, aSizePixel ).CreateMask( Color( COL_WHITE ) ) );
1705 if ( aBmpEx.IsTransparent() )
1707 if ( rBitmap.GetTransparentColor() == Color( COL_WHITE ) )
1708 aMask.CombineSimple( rBitmap.GetMask(), BMP_COMBINE_OR );
1709 else
1710 aMask.CombineSimple( rBitmap.GetMask(), BMP_COMBINE_AND );
1711 aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask );
1713 else
1714 aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask );
1716 if ( aBmpEx.IsTransparent() )
1717 mpGDIMetaFile->AddAction( new MetaBmpExScaleAction( rPos, rSize, aBmpEx ) );
1718 else
1719 mpGDIMetaFile->AddAction( new MetaBmpScaleAction( rPos, rSize, aBmpEx.GetBitmap() ) );
1722 //-----------------------------------------------------------------------------------
1724 void WinMtfOutput::ResolveBitmapActions( List& rSaveList )
1726 UpdateClipRegion();
1728 sal_uInt32 nObjects = rSaveList.Count();
1729 sal_uInt32 nObjectsLeft = nObjects;
1731 while ( nObjectsLeft )
1733 sal_uInt32 i, nObjectsOfSameSize = 0;
1734 sal_uInt32 nObjectStartIndex = nObjects - nObjectsLeft;
1736 BSaveStruct* pSave = (BSaveStruct*)rSaveList.GetObject( nObjectStartIndex );
1737 Rectangle aRect( pSave->aOutRect );
1739 for ( i = nObjectStartIndex; i < nObjects; )
1741 nObjectsOfSameSize++;
1742 if ( ++i < nObjects )
1744 pSave = (BSaveStruct*)rSaveList.GetObject( i );
1745 if ( pSave->aOutRect != aRect )
1746 break;
1749 Point aPos( ImplMap( aRect.TopLeft() ) );
1750 Size aSize( ImplMap( aRect.GetSize() ) );
1752 for ( i = nObjectStartIndex; i < ( nObjectStartIndex + nObjectsOfSameSize ); i++ )
1754 pSave = (BSaveStruct*)rSaveList.GetObject( i );
1756 sal_uInt32 nWinRop = pSave->nWinRop;
1757 sal_uInt8 nRasterOperation = (sal_uInt8)( nWinRop >> 16 );
1759 sal_uInt32 nUsed = 0;
1760 if ( ( nRasterOperation & 0xf ) != ( nRasterOperation >> 4 ) )
1761 nUsed |= 1; // pattern is used
1762 if ( ( nRasterOperation & 0x33 ) != ( ( nRasterOperation & 0xcc ) >> 2 ) )
1763 nUsed |= 2; // source is used
1764 if ( ( nRasterOperation & 0xaa ) != ( ( nRasterOperation & 0x55 ) << 1 ) )
1765 nUsed |= 4; // destination is used
1767 if ( (nUsed & 1) && (( nUsed & 2 ) == 0) && nWinRop != PATINVERT )
1768 { // patterns aren't well supported yet
1769 sal_uInt32 nOldRop = SetRasterOp( ROP_OVERPAINT ); // in this case nRasterOperation is either 0 or 0xff
1770 UpdateFillStyle();
1771 DrawRect( aRect, FALSE );
1772 SetRasterOp( nOldRop );
1774 else
1776 sal_Bool bDrawn = sal_False;
1778 if ( i == nObjectStartIndex ) // optimizing, sometimes it is possible to create just one transparent bitmap
1780 if ( nObjectsOfSameSize == 2 )
1782 BSaveStruct* pSave2 = (BSaveStruct*)rSaveList.GetObject( i + 1 );
1783 if ( ( pSave->aBmp.GetPrefSize() == pSave2->aBmp.GetPrefSize() ) &&
1784 ( pSave->aBmp.GetPrefMapMode() == pSave2->aBmp.GetPrefMapMode() ) )
1786 // TODO: Strictly speaking, we should
1787 // check whether mask is monochrome, and
1788 // whether image is black (upper branch)
1789 // or white (lower branch). Otherwise, the
1790 // effect is not the same as a masked
1791 // bitmap.
1792 if ( ( nWinRop == SRCPAINT ) && ( pSave2->nWinRop == SRCAND ) )
1794 Bitmap aMask( pSave->aBmp ); aMask.Invert();
1795 BitmapEx aBmpEx( pSave2->aBmp, aMask );
1796 ImplDrawBitmap( aPos, aSize, aBmpEx );
1797 bDrawn = sal_True;
1798 i++;
1800 // #i20085# This is just the other way
1801 // around as above. Only difference: mask
1802 // is inverted
1803 else if ( ( nWinRop == SRCAND ) && ( pSave2->nWinRop == SRCPAINT ) )
1805 Bitmap aMask( pSave->aBmp );
1806 BitmapEx aBmpEx( pSave2->aBmp, aMask );
1807 ImplDrawBitmap( aPos, aSize, aBmpEx );
1808 bDrawn = sal_True;
1809 i++;
1815 if ( !bDrawn )
1817 Push();
1818 sal_uInt32 nOldRop = SetRasterOp( R2_COPYPEN );
1819 Bitmap aBitmap( pSave->aBmp );
1820 sal_uInt32 nOperation = ( nRasterOperation & 0xf );
1821 switch( nOperation )
1823 case 0x1 :
1824 case 0xe :
1826 SetRasterOp( R2_XORPEN );
1827 ImplDrawBitmap( aPos, aSize, aBitmap );
1828 SetRasterOp( R2_COPYPEN );
1829 Bitmap aMask( aBitmap );
1830 aMask.Invert();
1831 BitmapEx aBmpEx( aBitmap, aMask );
1832 ImplDrawBitmap( aPos, aSize, aBmpEx );
1833 if ( nOperation == 0x1 )
1835 SetRasterOp( R2_NOT );
1836 DrawRect( aRect, FALSE );
1839 break;
1840 case 0x7 :
1841 case 0x8 :
1843 Bitmap aMask( aBitmap );
1844 if ( ( nUsed & 1 ) && ( nRasterOperation & 0xb0 ) == 0xb0 ) // pattern used
1846 aBitmap.Convert( BMP_CONVERSION_24BIT );
1847 aBitmap.Erase( maFillStyle.aFillColor );
1849 BitmapEx aBmpEx( aBitmap, aMask );
1850 ImplDrawBitmap( aPos, aSize, aBmpEx );
1851 if ( nOperation == 0x7 )
1853 SetRasterOp( R2_NOT );
1854 DrawRect( aRect, FALSE );
1857 break;
1859 case 0x4 :
1860 case 0xb :
1862 SetRasterOp( R2_NOT );
1863 DrawRect( aRect, FALSE );
1864 SetRasterOp( R2_COPYPEN );
1865 Bitmap aMask( aBitmap );
1866 aBitmap.Invert();
1867 BitmapEx aBmpEx( aBitmap, aMask );
1868 ImplDrawBitmap( aPos, aSize, aBmpEx );
1869 SetRasterOp( R2_XORPEN );
1870 ImplDrawBitmap( aPos, aSize, aBitmap );
1871 if ( nOperation == 0xb )
1873 SetRasterOp( R2_NOT );
1874 DrawRect( aRect, FALSE );
1877 break;
1879 case 0x2 :
1880 case 0xd :
1882 Bitmap aMask( aBitmap );
1883 aMask.Invert();
1884 BitmapEx aBmpEx( aBitmap, aMask );
1885 ImplDrawBitmap( aPos, aSize, aBmpEx );
1886 SetRasterOp( R2_XORPEN );
1887 ImplDrawBitmap( aPos, aSize, aBitmap );
1888 if ( nOperation == 0xd )
1890 SetRasterOp( R2_NOT );
1891 DrawRect( aRect, FALSE );
1894 break;
1895 case 0x6 :
1896 case 0x9 :
1898 SetRasterOp( R2_XORPEN );
1899 ImplDrawBitmap( aPos, aSize, aBitmap );
1900 if ( nOperation == 0x9 )
1902 SetRasterOp( R2_NOT );
1903 DrawRect( aRect, FALSE );
1906 break;
1908 case 0x0 : // WHITENESS
1909 case 0xf : // BLACKNESS
1910 { // in this case nRasterOperation is either 0 or 0xff
1911 maFillStyle = WinMtfFillStyle( Color( nRasterOperation, nRasterOperation, nRasterOperation ) );
1912 UpdateFillStyle();
1913 DrawRect( aRect, FALSE );
1915 break;
1917 case 0x3 : // only source is used
1918 case 0xc :
1920 if ( nRasterOperation == 0x33 )
1921 aBitmap.Invert();
1922 ImplDrawBitmap( aPos, aSize, aBitmap );
1924 break;
1926 case 0x5 : // only destination is used
1928 SetRasterOp( R2_NOT );
1929 DrawRect( aRect, FALSE );
1931 case 0xa : // no operation
1932 break;
1934 SetRasterOp( nOldRop );
1935 Pop();
1939 nObjectsLeft -= nObjectsOfSameSize;
1942 void* pPtr;
1943 for ( pPtr = rSaveList.First(); pPtr; pPtr = rSaveList.Next() )
1944 delete (BSaveStruct*)pPtr;
1945 rSaveList.Clear();
1948 //-----------------------------------------------------------------------------------
1950 void WinMtfOutput::SetDevOrg( const Point& rPoint )
1952 mnDevOrgX = rPoint.X();
1953 mnDevOrgY = rPoint.Y();
1956 //-----------------------------------------------------------------------------------
1958 void WinMtfOutput::SetDevOrgOffset( INT32 nXAdd, INT32 nYAdd )
1960 mnDevOrgX += nXAdd;
1961 mnDevOrgY += nYAdd;
1964 //-----------------------------------------------------------------------------------
1966 void WinMtfOutput::SetDevExt( const Size& rSize )
1968 if ( rSize.Width() && rSize.Height() )
1970 switch( mnMapMode )
1972 case MM_ISOTROPIC :
1973 case MM_ANISOTROPIC :
1975 mnDevWidth = rSize.Width();
1976 mnDevHeight = rSize.Height();
1982 //-----------------------------------------------------------------------------------
1984 void WinMtfOutput::ScaleDevExt( double fX, double fY )
1986 mnDevWidth = FRound( mnDevWidth * fX );
1987 mnDevHeight = FRound( mnDevHeight * fY );
1990 //-----------------------------------------------------------------------------------
1992 void WinMtfOutput::SetWinOrg( const Point& rPoint )
1994 mnWinOrgX = rPoint.X();
1995 mnWinOrgY = rPoint.Y();
1998 //-----------------------------------------------------------------------------------
2000 void WinMtfOutput::SetWinOrgOffset( INT32 nXAdd, INT32 nYAdd )
2002 mnWinOrgX += nXAdd;
2003 mnWinOrgY += nYAdd;
2006 //-----------------------------------------------------------------------------------
2008 void WinMtfOutput::SetWinExt( const Size& rSize )
2011 if( rSize.Width() && rSize.Height() )
2013 switch( mnMapMode )
2015 case MM_ISOTROPIC :
2016 case MM_ANISOTROPIC :
2018 mnWinExtX = rSize.Width();
2019 mnWinExtY = rSize.Height();
2025 //-----------------------------------------------------------------------------------
2027 void WinMtfOutput::ScaleWinExt( double fX, double fY )
2029 mnWinExtX = FRound( mnWinExtX * fX );
2030 mnWinExtY = FRound( mnWinExtY * fY );
2033 //-----------------------------------------------------------------------------------
2035 void WinMtfOutput::SetrclBounds( const Rectangle& rRect )
2037 mrclBounds = rRect;
2040 //-----------------------------------------------------------------------------------
2042 void WinMtfOutput::SetrclFrame( const Rectangle& rRect )
2044 mrclFrame = rRect;
2047 //-----------------------------------------------------------------------------------
2049 void WinMtfOutput::SetRefPix( const Size& rSize )
2051 mnPixX = rSize.Width();
2052 mnPixY = rSize.Height();
2055 //-----------------------------------------------------------------------------------
2057 void WinMtfOutput::SetRefMill( const Size& rSize )
2059 mnMillX = rSize.Width();
2060 mnMillY = rSize.Height();
2063 //-----------------------------------------------------------------------------------
2065 void WinMtfOutput::SetMapMode( sal_uInt32 nMapMode )
2067 mnMapMode = nMapMode;
2068 if ( nMapMode == MM_TEXT )
2070 mnWinExtX = mnDevWidth;
2071 mnWinExtY = mnDevHeight;
2073 else if ( mnMapMode == MM_HIMETRIC )
2075 mnWinExtX = mnMillX * 100;
2076 mnWinExtY = mnMillY * 100;
2080 //-----------------------------------------------------------------------------------
2082 void WinMtfOutput::SetUnitsPerInch( UINT16 nUnitsPerInch )
2084 if( nUnitsPerInch != 0 )
2085 mnUnitsPerInch = nUnitsPerInch;
2088 //-----------------------------------------------------------------------------------
2090 void WinMtfOutput::SetWorldTransform( const XForm& rXForm )
2092 maXForm.eM11 = rXForm.eM11;
2093 maXForm.eM12 = rXForm.eM12;
2094 maXForm.eM21 = rXForm.eM21;
2095 maXForm.eM22 = rXForm.eM22;
2096 maXForm.eDx = rXForm.eDx;
2097 maXForm.eDy = rXForm.eDy;
2100 //-----------------------------------------------------------------------------------
2102 void WinMtfOutput::ModifyWorldTransform( const XForm& rXForm, UINT32 nMode )
2104 switch( nMode )
2106 case MWT_IDENTITY :
2108 maXForm.eM11 = maXForm.eM12 = maXForm.eM21 = maXForm.eM22 = 1.0f;
2109 maXForm.eDx = maXForm.eDx = 0.0f;
2111 break;
2113 case MWT_RIGHTMULTIPLY :
2114 case MWT_LEFTMULTIPLY :
2116 const XForm* pLeft;
2117 const XForm* pRight;
2119 if ( nMode == MWT_LEFTMULTIPLY )
2121 pLeft = &rXForm;
2122 pRight = &maXForm;
2124 else
2126 pLeft = &maXForm;
2127 pRight = &rXForm;
2130 float aF[3][3];
2131 float bF[3][3];
2132 float cF[3][3];
2134 aF[0][0] = pLeft->eM11;
2135 aF[0][1] = pLeft->eM12;
2136 aF[0][2] = 0;
2137 aF[1][0] = pLeft->eM21;
2138 aF[1][1] = pLeft->eM22;
2139 aF[1][2] = 0;
2140 aF[2][0] = pLeft->eDx;
2141 aF[2][1] = pLeft->eDy;
2142 aF[2][2] = 1;
2144 bF[0][0] = pRight->eM11;
2145 bF[0][1] = pRight->eM12;
2146 bF[0][2] = 0;
2147 bF[1][0] = pRight->eM21;
2148 bF[1][1] = pRight->eM22;
2149 bF[1][2] = 0;
2150 bF[2][0] = pRight->eDx;
2151 bF[2][1] = pRight->eDy;
2152 bF[2][2] = 1;
2154 int i, j, k;
2155 for ( i = 0; i < 3; i++ )
2157 for ( j = 0; j < 3; j++ )
2159 cF[i][j] = 0;
2160 for ( k = 0; k < 3; k++ )
2161 cF[i][j] += aF[i][k] * bF[k][j];
2164 maXForm.eM11 = cF[0][0];
2165 maXForm.eM12 = cF[0][1];
2166 maXForm.eM21 = cF[1][0];
2167 maXForm.eM22 = cF[1][1];
2168 maXForm.eDx = cF[2][0];
2169 maXForm.eDy = cF[2][1];
2171 break;
2175 //-----------------------------------------------------------------------------------
2177 void WinMtfOutput::Push() // !! to be able to access the original ClipRegion it
2178 { // is not allowed to use the MetaPushAction()
2179 UpdateClipRegion(); // (the original clip region is on top of the stack) (SJ)
2180 SaveStructPtr pSave( new SaveStruct );
2182 pSave->aLineStyle = maLineStyle;
2183 pSave->aFillStyle = maFillStyle;
2185 pSave->aFont = maFont;
2186 pSave->aTextColor = maTextColor;
2187 pSave->nTextAlign = mnTextAlign;
2188 pSave->nTextLayoutMode = mnTextLayoutMode;
2189 pSave->nMapMode = mnMapMode;
2190 pSave->nGfxMode = mnGfxMode;
2191 pSave->nBkMode = mnBkMode;
2192 pSave->aBkColor = maBkColor;
2193 pSave->bFillStyleSelected = mbFillStyleSelected;
2195 pSave->aActPos = maActPos;
2196 pSave->aXForm = maXForm;
2197 pSave->eRasterOp = meRasterOp;
2199 pSave->nWinOrgX = mnWinOrgX;
2200 pSave->nWinOrgY = mnWinOrgY;
2201 pSave->nWinExtX = mnWinExtX;
2202 pSave->nWinExtY = mnWinExtY;
2203 pSave->nDevOrgX = mnDevOrgX;
2204 pSave->nDevOrgY = mnDevOrgY;
2205 pSave->nDevWidth = mnDevWidth;
2206 pSave->nDevHeight = mnDevHeight;
2208 pSave->aPathObj = aPathObj;
2209 pSave->aClipPath = aClipPath;
2211 vSaveStack.push_back( pSave );
2214 //-----------------------------------------------------------------------------------
2216 void WinMtfOutput::Pop()
2218 // Die aktuellen Daten vom Stack holen
2219 if( vSaveStack.size() )
2221 // Die aktuelle Daten auf dem Stack sichern
2222 SaveStructPtr pSave( vSaveStack.back() );
2224 maLineStyle = pSave->aLineStyle;
2225 maFillStyle = pSave->aFillStyle;
2227 maFont = pSave->aFont;
2228 maTextColor = pSave->aTextColor;
2229 mnTextAlign = pSave->nTextAlign;
2230 mnTextLayoutMode = pSave->nTextLayoutMode;
2231 mnBkMode = pSave->nBkMode;
2232 mnGfxMode = pSave->nGfxMode;
2233 mnMapMode = pSave->nMapMode;
2234 maBkColor = pSave->aBkColor;
2235 mbFillStyleSelected = pSave->bFillStyleSelected;
2237 maActPos = pSave->aActPos;
2238 maXForm = pSave->aXForm;
2239 meRasterOp = pSave->eRasterOp;
2241 mnWinOrgX = pSave->nWinOrgX;
2242 mnWinOrgY = pSave->nWinOrgY;
2243 mnWinExtX = pSave->nWinExtX;
2244 mnWinExtY = pSave->nWinExtY;
2245 mnDevOrgX = pSave->nDevOrgX;
2246 mnDevOrgY = pSave->nDevOrgY;
2247 mnDevWidth = pSave->nDevWidth;
2248 mnDevHeight = pSave->nDevHeight;
2250 aPathObj = pSave->aPathObj;
2251 if ( ! ( aClipPath == pSave->aClipPath ) )
2253 aClipPath = pSave->aClipPath;
2254 aClipPath.bNeedsUpdate = sal_True;
2256 if ( meLatestRasterOp != meRasterOp )
2257 mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
2258 vSaveStack.pop_back();
2262 void WinMtfOutput::PassEMFPlusHeaderInfo()
2264 EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS header info\n"));
2266 SvMemoryStream mem;
2267 sal_Int32 nLeft, nRight, nTop, nBottom;
2269 nLeft = mrclFrame.Left();
2270 nTop = mrclFrame.Top();
2271 nRight = mrclFrame.Right();
2272 nBottom = mrclFrame.Bottom();
2274 // emf header info
2275 mem << nLeft << nTop << nRight << nBottom;
2276 mem << mnPixX << mnPixY << mnMillX << mnMillY;
2278 float one, zero;
2280 one = 1;
2281 zero = 0;
2283 // add transformation matrix to be used in vcl's metaact.cxx for
2284 // rotate and scale operations
2285 mem << one << zero << zero << one << zero << zero;
2287 mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS_HEADER_INFO", 0, (const BYTE*) mem.GetData(), mem.GetSize() ) );
2288 mpGDIMetaFile->UseCanvas( TRUE );
2291 void WinMtfOutput::PassEMFPlus( void* pBuffer, UINT32 nLength )
2293 EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS comment length %d\n", nLength));
2294 mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS", 0, static_cast<const BYTE*>(pBuffer), nLength ) );