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