CLAW Library (a C++ Library Absolutely Wonderful) 1.5.5
|
00001 /* 00002 CLAW - a C++ Library Absolutely Wonderful 00003 00004 CLAW is a free library without any particular aim but being useful to 00005 anyone. 00006 00007 Copyright (C) 2005-2010 Julien Jorge 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public 00020 License along with this library; if not, write to the Free Software 00021 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00022 00023 contact: julien_jorge@yahoo.fr 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 } // xbm::reader::reader() 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 } // xbm::reader::reader() 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 } // xbm::reader::reader() 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 } // xbm::reader::~reader() 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 } // xbm::reader::load() 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 an XBM file." ); 00148 } // xbm::reader::read_from_file() 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 an XBM file." ); 00202 } // xbm::reader::read_size() 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 an XBM file." ); 00225 00226 return result; 00227 } // xbm::reader::read_dim() 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 an XBM file." ); 00263 00264 return result; 00265 } // xbm::reader::read_bits_per_entry() 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 an XBM file." ); 00297 } // xbm::reader::read_name() 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 an XBM file." ); 00342 } // xbm::reader::read_pixels() 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 } // xbm::reader::read_line() 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 } // xbm::reader::remove_comments()