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];
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
224  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 
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 
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 ==============================
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 
351 void PictReader::SetLineColor( const Color& rColor )
352 {
353  pVirDev->SetLineColor( rColor );
354 }
355 
356 void PictReader::SetFillColor( const Color& rColor )
357 {
358  pVirDev->SetFillColor( rColor );
359 }
360 
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 
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 
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 
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 
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 
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 
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 
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 
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");
460  rRect = tools::Rectangle();
461  return;
462  }
463  rRect=tools::Rectangle(aTopLeft,aBottomRight);
464 
465  SAL_INFO("filter.pict", "ReadRectangle: " << rRect);
466 }
467 
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 
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 
526 sal_uInt8 PictReader::ReadAndDrawRect(PictDrawingMethod eMethod)
527 {
528  ReadRectangle(aLastRect);
529  ReadAndDrawSameRect(eMethod);
530  return 8;
531 }
532 
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 
541 sal_uInt8 PictReader::ReadAndDrawRoundRect(PictDrawingMethod eMethod)
542 {
543  ReadRectangle(aLastRoundRect);
544  ReadAndDrawSameRoundRect(eMethod);
545  return 8;
546 }
547 
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 
556 sal_uInt8 PictReader::ReadAndDrawOval(PictDrawingMethod eMethod)
557 {
558  ReadRectangle(aLastOval);
559  ReadAndDrawSameOval(eMethod);
560  return 8;
561 }
562 
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 
571 sal_uInt64 PictReader::ReadAndDrawPolygon(PictDrawingMethod eMethod)
572 {
573  sal_uInt64 nDataSize;
574  nDataSize=ReadPolygon(aLastPolygon);
575  ReadAndDrawSamePolygon(eMethod);
576  return nDataSize;
577 }
578 
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 
588 sal_uInt8 PictReader::ReadAndDrawArc(PictDrawingMethod eMethod)
589 {
590  ReadRectangle(aLastArcRect);
591  ReadAndDrawSameArc(eMethod);
592  return 12;
593 }
594 
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 
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 
638 sal_uInt8 PictReader::ReadAndDrawSameRgn(PictDrawingMethod eMethod)
639 {
640  if (IsInvisible(eMethod)) return 0;
641  DrawingMethod(eMethod);
642  // DISPLAY: ...???...
643  return 0;
644 }
645 
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));
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));
686  break;
687  case PictDrawingMethod::TEXT:
688  aActFont.SetColor(aActForeColor);
689  aActFont.SetFillColor(aActBackColor);
690  aActFont.SetTransparent(true);
691  pVirDev->SetFont(aActFont);
693  break;
694  default:
695  break; // -Wall undefined not handled...
696  }
697  eActMethod=eMethod;
698 }
699 
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 
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 
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  }
1280 }
1281 
1282 #if OSL_DEBUG_LEVEL > 0
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 
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) {
1891  return 0;
1892  }
1893  return nDataSize;
1894 }
1895 
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  {
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  {
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 
1991 void ReadPictFile(SvStream &rStreamPict, GDIMetaFile& rGDIMetaFile)
1992 {
1993  PictReader aPictReader;
1994  aPictReader.ReadPict(rStreamPict, rGDIMetaFile);
1995 }
1996 
1997 //================== GraphicImport - the exported function ================
1998 
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: */
void SetFamily(FontFamily)
Definition: font/font.cxx:131
void EnableOutput(bool bEnable=true)
Point TopLeft() const
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, MetricVector *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
Definition: text.cxx:791
SvStream & ReadInt16(sal_Int16 &rInt16)
UNDEFINED
void SetFillColor(const Color &)
Definition: font/font.cxx:96
void SetFontSize(const Size &)
Definition: font/font.cxx:125
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
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
This is an overloaded member function, provided for convenience. It differs from the above function o...
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:176
void SetWeight(FontWeight)
Definition: font/font.cxx:223
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:241
sal_uInt64 Seek(sal_uInt64 nPos)
ERASE
void SetSize(sal_uInt16 nNewSize)
BitmapEx CreateFromData(sal_uInt8 const *pData, sal_Int32 nWidth, sal_Int32 nHeight, sal_Int32 nStride, vcl::PixelFormat ePixelFormat)
Copy block of image data into the bitmap.
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:137
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)
enum PenStyle penStyle
Definition: ipict.cxx:78
sal_uInt64 SeekRel(sal_Int64 nPos)
tools::Long getHeight() const
ErrCode GetError() const
void Record(OutputDevice *pOutDev)
Definition: gdimtf.cxx:312
tools::Long Left() const
bool eof() const
RasterOp
Definition: vclenum.hxx:192
void ReadPictFile(SvStream &rStreamPict, GDIMetaFile &rGDIMetaFile)
Function to access PictReader::ReadPict for unit testing.
Definition: ipict.cxx:1991
int nCount
void SetUnderline(FontLineStyle)
Definition: font/font.cxx:253
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:247
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
void SetAlignment(FontAlign)
Definition: font/font.cxx:109
void SetLineColor()
bool checkSeek(SvStream &rSt, sal_uInt64 nOffset)
void SetFamilyName(const OUString &rFamilyName)
Definition: font/font.cxx:115
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()
PenStyle
Definition: ios2met.cxx:40
void SetError(ErrCode nErrorCode)
static BitmapColor getColor(BitmapReadAccess *pReadAcc, tools::Long nZ)
SvStream & ReadUChar(unsigned char &rChar)
sal_Int16 nVersion
tools::Long Top() const
Intended to be used to feed into CreateFromData to create a BitmapEx.
Definition: RawBitmap.hxx:21
short nBitCount
Definition: ipict.cxx:80
Size GetSize() const
void SetColor(const Color &)
Definition: font/font.cxx:88
Reference< XOutputStream > stream
SvStream & ReadInt32(sal_Int32 &rInt32)
std::size_t ReadBytes(void *pData, std::size_t nSize)
PictDrawingMethod
Definition: ipict.cxx:146
sal_uInt8 GetGreen() const
SvStreamEndian GetEndian() const
void Stop()
Definition: gdimtf.cxx:538
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTCYAN
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)
static const char * operationName(sal_uInt16 nOpcode)
Definition: ipict.cxx:1283
void SetTransparent(bool bTransparent)
Definition: font/font.cxx:103
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)
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
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_YELLOW
bool good() const
void SetItalic(FontItalic)
Definition: font/font.cxx:235
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:1999
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:272
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:43
TEXT
rtl_TextEncoding GetCharSet() const
Definition: font/font.cxx:836
bool isColor
Definition: ipict.cxx:82
void setHeight(tools::Long n)
sal_uInt16 nPos
void SetPrefMapMode(const MapMode &rMapMode)
Definition: gdimtf.hxx:179