build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / filter / ixbm / xbmread.cxx
blob6c6438eb88fc66ac3a235b83d62b33263893711f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <ctype.h>
21 #include <comphelper/string.hxx>
22 #include "xbmread.hxx"
24 enum XBMFormat
26 XBM10,
27 XBM11
30 enum ReadState
32 XBMREAD_OK,
33 XBMREAD_ERROR,
34 XBMREAD_NEED_MORE
37 class XBMReader : public GraphicReader
39 SvStream& rIStm;
40 Bitmap aBmp1;
41 Bitmap::ScopedWriteAccess pAcc1;
42 std::unique_ptr<short[]>
43 pHexTable;
44 BitmapColor aWhite;
45 BitmapColor aBlack;
46 long nLastPos;
47 long nWidth;
48 long nHeight;
49 bool bStatus;
51 void InitTable();
52 OString FindTokenLine( SvStream* pInStm, const char* pTok1, const char* pTok2 );
53 long ParseDefine( const sal_Char* pDefine );
54 bool ParseData( SvStream* pInStm, const OString& aLastLine, XBMFormat eFormat );
56 public:
58 explicit XBMReader( SvStream& rStm );
60 ReadState ReadXBM( Graphic& rGraphic );
63 XBMReader::XBMReader( SvStream& rStm ) :
64 rIStm ( rStm ),
65 nLastPos ( rStm.Tell() ),
66 nWidth ( 0 ),
67 nHeight ( 0 ),
68 bStatus ( true )
70 pHexTable.reset( new short[ 256 ] );
71 maUpperName = "SVIXBM";
72 InitTable();
75 void XBMReader::InitTable()
77 memset( pHexTable.get(), 0, sizeof( short ) * 256 );
79 pHexTable[(int)'0'] = 0;
80 pHexTable[(int)'1'] = 1;
81 pHexTable[(int)'2'] = 2;
82 pHexTable[(int)'3'] = 3;
83 pHexTable[(int)'4'] = 4;
84 pHexTable[(int)'5'] = 5;
85 pHexTable[(int)'6'] = 6;
86 pHexTable[(int)'7'] = 7;
87 pHexTable[(int)'8'] = 8;
88 pHexTable[(int)'9'] = 9;
89 pHexTable[(int)'A'] = 10;
90 pHexTable[(int)'B'] = 11;
91 pHexTable[(int)'C'] = 12;
92 pHexTable[(int)'D'] = 13;
93 pHexTable[(int)'E'] = 14;
94 pHexTable[(int)'F'] = 15;
95 pHexTable[(int)'X'] = 0;
96 pHexTable[(int)'a'] = 10;
97 pHexTable[(int)'b'] = 11;
98 pHexTable[(int)'c'] = 12;
99 pHexTable[(int)'d'] = 13;
100 pHexTable[(int)'e'] = 14;
101 pHexTable[(int)'f'] = 15;
102 pHexTable[(int)'x'] = 0;
103 pHexTable[(int)' '] = -1;
104 pHexTable[(int)','] = -1;
105 pHexTable[(int)'}'] = -1;
106 pHexTable[(int)'\n'] = -1;
107 pHexTable[(int)'\t'] = -1;
108 pHexTable[(int)'\0'] = -1;
111 OString XBMReader::FindTokenLine( SvStream* pInStm, const char* pTok1,
112 const char* pTok2 )
114 OString aRet;
115 sal_Int32 nPos1, nPos2;
117 bStatus = false;
121 if( !pInStm->ReadLine( aRet ) )
122 break;
124 if( pTok1 )
126 if( ( nPos1 = aRet.indexOf( pTok1 ) ) != -1 )
128 bStatus = true;
130 if( pTok2 )
132 bStatus = false;
134 if( ( ( nPos2 = aRet.indexOf( pTok2 ) ) != -1 ) &&
135 ( nPos2 > nPos1 ) )
137 bStatus = true;
143 while( !bStatus );
145 return aRet;
148 long XBMReader::ParseDefine( const sal_Char* pDefine )
150 long nRet = 0;
151 char* pTmp = const_cast<char*>(pDefine);
152 unsigned char cTmp;
154 // move to end
155 pTmp += ( strlen( pDefine ) - 1 );
156 cTmp = *pTmp--;
158 // search last digit
159 while (pHexTable[ cTmp ] == -1 && pTmp >= pDefine)
160 cTmp = *pTmp--;
162 // move before number
163 while (pHexTable[ cTmp ] != -1 && pTmp >= pDefine)
164 cTmp = *pTmp--;
166 // move to start of number
167 pTmp += 2;
169 // read Hex
170 if( ( pTmp[0] == '0' ) && ( ( pTmp[1] == 'X' ) || ( pTmp[1] == 'x' ) ) )
172 pTmp += 2;
173 cTmp = *pTmp++;
175 while ( pHexTable[ cTmp ] != -1 )
177 nRet = ( nRet << 4 ) + pHexTable[ cTmp ];
178 cTmp = *pTmp++;
181 // read decimal
182 else
184 cTmp = *pTmp++;
185 while( ( cTmp >= '0' ) && ( cTmp <= '9' ) )
187 nRet = nRet * 10 + ( cTmp - '0' );
188 cTmp = *pTmp++;
192 return nRet;
195 bool XBMReader::ParseData( SvStream* pInStm, const OString& aLastLine, XBMFormat eFormat )
197 OString aLine;
198 long nRow = 0;
199 long nCol = 0;
200 long nBits = ( eFormat == XBM10 ) ? 16 : 8;
201 long nBit;
202 sal_uInt16 nValue;
203 sal_uInt16 nDigits;
204 bool bFirstLine = true;
206 while( nRow < nHeight )
208 if( bFirstLine )
210 sal_Int32 nPos;
212 // delete opening curly bracket
213 if( (nPos = ( aLine = aLastLine ).indexOf('{') ) != -1 )
214 aLine = aLine.copy(nPos + 1);
216 bFirstLine = false;
218 else if( !pInStm->ReadLine( aLine ) )
219 break;
221 if (!aLine.isEmpty())
223 const sal_Int32 nCount = comphelper::string::getTokenCount(aLine, ',');
225 for( sal_Int32 i = 0; ( i < nCount ) && ( nRow < nHeight ); ++i )
227 const OString aToken(aLine.getToken(i, ','));
228 const sal_Int32 nLen = aToken.getLength();
229 bool bProcessed = false;
231 nBit = nDigits = nValue = 0;
233 for (sal_Int32 n = 0; n < nLen; ++n)
235 const unsigned char cChar = aToken[n];
236 const short nTable = pHexTable[ cChar ];
238 if( isxdigit( cChar ) || !nTable )
240 nValue = ( nValue << 4 ) + nTable;
241 nDigits++;
242 bProcessed = true;
244 else if( ( nTable < 0 ) && nDigits )
246 bProcessed = true;
247 break;
251 if( bProcessed )
253 while( ( nCol < nWidth ) && ( nBit < nBits ) )
254 pAcc1->SetPixel( nRow, nCol++, ( nValue & ( 1 << nBit++ ) ) ? aBlack : aWhite );
256 if( nCol == nWidth )
258 nCol = 0;
259 nRow++;
266 return true;
269 ReadState XBMReader::ReadXBM( Graphic& rGraphic )
271 ReadState eReadState;
272 sal_uInt8 cDummy;
274 // check if we can read ALL
275 rIStm.Seek( STREAM_SEEK_TO_END );
276 rIStm.ReadUChar( cDummy );
278 // if we cannot read all
279 // we return and wait for new data
280 if ( rIStm.GetError() != ERRCODE_IO_PENDING )
282 rIStm.Seek( nLastPos );
283 bStatus = false;
284 OString aLine = FindTokenLine( &rIStm, "#define", "_width" );
286 if ( bStatus )
288 int nValue;
289 if ( ( nValue = (int) ParseDefine( aLine.getStr() ) ) > 0 )
291 nWidth = nValue;
292 aLine = FindTokenLine( &rIStm, "#define", "_height" );
294 // if height was not received, we search again
295 // from start of the file
296 if ( !bStatus )
298 rIStm.Seek( nLastPos );
299 aLine = FindTokenLine( &rIStm, "#define", "_height" );
302 else
303 bStatus = false;
305 if ( bStatus )
307 if ( ( nValue = (int) ParseDefine( aLine.getStr() ) ) > 0 )
309 nHeight = nValue;
310 aLine = FindTokenLine( &rIStm, "static", "_bits" );
312 if ( bStatus )
314 XBMFormat eFormat = XBM10;
316 if (aLine.indexOf("short") != -1)
317 eFormat = XBM10;
318 else if (aLine.indexOf("char") != -1)
319 eFormat = XBM11;
320 else
321 bStatus = false;
323 if ( bStatus && nWidth && nHeight )
325 aBmp1 = Bitmap( Size( nWidth, nHeight ), 1 );
326 pAcc1 = Bitmap::ScopedWriteAccess(aBmp1);
328 if( pAcc1 )
330 aWhite = pAcc1->GetBestMatchingColor( Color( COL_WHITE ) );
331 aBlack = pAcc1->GetBestMatchingColor( Color( COL_BLACK ) );
332 bStatus = ParseData( &rIStm, aLine, eFormat );
334 else
335 bStatus = false;
342 if (bStatus && pAcc1)
344 Bitmap aBlackBmp( Size( pAcc1->Width(), pAcc1->Height() ), 1 );
346 pAcc1.reset();
347 aBlackBmp.Erase( Color( COL_BLACK ) );
348 rGraphic = BitmapEx( aBlackBmp, aBmp1 );
349 eReadState = XBMREAD_OK;
351 else
352 eReadState = XBMREAD_ERROR;
354 else
356 rIStm.ResetError();
357 eReadState = XBMREAD_NEED_MORE;
360 return eReadState;
363 VCL_DLLPUBLIC bool ImportXBM( SvStream& rStm, Graphic& rGraphic )
365 std::shared_ptr<GraphicReader> pContext = rGraphic.GetContext();
366 rGraphic.SetContext(nullptr);
367 XBMReader* pXBMReader = dynamic_cast<XBMReader*>( pContext.get() );
368 if (!pXBMReader)
370 pContext = std::make_shared<XBMReader>( rStm );
371 pXBMReader = static_cast<XBMReader*>( pContext.get() );
374 bool bRet = true;
376 ReadState eReadState = pXBMReader->ReadXBM( rGraphic );
378 if( eReadState == XBMREAD_ERROR )
380 bRet = false;
382 else if( eReadState == XBMREAD_NEED_MORE )
383 rGraphic.SetContext( pContext );
385 return bRet;
388 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */