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