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