1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <string.h>
21 #include <osl/thread.h>
22 #include <sal/log.hxx>
23 #include <vcl/BitmapTools.hxx>
24 #include <vcl/graph.hxx>
25 #include <vcl/gdimtf.hxx>
26 #include <tools/poly.hxx>
27 #include <tools/fract.hxx>
28 #include <tools/stream.hxx>
29 #include <vcl/virdev.hxx>
30 #include <math.h>
31 
32 #include "ipict.hxx"
33 #include "shape.hxx"
34 #include <memory>
35 
36 #include <vcl/FilterConfigItem.hxx>
37     // complete FilterConfigItem for GraphicImport under -fsanitize=function
38 
39 namespace PictReaderInternal {
40   //! utilitary class to store a pattern, ...
41   class Pattern {
42   public:
43     //! constructor
Pattern()44     Pattern() : penStyle(PEN_SOLID),
45                 brushStyle(BRUSH_SOLID),
46                 nBitCount(64),
47                 isColor(false),
48                 isRead(false)
49     {}
50 
51     //! reads black/white pattern from SvStream
52     sal_uLong read(SvStream &stream);
53     //! sets the color
setColor(Color col)54     void setColor(Color col) { isColor = true; color = col; }
55     /** returns a color which can be "used" to replace the pattern,
56      *     created from ForeColor and BackColor, ...
57      *
58      * note: maybe, we must also use some mode PatCopy, ... to define the color
59      */
getColor(Color bkColor,Color fgColor) const60     Color getColor(Color bkColor, Color fgColor) const {
61       if (isColor) return color;
62       // we create a gray pattern from nBitCount
63       double alpha = nBitCount / 64.0;
64       return Color(sal_uInt8(alpha*fgColor.GetRed()+(1.0-alpha)*bkColor.GetRed()),
65            sal_uInt8(alpha*fgColor.GetGreen()+(1.0-alpha)*bkColor.GetGreen()),
66            sal_uInt8(alpha*fgColor.GetBlue()+(1.0-alpha)*bkColor.GetBlue()));
67     }
68 
69     //! returns true if this is the default pattern
isDefault() const70     bool isDefault() const { return !isRead; }
71 
72     enum PenStyle { PEN_NULL, PEN_SOLID, PEN_DOT, PEN_DASH, PEN_DASHDOT };
73     enum BrushStyle { BRUSH_SOLID, BRUSH_HORZ, BRUSH_VERT,
74               BRUSH_CROSS, BRUSH_DIAGCROSS, BRUSH_UPDIAG, BRUSH_DOWNDIAG,
75               BRUSH_25, BRUSH_50, BRUSH_75 };
76     // Data
77     enum PenStyle penStyle;
78     enum BrushStyle brushStyle;
79     short nBitCount;
80 
81     bool isColor; // true if it is a color pattern
82     Color color;
83 
84   protected:
85     // flag to know if the pattern came from reading the picture, or if it is the default pattern
86     bool isRead;
87   };
88 
read(SvStream & stream)89   sal_uLong Pattern::read(SvStream &stream) {
90     unsigned char nbyte[8];
91     sal_uLong nHiBytes, nLoBytes;
92     isColor = false;
93 
94     // count the no of bits in pattern which are set to 1:
95     nBitCount=0;
96     for (unsigned char & ny : nbyte) {
97       stream.ReadChar( reinterpret_cast<char&>(ny) );
98       for (short nx=0; nx<8; nx++) {
99     if ( (ny & (1<<nx)) != 0 ) nBitCount++;
100       }
101     }
102 
103     // store pattern in 2 long words:
104     nHiBytes=(((((static_cast<sal_uLong>(nbyte[0])<<8)|
105          static_cast<sal_uLong>(nbyte[1]))<<8)|
106            static_cast<sal_uLong>(nbyte[2]))<<8)|
107       static_cast<sal_uLong>(nbyte[3]);
108     nLoBytes=(((((static_cast<sal_uLong>(nbyte[4])<<8)|
109          static_cast<sal_uLong>(nbyte[5]))<<8)|
110            static_cast<sal_uLong>(nbyte[6]))<<8)|
111       static_cast<sal_uLong>(nbyte[7]);
112 
113     // create a PenStyle:
114     if      (nBitCount<=0)  penStyle=PEN_NULL;
115     else if (nBitCount<=16) penStyle=PEN_DOT;
116     else if (nBitCount<=32) penStyle=PEN_DASHDOT;
117     else if (nBitCount<=48) penStyle=PEN_DASH;
118     else                    penStyle=PEN_SOLID;
119 
120     // create a BrushStyle:
121     if      (nHiBytes==0xffffffff && nLoBytes==0xffffffff) brushStyle=BRUSH_SOLID;
122     else if (nHiBytes==0xff000000 && nLoBytes==0x00000000) brushStyle=BRUSH_HORZ;
123     else if (nHiBytes==0x80808080 && nLoBytes==0x80808080) brushStyle=BRUSH_VERT;
124     else if (nHiBytes==0xff808080 && nLoBytes==0x80808080) brushStyle=BRUSH_CROSS;
125     else if (nHiBytes==0x01824428 && nLoBytes==0x10284482) brushStyle=BRUSH_DIAGCROSS;
126     else if (nHiBytes==0x80402010 && nLoBytes==0x08040201) brushStyle=BRUSH_UPDIAG;
127     else if (nHiBytes==0x01020408 && nLoBytes==0x10204080) brushStyle=BRUSH_DOWNDIAG;
128     else if (nBitCount<=24) brushStyle=BRUSH_25;
129     else if (nBitCount<=40) brushStyle=BRUSH_50;
130     else if (nBitCount<=56) brushStyle=BRUSH_75;
131     else                    brushStyle=BRUSH_SOLID;
132 
133     isRead = true;
134 
135     return 8;
136   }
137 }
138 
139 //============================ PictReader ==================================
140 
141 enum class PictDrawingMethod {
142     FRAME, PAINT, ERASE, INVERT, FILL,
143     TEXT, UNDEFINED
144 };
145 
146 class PictReader {
147   typedef class PictReaderInternal::Pattern Pattern;
148 private:
149 
150     SvStream    * pPict;             // The Pict file to read.
151     VclPtr<VirtualDevice> pVirDev;   // Here the drawing method will be called.
152                                      // A recording into the GDIMetaFile will take place.
153 
154     sal_uLong     nOrigPos;          // Initial position in pPict.
155     bool          IsVersion2;        // If it is a version 2 Pictfile.
156     tools::Rectangle     aBoundingRect;     // Min/Max-Rectangle for the whole drawing.
157 
158     Point         aPenPosition;
159     Point         aTextPosition;
160     Color         aActForeColor;
161     Color         aActBackColor;
162     Pattern       eActPenPattern;
163     Pattern       eActFillPattern;
164     Pattern       eActBackPattern;
165     Size          nActPenSize;
166  // Note: Postscript mode is stored by setting eActRop to RasterOp::N1
167     RasterOp      eActROP;
168     PictDrawingMethod eActMethod;
169     Size          aActOvalSize;
170     vcl::Font     aActFont;
171 
172     Fraction        aHRes;
173     Fraction        aVRes;
174 
175     Point ReadPoint();
176 
177     Point ReadDeltaH(Point aBase);
178     Point ReadDeltaV(Point aBase);
179 
180     Point ReadUnsignedDeltaH(Point aBase);
181     Point ReadUnsignedDeltaV(Point aBase);
182 
183     Size ReadSize();
184 
185     Color ReadColor();
186 
187     Color ReadRGBColor();
188 
189     void ReadRectangle(tools::Rectangle & rRect);
190 
191     sal_uLong ReadPolygon(tools::Polygon & rPoly);
192 
193     sal_uLong ReadPixPattern(Pattern &pattern);
194 
195     tools::Rectangle aLastRect;
196     sal_uLong ReadAndDrawRect(PictDrawingMethod eMethod);
197     sal_uLong ReadAndDrawSameRect(PictDrawingMethod eMethod);
198 
199     tools::Rectangle aLastRoundRect;
200     sal_uLong ReadAndDrawRoundRect(PictDrawingMethod eMethod);
201     sal_uLong ReadAndDrawSameRoundRect(PictDrawingMethod eMethod);
202 
203     tools::Rectangle aLastOval;
204     sal_uLong ReadAndDrawOval(PictDrawingMethod eMethod);
205     sal_uLong ReadAndDrawSameOval(PictDrawingMethod eMethod);
206 
207     tools::Polygon aLastPolygon;
208     sal_uLong ReadAndDrawPolygon(PictDrawingMethod eMethod);
209     sal_uLong ReadAndDrawSamePolygon(PictDrawingMethod eMethod);
210 
211     tools::Rectangle aLastArcRect;
212     sal_uLong ReadAndDrawArc(PictDrawingMethod eMethod);
213     sal_uLong ReadAndDrawSameArc(PictDrawingMethod eMethod);
214 
215     sal_uLong ReadAndDrawRgn(PictDrawingMethod eMethod);
216     sal_uLong ReadAndDrawSameRgn(PictDrawingMethod eMethod);
217 
218     // returns true if there's no need to print the shape/text/frame
IsInvisible(PictDrawingMethod eMethod) const219     bool IsInvisible( PictDrawingMethod eMethod ) const {
220       if ( eActROP == RasterOp::N1 ) return true;
221       if ( eMethod == PictDrawingMethod::FRAME && ( nActPenSize.Width() == 0 || nActPenSize.Height() == 0 ) ) return true;
222       return false;
223     }
224 
225     void DrawingMethod(PictDrawingMethod eMethod);
226 
227     sal_uLong ReadAndDrawText();
228 
229     sal_uLong ReadPixMapEtc(BitmapEx & rBitmap, bool bBaseAddr, bool bColorTable,
230                         tools::Rectangle * pSrcRect, tools::Rectangle * pDestRect,
231                         bool bMode, bool bMaskRgn);
232 
233     void ReadHeader();
234         // Reads the header of the Pict file, set IsVersion and aBoundingRect
235 
236     sal_uLong ReadData(sal_uInt16 nOpcode);
237         // Reads the date of anOopcode and executes the operation.
238         // The number of data bytes belonging to the opcode will be returned
239         // in any case.
240 
241     void SetLineColor( const Color& rColor );
242     void SetFillColor( const Color& rColor );
243 
244     // OSNOLA: returns the text encoding which must be used for system id
245     static rtl_TextEncoding GetTextEncoding (sal_uInt16 fId = 0xFFFF);
246 
247 public:
248 
PictReader()249     PictReader()
250         : pPict(nullptr)
251         , pVirDev(nullptr)
252         , nOrigPos(0)
253         , IsVersion2(false)
254         , eActROP(RasterOp::OverPaint)
255         , eActMethod(PictDrawingMethod::UNDEFINED)
256     {
257         aActFont.SetCharSet(GetTextEncoding());
258     }
259 
260     void ReadPict( SvStream & rStreamPict, GDIMetaFile & rGDIMetaFile );
261         // reads a pict file from the stream and fills the GDIMetaFile
262 
263 };
264 
SetByte(sal_uInt16 & nx,sal_uInt16 ny,vcl::bitmap::RawBitmap & rBitmap,sal_uInt16 nPixelSize,sal_uInt8 nDat,sal_uInt16 nWidth,std::vector<Color> const & rvPalette)265 static void SetByte(sal_uInt16& nx, sal_uInt16 ny, vcl::bitmap::RawBitmap& rBitmap, sal_uInt16 nPixelSize, sal_uInt8 nDat, sal_uInt16 nWidth, std::vector<Color> const & rvPalette)
266 {
267     switch (nPixelSize)
268     {
269         case 1:
270             rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 7) & 1]);
271             if ( nx == nWidth ) break;
272             rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 6) & 1]);
273             if ( nx == nWidth ) break;
274             rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 5) & 1]);
275             if ( nx == nWidth ) break;
276             rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 4) & 1]);
277             if ( nx == nWidth ) break;
278             rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 3) & 1]);
279             if ( nx == nWidth ) break;
280             rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 2) & 1]);
281             if ( nx == nWidth ) break;
282             rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 1) & 1]);
283             if ( nx == nWidth ) break;
284             rBitmap.SetPixel(ny, nx++, rvPalette[nDat & 1]);
285             break;
286         case 2:
287             rBitmap.SetPixel(ny, nx++, rvPalette[nDat >> 6]);
288             if ( nx == nWidth ) break;
289             rBitmap.SetPixel(ny, nx++, rvPalette[(nDat>>4)&3]);
290             if ( nx == nWidth ) break;
291             rBitmap.SetPixel(ny, nx++, rvPalette[(nDat>>2)&3]);
292             if ( nx == nWidth ) break;
293             rBitmap.SetPixel(ny, nx++, rvPalette[nDat & 3]);
294             break;
295         case 4:
296             rBitmap.SetPixel(ny, nx++, rvPalette[nDat >> 4]);
297             if ( nx == nWidth ) break;
298             rBitmap.SetPixel(ny, nx++, rvPalette[nDat & 0x0f]);
299             break;
300         case 8:
301             rBitmap.SetPixel(ny, nx++, rvPalette[nDat]);
302             break;
303     }
304 }
305 
306 //=================== methods of PictReader ==============================
GetTextEncoding(sal_uInt16 fId)307 rtl_TextEncoding PictReader::GetTextEncoding (sal_uInt16 fId) {
308   static rtl_TextEncoding enc = [&]()
309   {
310     rtl_TextEncoding def = osl_getThreadTextEncoding();
311     // we keep osl_getThreadTextEncoding only if it is a mac encoding
312     switch(def) {
313     case RTL_TEXTENCODING_APPLE_ROMAN:
314     case RTL_TEXTENCODING_APPLE_ARABIC:
315     case RTL_TEXTENCODING_APPLE_CENTEURO:
316     case RTL_TEXTENCODING_APPLE_CROATIAN:
317     case RTL_TEXTENCODING_APPLE_CYRILLIC:
318     case RTL_TEXTENCODING_APPLE_DEVANAGARI:
319     case RTL_TEXTENCODING_APPLE_FARSI:
320     case RTL_TEXTENCODING_APPLE_GREEK:
321     case RTL_TEXTENCODING_APPLE_GUJARATI:
322     case RTL_TEXTENCODING_APPLE_GURMUKHI:
323     case RTL_TEXTENCODING_APPLE_HEBREW:
324     case RTL_TEXTENCODING_APPLE_ICELAND:
325     case RTL_TEXTENCODING_APPLE_ROMANIAN:
326     case RTL_TEXTENCODING_APPLE_THAI:
327     case RTL_TEXTENCODING_APPLE_TURKISH:
328     case RTL_TEXTENCODING_APPLE_UKRAINIAN:
329     case RTL_TEXTENCODING_APPLE_CHINSIMP:
330     case RTL_TEXTENCODING_APPLE_CHINTRAD:
331     case RTL_TEXTENCODING_APPLE_JAPANESE:
332     case RTL_TEXTENCODING_APPLE_KOREAN:
333       return def; break;
334     default:
335         break;
336     }
337     return RTL_TEXTENCODING_APPLE_ROMAN;
338   }();
339   if (fId == 13) return RTL_TEXTENCODING_ADOBE_DINGBATS; // CHECKME
340   if (fId == 23) return RTL_TEXTENCODING_ADOBE_SYMBOL;
341   return enc;
342 }
343 
SetLineColor(const Color & rColor)344 void PictReader::SetLineColor( const Color& rColor )
345 {
346     pVirDev->SetLineColor( rColor );
347 }
348 
SetFillColor(const Color & rColor)349 void PictReader::SetFillColor( const Color& rColor )
350 {
351     pVirDev->SetFillColor( rColor );
352 }
353 
ReadPoint()354 Point PictReader::ReadPoint()
355 {
356     short nx,ny;
357 
358     pPict->ReadInt16( ny ).ReadInt16( nx );
359 
360     Point aPoint( static_cast<long>(nx) - aBoundingRect.Left(),
361                  static_cast<long>(ny) - aBoundingRect.Top() );
362 
363     SAL_INFO("filter.pict", "ReadPoint: " << aPoint);
364     return aPoint;
365 }
366 
ReadDeltaH(Point aBase)367 Point PictReader::ReadDeltaH(Point aBase)
368 {
369     signed char ndh;
370 
371     pPict->ReadChar( reinterpret_cast<char&>(ndh) );
372 
373     return Point( aBase.X() + static_cast<long>(ndh), aBase.Y() );
374 }
375 
ReadDeltaV(Point aBase)376 Point PictReader::ReadDeltaV(Point aBase)
377 {
378     signed char ndv;
379 
380     pPict->ReadChar( reinterpret_cast<char&>(ndv) );
381 
382     return Point( aBase.X(), aBase.Y() + static_cast<long>(ndv) );
383 }
384 
ReadUnsignedDeltaH(Point aBase)385 Point PictReader::ReadUnsignedDeltaH(Point aBase)
386 {
387     sal_uInt8 ndh;
388 
389     pPict->ReadUChar( ndh );
390 
391     return Point( aBase.X() + static_cast<long>(ndh), aBase.Y() );
392 }
393 
ReadUnsignedDeltaV(Point aBase)394 Point PictReader::ReadUnsignedDeltaV(Point aBase)
395 {
396     sal_uInt8 ndv;
397 
398     pPict->ReadUChar( ndv );
399 
400     return Point( aBase.X(), aBase.Y() + static_cast<long>(ndv) );
401 }
402 
ReadSize()403 Size PictReader::ReadSize()
404 {
405     short nx,ny;
406 
407     pPict->ReadInt16( ny ).ReadInt16( nx );
408 
409     return Size( static_cast<long>(nx), static_cast<long>(ny) );
410 }
411 
ReadColor()412 Color PictReader::ReadColor()
413 {
414     sal_uInt32 nCol;
415     Color aCol;
416 
417     pPict->ReadUInt32( nCol );
418     switch (nCol)
419     {
420         case  33: aCol=COL_BLACK;        break;
421         case  30: aCol=COL_WHITE;        break;
422         case 205: aCol=COL_LIGHTRED;     break;
423         case 341: aCol=COL_LIGHTGREEN;   break;
424         case 409: aCol=COL_LIGHTBLUE;    break;
425         case 273: aCol=COL_LIGHTCYAN;    break;
426         case 137: aCol=COL_LIGHTMAGENTA; break;
427         case  69: aCol=COL_YELLOW;       break;
428         default:  aCol=COL_LIGHTGRAY;
429     }
430     return aCol;
431 }
432 
433 
ReadRGBColor()434 Color PictReader::ReadRGBColor()
435 {
436     sal_uInt16 nR, nG, nB;
437 
438     pPict->ReadUInt16( nR ).ReadUInt16( nG ).ReadUInt16( nB );
439     return Color( static_cast<sal_uInt8>( nR >> 8 ), static_cast<sal_uInt8>( nG >> 8 ), static_cast<sal_uInt8>( nB >> 8 ) );
440 }
441 
442 
ReadRectangle(tools::Rectangle & rRect)443 void PictReader::ReadRectangle(tools::Rectangle & rRect)
444 {
445     Point aTopLeft, aBottomRight;
446 
447     aTopLeft=ReadPoint();
448     aBottomRight=ReadPoint();
449     rRect=tools::Rectangle(aTopLeft,aBottomRight);
450 
451     SAL_INFO("filter.pict", "ReadRectangle: " << rRect);
452 }
453 
ReadPolygon(tools::Polygon & rPoly)454 sal_uLong PictReader::ReadPolygon(tools::Polygon & rPoly)
455 {
456     sal_uInt16 nSize(0);
457     pPict->ReadUInt16(nSize);
458     pPict->SeekRel(8);
459     sal_uLong nDataSize = static_cast<sal_uLong>(nSize);
460     nSize=(nSize-10)/4;
461     const size_t nMaxPossiblePoints = pPict->remainingSize() / 2 * sizeof(sal_uInt16);
462     if (nSize > nMaxPossiblePoints)
463     {
464         SAL_WARN("filter.pict", "pict record claims to have: " << nSize << " points, but only " << nMaxPossiblePoints << " possible, clamping");
465         nSize = nMaxPossiblePoints;
466     }
467     rPoly.SetSize(nSize);
468     for (sal_uInt16 i = 0; i < nSize; ++i)
469     {
470         rPoly.SetPoint(ReadPoint(), i);
471         if (!pPict->good())
472         {
473             rPoly.SetSize(i);
474             break;
475         }
476     }
477     return nDataSize;
478 }
479 
ReadPixPattern(PictReader::Pattern & pattern)480 sal_uLong PictReader::ReadPixPattern(PictReader::Pattern &pattern)
481 {
482     // Don't know if this is correct because no picture which contains PixPatterns found.
483     // Here again the attempt to calculate the size of the date to create simple StarView-Styles
484     // from them. Luckily a PixPattern always contains a normal pattern.
485 
486 
487     sal_uLong nDataSize;
488     sal_uInt16 nPatType;
489     BitmapEx aBMP;
490 
491     pPict->ReadUInt16( nPatType );
492     if (nPatType==1) {
493         pattern.read(*pPict);
494         nDataSize=ReadPixMapEtc(aBMP,false,true,nullptr,nullptr,false,false);
495         // CHANGEME: use average pixmap colors to update the pattern, ...
496         if (nDataSize!=0xffffffff) nDataSize+=10;
497     }
498     else if (nPatType==2) {
499         pattern.read(*pPict);
500         // RGBColor
501         sal_uInt16 nR, nG, nB;
502         pPict->ReadUInt16( nR ).ReadUInt16( nG ).ReadUInt16( nB );
503         Color col(static_cast<sal_uInt8>( nR >> 8 ), static_cast<sal_uInt8>( nG >> 8 ), static_cast<sal_uInt8>( nB >> 8 ) );
504         pattern.setColor(col);
505         nDataSize=16;
506     }
507     else nDataSize=0xffffffff;
508 
509     return nDataSize;
510 }
511 
ReadAndDrawRect(PictDrawingMethod eMethod)512 sal_uLong PictReader::ReadAndDrawRect(PictDrawingMethod eMethod)
513 {
514     ReadRectangle(aLastRect);
515     ReadAndDrawSameRect(eMethod);
516     return 8;
517 }
518 
ReadAndDrawSameRect(PictDrawingMethod eMethod)519 sal_uLong PictReader::ReadAndDrawSameRect(PictDrawingMethod eMethod)
520 {
521     if (IsInvisible(eMethod)) return 0;
522     DrawingMethod(eMethod);
523     PictReaderShape::drawRectangle( pVirDev, eMethod == PictDrawingMethod::FRAME, aLastRect, nActPenSize );
524     return 0;
525 }
526 
ReadAndDrawRoundRect(PictDrawingMethod eMethod)527 sal_uLong PictReader::ReadAndDrawRoundRect(PictDrawingMethod eMethod)
528 {
529     ReadRectangle(aLastRoundRect);
530     ReadAndDrawSameRoundRect(eMethod);
531     return 8;
532 }
533 
ReadAndDrawSameRoundRect(PictDrawingMethod eMethod)534 sal_uLong PictReader::ReadAndDrawSameRoundRect(PictDrawingMethod eMethod)
535 {
536     if (IsInvisible(eMethod)) return 0;
537     DrawingMethod(eMethod);
538     PictReaderShape::drawRoundRectangle( pVirDev, eMethod == PictDrawingMethod::FRAME, aLastRoundRect, aActOvalSize, nActPenSize );
539     return 0;
540 }
541 
ReadAndDrawOval(PictDrawingMethod eMethod)542 sal_uLong PictReader::ReadAndDrawOval(PictDrawingMethod eMethod)
543 {
544     ReadRectangle(aLastOval);
545     ReadAndDrawSameOval(eMethod);
546     return 8;
547 }
548 
ReadAndDrawSameOval(PictDrawingMethod eMethod)549 sal_uLong PictReader::ReadAndDrawSameOval(PictDrawingMethod eMethod)
550 {
551     if (IsInvisible(eMethod)) return 0;
552     DrawingMethod(eMethod);
553     PictReaderShape::drawEllipse( pVirDev, eMethod == PictDrawingMethod::FRAME, aLastOval, nActPenSize );
554     return 0;
555 }
556 
ReadAndDrawPolygon(PictDrawingMethod eMethod)557 sal_uLong PictReader::ReadAndDrawPolygon(PictDrawingMethod eMethod)
558 {
559     sal_uLong nDataSize;
560     nDataSize=ReadPolygon(aLastPolygon);
561     ReadAndDrawSamePolygon(eMethod);
562     return nDataSize;
563 }
564 
ReadAndDrawSamePolygon(PictDrawingMethod eMethod)565 sal_uLong PictReader::ReadAndDrawSamePolygon(PictDrawingMethod eMethod)
566 {
567     if (IsInvisible(eMethod)) return 0;
568     DrawingMethod(eMethod);
569     PictReaderShape::drawPolygon( pVirDev, eMethod == PictDrawingMethod::FRAME, aLastPolygon, nActPenSize );
570     return 0;
571 }
572 
573 
ReadAndDrawArc(PictDrawingMethod eMethod)574 sal_uLong PictReader::ReadAndDrawArc(PictDrawingMethod eMethod)
575 {
576     ReadRectangle(aLastArcRect);
577     ReadAndDrawSameArc(eMethod);
578     return 12;
579 }
580 
ReadAndDrawSameArc(PictDrawingMethod eMethod)581 sal_uLong PictReader::ReadAndDrawSameArc(PictDrawingMethod eMethod)
582 {
583     short nstartAngle, narcAngle;
584     double fAng1, fAng2;
585 
586     pPict->ReadInt16( nstartAngle ).ReadInt16( narcAngle );
587     if (IsInvisible(eMethod)) return 4;
588     DrawingMethod(eMethod);
589 
590     if (narcAngle<0) {
591         nstartAngle = nstartAngle + narcAngle;
592         narcAngle=-narcAngle;
593     }
594     const double pi = 2 * acos(0.0);
595     fAng1 = static_cast<double>(nstartAngle) * pi / 180.0;
596     fAng2 = static_cast<double>(nstartAngle + narcAngle) * pi / 180.0;
597     PictReaderShape::drawArc( pVirDev, eMethod == PictDrawingMethod::FRAME, aLastArcRect, fAng1, fAng2, nActPenSize );
598     return 4;
599 }
600 
ReadAndDrawRgn(PictDrawingMethod eMethod)601 sal_uLong PictReader::ReadAndDrawRgn(PictDrawingMethod eMethod)
602 {
603     sal_uInt16 nSize;
604 
605     pPict->ReadUInt16( nSize );
606     // read the DATA
607     //
608     // a region data is a mask and is probably coded as
609     // - the first 8 bytes: bdbox ( which can be read by ReadRectangle )
610     // - then a list of line modifiers: y_i, a_0, b_0, a_1, b_1, ..., a_{n_i}, b_{n_i}, 0x7fff
611     // - 0x7fff
612     // where y_i is the increasing sequences of line coordinates
613     // and on each line: a0 < b0 < a1 < b1 < ... < a_{n_i} < b_{n_i}
614 
615     // it can be probably decoded as :
616     // M=an empty mask: ie. (0, 0, ... ) with (left_box-right_box+1) zeroes
617     // then for each line (y_i):
618     //   - takes M and inverts all values in [a_0,b_0-1], in [a_1,b_1-1] ...
619     //   - sets M = new y_i line mask
620     ReadAndDrawSameRgn(eMethod);
621     return static_cast<sal_uLong>(nSize);
622 }
623 
ReadAndDrawSameRgn(PictDrawingMethod eMethod)624 sal_uLong PictReader::ReadAndDrawSameRgn(PictDrawingMethod eMethod)
625 {
626     if (IsInvisible(eMethod)) return 0;
627     DrawingMethod(eMethod);
628     // DISPLAY: ...???...
629     return 0;
630 }
631 
DrawingMethod(PictDrawingMethod eMethod)632 void PictReader::DrawingMethod(PictDrawingMethod eMethod)
633 {
634     if( eActMethod==eMethod ) return;
635     switch (eMethod) {
636         case PictDrawingMethod::FRAME:
637             if (eActPenPattern.isDefault())
638               SetLineColor( aActForeColor );
639             else
640               SetLineColor(eActPenPattern.getColor(aActBackColor, aActForeColor));
641             SetFillColor( COL_TRANSPARENT );
642             pVirDev->SetRasterOp(eActROP);
643             break;
644         case PictDrawingMethod::PAINT:
645             SetLineColor( COL_TRANSPARENT );
646             if (eActPenPattern.isDefault())
647               SetFillColor( aActForeColor );
648             else
649               SetFillColor(eActPenPattern.getColor(aActBackColor, aActForeColor));
650             pVirDev->SetRasterOp(eActROP);
651             break;
652         case PictDrawingMethod::ERASE:
653             SetLineColor( COL_TRANSPARENT );
654             if (eActBackPattern.isDefault())
655               SetFillColor( aActBackColor );// Osnola: previously aActForeColor
656             else // checkMe
657               SetFillColor(eActBackPattern.getColor(COL_BLACK, aActBackColor));
658             pVirDev->SetRasterOp(RasterOp::OverPaint);
659             break;
660         case PictDrawingMethod::INVERT: // checkme
661             SetLineColor( COL_TRANSPARENT);
662             SetFillColor( COL_BLACK );
663             pVirDev->SetRasterOp(RasterOp::Invert);
664             break;
665         case PictDrawingMethod::FILL:
666             SetLineColor( COL_TRANSPARENT );
667             if (eActFillPattern.isDefault())
668               SetFillColor( aActForeColor );
669             else
670               SetFillColor(eActFillPattern.getColor(aActBackColor, aActForeColor));
671             pVirDev->SetRasterOp(RasterOp::OverPaint);
672             break;
673         case PictDrawingMethod::TEXT:
674             aActFont.SetColor(aActForeColor);
675             aActFont.SetFillColor(aActBackColor);
676             aActFont.SetTransparent(true);
677             pVirDev->SetFont(aActFont);
678             pVirDev->SetRasterOp(RasterOp::OverPaint);
679             break;
680         default:
681             break;  // -Wall undefined not handled...
682     }
683     eActMethod=eMethod;
684 }
685 
ReadAndDrawText()686 sal_uLong PictReader::ReadAndDrawText()
687 {
688     char        nByteLen;
689     sal_uInt32  nLen, nDataLen;
690     sal_Char    sText[256];
691 
692     pPict->ReadChar( nByteLen ); nLen=static_cast<sal_uLong>(nByteLen)&0x000000ff;
693     nDataLen = nLen + 1;
694     pPict->ReadBytes(&sText, nLen);
695 
696     if (IsInvisible( PictDrawingMethod::TEXT )) return nDataLen;
697     DrawingMethod( PictDrawingMethod::TEXT );
698 
699     // remove annoying control characters:
700     while ( nLen > 0 && static_cast<unsigned char>(sText[ nLen - 1 ]) < 32 )
701             nLen--;
702     sText[ nLen ] = 0;
703     OUString aString( sText, strlen(sText), aActFont.GetCharSet());
704     pVirDev->DrawText( Point( aTextPosition.X(), aTextPosition.Y() ), aString );
705     return nDataLen;
706 }
707 
ReadPixMapEtc(BitmapEx & rBitmap,bool bBaseAddr,bool bColorTable,tools::Rectangle * pSrcRect,tools::Rectangle * pDestRect,bool bMode,bool bMaskRgn)708 sal_uLong PictReader::ReadPixMapEtc( BitmapEx &rBitmap, bool bBaseAddr, bool bColorTable, tools::Rectangle* pSrcRect,
709                                     tools::Rectangle* pDestRect, bool bMode, bool bMaskRgn )
710 {
711     std::unique_ptr<vcl::bitmap::RawBitmap> pBitmap;
712     sal_uInt16 nPackType(0), nPixelSize(0), nCmpCount(0), nCmpSize(0);
713     sal_uInt8  nDat(0), nRed(0), nGreen(0), nBlue(0);
714 
715     // The calculation of nDataSize is considering the size of the whole data.
716     size_t nDataSize = 0;
717 
718     // conditionally skip BaseAddr
719     if ( bBaseAddr )
720     {
721         pPict->SeekRel( 4 );
722         nDataSize += 4;
723     }
724 
725     // Read PixMap or Bitmap structure;
726     sal_uInt16 nRowBytes(0), nBndX(0), nBndY(0), nWidth(0), nHeight(0);
727     pPict->ReadUInt16(nRowBytes).ReadUInt16(nBndY).ReadUInt16(nBndX).ReadUInt16(nHeight).ReadUInt16(nWidth);
728     if (nBndY > nHeight)
729         return 0xffffffff;
730     nHeight = nHeight - nBndY;
731     if (nHeight == 0)
732         return 0xffffffff;
733     if (nBndX > nWidth)
734         return 0xffffffff;
735     nWidth = nWidth - nBndX;
736     if (nWidth == 0)
737         return 0xffffffff;
738     sal_uInt16 nDstBitCount = 1;
739 
740     std::vector<Color> aPalette;
741     const bool bNotMonoChrome = (nRowBytes & 0x8000) != 0;
742     if (bNotMonoChrome)
743     {   // it is a PixMap
744         nRowBytes &= 0x3fff;
745         sal_uInt16 nVersion;
746         sal_uInt32 nPackSize;
747         sal_uInt16 nPixelType;
748         sal_uInt32 nPlaneBytes;
749         sal_uInt32 nHRes, nVRes;
750         pPict->ReadUInt16( nVersion ).ReadUInt16( nPackType ).ReadUInt32( nPackSize ).ReadUInt32( nHRes ).ReadUInt32( nVRes ).ReadUInt16( nPixelType ).ReadUInt16( nPixelSize ).ReadUInt16( nCmpCount ).ReadUInt16( nCmpSize ).ReadUInt32( nPlaneBytes );
751 
752         pPict->SeekRel( 8 );
753         nDataSize += 46;
754 
755         nDstBitCount = nPixelSize;
756         if ( nDstBitCount > 8 )
757             nDstBitCount = 24;
758         else if ( nDstBitCount == 2 )
759             nDstBitCount = 4;
760 
761         if ( bColorTable )
762         {
763             pPict->SeekRel( 6 );
764             sal_uInt16 nColTabSize(0);
765             pPict->ReadUInt16(nColTabSize);
766 
767             if (nColTabSize > 255)
768                 return 0xffffffff;
769 
770             ++nColTabSize;
771 
772             aPalette.resize(nColTabSize);
773 
774             for (size_t i = 0; i < nColTabSize; ++i)
775             {
776                 pPict->SeekRel(2);
777                 sal_uInt8 nDummy;
778                 pPict->ReadUChar( nRed ).ReadUChar( nDummy ).ReadUChar( nGreen ).ReadUChar( nDummy ).ReadUChar( nBlue ).ReadUChar( nDummy );
779                 aPalette[i] = Color(nRed, nGreen, nBlue);
780             }
781 
782             nDataSize += 8 + nColTabSize * 8;
783         }
784     }
785     else
786     {
787         nRowBytes &= 0x3fff;
788         nPixelSize = nCmpCount = nCmpSize = 1;
789         nDataSize += 10;
790         aPalette.resize(2);
791         aPalette[0] = Color(0xff, 0xff, 0xff);
792         aPalette[1] = Color(0, 0, 0);
793     }
794 
795     // conditionally read source rectangle:
796     if ( pSrcRect != nullptr)
797     {
798         sal_uInt16  nTop, nLeft, nBottom, nRight;
799         pPict->ReadUInt16( nTop ).ReadUInt16( nLeft ).ReadUInt16( nBottom ).ReadUInt16( nRight );
800         *pSrcRect = tools::Rectangle( static_cast<sal_uLong>(nLeft), static_cast<sal_uLong>(nTop), static_cast<sal_uLong>(nRight), static_cast<sal_uLong>(nBottom) );
801         nDataSize += 8;
802     }
803 
804     // conditionally read destination rectangle:
805     if ( pDestRect != nullptr )
806     {
807         Point aTL, aBR;
808         aTL = ReadPoint();
809         aBR = ReadPoint();
810         *pDestRect = tools::Rectangle( aTL, aBR );
811         nDataSize += 8;
812     }
813 
814     // conditionally read mode (or skip it):
815     if ( bMode )
816     {
817         pPict->SeekRel(2);
818         nDataSize += 2;
819     }
820 
821     // conditionally read region (or skip it):
822     if ( bMaskRgn )
823     {
824         sal_uInt16 nSize;
825         pPict->ReadUInt16( nSize );
826         pPict->SeekRel( nSize - 2 );
827         nDataSize += static_cast<sal_uLong>(nSize);
828     }
829 
830     // read and write Bitmap bits:
831     if ( nPixelSize == 1 || nPixelSize == 2 || nPixelSize == 4 || nPixelSize == 8 )
832     {
833         sal_uInt16  nSrcBPL, nDestBPL;
834         size_t nCount;
835 
836         if      ( nPixelSize == 1 ) nSrcBPL = ( nWidth + 7 ) >> 3;
837         else if ( nPixelSize == 2 ) nSrcBPL = ( nWidth + 3 ) >> 2;
838         else if ( nPixelSize == 4 ) nSrcBPL = ( nWidth + 1 ) >> 1;
839         else                        nSrcBPL = nWidth;
840         nDestBPL = ( nSrcBPL + 3 ) & 0xfffc;
841         if (!nRowBytes || nRowBytes < nSrcBPL || nRowBytes > nDestBPL)
842             return 0xffffffff;
843 
844         if (nRowBytes < 8 || nPackType == 1)
845         {
846             if (nHeight > pPict->remainingSize() / (sizeof(sal_uInt8) * nRowBytes))
847                 return 0xffffffff;
848         }
849         else
850         {
851             size_t nByteCountSize = nRowBytes > 250 ? sizeof(sal_uInt16) : sizeof(sal_uInt8);
852             if (nHeight > pPict->remainingSize() / nByteCountSize)
853                 return 0xffffffff;
854         }
855 
856         pBitmap.reset(new vcl::bitmap::RawBitmap( Size(nWidth, nHeight), 24 ));
857 
858         for (sal_uInt16 ny = 0; ny < nHeight; ++ny)
859         {
860             sal_uInt16 nx = 0;
861             if ( nRowBytes < 8 || nPackType == 1 )
862             {
863                 for (size_t i = 0; i < nRowBytes; ++i)
864                 {
865                     pPict->ReadUChar( nDat );
866                     if ( nx < nWidth )
867                         SetByte(nx, ny, *pBitmap, nPixelSize, nDat, nWidth, aPalette);
868                 }
869                 nDataSize += nRowBytes;
870             }
871             else
872             {
873                 sal_uInt16 nByteCount(0);
874                 if ( nRowBytes > 250 )
875                 {
876                     pPict->ReadUInt16( nByteCount );
877                     nDataSize += 2 + static_cast<sal_uLong>(nByteCount);
878                 }
879                 else
880                 {
881                     sal_uInt8 nByteCountAsByte(0);
882                     pPict->ReadUChar( nByteCountAsByte );
883                     nByteCount = static_cast<sal_uInt16>(nByteCountAsByte) & 0x00ff;
884                     nDataSize += 1 + static_cast<sal_uLong>(nByteCount);
885                 }
886 
887                 while (pPict->good() && nByteCount)
888                 {
889                     sal_uInt8 nFlagCounterByte(0);
890                     pPict->ReadUChar(nFlagCounterByte);
891                     if ( ( nFlagCounterByte & 0x80 ) == 0 )
892                     {
893                         nCount = static_cast<sal_uInt16>(nFlagCounterByte) + 1;
894                         for (size_t i = 0; i < nCount; ++i)
895                         {
896                             pPict->ReadUChar( nDat );
897                             if ( nx < nWidth )
898                                 SetByte(nx, ny, *pBitmap, nPixelSize, nDat, nWidth, aPalette);
899                         }
900                         nByteCount -= 1 + nCount;
901                     }
902                     else
903                     {
904                         nCount = static_cast<sal_uInt16>( 1 - sal_Int16( static_cast<sal_uInt16>(nFlagCounterByte) | 0xff00 ) );
905                         pPict->ReadUChar( nDat );
906                         for (size_t i = 0; i < nCount; ++i)
907                         {
908                             if ( nx < nWidth )
909                                 SetByte(nx, ny, *pBitmap, nPixelSize, nDat, nWidth, aPalette);
910                         }
911                         nByteCount -= 2;
912                     }
913                 }
914             }
915         }
916     }
917     else if ( nPixelSize == 16 )
918     {
919         sal_uInt8   nByteCountAsByte, nFlagCounterByte;
920         sal_uInt16  nByteCount, nCount, nD;
921         sal_uLong   nSrcBitsPos;
922 
923         if (nWidth > nRowBytes / 2)
924             return 0xffffffff;
925 
926         if (nRowBytes < 8 || nPackType == 1)
927         {
928             if (nHeight > pPict->remainingSize() / (sizeof(sal_uInt8) * nRowBytes))
929                 return 0xffffffff;
930         }
931         else
932         {
933             size_t nByteCountSize = nRowBytes > 250 ? sizeof(sal_uInt16) : sizeof(sal_uInt8);
934             if (nHeight > pPict->remainingSize() / nByteCountSize)
935                 return 0xffffffff;
936         }
937 
938         pBitmap.reset(new vcl::bitmap::RawBitmap( Size(nWidth, nHeight), 24 ));
939 
940         for (sal_uInt16 ny = 0; ny < nHeight; ++ny)
941         {
942             sal_uInt16 nx = 0;
943             if ( nRowBytes < 8 || nPackType == 1 )
944             {
945                 for (size_t i = 0; i < nWidth; ++i)
946                 {
947                     pPict->ReadUInt16( nD );
948                     nRed = static_cast<sal_uInt8>( nD >> 7 );
949                     nGreen = static_cast<sal_uInt8>( nD >> 2 );
950                     nBlue = static_cast<sal_uInt8>( nD << 3 );
951                     pBitmap->SetPixel(ny, nx++, Color(nRed, nGreen, nBlue));
952                 }
953                 nDataSize += static_cast<sal_uLong>(nWidth) * 2;
954             }
955             else
956             {
957                 nSrcBitsPos = pPict->Tell();
958                 if ( nRowBytes > 250 )
959                 {
960                     pPict->ReadUInt16( nByteCount );
961                     nByteCount += 2;
962                 }
963                 else
964                 {
965                     pPict->ReadUChar( nByteCountAsByte );
966                     nByteCount = static_cast<sal_uInt16>(nByteCountAsByte) & 0x00ff;
967                     nByteCount++;
968                 }
969                 while ( nx != nWidth )
970                 {
971                     pPict->ReadUChar( nFlagCounterByte );
972                     if ( (nFlagCounterByte & 0x80) == 0)
973                     {
974                         nCount=static_cast<sal_uInt16>(nFlagCounterByte)+1;
975                         if ( nCount + nx > nWidth)
976                             nCount = nWidth - nx;
977                         if (pPict->remainingSize() < sizeof(sal_uInt16) * nCount)
978                             return 0xffffffff;
979                         /* SJ: the RLE decoding seems not to be correct here,
980                            I don't want to change this until I have a bugdoc for
981                            this case. Have a look at 32bit, there I changed the
982                            encoding, so that it is used a straight forward array
983                          */
984                         for (size_t i = 0; i < nCount; ++i)
985                         {
986                             pPict->ReadUInt16( nD );
987                             nRed = static_cast<sal_uInt8>( nD >> 7 );
988                             nGreen = static_cast<sal_uInt8>( nD >> 2 );
989                             nBlue = static_cast<sal_uInt8>( nD << 3 );
990                             pBitmap->SetPixel(ny, nx++, Color(nRed, nGreen, nBlue));
991                         }
992                     }
993                     else
994                     {
995                         if (pPict->remainingSize() < sizeof(sal_uInt16))
996                             return 0xffffffff;
997                         nCount=(1-sal_Int16(static_cast<sal_uInt16>(nFlagCounterByte)|0xff00));
998                         if ( nCount + nx > nWidth )
999                             nCount = nWidth - nx;
1000                         pPict->ReadUInt16( nD );
1001                         nRed = static_cast<sal_uInt8>( nD >> 7 );
1002                         nGreen = static_cast<sal_uInt8>( nD >> 2 );
1003                         nBlue = static_cast<sal_uInt8>( nD << 3 );
1004                         for (size_t i = 0; i < nCount; ++i)
1005                         {
1006                             pBitmap->SetPixel(ny, nx++, Color(nRed, nGreen, nBlue));
1007                         }
1008                     }
1009                 }
1010                 nDataSize+=static_cast<sal_uLong>(nByteCount);
1011                 pPict->Seek(nSrcBitsPos+static_cast<sal_uLong>(nByteCount));
1012             }
1013         }
1014     }
1015     else if ( nPixelSize == 32 )
1016     {
1017         sal_uInt16          nByteCount;
1018         size_t              nCount;
1019         sal_uLong           nSrcBitsPos;
1020         if ( nRowBytes != 4*nWidth )
1021             return 0xffffffff;
1022 
1023         if ( nRowBytes < 8 || nPackType == 1 )
1024         {
1025             const size_t nMaxPixels = pPict->remainingSize() / 4;
1026             const size_t nMaxRows = nMaxPixels / nWidth;
1027             if (nHeight > nMaxRows)
1028                 return 0xffffffff;
1029             const size_t nMaxCols = nMaxPixels / nHeight;
1030             if (nWidth > nMaxCols)
1031                 return 0xffffffff;
1032 
1033             pBitmap.reset(new vcl::bitmap::RawBitmap( Size(nWidth, nHeight), 24 ));
1034 
1035             for (sal_uInt16 ny = 0; ny < nHeight; ++ny)
1036             {
1037                 for (sal_uInt16 nx = 0; nx < nWidth; ++nx)
1038                 {
1039                     sal_uInt8 nDummy;
1040                     pPict->ReadUChar( nDummy ).ReadUChar( nRed ).ReadUChar( nGreen ).ReadUChar( nBlue );
1041                     pBitmap->SetPixel(ny, nx, Color(nRed, nGreen, nBlue));
1042                 }
1043                 nDataSize += static_cast<sal_uLong>(nWidth) * 4;
1044             }
1045         }
1046         else if ( nPackType == 2 )
1047         {
1048             const size_t nMaxPixels = pPict->remainingSize() / 3;
1049             const size_t nMaxRows = nMaxPixels / nWidth;
1050             if (nHeight > nMaxRows)
1051                 return 0xffffffff;
1052             const size_t nMaxCols = nMaxPixels / nHeight;
1053             if (nWidth > nMaxCols)
1054                 return 0xffffffff;
1055 
1056             pBitmap.reset(new vcl::bitmap::RawBitmap( Size(nWidth, nHeight), 24 ));
1057 
1058             for (sal_uInt16 ny = 0; ny < nHeight; ++ny)
1059             {
1060                 for (sal_uInt16 nx = 0; nx < nWidth; ++nx)
1061                 {
1062                     pPict->ReadUChar( nRed ).ReadUChar( nGreen ).ReadUChar( nBlue );
1063                     pBitmap->SetPixel(ny, nx, Color(nRed, nGreen, nBlue));
1064                 }
1065                 nDataSize += static_cast<sal_uLong>(nWidth) * 3;
1066             }
1067         }
1068         else
1069         {
1070             sal_uInt8 nByteCountAsByte;
1071             sal_uInt8 nFlagCounterByte;
1072             if ( ( nCmpCount == 3 ) || ( nCmpCount == 4 ) )
1073             {
1074                 size_t nByteCountSize = nRowBytes > 250 ? sizeof(sal_uInt16) : sizeof(sal_uInt8);
1075                 if (nHeight > pPict->remainingSize() / nByteCountSize)
1076                     return 0xffffffff;
1077 
1078                 pBitmap.reset(new vcl::bitmap::RawBitmap( Size(nWidth, nHeight), 24 ));
1079 
1080                 size_t nByteWidth = static_cast<size_t>(nWidth) * nCmpCount;
1081                 std::vector<sal_uInt8> aScanline(nByteWidth);
1082                 for (sal_uInt16 ny = 0; ny < nHeight; ++ny)
1083                 {
1084                     nSrcBitsPos = pPict->Tell();
1085                     if ( nRowBytes > 250 )
1086                     {
1087                         pPict->ReadUInt16( nByteCount );
1088                         nByteCount += 2;
1089                     }
1090                     else
1091                     {
1092                         pPict->ReadUChar( nByteCountAsByte );
1093                         nByteCount = nByteCountAsByte;
1094                         nByteCount++;
1095                     }
1096                     size_t i = 0;
1097                     while (i < aScanline.size())
1098                     {
1099                         pPict->ReadUChar( nFlagCounterByte );
1100                         if ( ( nFlagCounterByte & 0x80 ) == 0)
1101                         {
1102                             nCount = static_cast<sal_uInt16>(nFlagCounterByte) + 1;
1103                             if ((i + nCount) > aScanline.size())
1104                                 nCount = aScanline.size() - i;
1105                             if (pPict->remainingSize() < nCount)
1106                                 return 0xffffffff;
1107                             while( nCount-- )
1108                             {
1109                                 pPict->ReadUChar( nDat );
1110                                 aScanline[ i++ ] = nDat;
1111                             }
1112                         }
1113                         else
1114                         {
1115                             if (pPict->remainingSize() < 1)
1116                                 return 0xffffffff;
1117                             nCount = ( 1 - sal_Int16( static_cast<sal_uInt16>(nFlagCounterByte) | 0xff00 ) );
1118                             if (( i + nCount) > aScanline.size())
1119                                 nCount = aScanline.size() - i;
1120                             pPict->ReadUChar( nDat );
1121                             while( nCount-- )
1122                                 aScanline[ i++ ] = nDat;
1123                         }
1124                     }
1125                     sal_uInt8* pTmp = aScanline.data();
1126                     if ( nCmpCount == 4 )
1127                         pTmp += nWidth;
1128                     for (sal_uInt16 nx = 0; nx < nWidth; pTmp++)
1129                         pBitmap->SetPixel(ny, nx++, Color(*pTmp, pTmp[ nWidth ], pTmp[ 2 * nWidth ]));
1130                     nDataSize += static_cast<sal_uLong>(nByteCount);
1131                     pPict->Seek( nSrcBitsPos + static_cast<sal_uLong>(nByteCount) );
1132                 }
1133             }
1134         }
1135     }
1136     else
1137         return 0xffffffff;
1138     rBitmap = vcl::bitmap::CreateFromData(std::move(*pBitmap));
1139     return nDataSize;
1140 }
1141 
ReadHeader()1142 void PictReader::ReadHeader()
1143 {
1144     short y1,x1,y2,x2;
1145 
1146     sal_Char    sBuf[ 2 ];
1147     // previous code considers pPict->Tell() as the normal starting position,
1148     // can we have nStartPos != 0 ?
1149     sal_uLong   nStartPos = pPict->Tell();
1150     // Standard:
1151     // a picture file begins by 512 bytes (reserved to the application) followed by the picture data
1152     // while clipboard, pictures stored in a document often contain only the picture data.
1153 
1154     // Special cases:
1155     // - some Pict v.1 use 0x00 0x11 0x01 ( instead of 0x11 0x01) to store the version op
1156     //    (we consider here this as another standard for Pict. v.1 )
1157     // - some files seem to contain extra garbage data at the beginning
1158     // - some picture data seem to contain extra NOP opcode(0x00) between the bounding box and the version opcode
1159 
1160     // This code looks hard to find a picture header, ie. it looks at positions
1161     //   - nStartPos+0, nStartPos+512 with potential extra NOP codes between bdbox and version (at most 9 extra NOP)
1162     //   - 512..1024 with more strict bdbox checking and no extra NOP codes
1163 
1164     // Notes:
1165     // - if the header can begin at nStartPos+0 and at nStartPos+512, we try to choose the more
1166     //       <<probable>> ( using the variable confidence)
1167     // - svtools/source/filter.vcl/filter/{filter.cxx,filter2.cxx} only check for standard Pict,
1168     //       this may cause future problems
1169     int st;
1170     sal_uInt32 nOffset;
1171     int confidence[2] = { 0, 0};
1172     for ( st = 0; st < 3 + 513; st++ )
1173       {
1174         int actualConfid = 20; // the actual confidence
1175         pPict->ResetError();
1176         if (st < 2) nOffset = nStartPos+st*512;
1177         else if (st == 2) {
1178           // choose nStartPos+0 or nStartPos+512 even if there are a little dubious
1179           int actPos = -1, actConf=0;
1180           if (confidence[0] > 0) { actPos = 0; actConf =  confidence[0]; }
1181           if (confidence[1] > 0 && confidence[1] >= actConf) actPos = 1;
1182           if (actPos < 0) continue;
1183           nOffset = nStartPos+actPos*512;
1184         }
1185         else {
1186           nOffset = 509+st; // illogical : more logical will be nStartPos+509+st or to consider that nStartPos=0
1187           // a small test to check if versionOp code exists after the bdbox ( with no extra NOP codes)
1188           pPict->Seek(nOffset+10);
1189           pPict->ReadBytes(sBuf, 2);
1190           if (!pPict->good()) break;
1191           if (sBuf[0] == 0x11 || (sBuf[0] == 0x00 && sBuf[1] == 0x11)) ; // maybe ok
1192           else continue;
1193         }
1194         pPict->Seek(nOffset);
1195 
1196         // 2 bytes to store size ( version 1 ) ignored
1197         pPict->SeekRel( 2 );
1198         pPict->ReadInt16( y1 ).ReadInt16( x1 ).ReadInt16( y2 ).ReadInt16( x2 ); // frame rectangle of the picture
1199         if (x1 > x2 || y1 > y2) continue; // bad bdbox
1200         if (x1 < -2048 || x2 > 2048 || y1 < -2048 || y2 > 2048 || // origin|dest is very small|large
1201         (x1 == x2 && y1 == y2) ) // 1 pixel pict is dubious
1202           actualConfid-=3;
1203         else if (x2 < x1+8 || y2 < y1+8) // a little dubious
1204           actualConfid-=1;
1205         if (st >= 3 && actualConfid != 20) continue;
1206         aBoundingRect=tools::Rectangle( x1,y1, x2, y2 );
1207 
1208         if (!pPict->good()) continue;
1209         // read version
1210         pPict->ReadBytes(sBuf, 2);
1211         // version 1 file
1212         if ( sBuf[ 0 ] == 0x11 && sBuf[ 1 ] == 0x01 ) {
1213           // pict v1 must be rare and we do only few tests
1214           if (st < 2) { confidence[st] = --actualConfid; continue; }
1215           IsVersion2 = false; return;
1216         }
1217         if (sBuf[0] != 0x00) continue; // unrecoverable error
1218         int numZero = 0;
1219         do
1220           {
1221         numZero++;
1222         pPict->SeekRel(-1);
1223         pPict->ReadBytes(sBuf, 2);
1224           }
1225         while ( sBuf[0] == 0x00 && numZero < 10);
1226         actualConfid -= (numZero-1); // extra nop are dubious
1227         if (!pPict->good()) continue;
1228         if (sBuf[0] != 0x11) continue; // not a version opcode
1229         // abnormal version 1 file
1230         if (sBuf[1] == 0x01 ) {
1231           // pict v1 must be rare and we do only few tests
1232           if (st < 2) { confidence[st] = --actualConfid; continue; }
1233           IsVersion2 = false; return;
1234         }
1235         if (sBuf[1] != 0x02 ) continue; // not a version 2 file
1236 
1237         IsVersion2=true;
1238         short   nExtVer, nReserved;
1239         // 3 Bytes ignored : end of version arg 0x02FF (ie: 0xFF), HeaderOp : 0x0C00
1240         pPict->SeekRel( 3 );
1241         pPict->ReadInt16( nExtVer ).ReadInt16( nReserved );
1242         if (!pPict->good()) continue;
1243 
1244         if ( nExtVer == -2 ) // extended version 2 picture
1245           {
1246         sal_Int32 nHResFixed, nVResFixed;
1247         pPict->ReadInt32( nHResFixed ).ReadInt32( nVResFixed );
1248         pPict->ReadInt16( y1 ).ReadInt16( x1 ).ReadInt16( y2 ).ReadInt16( x2 ); // reading the optimal bounding rect
1249         if (x1 > x2 || y1 > y2) continue; // bad bdbox
1250         if (st < 2 && actualConfid != 20) { confidence[st] = actualConfid; continue; }
1251 
1252         double fHRes = nHResFixed;
1253         fHRes /= 65536;
1254         double fVRes = nVResFixed;
1255         fVRes /= 65536;
1256         aHRes /= fHRes;
1257         aVRes /= fVRes;
1258         aBoundingRect=tools::Rectangle( x1,y1, x2, y2 );
1259         pPict->SeekRel( 4 ); // 4 bytes reserved
1260         return;
1261           }
1262         else if (nExtVer == -1 ) { // basic version 2 picture
1263           if (st < 2 && actualConfid != 20) { confidence[st] = actualConfid; continue; }
1264           pPict->SeekRel( 16); // bdbox(4 fixed number)
1265           pPict->SeekRel(4); // 4 bytes reserved
1266           return;
1267         }
1268       }
1269     pPict->SetError(SVSTREAM_FILEFORMAT_ERROR);
1270 }
1271 
1272 #if OSL_DEBUG_LEVEL > 0
operationName(sal_uInt16 nOpcode)1273 static const char* operationName(sal_uInt16 nOpcode)
1274 {
1275     // add here whatever makes the debugging easier for you, otherwise you'll
1276     // see only the operation's opcode
1277     switch (nOpcode)
1278     {
1279         case 0x0001: return "Clip";
1280         case 0x0003: return "TxFont";
1281         case 0x0004: return "TxFace";
1282         case 0x0008: return "PnMode";
1283         case 0x0009: return "PnPat";
1284         case 0x000d: return "TxSize";
1285         case 0x001a: return "RGBFgCol";
1286         case 0x001d: return "HiliteColor";
1287         case 0x0020: return "Line";
1288         case 0x0022: return "ShortLine";
1289         case 0x0028: return "LongText";
1290         case 0x0029: return "DHText";
1291         case 0x002a: return "DVText";
1292         case 0x002c: return "fontName";
1293         case 0x002e: return "glyphState";
1294         case 0x0031: return "paintRect";
1295         case 0x0038: return "frameSameRect";
1296         case 0x0070: return "framePoly";
1297         case 0x0071: return "paintPoly";
1298         case 0x00a1: return "LongComment";
1299         default:     return "?";
1300     }
1301 }
1302 #endif
1303 
ReadData(sal_uInt16 nOpcode)1304 sal_uLong PictReader::ReadData(sal_uInt16 nOpcode)
1305 {
1306     sal_uInt16 nUSHORT;
1307     Point aPoint;
1308     sal_uLong nDataSize=0;
1309     PictDrawingMethod shapeDMethod = PictDrawingMethod::UNDEFINED;
1310     switch (nOpcode & 7) {
1311     case 0: shapeDMethod = PictDrawingMethod::FRAME; break;
1312     case 1: shapeDMethod = PictDrawingMethod::PAINT; break;
1313     case 2: shapeDMethod = PictDrawingMethod::ERASE; break;
1314     case 3: shapeDMethod = PictDrawingMethod::INVERT; break;
1315     case 4: shapeDMethod = PictDrawingMethod::FILL; break;
1316     default: break;
1317     }
1318 
1319 #if OSL_DEBUG_LEVEL > 0
1320     SAL_INFO("filter.pict", "Operation: 0x" << OUString::number(nOpcode, 16) << " [" << operationName(nOpcode) << "]");
1321 #endif
1322 
1323     switch(nOpcode) {
1324 
1325     case 0x0000:   // NOP
1326         nDataSize=0;
1327         break;
1328 
1329     case 0x0001: { // Clip
1330         tools::Rectangle aRect;
1331         pPict->ReadUInt16( nUSHORT );
1332         nDataSize=nUSHORT;
1333         ReadRectangle(aRect);
1334         // checkme: do we really want to extend the rectangle here ?
1335         // I do that because the clipping is often used to clean a region,
1336         //   before drawing some text and also to draw this text.
1337         // So using a too small region can lead to clip the end of the text ;
1338         //   but this can be discussable...
1339         aRect.setWidth(aRect.getWidth()+1);
1340         aRect.setHeight(aRect.getHeight()+1);
1341         pVirDev->SetClipRegion( vcl::Region( aRect ) );
1342         break;
1343     }
1344     case 0x0002:   // BkPat
1345         nDataSize = eActBackPattern.read(*pPict);
1346         eActMethod = PictDrawingMethod::UNDEFINED;
1347         break;
1348 
1349     case 0x0003:   // TxFont
1350         pPict->ReadUInt16( nUSHORT );
1351         if      (nUSHORT <=    1) aActFont.SetFamily(FAMILY_SWISS);
1352         else if (nUSHORT <=   12) aActFont.SetFamily(FAMILY_DECORATIVE);
1353         else if (nUSHORT <=   20) aActFont.SetFamily(FAMILY_ROMAN);
1354         else if (nUSHORT ==   21) aActFont.SetFamily(FAMILY_SWISS);
1355         else if (nUSHORT ==   22) aActFont.SetFamily(FAMILY_MODERN);
1356         else if (nUSHORT <= 1023) aActFont.SetFamily(FAMILY_SWISS);
1357         else                      aActFont.SetFamily(FAMILY_ROMAN);
1358         aActFont.SetCharSet(GetTextEncoding(nUSHORT));
1359         eActMethod = PictDrawingMethod::UNDEFINED;
1360         nDataSize=2;
1361         break;
1362 
1363     case 0x0004: {  // TxFace
1364         char nFace;
1365         pPict->ReadChar( nFace );
1366         if ( (nFace & 0x01)!=0 ) aActFont.SetWeight(WEIGHT_BOLD);
1367         else                     aActFont.SetWeight(WEIGHT_NORMAL);
1368         if ( (nFace & 0x02)!=0 ) aActFont.SetItalic(ITALIC_NORMAL);
1369         else                     aActFont.SetItalic(ITALIC_NONE);
1370         if ( (nFace & 0x04)!=0 ) aActFont.SetUnderline(LINESTYLE_SINGLE);
1371         else                     aActFont.SetUnderline(LINESTYLE_NONE);
1372         if ( (nFace & 0x08)!=0 ) aActFont.SetOutline(true);
1373         else                     aActFont.SetOutline(false);
1374         if ( (nFace & 0x10)!=0 ) aActFont.SetShadow(true);
1375         else                     aActFont.SetShadow(false);
1376         eActMethod = PictDrawingMethod::UNDEFINED;
1377         nDataSize=1;
1378         break;
1379     }
1380     case 0x0005:   // TxMode
1381         nDataSize=2;
1382         break;
1383 
1384     case 0x0006:   // SpExtra
1385         nDataSize=4;
1386         break;
1387 
1388     case 0x0007: { // PnSize
1389         nActPenSize=ReadSize();
1390         eActMethod = PictDrawingMethod::UNDEFINED;
1391         nDataSize=4;
1392         break;
1393     }
1394     case 0x0008:   // PnMode
1395         pPict->ReadUInt16( nUSHORT );
1396         // internal code for postscript command (Quickdraw Reference Drawing B-30,B-34)
1397         if (nUSHORT==23) eActROP = RasterOp::N1;
1398         else {
1399           switch (nUSHORT & 0x0007) {
1400             case 0: eActROP=RasterOp::OverPaint; break; // Copy
1401             case 1: eActROP=RasterOp::OverPaint; break; // Or
1402             case 2: eActROP=RasterOp::Xor;       break; // Xor
1403             case 3: eActROP=RasterOp::OverPaint; break; // Bic
1404             case 4: eActROP=RasterOp::Invert;    break; // notCopy
1405             case 5: eActROP=RasterOp::OverPaint; break; // notOr
1406             case 6: eActROP=RasterOp::Xor;       break; // notXor
1407             case 7: eActROP=RasterOp::OverPaint; break; // notBic
1408           }
1409         }
1410         eActMethod = PictDrawingMethod::UNDEFINED;
1411         nDataSize=2;
1412         break;
1413 
1414     case 0x0009:   // PnPat
1415         nDataSize=eActPenPattern.read(*pPict);
1416         eActMethod = PictDrawingMethod::UNDEFINED;
1417         break;
1418 
1419     case 0x000a:   // FillPat
1420         nDataSize=eActFillPattern.read(*pPict);
1421         eActMethod = PictDrawingMethod::UNDEFINED;
1422         break;
1423 
1424     case 0x000b:   // OvSize
1425         aActOvalSize=ReadSize();
1426         nDataSize=4;
1427         break;
1428 
1429     case 0x000c:   // Origin
1430         nDataSize=4;
1431         break;
1432 
1433     case 0x000d:   // TxSize
1434     {
1435         pPict->ReadUInt16( nUSHORT );
1436         aActFont.SetFontSize( Size( 0, static_cast<long>(nUSHORT) ) );
1437         eActMethod = PictDrawingMethod::UNDEFINED;
1438         nDataSize=2;
1439     }
1440     break;
1441 
1442     case 0x000e:   // FgColor
1443         aActForeColor=ReadColor();
1444         eActMethod = PictDrawingMethod::UNDEFINED;
1445         nDataSize=4;
1446         break;
1447 
1448     case 0x000f:   // BkColor
1449         aActBackColor=ReadColor();
1450         nDataSize=4;
1451         break;
1452 
1453     case 0x0010:   // TxRatio
1454         nDataSize=8;
1455         break;
1456 
1457     case 0x0011:   // VersionOp
1458         nDataSize=1;
1459         break;
1460 
1461     case 0x0012:   // BkPixPat
1462         nDataSize=ReadPixPattern(eActBackPattern);
1463         eActMethod = PictDrawingMethod::UNDEFINED;
1464         break;
1465 
1466     case 0x0013:   // PnPixPat
1467         nDataSize=ReadPixPattern(eActPenPattern);
1468         eActMethod = PictDrawingMethod::UNDEFINED;
1469         break;
1470 
1471     case 0x0014:   // FillPixPat
1472         nDataSize=ReadPixPattern(eActFillPattern);
1473         eActMethod = PictDrawingMethod::UNDEFINED;
1474         break;
1475 
1476     case 0x0015:   // PnLocHFrac
1477         nDataSize=2;
1478         break;
1479 
1480     case 0x0016:   // ChExtra
1481         nDataSize=2;
1482         break;
1483 
1484     case 0x0017:   // Reserved (0 Bytes)
1485     case 0x0018:   // Reserved (0 Bytes)
1486     case 0x0019:   // Reserved (0 Bytes)
1487         nDataSize=0;
1488         break;
1489 
1490     case 0x001a:   // RGBFgCol
1491         aActForeColor=ReadRGBColor();
1492         eActMethod = PictDrawingMethod::UNDEFINED;
1493         nDataSize=6;
1494         break;
1495 
1496     case 0x001b:   // RGBBkCol
1497         aActBackColor=ReadRGBColor();
1498         eActMethod = PictDrawingMethod::UNDEFINED;
1499         nDataSize=6;
1500         break;
1501 
1502     case 0x001c:   // HiliteMode
1503         nDataSize=0;
1504         break;
1505 
1506     case 0x001d:   // HiliteColor
1507         nDataSize=6;
1508         break;
1509 
1510     case 0x001e:   // DefHilite
1511         nDataSize=0;
1512         break;
1513 
1514     case 0x001f:   // OpColor
1515         nDataSize=6;
1516         break;
1517 
1518     case 0x0020:   // Line
1519         aPoint=ReadPoint(); aPenPosition=ReadPoint();
1520         nDataSize=8;
1521 
1522         if (IsInvisible( PictDrawingMethod::FRAME )) break;
1523         DrawingMethod( PictDrawingMethod::FRAME );
1524         PictReaderShape::drawLine(pVirDev, aPoint,aPenPosition, nActPenSize);
1525         break;
1526 
1527     case 0x0021:   // LineFrom
1528         aPoint=aPenPosition; aPenPosition=ReadPoint();
1529         nDataSize=4;
1530 
1531         if (IsInvisible( PictDrawingMethod::FRAME )) break;
1532         DrawingMethod( PictDrawingMethod::FRAME );
1533         PictReaderShape::drawLine(pVirDev, aPoint,aPenPosition, nActPenSize);
1534         break;
1535 
1536     case 0x0022:   // ShortLine
1537         aPoint=ReadPoint();
1538         aPenPosition=ReadDeltaH(aPoint);
1539         aPenPosition=ReadDeltaV(aPenPosition);
1540         nDataSize=6;
1541 
1542         if ( IsInvisible(PictDrawingMethod::FRAME) ) break;
1543         DrawingMethod( PictDrawingMethod::FRAME );
1544         PictReaderShape::drawLine(pVirDev, aPoint,aPenPosition, nActPenSize);
1545         break;
1546 
1547     case 0x0023:   // ShortLineFrom
1548         aPoint=aPenPosition;
1549         aPenPosition=ReadDeltaH(aPoint);
1550         aPenPosition=ReadDeltaV(aPenPosition);
1551         nDataSize=2;
1552 
1553         if (IsInvisible( PictDrawingMethod::FRAME )) break;
1554         DrawingMethod( PictDrawingMethod::FRAME );
1555         PictReaderShape::drawLine(pVirDev, aPoint,aPenPosition, nActPenSize);
1556         break;
1557 
1558     case 0x0024:   // Reserved (n Bytes)
1559     case 0x0025:   // Reserved (n Bytes)
1560     case 0x0026:   // Reserved (n Bytes)
1561     case 0x0027:   // Reserved (n Bytes)
1562         pPict->ReadUInt16( nUSHORT );
1563         nDataSize=2+nUSHORT;
1564         break;
1565 
1566     case 0x0028:   // LongText
1567         aTextPosition=ReadPoint();
1568         nDataSize=4+ReadAndDrawText();
1569         break;
1570 
1571     case 0x0029:   // DHText
1572         aTextPosition=ReadUnsignedDeltaH(aTextPosition);
1573         nDataSize=1+ReadAndDrawText();
1574         break;
1575 
1576     case 0x002a:   // DVText
1577         aTextPosition=ReadUnsignedDeltaV(aTextPosition);
1578         nDataSize=1+ReadAndDrawText();
1579         break;
1580 
1581     case 0x002b:   // DHDVText
1582         aTextPosition=ReadUnsignedDeltaH(aTextPosition);
1583         aTextPosition=ReadUnsignedDeltaV(aTextPosition);
1584         nDataSize=2+ReadAndDrawText();
1585         break;
1586 
1587     case 0x002c: { // fontName
1588         char        sFName[ 256 ], nByteLen;
1589         sal_uInt16  nLen;
1590         pPict->ReadUInt16( nUSHORT ); nDataSize=nUSHORT+2;
1591         pPict->ReadUInt16( nUSHORT );
1592         if      (nUSHORT <=    1) aActFont.SetFamily(FAMILY_SWISS);
1593         else if (nUSHORT <=   12) aActFont.SetFamily(FAMILY_DECORATIVE);
1594         else if (nUSHORT <=   20) aActFont.SetFamily(FAMILY_ROMAN);
1595         else if (nUSHORT ==   21) aActFont.SetFamily(FAMILY_SWISS);
1596         else if (nUSHORT ==   22) aActFont.SetFamily(FAMILY_MODERN);
1597         else if (nUSHORT <= 1023) aActFont.SetFamily(FAMILY_SWISS);
1598         else                      aActFont.SetFamily(FAMILY_ROMAN);
1599         aActFont.SetCharSet(GetTextEncoding(nUSHORT));
1600         pPict->ReadChar( nByteLen ); nLen=static_cast<sal_uInt16>(nByteLen)&0x00ff;
1601         pPict->ReadBytes(&sFName, nLen);
1602         sFName[ nLen ] = 0;
1603         OUString aString( sFName, strlen(sFName), osl_getThreadTextEncoding() );
1604         aActFont.SetFamilyName( aString );
1605         eActMethod = PictDrawingMethod::UNDEFINED;
1606         break;
1607     }
1608     case 0x002d:   // lineJustify
1609         nDataSize=10;
1610         break;
1611 
1612     case 0x002e:   // glyphState
1613         pPict->ReadUInt16( nUSHORT );
1614         nDataSize=2+nUSHORT;
1615         break;
1616 
1617     case 0x002f:   // Reserved (n Bytes)
1618         pPict->ReadUInt16( nUSHORT );
1619         nDataSize=2+nUSHORT;
1620         break;
1621 
1622     case 0x0030:   // frameRect
1623     case 0x0031:   // paintRect
1624     case 0x0032:   // eraseRect
1625     case 0x0033:   // invertRect
1626     case 0x0034:   // fillRect
1627         nDataSize=ReadAndDrawRect(shapeDMethod);
1628         break;
1629 
1630     case 0x0035:   // Reserved (8 Bytes)
1631     case 0x0036:   // Reserved (8 Bytes)
1632     case 0x0037:   // Reserved (8 Bytes)
1633         nDataSize=8;
1634         break;
1635 
1636     case 0x0038:   // frameSameRect
1637     case 0x0039:   // paintSameRect
1638     case 0x003a:   // eraseSameRect
1639     case 0x003b:   // invertSameRect
1640     case 0x003c:   // fillSameRect
1641         nDataSize=ReadAndDrawSameRect(shapeDMethod);
1642         break;
1643 
1644     case 0x003d:   // Reserved (0 Bytes)
1645     case 0x003e:   // Reserved (0 Bytes)
1646     case 0x003f:   // Reserved (0 Bytes)
1647         nDataSize=0;
1648         break;
1649 
1650     case 0x0040:   // frameRRect
1651     case 0x0041:   // paintRRect
1652     case 0x0042:   // eraseRRect
1653     case 0x0043:   // invertRRect
1654     case 0x0044:   // fillRRect
1655         nDataSize=ReadAndDrawRoundRect(shapeDMethod);
1656         break;
1657 
1658     case 0x0045:   // Reserved (8 Bytes)
1659     case 0x0046:   // Reserved (8 Bytes)
1660     case 0x0047:   // Reserved (8 Bytes)
1661         nDataSize=8;
1662         break;
1663 
1664     case 0x0048:   // frameSameRRect
1665     case 0x0049:   // paintSameRRect
1666     case 0x004a:   // eraseSameRRect
1667     case 0x004b:   // invertSameRRect
1668     case 0x004c:   // fillSameRRect
1669         nDataSize=ReadAndDrawSameRoundRect(shapeDMethod);
1670         break;
1671 
1672     case 0x004d:   // Reserved (0 Bytes)
1673     case 0x004e:   // Reserved (0 Bytes)
1674     case 0x004f:   // Reserved (0 Bytes)
1675         nDataSize=0;
1676         break;
1677 
1678     case 0x0050:   // frameOval
1679     case 0x0051:   // paintOval
1680     case 0x0052:   // eraseOval
1681     case 0x0053:   // invertOval
1682     case 0x0054:   // fillOval
1683         nDataSize=ReadAndDrawOval(shapeDMethod);
1684         break;
1685 
1686     case 0x0055:   // Reserved (8 Bytes)
1687     case 0x0056:   // Reserved (8 Bytes)
1688     case 0x0057:   // Reserved (8 Bytes)
1689         nDataSize=8;
1690         break;
1691 
1692     case 0x0058:   // frameSameOval
1693     case 0x0059:   // paintSameOval
1694     case 0x005a:   // eraseSameOval
1695     case 0x005b:   // invertSameOval
1696     case 0x005c:   // fillSameOval
1697         nDataSize=ReadAndDrawSameOval(shapeDMethod);
1698         break;
1699 
1700     case 0x005d:   // Reserved (0 Bytes)
1701     case 0x005e:   // Reserved (0 Bytes)
1702     case 0x005f:   // Reserved (0 Bytes)
1703         nDataSize=0;
1704         break;
1705 
1706     case 0x0060:   // frameArc
1707     case 0x0061:   // paintArc
1708     case 0x0062:   // eraseArc
1709     case 0x0063:   // invertArc
1710     case 0x0064:   // fillArc
1711         nDataSize=ReadAndDrawArc(shapeDMethod);
1712         break;
1713 
1714     case 0x0065:   // Reserved (12 Bytes)
1715     case 0x0066:   // Reserved (12 Bytes)
1716     case 0x0067:   // Reserved (12 Bytes)
1717         nDataSize=12;
1718         break;
1719 
1720     case 0x0068:   // frameSameArc
1721     case 0x0069:   // paintSameArc
1722     case 0x006a:   // eraseSameArc
1723     case 0x006b:   // invertSameArc
1724     case 0x006c:   // fillSameArc
1725         nDataSize=ReadAndDrawSameArc(shapeDMethod);
1726         break;
1727 
1728     case 0x006d:   // Reserved (4 Bytes)
1729     case 0x006e:   // Reserved (4 Bytes)
1730     case 0x006f:   // Reserved (4 Bytes)
1731         nDataSize=4;
1732         break;
1733 
1734     case 0x0070:   // framePoly
1735     case 0x0071:   // paintPoly
1736     case 0x0072:   // erasePoly
1737     case 0x0073:   // invertPoly
1738     case 0x0074:   // fillPoly
1739         nDataSize=ReadAndDrawPolygon(shapeDMethod);
1740         break;
1741 
1742     case 0x0075:   // Reserved (Polygon-Size)
1743     case 0x0076:   // Reserved (Polygon-Size)
1744     case 0x0077:   // Reserved (Polygon-Size)
1745         pPict->ReadUInt16( nUSHORT ); nDataSize=nUSHORT;
1746         break;
1747 
1748     case 0x0078:   // frameSamePoly
1749     case 0x0079:   // paintSamePoly
1750     case 0x007a:   // eraseSamePoly
1751     case 0x007b:   // invertSamePoly
1752     case 0x007c:   // fillSamePoly
1753         nDataSize=ReadAndDrawSamePolygon(shapeDMethod);
1754         break;
1755 
1756     case 0x007d:   // Reserved (0 Bytes)
1757     case 0x007e:   // Reserved (0 Bytes)
1758     case 0x007f:   // Reserved (0 Bytes)
1759         nDataSize=0;
1760         break;
1761 
1762     case 0x0080:   // frameRgn
1763     case 0x0081:   // paintRgn
1764     case 0x0082:   // eraseRgn
1765     case 0x0083:   // invertRgn
1766     case 0x0084:   // fillRgn
1767         nDataSize=ReadAndDrawRgn(shapeDMethod);
1768         break;
1769 
1770     case 0x0085:   // Reserved (Region-Size)
1771     case 0x0086:   // Reserved (Region-Size)
1772     case 0x0087:   // Reserved (Region-Size)
1773         pPict->ReadUInt16( nUSHORT ); nDataSize=nUSHORT;
1774         break;
1775 
1776     case 0x0088:   // frameSameRgn
1777     case 0x0089:   // paintSameRgn
1778     case 0x008a:   // eraseSameRgn
1779     case 0x008b:   // invertSameRgn
1780     case 0x008c:   // fillSameRgn
1781         nDataSize=ReadAndDrawSameRgn(shapeDMethod);
1782         break;
1783 
1784     case 0x008d:   // Reserved (0 Bytes)
1785     case 0x008e:   // Reserved (0 Bytes)
1786     case 0x008f:   // Reserved (0 Bytes)
1787         nDataSize=0;
1788         break;
1789 
1790     case 0x0090: { // BitsRect
1791         BitmapEx aBmp;
1792         tools::Rectangle aSrcRect, aDestRect;
1793         nDataSize=ReadPixMapEtc(aBmp, false, true, &aSrcRect, &aDestRect, true, false);
1794         DrawingMethod( PictDrawingMethod::PAINT );
1795         pVirDev->DrawBitmapEx(aDestRect.TopLeft(),aDestRect.GetSize(),aBmp);
1796         break;
1797     }
1798     case 0x0091: { // BitsRgn
1799         BitmapEx aBmp;
1800         tools::Rectangle aSrcRect, aDestRect;
1801         nDataSize=ReadPixMapEtc(aBmp, false, true, &aSrcRect, &aDestRect, true, true);
1802         DrawingMethod( PictDrawingMethod::PAINT );
1803         pVirDev->DrawBitmapEx(aDestRect.TopLeft(),aDestRect.GetSize(),aBmp);
1804         break;
1805     }
1806     case 0x0092:   // Reserved (n Bytes)
1807     case 0x0093:   // Reserved (n Bytes)
1808     case 0x0094:   // Reserved (n Bytes)
1809     case 0x0095:   // Reserved (n Bytes)
1810     case 0x0096:   // Reserved (n Bytes)
1811     case 0x0097:   // Reserved (n Bytes)
1812         pPict->ReadUInt16( nUSHORT ); nDataSize=2+nUSHORT;
1813         break;
1814 
1815     case 0x0098: { // PackBitsRect
1816         BitmapEx aBmp;
1817         tools::Rectangle aSrcRect, aDestRect;
1818         nDataSize=ReadPixMapEtc(aBmp, false, true, &aSrcRect, &aDestRect, true, false);
1819         DrawingMethod( PictDrawingMethod::PAINT );
1820         pVirDev->DrawBitmapEx(aDestRect.TopLeft(),aDestRect.GetSize(),aBmp);
1821         break;
1822     }
1823     case 0x0099: { // PackBitsRgn
1824         BitmapEx aBmp;
1825         tools::Rectangle aSrcRect, aDestRect;
1826         nDataSize=ReadPixMapEtc(aBmp, false, true, &aSrcRect, &aDestRect, true, true);
1827         DrawingMethod( PictDrawingMethod::PAINT );
1828         pVirDev->DrawBitmapEx(aDestRect.TopLeft(),aDestRect.GetSize(),aBmp);
1829         break;
1830     }
1831     case 0x009a: { // DirectBitsRect
1832         BitmapEx aBmp;
1833         tools::Rectangle aSrcRect, aDestRect;
1834         nDataSize=ReadPixMapEtc(aBmp, true, false, &aSrcRect, &aDestRect, true, false);
1835         DrawingMethod( PictDrawingMethod::PAINT );
1836         pVirDev->DrawBitmapEx(aDestRect.TopLeft(),aDestRect.GetSize(),aBmp);
1837         break;
1838     }
1839     case 0x009b: { // DirectBitsRgn
1840         BitmapEx aBmp;
1841         tools::Rectangle aSrcRect, aDestRect;
1842         nDataSize=ReadPixMapEtc(aBmp, true, false, &aSrcRect, &aDestRect, true, true);
1843         DrawingMethod( PictDrawingMethod::PAINT );
1844         pVirDev->DrawBitmapEx(aDestRect.TopLeft(),aDestRect.GetSize(),aBmp);
1845         break;
1846     }
1847     case 0x009c:   // Reserved (n Bytes)
1848     case 0x009d:   // Reserved (n Bytes)
1849     case 0x009e:   // Reserved (n Bytes)
1850     case 0x009f:   // Reserved (n Bytes)
1851         pPict->ReadUInt16( nUSHORT ); nDataSize=2+nUSHORT;
1852         break;
1853 
1854     case 0x00a0:   // ShortComment
1855         nDataSize=2;
1856         break;
1857 
1858     case 0x00a1:   // LongComment
1859         pPict->SeekRel(2); pPict->ReadUInt16( nUSHORT ); nDataSize=4+nUSHORT;
1860         break;
1861 
1862     default: // 0x00a2 bis 0xffff (most times reserved)
1863         if      (nOpcode<=0x00af) { pPict->ReadUInt16( nUSHORT ); nDataSize=2+nUSHORT; }
1864         else if (nOpcode<=0x00cf) { nDataSize=0; }
1865         else if (nOpcode<=0x00fe) { sal_uInt32 nTemp; pPict->ReadUInt32( nTemp ) ; nDataSize = nTemp; nDataSize+=4; }
1866         // Osnola: checkme: in the Quickdraw Ref examples ( for pict v2)
1867         //         0x00ff(EndOfPict) is also not followed by any data...
1868         else if (nOpcode==0x00ff) { nDataSize=IsVersion2 ? 2 : 0; } // OpEndPic
1869         else if (nOpcode<=0x01ff) { nDataSize=2; }
1870         else if (nOpcode<=0x0bfe) { nDataSize=4; }
1871         else if (nOpcode<=0x0bff) { nDataSize=22; }
1872         else if (nOpcode==0x0c00) { nDataSize=24; } // HeaderOp
1873         else if (nOpcode<=0x7eff) { nDataSize=24; }
1874         else if (nOpcode<=0x7fff) { nDataSize=254; }
1875         else if (nOpcode<=0x80ff) { nDataSize=0; }
1876         else                      { sal_uInt32 nTemp; pPict->ReadUInt32( nTemp ) ; nDataSize = nTemp; nDataSize+=4; }
1877     }
1878 
1879     if (nDataSize==0xffffffff) {
1880         pPict->SetError(SVSTREAM_FILEFORMAT_ERROR);
1881         return 0;
1882     }
1883     return nDataSize;
1884 }
1885 
ReadPict(SvStream & rStreamPict,GDIMetaFile & rGDIMetaFile)1886 void PictReader::ReadPict( SvStream & rStreamPict, GDIMetaFile & rGDIMetaFile )
1887 {
1888     try {
1889     sal_uInt16          nOpcode;
1890     sal_uInt8           nOneByteOpcode;
1891     sal_uLong           nSize;
1892 
1893     pPict               = &rStreamPict;
1894     nOrigPos            = pPict->Tell();
1895     SvStreamEndian nOrigNumberFormat = pPict->GetEndian();
1896 
1897     aActForeColor       = COL_BLACK;
1898     aActBackColor       = COL_WHITE;
1899     nActPenSize         = Size(1,1);
1900     eActROP             = RasterOp::OverPaint;
1901     eActMethod          = PictDrawingMethod::UNDEFINED;
1902     aActOvalSize        = Size(1,1);
1903 
1904     aActFont.SetCharSet( GetTextEncoding());
1905     aActFont.SetFamily(FAMILY_SWISS);
1906     aActFont.SetFontSize(Size(0,12));
1907     aActFont.SetAlignment(ALIGN_BASELINE);
1908 
1909     aHRes = aVRes = Fraction( 1, 1 );
1910 
1911     pVirDev = VclPtr<VirtualDevice>::Create();
1912     pVirDev->EnableOutput(false);
1913     rGDIMetaFile.Record(pVirDev);
1914 
1915     pPict->SetEndian(SvStreamEndian::BIG);
1916 
1917     ReadHeader();
1918 
1919     aPenPosition=Point(-aBoundingRect.Left(),-aBoundingRect.Top());
1920     aTextPosition=aPenPosition;
1921 
1922     sal_uInt64 nPos=pPict->Tell();
1923 
1924     for (;;) {
1925 
1926         if (IsVersion2 )
1927             pPict->ReadUInt16( nOpcode );
1928         else
1929         {
1930             pPict->ReadUChar( nOneByteOpcode );
1931             nOpcode=static_cast<sal_uInt16>(nOneByteOpcode);
1932         }
1933 
1934         if (pPict->GetError())
1935             break;
1936 
1937         if (pPict->eof())
1938         {
1939             pPict->SetError(SVSTREAM_FILEFORMAT_ERROR);
1940             break;
1941         }
1942 
1943         if (nOpcode==0x00ff)
1944             break;
1945 
1946         nSize=ReadData(nOpcode);
1947 
1948         if ( IsVersion2 )
1949         {
1950             if ( nSize & 1 )
1951                 nSize++;
1952 
1953             nPos+=2+nSize;
1954         }
1955         else
1956             nPos+=1+nSize;
1957 
1958         pPict->Seek(nPos);
1959     }
1960 
1961     pVirDev->SetClipRegion();
1962     rGDIMetaFile.Stop();
1963     pVirDev.disposeAndClear();
1964 
1965     rGDIMetaFile.SetPrefMapMode( MapMode( MapUnit::MapInch, Point(), aHRes, aVRes ) );
1966     rGDIMetaFile.SetPrefSize( aBoundingRect.GetSize() );
1967 
1968     pPict->SetEndian(nOrigNumberFormat);
1969 
1970     if (pPict->GetError()) pPict->Seek(nOrigPos);
1971     } catch (...)
1972     {
1973         rStreamPict.SetError(SVSTREAM_FILEFORMAT_ERROR);
1974     }
1975 }
1976 
1977 namespace pict {
1978 
ReadPictFile(SvStream & rStreamPict,GDIMetaFile & rGDIMetaFile)1979 void ReadPictFile(SvStream &rStreamPict, GDIMetaFile& rGDIMetaFile)
1980 {
1981     PictReader aPictReader;
1982     aPictReader.ReadPict(rStreamPict, rGDIMetaFile);
1983 }
1984 
1985 }
1986 
1987 //================== GraphicImport - the exported function ================
1988 
1989 extern "C" SAL_DLLPUBLIC_EXPORT bool
iptGraphicImport(SvStream & rIStm,Graphic & rGraphic,FilterConfigItem *)1990 iptGraphicImport( SvStream& rIStm, Graphic & rGraphic, FilterConfigItem* )
1991 {
1992     GDIMetaFile aMTF;
1993     bool        bRet = false;
1994 
1995     pict::ReadPictFile( rIStm, aMTF );
1996 
1997     if ( !rIStm.GetError() )
1998     {
1999         rGraphic = Graphic( aMTF );
2000         bRet = true;
2001     }
2002 
2003     return bRet;
2004 }
2005 
2006 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2007