Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <vcl/metaact.hxx>
21 : #include <vcl/graphicfilter.hxx>
22 : #include <svl/solar.hrc>
23 : #include <vcl/fltcall.hxx>
24 :
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>
37 :
38 : #include <basegfx/polygon/b2dpolygon.hxx>
39 : #include <basegfx/polygon/b2dpolypolygon.hxx>
40 :
41 : //============================== PictWriter ===================================
42 :
43 0 : struct PictWriterAttrStackMember {
44 : struct PictWriterAttrStackMember * pSucc;
45 : Color aLineColor;
46 : Color aFillColor;
47 : RasterOp eRasterOp;
48 : Font aFont;
49 : MapMode aMapMode;
50 : Rectangle aClipRect;
51 : };
52 :
53 :
54 : enum PictDrawingMethod {
55 : PDM_FRAME, PDM_PAINT, PDM_ERASE, PDM_INVERT, PDM_FILL
56 : };
57 :
58 :
59 : struct PictPattern {
60 : sal_uInt32 nLo, nHi;
61 : };
62 :
63 0 : class PictWriter {
64 :
65 : private:
66 :
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;
70 :
71 : SvStream * pPict;
72 :
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;
82 :
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;
97 :
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
103 :
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
108 :
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)
112 :
113 : Polygon PolyPolygonToPolygon(const PolyPolygon & rPoly);
114 : // generates a relatively sane polygon on the basis of a PolyPolygon
115 :
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);
124 :
125 : void ConvertLinePattern(PictPattern & rPat, sal_Bool bVisible) const;
126 : void ConvertFillPattern(PictPattern & rPat, sal_Bool bVisible) const;
127 :
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();
156 :
157 : void SetAttrForPaint();
158 : void SetAttrForFrame();
159 : void SetAttrForText();
160 :
161 : void WriteTextArray(Point & rPoint, const String& rString, const sal_Int32 * pDXAry);
162 :
163 : void HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon);
164 : void WriteOpcodes(const GDIMetaFile & rMTF);
165 :
166 : void WriteHeader(const GDIMetaFile & rMTF);
167 : void UpdateHeader();
168 :
169 : public:
170 :
171 : sal_Bool WritePict( const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem* pFilterConfigItem );
172 : };
173 :
174 :
175 : //========================== Methods of PictWriter ==========================
176 :
177 :
178 0 : void PictWriter::MayCallback()
179 : {
180 0 : if ( xStatusIndicator.is() )
181 : {
182 : sal_uLong nPercent;
183 0 : nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions)
184 0 : *100
185 0 : /((nNumberOfBitmaps<<14)+nNumberOfActions);
186 :
187 0 : if (nPercent>=nLastPercent+3)
188 : {
189 0 : nLastPercent=nPercent;
190 0 : if( nPercent<=100 )
191 0 : xStatusIndicator->setValue( nPercent );
192 : }
193 : }
194 0 : }
195 :
196 0 : void PictWriter::CountActionsAndBitmaps(const GDIMetaFile & rMTF)
197 : {
198 : size_t nAction, nActionCount;
199 : const MetaAction* pMA;
200 :
201 0 : nActionCount = rMTF.GetActionSize();
202 :
203 0 : for (nAction=0; nAction < nActionCount; nAction++)
204 : {
205 0 : pMA = rMTF.GetAction( nAction );
206 :
207 0 : switch( pMA->GetType() )
208 : {
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 0 : nNumberOfBitmaps++;
216 0 : break;
217 : }
218 :
219 0 : nNumberOfActions++;
220 : }
221 0 : }
222 :
223 :
224 0 : Polygon PictWriter::PolyPolygonToPolygon(const PolyPolygon & rPolyPoly)
225 : {
226 : sal_uInt16 nCount,nSize1,nSize2,np,i1,i2,i3,nBestIdx1,nBestIdx2;
227 : long nDistSqr,nBestDistSqr, nCountdownTests;
228 0 : Point aP1,aPRel;
229 0 : Polygon aPoly1, aPoly2, aPoly3;
230 :
231 0 : nCount=rPolyPoly.Count();
232 0 : if (nCount==0) return Polygon(0);
233 :
234 0 : aPoly1=rPolyPoly.GetObject(0);
235 0 : for (np=1; np<nCount; np++) {
236 0 : aPoly2=rPolyPoly.GetObject(np);
237 :
238 : //-----------------The following code merges aPoly1 and aPoly2 to aPoly1-----------------
239 :
240 0 : nSize1=aPoly1.GetSize();
241 0 : nSize2=aPoly2.GetSize();
242 :
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 0 : nCountdownTests=1000;
250 0 : nBestDistSqr=0x7fffffff;
251 0 : nBestIdx1=0;
252 0 : nBestIdx2=0;
253 0 : for (i1=0; i1<nSize1; i1++) {
254 0 : aP1=aPoly1.GetPoint(i1);
255 0 : for (i2=0; i2<nSize2; i2++) {
256 0 : aPRel=aPoly2.GetPoint(i2); aPRel-=aP1;
257 0 : nDistSqr=aPRel.X()*aPRel.X()+aPRel.Y()*aPRel.Y();
258 0 : if (nDistSqr<nBestDistSqr) {
259 0 : nBestIdx1=i1;
260 0 : nBestIdx2=i2;
261 0 : nBestDistSqr=nDistSqr;
262 : }
263 0 : if (nCountdownTests<=0) break;
264 0 : nCountdownTests--;
265 : }
266 0 : if (nCountdownTests<=0) break;
267 : }
268 :
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 0 : aPoly3.Clear();
272 0 : aPoly3.SetSize(nSize1+nSize2+2);
273 0 : i3=0;
274 0 : for (i1=nBestIdx1; i1<nSize1; i1++) aPoly3.SetPoint(aPoly1.GetPoint(i1),i3++);
275 0 : for (i1=0; i1<=nBestIdx1; i1++) aPoly3.SetPoint(aPoly1.GetPoint(i1),i3++);
276 0 : for (i2=nBestIdx2; i2<nSize2; i2++) aPoly3.SetPoint(aPoly2.GetPoint(i2),i3++);
277 0 : for (i2=0; i2<=nBestIdx2; i2++) aPoly3.SetPoint(aPoly2.GetPoint(i2),i3++);
278 :
279 0 : aPoly1=aPoly3;
280 :
281 : //-----------------------------------------------------------------------------------
282 :
283 : }
284 0 : return aPoly1;
285 : }
286 :
287 :
288 0 : void PictWriter::WritePoint(const Point & rPoint)
289 : {
290 0 : Point aPoint = OutputDevice::LogicToLogic( rPoint, aSrcMapMode, aTargetMapMode );
291 0 : *pPict << ((short)aPoint.Y()) << ((short)aPoint.X());
292 0 : }
293 :
294 :
295 0 : void PictWriter::WriteSize(const Size & rSize)
296 : {
297 0 : OutputDevice::LogicToLogic( rSize, aSrcMapMode, aTargetMapMode ); // -Wall is this needed.
298 0 : *pPict << ((short)rSize.Height()) << ((short)rSize.Width());
299 0 : }
300 :
301 :
302 0 : void PictWriter::WriteRGBColor(const Color & rColor)
303 : {
304 0 : const sal_uInt16 nR = ( (sal_uInt16) rColor.GetRed() << 8 ) | (sal_uInt16) rColor.GetRed();
305 0 : const sal_uInt16 nG = ( (sal_uInt16) rColor.GetGreen() << 8 ) | (sal_uInt16) rColor.GetGreen();
306 0 : const sal_uInt16 nB = ( (sal_uInt16) rColor.GetBlue() << 8 ) | (sal_uInt16) rColor.GetBlue();
307 :
308 0 : *pPict << nR << nG << nB;
309 0 : }
310 :
311 0 : void PictWriter::WriteString( const String & rString )
312 : {
313 0 : OString aString(OUStringToOString(rString, osl_getThreadTextEncoding()));
314 0 : sal_Int32 nLen = aString.getLength();
315 0 : if ( nLen > 255 )
316 0 : nLen = 255;
317 0 : *pPict << ( (sal_uInt8)nLen );
318 0 : for (sal_Int32 i = 0; i < nLen; ++i)
319 0 : *pPict << aString[i];
320 0 : }
321 :
322 0 : Rectangle PictWriter::MapRectangle( const Rectangle& rRect )
323 : {
324 0 : Point aPoint = OutputDevice::LogicToLogic( rRect.TopLeft(), aSrcMapMode, aTargetMapMode );
325 0 : Size aSize = OutputDevice::LogicToLogic( rRect.GetSize(), aSrcMapMode, aTargetMapMode );
326 0 : Rectangle aRect( aPoint, aSize );
327 0 : aRect.Justify();
328 0 : ++aRect.Bottom();
329 0 : ++aRect.Right();
330 0 : return aRect;
331 : }
332 :
333 0 : void PictWriter::WriteRectangle(const Rectangle & rRect)
334 : {
335 0 : Rectangle aRect( MapRectangle( rRect ) );
336 0 : *pPict << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left()
337 0 : << (sal_Int16)aRect.Bottom() << (sal_Int16)aRect.Right();
338 0 : }
339 :
340 0 : void PictWriter::WritePolygon(const Polygon & rPoly)
341 : {
342 : sal_uInt16 nDataSize,i,nSize;
343 0 : short nMinX = 0, nMinY = 0, nMaxX = 0, nMaxY = 0;
344 : short nx,ny;
345 0 : Polygon aPoly(rPoly);
346 :
347 0 : nSize=aPoly.GetSize();
348 :
349 0 : if (aPoly.GetPoint(0) != aPoly.GetPoint(nSize-1))
350 : {
351 0 : nSize++;
352 0 : aPoly.SetSize(nSize);
353 0 : aPoly.SetPoint(aPoly.GetPoint(0),nSize-1);
354 : }
355 :
356 0 : nDataSize=nSize*4+10;
357 0 : for (i=0; i<nSize; i++)
358 : {
359 0 : Point aPoint = OutputDevice::LogicToLogic( aPoly.GetPoint( i ),
360 : aSrcMapMode,
361 0 : aTargetMapMode );
362 :
363 0 : nx = (short) aPoint.X();
364 0 : ny = (short) aPoint.Y();
365 :
366 0 : if ( i==0 || nMinX>nx )
367 0 : nMinX=nx;
368 0 : if ( i==0 || nMinY>ny )
369 0 : nMinY=ny;
370 0 : if ( i==0 || nMaxX<nx )
371 0 : nMaxX=nx;
372 0 : if ( i==0 || nMaxY<ny )
373 0 : nMaxY=ny;
374 : }
375 :
376 0 : *pPict << nDataSize << nMinY << nMinX << nMaxY << nMaxX;
377 :
378 0 : for (i=0; i<nSize; i++)
379 0 : WritePoint( aPoly.GetPoint(i) );
380 0 : }
381 :
382 :
383 0 : void PictWriter::WriteArcAngles(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
384 : {
385 : Point aStartPt = OutputDevice::LogicToLogic( rStartPt,
386 : aSrcMapMode,
387 0 : aTargetMapMode );
388 : Point aEndPt = OutputDevice::LogicToLogic( rEndPt,
389 : aSrcMapMode,
390 0 : aTargetMapMode );
391 : Rectangle aRect( OutputDevice::LogicToLogic( rRect.TopLeft(),
392 : aSrcMapMode,
393 0 : aTargetMapMode ),
394 : OutputDevice::LogicToLogic( rRect.GetSize(),
395 : aSrcMapMode,
396 0 : aTargetMapMode ) );
397 0 : Point aCenter;
398 : double fAngS, fAngE, fdx, fdy;
399 : short nStartAngle, nArcAngle;
400 :
401 :
402 0 : aCenter=Point( ( aRect.Left() + aRect.Right() ) >> 1,
403 0 : ( aRect.Top() + aRect.Bottom() ) >> 1 );
404 :
405 0 : fdx=(double)(aStartPt.X()-aCenter.X());
406 0 : fdy=(double)(aStartPt.Y()-aCenter.Y());
407 0 : if ( fdx==0.0 && fdy==0.0 )
408 0 : fdx=1.0;
409 0 : fAngE=atan2(fdx,-fdy);
410 :
411 0 : fdx=(double)(aEndPt.X()-aCenter.X());
412 0 : fdy=(double)(aEndPt.Y()-aCenter.Y());
413 0 : if ( fdx==0.0 && fdy==0.0 )
414 0 : fdx=1.0;
415 0 : fAngS=atan2(fdx,-fdy);
416 :
417 0 : nStartAngle=(short)(fAngS*180.0/3.14159265359);
418 0 : nArcAngle=((short)(fAngE*180.0/3.14159265359))-nStartAngle;
419 0 : if (nArcAngle<0)
420 0 : nArcAngle += 360;
421 0 : *pPict << nStartAngle << nArcAngle;
422 0 : }
423 :
424 :
425 0 : void PictWriter::ConvertLinePattern(PictPattern & rPat, sal_Bool bVisible) const
426 : {
427 0 : if( bVisible )
428 : {
429 0 : rPat.nHi=0xffffffff;
430 0 : rPat.nLo=0xffffffff;
431 : }
432 : else
433 : {
434 0 : rPat.nHi=0x00000000;
435 0 : rPat.nLo=0x00000000;
436 : }
437 0 : }
438 :
439 0 : void PictWriter::ConvertFillPattern(PictPattern & rPat, sal_Bool bVisible) const
440 : {
441 0 : if( bVisible )
442 : {
443 0 : rPat.nHi=0xffffffff;
444 0 : rPat.nLo=0xffffffff;
445 : }
446 : else
447 : {
448 0 : rPat.nHi=0x00000000;
449 0 : rPat.nLo=0x00000000;
450 : }
451 0 : }
452 :
453 :
454 0 : void PictWriter::WriteOpcode_TxFace(const Font & rFont)
455 : {
456 : sal_uInt8 nFace;
457 : FontWeight eWeight;
458 :
459 0 : nFace=0;
460 0 : eWeight=rFont.GetWeight();
461 0 : if (eWeight==WEIGHT_BOLD ||
462 0 : eWeight==WEIGHT_SEMIBOLD ||
463 0 : eWeight==WEIGHT_ULTRABOLD ||
464 0 : eWeight==WEIGHT_BLACK) nFace|=0x01;
465 0 : if (rFont.GetItalic()!=ITALIC_NONE) nFace|=0x02;
466 0 : if (rFont.GetUnderline()!=UNDERLINE_NONE) nFace|=0x04;
467 0 : if (rFont.IsOutline()==sal_True) nFace|=0x08;
468 0 : if (rFont.IsShadow()==sal_True) nFace|=0x10;
469 :
470 0 : if (bDstTxFaceValid==sal_False || nDstTxFace!=nFace) {
471 0 : *pPict << (sal_uInt16)0x0004 << nFace << (sal_uInt8)0;
472 0 : nDstTxFace=nFace;
473 0 : bDstTxFaceValid=sal_True;
474 : }
475 0 : }
476 :
477 :
478 0 : void PictWriter::WriteOpcode_TxMode(RasterOp eMode)
479 : {
480 : sal_uInt16 nVal;
481 :
482 0 : if (bDstTxModeValid==sal_False || eDstTxMode!=eMode) {
483 0 : switch (eMode) {
484 0 : case ROP_INVERT: nVal=0x000c; break;
485 0 : case ROP_XOR: nVal=0x000a; break;
486 0 : default: nVal=0x0008;
487 : }
488 0 : *pPict << (sal_uInt16)0x0005 << nVal;
489 0 : eDstTxMode=eMode;
490 0 : bDstTxModeValid=sal_True;
491 : }
492 0 : }
493 :
494 :
495 0 : void PictWriter::WriteOpcode_PnSize(sal_uInt16 nSize)
496 : {
497 0 : if (nSize==0) nSize=1;
498 0 : if (bDstPnSizeValid==sal_False || nDstPnSize!=nSize) {
499 0 : *pPict << (sal_uInt16)0x0007 << nSize << nSize;
500 0 : nDstPnSize=nSize;
501 0 : bDstPnSizeValid=sal_True;
502 : }
503 0 : }
504 :
505 :
506 0 : void PictWriter::WriteOpcode_PnMode(RasterOp eMode)
507 : {
508 : sal_uInt16 nVal;
509 :
510 0 : if (bDstPnModeValid==sal_False || eDstPnMode!=eMode) {
511 0 : switch (eMode)
512 : {
513 0 : case ROP_INVERT: nVal=0x000c; break;
514 0 : case ROP_XOR: nVal=0x000a; break;
515 0 : default: nVal=0x0008;
516 : }
517 0 : *pPict << (sal_uInt16)0x0008 << nVal;
518 0 : eDstPnMode=eMode;
519 0 : bDstPnModeValid=sal_True;
520 : }
521 0 : }
522 :
523 :
524 0 : void PictWriter::WriteOpcode_PnLinePat(sal_Bool bVisible)
525 : {
526 : PictPattern aPat;
527 :
528 0 : ConvertLinePattern(aPat,bVisible);
529 0 : if (bDstPnPatValid==sal_False || aDstPnPat.nHi!=aPat.nHi || aDstPnPat.nLo!=aPat.nLo) {
530 0 : *pPict << (sal_uInt16)0x0009 << aPat.nHi << aPat.nLo;
531 0 : aDstPnPat=aPat;
532 0 : bDstPnPatValid=sal_True;
533 : }
534 0 : }
535 :
536 :
537 0 : void PictWriter::WriteOpcode_PnFillPat(sal_Bool bVisible)
538 : {
539 : PictPattern aPat;
540 :
541 0 : ConvertFillPattern(aPat,bVisible);
542 0 : if (bDstPnPatValid==sal_False || aDstPnPat.nHi!=aPat.nHi || aDstPnPat.nLo!=aPat.nLo) {
543 0 : *pPict << (sal_uInt16)0x0009 << aPat.nHi << aPat.nLo;
544 0 : aDstPnPat=aPat;
545 0 : bDstPnPatValid=sal_True;
546 : }
547 0 : }
548 :
549 :
550 0 : void PictWriter::WriteOpcode_OvSize(const Size & rSize)
551 : {
552 0 : *pPict << (sal_uInt16)0x000b;
553 0 : WriteSize(rSize);
554 0 : }
555 :
556 :
557 0 : void PictWriter::WriteOpcode_TxSize(sal_uInt16 nSize)
558 : {
559 0 : if (bDstTxSizeValid==sal_False || nDstTxSize!=nSize) {
560 :
561 : nDstTxSize = (sal_uInt16) OutputDevice::LogicToLogic( Size( 0, nSize ),
562 0 : aSrcMapMode, aTargetMapMode ).Height();
563 :
564 0 : *pPict << (sal_uInt16)0x000d << nDstTxSize;
565 0 : bDstTxSizeValid=sal_True;
566 : }
567 0 : }
568 :
569 :
570 0 : void PictWriter::WriteOpcode_RGBFgCol(const Color & rColor)
571 : {
572 0 : if (bDstFgColValid==sal_False || aDstFgCol!=rColor) {
573 0 : *pPict << (sal_uInt16)0x001a;
574 0 : WriteRGBColor(rColor);
575 0 : aDstFgCol=rColor;
576 0 : bDstFgColValid=sal_True;
577 : }
578 0 : }
579 :
580 :
581 0 : void PictWriter::WriteOpcode_RGBBkCol(const Color & rColor)
582 : {
583 0 : if (bDstBkColValid==sal_False || aDstBkCol!=rColor) {
584 0 : *pPict << (sal_uInt16)0x001b;
585 0 : WriteRGBColor(rColor);
586 0 : aDstBkCol=rColor;
587 0 : bDstBkColValid=sal_True;
588 : }
589 0 : }
590 :
591 :
592 0 : void PictWriter::WriteOpcode_Line(const Point & rLocPt, const Point & rNewPt)
593 : {
594 : Point aLocPt = OutputDevice::LogicToLogic( rLocPt,
595 : aSrcMapMode,
596 0 : aTargetMapMode );
597 : Point aNewPt = OutputDevice::LogicToLogic( rNewPt,
598 : aSrcMapMode,
599 0 : aTargetMapMode );
600 : long dh,dv;
601 :
602 0 : dh=aNewPt.X()-aLocPt.X();
603 0 : dv=aNewPt.Y()-aLocPt.Y();
604 0 : if (dh<=127 && dh>=-128 && dv<=127 && dv>=-128)
605 : { // ShortLine
606 0 : *pPict << (sal_uInt16)0x0022;
607 0 : WritePoint(rLocPt);
608 0 : *pPict << (char)dh << (char)dv;
609 : }
610 : else
611 : {
612 0 : *pPict << (sal_uInt16)0x0020;
613 0 : WritePoint(rLocPt);
614 0 : WritePoint(rNewPt);
615 : }
616 0 : aDstPenPosition=rNewPt;
617 0 : bDstPenPositionValid=sal_True;
618 0 : }
619 :
620 :
621 0 : void PictWriter::WriteOpcode_LineFrom(const Point & rNewPt)
622 : {
623 : Point aNewPt = OutputDevice::LogicToLogic( rNewPt,
624 : aSrcMapMode,
625 0 : aTargetMapMode );
626 : long dh,dv;
627 :
628 0 : dh = aNewPt.X()-aDstPenPosition.X();
629 0 : dv = aNewPt.Y()-aDstPenPosition.Y();
630 :
631 0 : if (dh<=127 && dh>=-128 && dv<=127 && dv>=-128)
632 : { // ShortLine
633 0 : *pPict << (sal_uInt16)0x0023;
634 0 : *pPict << (char)dh << (char)dv;
635 : }
636 : else
637 : {
638 0 : *pPict << (sal_uInt16)0x0021;
639 0 : WritePoint(rNewPt);
640 : }
641 0 : aDstPenPosition=rNewPt;
642 0 : bDstPenPositionValid=sal_True;
643 0 : }
644 :
645 :
646 0 : void PictWriter::WriteOpcode_Text(const Point & rPoint, const String& rString, sal_Bool bDelta)
647 : {
648 : Point aPoint = OutputDevice::LogicToLogic( rPoint,
649 : aSrcMapMode,
650 0 : aTargetMapMode );
651 : long dh,dv;
652 : sal_uLong nPos;
653 :
654 0 : nPos = pPict->Tell();
655 0 : dh = aPoint.X()-aDstTextPosition.X();
656 0 : dv = aPoint.Y()-aDstTextPosition.Y();
657 :
658 0 : if (bDstTextPositionValid==sal_False || dh<0 || dh>255 || dv<0 || dv>255 || bDelta==sal_False)
659 : {
660 0 : *pPict << (sal_uInt16)0x0028;
661 0 : WritePoint(rPoint);
662 : }
663 0 : else if (dv==0)
664 : {
665 0 : *pPict << (sal_uInt16)0x0029 << (sal_uInt8)dh;
666 : }
667 0 : else if (dh==0)
668 : {
669 0 : *pPict << (sal_uInt16)0x002a << (sal_uInt8)dv;
670 : }
671 : else
672 : {
673 0 : *pPict << (sal_uInt16)0x002b << (sal_uInt8)dh << (sal_uInt8)dv;
674 : }
675 :
676 0 : WriteString( rString );
677 0 : if (((pPict->Tell()-nPos)&1)!=0)
678 0 : *pPict << (sal_uInt8)0;
679 :
680 0 : aDstTextPosition = aPoint;
681 0 : bDstTextPositionValid=sal_True;
682 0 : }
683 :
684 :
685 0 : void PictWriter::WriteOpcode_FontName(const Font & rFont)
686 : {
687 : sal_uInt16 nDataLen,nFontId;
688 :
689 0 : switch (rFont.GetFamily()) {
690 0 : case FAMILY_MODERN: nFontId=22; break;
691 0 : case FAMILY_ROMAN: nFontId=20; break;
692 0 : case FAMILY_SWISS: nFontId=21; break;
693 0 : default: nFontId=1;
694 : }
695 :
696 0 : if (bDstFontNameValid==sal_False || nDstFontNameId!=nFontId || aDstFontName!=rFont.GetName())
697 : {
698 0 : OString aString(OUStringToOString(rFont.GetName(), osl_getThreadTextEncoding()));
699 0 : sal_uInt16 nFontNameLen = aString.getLength();
700 0 : if ( nFontNameLen )
701 : {
702 0 : nDataLen = 3 + nFontNameLen;
703 0 : *pPict << (sal_uInt16)0x002c << nDataLen << nFontId;
704 0 : WriteString( rFont.GetName() );
705 0 : if ( ( nFontNameLen & 1 ) == 0 )
706 0 : *pPict << (sal_uInt8)0;
707 : }
708 0 : *pPict << (sal_uInt16)0x0003 << nFontId;
709 0 : aDstFontName=rFont.GetName();
710 0 : nDstFontNameId=nFontId;
711 0 : bDstFontNameValid=sal_True;
712 : }
713 0 : }
714 :
715 0 : void PictWriter::WriteOpcode_ClipRect( const Rectangle& rRect )
716 : {
717 0 : Rectangle aRect( MapRectangle( rRect ) );
718 0 : ++aRect.Bottom();
719 0 : ++aRect.Right();
720 0 : *pPict << (sal_uInt16)1 // opcode 1
721 0 : << (sal_uInt16)10 // data size
722 0 : << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left()
723 0 : << (sal_Int16)aRect.Bottom() << (sal_Int16)aRect.Right();
724 0 : aClipRect = aRect;
725 0 : }
726 :
727 0 : void PictWriter::WriteOpcode_Rect(PictDrawingMethod eMethod, const Rectangle & rRect)
728 : {
729 : sal_uInt16 oc;
730 0 : switch (eMethod) {
731 0 : case PDM_FRAME: oc=0x0030; break;
732 0 : case PDM_PAINT: oc=0x0031; break;
733 0 : case PDM_ERASE: oc=0x0032; break;
734 0 : case PDM_INVERT: oc=0x0033; break;
735 0 : case PDM_FILL: oc=0x0034; break;
736 0 : default: oc=0; break; // -Wall a default for oc...
737 : }
738 0 : *pPict << oc;
739 0 : WriteRectangle(rRect);
740 0 : }
741 :
742 :
743 0 : void PictWriter::WriteOpcode_SameRect(PictDrawingMethod eMethod)
744 : {
745 : sal_uInt16 oc;
746 0 : switch (eMethod) {
747 0 : case PDM_FRAME: oc=0x0038; break;
748 0 : case PDM_PAINT: oc=0x0039; break;
749 0 : case PDM_ERASE: oc=0x003a; break;
750 0 : case PDM_INVERT: oc=0x003b; break;
751 0 : case PDM_FILL: oc=0x003c; break;
752 0 : default: oc=0; break; // -Wall a default for oc...
753 : }
754 0 : *pPict << oc;
755 0 : }
756 :
757 :
758 0 : void PictWriter::WriteOpcode_RRect(PictDrawingMethod eMethod, const Rectangle & rRect)
759 : {
760 : sal_uInt16 oc;
761 0 : switch (eMethod) {
762 0 : case PDM_FRAME: oc=0x0040; break;
763 0 : case PDM_PAINT: oc=0x0041; break;
764 0 : case PDM_ERASE: oc=0x0042; break;
765 0 : case PDM_INVERT: oc=0x0043; break;
766 0 : case PDM_FILL: oc=0x0044; break;
767 0 : default: oc=0; break; // -Wall a default for oc...
768 : }
769 0 : *pPict << oc;
770 0 : WriteRectangle(rRect);
771 0 : }
772 :
773 :
774 0 : void PictWriter::WriteOpcode_SameRRect(PictDrawingMethod eMethod)
775 : {
776 : sal_uInt16 oc;
777 0 : switch (eMethod) {
778 0 : case PDM_FRAME: oc=0x0048; break;
779 0 : case PDM_PAINT: oc=0x0049; break;
780 0 : case PDM_ERASE: oc=0x004a; break;
781 0 : case PDM_INVERT: oc=0x004b; break;
782 0 : case PDM_FILL: oc=0x004c; break;
783 0 : default: oc=0; break; // -Wall a default for oc...
784 : }
785 0 : *pPict << oc;
786 0 : }
787 :
788 :
789 0 : void PictWriter::WriteOpcode_Oval(PictDrawingMethod eMethod, const Rectangle & rRect)
790 : {
791 : sal_uInt16 oc;
792 0 : switch (eMethod) {
793 0 : case PDM_FRAME: oc=0x0050; break;
794 0 : case PDM_PAINT: oc=0x0051; break;
795 0 : case PDM_ERASE: oc=0x0052; break;
796 0 : case PDM_INVERT: oc=0x0053; break;
797 0 : case PDM_FILL: oc=0x0054; break;
798 0 : default: oc=0; break; // -Wall a default for oc...
799 : }
800 0 : *pPict << oc;
801 0 : WriteRectangle(rRect);
802 0 : }
803 :
804 :
805 0 : void PictWriter::WriteOpcode_SameOval(PictDrawingMethod eMethod)
806 : {
807 : sal_uInt16 oc;
808 0 : switch (eMethod) {
809 0 : case PDM_FRAME: oc=0x0058; break;
810 0 : case PDM_PAINT: oc=0x0059; break;
811 0 : case PDM_ERASE: oc=0x005a; break;
812 0 : case PDM_INVERT: oc=0x005b; break;
813 0 : case PDM_FILL: oc=0x005c; break;
814 0 : default: oc=0; break; // -Wall a default for oc...
815 : }
816 0 : *pPict << oc;
817 0 : }
818 :
819 :
820 0 : void PictWriter::WriteOpcode_Arc(PictDrawingMethod eMethod, const Rectangle & rRect,
821 : const Point & rStartPt, const Point & rEndPt)
822 : {
823 : sal_uInt16 oc;
824 0 : switch (eMethod) {
825 0 : case PDM_FRAME: oc=0x0060; break;
826 0 : case PDM_PAINT: oc=0x0061; break;
827 0 : case PDM_ERASE: oc=0x0062; break;
828 0 : case PDM_INVERT: oc=0x0063; break;
829 0 : case PDM_FILL: oc=0x0064; break;
830 0 : default: oc=0; break; // -Wall a default for oc...
831 : }
832 0 : *pPict << oc;
833 0 : WriteRectangle(rRect);
834 0 : WriteArcAngles(rRect,rStartPt,rEndPt);
835 0 : }
836 :
837 :
838 0 : void PictWriter::WriteOpcode_SameArc(PictDrawingMethod eMethod, const Rectangle & rRect,
839 : const Point & rStartPt, const Point & rEndPt)
840 : {
841 : sal_uInt16 oc;
842 0 : switch (eMethod) {
843 0 : case PDM_FRAME: oc=0x0068; break;
844 0 : case PDM_PAINT: oc=0x0069; break;
845 0 : case PDM_ERASE: oc=0x006a; break;
846 0 : case PDM_INVERT: oc=0x006b; break;
847 0 : case PDM_FILL: oc=0x006c; break;
848 0 : default: oc=0; break; // -Wall a default for oc...
849 : }
850 0 : *pPict << oc;
851 0 : WriteArcAngles(rRect,rStartPt,rEndPt);
852 0 : }
853 :
854 :
855 0 : void PictWriter::WriteOpcode_Poly(PictDrawingMethod eMethod, const Polygon & rPoly)
856 : {
857 : sal_uInt16 oc;
858 :
859 0 : if (rPoly.GetSize()<3) return;
860 0 : switch (eMethod) {
861 0 : case PDM_FRAME: oc=0x0070; break;
862 0 : case PDM_PAINT: oc=0x0071; break;
863 0 : case PDM_ERASE: oc=0x0072; break;
864 0 : case PDM_INVERT: oc=0x0073; break;
865 0 : case PDM_FILL: oc=0x0074; break;
866 0 : default: oc=0; break; // -Wall a default for oc...
867 : }
868 0 : *pPict << oc;
869 0 : WritePolygon(rPoly);
870 : }
871 :
872 :
873 0 : void PictWriter::WriteOpcode_BitsRect(const Point & rPoint, const Size & rSize, const Bitmap & rBitmap)
874 : {
875 0 : BitmapReadAccess* pAcc = NULL;
876 0 : Bitmap aBitmap( rBitmap );
877 :
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 0 : sal_uInt8 nEquData = 0;
883 : sal_uInt8 nFlagCounterByte, nRed, nGreen, nBlue;
884 :
885 0 : SetAttrForPaint();
886 :
887 : // generating a temporary Windows-BMP-File:
888 0 : nActBitmapPercent=30;
889 0 : MayCallback();
890 :
891 0 : if ( bStatus == sal_False )
892 0 : return;
893 0 : if ( ( pAcc = aBitmap.AcquireReadAccess() ) == NULL )
894 0 : return;
895 :
896 0 : nBitsPerPixel = aBitmap.GetBitCount();
897 :
898 : // export code below only handles four discrete cases
899 : nBitsPerPixel =
900 0 : nBitsPerPixel <= 1 ? 1 : nBitsPerPixel <= 4 ? 4 : nBitsPerPixel <= 8 ? 8 : 24;
901 :
902 0 : nWidth = pAcc->Width();
903 0 : nHeight = pAcc->Height();
904 :
905 : // If 24-Bit, then create the Opcode 'DirectBitsRect':
906 0 : if ( nBitsPerPixel == 24 )
907 : {
908 : // Calculate the number of bytes of an (uncompressed) line of source and destination.
909 0 : nSrcRowBytes =( ( 3 * nWidth ) + 0x0003 ) & 0xfffc;
910 0 : nDstRowBytes = nWidth * 4;
911 :
912 : // writing Opcode and BaseAddr (?):
913 0 : *pPict << (sal_uInt16)0x009a << (sal_uInt32)0x000000ff;
914 :
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:
919 :
920 0 : if ( nDstRowBytes < 8 )
921 0 : nPackType = 1;
922 : else
923 0 : nPackType = 4;
924 :
925 : // writing PixMap-Structure:
926 0 : *pPict << (sal_uInt16)(nDstRowBytes|0x8000) // Bytes per row and the fact that it's a 'PixMap'
927 0 : << (sal_uInt16)0x0000 // Y1-position of the bitmap in the source
928 0 : << (sal_uInt16)0x0000 // X1-position of the bitmap in the source
929 0 : << (sal_uInt16)nHeight // Y2-position of the bitmap in the source
930 0 : << (sal_uInt16)nWidth // X2-position of the bitmap in the source
931 0 : << (sal_uInt16)0x0000 // Version
932 0 : << (sal_uInt16)nPackType // Packing type
933 0 : << (sal_uInt32) 0x00000000 // Packing size (?)
934 0 : << (sal_uInt32) 0x00480000 // H-Res
935 0 : << (sal_uInt32) 0x00480000 // V-Res
936 0 : << (sal_uInt16)0x0010 // Pixel type (?)
937 0 : << (sal_uInt16)0x0020 // Pixel size: 32 bit
938 0 : << (sal_uInt16)0x0004 // CmpCount: 4 components
939 0 : << (sal_uInt16)0x0008 // CmpSize: 8 bits
940 0 : << (sal_uInt32) 0x00000000 // PlaneBytes (?)
941 0 : << (sal_uInt32) 0x00000000 // (?)
942 0 : << (sal_uInt32) 0x00000000; // (?)
943 :
944 : // Source-Rectangle schreiben:
945 0 : *pPict << (sal_uInt16)0x0000 // Y1-position on the bitmap
946 0 : << (sal_uInt16)0x0000 // X1-position on the bitmap
947 0 : << (sal_uInt16)nHeight // Y2-position on the bitmap
948 0 : << (sal_uInt16)nWidth; // X2-position on the bitmap
949 :
950 : // writing the Destination-Rectangle:
951 0 : WritePoint( rPoint );
952 0 : WritePoint( Point( rPoint.X() + rSize.Width(), rPoint.Y() + rSize.Height() ) );
953 :
954 : // writing the Transfer mode:
955 0 : *pPict << (sal_uInt16)0x0000; // (?)
956 :
957 : // remember position of the Map-data in the target:
958 0 : nDstMapPos=pPict->Tell();
959 :
960 0 : if ( nPackType == 1 ) // when 24 bits nWidth == 1 !!
961 : { // don't pack
962 0 : for ( ny = 0; ny < nHeight; ny++ )
963 : {
964 0 : *pPict << (sal_uInt8)0;
965 0 : *pPict << (sal_uInt8)pAcc->GetPixel( ny, 0 ).GetRed();
966 0 : *pPict << (sal_uInt8)pAcc->GetPixel( ny, 0 ).GetGreen();
967 0 : *pPict << (sal_uInt8)pAcc->GetPixel( ny, 0 ).GetBlue();
968 : // count percentages, Callback, check errors:
969 0 : nActBitmapPercent = ( ny * 70 / nHeight ) + 30; // (30% already added up to the writing of the Win-BMP file)
970 0 : MayCallback();
971 : }
972 : }
973 : else // packing ( PackType == 4 )
974 : {
975 : // allocate memory for lines-intermediate-data-structure
976 0 : for ( nc = 0; nc < 4; nc++ )
977 0 : pComp[ nc ] = new sal_uInt8[ nWidth ];
978 :
979 : // loop trough rows:
980 0 : for ( ny = 0; ny < nHeight; ny++ )
981 : {
982 : // read line ny of source into the intermediate data structure
983 :
984 0 : for ( nx = 0; nx < nWidth; nx++ )
985 : {
986 0 : pComp[ 1 ][ nx ] = (sal_uInt8)pAcc->GetPixel( ny, nx ) .GetRed();
987 0 : pComp[ 2 ][ nx ] = (sal_uInt8)pAcc->GetPixel( ny, nx ) .GetGreen();
988 0 : pComp[ 3 ][ nx ] = (sal_uInt8)pAcc->GetPixel( ny, nx ) .GetBlue();
989 0 : pComp[ 0 ][ nx ] = 0;
990 : }
991 :
992 : // remember start of the row in the target:
993 0 : nDstRowPos = pPict->Tell();
994 :
995 : // ByteCount (that's the size of the packed row) is at first 0 (will be corrected later):
996 0 : if ( nDstRowBytes > 250 )
997 0 : *pPict << (sal_uInt16)0;
998 : else
999 0 : *pPict << (sal_uInt8)0;
1000 :
1001 : // loop trough components:
1002 0 : for ( nc = 0; nc < 4; nc++ )
1003 : {
1004 : // loop through x:
1005 0 : nx = 0;
1006 0 : while ( nx < nWidth )
1007 : {
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 0 : nEqu3 = nx;
1012 : for (;;)
1013 : {
1014 0 : if ( nEqu3 + 2 >= nWidth )
1015 : {
1016 0 : nEqu3 = nWidth;
1017 0 : break;
1018 : }
1019 0 : nEquData = pComp[nc][nEqu3];
1020 0 : if ( nEquData == pComp[nc][nEqu3+1] && nEquData==pComp[nc][nEqu3+2] )
1021 0 : break;
1022 0 : nEqu3++;
1023 : }
1024 :
1025 : // write the data from nx to nEqu3 uncompressed (into multiple records if necessarcy);
1026 0 : while ( nEqu3 > nx )
1027 : {
1028 0 : nCount = nEqu3 - nx;
1029 0 : if ( nCount > 128 )
1030 0 : nCount=128;
1031 0 : nFlagCounterByte = (sal_uInt8)(nCount-1);
1032 0 : *pPict << nFlagCounterByte;
1033 0 : do
1034 : {
1035 0 : *pPict << pComp[nc][nx++];
1036 0 : nCount--;
1037 : }
1038 : while ( nCount > 0 );
1039 : }
1040 :
1041 : // now create a compression record (if at least 3 identical bytes were found above)
1042 0 : if ( nx < nWidth )
1043 : { // Hint: Then one has nx==nEqu3 (hopefully)
1044 0 : 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 0 : while ( nx + nCount < nWidth && nCount < 128 )
1047 : {
1048 0 : if ( nEquData != pComp[ nc ][ nx + nCount ] )
1049 0 : break;
1050 0 : nCount++;
1051 : }
1052 : // nCount write equal Bytes compressed:
1053 0 : nFlagCounterByte = (sal_uInt8)( 1 - (long)nCount );
1054 0 : *pPict << nFlagCounterByte << nEquData;
1055 0 : nx += nCount;
1056 : }
1057 : }
1058 : }
1059 : // correct ByteCount:
1060 0 : nPos = pPict->Tell();
1061 0 : pPict->Seek( nDstRowPos );
1062 0 : if ( nDstRowBytes > 250 )
1063 0 : *pPict << ( (sal_uInt16)( nPos - nDstRowPos - 2 ) );
1064 : else
1065 0 : *pPict << ( (sal_uInt8)( nPos - nDstRowPos - 1 ) );
1066 0 : pPict->Seek( nPos );
1067 :
1068 : // count percentages, Callback, check errors:
1069 0 : nActBitmapPercent = ( ny * 70 / nHeight ) + 30; // (30% already added up to the writing of the Win-BMP file)
1070 0 : MayCallback();
1071 : }
1072 : // clean up:
1073 0 : for ( nc = 0; nc < 4; nc++ )
1074 0 : delete pComp[ nc ];
1075 : }
1076 : }
1077 : else
1078 : { // don't generate 24-bit i.e. Opcode 'PackBitsRect':
1079 :
1080 : // Some input filters are ignoring the palette of 1-bit images and are using
1081 : // the foreground and the background color instead.
1082 0 : if ( nBitsPerPixel == 1 )
1083 : {
1084 0 : WriteOpcode_RGBBkCol( pAcc->GetPaletteColor( 0 ) );
1085 0 : WriteOpcode_RGBFgCol( pAcc->GetPaletteColor( 1 ) );
1086 : }
1087 : else
1088 : {
1089 0 : WriteOpcode_RGBBkCol( Color( COL_BLACK ) );
1090 0 : WriteOpcode_RGBFgCol( Color( COL_WHITE ) );
1091 : }
1092 :
1093 : // Calculate the number of bytes of an (unpacked) line of source an destination.
1094 0 : nDstRowBytes = ( nWidth * nBitsPerPixel + 7 ) >> 3;
1095 0 : nSrcRowBytes = ( nDstRowBytes + 3 ) & 0xfffffffc;
1096 :
1097 : // writing Opcode:
1098 0 : *pPict << (sal_uInt16)0x0098;
1099 :
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 0 : if ( nDstRowBytes < 8 )
1105 0 : nPackType = 1;
1106 : else
1107 0 : nPackType = 0;
1108 :
1109 : // write PixMap-Structure:
1110 0 : *pPict << (sal_uInt16)(nDstRowBytes|0x8000) // Bytes per row and the fact that it's a 'PixMap'
1111 0 : << (sal_uInt16)0x0000 // Y1-position of the bitmap in the source
1112 0 : << (sal_uInt16)0x0000 // X1-position of the bitmap in the source
1113 0 : << (sal_uInt16)nHeight // Y2-position of the bitmap in the source
1114 0 : << (sal_uInt16)nWidth // X2-position of the bitmap in the source
1115 0 : << (sal_uInt16)0x0000 // Version
1116 0 : << (sal_uInt16)nPackType // Packing type
1117 0 : << (sal_uInt32) 0x00000000 // Packing size (?)
1118 0 : << (sal_uInt32) 0x00480000 // H-Res
1119 0 : << (sal_uInt32) 0x00480000 // V-Res
1120 0 : << (sal_uInt16)0x0000 // Pixel type (?)
1121 0 : << (sal_uInt16)nBitsPerPixel // Pixel size
1122 0 : << (sal_uInt16)0x0001 // CmpCount: 1 component
1123 0 : << (sal_uInt16)nBitsPerPixel // CmpSize
1124 0 : << (sal_uInt32) 0x00000000 // PlaneBytes (?)
1125 0 : << (sal_uInt32) 0x00000000 // (?)
1126 0 : << (sal_uInt32) 0x00000000; // (?)
1127 :
1128 : // writing and reading the palette:
1129 0 : nColTabSize = pAcc->GetPaletteEntryCount();
1130 0 : *pPict << (sal_uInt32)0 << (sal_uInt16)0x8000 << (sal_uInt16)( nColTabSize - 1 );
1131 :
1132 0 : for ( i = 0; i < nColTabSize; i++ )
1133 : {
1134 0 : nRed = (sal_uInt8)pAcc->GetPaletteColor( (sal_uInt16)i ).GetRed();
1135 0 : nGreen = (sal_uInt8)pAcc->GetPaletteColor( (sal_uInt16)i ).GetGreen();
1136 0 : nBlue = (sal_uInt8)pAcc->GetPaletteColor( (sal_uInt16)i ).GetBlue();
1137 0 : *pPict << (sal_uInt16)0 << nRed << nRed << nGreen << nGreen << nBlue << nBlue;
1138 : }
1139 :
1140 : // writing Source-Rectangle:
1141 0 : *pPict << (sal_uInt16)0 << (sal_uInt16)0 << (sal_uInt16)nHeight << (sal_uInt16)nWidth;
1142 :
1143 : // writing Destination-Rectangle:
1144 0 : WritePoint( rPoint );
1145 0 : WritePoint( Point( rPoint.X() + rSize.Width(), rPoint.Y() + rSize.Height() ) );
1146 :
1147 : // writing Transfer mode:
1148 0 : *pPict << (sal_uInt16)0; // (?)
1149 :
1150 : // allocate memory for a row:
1151 0 : pPix = new sal_uInt8[ nSrcRowBytes ];
1152 :
1153 : // Position der Map-Daten in Ziel merken:
1154 0 : nDstMapPos=pPict->Tell();
1155 :
1156 : // loop trough rows:
1157 0 : for ( ny = 0; ny < nHeight; ny++ )
1158 : {
1159 :
1160 : // read line ny of source into the buffer:
1161 0 : switch ( nBitsPerPixel )
1162 : {
1163 : case 1 :
1164 0 : for ( pTemp = pPix, i = 0; i < nSrcRowBytes; i++ )
1165 0 : *pTemp++ = (sal_uInt8)0;
1166 0 : for ( i = 0; i < nWidth; i++ )
1167 0 : pPix[ ( i >> 3 ) ] |= (pAcc->GetPixelIndex( ny, i ) & 1) << ((i & 7) ^ 7);
1168 0 : break;
1169 : case 4 :
1170 0 : for ( pTemp = pPix, i = 0; i < nSrcRowBytes; i++ )
1171 0 : *pTemp++ = (sal_uInt8)0;
1172 0 : for ( i = 0; i < nWidth; i++ )
1173 0 : pPix[ ( i >> 1 ) ] |= (pAcc->GetPixelIndex( ny, i ) & 15) << ((i & 1) << 2);
1174 0 : break;
1175 : case 8 :
1176 0 : for ( i = 0; i < nWidth; i++ )
1177 0 : pPix[ i ] = pAcc->GetPixelIndex( ny, i );
1178 0 : break;
1179 : }
1180 :
1181 0 : if ( nPackType == 1 )
1182 : { // don't pack
1183 0 : pPict->Write( pPix, nDstRowBytes );
1184 : }
1185 : else
1186 : { // Ppacking (nPackType==0)
1187 :
1188 : // remember start of the row in the target:
1189 0 : nDstRowPos = pPict->Tell();
1190 :
1191 : // ByteCount (this is the size of the packed line) initialized with 0 (will be corrected later):
1192 0 : if ( nDstRowBytes > 250 )
1193 0 : *pPict << (sal_uInt16)0;
1194 : else
1195 0 : *pPict << (sal_uInt8)0;
1196 :
1197 : // loop trough bytes of the row:
1198 0 : nx=0;
1199 0 : while ( nx < nDstRowBytes && bStatus )
1200 : {
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 0 : nEqu3 = nx;
1205 : for (;;)
1206 : {
1207 0 : if ( nEqu3 + 2 >= nDstRowBytes )
1208 : {
1209 0 : nEqu3 = nDstRowBytes;
1210 0 : break;
1211 : }
1212 0 : nEquData = pPix[ nEqu3 ];
1213 0 : if ( nEquData == pPix[ nEqu3 + 1 ] && nEquData == pPix[ nEqu3 + 2 ] )
1214 0 : break;
1215 0 : nEqu3++;
1216 : }
1217 :
1218 : // Write the data unpacked from nx to nEqu3 (in multiple records if necessary):
1219 0 : while ( nEqu3 > nx )
1220 : {
1221 0 : nCount = nEqu3 - nx;
1222 0 : if ( nCount > 128 )
1223 0 : nCount = 128;
1224 0 : nFlagCounterByte = (sal_uInt8)( nCount - 1 );
1225 0 : *pPict << nFlagCounterByte;
1226 0 : do
1227 : {
1228 0 : *pPict << pPix[ nx++ ];
1229 0 : nCount--;
1230 : } while ( nCount > 0 );
1231 : }
1232 :
1233 : // Now create a compression record (if at least 3 identical bytes were found above):
1234 0 : if ( nx < nDstRowBytes )
1235 : { // Note: it is imperative nx==nEqu3 (hopefully)
1236 0 : nCount = 3; // three bytes are identically, as identified above
1237 : // Check if more identical bytes exist. (in doing so, consider max record size):
1238 0 : while ( nx + nCount < nDstRowBytes && nCount < 128 )
1239 : {
1240 0 : if ( nEquData != pPix[ nx + nCount ] )
1241 0 : break;
1242 0 : nCount++;
1243 : }
1244 : // write nCount identical bytes unpacked:
1245 0 : nFlagCounterByte = (sal_uInt8)( 1 - (long)nCount );
1246 0 : *pPict << nFlagCounterByte << nEquData;
1247 0 : nx += nCount;
1248 : }
1249 : }
1250 :
1251 : // correct ByteCount:
1252 0 : nPos = pPict->Tell();
1253 0 : pPict->Seek( nDstRowPos );
1254 0 : if ( nDstRowBytes > 250 )
1255 0 : *pPict << ( (sal_uInt16)( nPos - nDstRowPos - 2 ) );
1256 : else
1257 0 : *pPict << ( (sal_uInt8)( nPos - nDstRowPos - 1 ) );
1258 0 : pPict->Seek( nPos );
1259 : }
1260 :
1261 : // count percentages, Callback, check errors:
1262 0 : nActBitmapPercent =( ny * 70 / nHeight ) + 30; // (30% already added up to the writing of the Win-BMP file)
1263 0 : MayCallback();
1264 0 : if ( pPict->GetError() )
1265 0 : bStatus = sal_False;
1266 : }
1267 : // cleaning up:
1268 0 : delete[] pPix;
1269 : }
1270 :
1271 : // Map-Data has to be an even number of bytes:
1272 0 : if ( ( ( pPict->Tell() - nDstMapPos ) & 1 ) != 0 )
1273 0 : *pPict << (sal_uInt8)0;
1274 :
1275 : // counting Bitmaps:
1276 0 : nWrittenBitmaps++;
1277 0 : nActBitmapPercent = 0;
1278 0 : if ( pAcc )
1279 0 : aBitmap.ReleaseAccess( pAcc );
1280 : }
1281 :
1282 0 : void PictWriter::WriteOpcode_EndOfFile()
1283 : {
1284 0 : *pPict << (sal_uInt16)0x00ff;
1285 0 : }
1286 :
1287 :
1288 0 : void PictWriter::SetAttrForPaint()
1289 : {
1290 0 : WriteOpcode_PnMode(eSrcRasterOp);
1291 0 : WriteOpcode_RGBFgCol(aFillColor);
1292 0 : WriteOpcode_RGBBkCol(aFillColor);
1293 0 : WriteOpcode_PnFillPat(aFillColor!=Color( COL_TRANSPARENT ));
1294 0 : }
1295 :
1296 :
1297 0 : void PictWriter::SetAttrForFrame()
1298 : {
1299 0 : WriteOpcode_PnMode(eSrcRasterOp);
1300 0 : WriteOpcode_PnSize(0);
1301 0 : WriteOpcode_RGBFgCol(aLineColor);
1302 0 : WriteOpcode_PnLinePat(aLineColor!=Color( COL_TRANSPARENT ));
1303 0 : }
1304 :
1305 :
1306 0 : void PictWriter::SetAttrForText()
1307 : {
1308 0 : WriteOpcode_RGBFgCol(aSrcFont.GetColor());
1309 0 : WriteOpcode_RGBBkCol(aSrcFont.GetFillColor());
1310 0 : WriteOpcode_PnLinePat(sal_True);
1311 0 : WriteOpcode_FontName(aSrcFont);
1312 0 : WriteOpcode_TxSize((sal_uInt16)(aSrcFont.GetSize().Height()));
1313 0 : WriteOpcode_TxMode(eSrcRasterOp);
1314 0 : WriteOpcode_TxFace(aSrcFont);
1315 0 : }
1316 :
1317 :
1318 0 : void PictWriter::WriteTextArray(Point & rPoint, const String& rString, const sal_Int32 * pDXAry)
1319 : {
1320 : sal_uInt16 i,nLen;
1321 : sal_Unicode c;
1322 : sal_Bool bDelta;
1323 0 : Point aPt;
1324 :
1325 0 : if ( pDXAry == NULL )
1326 0 : WriteOpcode_Text( rPoint, rString, sal_False );
1327 : else
1328 : {
1329 0 : bDelta = sal_False;
1330 0 : nLen = rString.Len();
1331 0 : for ( i = 0; i < nLen; i++ )
1332 : {
1333 0 : c = rString.GetChar( i );
1334 0 : if ( c && ( c != 0x20 ) )
1335 : {
1336 0 : aPt = rPoint;
1337 0 : if ( i > 0 )
1338 0 : aPt.X() += pDXAry[ i - 1 ];
1339 :
1340 0 : WriteOpcode_Text( aPt, OUString( c ), bDelta );
1341 0 : bDelta = sal_True;
1342 : }
1343 : }
1344 : }
1345 0 : }
1346 :
1347 0 : void PictWriter::HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
1348 : {
1349 0 : if(rLinePolygon.count())
1350 : {
1351 0 : basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
1352 0 : basegfx::B2DPolyPolygon aFillPolyPolygon;
1353 :
1354 0 : rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
1355 :
1356 0 : if(aLinePolyPolygon.count())
1357 : {
1358 0 : aLinePolyPolygon = aLinePolyPolygon.getDefaultAdaptiveSubdivision();
1359 0 : const sal_uInt32 nPolyCount(aLinePolyPolygon.count());
1360 0 : SetAttrForFrame();
1361 :
1362 0 : for(sal_uInt32 a(0); a < nPolyCount; a++)
1363 : {
1364 0 : const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
1365 0 : const sal_uInt32 nPointCount(aCandidate.count());
1366 :
1367 0 : if(nPointCount)
1368 : {
1369 0 : const sal_uInt32 nEdgeCount(aCandidate.isClosed() ? nPointCount + 1 : nPointCount);
1370 0 : const basegfx::B2DPoint aCurr(aCandidate.getB2DPoint(0));
1371 0 : Point nCurr(basegfx::fround(aCurr.getX()), basegfx::fround(aCurr.getY()));
1372 :
1373 0 : for(sal_uInt32 b(0); b < nEdgeCount; b++)
1374 : {
1375 0 : const sal_uInt32 nNextIndex((b + 1) % nPointCount);
1376 0 : const basegfx::B2DPoint aNext(aCandidate.getB2DPoint(nNextIndex));
1377 0 : const Point nNext(basegfx::fround(aNext.getX()), basegfx::fround(aNext.getY()));
1378 :
1379 0 : WriteOpcode_Line(nCurr, nNext);
1380 0 : nCurr = nNext;
1381 0 : }
1382 : }
1383 0 : }
1384 : }
1385 :
1386 0 : if(aFillPolyPolygon.count())
1387 : {
1388 0 : const Color aOldLineColor(aLineColor);
1389 0 : const Color aOldFillColor(aFillColor);
1390 :
1391 0 : aLineColor = Color( COL_TRANSPARENT );
1392 0 : aFillColor = aOldLineColor;
1393 0 : SetAttrForPaint();
1394 :
1395 0 : for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
1396 : {
1397 0 : const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a).getDefaultAdaptiveSubdivision());
1398 0 : WriteOpcode_Poly(PDM_PAINT, aPolygon);
1399 0 : }
1400 :
1401 0 : aLineColor = aOldLineColor;
1402 0 : aFillColor = aOldFillColor;
1403 0 : }
1404 : }
1405 0 : }
1406 :
1407 0 : void PictWriter::WriteOpcodes( const GDIMetaFile & rMTF )
1408 : {
1409 : size_t nA, nACount;
1410 : const MetaAction* pMA;
1411 :
1412 0 : if( !bStatus)
1413 0 : return;
1414 :
1415 0 : nACount = rMTF.GetActionSize();
1416 :
1417 0 : for (nA=0; nA < nACount; nA++)
1418 : {
1419 0 : pMA = rMTF.GetAction(nA);
1420 :
1421 0 : switch (pMA->GetType())
1422 : {
1423 : case META_PIXEL_ACTION:
1424 : {
1425 0 : const MetaPixelAction* pA = (const MetaPixelAction*) pMA;
1426 0 : WriteOpcode_PnMode(eSrcRasterOp);
1427 0 : WriteOpcode_PnSize(1);
1428 0 : WriteOpcode_RGBFgCol(pA->GetColor());
1429 0 : WriteOpcode_PnLinePat(sal_True);
1430 0 : WriteOpcode_Line(pA->GetPoint(),pA->GetPoint());
1431 : }
1432 0 : break;
1433 :
1434 : case META_POINT_ACTION:
1435 : {
1436 0 : const MetaPointAction* pA = (const MetaPointAction*) pMA;
1437 :
1438 0 : if( aLineColor != Color( COL_TRANSPARENT ) )
1439 : {
1440 0 : SetAttrForFrame();
1441 0 : WriteOpcode_Line( pA->GetPoint(),pA->GetPoint() );
1442 : }
1443 : }
1444 0 : break;
1445 :
1446 : case META_LINE_ACTION:
1447 : {
1448 0 : const MetaLineAction* pA = (const MetaLineAction*) pMA;
1449 :
1450 0 : if( aLineColor != Color( COL_TRANSPARENT ) )
1451 : {
1452 0 : if(pA->GetLineInfo().IsDefault())
1453 : {
1454 0 : SetAttrForFrame();
1455 0 : WriteOpcode_Line( pA->GetStartPoint(),pA->GetEndPoint() );
1456 : }
1457 : else
1458 : {
1459 : // LineInfo used; handle Dash/Dot and fat lines
1460 0 : basegfx::B2DPolygon aPolygon;
1461 0 : aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
1462 0 : aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
1463 0 : HandleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
1464 : }
1465 : }
1466 0 : break;
1467 : }
1468 :
1469 : case META_RECT_ACTION:
1470 : {
1471 0 : const MetaRectAction* pA = (const MetaRectAction*) pMA;
1472 :
1473 0 : if (aFillColor!=Color( COL_TRANSPARENT ))
1474 : {
1475 0 : SetAttrForPaint();
1476 0 : WriteOpcode_Rect(PDM_PAINT,pA->GetRect());
1477 0 : if (aLineColor!=Color( COL_TRANSPARENT ))
1478 : {
1479 0 : SetAttrForFrame();
1480 0 : WriteOpcode_SameRect(PDM_FRAME);
1481 : }
1482 : }
1483 0 : else if (aLineColor!=Color( COL_TRANSPARENT ))
1484 : {
1485 0 : SetAttrForFrame();
1486 0 : WriteOpcode_Rect(PDM_FRAME,pA->GetRect());
1487 : }
1488 : }
1489 0 : break;
1490 :
1491 : case META_ROUNDRECT_ACTION:
1492 : {
1493 0 : const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pMA;
1494 :
1495 0 : WriteOpcode_OvSize( Size( pA->GetHorzRound(), pA->GetVertRound() ) );
1496 :
1497 0 : if (aFillColor!=Color( COL_TRANSPARENT ))
1498 : {
1499 0 : SetAttrForPaint();
1500 0 : WriteOpcode_RRect(PDM_PAINT,pA->GetRect());
1501 0 : if (aLineColor!=Color( COL_TRANSPARENT ))
1502 : {
1503 0 : SetAttrForFrame();
1504 0 : WriteOpcode_SameRRect(PDM_FRAME);
1505 : }
1506 : }
1507 0 : else if (aLineColor!=Color( COL_TRANSPARENT ))
1508 : {
1509 0 : SetAttrForFrame();
1510 0 : WriteOpcode_RRect(PDM_FRAME,pA->GetRect());
1511 : }
1512 : }
1513 0 : break;
1514 :
1515 : case META_ELLIPSE_ACTION:
1516 : {
1517 0 : const MetaEllipseAction* pA = (const MetaEllipseAction*) pMA;
1518 :
1519 0 : if (aFillColor!=Color( COL_TRANSPARENT ))
1520 : {
1521 0 : SetAttrForPaint();
1522 0 : WriteOpcode_Oval(PDM_PAINT,pA->GetRect());
1523 0 : if (aLineColor!=Color( COL_TRANSPARENT ))
1524 : {
1525 0 : SetAttrForFrame();
1526 0 : WriteOpcode_SameOval(PDM_FRAME);
1527 : }
1528 : }
1529 0 : else if (aLineColor!=Color( COL_TRANSPARENT ))
1530 : {
1531 0 : SetAttrForFrame();
1532 0 : WriteOpcode_Oval(PDM_FRAME,pA->GetRect());
1533 : }
1534 : }
1535 0 : break;
1536 :
1537 : case META_ARC_ACTION:
1538 : {
1539 0 : const MetaArcAction* pA = (const MetaArcAction*) pMA;
1540 :
1541 0 : if (aLineColor!=Color( COL_TRANSPARENT ))
1542 : {
1543 0 : SetAttrForFrame();
1544 0 : WriteOpcode_Arc(PDM_FRAME,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint());
1545 : }
1546 : }
1547 0 : break;
1548 :
1549 : case META_PIE_ACTION:
1550 : {
1551 0 : const MetaPieAction* pA = (const MetaPieAction *) pMA;
1552 :
1553 0 : if (aFillColor!=Color( COL_TRANSPARENT ))
1554 : {
1555 0 : SetAttrForPaint();
1556 0 : WriteOpcode_Arc(PDM_PAINT,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint());
1557 :
1558 0 : if (aLineColor!=Color( COL_TRANSPARENT ))
1559 : {
1560 0 : SetAttrForFrame();
1561 0 : WriteOpcode_SameArc(PDM_FRAME,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint());
1562 : }
1563 : }
1564 0 : else if (aLineColor!=Color( COL_TRANSPARENT ))
1565 : {
1566 0 : SetAttrForFrame();
1567 0 : WriteOpcode_Arc(PDM_FRAME,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint());
1568 : }
1569 :
1570 0 : if (aLineColor!=Color( COL_TRANSPARENT ))
1571 : {
1572 : double fxc,fyc,fxr,fyr,fx1,fy1,fx2,fy2,l1,l2;
1573 :
1574 0 : fxc=((double)(pA->GetRect().Left()+pA->GetRect().Right()))/2.0;
1575 0 : fyc=((double)(pA->GetRect().Top()+pA->GetRect().Bottom()))/2.0;
1576 0 : fxr=((double)pA->GetRect().GetWidth())/2.0;
1577 0 : fyr=((double)pA->GetRect().GetHeight())/2.0;
1578 0 : fx1=((double)pA->GetStartPoint().X())-fxc;
1579 0 : fy1=((double)pA->GetStartPoint().Y())-fyc;
1580 0 : fx2=((double)pA->GetEndPoint().X())-fxc;
1581 0 : fy2=((double)pA->GetEndPoint().Y())-fyc;
1582 0 : l1=sqrt(fx1*fx1+fy1*fy1);
1583 0 : l2=sqrt(fx2*fx2+fy2*fy2);
1584 :
1585 0 : if (l1>0)
1586 : {
1587 0 : fx1=fx1/l1*fxr;
1588 0 : fy1=fy1/l1*fyr;
1589 : }
1590 :
1591 0 : if (l2>0)
1592 : {
1593 0 : fx2=fx2/l2*fxr;
1594 0 : fy2=fy2/l2*fyr;
1595 : }
1596 0 : fx1+=fxc; fy1+=fyc; fx2+=fxc; fy2+=fyc;
1597 0 : WriteOpcode_Line(Point((long)(fx1+0.5),(long)(fy1+0.5)), Point((long)(fxc+0.5),(long)(fyc+0.5)));
1598 0 : WriteOpcode_LineFrom(Point((long)(fx2+0.5),(long)(fy2+0.5)));
1599 : }
1600 : }
1601 0 : break;
1602 :
1603 : case META_CHORD_ACTION:
1604 : {
1605 : // OSL_FAIL( "Unsupported PICT-Action: META_CHORD_ACTION!" );
1606 : }
1607 0 : break;
1608 :
1609 : case META_POLYLINE_ACTION:
1610 : {
1611 0 : const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pMA;
1612 :
1613 0 : if( aLineColor!=Color( COL_TRANSPARENT ) )
1614 : {
1615 0 : const Polygon& rPoly = pA->GetPolygon();
1616 :
1617 0 : if( rPoly.GetSize() )
1618 : {
1619 0 : if(pA->GetLineInfo().IsDefault())
1620 : {
1621 0 : Polygon aSimplePoly;
1622 0 : if ( rPoly.HasFlags() )
1623 0 : rPoly.AdaptiveSubdivide( aSimplePoly );
1624 : else
1625 0 : aSimplePoly = rPoly;
1626 :
1627 0 : const sal_uInt16 nSize = aSimplePoly.GetSize();
1628 0 : Point aLast;
1629 :
1630 0 : if ( nSize )
1631 : {
1632 0 : SetAttrForFrame();
1633 0 : aLast = aSimplePoly[0];
1634 :
1635 0 : for ( sal_uInt16 i = 1; i < nSize; i++ )
1636 : {
1637 0 : WriteOpcode_Line( aLast, aSimplePoly[i] );
1638 0 : aLast = aSimplePoly[i];
1639 : }
1640 0 : }
1641 : }
1642 : else
1643 : {
1644 : // LineInfo used; handle Dash/Dot and fat lines
1645 0 : HandleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
1646 : }
1647 : }
1648 : }
1649 : }
1650 0 : break;
1651 :
1652 : case META_POLYGON_ACTION:
1653 : {
1654 0 : const MetaPolygonAction* pA = (const MetaPolygonAction*) pMA;
1655 :
1656 0 : const Polygon& rPoly = pA->GetPolygon();
1657 :
1658 0 : Polygon aSimplePoly;
1659 0 : if ( rPoly.HasFlags() )
1660 0 : rPoly.AdaptiveSubdivide( aSimplePoly );
1661 : else
1662 0 : aSimplePoly = rPoly;
1663 :
1664 0 : if (aFillColor!=Color( COL_TRANSPARENT ))
1665 : {
1666 0 : SetAttrForPaint();
1667 0 : WriteOpcode_Poly( PDM_PAINT, aSimplePoly );
1668 : }
1669 0 : if (aLineColor!=Color( COL_TRANSPARENT ))
1670 : {
1671 0 : SetAttrForFrame();
1672 0 : WriteOpcode_Poly( PDM_FRAME, aSimplePoly );
1673 0 : }
1674 : }
1675 0 : break;
1676 :
1677 : case META_POLYPOLYGON_ACTION:
1678 : {
1679 0 : const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pMA;
1680 :
1681 0 : const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
1682 0 : sal_uInt16 nPolyCount = rPolyPoly.Count();
1683 0 : PolyPolygon aSimplePolyPoly( rPolyPoly );
1684 0 : for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
1685 : {
1686 0 : if ( aSimplePolyPoly[ i ].HasFlags() )
1687 : {
1688 0 : Polygon aSimplePoly;
1689 0 : aSimplePolyPoly[ i ].AdaptiveSubdivide( aSimplePoly );
1690 0 : aSimplePolyPoly[ i ] = aSimplePoly;
1691 : }
1692 : }
1693 0 : if (aFillColor!=Color( COL_TRANSPARENT ))
1694 : {
1695 0 : SetAttrForPaint();
1696 0 : WriteOpcode_Poly( PDM_PAINT, PolyPolygonToPolygon( aSimplePolyPoly ));
1697 : }
1698 :
1699 0 : if (aLineColor!=Color( COL_TRANSPARENT ))
1700 : {
1701 : sal_uInt16 nCount,i;
1702 0 : SetAttrForFrame();
1703 0 : nCount = aSimplePolyPoly.Count();
1704 0 : for ( i = 0; i < nCount; i++ )
1705 0 : WriteOpcode_Poly( PDM_FRAME, aSimplePolyPoly.GetObject( i ) );
1706 0 : }
1707 : }
1708 0 : break;
1709 :
1710 : case META_TEXT_ACTION:
1711 : {
1712 0 : const MetaTextAction* pA = (const MetaTextAction*) pMA;
1713 0 : Point aPt( pA->GetPoint() );
1714 :
1715 0 : if ( aSrcFont.GetAlign() != ALIGN_BASELINE )
1716 : {
1717 0 : VirtualDevice aVirDev;
1718 :
1719 0 : if (aSrcFont.GetAlign()==ALIGN_TOP)
1720 0 : aPt.Y()+=(long)aVirDev.GetFontMetric(aSrcFont).GetAscent();
1721 : else
1722 0 : aPt.Y()-=(long)aVirDev.GetFontMetric(aSrcFont).GetDescent();
1723 : }
1724 :
1725 0 : SetAttrForText();
1726 0 : String aStr( pA->GetText(),pA->GetIndex(),pA->GetLen() );
1727 0 : WriteOpcode_Text( aPt, aStr, sal_False );
1728 : }
1729 0 : break;
1730 :
1731 : case META_TEXTARRAY_ACTION:
1732 : {
1733 0 : const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pMA;
1734 0 : Point aPt( pA->GetPoint() );
1735 :
1736 0 : if (aSrcFont.GetAlign()!=ALIGN_BASELINE)
1737 : {
1738 0 : VirtualDevice aVirDev;
1739 :
1740 0 : if (aSrcFont.GetAlign()==ALIGN_TOP)
1741 0 : aPt.Y()+=(long)aVirDev.GetFontMetric(aSrcFont).GetAscent();
1742 : else
1743 0 : aPt.Y()-=(long)aVirDev.GetFontMetric(aSrcFont).GetDescent();
1744 : }
1745 0 : SetAttrForText();
1746 0 : String aStr( pA->GetText(),pA->GetIndex(),pA->GetLen() );
1747 0 : WriteTextArray( aPt, aStr, pA->GetDXArray() );
1748 0 : break;
1749 : }
1750 :
1751 : case META_STRETCHTEXT_ACTION:
1752 : {
1753 0 : const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pMA;
1754 0 : Point aPt( pA->GetPoint() );
1755 0 : String aStr( pA->GetText(),pA->GetIndex(),pA->GetLen() );
1756 0 : VirtualDevice aVirDev;
1757 0 : sal_Int32* pDXAry = new sal_Int32[ aStr.Len() ];
1758 0 : sal_Int32 nNormSize( aVirDev.GetTextArray( aStr,pDXAry ) );
1759 : sal_uInt16 i;
1760 :
1761 0 : if (aSrcFont.GetAlign()!=ALIGN_BASELINE)
1762 : {
1763 0 : if (aSrcFont.GetAlign()==ALIGN_TOP)
1764 0 : aPt.Y()+=(long)aVirDev.GetFontMetric(aSrcFont).GetAscent();
1765 : else
1766 0 : aPt.Y()-=(long)aVirDev.GetFontMetric(aSrcFont).GetDescent();
1767 : }
1768 :
1769 0 : for ( i = 0; i < aStr.Len() - 1; i++ )
1770 0 : pDXAry[ i ] = pDXAry[ i ] * ( (long)pA->GetWidth() ) / nNormSize;
1771 :
1772 0 : SetAttrForText();
1773 0 : WriteTextArray( aPt, aStr, pDXAry );
1774 0 : delete[] pDXAry;
1775 : }
1776 0 : break;
1777 :
1778 : case META_TEXTRECT_ACTION:
1779 : {
1780 : // OSL_FAIL( "Unsupported PICT-Action: META_TEXTRECT_ACTION!" );
1781 : }
1782 0 : break;
1783 :
1784 : case META_BMP_ACTION:
1785 : {
1786 0 : const MetaBmpAction* pA = (const MetaBmpAction*) pMA;
1787 0 : const Bitmap aBmp( pA->GetBitmap() );
1788 0 : VirtualDevice aVirDev;
1789 :
1790 0 : WriteOpcode_BitsRect( pA->GetPoint(), aVirDev.PixelToLogic( aBmp.GetSizePixel(), aSrcMapMode ), aBmp );
1791 : }
1792 0 : break;
1793 :
1794 : case META_BMPSCALE_ACTION:
1795 : {
1796 0 : const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pMA;
1797 0 : WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), pA->GetBitmap() );
1798 : }
1799 0 : break;
1800 :
1801 : case META_BMPSCALEPART_ACTION:
1802 : {
1803 0 : const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pMA;
1804 0 : Bitmap aBmp( pA->GetBitmap() );
1805 :
1806 0 : aBmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1807 0 : WriteOpcode_BitsRect( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
1808 : }
1809 0 : break;
1810 :
1811 : case META_BMPEX_ACTION:
1812 : {
1813 0 : const MetaBmpExAction* pA = (const MetaBmpExAction*) pMA;
1814 0 : const Bitmap aBmp( Graphic( pA->GetBitmapEx() ).GetBitmap() );
1815 0 : VirtualDevice aVirDev;
1816 :
1817 0 : WriteOpcode_BitsRect( pA->GetPoint(), aVirDev.PixelToLogic( aBmp.GetSizePixel(), aSrcMapMode ), aBmp );
1818 : }
1819 0 : break;
1820 :
1821 : case META_BMPEXSCALE_ACTION:
1822 : {
1823 0 : const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pMA;
1824 0 : const Bitmap aBmp( Graphic( pA->GetBitmapEx() ).GetBitmap() );
1825 :
1826 0 : WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), aBmp );
1827 : }
1828 0 : break;
1829 :
1830 : case META_BMPEXSCALEPART_ACTION:
1831 : {
1832 0 : const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pMA;
1833 0 : Bitmap aBmp( Graphic( pA->GetBitmapEx() ).GetBitmap() );
1834 :
1835 0 : aBmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1836 0 : WriteOpcode_BitsRect( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
1837 : }
1838 0 : break;
1839 :
1840 : case META_EPS_ACTION :
1841 : {
1842 0 : const MetaEPSAction* pA = (const MetaEPSAction*)pMA;
1843 0 : const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
1844 :
1845 0 : size_t nCount = aGDIMetaFile.GetActionSize();
1846 0 : for ( size_t i = 0; i < nCount; i++ )
1847 : {
1848 0 : const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
1849 0 : if ( pMetaAct->GetType() == META_BMPSCALE_ACTION )
1850 : {
1851 0 : const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*)pMetaAct;
1852 0 : WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap() );
1853 0 : break;
1854 : }
1855 0 : }
1856 : }
1857 0 : break;
1858 :
1859 : case META_MASK_ACTION:
1860 : case META_MASKSCALE_ACTION:
1861 : case META_MASKSCALEPART_ACTION:
1862 : {
1863 : // OSL_FAIL( "Unsupported PICT-Action: META_MASK..._ACTION!" );
1864 : }
1865 0 : break;
1866 :
1867 : case META_GRADIENT_ACTION:
1868 : {
1869 0 : VirtualDevice aVDev;
1870 0 : GDIMetaFile aTmpMtf;
1871 0 : const MetaGradientAction* pA = (const MetaGradientAction*) pMA;
1872 :
1873 0 : aVDev.SetMapMode( aTargetMapMode );
1874 0 : aVDev.AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
1875 0 : WriteOpcodes( aTmpMtf );
1876 : }
1877 0 : break;
1878 :
1879 : case META_HATCH_ACTION:
1880 : {
1881 0 : VirtualDevice aVDev;
1882 0 : GDIMetaFile aTmpMtf;
1883 0 : const MetaHatchAction* pA = (const MetaHatchAction*) pMA;
1884 :
1885 0 : aVDev.SetMapMode( aTargetMapMode );
1886 0 : aVDev.AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
1887 0 : WriteOpcodes( aTmpMtf );
1888 : }
1889 0 : break;
1890 :
1891 : case META_WALLPAPER_ACTION:
1892 : {
1893 : // OSL_FAIL( "Unsupported PICT-Action: META_WALLPAPER_ACTION!" );
1894 : }
1895 0 : break;
1896 :
1897 : case META_CLIPREGION_ACTION:
1898 : {
1899 : // OSL_FAIL( "Unsupported PICT-Action: META_CLIPREGION_ACTION!" );
1900 : }
1901 0 : break;
1902 :
1903 : case META_ISECTRECTCLIPREGION_ACTION:
1904 : {
1905 0 : const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pMA;
1906 0 : WriteOpcode_ClipRect( pA->GetRect() );
1907 : }
1908 0 : break;
1909 :
1910 : case META_ISECTREGIONCLIPREGION_ACTION:
1911 : {
1912 : // OSL_FAIL( "Unsupported PICT-Action: META_ISECTREGIONCLIPREGION_ACTION!" );
1913 : }
1914 0 : break;
1915 :
1916 : case META_MOVECLIPREGION_ACTION:
1917 : {
1918 : // OSL_FAIL( "Unsupported PICT-Action: META_MOVECLIPREGION_ACTION!" );
1919 : }
1920 0 : break;
1921 :
1922 : case META_LINECOLOR_ACTION:
1923 : {
1924 0 : const MetaLineColorAction* pA = (const MetaLineColorAction*) pMA;
1925 :
1926 0 : if( pA->IsSetting() )
1927 0 : aLineColor = pA->GetColor();
1928 : else
1929 0 : aLineColor = Color( COL_TRANSPARENT );
1930 : }
1931 0 : break;
1932 :
1933 : case META_FILLCOLOR_ACTION:
1934 : {
1935 0 : const MetaFillColorAction* pA = (const MetaFillColorAction*) pMA;
1936 :
1937 0 : if( pA->IsSetting() )
1938 0 : aFillColor = pA->GetColor();
1939 : else
1940 0 : aFillColor = Color( COL_TRANSPARENT );
1941 : }
1942 0 : break;
1943 :
1944 : case META_TEXTCOLOR_ACTION:
1945 : {
1946 0 : const MetaTextColorAction* pA = (const MetaTextColorAction*) pMA;
1947 0 : aSrcFont.SetColor( pA->GetColor() );
1948 : }
1949 0 : break;
1950 :
1951 : case META_TEXTFILLCOLOR_ACTION:
1952 : {
1953 0 : const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pMA;
1954 :
1955 0 : if( pA->IsSetting() )
1956 0 : aSrcFont.SetFillColor( pA->GetColor() );
1957 : else
1958 0 : aSrcFont.SetFillColor( Color( COL_TRANSPARENT ) );
1959 : }
1960 0 : break;
1961 :
1962 : case META_TEXTALIGN_ACTION:
1963 : {
1964 : // OSL_FAIL( "Unsupported PICT-Action: META_TEXTALIGN_ACTION!" );
1965 : }
1966 0 : break;
1967 :
1968 : case META_MAPMODE_ACTION:
1969 : {
1970 0 : const MetaMapModeAction* pA = (const MetaMapModeAction*) pMA;
1971 :
1972 0 : if (aSrcMapMode!=pA->GetMapMode())
1973 : {
1974 0 : if( pA->GetMapMode().GetMapUnit() == MAP_RELATIVE )
1975 : {
1976 0 : MapMode aMM = pA->GetMapMode();
1977 0 : Fraction aScaleX = aMM.GetScaleX();
1978 0 : Fraction aScaleY = aMM.GetScaleY();
1979 :
1980 0 : Point aOrigin = aSrcMapMode.GetOrigin();
1981 0 : BigInt aX( aOrigin.X() );
1982 0 : aX *= BigInt( aScaleX.GetDenominator() );
1983 0 : if( aOrigin.X() >= 0 )
1984 : {
1985 0 : if( aScaleX.GetNumerator() >= 0 )
1986 0 : aX += BigInt( aScaleX.GetNumerator()/2 );
1987 : else
1988 0 : aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
1989 : }
1990 : else
1991 : {
1992 0 : if( aScaleX.GetNumerator() >= 0 )
1993 0 : aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
1994 : else
1995 0 : aX += BigInt( aScaleX.GetNumerator()/2 );
1996 : }
1997 :
1998 0 : aX /= BigInt( aScaleX.GetNumerator() );
1999 0 : aOrigin.X() = (long)aX + aMM.GetOrigin().X();
2000 0 : BigInt aY( aOrigin.Y() );
2001 0 : aY *= BigInt( aScaleY.GetDenominator() );
2002 :
2003 0 : if( aOrigin.Y() >= 0 )
2004 : {
2005 0 : if( aScaleY.GetNumerator() >= 0 )
2006 0 : aY += BigInt( aScaleY.GetNumerator()/2 );
2007 : else
2008 0 : aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
2009 : }
2010 : else
2011 : {
2012 0 : if( aScaleY.GetNumerator() >= 0 )
2013 0 : aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
2014 : else
2015 0 : aY += BigInt( aScaleY.GetNumerator()/2 );
2016 : }
2017 :
2018 0 : aY /= BigInt( aScaleY.GetNumerator() );
2019 0 : aOrigin.Y() = (long)aY + aMM.GetOrigin().Y();
2020 0 : aSrcMapMode.SetOrigin( aOrigin );
2021 :
2022 0 : aScaleX *= aSrcMapMode.GetScaleX();
2023 0 : aScaleY *= aSrcMapMode.GetScaleY();
2024 0 : aSrcMapMode.SetScaleX( aScaleX );
2025 0 : aSrcMapMode.SetScaleY( aScaleY );
2026 : }
2027 : else
2028 0 : aSrcMapMode = pA->GetMapMode();
2029 : }
2030 : }
2031 0 : break;
2032 :
2033 : case META_FONT_ACTION:
2034 : {
2035 0 : const MetaFontAction* pA = (const MetaFontAction*) pMA;
2036 0 : aSrcFont=pA->GetFont();
2037 : }
2038 0 : break;
2039 :
2040 : case META_PUSH_ACTION:
2041 : {
2042 0 : PictWriterAttrStackMember * pAt = new PictWriterAttrStackMember;
2043 0 : pAt->aLineColor=aLineColor;
2044 0 : pAt->aFillColor=aFillColor;
2045 0 : pAt->eRasterOp=eSrcRasterOp;
2046 0 : pAt->aFont=aSrcFont;
2047 0 : pAt->aMapMode=aSrcMapMode;
2048 0 : pAt->aClipRect=aClipRect;
2049 0 : pAt->pSucc=pAttrStack;
2050 0 : pAttrStack=pAt;
2051 : }
2052 0 : break;
2053 :
2054 : case META_POP_ACTION:
2055 : {
2056 0 : PictWriterAttrStackMember* pAt=pAttrStack;
2057 :
2058 0 : if( pAt )
2059 : {
2060 0 : aLineColor=pAt->aLineColor;
2061 0 : aFillColor=pAt->aFillColor;
2062 0 : eSrcRasterOp=pAt->eRasterOp;
2063 0 : aSrcFont=pAt->aFont;
2064 0 : aSrcMapMode=pAt->aMapMode;
2065 0 : if ( pAt->aClipRect != aClipRect )
2066 : {
2067 0 : Rectangle aRect( pAt->aClipRect );
2068 0 : *pPict << (sal_uInt16)1 // opcode 1
2069 0 : << (sal_uInt16)10 // data size
2070 0 : << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left()
2071 0 : << (sal_Int16)aRect.Bottom() << (sal_Int16)aRect.Right();
2072 : }
2073 0 : aClipRect=pAt->aClipRect;
2074 0 : pAttrStack=pAt->pSucc;
2075 0 : delete pAt;
2076 : }
2077 : }
2078 0 : break;
2079 :
2080 : case META_RASTEROP_ACTION:
2081 : {
2082 0 : const MetaRasterOpAction* pA = (const MetaRasterOpAction*) pMA;
2083 0 : eSrcRasterOp=pA->GetRasterOp();
2084 : }
2085 0 : break;
2086 :
2087 : case META_TRANSPARENT_ACTION:
2088 : {
2089 0 : const PolyPolygon& rPolyPoly = ( (const MetaTransparentAction*) pMA )->GetPolyPolygon();
2090 :
2091 0 : if (aFillColor!=Color( COL_TRANSPARENT ))
2092 : {
2093 0 : SetAttrForPaint();
2094 0 : WriteOpcode_Poly( PDM_PAINT, PolyPolygonToPolygon( rPolyPoly ) );
2095 : }
2096 :
2097 0 : if (aLineColor!=Color( COL_TRANSPARENT ))
2098 : {
2099 0 : SetAttrForFrame();
2100 0 : for( sal_uInt16 i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
2101 0 : WriteOpcode_Poly( PDM_FRAME, rPolyPoly.GetObject( i ) );
2102 : }
2103 : }
2104 0 : break;
2105 :
2106 : case META_FLOATTRANSPARENT_ACTION:
2107 : {
2108 0 : const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pMA;
2109 :
2110 0 : GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
2111 0 : Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
2112 0 : const Size aSrcSize( aTmpMtf.GetPrefSize() );
2113 0 : const Point aDestPt( pA->GetPoint() );
2114 0 : const Size aDestSize( pA->GetSize() );
2115 0 : const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
2116 0 : const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
2117 : long nMoveX, nMoveY;
2118 :
2119 0 : if( fScaleX != 1.0 || fScaleY != 1.0 )
2120 : {
2121 0 : aTmpMtf.Scale( fScaleX, fScaleY );
2122 0 : aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
2123 : }
2124 :
2125 0 : nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
2126 :
2127 0 : if( nMoveX || nMoveY )
2128 0 : aTmpMtf.Move( nMoveX, nMoveY );
2129 :
2130 0 : WriteOpcodes( aTmpMtf );
2131 : }
2132 0 : break;
2133 : }
2134 :
2135 0 : nWrittenActions++;
2136 0 : MayCallback();
2137 :
2138 0 : if (pPict->GetError())
2139 0 : bStatus=sal_False;
2140 :
2141 0 : if (bStatus==sal_False)
2142 0 : break;
2143 : }
2144 : }
2145 :
2146 :
2147 0 : void PictWriter::WriteHeader(const GDIMetaFile & rMTF)
2148 : {
2149 : sal_uInt16 i;
2150 0 : Size aSize( rMTF.GetPrefSize() );
2151 0 : Point aPoint;
2152 0 : Rectangle aRect( aPoint, aSize );
2153 :
2154 : // 512 Bytes "trash" at the beginning:
2155 0 : for (i=0;i<128;i++) *pPict << (sal_uInt32)0;
2156 :
2157 : // Lo-16-Bits of the file size without the 512 bytes trash:
2158 0 : *pPict << (sal_uInt16)0; // gets corrected later on by UpdateHeader()
2159 :
2160 : // The Bounding-Rectangle (y1,x1,y2,x2 !):
2161 0 : WriteRectangle( aRect );
2162 :
2163 : // Version 2:
2164 0 : *pPict << (sal_uInt32)0x001102ff;
2165 :
2166 : // Extended-Version-2-Header:
2167 0 : *pPict << (sal_uInt16)0x0c00 // Opcode
2168 0 : << (sal_uInt16)0xfffe // Version (?)
2169 0 : << (sal_uInt16)0x0000 // Reserved
2170 0 : << (sal_uInt32) 0x00480000 // hRes
2171 0 : << (sal_uInt32) 0x00480000;
2172 0 : WriteRectangle( aRect );
2173 0 : *pPict << (sal_uInt32)0x00000000; // Reserved
2174 :
2175 : // many import filters demand the declaration
2176 : // of a clipping area at the beginning
2177 :
2178 0 : WriteOpcode_ClipRect( aRect );
2179 0 : }
2180 :
2181 :
2182 0 : void PictWriter::UpdateHeader()
2183 : {
2184 : sal_uLong nPos;
2185 :
2186 : // correct the Lo-16-Bits of the file size without the 512 bytes trash:
2187 0 : nPos=pPict->Tell();
2188 0 : pPict->Seek(512);
2189 0 : *pPict << (sal_uInt16)((nPos-512)&0x0000ffff);
2190 0 : pPict->Seek(nPos);
2191 0 : }
2192 :
2193 :
2194 0 : sal_Bool PictWriter::WritePict(const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem* pFilterConfigItem )
2195 : {
2196 : PictWriterAttrStackMember* pAt;
2197 0 : MapMode aMap72( MAP_INCH );
2198 0 : Fraction aDPIFrac( 1, 72 );
2199 :
2200 0 : bStatus=sal_True;
2201 0 : nLastPercent=0;
2202 :
2203 0 : if ( pFilterConfigItem )
2204 : {
2205 0 : xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
2206 0 : if ( xStatusIndicator.is() )
2207 : {
2208 0 : OUString aMsg;
2209 0 : xStatusIndicator->start( aMsg, 100 );
2210 : }
2211 : }
2212 :
2213 0 : pPict=&rTargetStream;
2214 0 : pPict->SetNumberFormatInt(NUMBERFORMAT_INT_BIGENDIAN);
2215 :
2216 0 : aLineColor=Color( COL_BLACK );
2217 0 : aFillColor=Color( COL_WHITE );
2218 0 : eSrcRasterOp=ROP_OVERPAINT;
2219 0 : aSrcFont=Font();
2220 0 : aSrcMapMode = rMTF.GetPrefMapMode();
2221 :
2222 0 : aMap72.SetScaleX( aDPIFrac );
2223 0 : aMap72.SetScaleY( aDPIFrac );
2224 0 : aTargetMapMode = aMap72;
2225 :
2226 0 : pAttrStack=NULL;
2227 :
2228 0 : bDstBkPatValid=sal_False;
2229 0 : bDstTxFaceValid=sal_False;
2230 0 : bDstTxModeValid=sal_False;
2231 0 : bDstPnSizeValid=sal_False;
2232 0 : bDstPnModeValid=sal_False;
2233 0 : bDstPnPatValid=sal_False;
2234 0 : bDstFillPatValid=sal_False;
2235 0 : bDstTxSizeValid=sal_False;
2236 0 : bDstFgColValid=sal_False;
2237 0 : bDstBkColValid=sal_False;
2238 0 : bDstPenPositionValid=sal_False;
2239 0 : bDstTextPositionValid=sal_False;
2240 0 : bDstFontNameValid=sal_False;
2241 :
2242 0 : nNumberOfActions=0;
2243 0 : nNumberOfBitmaps=0;
2244 0 : nWrittenActions=0;
2245 0 : nWrittenBitmaps=0;
2246 0 : nActBitmapPercent=0;
2247 :
2248 0 : CountActionsAndBitmaps(rMTF);
2249 :
2250 0 : WriteHeader(rMTF);
2251 0 : WriteOpcodes(rMTF);
2252 0 : WriteOpcode_EndOfFile();
2253 0 : UpdateHeader();
2254 :
2255 0 : while (pAttrStack!=NULL) {
2256 0 : pAt=pAttrStack;
2257 0 : pAttrStack=pAt->pSucc;
2258 0 : delete pAt;
2259 : }
2260 :
2261 0 : if ( xStatusIndicator.is() )
2262 0 : xStatusIndicator->end();
2263 :
2264 0 : return bStatus;
2265 : }
2266 :
2267 : //================== GraphicExport - the exported Function ================
2268 :
2269 : #if defined(DISABLE_DYNLOADING) || defined(LIBO_MERGELIBS)
2270 : #define GraphicExport eptGraphicExport
2271 : #endif
2272 :
2273 : extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL
2274 0 : GraphicExport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pFilterConfigItem, sal_Bool)
2275 : {
2276 0 : PictWriter aPictWriter;
2277 :
2278 : // #i119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
2279 0 : GDIMetaFile aScaledMtf( rGraphic.GetGDIMetaFile() );
2280 :
2281 0 : return aPictWriter.WritePict( aScaledMtf, rStream, pFilterConfigItem );
2282 0 : }
2283 :
2284 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|