bump product version to 4.1.6.2
[LibreOffice.git] / filter / source / graphicfilter / epict / epict.cxx
blob60419f7c78e60a2024390bf89c4318ca29c8bf52
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/metaact.hxx>
21 #include <vcl/graphicfilter.hxx>
22 #include <svl/solar.hrc>
23 #include <vcl/fltcall.hxx>
25 #include <math.h>
26 #include <vcl/bmpacc.hxx>
27 #include <vcl/graph.hxx>
28 #include <vcl/gradient.hxx>
29 #include <vcl/hatch.hxx>
30 #include <vcl/metric.hxx>
31 #include <vcl/font.hxx>
32 #include <vcl/virdev.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/msgbox.hxx>
35 #include <vcl/gdimtf.hxx>
36 #include <tools/bigint.hxx>
38 #include <basegfx/polygon/b2dpolygon.hxx>
39 #include <basegfx/polygon/b2dpolypolygon.hxx>
41 //============================== PictWriter ===================================
43 struct PictWriterAttrStackMember {
44 struct PictWriterAttrStackMember * pSucc;
45 Color aLineColor;
46 Color aFillColor;
47 RasterOp eRasterOp;
48 Font aFont;
49 MapMode aMapMode;
50 Rectangle aClipRect;
54 enum PictDrawingMethod {
55 PDM_FRAME, PDM_PAINT, PDM_ERASE, PDM_INVERT, PDM_FILL
59 struct PictPattern {
60 sal_uInt32 nLo, nHi;
63 class PictWriter {
65 private:
67 sal_Bool bStatus;
68 sal_uLong nLastPercent; // with which number pCallback has been called the last time
69 com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
71 SvStream * pPict;
73 // current attributes in the source-metafile:
74 Color aLineColor;
75 Color aFillColor;
76 RasterOp eSrcRasterOp;
77 Font aSrcFont;
78 MapMode aSrcMapMode;
79 MapMode aTargetMapMode;
80 Rectangle aClipRect;
81 PictWriterAttrStackMember * pAttrStack;
83 // current attributes in the target-metafile and whether they are valid
84 sal_Bool bDstBkPatValid;
85 sal_uInt8 nDstTxFace; sal_Bool bDstTxFaceValid;
86 RasterOp eDstTxMode; sal_Bool bDstTxModeValid;
87 sal_uInt16 nDstPnSize; sal_Bool bDstPnSizeValid;
88 RasterOp eDstPnMode; sal_Bool bDstPnModeValid;
89 PictPattern aDstPnPat; sal_Bool bDstPnPatValid;
90 sal_Bool bDstFillPatValid;
91 sal_uInt16 nDstTxSize; sal_Bool bDstTxSizeValid;
92 Color aDstFgCol; sal_Bool bDstFgColValid;
93 Color aDstBkCol; sal_Bool bDstBkColValid;
94 Point aDstPenPosition; sal_Bool bDstPenPositionValid;
95 Point aDstTextPosition; sal_Bool bDstTextPositionValid;
96 String aDstFontName; sal_uInt16 nDstFontNameId; sal_Bool bDstFontNameValid;
98 sal_uLong nNumberOfActions; // number of actions in the GDIMetafile
99 sal_uLong nNumberOfBitmaps; // number of bitmaps
100 sal_uLong nWrittenActions; // number of already processed actions during writing the Opcodes
101 sal_uLong nWrittenBitmaps; // number of already written Bitmaps
102 sal_uLong nActBitmapPercent; // what percentage of the next bitmap is already written
104 void MayCallback();
105 // calculates a percentage on the basis of the 5 parameters above
106 // and then does a Callback should the situation arise. Sets bStatus to sal_False
107 // if the user wants to cancel
109 void CountActionsAndBitmaps(const GDIMetaFile & rMTF);
110 // counts the bitmaps and actions (nNumberOfActions and nNumberOfBitmaps
111 // have to be set to 0 at the beginning, since this method is recursive)
113 Polygon PolyPolygonToPolygon(const PolyPolygon & rPoly);
114 // generates a relatively sane polygon on the basis of a PolyPolygon
116 Rectangle MapRectangle( const Rectangle& rRect );
117 void WritePoint(const Point & rPoint);
118 void WriteSize(const Size & rSize);
119 void WriteRGBColor(const Color & rColor);
120 void WriteString( const String & rString );
121 void WriteRectangle(const Rectangle & rRect);
122 void WritePolygon(const Polygon & rPoly);
123 void WriteArcAngles(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt);
125 void ConvertLinePattern(PictPattern & rPat, sal_Bool bVisible) const;
126 void ConvertFillPattern(PictPattern & rPat, sal_Bool bVisible) const;
128 void WriteOpcode_TxFace(const Font & rFont);
129 void WriteOpcode_TxMode(RasterOp eMode);
130 void WriteOpcode_PnSize(sal_uInt16 nSize);
131 void WriteOpcode_PnMode(RasterOp eMode);
132 void WriteOpcode_PnLinePat(sal_Bool bVisible);
133 void WriteOpcode_PnFillPat(sal_Bool bVisible);
134 void WriteOpcode_OvSize(const Size & rSize);
135 void WriteOpcode_TxSize(sal_uInt16 nSize);
136 void WriteOpcode_RGBFgCol(const Color & rColor);
137 void WriteOpcode_RGBBkCol(const Color & rColor);
138 void WriteOpcode_Line(const Point & rLocPt, const Point & rNewPt);
139 void WriteOpcode_LineFrom(const Point & rNewPt);
140 void WriteOpcode_Text(const Point & rPoint, const String& rString, sal_Bool bDelta);
141 void WriteOpcode_FontName(const Font & rFont);
142 void WriteOpcode_ClipRect( const Rectangle& rRect );
143 void WriteOpcode_Rect(PictDrawingMethod eMethod, const Rectangle & rRect);
144 void WriteOpcode_SameRect(PictDrawingMethod eMethod);
145 void WriteOpcode_RRect(PictDrawingMethod eMethod, const Rectangle & rRect);
146 void WriteOpcode_SameRRect(PictDrawingMethod eMethod);
147 void WriteOpcode_Oval(PictDrawingMethod eMethod, const Rectangle & rRect);
148 void WriteOpcode_SameOval(PictDrawingMethod eMethod);
149 void WriteOpcode_Arc(PictDrawingMethod eMethod, const Rectangle & rRect,
150 const Point & rStartPt, const Point & rEndPt);
151 void WriteOpcode_SameArc(PictDrawingMethod eMethod, const Rectangle & rRect,
152 const Point & rStartPt, const Point & rEndPt);
153 void WriteOpcode_Poly(PictDrawingMethod eMethod, const Polygon & rPoly);
154 void WriteOpcode_BitsRect(const Point & rPoint, const Size & rSize, const Bitmap & rBitmap);
155 void WriteOpcode_EndOfFile();
157 void SetAttrForPaint();
158 void SetAttrForFrame();
159 void SetAttrForText();
161 void WriteTextArray(Point & rPoint, const String& rString, const sal_Int32 * pDXAry);
163 void HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon);
164 void WriteOpcodes(const GDIMetaFile & rMTF);
166 void WriteHeader(const GDIMetaFile & rMTF);
167 void UpdateHeader();
169 public:
171 sal_Bool WritePict( const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem* pFilterConfigItem );
175 //========================== Methods of PictWriter ==========================
178 void PictWriter::MayCallback()
180 if ( xStatusIndicator.is() )
182 sal_uLong nPercent;
183 nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions)
184 *100
185 /((nNumberOfBitmaps<<14)+nNumberOfActions);
187 if (nPercent>=nLastPercent+3)
189 nLastPercent=nPercent;
190 if( nPercent<=100 )
191 xStatusIndicator->setValue( nPercent );
196 void PictWriter::CountActionsAndBitmaps(const GDIMetaFile & rMTF)
198 size_t nAction, nActionCount;
199 const MetaAction* pMA;
201 nActionCount = rMTF.GetActionSize();
203 for (nAction=0; nAction < nActionCount; nAction++)
205 pMA = rMTF.GetAction( nAction );
207 switch( pMA->GetType() )
209 case META_BMP_ACTION:
210 case META_BMPSCALE_ACTION:
211 case META_BMPSCALEPART_ACTION:
212 case META_BMPEX_ACTION:
213 case META_BMPEXSCALE_ACTION:
214 case META_BMPEXSCALEPART_ACTION:
215 nNumberOfBitmaps++;
216 break;
219 nNumberOfActions++;
224 Polygon PictWriter::PolyPolygonToPolygon(const PolyPolygon & rPolyPoly)
226 sal_uInt16 nCount,nSize1,nSize2,np,i1,i2,i3,nBestIdx1,nBestIdx2;
227 long nDistSqr,nBestDistSqr, nCountdownTests;
228 Point aP1,aPRel;
229 Polygon aPoly1, aPoly2, aPoly3;
231 nCount=rPolyPoly.Count();
232 if (nCount==0) return Polygon(0);
234 aPoly1=rPolyPoly.GetObject(0);
235 for (np=1; np<nCount; np++) {
236 aPoly2=rPolyPoly.GetObject(np);
238 //-----------------The following code merges aPoly1 and aPoly2 to aPoly1-----------------
240 nSize1=aPoly1.GetSize();
241 nSize2=aPoly2.GetSize();
243 // At first we look for a point in aPoly1 (referenced by nBestIdx1) and a
244 // point in aPoly2 (referenced by nBestid2), which are as close together as
245 // possible. Because this is following square complexity and therefore some
246 // pictures would need infinite time to export, we limit the the number of test
247 // by the number of 1000 and cancel the search if necessary preliminarily.
248 // The result of this will not be wrong but rather not so beautiful.
249 nCountdownTests=1000;
250 nBestDistSqr=0x7fffffff;
251 nBestIdx1=0;
252 nBestIdx2=0;
253 for (i1=0; i1<nSize1; i1++) {
254 aP1=aPoly1.GetPoint(i1);
255 for (i2=0; i2<nSize2; i2++) {
256 aPRel=aPoly2.GetPoint(i2); aPRel-=aP1;
257 nDistSqr=aPRel.X()*aPRel.X()+aPRel.Y()*aPRel.Y();
258 if (nDistSqr<nBestDistSqr) {
259 nBestIdx1=i1;
260 nBestIdx2=i2;
261 nBestDistSqr=nDistSqr;
263 if (nCountdownTests<=0) break;
264 nCountdownTests--;
266 if (nCountdownTests<=0) break;
269 // Now aPoly1 and aPoly2 are being merged to a polygon aPoly3 (later aPoly1)
270 // Both polygons are being connected by two additional edges between the points found above
271 aPoly3.Clear();
272 aPoly3.SetSize(nSize1+nSize2+2);
273 i3=0;
274 for (i1=nBestIdx1; i1<nSize1; i1++) aPoly3.SetPoint(aPoly1.GetPoint(i1),i3++);
275 for (i1=0; i1<=nBestIdx1; i1++) aPoly3.SetPoint(aPoly1.GetPoint(i1),i3++);
276 for (i2=nBestIdx2; i2<nSize2; i2++) aPoly3.SetPoint(aPoly2.GetPoint(i2),i3++);
277 for (i2=0; i2<=nBestIdx2; i2++) aPoly3.SetPoint(aPoly2.GetPoint(i2),i3++);
279 aPoly1=aPoly3;
281 //-----------------------------------------------------------------------------------
284 return aPoly1;
288 void PictWriter::WritePoint(const Point & rPoint)
290 Point aPoint = OutputDevice::LogicToLogic( rPoint, aSrcMapMode, aTargetMapMode );
291 *pPict << ((short)aPoint.Y()) << ((short)aPoint.X());
295 void PictWriter::WriteSize(const Size & rSize)
297 OutputDevice::LogicToLogic( rSize, aSrcMapMode, aTargetMapMode ); // -Wall is this needed.
298 *pPict << ((short)rSize.Height()) << ((short)rSize.Width());
302 void PictWriter::WriteRGBColor(const Color & rColor)
304 const sal_uInt16 nR = ( (sal_uInt16) rColor.GetRed() << 8 ) | (sal_uInt16) rColor.GetRed();
305 const sal_uInt16 nG = ( (sal_uInt16) rColor.GetGreen() << 8 ) | (sal_uInt16) rColor.GetGreen();
306 const sal_uInt16 nB = ( (sal_uInt16) rColor.GetBlue() << 8 ) | (sal_uInt16) rColor.GetBlue();
308 *pPict << nR << nG << nB;
311 void PictWriter::WriteString( const String & rString )
313 OString aString(OUStringToOString(rString, osl_getThreadTextEncoding()));
314 sal_Int32 nLen = aString.getLength();
315 if ( nLen > 255 )
316 nLen = 255;
317 *pPict << ( (sal_uInt8)nLen );
318 for (sal_Int32 i = 0; i < nLen; ++i)
319 *pPict << aString[i];
322 Rectangle PictWriter::MapRectangle( const Rectangle& rRect )
324 Point aPoint = OutputDevice::LogicToLogic( rRect.TopLeft(), aSrcMapMode, aTargetMapMode );
325 Size aSize = OutputDevice::LogicToLogic( rRect.GetSize(), aSrcMapMode, aTargetMapMode );
326 Rectangle aRect( aPoint, aSize );
327 aRect.Justify();
328 ++aRect.Bottom();
329 ++aRect.Right();
330 return aRect;
333 void PictWriter::WriteRectangle(const Rectangle & rRect)
335 Rectangle aRect( MapRectangle( rRect ) );
336 *pPict << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left()
337 << (sal_Int16)aRect.Bottom() << (sal_Int16)aRect.Right();
340 void PictWriter::WritePolygon(const Polygon & rPoly)
342 sal_uInt16 nDataSize,i,nSize;
343 short nMinX = 0, nMinY = 0, nMaxX = 0, nMaxY = 0;
344 short nx,ny;
345 Polygon aPoly(rPoly);
347 nSize=aPoly.GetSize();
349 if (aPoly.GetPoint(0) != aPoly.GetPoint(nSize-1))
351 nSize++;
352 aPoly.SetSize(nSize);
353 aPoly.SetPoint(aPoly.GetPoint(0),nSize-1);
356 nDataSize=nSize*4+10;
357 for (i=0; i<nSize; i++)
359 Point aPoint = OutputDevice::LogicToLogic( aPoly.GetPoint( i ),
360 aSrcMapMode,
361 aTargetMapMode );
363 nx = (short) aPoint.X();
364 ny = (short) aPoint.Y();
366 if ( i==0 || nMinX>nx )
367 nMinX=nx;
368 if ( i==0 || nMinY>ny )
369 nMinY=ny;
370 if ( i==0 || nMaxX<nx )
371 nMaxX=nx;
372 if ( i==0 || nMaxY<ny )
373 nMaxY=ny;
376 *pPict << nDataSize << nMinY << nMinX << nMaxY << nMaxX;
378 for (i=0; i<nSize; i++)
379 WritePoint( aPoly.GetPoint(i) );
383 void PictWriter::WriteArcAngles(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
385 Point aStartPt = OutputDevice::LogicToLogic( rStartPt,
386 aSrcMapMode,
387 aTargetMapMode );
388 Point aEndPt = OutputDevice::LogicToLogic( rEndPt,
389 aSrcMapMode,
390 aTargetMapMode );
391 Rectangle aRect( OutputDevice::LogicToLogic( rRect.TopLeft(),
392 aSrcMapMode,
393 aTargetMapMode ),
394 OutputDevice::LogicToLogic( rRect.GetSize(),
395 aSrcMapMode,
396 aTargetMapMode ) );
397 Point aCenter;
398 double fAngS, fAngE, fdx, fdy;
399 short nStartAngle, nArcAngle;
402 aCenter=Point( ( aRect.Left() + aRect.Right() ) >> 1,
403 ( aRect.Top() + aRect.Bottom() ) >> 1 );
405 fdx=(double)(aStartPt.X()-aCenter.X());
406 fdy=(double)(aStartPt.Y()-aCenter.Y());
407 if ( fdx==0.0 && fdy==0.0 )
408 fdx=1.0;
409 fAngE=atan2(fdx,-fdy);
411 fdx=(double)(aEndPt.X()-aCenter.X());
412 fdy=(double)(aEndPt.Y()-aCenter.Y());
413 if ( fdx==0.0 && fdy==0.0 )
414 fdx=1.0;
415 fAngS=atan2(fdx,-fdy);
417 nStartAngle=(short)(fAngS*180.0/3.14159265359);
418 nArcAngle=((short)(fAngE*180.0/3.14159265359))-nStartAngle;
419 if (nArcAngle<0)
420 nArcAngle += 360;
421 *pPict << nStartAngle << nArcAngle;
425 void PictWriter::ConvertLinePattern(PictPattern & rPat, sal_Bool bVisible) const
427 if( bVisible )
429 rPat.nHi=0xffffffff;
430 rPat.nLo=0xffffffff;
432 else
434 rPat.nHi=0x00000000;
435 rPat.nLo=0x00000000;
439 void PictWriter::ConvertFillPattern(PictPattern & rPat, sal_Bool bVisible) const
441 if( bVisible )
443 rPat.nHi=0xffffffff;
444 rPat.nLo=0xffffffff;
446 else
448 rPat.nHi=0x00000000;
449 rPat.nLo=0x00000000;
454 void PictWriter::WriteOpcode_TxFace(const Font & rFont)
456 sal_uInt8 nFace;
457 FontWeight eWeight;
459 nFace=0;
460 eWeight=rFont.GetWeight();
461 if (eWeight==WEIGHT_BOLD ||
462 eWeight==WEIGHT_SEMIBOLD ||
463 eWeight==WEIGHT_ULTRABOLD ||
464 eWeight==WEIGHT_BLACK) nFace|=0x01;
465 if (rFont.GetItalic()!=ITALIC_NONE) nFace|=0x02;
466 if (rFont.GetUnderline()!=UNDERLINE_NONE) nFace|=0x04;
467 if (rFont.IsOutline()==sal_True) nFace|=0x08;
468 if (rFont.IsShadow()==sal_True) nFace|=0x10;
470 if (bDstTxFaceValid==sal_False || nDstTxFace!=nFace) {
471 *pPict << (sal_uInt16)0x0004 << nFace << (sal_uInt8)0;
472 nDstTxFace=nFace;
473 bDstTxFaceValid=sal_True;
478 void PictWriter::WriteOpcode_TxMode(RasterOp eMode)
480 sal_uInt16 nVal;
482 if (bDstTxModeValid==sal_False || eDstTxMode!=eMode) {
483 switch (eMode) {
484 case ROP_INVERT: nVal=0x000c; break;
485 case ROP_XOR: nVal=0x000a; break;
486 default: nVal=0x0008;
488 *pPict << (sal_uInt16)0x0005 << nVal;
489 eDstTxMode=eMode;
490 bDstTxModeValid=sal_True;
495 void PictWriter::WriteOpcode_PnSize(sal_uInt16 nSize)
497 if (nSize==0) nSize=1;
498 if (bDstPnSizeValid==sal_False || nDstPnSize!=nSize) {
499 *pPict << (sal_uInt16)0x0007 << nSize << nSize;
500 nDstPnSize=nSize;
501 bDstPnSizeValid=sal_True;
506 void PictWriter::WriteOpcode_PnMode(RasterOp eMode)
508 sal_uInt16 nVal;
510 if (bDstPnModeValid==sal_False || eDstPnMode!=eMode) {
511 switch (eMode)
513 case ROP_INVERT: nVal=0x000c; break;
514 case ROP_XOR: nVal=0x000a; break;
515 default: nVal=0x0008;
517 *pPict << (sal_uInt16)0x0008 << nVal;
518 eDstPnMode=eMode;
519 bDstPnModeValid=sal_True;
524 void PictWriter::WriteOpcode_PnLinePat(sal_Bool bVisible)
526 PictPattern aPat;
528 ConvertLinePattern(aPat,bVisible);
529 if (bDstPnPatValid==sal_False || aDstPnPat.nHi!=aPat.nHi || aDstPnPat.nLo!=aPat.nLo) {
530 *pPict << (sal_uInt16)0x0009 << aPat.nHi << aPat.nLo;
531 aDstPnPat=aPat;
532 bDstPnPatValid=sal_True;
537 void PictWriter::WriteOpcode_PnFillPat(sal_Bool bVisible)
539 PictPattern aPat;
541 ConvertFillPattern(aPat,bVisible);
542 if (bDstPnPatValid==sal_False || aDstPnPat.nHi!=aPat.nHi || aDstPnPat.nLo!=aPat.nLo) {
543 *pPict << (sal_uInt16)0x0009 << aPat.nHi << aPat.nLo;
544 aDstPnPat=aPat;
545 bDstPnPatValid=sal_True;
550 void PictWriter::WriteOpcode_OvSize(const Size & rSize)
552 *pPict << (sal_uInt16)0x000b;
553 WriteSize(rSize);
557 void PictWriter::WriteOpcode_TxSize(sal_uInt16 nSize)
559 if (bDstTxSizeValid==sal_False || nDstTxSize!=nSize) {
561 nDstTxSize = (sal_uInt16) OutputDevice::LogicToLogic( Size( 0, nSize ),
562 aSrcMapMode, aTargetMapMode ).Height();
564 *pPict << (sal_uInt16)0x000d << nDstTxSize;
565 bDstTxSizeValid=sal_True;
570 void PictWriter::WriteOpcode_RGBFgCol(const Color & rColor)
572 if (bDstFgColValid==sal_False || aDstFgCol!=rColor) {
573 *pPict << (sal_uInt16)0x001a;
574 WriteRGBColor(rColor);
575 aDstFgCol=rColor;
576 bDstFgColValid=sal_True;
581 void PictWriter::WriteOpcode_RGBBkCol(const Color & rColor)
583 if (bDstBkColValid==sal_False || aDstBkCol!=rColor) {
584 *pPict << (sal_uInt16)0x001b;
585 WriteRGBColor(rColor);
586 aDstBkCol=rColor;
587 bDstBkColValid=sal_True;
592 void PictWriter::WriteOpcode_Line(const Point & rLocPt, const Point & rNewPt)
594 Point aLocPt = OutputDevice::LogicToLogic( rLocPt,
595 aSrcMapMode,
596 aTargetMapMode );
597 Point aNewPt = OutputDevice::LogicToLogic( rNewPt,
598 aSrcMapMode,
599 aTargetMapMode );
600 long dh,dv;
602 dh=aNewPt.X()-aLocPt.X();
603 dv=aNewPt.Y()-aLocPt.Y();
604 if (dh<=127 && dh>=-128 && dv<=127 && dv>=-128)
605 { // ShortLine
606 *pPict << (sal_uInt16)0x0022;
607 WritePoint(rLocPt);
608 *pPict << (char)dh << (char)dv;
610 else
612 *pPict << (sal_uInt16)0x0020;
613 WritePoint(rLocPt);
614 WritePoint(rNewPt);
616 aDstPenPosition=rNewPt;
617 bDstPenPositionValid=sal_True;
621 void PictWriter::WriteOpcode_LineFrom(const Point & rNewPt)
623 Point aNewPt = OutputDevice::LogicToLogic( rNewPt,
624 aSrcMapMode,
625 aTargetMapMode );
626 long dh,dv;
628 dh = aNewPt.X()-aDstPenPosition.X();
629 dv = aNewPt.Y()-aDstPenPosition.Y();
631 if (dh<=127 && dh>=-128 && dv<=127 && dv>=-128)
632 { // ShortLine
633 *pPict << (sal_uInt16)0x0023;
634 *pPict << (char)dh << (char)dv;
636 else
638 *pPict << (sal_uInt16)0x0021;
639 WritePoint(rNewPt);
641 aDstPenPosition=rNewPt;
642 bDstPenPositionValid=sal_True;
646 void PictWriter::WriteOpcode_Text(const Point & rPoint, const String& rString, sal_Bool bDelta)
648 Point aPoint = OutputDevice::LogicToLogic( rPoint,
649 aSrcMapMode,
650 aTargetMapMode );
651 long dh,dv;
652 sal_uLong nPos;
654 nPos = pPict->Tell();
655 dh = aPoint.X()-aDstTextPosition.X();
656 dv = aPoint.Y()-aDstTextPosition.Y();
658 if (bDstTextPositionValid==sal_False || dh<0 || dh>255 || dv<0 || dv>255 || bDelta==sal_False)
660 *pPict << (sal_uInt16)0x0028;
661 WritePoint(rPoint);
663 else if (dv==0)
665 *pPict << (sal_uInt16)0x0029 << (sal_uInt8)dh;
667 else if (dh==0)
669 *pPict << (sal_uInt16)0x002a << (sal_uInt8)dv;
671 else
673 *pPict << (sal_uInt16)0x002b << (sal_uInt8)dh << (sal_uInt8)dv;
676 WriteString( rString );
677 if (((pPict->Tell()-nPos)&1)!=0)
678 *pPict << (sal_uInt8)0;
680 aDstTextPosition = aPoint;
681 bDstTextPositionValid=sal_True;
685 void PictWriter::WriteOpcode_FontName(const Font & rFont)
687 sal_uInt16 nDataLen,nFontId;
689 switch (rFont.GetFamily()) {
690 case FAMILY_MODERN: nFontId=22; break;
691 case FAMILY_ROMAN: nFontId=20; break;
692 case FAMILY_SWISS: nFontId=21; break;
693 default: nFontId=1;
696 if (bDstFontNameValid==sal_False || nDstFontNameId!=nFontId || aDstFontName!=rFont.GetName())
698 OString aString(OUStringToOString(rFont.GetName(), osl_getThreadTextEncoding()));
699 sal_uInt16 nFontNameLen = aString.getLength();
700 if ( nFontNameLen )
702 nDataLen = 3 + nFontNameLen;
703 *pPict << (sal_uInt16)0x002c << nDataLen << nFontId;
704 WriteString( rFont.GetName() );
705 if ( ( nFontNameLen & 1 ) == 0 )
706 *pPict << (sal_uInt8)0;
708 *pPict << (sal_uInt16)0x0003 << nFontId;
709 aDstFontName=rFont.GetName();
710 nDstFontNameId=nFontId;
711 bDstFontNameValid=sal_True;
715 void PictWriter::WriteOpcode_ClipRect( const Rectangle& rRect )
717 Rectangle aRect( MapRectangle( rRect ) );
718 ++aRect.Bottom();
719 ++aRect.Right();
720 *pPict << (sal_uInt16)1 // opcode 1
721 << (sal_uInt16)10 // data size
722 << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left()
723 << (sal_Int16)aRect.Bottom() << (sal_Int16)aRect.Right();
724 aClipRect = aRect;
727 void PictWriter::WriteOpcode_Rect(PictDrawingMethod eMethod, const Rectangle & rRect)
729 sal_uInt16 oc;
730 switch (eMethod) {
731 case PDM_FRAME: oc=0x0030; break;
732 case PDM_PAINT: oc=0x0031; break;
733 case PDM_ERASE: oc=0x0032; break;
734 case PDM_INVERT: oc=0x0033; break;
735 case PDM_FILL: oc=0x0034; break;
736 default: oc=0; break; // -Wall a default for oc...
738 *pPict << oc;
739 WriteRectangle(rRect);
743 void PictWriter::WriteOpcode_SameRect(PictDrawingMethod eMethod)
745 sal_uInt16 oc;
746 switch (eMethod) {
747 case PDM_FRAME: oc=0x0038; break;
748 case PDM_PAINT: oc=0x0039; break;
749 case PDM_ERASE: oc=0x003a; break;
750 case PDM_INVERT: oc=0x003b; break;
751 case PDM_FILL: oc=0x003c; break;
752 default: oc=0; break; // -Wall a default for oc...
754 *pPict << oc;
758 void PictWriter::WriteOpcode_RRect(PictDrawingMethod eMethod, const Rectangle & rRect)
760 sal_uInt16 oc;
761 switch (eMethod) {
762 case PDM_FRAME: oc=0x0040; break;
763 case PDM_PAINT: oc=0x0041; break;
764 case PDM_ERASE: oc=0x0042; break;
765 case PDM_INVERT: oc=0x0043; break;
766 case PDM_FILL: oc=0x0044; break;
767 default: oc=0; break; // -Wall a default for oc...
769 *pPict << oc;
770 WriteRectangle(rRect);
774 void PictWriter::WriteOpcode_SameRRect(PictDrawingMethod eMethod)
776 sal_uInt16 oc;
777 switch (eMethod) {
778 case PDM_FRAME: oc=0x0048; break;
779 case PDM_PAINT: oc=0x0049; break;
780 case PDM_ERASE: oc=0x004a; break;
781 case PDM_INVERT: oc=0x004b; break;
782 case PDM_FILL: oc=0x004c; break;
783 default: oc=0; break; // -Wall a default for oc...
785 *pPict << oc;
789 void PictWriter::WriteOpcode_Oval(PictDrawingMethod eMethod, const Rectangle & rRect)
791 sal_uInt16 oc;
792 switch (eMethod) {
793 case PDM_FRAME: oc=0x0050; break;
794 case PDM_PAINT: oc=0x0051; break;
795 case PDM_ERASE: oc=0x0052; break;
796 case PDM_INVERT: oc=0x0053; break;
797 case PDM_FILL: oc=0x0054; break;
798 default: oc=0; break; // -Wall a default for oc...
800 *pPict << oc;
801 WriteRectangle(rRect);
805 void PictWriter::WriteOpcode_SameOval(PictDrawingMethod eMethod)
807 sal_uInt16 oc;
808 switch (eMethod) {
809 case PDM_FRAME: oc=0x0058; break;
810 case PDM_PAINT: oc=0x0059; break;
811 case PDM_ERASE: oc=0x005a; break;
812 case PDM_INVERT: oc=0x005b; break;
813 case PDM_FILL: oc=0x005c; break;
814 default: oc=0; break; // -Wall a default for oc...
816 *pPict << oc;
820 void PictWriter::WriteOpcode_Arc(PictDrawingMethod eMethod, const Rectangle & rRect,
821 const Point & rStartPt, const Point & rEndPt)
823 sal_uInt16 oc;
824 switch (eMethod) {
825 case PDM_FRAME: oc=0x0060; break;
826 case PDM_PAINT: oc=0x0061; break;
827 case PDM_ERASE: oc=0x0062; break;
828 case PDM_INVERT: oc=0x0063; break;
829 case PDM_FILL: oc=0x0064; break;
830 default: oc=0; break; // -Wall a default for oc...
832 *pPict << oc;
833 WriteRectangle(rRect);
834 WriteArcAngles(rRect,rStartPt,rEndPt);
838 void PictWriter::WriteOpcode_SameArc(PictDrawingMethod eMethod, const Rectangle & rRect,
839 const Point & rStartPt, const Point & rEndPt)
841 sal_uInt16 oc;
842 switch (eMethod) {
843 case PDM_FRAME: oc=0x0068; break;
844 case PDM_PAINT: oc=0x0069; break;
845 case PDM_ERASE: oc=0x006a; break;
846 case PDM_INVERT: oc=0x006b; break;
847 case PDM_FILL: oc=0x006c; break;
848 default: oc=0; break; // -Wall a default for oc...
850 *pPict << oc;
851 WriteArcAngles(rRect,rStartPt,rEndPt);
855 void PictWriter::WriteOpcode_Poly(PictDrawingMethod eMethod, const Polygon & rPoly)
857 sal_uInt16 oc;
859 if (rPoly.GetSize()<3) return;
860 switch (eMethod) {
861 case PDM_FRAME: oc=0x0070; break;
862 case PDM_PAINT: oc=0x0071; break;
863 case PDM_ERASE: oc=0x0072; break;
864 case PDM_INVERT: oc=0x0073; break;
865 case PDM_FILL: oc=0x0074; break;
866 default: oc=0; break; // -Wall a default for oc...
868 *pPict << oc;
869 WritePolygon(rPoly);
873 void PictWriter::WriteOpcode_BitsRect(const Point & rPoint, const Size & rSize, const Bitmap & rBitmap)
875 BitmapReadAccess* pAcc = NULL;
876 Bitmap aBitmap( rBitmap );
878 sal_uLong nWidth, nHeight, nDstRowBytes, nx, nc, ny, nCount, nColTabSize, i;
879 sal_uLong nDstRowPos, nSrcRowBytes, nEqu3, nPos, nDstMapPos;
880 sal_uInt16 nBitsPerPixel, nPackType;
881 sal_uInt8 *pComp[4], *pPix, *pTemp;
882 sal_uInt8 nEquData = 0;
883 sal_uInt8 nFlagCounterByte, nRed, nGreen, nBlue;
885 SetAttrForPaint();
887 // generating a temporary Windows-BMP-File:
888 nActBitmapPercent=30;
889 MayCallback();
891 if ( bStatus == sal_False )
892 return;
893 if ( ( pAcc = aBitmap.AcquireReadAccess() ) == NULL )
894 return;
896 nBitsPerPixel = aBitmap.GetBitCount();
898 // export code below only handles four discrete cases
899 nBitsPerPixel =
900 nBitsPerPixel <= 1 ? 1 : nBitsPerPixel <= 4 ? 4 : nBitsPerPixel <= 8 ? 8 : 24;
902 nWidth = pAcc->Width();
903 nHeight = pAcc->Height();
905 // If 24-Bit, then create the Opcode 'DirectBitsRect':
906 if ( nBitsPerPixel == 24 )
908 // Calculate the number of bytes of an (uncompressed) line of source and destination.
909 nSrcRowBytes =( ( 3 * nWidth ) + 0x0003 ) & 0xfffc;
910 nDstRowBytes = nWidth * 4;
912 // writing Opcode and BaseAddr (?):
913 *pPict << (sal_uInt16)0x009a << (sal_uInt32)0x000000ff;
915 // Normally we want to produce packing type 4 (run length encoding
916 // for 32-bit pixels). But if RowBytes<8 is true, generally all data is
917 // unpacked even if packing type 4 is specified, which seems a little bit
918 // strange. Hence we want to specify packing type 1 (no packing) in these cases:
920 if ( nDstRowBytes < 8 )
921 nPackType = 1;
922 else
923 nPackType = 4;
925 // writing PixMap-Structure:
926 *pPict << (sal_uInt16)(nDstRowBytes|0x8000) // Bytes per row and the fact that it's a 'PixMap'
927 << (sal_uInt16)0x0000 // Y1-position of the bitmap in the source
928 << (sal_uInt16)0x0000 // X1-position of the bitmap in the source
929 << (sal_uInt16)nHeight // Y2-position of the bitmap in the source
930 << (sal_uInt16)nWidth // X2-position of the bitmap in the source
931 << (sal_uInt16)0x0000 // Version
932 << (sal_uInt16)nPackType // Packing type
933 << (sal_uInt32) 0x00000000 // Packing size (?)
934 << (sal_uInt32) 0x00480000 // H-Res
935 << (sal_uInt32) 0x00480000 // V-Res
936 << (sal_uInt16)0x0010 // Pixel type (?)
937 << (sal_uInt16)0x0020 // Pixel size: 32 bit
938 << (sal_uInt16)0x0004 // CmpCount: 4 components
939 << (sal_uInt16)0x0008 // CmpSize: 8 bits
940 << (sal_uInt32) 0x00000000 // PlaneBytes (?)
941 << (sal_uInt32) 0x00000000 // (?)
942 << (sal_uInt32) 0x00000000; // (?)
944 // Source-Rectangle schreiben:
945 *pPict << (sal_uInt16)0x0000 // Y1-position on the bitmap
946 << (sal_uInt16)0x0000 // X1-position on the bitmap
947 << (sal_uInt16)nHeight // Y2-position on the bitmap
948 << (sal_uInt16)nWidth; // X2-position on the bitmap
950 // writing the Destination-Rectangle:
951 WritePoint( rPoint );
952 WritePoint( Point( rPoint.X() + rSize.Width(), rPoint.Y() + rSize.Height() ) );
954 // writing the Transfer mode:
955 *pPict << (sal_uInt16)0x0000; // (?)
957 // remember position of the Map-data in the target:
958 nDstMapPos=pPict->Tell();
960 if ( nPackType == 1 ) // when 24 bits nWidth == 1 !!
961 { // don't pack
962 for ( ny = 0; ny < nHeight; ny++ )
964 *pPict << (sal_uInt8)0;
965 *pPict << (sal_uInt8)pAcc->GetPixel( ny, 0 ).GetRed();
966 *pPict << (sal_uInt8)pAcc->GetPixel( ny, 0 ).GetGreen();
967 *pPict << (sal_uInt8)pAcc->GetPixel( ny, 0 ).GetBlue();
968 // count percentages, Callback, check errors:
969 nActBitmapPercent = ( ny * 70 / nHeight ) + 30; // (30% already added up to the writing of the Win-BMP file)
970 MayCallback();
973 else // packing ( PackType == 4 )
975 // allocate memory for lines-intermediate-data-structure
976 for ( nc = 0; nc < 4; nc++ )
977 pComp[ nc ] = new sal_uInt8[ nWidth ];
979 // loop trough rows:
980 for ( ny = 0; ny < nHeight; ny++ )
982 // read line ny of source into the intermediate data structure
984 for ( nx = 0; nx < nWidth; nx++ )
986 pComp[ 1 ][ nx ] = (sal_uInt8)pAcc->GetPixel( ny, nx ) .GetRed();
987 pComp[ 2 ][ nx ] = (sal_uInt8)pAcc->GetPixel( ny, nx ) .GetGreen();
988 pComp[ 3 ][ nx ] = (sal_uInt8)pAcc->GetPixel( ny, nx ) .GetBlue();
989 pComp[ 0 ][ nx ] = 0;
992 // remember start of the row in the target:
993 nDstRowPos = pPict->Tell();
995 // ByteCount (that's the size of the packed row) is at first 0 (will be corrected later):
996 if ( nDstRowBytes > 250 )
997 *pPict << (sal_uInt16)0;
998 else
999 *pPict << (sal_uInt8)0;
1001 // loop trough components:
1002 for ( nc = 0; nc < 4; nc++ )
1004 // loop through x:
1005 nx = 0;
1006 while ( nx < nWidth )
1008 // look up the position of 3 equal bytes and seve it in nEqu3
1009 // if it's not found, set nEqu3=nWidth
1010 // if it's found save the value of the bytes in nEquData
1011 nEqu3 = nx;
1012 for (;;)
1014 if ( nEqu3 + 2 >= nWidth )
1016 nEqu3 = nWidth;
1017 break;
1019 nEquData = pComp[nc][nEqu3];
1020 if ( nEquData == pComp[nc][nEqu3+1] && nEquData==pComp[nc][nEqu3+2] )
1021 break;
1022 nEqu3++;
1025 // write the data from nx to nEqu3 uncompressed (into multiple records if necessarcy);
1026 while ( nEqu3 > nx )
1028 nCount = nEqu3 - nx;
1029 if ( nCount > 128 )
1030 nCount=128;
1031 nFlagCounterByte = (sal_uInt8)(nCount-1);
1032 *pPict << nFlagCounterByte;
1035 *pPict << pComp[nc][nx++];
1036 nCount--;
1038 while ( nCount > 0 );
1041 // now create a compression record (if at least 3 identical bytes were found above)
1042 if ( nx < nWidth )
1043 { // Hint: Then one has nx==nEqu3 (hopefully)
1044 nCount=3; // Three bytes are equal, as we found out above
1045 // Check, whether there are further equal bytes (and pay attention to Max.-Record-Size):
1046 while ( nx + nCount < nWidth && nCount < 128 )
1048 if ( nEquData != pComp[ nc ][ nx + nCount ] )
1049 break;
1050 nCount++;
1052 // nCount write equal Bytes compressed:
1053 nFlagCounterByte = (sal_uInt8)( 1 - (long)nCount );
1054 *pPict << nFlagCounterByte << nEquData;
1055 nx += nCount;
1059 // correct ByteCount:
1060 nPos = pPict->Tell();
1061 pPict->Seek( nDstRowPos );
1062 if ( nDstRowBytes > 250 )
1063 *pPict << ( (sal_uInt16)( nPos - nDstRowPos - 2 ) );
1064 else
1065 *pPict << ( (sal_uInt8)( nPos - nDstRowPos - 1 ) );
1066 pPict->Seek( nPos );
1068 // count percentages, Callback, check errors:
1069 nActBitmapPercent = ( ny * 70 / nHeight ) + 30; // (30% already added up to the writing of the Win-BMP file)
1070 MayCallback();
1072 // clean up:
1073 for ( nc = 0; nc < 4; nc++ )
1074 delete pComp[ nc ];
1077 else
1078 { // don't generate 24-bit i.e. Opcode 'PackBitsRect':
1080 // Some input filters are ignoring the palette of 1-bit images and are using
1081 // the foreground and the background color instead.
1082 if ( nBitsPerPixel == 1 )
1084 WriteOpcode_RGBBkCol( pAcc->GetPaletteColor( 0 ) );
1085 WriteOpcode_RGBFgCol( pAcc->GetPaletteColor( 1 ) );
1087 else
1089 WriteOpcode_RGBBkCol( Color( COL_BLACK ) );
1090 WriteOpcode_RGBFgCol( Color( COL_WHITE ) );
1093 // Calculate the number of bytes of an (unpacked) line of source an destination.
1094 nDstRowBytes = ( nWidth * nBitsPerPixel + 7 ) >> 3;
1095 nSrcRowBytes = ( nDstRowBytes + 3 ) & 0xfffffffc;
1097 // writing Opcode:
1098 *pPict << (sal_uInt16)0x0098;
1100 // Normally we want to produce packing type 0 (default packing).
1101 // But if RowBytes<8 is true, generally all data is unpacked even if packing
1102 // type 0 is specified, which seems a little bit strange. Hence we want to
1103 // specify packing type 1 (no packing) in these cases.
1104 if ( nDstRowBytes < 8 )
1105 nPackType = 1;
1106 else
1107 nPackType = 0;
1109 // write PixMap-Structure:
1110 *pPict << (sal_uInt16)(nDstRowBytes|0x8000) // Bytes per row and the fact that it's a 'PixMap'
1111 << (sal_uInt16)0x0000 // Y1-position of the bitmap in the source
1112 << (sal_uInt16)0x0000 // X1-position of the bitmap in the source
1113 << (sal_uInt16)nHeight // Y2-position of the bitmap in the source
1114 << (sal_uInt16)nWidth // X2-position of the bitmap in the source
1115 << (sal_uInt16)0x0000 // Version
1116 << (sal_uInt16)nPackType // Packing type
1117 << (sal_uInt32) 0x00000000 // Packing size (?)
1118 << (sal_uInt32) 0x00480000 // H-Res
1119 << (sal_uInt32) 0x00480000 // V-Res
1120 << (sal_uInt16)0x0000 // Pixel type (?)
1121 << (sal_uInt16)nBitsPerPixel // Pixel size
1122 << (sal_uInt16)0x0001 // CmpCount: 1 component
1123 << (sal_uInt16)nBitsPerPixel // CmpSize
1124 << (sal_uInt32) 0x00000000 // PlaneBytes (?)
1125 << (sal_uInt32) 0x00000000 // (?)
1126 << (sal_uInt32) 0x00000000; // (?)
1128 // writing and reading the palette:
1129 nColTabSize = pAcc->GetPaletteEntryCount();
1130 *pPict << (sal_uInt32)0 << (sal_uInt16)0x8000 << (sal_uInt16)( nColTabSize - 1 );
1132 for ( i = 0; i < nColTabSize; i++ )
1134 nRed = (sal_uInt8)pAcc->GetPaletteColor( (sal_uInt16)i ).GetRed();
1135 nGreen = (sal_uInt8)pAcc->GetPaletteColor( (sal_uInt16)i ).GetGreen();
1136 nBlue = (sal_uInt8)pAcc->GetPaletteColor( (sal_uInt16)i ).GetBlue();
1137 *pPict << (sal_uInt16)0 << nRed << nRed << nGreen << nGreen << nBlue << nBlue;
1140 // writing Source-Rectangle:
1141 *pPict << (sal_uInt16)0 << (sal_uInt16)0 << (sal_uInt16)nHeight << (sal_uInt16)nWidth;
1143 // writing Destination-Rectangle:
1144 WritePoint( rPoint );
1145 WritePoint( Point( rPoint.X() + rSize.Width(), rPoint.Y() + rSize.Height() ) );
1147 // writing Transfer mode:
1148 *pPict << (sal_uInt16)0; // (?)
1150 // allocate memory for a row:
1151 pPix = new sal_uInt8[ nSrcRowBytes ];
1153 // Position der Map-Daten in Ziel merken:
1154 nDstMapPos=pPict->Tell();
1156 // loop trough rows:
1157 for ( ny = 0; ny < nHeight; ny++ )
1160 // read line ny of source into the buffer:
1161 switch ( nBitsPerPixel )
1163 case 1 :
1164 for ( pTemp = pPix, i = 0; i < nSrcRowBytes; i++ )
1165 *pTemp++ = (sal_uInt8)0;
1166 for ( i = 0; i < nWidth; i++ )
1167 pPix[ ( i >> 3 ) ] |= (pAcc->GetPixelIndex( ny, i ) & 1) << ((i & 7) ^ 7);
1168 break;
1169 case 4 :
1170 for ( pTemp = pPix, i = 0; i < nSrcRowBytes; i++ )
1171 *pTemp++ = (sal_uInt8)0;
1172 for ( i = 0; i < nWidth; i++ )
1173 pPix[ ( i >> 1 ) ] |= (pAcc->GetPixelIndex( ny, i ) & 15) << ((i & 1) << 2);
1174 break;
1175 case 8 :
1176 for ( i = 0; i < nWidth; i++ )
1177 pPix[ i ] = pAcc->GetPixelIndex( ny, i );
1178 break;
1181 if ( nPackType == 1 )
1182 { // don't pack
1183 pPict->Write( pPix, nDstRowBytes );
1185 else
1186 { // Ppacking (nPackType==0)
1188 // remember start of the row in the target:
1189 nDstRowPos = pPict->Tell();
1191 // ByteCount (this is the size of the packed line) initialized with 0 (will be corrected later):
1192 if ( nDstRowBytes > 250 )
1193 *pPict << (sal_uInt16)0;
1194 else
1195 *pPict << (sal_uInt8)0;
1197 // loop trough bytes of the row:
1198 nx=0;
1199 while ( nx < nDstRowBytes && bStatus )
1201 // Look for the position of three identical bytes and remember it in nEqu3.
1202 // Set nEqu3=nDstRowBytes if not found.
1203 // Else remember the value of these bytes in nEquData.
1204 nEqu3 = nx;
1205 for (;;)
1207 if ( nEqu3 + 2 >= nDstRowBytes )
1209 nEqu3 = nDstRowBytes;
1210 break;
1212 nEquData = pPix[ nEqu3 ];
1213 if ( nEquData == pPix[ nEqu3 + 1 ] && nEquData == pPix[ nEqu3 + 2 ] )
1214 break;
1215 nEqu3++;
1218 // Write the data unpacked from nx to nEqu3 (in multiple records if necessary):
1219 while ( nEqu3 > nx )
1221 nCount = nEqu3 - nx;
1222 if ( nCount > 128 )
1223 nCount = 128;
1224 nFlagCounterByte = (sal_uInt8)( nCount - 1 );
1225 *pPict << nFlagCounterByte;
1228 *pPict << pPix[ nx++ ];
1229 nCount--;
1230 } while ( nCount > 0 );
1233 // Now create a compression record (if at least 3 identical bytes were found above):
1234 if ( nx < nDstRowBytes )
1235 { // Note: it is imperative nx==nEqu3 (hopefully)
1236 nCount = 3; // three bytes are identically, as identified above
1237 // Check if more identical bytes exist. (in doing so, consider max record size):
1238 while ( nx + nCount < nDstRowBytes && nCount < 128 )
1240 if ( nEquData != pPix[ nx + nCount ] )
1241 break;
1242 nCount++;
1244 // write nCount identical bytes unpacked:
1245 nFlagCounterByte = (sal_uInt8)( 1 - (long)nCount );
1246 *pPict << nFlagCounterByte << nEquData;
1247 nx += nCount;
1251 // correct ByteCount:
1252 nPos = pPict->Tell();
1253 pPict->Seek( nDstRowPos );
1254 if ( nDstRowBytes > 250 )
1255 *pPict << ( (sal_uInt16)( nPos - nDstRowPos - 2 ) );
1256 else
1257 *pPict << ( (sal_uInt8)( nPos - nDstRowPos - 1 ) );
1258 pPict->Seek( nPos );
1261 // count percentages, Callback, check errors:
1262 nActBitmapPercent =( ny * 70 / nHeight ) + 30; // (30% already added up to the writing of the Win-BMP file)
1263 MayCallback();
1264 if ( pPict->GetError() )
1265 bStatus = sal_False;
1267 // cleaning up:
1268 delete[] pPix;
1271 // Map-Data has to be an even number of bytes:
1272 if ( ( ( pPict->Tell() - nDstMapPos ) & 1 ) != 0 )
1273 *pPict << (sal_uInt8)0;
1275 // counting Bitmaps:
1276 nWrittenBitmaps++;
1277 nActBitmapPercent = 0;
1278 if ( pAcc )
1279 aBitmap.ReleaseAccess( pAcc );
1282 void PictWriter::WriteOpcode_EndOfFile()
1284 *pPict << (sal_uInt16)0x00ff;
1288 void PictWriter::SetAttrForPaint()
1290 WriteOpcode_PnMode(eSrcRasterOp);
1291 WriteOpcode_RGBFgCol(aFillColor);
1292 WriteOpcode_RGBBkCol(aFillColor);
1293 WriteOpcode_PnFillPat(aFillColor!=Color( COL_TRANSPARENT ));
1297 void PictWriter::SetAttrForFrame()
1299 WriteOpcode_PnMode(eSrcRasterOp);
1300 WriteOpcode_PnSize(0);
1301 WriteOpcode_RGBFgCol(aLineColor);
1302 WriteOpcode_PnLinePat(aLineColor!=Color( COL_TRANSPARENT ));
1306 void PictWriter::SetAttrForText()
1308 WriteOpcode_RGBFgCol(aSrcFont.GetColor());
1309 WriteOpcode_RGBBkCol(aSrcFont.GetFillColor());
1310 WriteOpcode_PnLinePat(sal_True);
1311 WriteOpcode_FontName(aSrcFont);
1312 WriteOpcode_TxSize((sal_uInt16)(aSrcFont.GetSize().Height()));
1313 WriteOpcode_TxMode(eSrcRasterOp);
1314 WriteOpcode_TxFace(aSrcFont);
1318 void PictWriter::WriteTextArray(Point & rPoint, const String& rString, const sal_Int32 * pDXAry)
1320 sal_uInt16 i,nLen;
1321 sal_Unicode c;
1322 sal_Bool bDelta;
1323 Point aPt;
1325 if ( pDXAry == NULL )
1326 WriteOpcode_Text( rPoint, rString, sal_False );
1327 else
1329 bDelta = sal_False;
1330 nLen = rString.Len();
1331 for ( i = 0; i < nLen; i++ )
1333 c = rString.GetChar( i );
1334 if ( c && ( c != 0x20 ) )
1336 aPt = rPoint;
1337 if ( i > 0 )
1338 aPt.X() += pDXAry[ i - 1 ];
1340 WriteOpcode_Text( aPt, OUString( c ), bDelta );
1341 bDelta = sal_True;
1347 void PictWriter::HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
1349 if(rLinePolygon.count())
1351 basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
1352 basegfx::B2DPolyPolygon aFillPolyPolygon;
1354 rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
1356 if(aLinePolyPolygon.count())
1358 aLinePolyPolygon = aLinePolyPolygon.getDefaultAdaptiveSubdivision();
1359 const sal_uInt32 nPolyCount(aLinePolyPolygon.count());
1360 SetAttrForFrame();
1362 for(sal_uInt32 a(0); a < nPolyCount; a++)
1364 const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
1365 const sal_uInt32 nPointCount(aCandidate.count());
1367 if(nPointCount)
1369 const sal_uInt32 nEdgeCount(aCandidate.isClosed() ? nPointCount + 1 : nPointCount);
1370 const basegfx::B2DPoint aCurr(aCandidate.getB2DPoint(0));
1371 Point nCurr(basegfx::fround(aCurr.getX()), basegfx::fround(aCurr.getY()));
1373 for(sal_uInt32 b(0); b < nEdgeCount; b++)
1375 const sal_uInt32 nNextIndex((b + 1) % nPointCount);
1376 const basegfx::B2DPoint aNext(aCandidate.getB2DPoint(nNextIndex));
1377 const Point nNext(basegfx::fround(aNext.getX()), basegfx::fround(aNext.getY()));
1379 WriteOpcode_Line(nCurr, nNext);
1380 nCurr = nNext;
1386 if(aFillPolyPolygon.count())
1388 const Color aOldLineColor(aLineColor);
1389 const Color aOldFillColor(aFillColor);
1391 aLineColor = Color( COL_TRANSPARENT );
1392 aFillColor = aOldLineColor;
1393 SetAttrForPaint();
1395 for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
1397 const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a).getDefaultAdaptiveSubdivision());
1398 WriteOpcode_Poly(PDM_PAINT, aPolygon);
1401 aLineColor = aOldLineColor;
1402 aFillColor = aOldFillColor;
1407 void PictWriter::WriteOpcodes( const GDIMetaFile & rMTF )
1409 size_t nA, nACount;
1410 const MetaAction* pMA;
1412 if( !bStatus)
1413 return;
1415 nACount = rMTF.GetActionSize();
1417 for (nA=0; nA < nACount; nA++)
1419 pMA = rMTF.GetAction(nA);
1421 switch (pMA->GetType())
1423 case META_PIXEL_ACTION:
1425 const MetaPixelAction* pA = (const MetaPixelAction*) pMA;
1426 WriteOpcode_PnMode(eSrcRasterOp);
1427 WriteOpcode_PnSize(1);
1428 WriteOpcode_RGBFgCol(pA->GetColor());
1429 WriteOpcode_PnLinePat(sal_True);
1430 WriteOpcode_Line(pA->GetPoint(),pA->GetPoint());
1432 break;
1434 case META_POINT_ACTION:
1436 const MetaPointAction* pA = (const MetaPointAction*) pMA;
1438 if( aLineColor != Color( COL_TRANSPARENT ) )
1440 SetAttrForFrame();
1441 WriteOpcode_Line( pA->GetPoint(),pA->GetPoint() );
1444 break;
1446 case META_LINE_ACTION:
1448 const MetaLineAction* pA = (const MetaLineAction*) pMA;
1450 if( aLineColor != Color( COL_TRANSPARENT ) )
1452 if(pA->GetLineInfo().IsDefault())
1454 SetAttrForFrame();
1455 WriteOpcode_Line( pA->GetStartPoint(),pA->GetEndPoint() );
1457 else
1459 // LineInfo used; handle Dash/Dot and fat lines
1460 basegfx::B2DPolygon aPolygon;
1461 aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
1462 aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
1463 HandleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
1466 break;
1469 case META_RECT_ACTION:
1471 const MetaRectAction* pA = (const MetaRectAction*) pMA;
1473 if (aFillColor!=Color( COL_TRANSPARENT ))
1475 SetAttrForPaint();
1476 WriteOpcode_Rect(PDM_PAINT,pA->GetRect());
1477 if (aLineColor!=Color( COL_TRANSPARENT ))
1479 SetAttrForFrame();
1480 WriteOpcode_SameRect(PDM_FRAME);
1483 else if (aLineColor!=Color( COL_TRANSPARENT ))
1485 SetAttrForFrame();
1486 WriteOpcode_Rect(PDM_FRAME,pA->GetRect());
1489 break;
1491 case META_ROUNDRECT_ACTION:
1493 const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pMA;
1495 WriteOpcode_OvSize( Size( pA->GetHorzRound(), pA->GetVertRound() ) );
1497 if (aFillColor!=Color( COL_TRANSPARENT ))
1499 SetAttrForPaint();
1500 WriteOpcode_RRect(PDM_PAINT,pA->GetRect());
1501 if (aLineColor!=Color( COL_TRANSPARENT ))
1503 SetAttrForFrame();
1504 WriteOpcode_SameRRect(PDM_FRAME);
1507 else if (aLineColor!=Color( COL_TRANSPARENT ))
1509 SetAttrForFrame();
1510 WriteOpcode_RRect(PDM_FRAME,pA->GetRect());
1513 break;
1515 case META_ELLIPSE_ACTION:
1517 const MetaEllipseAction* pA = (const MetaEllipseAction*) pMA;
1519 if (aFillColor!=Color( COL_TRANSPARENT ))
1521 SetAttrForPaint();
1522 WriteOpcode_Oval(PDM_PAINT,pA->GetRect());
1523 if (aLineColor!=Color( COL_TRANSPARENT ))
1525 SetAttrForFrame();
1526 WriteOpcode_SameOval(PDM_FRAME);
1529 else if (aLineColor!=Color( COL_TRANSPARENT ))
1531 SetAttrForFrame();
1532 WriteOpcode_Oval(PDM_FRAME,pA->GetRect());
1535 break;
1537 case META_ARC_ACTION:
1539 const MetaArcAction* pA = (const MetaArcAction*) pMA;
1541 if (aLineColor!=Color( COL_TRANSPARENT ))
1543 SetAttrForFrame();
1544 WriteOpcode_Arc(PDM_FRAME,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint());
1547 break;
1549 case META_PIE_ACTION:
1551 const MetaPieAction* pA = (const MetaPieAction *) pMA;
1553 if (aFillColor!=Color( COL_TRANSPARENT ))
1555 SetAttrForPaint();
1556 WriteOpcode_Arc(PDM_PAINT,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint());
1558 if (aLineColor!=Color( COL_TRANSPARENT ))
1560 SetAttrForFrame();
1561 WriteOpcode_SameArc(PDM_FRAME,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint());
1564 else if (aLineColor!=Color( COL_TRANSPARENT ))
1566 SetAttrForFrame();
1567 WriteOpcode_Arc(PDM_FRAME,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint());
1570 if (aLineColor!=Color( COL_TRANSPARENT ))
1572 double fxc,fyc,fxr,fyr,fx1,fy1,fx2,fy2,l1,l2;
1574 fxc=((double)(pA->GetRect().Left()+pA->GetRect().Right()))/2.0;
1575 fyc=((double)(pA->GetRect().Top()+pA->GetRect().Bottom()))/2.0;
1576 fxr=((double)pA->GetRect().GetWidth())/2.0;
1577 fyr=((double)pA->GetRect().GetHeight())/2.0;
1578 fx1=((double)pA->GetStartPoint().X())-fxc;
1579 fy1=((double)pA->GetStartPoint().Y())-fyc;
1580 fx2=((double)pA->GetEndPoint().X())-fxc;
1581 fy2=((double)pA->GetEndPoint().Y())-fyc;
1582 l1=sqrt(fx1*fx1+fy1*fy1);
1583 l2=sqrt(fx2*fx2+fy2*fy2);
1585 if (l1>0)
1587 fx1=fx1/l1*fxr;
1588 fy1=fy1/l1*fyr;
1591 if (l2>0)
1593 fx2=fx2/l2*fxr;
1594 fy2=fy2/l2*fyr;
1596 fx1+=fxc; fy1+=fyc; fx2+=fxc; fy2+=fyc;
1597 WriteOpcode_Line(Point((long)(fx1+0.5),(long)(fy1+0.5)), Point((long)(fxc+0.5),(long)(fyc+0.5)));
1598 WriteOpcode_LineFrom(Point((long)(fx2+0.5),(long)(fy2+0.5)));
1601 break;
1603 case META_CHORD_ACTION:
1605 // OSL_FAIL( "Unsupported PICT-Action: META_CHORD_ACTION!" );
1607 break;
1609 case META_POLYLINE_ACTION:
1611 const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pMA;
1613 if( aLineColor!=Color( COL_TRANSPARENT ) )
1615 const Polygon& rPoly = pA->GetPolygon();
1617 if( rPoly.GetSize() )
1619 if(pA->GetLineInfo().IsDefault())
1621 Polygon aSimplePoly;
1622 if ( rPoly.HasFlags() )
1623 rPoly.AdaptiveSubdivide( aSimplePoly );
1624 else
1625 aSimplePoly = rPoly;
1627 const sal_uInt16 nSize = aSimplePoly.GetSize();
1628 Point aLast;
1630 if ( nSize )
1632 SetAttrForFrame();
1633 aLast = aSimplePoly[0];
1635 for ( sal_uInt16 i = 1; i < nSize; i++ )
1637 WriteOpcode_Line( aLast, aSimplePoly[i] );
1638 aLast = aSimplePoly[i];
1642 else
1644 // LineInfo used; handle Dash/Dot and fat lines
1645 HandleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
1650 break;
1652 case META_POLYGON_ACTION:
1654 const MetaPolygonAction* pA = (const MetaPolygonAction*) pMA;
1656 const Polygon& rPoly = pA->GetPolygon();
1658 Polygon aSimplePoly;
1659 if ( rPoly.HasFlags() )
1660 rPoly.AdaptiveSubdivide( aSimplePoly );
1661 else
1662 aSimplePoly = rPoly;
1664 if (aFillColor!=Color( COL_TRANSPARENT ))
1666 SetAttrForPaint();
1667 WriteOpcode_Poly( PDM_PAINT, aSimplePoly );
1669 if (aLineColor!=Color( COL_TRANSPARENT ))
1671 SetAttrForFrame();
1672 WriteOpcode_Poly( PDM_FRAME, aSimplePoly );
1675 break;
1677 case META_POLYPOLYGON_ACTION:
1679 const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pMA;
1681 const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
1682 sal_uInt16 nPolyCount = rPolyPoly.Count();
1683 PolyPolygon aSimplePolyPoly( rPolyPoly );
1684 for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
1686 if ( aSimplePolyPoly[ i ].HasFlags() )
1688 Polygon aSimplePoly;
1689 aSimplePolyPoly[ i ].AdaptiveSubdivide( aSimplePoly );
1690 aSimplePolyPoly[ i ] = aSimplePoly;
1693 if (aFillColor!=Color( COL_TRANSPARENT ))
1695 SetAttrForPaint();
1696 WriteOpcode_Poly( PDM_PAINT, PolyPolygonToPolygon( aSimplePolyPoly ));
1699 if (aLineColor!=Color( COL_TRANSPARENT ))
1701 sal_uInt16 nCount,i;
1702 SetAttrForFrame();
1703 nCount = aSimplePolyPoly.Count();
1704 for ( i = 0; i < nCount; i++ )
1705 WriteOpcode_Poly( PDM_FRAME, aSimplePolyPoly.GetObject( i ) );
1708 break;
1710 case META_TEXT_ACTION:
1712 const MetaTextAction* pA = (const MetaTextAction*) pMA;
1713 Point aPt( pA->GetPoint() );
1715 if ( aSrcFont.GetAlign() != ALIGN_BASELINE )
1717 VirtualDevice aVirDev;
1719 if (aSrcFont.GetAlign()==ALIGN_TOP)
1720 aPt.Y()+=(long)aVirDev.GetFontMetric(aSrcFont).GetAscent();
1721 else
1722 aPt.Y()-=(long)aVirDev.GetFontMetric(aSrcFont).GetDescent();
1725 SetAttrForText();
1726 String aStr( pA->GetText(),pA->GetIndex(),pA->GetLen() );
1727 WriteOpcode_Text( aPt, aStr, sal_False );
1729 break;
1731 case META_TEXTARRAY_ACTION:
1733 const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pMA;
1734 Point aPt( pA->GetPoint() );
1736 if (aSrcFont.GetAlign()!=ALIGN_BASELINE)
1738 VirtualDevice aVirDev;
1740 if (aSrcFont.GetAlign()==ALIGN_TOP)
1741 aPt.Y()+=(long)aVirDev.GetFontMetric(aSrcFont).GetAscent();
1742 else
1743 aPt.Y()-=(long)aVirDev.GetFontMetric(aSrcFont).GetDescent();
1745 SetAttrForText();
1746 String aStr( pA->GetText(),pA->GetIndex(),pA->GetLen() );
1747 WriteTextArray( aPt, aStr, pA->GetDXArray() );
1748 break;
1751 case META_STRETCHTEXT_ACTION:
1753 const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pMA;
1754 Point aPt( pA->GetPoint() );
1755 String aStr( pA->GetText(),pA->GetIndex(),pA->GetLen() );
1756 VirtualDevice aVirDev;
1757 sal_Int32* pDXAry = new sal_Int32[ aStr.Len() ];
1758 sal_Int32 nNormSize( aVirDev.GetTextArray( aStr,pDXAry ) );
1759 sal_uInt16 i;
1761 if (aSrcFont.GetAlign()!=ALIGN_BASELINE)
1763 if (aSrcFont.GetAlign()==ALIGN_TOP)
1764 aPt.Y()+=(long)aVirDev.GetFontMetric(aSrcFont).GetAscent();
1765 else
1766 aPt.Y()-=(long)aVirDev.GetFontMetric(aSrcFont).GetDescent();
1769 for ( i = 0; i < aStr.Len() - 1; i++ )
1770 pDXAry[ i ] = pDXAry[ i ] * ( (long)pA->GetWidth() ) / nNormSize;
1772 SetAttrForText();
1773 WriteTextArray( aPt, aStr, pDXAry );
1774 delete[] pDXAry;
1776 break;
1778 case META_TEXTRECT_ACTION:
1780 // OSL_FAIL( "Unsupported PICT-Action: META_TEXTRECT_ACTION!" );
1782 break;
1784 case META_BMP_ACTION:
1786 const MetaBmpAction* pA = (const MetaBmpAction*) pMA;
1787 const Bitmap aBmp( pA->GetBitmap() );
1788 VirtualDevice aVirDev;
1790 WriteOpcode_BitsRect( pA->GetPoint(), aVirDev.PixelToLogic( aBmp.GetSizePixel(), aSrcMapMode ), aBmp );
1792 break;
1794 case META_BMPSCALE_ACTION:
1796 const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pMA;
1797 WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), pA->GetBitmap() );
1799 break;
1801 case META_BMPSCALEPART_ACTION:
1803 const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pMA;
1804 Bitmap aBmp( pA->GetBitmap() );
1806 aBmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1807 WriteOpcode_BitsRect( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
1809 break;
1811 case META_BMPEX_ACTION:
1813 const MetaBmpExAction* pA = (const MetaBmpExAction*) pMA;
1814 const Bitmap aBmp( Graphic( pA->GetBitmapEx() ).GetBitmap() );
1815 VirtualDevice aVirDev;
1817 WriteOpcode_BitsRect( pA->GetPoint(), aVirDev.PixelToLogic( aBmp.GetSizePixel(), aSrcMapMode ), aBmp );
1819 break;
1821 case META_BMPEXSCALE_ACTION:
1823 const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pMA;
1824 const Bitmap aBmp( Graphic( pA->GetBitmapEx() ).GetBitmap() );
1826 WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), aBmp );
1828 break;
1830 case META_BMPEXSCALEPART_ACTION:
1832 const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pMA;
1833 Bitmap aBmp( Graphic( pA->GetBitmapEx() ).GetBitmap() );
1835 aBmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1836 WriteOpcode_BitsRect( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
1838 break;
1840 case META_EPS_ACTION :
1842 const MetaEPSAction* pA = (const MetaEPSAction*)pMA;
1843 const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
1845 size_t nCount = aGDIMetaFile.GetActionSize();
1846 for ( size_t i = 0; i < nCount; i++ )
1848 const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
1849 if ( pMetaAct->GetType() == META_BMPSCALE_ACTION )
1851 const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*)pMetaAct;
1852 WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap() );
1853 break;
1857 break;
1859 case META_MASK_ACTION:
1860 case META_MASKSCALE_ACTION:
1861 case META_MASKSCALEPART_ACTION:
1863 // OSL_FAIL( "Unsupported PICT-Action: META_MASK..._ACTION!" );
1865 break;
1867 case META_GRADIENT_ACTION:
1869 VirtualDevice aVDev;
1870 GDIMetaFile aTmpMtf;
1871 const MetaGradientAction* pA = (const MetaGradientAction*) pMA;
1873 aVDev.SetMapMode( aTargetMapMode );
1874 aVDev.AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
1875 WriteOpcodes( aTmpMtf );
1877 break;
1879 case META_HATCH_ACTION:
1881 VirtualDevice aVDev;
1882 GDIMetaFile aTmpMtf;
1883 const MetaHatchAction* pA = (const MetaHatchAction*) pMA;
1885 aVDev.SetMapMode( aTargetMapMode );
1886 aVDev.AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
1887 WriteOpcodes( aTmpMtf );
1889 break;
1891 case META_WALLPAPER_ACTION:
1893 // OSL_FAIL( "Unsupported PICT-Action: META_WALLPAPER_ACTION!" );
1895 break;
1897 case META_CLIPREGION_ACTION:
1899 // OSL_FAIL( "Unsupported PICT-Action: META_CLIPREGION_ACTION!" );
1901 break;
1903 case META_ISECTRECTCLIPREGION_ACTION:
1905 const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pMA;
1906 WriteOpcode_ClipRect( pA->GetRect() );
1908 break;
1910 case META_ISECTREGIONCLIPREGION_ACTION:
1912 // OSL_FAIL( "Unsupported PICT-Action: META_ISECTREGIONCLIPREGION_ACTION!" );
1914 break;
1916 case META_MOVECLIPREGION_ACTION:
1918 // OSL_FAIL( "Unsupported PICT-Action: META_MOVECLIPREGION_ACTION!" );
1920 break;
1922 case META_LINECOLOR_ACTION:
1924 const MetaLineColorAction* pA = (const MetaLineColorAction*) pMA;
1926 if( pA->IsSetting() )
1927 aLineColor = pA->GetColor();
1928 else
1929 aLineColor = Color( COL_TRANSPARENT );
1931 break;
1933 case META_FILLCOLOR_ACTION:
1935 const MetaFillColorAction* pA = (const MetaFillColorAction*) pMA;
1937 if( pA->IsSetting() )
1938 aFillColor = pA->GetColor();
1939 else
1940 aFillColor = Color( COL_TRANSPARENT );
1942 break;
1944 case META_TEXTCOLOR_ACTION:
1946 const MetaTextColorAction* pA = (const MetaTextColorAction*) pMA;
1947 aSrcFont.SetColor( pA->GetColor() );
1949 break;
1951 case META_TEXTFILLCOLOR_ACTION:
1953 const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pMA;
1955 if( pA->IsSetting() )
1956 aSrcFont.SetFillColor( pA->GetColor() );
1957 else
1958 aSrcFont.SetFillColor( Color( COL_TRANSPARENT ) );
1960 break;
1962 case META_TEXTALIGN_ACTION:
1964 // OSL_FAIL( "Unsupported PICT-Action: META_TEXTALIGN_ACTION!" );
1966 break;
1968 case META_MAPMODE_ACTION:
1970 const MetaMapModeAction* pA = (const MetaMapModeAction*) pMA;
1972 if (aSrcMapMode!=pA->GetMapMode())
1974 if( pA->GetMapMode().GetMapUnit() == MAP_RELATIVE )
1976 MapMode aMM = pA->GetMapMode();
1977 Fraction aScaleX = aMM.GetScaleX();
1978 Fraction aScaleY = aMM.GetScaleY();
1980 Point aOrigin = aSrcMapMode.GetOrigin();
1981 BigInt aX( aOrigin.X() );
1982 aX *= BigInt( aScaleX.GetDenominator() );
1983 if( aOrigin.X() >= 0 )
1985 if( aScaleX.GetNumerator() >= 0 )
1986 aX += BigInt( aScaleX.GetNumerator()/2 );
1987 else
1988 aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
1990 else
1992 if( aScaleX.GetNumerator() >= 0 )
1993 aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
1994 else
1995 aX += BigInt( aScaleX.GetNumerator()/2 );
1998 aX /= BigInt( aScaleX.GetNumerator() );
1999 aOrigin.X() = (long)aX + aMM.GetOrigin().X();
2000 BigInt aY( aOrigin.Y() );
2001 aY *= BigInt( aScaleY.GetDenominator() );
2003 if( aOrigin.Y() >= 0 )
2005 if( aScaleY.GetNumerator() >= 0 )
2006 aY += BigInt( aScaleY.GetNumerator()/2 );
2007 else
2008 aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
2010 else
2012 if( aScaleY.GetNumerator() >= 0 )
2013 aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
2014 else
2015 aY += BigInt( aScaleY.GetNumerator()/2 );
2018 aY /= BigInt( aScaleY.GetNumerator() );
2019 aOrigin.Y() = (long)aY + aMM.GetOrigin().Y();
2020 aSrcMapMode.SetOrigin( aOrigin );
2022 aScaleX *= aSrcMapMode.GetScaleX();
2023 aScaleY *= aSrcMapMode.GetScaleY();
2024 aSrcMapMode.SetScaleX( aScaleX );
2025 aSrcMapMode.SetScaleY( aScaleY );
2027 else
2028 aSrcMapMode = pA->GetMapMode();
2031 break;
2033 case META_FONT_ACTION:
2035 const MetaFontAction* pA = (const MetaFontAction*) pMA;
2036 aSrcFont=pA->GetFont();
2038 break;
2040 case META_PUSH_ACTION:
2042 PictWriterAttrStackMember * pAt = new PictWriterAttrStackMember;
2043 pAt->aLineColor=aLineColor;
2044 pAt->aFillColor=aFillColor;
2045 pAt->eRasterOp=eSrcRasterOp;
2046 pAt->aFont=aSrcFont;
2047 pAt->aMapMode=aSrcMapMode;
2048 pAt->aClipRect=aClipRect;
2049 pAt->pSucc=pAttrStack;
2050 pAttrStack=pAt;
2052 break;
2054 case META_POP_ACTION:
2056 PictWriterAttrStackMember* pAt=pAttrStack;
2058 if( pAt )
2060 aLineColor=pAt->aLineColor;
2061 aFillColor=pAt->aFillColor;
2062 eSrcRasterOp=pAt->eRasterOp;
2063 aSrcFont=pAt->aFont;
2064 aSrcMapMode=pAt->aMapMode;
2065 if ( pAt->aClipRect != aClipRect )
2067 Rectangle aRect( pAt->aClipRect );
2068 *pPict << (sal_uInt16)1 // opcode 1
2069 << (sal_uInt16)10 // data size
2070 << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left()
2071 << (sal_Int16)aRect.Bottom() << (sal_Int16)aRect.Right();
2073 aClipRect=pAt->aClipRect;
2074 pAttrStack=pAt->pSucc;
2075 delete pAt;
2078 break;
2080 case META_RASTEROP_ACTION:
2082 const MetaRasterOpAction* pA = (const MetaRasterOpAction*) pMA;
2083 eSrcRasterOp=pA->GetRasterOp();
2085 break;
2087 case META_TRANSPARENT_ACTION:
2089 const PolyPolygon& rPolyPoly = ( (const MetaTransparentAction*) pMA )->GetPolyPolygon();
2091 if (aFillColor!=Color( COL_TRANSPARENT ))
2093 SetAttrForPaint();
2094 WriteOpcode_Poly( PDM_PAINT, PolyPolygonToPolygon( rPolyPoly ) );
2097 if (aLineColor!=Color( COL_TRANSPARENT ))
2099 SetAttrForFrame();
2100 for( sal_uInt16 i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
2101 WriteOpcode_Poly( PDM_FRAME, rPolyPoly.GetObject( i ) );
2104 break;
2106 case META_FLOATTRANSPARENT_ACTION:
2108 const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pMA;
2110 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
2111 Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
2112 const Size aSrcSize( aTmpMtf.GetPrefSize() );
2113 const Point aDestPt( pA->GetPoint() );
2114 const Size aDestSize( pA->GetSize() );
2115 const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
2116 const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
2117 long nMoveX, nMoveY;
2119 if( fScaleX != 1.0 || fScaleY != 1.0 )
2121 aTmpMtf.Scale( fScaleX, fScaleY );
2122 aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
2125 nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
2127 if( nMoveX || nMoveY )
2128 aTmpMtf.Move( nMoveX, nMoveY );
2130 WriteOpcodes( aTmpMtf );
2132 break;
2135 nWrittenActions++;
2136 MayCallback();
2138 if (pPict->GetError())
2139 bStatus=sal_False;
2141 if (bStatus==sal_False)
2142 break;
2147 void PictWriter::WriteHeader(const GDIMetaFile & rMTF)
2149 sal_uInt16 i;
2150 Size aSize( rMTF.GetPrefSize() );
2151 Point aPoint;
2152 Rectangle aRect( aPoint, aSize );
2154 // 512 Bytes "trash" at the beginning:
2155 for (i=0;i<128;i++) *pPict << (sal_uInt32)0;
2157 // Lo-16-Bits of the file size without the 512 bytes trash:
2158 *pPict << (sal_uInt16)0; // gets corrected later on by UpdateHeader()
2160 // The Bounding-Rectangle (y1,x1,y2,x2 !):
2161 WriteRectangle( aRect );
2163 // Version 2:
2164 *pPict << (sal_uInt32)0x001102ff;
2166 // Extended-Version-2-Header:
2167 *pPict << (sal_uInt16)0x0c00 // Opcode
2168 << (sal_uInt16)0xfffe // Version (?)
2169 << (sal_uInt16)0x0000 // Reserved
2170 << (sal_uInt32) 0x00480000 // hRes
2171 << (sal_uInt32) 0x00480000;
2172 WriteRectangle( aRect );
2173 *pPict << (sal_uInt32)0x00000000; // Reserved
2175 // many import filters demand the declaration
2176 // of a clipping area at the beginning
2178 WriteOpcode_ClipRect( aRect );
2182 void PictWriter::UpdateHeader()
2184 sal_uLong nPos;
2186 // correct the Lo-16-Bits of the file size without the 512 bytes trash:
2187 nPos=pPict->Tell();
2188 pPict->Seek(512);
2189 *pPict << (sal_uInt16)((nPos-512)&0x0000ffff);
2190 pPict->Seek(nPos);
2194 sal_Bool PictWriter::WritePict(const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem* pFilterConfigItem )
2196 PictWriterAttrStackMember* pAt;
2197 MapMode aMap72( MAP_INCH );
2198 Fraction aDPIFrac( 1, 72 );
2200 bStatus=sal_True;
2201 nLastPercent=0;
2203 if ( pFilterConfigItem )
2205 xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
2206 if ( xStatusIndicator.is() )
2208 OUString aMsg;
2209 xStatusIndicator->start( aMsg, 100 );
2213 pPict=&rTargetStream;
2214 pPict->SetNumberFormatInt(NUMBERFORMAT_INT_BIGENDIAN);
2216 aLineColor=Color( COL_BLACK );
2217 aFillColor=Color( COL_WHITE );
2218 eSrcRasterOp=ROP_OVERPAINT;
2219 aSrcFont=Font();
2220 aSrcMapMode = rMTF.GetPrefMapMode();
2222 aMap72.SetScaleX( aDPIFrac );
2223 aMap72.SetScaleY( aDPIFrac );
2224 aTargetMapMode = aMap72;
2226 pAttrStack=NULL;
2228 bDstBkPatValid=sal_False;
2229 bDstTxFaceValid=sal_False;
2230 bDstTxModeValid=sal_False;
2231 bDstPnSizeValid=sal_False;
2232 bDstPnModeValid=sal_False;
2233 bDstPnPatValid=sal_False;
2234 bDstFillPatValid=sal_False;
2235 bDstTxSizeValid=sal_False;
2236 bDstFgColValid=sal_False;
2237 bDstBkColValid=sal_False;
2238 bDstPenPositionValid=sal_False;
2239 bDstTextPositionValid=sal_False;
2240 bDstFontNameValid=sal_False;
2242 nNumberOfActions=0;
2243 nNumberOfBitmaps=0;
2244 nWrittenActions=0;
2245 nWrittenBitmaps=0;
2246 nActBitmapPercent=0;
2248 CountActionsAndBitmaps(rMTF);
2250 WriteHeader(rMTF);
2251 WriteOpcodes(rMTF);
2252 WriteOpcode_EndOfFile();
2253 UpdateHeader();
2255 while (pAttrStack!=NULL) {
2256 pAt=pAttrStack;
2257 pAttrStack=pAt->pSucc;
2258 delete pAt;
2261 if ( xStatusIndicator.is() )
2262 xStatusIndicator->end();
2264 return bStatus;
2267 //================== GraphicExport - the exported Function ================
2269 // this needs to be kept in sync with
2270 // ImpFilterLibCacheEntry::GetImportFunction() from
2271 // vcl/source/filter/graphicfilter.cxx
2272 #if defined(DISABLE_DYNLOADING)
2273 #define GraphicExport eptGraphicExport
2274 #endif
2276 extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL
2277 GraphicExport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pFilterConfigItem, sal_Bool)
2279 PictWriter aPictWriter;
2281 // #i119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
2282 GDIMetaFile aScaledMtf( rGraphic.GetGDIMetaFile() );
2284 return aPictWriter.WritePict( aScaledMtf, rStream, pFilterConfigItem );
2287 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */