//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // SVG path tokenizer. // //---------------------------------------------------------------------------- #include #include #include #include "agg_svg_exception.h" #include "agg_svg_path_tokenizer.h" namespace agg { namespace svg { //------------------------------------------------------------------------ const char path_tokenizer::s_commands[] = "+-MmZzLlHhVvCcSsQqTtAaFfPp"; const char path_tokenizer::s_numeric[] = ".Ee0123456789"; const char path_tokenizer::s_separators[] = " ,\t\n\r"; //------------------------------------------------------------------------ path_tokenizer::path_tokenizer() : m_path(0), m_last_number(0.0), m_last_command(0) { init_char_mask(m_commands_mask, s_commands); init_char_mask(m_numeric_mask, s_numeric); init_char_mask(m_separators_mask, s_separators); } //------------------------------------------------------------------------ void path_tokenizer::set_path_str(const char* str) { m_path = str; m_last_command = 0; m_last_number = 0.0; } //------------------------------------------------------------------------ void path_tokenizer::init_char_mask(char* mask, const char* char_set) { memset(mask, 0, 256/8); while(*char_set) { unsigned c = unsigned(*char_set++) & 0xFF; mask[c >> 3] |= 1 << (c & 7); } } //------------------------------------------------------------------------ bool path_tokenizer::next() { if(m_path == 0) return false; // Skip all white spaces and other garbage while(*m_path && !is_command(*m_path) && !is_numeric(*m_path)) { if(!is_separator(*m_path)) { char buf[100]; sprintf(buf, "path_tokenizer::next : Invalid Character %c", *m_path); throw exception(buf); } m_path++; } if(*m_path == 0) return false; if(is_command(*m_path)) { // Check if the command is a numeric sign character if(*m_path == '-' || *m_path == '+') { return parse_number(); } m_last_command = *m_path++; while(*m_path && is_separator(*m_path)) m_path++; if(*m_path == 0) return true; } return parse_number(); } //------------------------------------------------------------------------ double path_tokenizer::next(char cmd) { if(!next()) throw exception("parse_path: Unexpected end of path"); if(last_command() != cmd) { char buf[100]; sprintf(buf, "parse_path: Command %c: bad or missing parameters", cmd); throw exception(buf); } return last_number(); } //------------------------------------------------------------------------ bool path_tokenizer::parse_number() { char buf[256]; // Should be enough for any number char* buf_ptr = buf; // Copy all sign characters while(buf_ptr < buf+255 && (*m_path == '-' || *m_path == '+')) { *buf_ptr++ = *m_path++; } // Copy all numeric characters while(buf_ptr < buf+255 && (is_numeric(*m_path))) { *buf_ptr++ = *m_path++; } *buf_ptr = 0; m_last_number = atof(buf); return true; } } //namespace svg } //namespace agg