home *** CD-ROM | disk | FTP | other *** search
- //
- // Copyright (c) 1997,1998 Colosseum Builders, Inc.
- // All rights reserved.
- //
- // Colosseum Builders, Inc. makes no warranty, expressed or implied
- // with regards to this software. It is provided as is.
- //
- // See the README.TXT file that came with this software for restrictions
- // on the use and redistribution of this file or send E-mail to
- // info@colosseumbuilders.com
- //
-
- //
- // Title: XBM Decoder
- //
- // Author: John M. Miano miano@colosseumbuilers.com
- //
-
- #include <ctype.h>
- #include <string>
-
- #include "xbmdecod.h"
- #include "xbmpvt.h"
-
- using namespace std ;
-
- // File Tokens
- enum Token
- {
- Invalid, // INVALID TOKEN
- Define, // #define
- Comma, // ,
- Integer, // 123 0x123 0123
- Static, // static
- Char, // char
- Bits, // name_bits
- LBrace, // {
- RBrace, // }
- Equal, // =
- LBracket, // [
- RBracket, // ]
- HotX, // name_hot_x
- HotY, // name_hot_y
- Width, // name_width
- Height, // name_height
- Semicolon, // ;
- Unsigned, // signed or unsigned
- } ;
- const NoData = 0xFFFF ;
-
- //
- // Description:
- //
- // Class default constructor
- //
- XbmDecoder::XbmDecoder ()
- {
- Initialize () ;
- return ;
- }
-
- //
- // Description:
- //
- // Class copy constructor
- //
- XbmDecoder::XbmDecoder (const XbmDecoder &source)
- {
- Initialize () ;
- DoCopy (source) ;
- return ;
- }
-
- //
- // Descripton:
- //
- // Class Default Constructor
- //
- XbmDecoder::~XbmDecoder ()
- {
- return ;
- }
-
- //
- // Description:
- //
- // Class initialization function.
- //
- void XbmDecoder::Initialize ()
- {
- image_name = "" ;
- hot_spot_x = -1 ;
- hot_spot_y = -1 ;
- return ;
- }
-
- //
- // Description:
- //
- // Object copy function.
- //
- void XbmDecoder::DoCopy (const XbmDecoder &source)
- {
- image_name = source.image_name ;
- hot_spot_x = source.hot_spot_x ;
- hot_spot_y = source.hot_spot_y ;
- return;
- }
-
- //
- // Description:
- //
- // Class assignment operator.
- //
- XbmDecoder &XbmDecoder::operator=(const XbmDecoder &source)
- {
- DoCopy (source) ;
- return *this ;
- }
-
- //
- // Description:
- //
- // This function reads an XBM file from an input stream.
- //
- // The format is (according to our grammar):
- //
- // Define Width Integer
- // Define Height Integer
- // [Define HotX Integer
- // Define HotY Integer]
- // Static [signed|unsigned] Char LBracket RightBracket Equal
- // LBrace
- // Integer Comma Integer Comma ... Integer [Comma]
- // RBrace Semicolon
- //
- // In other words
- //
- // #define name_width 124
- // #define name_height 124
- // -#define name_hot_x 124
- // -#define name_hot_y 124
- // static --un-signed- char name_bits [] = {
- // 0x1, 0x2, .... } ;
- //
- // Parameters:
- // strm: The input stream
- // image: The image object
- //
- void XbmDecoder::ReadImage (std::istream &strm, BitmapImage &image)
- {
- last_char = '\n' ;
- hot_spot_x = -1 ;
- hot_spot_y = -1 ;
- int width = -1 ;
- int height = -1 ;
-
- // Read Image Width/Height
- Token token = (Token) NextToken (strm) ;
- if (token != Define)
- throw EXbmInvalid () ;
-
- token = (Token) NextToken (strm) ;
- if (token == Height)
- {
- token = (Token) NextToken (strm) ;
- if (token != Integer)
- throw EXbmInvalid () ;
- height = lexical_value ;
- }
- else if (token == Width)
- {
- token = (Token) NextToken (strm) ;
- if (token != Integer)
- throw EXbmInvalid () ;
- width = lexical_value ;
- }
- else
- {
- throw EXbmInvalid () ;
- }
-
- token = (Token) NextToken (strm) ;
- if (token != Define)
- throw EXbmInvalid () ;
-
- token = (Token) NextToken (strm) ;
- if (token == Height)
- {
- token = (Token) NextToken (strm) ;
- if (token != Integer)
- throw EXbmInvalid () ;
- height = lexical_value ;
- }
- else if (token == Width)
- {
- token = (Token) NextToken (strm) ;
- if (token != Integer)
- throw EXbmInvalid () ;
- width = lexical_value ;
- }
- else
- {
- throw EXbmInvalid () ;
- }
- if (height < 0 || width < 0)
- throw EXbmInvalid () ; // Width and Height must be specified
-
- // Read Hot Spot X
- token = (Token) NextToken (strm) ;
- if (token == Define)
- {
- token = (Token) NextToken (strm) ;
- if (token != HotX)
- throw EXbmInvalid () ;
-
- token = (Token) NextToken (strm) ;
- if (token != Integer)
- throw EXbmInvalid () ;
- hot_spot_x = lexical_value ;
-
- token = (Token) NextToken (strm) ;
- if (token != Define)
- throw EXbmInvalid () ;
-
- // Read the Hot spot Y
- token = (Token) NextToken (strm) ;
- if (token != HotY)
- throw EXbmInvalid () ;
-
- token = (Token) NextToken (strm) ;
- if (token != Integer)
- throw EXbmInvalid () ;
- hot_spot_y = lexical_value ;
- token = (Token) NextToken (strm) ;
- }
- if (token != Static)
- throw EXbmInvalid () ;
-
- // Optional signed or unsigned
- token = (Token) NextToken (strm) ;
- if (token == Unsigned)
- token = (Token) NextToken (strm) ;
-
- if (token != Char)
- throw EXbmInvalid () ;
-
- token = (Token) NextToken (strm) ;
- if (token != Bits)
- throw EXbmInvalid () ;
-
- token = (Token) NextToken (strm) ;
- if (token != LBracket)
- throw EXbmInvalid () ;
-
- token = (Token) NextToken (strm) ;
- if (token != RBracket)
- throw EXbmInvalid () ;
-
- token = (Token) NextToken (strm) ;
- if (token != Equal)
- throw EXbmInvalid () ;
-
- token = (Token) NextToken (strm) ;
- if (token != LBrace)
- throw EXbmInvalid () ;
-
- image.SetSize (2, 1, width, height) ;
- image.ColorMap (0).red = 255 ;
- image.ColorMap (0).green = 255 ;
- image.ColorMap (0).blue = 255 ;
- image.ColorMap (1).red = 0 ;
- image.ColorMap (1).green = 0 ;
- image.ColorMap (1).blue = 0 ;
-
- for (unsigned int ii = 0 ; ii < height ; ++ ii)
- {
- for (unsigned int jj = 0 ; jj < (width + 7) / 8 ; ++ jj)
- {
- token = (Token) NextToken (strm) ;
- if (token != Integer)
- throw EXbmInvalid () ;
- image [ii][jj] = RotateByte (lexical_value) ;
- token = (Token) NextToken (strm) ;
- if (token != Comma && ii != height - 1 && jj != width - 1)
- throw EXbmInvalid () ;
- }
- }
-
- if (token == Comma)
- token = (Token) NextToken (strm) ;
- if (token != RBrace)
- throw EXbmInvalid () ;
-
- token = (Token) NextToken (strm) ;
- if (token != Semicolon)
- throw EXbmInvalid () ;
-
- return ;
- }
-
- //
- // Description:
- //
- // This function return the X coordinate of the Hot Spot
- //
- // Return Value:
- // >= 0 => The Hot Spot X coordinate
- // < 0 => No Hot Spot
- //
- int XbmDecoder::GetHotSpotX () const
- {
- return hot_spot_x ;
- }
-
- //
- // Description:
- //
- // This function return the Y coordinate of the Hot Spot
- //
- // Return Value:
- // >= 0 => The Hot Spot Y coordinate
- // < 0 => No Hot Spot
- //
- int XbmDecoder::GetHotSpotY () const
- {
- return hot_spot_y ;
- }
-
- //
- // Description:
- //
- // This function returns the name of the image used in the XBM file.
- //
- // Return Value:
- // The image name
- //
- std::string XbmDecoder::GetImageName () const
- {
- return image_name ;
- }
-
- //
- // Description:
- //
- // This function returns the next character in the input stream. One
- // character of push back is supported.
- //
- // Return Value:
- // >= 0 => The next character in in the input stream.
- // < 0 => EOF
- //
- int XbmDecoder::NextChar (std::istream &strm)
- {
- if (last_char != NoData)
- {
- int value = last_char ;
- last_char = NoData ;
- return value ;
- }
-
- char data ;
- if (strm.eof ())
- return -1 ;
-
- strm.read (&data, sizeof (data)) ;
- return data ;
- }
-
- //
- // Description:
- //
- // This function returns an identifier for the next token in the input
- // stream.
- //
- // Return Value:
- // Enumeration from the Token type.
- // The member variable lexical_value contains the value of an
- // integer token.
- //
- int XbmDecoder::NextToken (std::istream &strm)
- {
- int thischar = NextChar (strm) ;
-
- while (isspace (thischar) && thischar != '\n')
- thischar = NextChar (strm) ;
-
- // Check for \n#<SPACE>define
- if (thischar == '\n')
- {
- thischar = NextChar (strm) ;
- if (thischar == '#')
- {
- thischar = NextChar (strm) ;
- while (isspace (thischar))
- thischar = NextChar (strm) ;
-
- if (thischar != 'd')
- return Invalid ;
- thischar = NextChar (strm) ;
- if (thischar != 'e')
- return Invalid ;
- thischar = NextChar (strm) ;
- if (thischar != 'f')
- return Invalid ;
- thischar = NextChar (strm) ;
- if (thischar != 'i')
- return Invalid ;
- thischar = NextChar (strm) ;
- if (thischar != 'n')
- return Invalid ;
- thischar = NextChar (strm) ;
- if (thischar != 'e')
- return Invalid ;
-
- thischar = NextChar (strm) ;
- if (! isspace (thischar))
- return Invalid ;
-
- return Define ;
- }
- }
- // Skip whitespace
- while (isspace (thischar))
- thischar = NextChar (strm) ;
-
- // Check for one-character tokens
- last_char = NoData ;
- if (thischar == ',')
- {
- return Comma ;
- }
- else if (thischar == '[')
- {
- return LBracket ;
- }
- else if (thischar == ']')
- {
- return RBracket ;
- }
- else if (thischar == '{')
- {
- return LBrace ;
- }
- else if (thischar == '}')
- {
- return RBrace ;
- }
- else if (thischar == '=')
- {
- return Equal ;
- }
- else if (thischar == ';')
- {
- return Semicolon ;
- }
-
- if (isdigit (thischar))
- {
- lexical_value = 0 ;
- if (thischar == '0')
- {
- thischar = NextChar (strm) ;
- if (thischar == 'x' || thischar == 'X')
- {
- thischar = NextChar (strm) ;
- while (true)
- {
- if (isdigit (thischar))
- {
- lexical_value *= 16 ;
- lexical_value += thischar - '0' ;
- }
- else if (thischar >= 'a' && thischar <= 'f')
- {
- lexical_value *= 16 ;
- lexical_value += thischar - 'a' + 10 ;
- }
- else if (thischar >= 'A' && thischar <= 'F')
- {
- lexical_value *= 16 ;
- lexical_value += thischar - 'A' + 10 ;
- }
- else
- {
- if (isalnum (thischar))
- return Invalid ;
-
- last_char = thischar ;
- return Integer ;
- }
- thischar = NextChar (strm) ;
- }
- }
- else
- {
- // Octal Integer or Zero
- while (thischar >= '0' && thischar <= '7')
- {
- lexical_value *= 8 ;
- lexical_value += thischar - '0' ;
- thischar = NextChar (strm) ;
- }
- // A Zero Integer
- if (isalnum (thischar))
- return Invalid ;
- last_char = thischar ;
- return Integer ;
- }
- }
- else
- {
- // Handle Decimal Integers
- lexical_value = 0 ;
- while (thischar >= '0' && thischar <= '9')
- {
- lexical_value *= 10 ;
- lexical_value += thischar - '0' ;
- thischar = NextChar (strm) ;
- }
- if (isalnum (thischar))
- return Invalid ;
- last_char = thischar ;
- return Integer ;
- }
- }
-
- if (! (isalpha (thischar) || thischar == '_'))
- return Invalid ;
-
- const int buffersize = 256 ;
- char buffer [buffersize] ;
- unsigned int length = 0 ;
- while (isalnum (thischar) || thischar == '_')
- {
- if (length >= buffersize)
- return Invalid ;
-
- buffer [length] = thischar ;
- ++ length ;
- thischar = NextChar (strm) ;
- }
- if (length >= buffersize)
- return Invalid ;
- buffer [length] = '\000' ;
- last_char = thischar ;
-
- if (std::string (buffer) == "char")
- {
- return Char ;
- }
- else if (std::string (buffer) == "static")
- {
- return Static ;
- }
- else if (std::string (buffer) == "unsigned"
- || std::string (buffer) == "signed")
- {
- return Unsigned ;
- }
-
- if (length < 6)
- return Invalid ;
-
- if (std::string (&buffer [length - 5]) == "_bits")
- {
- image_name = std::string (buffer).substr (0, length - 5) ;
- return Bits ;
- }
-
- if (length < 7)
- return Invalid ;
-
- if (std::string (&buffer [length - 6]) == "_x_hot")
- return HotX ;
- else if (std::string (&buffer [length - 6]) == "_y_hot")
- return HotY ;
- else if (std::string (&buffer [length - 6]) == "_width")
- return Width ;
-
- if (length < 8)
- return Invalid ;
-
- if (std::string (&buffer [length - 7]) == "_height")
- return Height ;
-
- return Invalid ;
- }
-
-
-
-
-