svg-length.cpp revision 397a587b5704b39576622db2146c3dc5e5efa544
#define __SP_SVG_LENGTH_C__
/*
* SVG data parser
*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* bulia byak <buliabyak@users.sf.net>
*
* Copyright (C) 1999-2002 Lauris Kaplinski
*
* This code is in public domain
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <cstring>
#include <string>
#include <math.h>
#include <glib.h>
#include "svg.h"
#include "stringstream.h"
static unsigned sp_svg_length_read_lff(gchar const *str, SVGLength::Unit *unit, float *val, float *computed, char **next);
#ifndef MAX
# define MAX(a,b) ((a < b) ? (b) : (a))
#endif
{
if (!str) {
return 0;
}
char *e;
float const v = g_ascii_strtod(str, &e);
return 0;
}
*val = v;
return 1;
}
{
if (!str) {
return 0;
}
char *e;
double const v = g_ascii_strtod(str, &e);
return 0;
}
*val = v;
return 1;
}
// TODO must add a buffer length parameter for safety:
{
unsigned int i = 0;
char c[16u];
do {
val /= 10u;
} while (val > 0u);
buf[i] = 0;
return i;
}
// TODO unsafe code ingnoring bufLen
{
int p = 0;
unsigned int uval;
if (val < 0) {
buf[p++] = '-';
} else {
}
return p;
}
// TODO unsafe code ingnoring bufLen
static unsigned sp_svg_number_write_d(gchar *buf, int bufLen, double val, unsigned int tprec, unsigned int fprec)
{
/* Process sign */
int i = 0;
if (val < 0.0) {
buf[i++] = '-';
}
/* Determine number of integral digits */
int idigits = 0;
if (val >= 1.0) {
}
/* Determine the actual number of fractional digits */
/* Round value */
/* Extract integral and fractional parts */
/* Write integra */
buf[i+j] = '0';
}
} else {
}
int end_i = i;
buf[i++] = '.';
do {
fval *= 10.0;
if (int_dival != 0) {
end_i = i;
}
fprec -= 1;
}
return end_i;
}
unsigned int sp_svg_number_write_de(gchar *buf, int bufLen, double val, unsigned int tprec, int min_exp)
{
return sp_svg_number_write_ui(buf, 0);
}
unsigned int maxnumdigitsWithoutExp = // This doesn't include the sign because it is included in either representation
(unsigned int)eval+1;
unsigned int maxnumdigitsWithExp = tprec + ( eval<0 ? 4 : 3 ); // It's not necessary to take larger exponents into account, because then maxnumdigitsWithoutExp is DEFINITELY larger
if (maxnumdigitsWithoutExp <= maxnumdigitsWithExp) {
} else {
buf[p++] = 'e';
return p;
}
}
/* Length */
{
if (!str) {
return false;
}
float v;
float c;
return false;
}
_set = true;
unit = u;
value = v;
computed = c;
return true;
}
{
}
{
if (!str) {
return false;
}
float v;
float c;
return false;
}
if (svg_length_absolute_unit(u) == false) {
return false;
}
_set = true;
unit = u;
value = v;
computed = c;
return true;
}
{
if (!str) {
return 0;
}
float computed;
// failed to read
return 0;
}
if (svg_length_absolute_unit(unit) == false) {
return 0;
}
return 1;
}
{
if (!str) {
}
float value;
float computed;
// the list can be comma- or space-separated, but we will be generous and accept
// a mix, including newlines and tabs
next++;
}
break;
}
}
return list;
}
#define UVAL(a,b) (((unsigned int) (a) << 8) | (unsigned int) (b))
static unsigned sp_svg_length_read_lff(gchar const *str, SVGLength::Unit *unit, float *val, float *computed, char **next)
{
/* note: this function is sometimes fed a string with several consecutive numbers, e.g. by sp_svg_length_list_read.
So after the number, the string does not necessarily have a \0 or a unit, it might also contain a space or comma and then the next number!
*/
if (!str) {
return 0;
}
gchar const *e;
float const v = g_ascii_strtod(str, (char **) &e);
if (e == str) {
return 0;
}
if (!e[0]) {
/* Unitless */
if (unit) {
}
if (val) {
*val = v;
}
if (computed) {
*computed = v;
}
if (next) {
}
return 1;
} else if (!g_ascii_isalnum(e[0])) {
/* Unitless or percent */
if (e[0] == '%') {
/* Percent */
return 0;
}
if (unit) {
}
if (val) {
*val = v * 0.01;
}
if (computed) {
*computed = v * 0.01;
}
if (next) {
*next = (char *) e + 1;
}
return 1;
} else {
/* Unitless */
if (unit) {
}
if (val) {
*val = v;
}
if (computed) {
*computed = v;
}
if (next) {
*next = (char *) e;
}
return 1;
}
/* TODO: Allow the number of px per inch to vary (document preferences, X server
* or whatever). E.g. don't fill in computed here, do it at the same time as
* percentage units are done. */
switch (uval) {
if (unit) {
}
if (computed) {
*computed = v;
}
break;
if (unit) {
}
if (computed) {
}
break;
if (unit) {
}
if (computed) {
}
break;
if (unit) {
}
if (computed) {
}
break;
if (unit) {
}
if (computed) {
}
break;
if (unit) {
}
if (computed) {
}
break;
if (unit) {
}
if (computed) {
}
break;
if (unit) {
}
break;
if (unit) {
}
break;
default:
/* Invalid */
return 0;
break;
}
if (val) {
*val = v;
}
if (next) {
*next = (char *) e + 2;
}
return 1;
}
/* Invalid */
return 0;
}
unsigned int sp_svg_length_read_ldd(gchar const *str, SVGLength::Unit *unit, double *value, double *computed)
{
float a;
float b;
if (r) {
if (value) {
*value = a;
}
if (computed) {
*computed = b;
}
}
return r;
}
{
_set = true;
unit = u;
value = v;
computed = c;
}
{
_set = false;
unit = u;
value = v;
computed = c;
}
{
}
}
{
return def;
}
char *u;
double v = g_ascii_strtod(str, &u);
while (isspace(*u)) {
if (*u == '\0') {
return v;
}
u++;
}
if (*u == '%') {
v /= 100.0;
}
return v;
}
{
switch (unit) {
}
return "";
}
/**
* N.B.\ This routine will sometimes return strings with `e' notation, so is unsuitable for CSS
* lengths (which don't allow scientific `e' notation).
*/
{
} else {
}
}
{
unset(u, v, c);
}
}
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :