forked from matplotlib/matplotlib
/
agg_svg_path_tokenizer.cpp
144 lines (118 loc) · 4.2 KB
/
agg_svg_path_tokenizer.cpp
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
//----------------------------------------------------------------------------
// 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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#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_command(0), m_last_number(0.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