xbm_reader.cpp

Go to the documentation of this file.
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-2008 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 a 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 a 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 a 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 a 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 a 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 a 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()

Generated on 9 Nov 2009 for CLAW Library (a C++ Library Absolutely Wonderful) by  doxygen 1.6.1