/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svtools.hxx" #define XBMMINREAD 512 #define _XBMPRIVATE #include #include "xbmread.hxx" // ------------- // - XBMReader - // ------------- XBMReader::XBMReader( SvStream& rStm ) : rIStm ( rStm ), pAcc1 ( NULL ), nLastPos ( rStm.Tell() ), nWidth ( 0 ), nHeight ( 0 ), bStatus ( sal_True ) { pHexTable = new short[ 256 ]; maUpperName = String::CreateFromAscii( "SVIXBM", 6 ); InitTable(); } // ------------------------------------------------------------------------ XBMReader::~XBMReader() { delete[] pHexTable; if( pAcc1 ) aBmp1.ReleaseAccess( pAcc1 ); } // ------------------------------------------------------------------------ void XBMReader::InitTable() { memset( pHexTable, 0, sizeof( short ) ); pHexTable['0'] = 0; pHexTable['1'] = 1; pHexTable['2'] = 2; pHexTable['3'] = 3; pHexTable['4'] = 4; pHexTable['5'] = 5; pHexTable['6'] = 6; pHexTable['7'] = 7; pHexTable['8'] = 8; pHexTable['9'] = 9; pHexTable['A'] = 10; pHexTable['B'] = 11; pHexTable['C'] = 12; pHexTable['D'] = 13; pHexTable['E'] = 14; pHexTable['F'] = 15; pHexTable['X'] = 0; pHexTable['a'] = 10; pHexTable['b'] = 11; pHexTable['c'] = 12; pHexTable['d'] = 13; pHexTable['e'] = 14; pHexTable['f'] = 15; pHexTable['x'] = 0; pHexTable[' '] = -1; pHexTable[','] = -1; pHexTable['}'] = -1; pHexTable['\n'] = -1; pHexTable['\t'] = -1; pHexTable['\0'] = -1; } // ------------------------------------------------------------------------ ByteString XBMReader::FindTokenLine( SvStream* pInStm, const char* pTok1, const char* pTok2, const char* pTok3 ) { ByteString aRet; long nPos1; long nPos2; long nPos3; bStatus = sal_False; do { if( !pInStm->ReadLine( aRet ) ) break; if( pTok1 ) { if( ( nPos1 = aRet.Search( pTok1 ) ) != STRING_NOTFOUND ) { bStatus = sal_True; if( pTok2 ) { bStatus = sal_False; if( ( ( nPos2 = aRet.Search( pTok2 ) ) != STRING_NOTFOUND ) && ( nPos2 > nPos1 ) ) { bStatus = sal_True; if( pTok3 ) { bStatus = sal_False; if( ( ( nPos3 = aRet.Search( pTok3 ) ) != STRING_NOTFOUND ) && ( nPos3 > nPos2 ) ) bStatus = sal_True; } } } } } } while( !bStatus ); return aRet; } // ------------------------------------------------------------------------ long XBMReader::ParseDefine( const sal_Char* pDefine ) { long nRet = 0; char* pTmp = (char*) pDefine; unsigned char cTmp; // bis zum Ende gehen pTmp += ( strlen( pDefine ) - 1 ); cTmp = *pTmp--; // letzte Ziffer suchen while( pHexTable[ cTmp ] == -1 ) cTmp = *pTmp--; // bis vor die Zahl laufen while( pHexTable[ cTmp ] != -1 ) cTmp = *pTmp--; // auf Anfang der Zahl gehen pTmp += 2; // Hex lesen if( ( pTmp[0] == '0' ) && ( ( pTmp[1] == 'X' ) || ( pTmp[1] == 'x' ) ) ) { pTmp += 2; cTmp = *pTmp++; while ( pHexTable[ cTmp ] != -1 ) { nRet = ( nRet << 4 ) + pHexTable[ cTmp ]; cTmp = *pTmp++; } } // Dezimal lesen else { cTmp = *pTmp++; while( ( cTmp >= '0' ) && ( cTmp <= '9' ) ) { nRet = nRet * 10 + ( cTmp - '0' ); cTmp = *pTmp++; } } return nRet; } // ------------------------------------------------------------------------ sal_Bool XBMReader::ParseData( SvStream* pInStm, const ByteString& aLastLine, XBMFormat eFormat ) { ByteString aLine; long nRow = 0; long nCol = 0; long nBits = ( eFormat == XBM10 ) ? 16 : 8; long nBit; sal_uInt16 nValue; sal_uInt16 nDigits; sal_Bool bFirstLine = sal_True; while( nRow < nHeight ) { if( bFirstLine ) { xub_StrLen nPos; // einfuehrende geschweifte Klammer loeschen if( (nPos = ( aLine = aLastLine ).Search( '{' ) ) != STRING_NOTFOUND ) aLine.Erase( 0, nPos + 1 ); bFirstLine = sal_False; } else if( !pInStm->ReadLine( aLine ) ) break; if( aLine.Len() ) { const sal_uInt16 nCount = aLine.GetTokenCount( ',' ); for( sal_uInt16 i = 0; ( i < nCount ) && ( nRow < nHeight ); i++ ) { const ByteString aToken( aLine.GetToken( i, ',' ) ); const xub_StrLen nLen = aToken.Len(); sal_Bool bProcessed = sal_False; nBit = nDigits = nValue = 0; for( xub_StrLen n = 0UL; n < nLen; n++ ) { const unsigned char cChar = aToken.GetChar( n ); const short nTable = pHexTable[ cChar ]; if( isxdigit( cChar ) || !nTable ) { nValue = ( nValue << 4 ) + nTable; nDigits++; bProcessed = sal_True; } else if( ( nTable < 0 ) && nDigits ) { bProcessed = sal_True; break; } } if( bProcessed ) { while( ( nCol < nWidth ) && ( nBit < nBits ) ) pAcc1->SetPixel( nRow, nCol++, ( nValue & ( 1 << nBit++ ) ) ? aBlack : aWhite ); if( nCol == nWidth ) nCol = 0, nRow++; } } } } return sal_True; } // ------------------------------------------------------------------------ ReadState XBMReader::ReadXBM( Graphic& rGraphic ) { ReadState eReadState; sal_uInt8 cDummy; // sehen, ob wir _alles_ lesen koennen rIStm.Seek( STREAM_SEEK_TO_END ); rIStm >> cDummy; // falls wir nicht alles lesen koennen // kehren wir zurueck und warten auf neue Daten if ( rIStm.GetError() != ERRCODE_IO_PENDING ) { ByteString aLine; int nValue; rIStm.Seek( nLastPos ); bStatus = sal_False; aLine = FindTokenLine( &rIStm, "#define", "_width" ); if ( bStatus ) { if ( ( nValue = (int) ParseDefine( aLine.GetBuffer() ) ) > 0 ) { nWidth = nValue; aLine = FindTokenLine( &rIStm, "#define", "_height" ); // Falls die Hoehe nicht folgt, suchen wir noch // einmal vom Anfang der Datei an if ( !bStatus ) { rIStm.Seek( nLastPos ); aLine = FindTokenLine( &rIStm, "#define", "_height" ); } } else bStatus = sal_False; if ( bStatus ) { if ( ( nValue = (int) ParseDefine( aLine.GetBuffer() ) ) > 0 ) { nHeight = nValue; aLine = FindTokenLine( &rIStm, "static", "_bits" ); if ( bStatus ) { XBMFormat eFormat = XBM10; if ( aLine.Search( "short" ) != STRING_NOTFOUND ) eFormat = XBM10; else if ( aLine.Search( "char" ) != STRING_NOTFOUND ) eFormat = XBM11; else bStatus = sal_False; if ( bStatus && nWidth && nHeight ) { aBmp1 = Bitmap( Size( nWidth, nHeight ), 1 ); pAcc1 = aBmp1.AcquireWriteAccess(); if( pAcc1 ) { aWhite = pAcc1->GetBestMatchingColor( Color( COL_WHITE ) ); aBlack = pAcc1->GetBestMatchingColor( Color( COL_BLACK ) ); bStatus = ParseData( &rIStm, aLine, eFormat ); } else bStatus = sal_False; } } } } } if( bStatus ) { Bitmap aBlackBmp( Size( pAcc1->Width(), pAcc1->Height() ), 1 ); aBmp1.ReleaseAccess( pAcc1 ), pAcc1 = NULL; aBlackBmp.Erase( Color( COL_BLACK ) ); rGraphic = BitmapEx( aBlackBmp, aBmp1 ); eReadState = XBMREAD_OK; } else eReadState = XBMREAD_ERROR; } else { rIStm.ResetError(); eReadState = XBMREAD_NEED_MORE; } return eReadState; } // ------------- // - ImportXBM - // ------------- sal_Bool ImportXBM( SvStream& rStm, Graphic& rGraphic ) { XBMReader* pXBMReader = (XBMReader*) rGraphic.GetContext(); ReadState eReadState; sal_Bool bRet = sal_True; if( !pXBMReader ) pXBMReader = new XBMReader( rStm ); rGraphic.SetContext( NULL ); eReadState = pXBMReader->ReadXBM( rGraphic ); if( eReadState == XBMREAD_ERROR ) { bRet = sal_False; delete pXBMReader; } else if( eReadState == XBMREAD_OK ) delete pXBMReader; else rGraphic.SetContext( pXBMReader ); return bRet; }