Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00030 #include <claw/xbm.hpp>
00031
00032 #include <claw/exception.hpp>
00033 #include <claw/assert.hpp>
00034 #include <claw/string_algorithm.hpp>
00035
00036
00041 claw::graphic::xbm::reader::reader( image& img )
00042 : m_image( img ), m_hot(NULL)
00043 {
00044
00045 }
00046
00047
00054 claw::graphic::xbm::reader::reader( image& img, std::istream& f )
00055 : m_image( img ), m_hot(NULL)
00056 {
00057 load(f);
00058 }
00059
00060
00067 claw::graphic::xbm::reader::reader( xbm& img, std::istream& f )
00068 : m_image( img ), m_hot(NULL)
00069 {
00070 load(f);
00071 img.set_name( m_name );
00072
00073 if (m_hot != NULL)
00074 img.set_hot( *m_hot );
00075 }
00076
00077
00081 claw::graphic::xbm::reader::~reader()
00082 {
00083 if (m_hot != NULL)
00084 {
00085 delete m_hot;
00086 m_hot = NULL;
00087 }
00088 }
00089
00090
00095 void claw::graphic::xbm::reader::load( std::istream& f )
00096 {
00097 CLAW_PRECOND( !!f );
00098
00099 std::istream::pos_type init_pos = f.tellg();
00100
00101 if (m_hot != NULL)
00102 {
00103 delete m_hot;
00104 m_hot = NULL;
00105 }
00106
00107 try
00108 {
00109 read_from_file(f);
00110 }
00111 catch(...)
00112 {
00113 if (m_hot != NULL)
00114 delete m_hot;
00115
00116 f.clear();
00117 f.seekg( init_pos, std::ios_base::beg );
00118 throw;
00119 }
00120 }
00121
00122
00127 void claw::graphic::xbm::reader::read_from_file( std::istream& f )
00128 {
00129 std::string line;
00130 bool valid_format = false;
00131 unsigned int bpe;
00132
00133 read_size(f);
00134 bpe = read_bits_per_entry(f);
00135 read_name(f);
00136 read_line( f, line, '{' );
00137
00138 if ( !line.empty() )
00139 {
00140 read_pixels(f, bpe);
00141 read_line(f, line, ';');
00142
00143 valid_format = true;
00144 }
00145
00146 if ( !valid_format )
00147 throw CLAW_EXCEPTION( "Not a XBM file." );
00148 }
00149
00150
00155 void claw::graphic::xbm::reader::read_size( std::istream& f )
00156 {
00157 unsigned int w(0), h(0);
00158 bool valid = true;
00159 bool stop = false;
00160 std::string line;
00161
00162 while ( valid && !stop )
00163 {
00164 std::ios::pos_type pos = f.tellg();
00165
00166 read_line( f, line, '\n' );
00167
00168 if ( !line.empty() )
00169 {
00170 if ( line.find("width") != std::string::npos )
00171 w = read_dim(line);
00172 else if ( line.find("height") != std::string::npos )
00173 h = read_dim(line);
00174 else if ( line.find("x_hot") != std::string::npos )
00175 {
00176 if ( m_hot == NULL )
00177 m_hot = new claw::math::coordinate_2d<int>;
00178
00179 m_hot->x = read_dim(line);
00180 }
00181 else if ( line.find("y_hot") != std::string::npos )
00182 {
00183 if ( m_hot == NULL )
00184 m_hot = new claw::math::coordinate_2d<int>;
00185
00186 m_hot->y = read_dim(line);
00187 }
00188 else if ( line.find("static") != std::string::npos )
00189 {
00190 stop = true;
00191 f.seekg( pos );
00192 }
00193 }
00194 else
00195 valid = false;
00196 }
00197
00198 if ( valid )
00199 m_image.set_size(w, h);
00200 else
00201 throw CLAW_EXCEPTION( "Not a XBM file." );
00202 }
00203
00204
00209 unsigned int
00210 claw::graphic::xbm::reader::read_dim( const std::string& line ) const
00211 {
00212 unsigned int result;
00213 std::istringstream iss(line);
00214 std::string token;
00215 bool valid = false;
00216
00217 if (iss >> token)
00218 if ( token == "#define" )
00219 if ( iss >> token )
00220 if ( iss >> result )
00221 valid = true;
00222
00223 if ( !valid )
00224 throw CLAW_EXCEPTION( "Not a XBM file." );
00225
00226 return result;
00227 }
00228
00229
00234 unsigned int
00235 claw::graphic::xbm::reader::read_bits_per_entry( std::istream& f ) const
00236 {
00237 std::string line;
00238 unsigned int result(0);
00239
00240 std::string token;
00241
00242 if ( f >> token )
00243 if ( token == "static" )
00244 if ( f >> token )
00245 {
00246 if ( token == "unsigned" )
00247 f >> token;
00248 else if ( token == "signed" )
00249 f >> token;
00250
00251 if ( token == "char" )
00252 result = sizeof(char) * 8;
00253 else if ( token == "short" )
00254 result = sizeof(short) * 8;
00255 else if ( token == "int" )
00256 result = sizeof(int) * 8;
00257 else if ( token == "long" )
00258 result = sizeof(long) * 8;
00259 }
00260
00261 if ( result == 0 )
00262 throw CLAW_EXCEPTION( "Not a XBM file." );
00263
00264 return result;
00265 }
00266
00267
00272 void claw::graphic::xbm::reader::read_name( std::istream& f )
00273 {
00274 bool valid = false;
00275 std::string line;
00276
00277 read_line(f, line, '[');
00278
00279 if ( !line.empty() )
00280 {
00281 std::string::size_type end = line.find_last_of('_');
00282
00283 if ( end != std::string::npos )
00284 {
00285 std::string::size_type begin = line.find_last_of(" \t", end);
00286
00287 if ( begin == std::string::npos )
00288 begin = 0;
00289
00290 m_name = line.substr(begin, end - begin);
00291 valid = true;
00292 }
00293 }
00294
00295 if ( !valid )
00296 throw CLAW_EXCEPTION( "Not a XBM file." );
00297 }
00298
00299
00305 void claw::graphic::xbm::reader::read_pixels
00306 ( std::istream& f, unsigned int bpe ) const
00307 {
00308 image::iterator first = m_image.begin();
00309 const image::iterator last = m_image.end();
00310
00311 bool valid = true;
00312
00313 unsigned int x = 0;
00314
00315 while ( (first!=last) && valid )
00316 {
00317 std::string s_val;
00318 read_line( f, s_val, ',' );
00319
00320 std::istringstream iss(s_val);
00321 long int val;
00322
00323 if ( iss >> std::hex >> val )
00324 {
00325 for( unsigned int i=0;
00326 (i!=bpe) && (first!=last) && (x!=m_image.width());
00327 ++i, ++first, ++x, val >>= 1 )
00328 if ( val & 1 )
00329 *first = black_pixel;
00330 else
00331 *first = white_pixel;
00332
00333 if ( x==m_image.width() )
00334 x = 0;
00335 }
00336 else
00337 valid = false;
00338 }
00339
00340 if ( !valid )
00341 throw CLAW_EXCEPTION( "Not a XBM file." );
00342 }
00343
00344
00351 void claw::graphic::xbm::reader::read_line
00352 ( std::istream& f, std::string& line, char endchar ) const
00353 {
00354 bool stop = false;
00355
00356 line.clear();
00357
00358 while ( !stop )
00359 if ( std::getline( f, line, endchar ) )
00360 {
00361 text::trim(line);
00362
00363
00364 remove_comments(f, line, endchar);
00365 stop = !line.empty();
00366 }
00367 else
00368 stop = true;
00369 }
00370
00371
00379 void claw::graphic::xbm::reader::remove_comments
00380 ( std::istream& f, std::string& line, char endchar ) const
00381 {
00382 std::string working(line);
00383 std::string::size_type beg = working.find( "/*" );
00384
00385 if ( beg != std::string::npos )
00386 {
00387 line = working.substr(0, beg);
00388
00389 std::string::size_type end = working.rfind( "*/" );
00390 bool stop = false;
00391
00392 while ( (end == std::string::npos) && !stop )
00393 if ( std::getline(f, working, endchar) )
00394 end = working.find( "*/" );
00395 else
00396 stop = true;
00397
00398 if ( !stop )
00399 {
00400 line += working.substr(end+2, line.length() - end - 2);
00401 text::trim(line);
00402 }
00403
00404 if ( !line.empty() )
00405 remove_comments(f, line, endchar);
00406 }
00407 }