1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
//----------------------------------------------------------------------------
// 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.
//
//----------------------------------------------------------------------------
/*
* Copyright (c) 2008 Rene Rebe <rene@exactcode.de>
*
*/
#include <string.h>
#include <stdlib.h>
#include "agg_svg_exception.hh"
#include "agg_svg_path_tokenizer.hh"
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
|