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