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