1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
22 #include <comphelper/string.hxx>
23 #include "xbmread.hxx"
25 XBMReader::XBMReader( SvStream
& rStm
) :
28 nLastPos ( rStm
.Tell() ),
33 pHexTable
= new short[ 256 ];
34 maUpperName
= "SVIXBM";
38 XBMReader::~XBMReader()
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
)
86 sal_Int32 nPos1
, nPos2
, nPos3
;
92 if( !pInStm
->ReadLine( aRet
) )
97 if( ( nPos1
= aRet
.indexOf( pTok1
) ) != -1 )
105 if( ( ( nPos2
= aRet
.indexOf( pTok2
) ) != -1 ) &&
114 if( ( ( nPos3
= aRet
.indexOf( pTok3
) ) != -1 ) && ( nPos3
> nPos2
) )
127 long XBMReader::ParseDefine( const sal_Char
* pDefine
)
130 char* pTmp
= const_cast<char*>(pDefine
);
134 pTmp
+= ( strlen( pDefine
) - 1 );
138 while( pHexTable
[ cTmp
] == -1 )
141 // move before number
142 while( pHexTable
[ cTmp
] != -1 )
145 // move to start of number
149 if( ( pTmp
[0] == '0' ) && ( ( pTmp
[1] == 'X' ) || ( pTmp
[1] == 'x' ) ) )
154 while ( pHexTable
[ cTmp
] != -1 )
156 nRet
= ( nRet
<< 4 ) + pHexTable
[ cTmp
];
164 while( ( cTmp
>= '0' ) && ( cTmp
<= '9' ) )
166 nRet
= nRet
* 10 + ( cTmp
- '0' );
174 bool XBMReader::ParseData( SvStream
* pInStm
, const OString
& aLastLine
, XBMFormat eFormat
)
179 long nBits
= ( eFormat
== XBM10
) ? 16 : 8;
183 bool bFirstLine
= true;
185 while( nRow
< nHeight
)
191 // delete opening curly bracket
192 if( (nPos
= ( aLine
= aLastLine
).indexOf('{') ) != -1 )
193 aLine
= aLine
.copy(nPos
+ 1);
197 else if( !pInStm
->ReadLine( aLine
) )
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
;
223 else if( ( nTable
< 0 ) && nDigits
)
232 while( ( nCol
< nWidth
) && ( nBit
< nBits
) )
233 pAcc1
->SetPixel( nRow
, nCol
++, ( nValue
& ( 1 << nBit
++ ) ) ? aBlack
: aWhite
);
245 ReadState
XBMReader::ReadXBM( Graphic
& rGraphic
)
247 ReadState eReadState
;
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
);
260 OString aLine
= FindTokenLine( &rIStm
, "#define", "_width" );
265 if ( ( nValue
= (int) ParseDefine( aLine
.getStr() ) ) > 0 )
268 aLine
= FindTokenLine( &rIStm
, "#define", "_height" );
270 // if height was not received, we search again
271 // from start of the file
274 rIStm
.Seek( nLastPos
);
275 aLine
= FindTokenLine( &rIStm
, "#define", "_height" );
283 if ( ( nValue
= (int) ParseDefine( aLine
.getStr() ) ) > 0 )
286 aLine
= FindTokenLine( &rIStm
, "static", "_bits" );
290 XBMFormat eFormat
= XBM10
;
292 if (aLine
.indexOf("short") != -1)
294 else if (aLine
.indexOf("char") != -1)
299 if ( bStatus
&& nWidth
&& nHeight
)
301 aBmp1
= Bitmap( Size( nWidth
, nHeight
), 1 );
302 pAcc1
= aBmp1
.AcquireWriteAccess();
306 aWhite
= pAcc1
->GetBestMatchingColor( Color( COL_WHITE
) );
307 aBlack
= pAcc1
->GetBestMatchingColor( Color( COL_BLACK
) );
308 bStatus
= ParseData( &rIStm
, aLine
, eFormat
);
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
;
328 eReadState
= XBMREAD_ERROR
;
333 eReadState
= XBMREAD_NEED_MORE
;
339 bool ImportXBM( SvStream
& rStm
, Graphic
& rGraphic
)
341 XBMReader
* pXBMReader
= static_cast<XBMReader
*>( rGraphic
.GetContext() );
342 ReadState eReadState
;
346 pXBMReader
= new XBMReader( rStm
);
348 rGraphic
.SetContext( NULL
);
349 eReadState
= pXBMReader
->ReadXBM( rGraphic
);
351 if( eReadState
== XBMREAD_ERROR
)
356 else if( eReadState
== XBMREAD_OK
)
359 rGraphic
.SetContext( pXBMReader
);
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */