LibreOffice Module vcl (master)  1
xpmread.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 <bitmapwriteaccess.hxx>
21 #include <vcl/graph.hxx>
22 #include <tools/stream.hxx>
23 #include "rgbtable.hxx"
24 #include "xpmread.hxx"
25 #include <cstring>
26 #include <array>
27 #include <map>
28 
29 #define XPMTEMPBUFSIZE 0x00008000
30 #define XPMSTRINGBUF 0x00008000
31 
32 #define XPMIDENTIFIER 0x00000001 // mnIdentifier includes one of the six phases
33 #define XPMDEFINITION 0x00000002 // the XPM format consists of
34 #define XPMVALUES 0x00000003
35 #define XPMCOLORS 0x00000004
36 #define XPMPIXELS 0x00000005
37 #define XPMEXTENSIONS 0x00000006
38 #define XPMENDEXT 0x00000007
39 
40 #define XPMREMARK 0x00000001 // defines used by mnStatus
41 #define XPMDOUBLE 0x00000002
42 #define XPMSTRING 0x00000004
43 #define XPMFINISHED 0x00000008
44 
46 {
50 };
51 
52 class BitmapWriteAccess;
53 class Graphic;
54 
55 class XPMReader : public GraphicReader
56 {
57 private:
58 
64  long const mnLastPos;
65 
69  sal_uInt32 mnCpp; // characters per pix
71  bool mbStatus;
79  // each key is ( mnCpp )Byte(s)-> ASCII entry assigned to the colour
80  // each colordata is
81  // 1 Byte -> 0xFF if colour is transparent
82  // 3 Bytes -> RGB value of the colour
83  typedef std::array<sal_uInt8,4> colordata;
84  typedef std::map<OString, colordata> colormap;
85  colormap maColMap;
90 
91  bool ImplGetString();
92  bool ImplGetColor();
93  bool ImplGetScanLine( sal_uLong );
94  bool ImplGetColSub(colordata &rDest);
95  bool ImplGetColKey( sal_uInt8 );
96  void ImplGetRGBHex(colordata &rDest, sal_uLong);
97  bool ImplGetPara( sal_uLong numb );
98  static bool ImplCompare(sal_uInt8 const *, sal_uInt8 const *, sal_uLong);
100 
101 public:
102  explicit XPMReader( SvStream& rStm );
103 
104  ReadState ReadXPM( Graphic& rGraphic );
105 };
106 
108  : mrIStm(rStm)
109  , mnLastPos(rStm.Tell())
110  , mnWidth(0)
111  , mnHeight(0)
112  , mnColors(0)
113  , mnCpp(0)
114  , mbTransparent(false)
115  , mbStatus(true)
116  , mnStatus( 0 )
117  , mnIdentifier(XPMIDENTIFIER)
118  , mcThisByte(0)
119  , mcLastByte(0)
120  , mnTempAvail(0)
121  , mpTempBuf(nullptr)
122  , mpTempPtr(nullptr)
123  , mnStringSize(0)
124  , mpStringBuf(nullptr)
125  , mnParaSize(0)
126  , mpPara(nullptr)
127 {
128 }
129 
131 {
132  ReadState eReadState;
133  sal_uInt8 cDummy;
134 
135  // check if we can real ALL
137  mrIStm.ReadUChar( cDummy );
138 
139  // if we could not read all
140  // return and wait for new data
142  {
143  mrIStm.Seek( mnLastPos );
144  mbStatus = true;
145 
146  if ( mbStatus )
147  {
150 
152  if ( mbStatus )
153  {
154  mnIdentifier = XPMVALUES; // fetch Bitmap information
155  mnWidth = ImplGetULONG( 0 );
156  mnHeight = ImplGetULONG( 1 );
157  mnColors = ImplGetULONG( 2 );
158  mnCpp = ImplGetULONG( 3 );
159  }
160  if ( mnColors > ( SAL_MAX_UINT32 / ( 4 + mnCpp ) ) )
161  mbStatus = false;
162  if ( ( mnWidth * mnCpp ) >= XPMSTRINGBUF )
163  mbStatus = false;
164  //xpms are a minimum of one character (one byte) per pixel, so if the file isn't
165  //even that long, it's not all there
166  if (mrIStm.remainingSize() + mnTempAvail < static_cast<sal_uInt64>(mnWidth) * mnHeight)
167  mbStatus = false;
168  if ( mbStatus && mnWidth && mnHeight && mnColors && mnCpp )
169  {
171 
172  for (sal_uLong i = 0; i < mnColors; ++i)
173  {
174  if (!ImplGetColor())
175  {
176  mbStatus = false;
177  break;
178  }
179  }
180 
181  if ( mbStatus )
182  {
183  // create a 24bit graphic when more as 256 colours present
184  sal_uInt16 nBits = 1;
185  if ( mnColors > 256 )
186  nBits = 24;
187  else if ( mnColors > 16 )
188  nBits = 8;
189  else if ( mnColors > 2 )
190  nBits = 4;
191  else
192  nBits = 1;
193 
194  maBmp = Bitmap( Size( mnWidth, mnHeight ), nBits );
196 
197  // mbTransparent is TRUE if at least one colour is transparent
198  if ( mbTransparent )
199  {
200  maMaskBmp = Bitmap( Size( mnWidth, mnHeight ), 1 );
202  if ( !mpMaskAcc )
203  mbStatus = false;
204  }
205  if( mpAcc && mbStatus )
206  {
207  if (mnColors <= 256) // palette is only needed by using less than 257
208  { // colors
209  sal_uInt8 i = 0;
210  for (auto& elem : maColMap)
211  {
212  mpAcc->SetPaletteColor(i, Color(elem.second[1], elem.second[2], elem.second[3]));
213  //reuse map entry, overwrite color with palette index
214  elem.second[1] = i;
215  i++;
216  }
217  }
218 
219  // now we get the bitmap data
221  for (sal_uLong i = 0; i < mnHeight; ++i)
222  {
223  if ( !ImplGetScanLine( i ) )
224  {
225  mbStatus = false;
226  break;
227  }
228  }
230  }
231  }
232  }
233 
234  delete[] mpStringBuf;
235  delete[] mpTempBuf;
236 
237  }
238  if( mbStatus )
239  {
240  mpAcc.reset();
241  if ( mpMaskAcc )
242  {
243  mpMaskAcc.reset();
244  rGraphic = Graphic( BitmapEx( maBmp, maMaskBmp ) );
245  }
246  else
247  {
248  rGraphic = maBmp;
249  }
250  eReadState = XPMREAD_OK;
251  }
252  else
253  {
254  mpMaskAcc.reset();
255  mpAcc.reset();
256 
257  eReadState = XPMREAD_ERROR;
258  }
259  }
260  else
261  {
262  mrIStm.ResetError();
263  eReadState = XPMREAD_NEED_MORE;
264  }
265  return eReadState;
266 }
267 
268 // ImplGetColor returns various colour values,
269 // returns TRUE if various colours could be assigned
271 {
272  sal_uInt8* pString = mpStringBuf;
273  if (!ImplGetString())
274  return false;
275 
276  if (mnStringSize < mnCpp)
277  return false;
278 
279  OString aKey(reinterpret_cast<sal_Char*>(pString), mnCpp);
280  colordata aValue;
281  bool bStatus = ImplGetColSub(aValue);
282  if (bStatus)
283  {
284  maColMap[aKey] = aValue;
285  }
286  return bStatus;
287 }
288 
289 // ImpGetScanLine reads the string mpBufSize and writes the pixel in the
290 // Bitmap. Parameter nY is the horizontal position.
292 {
293  bool bStatus = ImplGetString();
294  sal_uInt8* pString = mpStringBuf;
295  BitmapColor aWhite;
296  BitmapColor aBlack;
297 
298  if ( bStatus )
299  {
300  if ( mpMaskAcc )
301  {
304  }
305  if ( mnStringSize != ( mnWidth * mnCpp ))
306  bStatus = false;
307  else
308  {
309  Scanline pScanline = mpAcc->GetScanline(nY);
310  Scanline pMaskScanline = mpMaskAcc ? mpMaskAcc->GetScanline(nY) : nullptr;
311  for (sal_uLong i = 0; i < mnWidth; ++i)
312  {
313  OString aKey(reinterpret_cast<sal_Char*>(pString), mnCpp);
314  auto it = maColMap.find(aKey);
315  if (it != maColMap.end())
316  {
317  if (mnColors > 256)
318  mpAcc->SetPixelOnData(pScanline, i, Color(it->second[1], it->second[2], it->second[3]));
319  else
320  mpAcc->SetPixelOnData(pScanline, i, BitmapColor(it->second[1]));
321  if (pMaskScanline)
322  mpMaskAcc->SetPixelOnData(pMaskScanline, i, it->second[0] ? aWhite : aBlack);
323  }
324  pString += mnCpp;
325  }
326  }
327  }
328  return bStatus;
329 }
330 
331 // tries to determine a colour value from mpStringBuf
332 // if a colour was found the RGB value is written a pDest[1]..pDest[2]
333 // pDest[0] contains 0xFF if the colour is transparent otherwise 0
334 
336 {
337  unsigned char cTransparent[] = "None";
338 
339  bool bColStatus = false;
340 
341  if ( ImplGetColKey( 'c' ) || ImplGetColKey( 'm' ) || ImplGetColKey( 'g' ) )
342  {
343  // hexentry for RGB or HSV color ?
344  if (*mpPara == '#')
345  {
346  rDest[0] = 0;
347  bColStatus = true;
348  switch ( mnParaSize )
349  {
350  case 25 :
351  ImplGetRGBHex(rDest, 6);
352  break;
353  case 13 :
354  ImplGetRGBHex(rDest, 2);
355  break;
356  case 7 :
357  ImplGetRGBHex(rDest, 0);
358  break;
359  default:
360  bColStatus = false;
361  break;
362  }
363  }
364  // maybe pixel is transparent
365  else if ( ImplCompare( &cTransparent[0], mpPara, 4 ))
366  {
367  rDest[0] = 0xff;
368  bColStatus = true;
369  mbTransparent = true;
370  }
371  // last we will try to get the colorname
372  else if ( mnParaSize > 2 ) // name must enlarge the minimum size
373  {
374  sal_uLong i = 0;
375  while ( true )
376  {
377  if ( pRGBTable[ i ].name == nullptr )
378  break;
379  if ( std::strlen(pRGBTable[i].name) > mnParaSize &&
380  pRGBTable[ i ].name[ mnParaSize ] == 0 )
381  {
382  if ( ImplCompare ( reinterpret_cast<unsigned char const *>(pRGBTable[ i ].name),
383  mpPara, mnParaSize ) )
384  {
385  bColStatus = true;
386  rDest[0] = 0;
387  rDest[1] = pRGBTable[i].red;
388  rDest[2] = pRGBTable[i].green;
389  rDest[3] = pRGBTable[i].blue;
390  break;
391  }
392  }
393  i++;
394  }
395  }
396  }
397  return bColStatus;
398 }
399 
400 // ImplGetColKey searches string mpStringBuf for a parameter 'nKey'
401 // and returns a boolean. (if TRUE mpPara and mnParaSize will be set)
402 
404 {
405  sal_uInt8 nTemp, nPrev = ' ';
406 
407  if (mnStringSize < mnCpp + 1)
408  return false;
409 
410  mpPara = mpStringBuf + mnCpp + 1;
411  mnParaSize = 0;
412 
413  while ( *mpPara != 0 )
414  {
415  if ( *mpPara == nKey )
416  {
417  nTemp = *( mpPara + 1 );
418  if ( nTemp == ' ' || nTemp == 0x09 )
419  {
420  if ( nPrev == ' ' || nPrev == 0x09 )
421  break;
422  }
423  }
424  nPrev = *mpPara;
425  mpPara++;
426  }
427  if ( *mpPara )
428  {
429  mpPara++;
430  while ( (*mpPara == ' ') || (*mpPara == 0x09) )
431  {
432  mpPara++;
433  }
434  if ( *mpPara != 0 )
435  {
436  while ( *(mpPara+mnParaSize) != ' ' && *(mpPara+mnParaSize) != 0x09 &&
437  *(mpPara+mnParaSize) != 0 )
438  {
439  mnParaSize++;
440  }
441  }
442  }
443  return mnParaSize != 0;
444 }
445 
446 // ImplGetRGBHex translates the ASCII-Hexadecimalvalue belonging to mpPara
447 // in a RGB value and writes this to rDest
448 // below formats should be contained in mpPara:
449 // if nAdd = 0 : '#12ab12' -> RGB = 0x12, 0xab, 0x12
450 // 2 : '#1234abcd1234' " " " "
451 // 6 : '#12345678abcdefab12345678' " " " "
452 
454 {
455  sal_uInt8* pPtr = mpPara+1;
456 
457  for (sal_uLong i = 1; i < 4; ++i)
458  {
459  sal_uInt8 nHex = (*pPtr++) - '0';
460  if ( nHex > 9 )
461  nHex = ((nHex - 'A' + '0') & 7) + 10;
462 
463  sal_uInt8 nTemp = (*pPtr++) - '0';
464  if ( nTemp > 9 )
465  nTemp = ((nTemp - 'A' + '0') & 7) + 10;
466  nHex = ( nHex << 4 ) + nTemp;
467 
468  pPtr += nAdd;
469  rDest[i] = nHex;
470  }
471 }
472 
473 // ImplGetUlong returns the value of a up to 6-digit long ASCII-decimal number.
474 
476 {
477  if ( ImplGetPara ( nPara ) )
478  {
479  sal_uLong nRetValue = 0;
480  sal_uInt8* pPtr = mpPara;
481 
482  if ( ( mnParaSize > 6 ) || ( mnParaSize == 0 ) ) return 0;
483  for ( sal_uLong i = 0; i < mnParaSize; i++ )
484  {
485  sal_uInt8 j = (*pPtr++) - 48;
486  if ( j > 9 ) return 0; // ascii is invalid
487  nRetValue*=10;
488  nRetValue+=j;
489  }
490  return nRetValue;
491  }
492  else return 0;
493 }
494 
495 bool XPMReader::ImplCompare(sal_uInt8 const * pSource, sal_uInt8 const * pDest, sal_uLong nSize)
496 {
497  for (sal_uLong i = 0; i < nSize; ++i)
498  {
499  if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
500  {
501  return false;
502  }
503  }
504  return true;
505 }
506 
507 // ImplGetPara tries to retrieve nNumb (0...x) parameters from mpStringBuf.
508 // Parameters are separated by spaces or tabs.
509 // If a parameter was found then the return value is TRUE and mpPara + mnParaSize
510 // are set.
511 
513 {
514  sal_uInt8 nByte;
515  sal_uLong nSize = 0;
516  sal_uInt8* pPtr = mpStringBuf;
517  sal_uLong nCount = 0;
518 
519  if ( ( *pPtr != ' ' ) && ( *pPtr != 0x09 ) )
520  {
521  mpPara = pPtr;
522  mnParaSize = 0;
523  nCount = 0;
524  }
525  else
526  {
527  mpPara = nullptr;
528  nCount = 0xffffffff;
529  }
530 
531  while ( nSize < mnStringSize )
532  {
533  nByte = *pPtr;
534 
535  if ( mpPara )
536  {
537  if ( ( nByte == ' ' ) || ( nByte == 0x09 ) )
538  {
539  if ( nCount == nNumb )
540  break;
541  else
542  mpPara = nullptr;
543  }
544  else
545  mnParaSize++;
546  }
547  else
548  {
549  if ( ( nByte != ' ' ) && ( nByte != 0x09 ) )
550  {
551  mpPara = pPtr;
552  mnParaSize = 1;
553  nCount++;
554  }
555  }
556  nSize++;
557  pPtr++;
558  }
559  return ( ( nCount == nNumb ) && mpPara );
560 }
561 
562 // The next string is read and stored in mpStringBuf (terminated with 0);
563 // mnStringSize contains the size of the string read.
564 // Comments like '//' and '/*...*/' are skipped.
565 
567 {
568  sal_uInt8 const sID[] = "/* XPM */";
569  sal_uInt8* pString = mpStringBuf;
570 
571  mnStringSize = 0;
572  mpStringBuf[0] = 0;
573 
574  while( mbStatus && ( mnStatus != XPMFINISHED ) )
575  {
576  if ( mnTempAvail == 0 )
577  {
579  if ( mnTempAvail == 0 )
580  break;
581 
583 
584  if ( mnIdentifier == XPMIDENTIFIER )
585  {
586  if ( mnTempAvail <= 50 )
587  {
588  mbStatus = false; // file is too short to be a correct XPM format
589  break;
590  }
591  for ( int i = 0; i < 9; i++ ) // searching for "/* XPM */"
592  if ( *mpTempPtr++ != sID[i] )
593  {
594  mbStatus = false;
595  break;
596  }
597  mnTempAvail-=9;
598  mnIdentifier++;
599  }
600  }
602  mcThisByte = *mpTempPtr++;
603  mnTempAvail--;
604 
605  if ( mnStatus & XPMDOUBLE )
606  {
607  if ( mcThisByte == 0x0a )
608  mnStatus &=~XPMDOUBLE;
609  continue;
610  }
611  if ( mnStatus & XPMREMARK )
612  {
613  if ( ( mcThisByte == '/' ) && ( mcLastByte == '*' ) )
614  mnStatus &=~XPMREMARK;
615  continue;
616  }
617  if ( mnStatus & XPMSTRING ) // characters in string
618  {
619  if ( mcThisByte == '"' )
620  {
621  mnStatus &=~XPMSTRING; // end of parameter by eol
622  break;
623  }
624  if ( mnStringSize >= ( XPMSTRINGBUF - 1 ) )
625  {
626  mbStatus = false;
627  break;
628  }
629  *pString++ = mcThisByte;
630  pString[0] = 0;
631  mnStringSize++;
632  continue;
633  }
634  else
635  { // characters beside string
636  switch ( mcThisByte )
637  {
638  case '*' :
639  if ( mcLastByte == '/' ) mnStatus |= XPMREMARK;
640  break;
641  case '/' :
642  if ( mcLastByte == '/' ) mnStatus |= XPMDOUBLE;
643  break;
644  case '"' : mnStatus |= XPMSTRING;
645  break;
646  case '{' :
647  if ( mnIdentifier == XPMDEFINITION )
648  mnIdentifier++;
649  break;
650  case '}' :
651  if ( mnIdentifier == XPMENDEXT )
653  break;
654  }
655  }
656  }
657  return mbStatus;
658 }
659 
660 
661 VCL_DLLPUBLIC bool ImportXPM( SvStream& rStm, Graphic& rGraphic )
662 {
663  std::shared_ptr<GraphicReader> pContext = rGraphic.GetContext();
664  rGraphic.SetContext(nullptr);
665  XPMReader* pXPMReader = dynamic_cast<XPMReader*>( pContext.get() );
666  if (!pXPMReader)
667  {
668  pContext = std::make_shared<XPMReader>( rStm );
669  pXPMReader = static_cast<XPMReader*>( pContext.get() );
670  }
671 
672  bool bRet = true;
673 
674  ReadState eReadState = pXPMReader->ReadXPM( rGraphic );
675 
676  if( eReadState == XPMREAD_ERROR )
677  {
678  bRet = false;
679  }
680  else if( eReadState == XPMREAD_NEED_MORE )
681  rGraphic.SetContext( pContext );
682 
683  return bRet;
684 }
685 
686 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
double mnHeight
SvStream & mrIStm
Definition: xpmread.cxx:59
bool ImplGetColKey(sal_uInt8)
Definition: xpmread.cxx:403
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
sal_uInt8 const red
Definition: rgbtable.hxx:28
Scanline GetScanline(long nY) const
sal_uLong mnHeight
Definition: xpmread.cxx:67
sal_uInt8 const green
Definition: rgbtable.hxx:29
sal_uLong mnStringSize
Definition: xpmread.cxx:86
#define XPMIDENTIFIER
Definition: xpmread.cxx:32
void SetContext(const std::shared_ptr< GraphicReader > &pReader)
Definition: graph.cxx:501
#define XPMENDEXT
Definition: xpmread.cxx:38
BitmapScopedWriteAccess mpAcc
Definition: xpmread.cxx:61
#define VCL_DLLPUBLIC
Definition: dllapi.h:29
bool ImplGetPara(sal_uLong numb)
Definition: xpmread.cxx:512
sal_uIntPtr sal_uLong
#define XPMSTRINGBUF
Definition: xpmread.cxx:30
std::array< sal_uInt8, 4 > colordata
Definition: xpmread.cxx:83
sal_uLong mnIdentifier
Definition: xpmread.cxx:73
sal_uLong mnStatus
Definition: xpmread.cxx:72
sal_uInt8 * mpTempPtr
Definition: xpmread.cxx:78
vcl::ScopedBitmapAccess< BitmapWriteAccess, Bitmap,&Bitmap::AcquireWriteAccess > BitmapScopedWriteAccess
std::shared_ptr< GraphicReader > & GetContext()
Definition: graph.cxx:496
#define STREAM_SEEK_TO_END
#define XPMDEFINITION
Definition: xpmread.cxx:33
sal_uInt64 Seek(sal_uInt64 nPos)
std::map< OString, colordata > colormap
Definition: xpmread.cxx:84
ReadState
Definition: gifread.cxx:41
static bool ImplCompare(sal_uInt8 const *, sal_uInt8 const *, sal_uLong)
Definition: xpmread.cxx:495
sal_uInt8 mcLastByte
Definition: xpmread.cxx:75
void ImplGetRGBHex(colordata &rDest, sal_uLong)
Definition: xpmread.cxx:453
sal_uInt8 * mpPara
Definition: xpmread.cxx:89
bool mbStatus
Definition: xpmread.cxx:71
#define SAL_MAX_UINT32
static const XPMRGBTab pRGBTable[]
Definition: rgbtable.hxx:33
ErrCode GetError() const
void SetPixelOnData(sal_uInt8 *pData, long nX, const BitmapColor &rBitmapColor)
VCL_DLLPUBLIC bool ImportXPM(SvStream &rStm, Graphic &rGraphic)
Definition: xpmread.cxx:661
sal_uInt64 remainingSize()
bool ImplGetScanLine(sal_uLong)
Definition: xpmread.cxx:291
sal_uInt8 * mpStringBuf
Definition: xpmread.cxx:87
sal_uLong mnWidth
Definition: xpmread.cxx:66
#define XPMEXTENSIONS
Definition: xpmread.cxx:37
sal_uLong mnParaSize
Definition: xpmread.cxx:88
sal_uLong ImplGetULONG(sal_uLong nPara)
Definition: xpmread.cxx:475
sal_uInt8 * Scanline
Definition: Scanline.hxx:25
#define XPMDOUBLE
Definition: xpmread.cxx:41
Bitmap maBmp
Definition: xpmread.cxx:60
Bitmap maMaskBmp
Definition: xpmread.cxx:62
#define XPMCOLORS
Definition: xpmread.cxx:35
int i
#define XPMFINISHED
Definition: xpmread.cxx:43
#define XPMSTRING
Definition: xpmread.cxx:42
colormap maColMap
Definition: xpmread.cxx:85
SvStream & ReadUChar(unsigned char &rChar)
sal_uLong mnTempAvail
Definition: xpmread.cxx:76
std::size_t ReadBytes(void *pData, std::size_t nSize)
#define XPMTEMPBUFSIZE
Definition: xpmread.cxx:29
#define XPMREMARK
Definition: xpmread.cxx:40
bool ImplGetString()
Definition: xpmread.cxx:566
sal_uInt8 const blue
Definition: rgbtable.hxx:30
unsigned char sal_uInt8
sal_uInt8 * mpTempBuf
Definition: xpmread.cxx:77
bool ImplGetColor()
Definition: xpmread.cxx:270
double mnWidth
BitmapScopedWriteAccess mpMaskAcc
Definition: xpmread.cxx:63
#define XPMVALUES
Definition: xpmread.cxx:34
bool ImplGetColSub(colordata &rDest)
Definition: xpmread.cxx:335
const char * name
constexpr::Color COL_WHITE(0xFF, 0xFF, 0xFF)
ReadState ReadXPM(Graphic &rGraphic)
Definition: xpmread.cxx:130
long const mnLastPos
Definition: xpmread.cxx:64
#define ERRCODE_IO_PENDING
Definition: errcode.hxx:227
sal_uInt8 mcThisByte
Definition: xpmread.cxx:74
#define XPMPIXELS
Definition: xpmread.cxx:36
virtual void ResetError()
sal_uLong mnColors
Definition: xpmread.cxx:68
XPMReader(SvStream &rStm)
Definition: xpmread.cxx:107
bool mbTransparent
Definition: xpmread.cxx:70
sal_uInt32 mnCpp
Definition: xpmread.cxx:69
BitmapColor GetBestMatchingColor(const BitmapColor &rBitmapColor)
void SetPaletteColor(sal_uInt16 nColor, const BitmapColor &rBitmapColor)