/************************************************************************* ** ColorSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- the DVI to SVG converter ** ** Copyright (C) 2005-2013 Martin Gieseking ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** ** published by the Free Software Foundation; either version 3 of ** ** the License, or (at your option) any later version. ** ** ** ** This program is distributed in the hope that it will be useful, but ** ** WITHOUT ANY WARRANTY; without even the implied warranty of ** ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** ** GNU General Public License for more details. ** ** ** ** You should have received a copy of the GNU General Public License ** ** along with this program; if not, see . ** *************************************************************************/ #include #include #include #include #include #include #include "ColorSpecialHandler.h" #include "SpecialActions.h" using namespace std; static float read_float (istream &is) { is.clear(); float v; is >> v; if (is.fail()) throw SpecialException("number expected"); return v; } /** Reads multiple float values from a given stream. The number of * values read is determined by the size of the result vector. * @param[in] is stream to be read from * @param[out] v the resulting floats */ static void read_floats (istream &is, vector &v) { for (size_t i=0; i < v.size(); i++) v[i] = read_float(is); } /** Reads a color statement from an input stream and converts it to RGB. * A color statement has the following syntax: * * Currently, the following color models are supported: rgb, cmyk, hsb and gray. * Examples: rgb 1 0.5 0, gray 0.5 * @param[in] model if model != "" this value specifies the model, otherwise it's read from the stream * @param[in] is stream to be read from * @param[out] resulting RGB triple * @return true if statement has successfully been read */ static void read_color (string model, istream &is, Color &color) { if (model.empty()) is >> model; if (model == "rgb") { vector rgb(3); read_floats(is, rgb); color.set(rgb[0], rgb[1], rgb[2]); } else if (model == "cmyk") { vector cmyk(4); read_floats(is, cmyk); color.setCMYK(cmyk[0], cmyk[1], cmyk[2], cmyk[3]); } else if (model == "hsb") { vector hsb(3); read_floats(is, hsb); color.setHSB(hsb[0], hsb[1], hsb[2]); } else if (model == "gray") color.setGray(read_float(is)); else if (!color.set(model, true)) throw SpecialException("unknown color statement"); } bool ColorSpecialHandler::process (const char *prefix, istream &is, SpecialActions *actions) { Color color; if (prefix && strcmp(prefix, "background") == 0) { read_color("", is, color); actions->setBgColor(color); } else { string cmd; is >> cmd; if (cmd == "push") { // color push read_color("", is, color); _colorStack.push(color); } else if (cmd == "pop") { if (!_colorStack.empty()) // color pop _colorStack.pop(); } else { // color read_color(cmd, is, color); while (!_colorStack.empty()) _colorStack.pop(); _colorStack.push(color); } if (actions) { if (_colorStack.empty()) actions->setColor(Color::BLACK); else actions->setColor(_colorStack.top()); } } return true; } const char** ColorSpecialHandler::prefixes () const { static const char *pfx[] = {"color", 0}; return pfx; }