1/* 2 * Copyright 2006, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9//---------------------------------------------------------------------------- 10// Anti-Grain Geometry - Version 2.2 11// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) 12// 13// Permission to copy, use, modify, sell and distribute this software 14// is granted provided this copyright notice appears in all copies. 15// This software is provided "as is" without express or implied 16// warranty, and with no claim as to its suitability for any purpose. 17// 18//---------------------------------------------------------------------------- 19// Contact: mcseem@antigrain.com 20// mcseemagg@yahoo.com 21// http://www.antigrain.com 22 23#include "PathTokenizer.h" 24 25#include <string.h> 26#include <stdlib.h> 27#include <stdio.h> 28 29 30namespace agg { 31namespace svg { 32 33// globals 34const char PathTokenizer::sCommands[] = "+-MmZzLlHhVvCcSsQqTtAaFfPp"; 35const char PathTokenizer::sNumeric[] = ".Ee0123456789"; 36const char PathTokenizer::sSeparators[] = " ,\t\n\r"; 37 38// constructor 39PathTokenizer::PathTokenizer() 40 : fPath(0), 41 fLastNumber(0.0), 42 fLastCommand(0) 43{ 44 init_char_mask(fCommandsMask, sCommands); 45 init_char_mask(fNumericMask, sNumeric); 46 init_char_mask(fSeparatorsMask, sSeparators); 47} 48 49// set_path_str 50void 51PathTokenizer::set_path_str(const char* str) 52{ 53 fPath = str; 54 fLastCommand = 0; 55 fLastNumber = 0.0; 56} 57 58// next 59bool 60PathTokenizer::next() 61{ 62 if(fPath == 0) return false; 63 64 // Skip all white spaces and other garbage 65 while (*fPath && !is_command(*fPath) && !isNumeric(*fPath)) { 66 if (!is_separator(*fPath)) { 67 char buf[100]; 68 sprintf(buf, "PathTokenizer::next : Invalid Character %c", *fPath); 69 throw exception(buf); 70 } 71 fPath++; 72 } 73 74 if (*fPath == 0) return false; 75 76 if (is_command(*fPath)) { 77 // Check if the command is a numeric sign character 78 if(*fPath == '-' || *fPath == '+') 79 { 80 return parse_number(); 81 } 82 fLastCommand = *fPath++; 83 while(*fPath && is_separator(*fPath)) fPath++; 84 if(*fPath == 0) return true; 85 } 86 return parse_number(); 87} 88 89// next 90double 91PathTokenizer::next(char cmd) 92{ 93 if (!next()) throw exception("parse_path: Unexpected end of path"); 94 if (last_command() != cmd) { 95 char buf[100]; 96 sprintf(buf, "parse_path: Command %c: bad or missing parameters", cmd); 97 throw exception(buf); 98 } 99 return last_number(); 100} 101 102// init_char_mask 103void 104PathTokenizer::init_char_mask(char* mask, const char* char_set) 105{ 106 memset(mask, 0, 256/8); 107 while (*char_set) { 108 unsigned c = unsigned(*char_set++) & 0xFF; 109 mask[c >> 3] |= 1 << (c & 7); 110 } 111} 112 113// contains 114inline bool 115PathTokenizer::contains(const char* mask, unsigned c) const 116{ 117 return (mask[(c >> 3) & (256 / 8 - 1)] & (1 << (c & 7))) != 0; 118} 119 120// is_command 121inline bool 122PathTokenizer::is_command(unsigned c) const 123{ 124 return contains(fCommandsMask, c); 125} 126 127// isNumeric 128inline bool 129PathTokenizer::isNumeric(unsigned c) const 130{ 131 return contains(fNumericMask, c); 132} 133 134// is_separator 135inline bool 136PathTokenizer::is_separator(unsigned c) const 137{ 138 return contains(fSeparatorsMask, c); 139} 140 141// parse_number 142bool 143PathTokenizer::parse_number() 144{ 145 char* end; 146 fLastNumber = strtod(fPath, &end); 147 fPath = end; 148 return true; 149} 150 151 152} //namespace svg 153} //namespace agg 154 155 156 157 158