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