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