Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / source / filter / ixbm / xbmread.cxx
blob770eb3f25d820abe3fdd81fb1e1116d3bc662fc4
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 #define _XBMPRIVATE
21 #include <ctype.h>
22 #include <comphelper/string.hxx>
23 #include "xbmread.hxx"
25 XBMReader::XBMReader( SvStream& rStm ) :
26 rIStm ( rStm ),
27 pAcc1 ( NULL ),
28 nLastPos ( rStm.Tell() ),
29 nWidth ( 0 ),
30 nHeight ( 0 ),
31 bStatus ( true )
33 pHexTable = new short[ 256 ];
34 maUpperName = "SVIXBM";
35 InitTable();
38 XBMReader::~XBMReader()
40 delete[] pHexTable;
42 if( pAcc1 )
43 Bitmap::ReleaseAccess( pAcc1 );
46 void XBMReader::InitTable()
48 memset( pHexTable, 0, sizeof( short ) * 256 );
50 pHexTable[(int)'0'] = 0;
51 pHexTable[(int)'1'] = 1;
52 pHexTable[(int)'2'] = 2;
53 pHexTable[(int)'3'] = 3;
54 pHexTable[(int)'4'] = 4;
55 pHexTable[(int)'5'] = 5;
56 pHexTable[(int)'6'] = 6;
57 pHexTable[(int)'7'] = 7;
58 pHexTable[(int)'8'] = 8;
59 pHexTable[(int)'9'] = 9;
60 pHexTable[(int)'A'] = 10;
61 pHexTable[(int)'B'] = 11;
62 pHexTable[(int)'C'] = 12;
63 pHexTable[(int)'D'] = 13;
64 pHexTable[(int)'E'] = 14;
65 pHexTable[(int)'F'] = 15;
66 pHexTable[(int)'X'] = 0;
67 pHexTable[(int)'a'] = 10;
68 pHexTable[(int)'b'] = 11;
69 pHexTable[(int)'c'] = 12;
70 pHexTable[(int)'d'] = 13;
71 pHexTable[(int)'e'] = 14;
72 pHexTable[(int)'f'] = 15;
73 pHexTable[(int)'x'] = 0;
74 pHexTable[(int)' '] = -1;
75 pHexTable[(int)','] = -1;
76 pHexTable[(int)'}'] = -1;
77 pHexTable[(int)'\n'] = -1;
78 pHexTable[(int)'\t'] = -1;
79 pHexTable[(int)'\0'] = -1;
82 OString XBMReader::FindTokenLine( SvStream* pInStm, const char* pTok1,
83 const char* pTok2, const char* pTok3 )
85 OString aRet;
86 sal_Int32 nPos1, nPos2, nPos3;
88 bStatus = false;
92 if( !pInStm->ReadLine( aRet ) )
93 break;
95 if( pTok1 )
97 if( ( nPos1 = aRet.indexOf( pTok1 ) ) != -1 )
99 bStatus = true;
101 if( pTok2 )
103 bStatus = false;
105 if( ( ( nPos2 = aRet.indexOf( pTok2 ) ) != -1 ) &&
106 ( nPos2 > nPos1 ) )
108 bStatus = true;
110 if( pTok3 )
112 bStatus = false;
114 if( ( ( nPos3 = aRet.indexOf( pTok3 ) ) != -1 ) && ( nPos3 > nPos2 ) )
115 bStatus = true;
122 while( !bStatus );
124 return aRet;
127 long XBMReader::ParseDefine( const sal_Char* pDefine )
129 long nRet = 0;
130 char* pTmp = const_cast<char*>(pDefine);
131 unsigned char cTmp;
133 // move to end
134 pTmp += ( strlen( pDefine ) - 1 );
135 cTmp = *pTmp--;
137 // search last digit
138 while( pHexTable[ cTmp ] == -1 )
139 cTmp = *pTmp--;
141 // move before number
142 while( pHexTable[ cTmp ] != -1 )
143 cTmp = *pTmp--;
145 // move to start of number
146 pTmp += 2;
148 // read Hex
149 if( ( pTmp[0] == '0' ) && ( ( pTmp[1] == 'X' ) || ( pTmp[1] == 'x' ) ) )
151 pTmp += 2;
152 cTmp = *pTmp++;
154 while ( pHexTable[ cTmp ] != -1 )
156 nRet = ( nRet << 4 ) + pHexTable[ cTmp ];
157 cTmp = *pTmp++;
160 // read decimal
161 else
163 cTmp = *pTmp++;
164 while( ( cTmp >= '0' ) && ( cTmp <= '9' ) )
166 nRet = nRet * 10 + ( cTmp - '0' );
167 cTmp = *pTmp++;
171 return nRet;
174 bool XBMReader::ParseData( SvStream* pInStm, const OString& aLastLine, XBMFormat eFormat )
176 OString aLine;
177 long nRow = 0;
178 long nCol = 0;
179 long nBits = ( eFormat == XBM10 ) ? 16 : 8;
180 long nBit;
181 sal_uInt16 nValue;
182 sal_uInt16 nDigits;
183 bool bFirstLine = true;
185 while( nRow < nHeight )
187 if( bFirstLine )
189 sal_Int32 nPos;
191 // delete opening curly bracket
192 if( (nPos = ( aLine = aLastLine ).indexOf('{') ) != -1 )
193 aLine = aLine.copy(nPos + 1);
195 bFirstLine = false;
197 else if( !pInStm->ReadLine( aLine ) )
198 break;
200 if (!aLine.isEmpty())
202 const sal_Int32 nCount = comphelper::string::getTokenCount(aLine, ',');
204 for( sal_Int32 i = 0; ( i < nCount ) && ( nRow < nHeight ); ++i )
206 const OString aToken(aLine.getToken(i, ','));
207 const sal_Int32 nLen = aToken.getLength();
208 bool bProcessed = false;
210 nBit = nDigits = nValue = 0;
212 for (sal_Int32 n = 0; n < nLen; ++n)
214 const unsigned char cChar = aToken[n];
215 const short nTable = pHexTable[ cChar ];
217 if( isxdigit( cChar ) || !nTable )
219 nValue = ( nValue << 4 ) + nTable;
220 nDigits++;
221 bProcessed = true;
223 else if( ( nTable < 0 ) && nDigits )
225 bProcessed = true;
226 break;
230 if( bProcessed )
232 while( ( nCol < nWidth ) && ( nBit < nBits ) )
233 pAcc1->SetPixel( nRow, nCol++, ( nValue & ( 1 << nBit++ ) ) ? aBlack : aWhite );
235 if( nCol == nWidth )
236 nCol = 0, nRow++;
242 return true;
245 ReadState XBMReader::ReadXBM( Graphic& rGraphic )
247 ReadState eReadState;
248 sal_uInt8 cDummy;
250 // check if we can read ALL
251 rIStm.Seek( STREAM_SEEK_TO_END );
252 rIStm.ReadUChar( cDummy );
254 // if we cannot read all
255 // we returnn and wait for new data
256 if ( rIStm.GetError() != ERRCODE_IO_PENDING )
258 rIStm.Seek( nLastPos );
259 bStatus = false;
260 OString aLine = FindTokenLine( &rIStm, "#define", "_width" );
262 if ( bStatus )
264 int nValue;
265 if ( ( nValue = (int) ParseDefine( aLine.getStr() ) ) > 0 )
267 nWidth = nValue;
268 aLine = FindTokenLine( &rIStm, "#define", "_height" );
270 // if height was not received, we search again
271 // from start of the file
272 if ( !bStatus )
274 rIStm.Seek( nLastPos );
275 aLine = FindTokenLine( &rIStm, "#define", "_height" );
278 else
279 bStatus = false;
281 if ( bStatus )
283 if ( ( nValue = (int) ParseDefine( aLine.getStr() ) ) > 0 )
285 nHeight = nValue;
286 aLine = FindTokenLine( &rIStm, "static", "_bits" );
288 if ( bStatus )
290 XBMFormat eFormat = XBM10;
292 if (aLine.indexOf("short") != -1)
293 eFormat = XBM10;
294 else if (aLine.indexOf("char") != -1)
295 eFormat = XBM11;
296 else
297 bStatus = false;
299 if ( bStatus && nWidth && nHeight )
301 aBmp1 = Bitmap( Size( nWidth, nHeight ), 1 );
302 pAcc1 = aBmp1.AcquireWriteAccess();
304 if( pAcc1 )
306 aWhite = pAcc1->GetBestMatchingColor( Color( COL_WHITE ) );
307 aBlack = pAcc1->GetBestMatchingColor( Color( COL_BLACK ) );
308 bStatus = ParseData( &rIStm, aLine, eFormat );
310 else
311 bStatus = false;
318 if (bStatus && pAcc1)
320 Bitmap aBlackBmp( Size( pAcc1->Width(), pAcc1->Height() ), 1 );
322 Bitmap::ReleaseAccess( pAcc1 ), pAcc1 = NULL;
323 aBlackBmp.Erase( Color( COL_BLACK ) );
324 rGraphic = BitmapEx( aBlackBmp, aBmp1 );
325 eReadState = XBMREAD_OK;
327 else
328 eReadState = XBMREAD_ERROR;
330 else
332 rIStm.ResetError();
333 eReadState = XBMREAD_NEED_MORE;
336 return eReadState;
339 bool ImportXBM( SvStream& rStm, Graphic& rGraphic )
341 XBMReader* pXBMReader = static_cast<XBMReader*>( rGraphic.GetContext() );
342 ReadState eReadState;
343 bool bRet = true;
345 if( !pXBMReader )
346 pXBMReader = new XBMReader( rStm );
348 rGraphic.SetContext( NULL );
349 eReadState = pXBMReader->ReadXBM( rGraphic );
351 if( eReadState == XBMREAD_ERROR )
353 bRet = false;
354 delete pXBMReader;
356 else if( eReadState == XBMREAD_OK )
357 delete pXBMReader;
358 else
359 rGraphic.SetContext( pXBMReader );
361 return bRet;
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */