34#define XPMTEMPBUFSIZE 0x00008000
35#define XPMSTRINGBUF 0x00008000
37#define XPMIDENTIFIER 0x00000001
38#define XPMDEFINITION 0x00000002
39#define XPMVALUES 0x00000003
40#define XPMCOLORS 0x00000004
41#define XPMPIXELS 0x00000005
42#define XPMEXTENSIONS 0x00000006
43#define XPMENDEXT 0x00000007
45#define XPMREMARK 0x00000001
46#define XPMDOUBLE 0x00000002
47#define XPMSTRING 0x00000004
48#define XPMFINISHED 0x00000008
94 typedef std::array<sal_uInt8,4> colordata;
95 typedef std::map<OString, colordata> colormap;
102 bool ImplGetString();
105 bool ImplGetColSub(colordata &rDest);
107 void ImplGetRGBHex(colordata &rDest,
sal_uLong);
113 explicit XPMReader(
SvStream& rStm );
122 , mnLastPos(rStm.Tell())
127 , mbTransparent(false)
137 , mpStringBuf(nullptr)
149 mrIStm.Seek( STREAM_SEEK_TO_END );
150 mrIStm.ReadUChar( cDummy );
154 if ( mrIStm.GetError() != ERRCODE_IO_PENDING )
156 mrIStm.Seek( mnLastPos );
164 mbStatus = ImplGetString();
170 mnColors = ImplGetULONG( 2 );
171 mnCpp = ImplGetULONG( 3 );
173 if ( mnColors > ( SAL_MAX_UINT32 / ( 4 + mnCpp ) ) )
179 if (mrIStm.remainingSize() + mnTempAvail <
static_cast<sal_uInt64
>(mnWidth) * mnHeight)
181 if ( mbStatus && mnWidth && mnHeight && mnColors && mnCpp )
198 if ( mnColors > 256 )
203 maBmp =
Bitmap(
Size(mnWidth, mnHeight), ePixelFormat);
214 if( mpAcc && mbStatus )
219 for (
auto& elem : maColMap)
221 mpAcc->SetPaletteColor(i,
Color(elem.second[1], elem.second[2], elem.second[3]));
232 if ( !ImplGetScanLine( i ) )
243 delete[] mpStringBuf;
259 eReadState = XPMREAD_OK;
266 eReadState = XPMREAD_ERROR;
272 eReadState = XPMREAD_NEED_MORE;
279bool XPMReader::ImplGetColor()
282 if (!ImplGetString())
285 if (mnStringSize < mnCpp)
288 OString aKey(
reinterpret_cast<char*
>(pString), mnCpp);
290 bool bStatus = ImplGetColSub(aValue);
293 maColMap[aKey] = aValue;
300bool XPMReader::ImplGetScanLine(
sal_uLong nY )
302 bool bStatus = ImplGetString();
311 aWhite = mpMaskAcc->GetBestMatchingColor( COL_WHITE );
312 aBlack = mpMaskAcc->GetBestMatchingColor( COL_BLACK );
314 if ( mnStringSize != ( mnWidth * mnCpp ))
318 Scanline pScanline = mpAcc->GetScanline(nY);
319 Scanline pMaskScanline = mpMaskAcc ? mpMaskAcc->GetScanline(nY) :
nullptr;
322 OString aKey(
reinterpret_cast<char*
>(pString), mnCpp);
323 auto it = maColMap.find(aKey);
324 if (it != maColMap.end())
327 mpAcc->SetPixelOnData(pScanline, i,
Color(it->second[1], it->second[2], it->second[3]));
329 mpAcc->SetPixelOnData(pScanline, i,
BitmapColor(it->second[1]));
331 mpMaskAcc->SetPixelOnData(pMaskScanline, i, it->second[0] ? aWhite : aBlack);
344bool XPMReader::ImplGetColSub(colordata &rDest)
346 unsigned char cTransparent[] =
"None";
348 bool bColStatus =
false;
350 if ( ImplGetColKey(
'c' ) || ImplGetColKey(
'm' ) || ImplGetColKey(
'g' ) )
357 switch ( mnParaSize )
360 ImplGetRGBHex(rDest, 6);
363 ImplGetRGBHex(rDest, 2);
366 ImplGetRGBHex(rDest, 0);
374 else if ( ImplCompare( &cTransparent[0], mpPara, 4 ))
378 mbTransparent =
true;
381 else if ( mnParaSize > 2 )
388 if ( std::strlen(
pRGBTable[i].name) > mnParaSize &&
391 if ( ImplCompare (
reinterpret_cast<unsigned char const *
>(
pRGBTable[ i ].name),
392 mpPara, mnParaSize ) )
412bool XPMReader::ImplGetColKey(
sal_uInt8 nKey )
416 if (mnStringSize < mnCpp + 1)
419 mpPara = mpStringBuf + mnCpp + 1;
422 while ( *mpPara != 0 )
424 if ( *mpPara == nKey )
426 nTemp = *( mpPara + 1 );
427 if ( nTemp ==
' ' || nTemp == 0x09 )
429 if ( nPrev ==
' ' || nPrev == 0x09 )
439 while ( (*mpPara ==
' ') || (*mpPara == 0x09) )
445 while ( *(mpPara+mnParaSize) !=
' ' && *(mpPara+mnParaSize) != 0x09 &&
446 *(mpPara+mnParaSize) != 0 )
452 return mnParaSize != 0;
462void XPMReader::ImplGetRGBHex(colordata &rDest,
sal_uLong nAdd)
470 nHex = ((nHex -
'A' +
'0') & 7) + 10;
474 nTemp = ((nTemp -
'A' +
'0') & 7) + 10;
475 nHex = ( nHex << 4 ) + nTemp;
486 if ( ImplGetPara ( nPara ) )
491 if ( ( mnParaSize > 6 ) || ( mnParaSize == 0 ) )
return 0;
495 if ( j > 9 )
return 0;
508 if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
521bool XPMReader::ImplGetPara (
sal_uLong nNumb )
528 if ( ( *pPtr !=
' ' ) && ( *pPtr != 0x09 ) )
540 while ( nSize < mnStringSize )
546 if ( ( nByte ==
' ' ) || ( nByte == 0x09 ) )
548 if ( nCount == nNumb )
558 if ( ( nByte !=
' ' ) && ( nByte != 0x09 ) )
568 return ( ( nCount == nNumb ) && mpPara );
575bool XPMReader::ImplGetString()
585 if ( mnTempAvail == 0 )
588 if ( mnTempAvail == 0 )
591 mpTempPtr = mpTempBuf;
595 if ( mnTempAvail <= 50 )
600 for (
int i = 0;
i < 9;
i++ )
601 if ( *mpTempPtr++ != sID[i] )
610 mcLastByte = mcThisByte;
611 mcThisByte = *mpTempPtr++;
616 if ( mcThisByte == 0x0a )
617 mnStatus &=~XPMDOUBLE;
622 if ( ( mcThisByte ==
'/' ) && ( mcLastByte ==
'*' ) )
623 mnStatus &=~XPMREMARK;
628 if ( mcThisByte ==
'"' )
630 mnStatus &=~XPMSTRING;
638 *pString++ = mcThisByte;
645 switch ( mcThisByte )
648 if ( mcLastByte ==
'/' ) mnStatus |=
XPMREMARK;
651 if ( mcLastByte ==
'/' ) mnStatus |=
XPMDOUBLE;
674 XPMReader* pXPMReader =
dynamic_cast<XPMReader*
>( pContext.get() );
677 pContext = std::make_shared<XPMReader>( rStm );
678 pXPMReader =
static_cast<XPMReader*
>( pContext.get() );
683 ReadState eReadState = pXPMReader->ReadXPM( rGraphic );
685 if( eReadState == XPMREAD_ERROR )
689 else if( eReadState == XPMREAD_NEED_MORE )
vcl::ScopedBitmapAccess< BitmapWriteAccess, Bitmap, &Bitmap::AcquireWriteAccess > BitmapScopedWriteAccess
static const BitmapPalette & GetGreyPalette(int nEntries)
void SetReaderContext(const std::shared_ptr< GraphicReader > &pReader)
std::shared_ptr< GraphicReader > & GetReaderContext()
This template handles BitmapAccess the RAII way.
const XPMRGBTab pRGBTable[]
VCL_DLLPUBLIC bool ImportXPM(SvStream &rStm, Graphic &rGraphic)