prop_types.cpp

Go to the documentation of this file.
00001 /*
00002  * prop_types.cpp
00003  *
00004  * Copyright (C) 2007,2009  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Property type helper implementation.  See prop_types.h
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include "prop_types.h"         // always include our own header first!
00036 
00037 #include <sstream>
00038 
00039 #include "common/wave_ex.h"
00040 
00041 #include "util/parsing.h"
00042 
00043 
00044 namespace objtree {
00045 
00046 
00047 static const char s_escape                      = (char) 205; // '\xCD'
00048 
00049 
00050 ////////////////////////////////////////////////////////////////////////////////
00051 //
00052 //      static helper methods
00053 //
00054 ////////////////////////////////////////////////////////////////////////////////
00055 
00056 static bool
00057 getBoolean
00058 (
00059 IN const dictionary_t& data,
00060 IN const char * key
00061 )
00062 {
00063         ASSERT(key, "null");
00064 
00065         const char * val = getOptionalValue(data, key, "false");
00066         return !strcmp("true", val);
00067 }
00068 
00069 
00070 
00071 static void
00072 addBooleanIfTrue
00073 (
00074 IO std::ostream& out,
00075 IN const char * key,
00076 IN bool val
00077 )
00078 {
00079         ASSERT(out.good(), "bad");
00080         ASSERT(key, "null");
00081 
00082         if (val) {
00083                 out << " " << key << " true";
00084         }
00085 }
00086 
00087 
00088 
00089 static void
00090 addPrettyIfTrue
00091 (
00092 IO std::ostream& out,
00093 IN const char * key,
00094 IN bool val
00095 )
00096 {
00097         if (val) {
00098                 out << " " << key;
00099         }
00100 }
00101 
00102 
00103 static std::string
00104 escape
00105 (
00106 IN const char * p
00107 )
00108 {
00109         ASSERT(p, "null");
00110 
00111         std::string out;
00112         for (; *p; ++p) {
00113                 char a = *p;
00114                 if (' ' == a) {
00115                         a = s_escape; 
00116                 }
00117                 out += a;
00118         }
00119         return out;
00120 }
00121 
00122 
00123 
00124 static std::string
00125 unescape
00126 (
00127 IN const char * p
00128 )
00129 {
00130         ASSERT(p, "null");
00131 
00132         std::string out;
00133         for (; *p; ++p) {
00134                 char a = *p;
00135                 if (s_escape == a)
00136                         a = ' ';
00137                 out += a;
00138         }
00139 
00140         return out;
00141 }
00142 
00143 
00144 
00145 static void
00146 validateColorComponent
00147 (
00148 IN int x
00149 )
00150 {
00151         if (x < 0 || x > 255) {
00152                 WAVE_EX(wex);
00153                 wex << "Invalid color component (should be 0-255): " << x;
00154         }
00155 }
00156 
00157 
00158 
00159 static void
00160 addColorComponent
00161 (
00162 IO std::string& s,
00163 IN const char * tag,
00164 IN int x,
00165 IN int default_value
00166 )
00167 {
00168         ASSERT(tag, "null tag");
00169         validateColorComponent(x);
00170         validateColorComponent(default_value);
00171 
00172         if (x == default_value)
00173                 return;         // don't write default values
00174 
00175         char buffer[4];         // safe for 0-255
00176         snprintf(buffer, 4, "%d", x);
00177         s += tag;
00178         s += " ";
00179         s += buffer;
00180         s += " ";
00181 }
00182 
00183 
00184 
00185 
00186 ////////////////////////////////////////////////////////////////////////////////
00187 //
00188 //      public API
00189 //
00190 ////////////////////////////////////////////////////////////////////////////////
00191 
00192 color_t
00193 getColorFromString
00194 (
00195 IN const char * text
00196 )
00197 {
00198         ASSERT(text, "null string in getColorFromString()");
00199 
00200         dictionary_t data;
00201         getDictionaryFromString(text, "color data", data);
00202 
00203         color_t c;              // return value
00204         c.red = atoi(getOptionalValue(data, "r", "0"));
00205         c.green = atoi(getOptionalValue(data, "g", "0"));
00206         c.blue = atoi(getOptionalValue(data, "b", "0"));
00207         c.alpha = atoi(getOptionalValue(data, "a", "255"));
00208 
00209         validateColorComponent(c.red);
00210         validateColorComponent(c.green);
00211         validateColorComponent(c.blue);
00212         validateColorComponent(c.alpha);
00213 
00214         return c;
00215 }
00216 
00217 
00218 
00219 void
00220 getStringFromColor
00221 (
00222 IN const color_t& c,
00223 OUT std::string& s
00224 )
00225 {
00226         s.clear();
00227 
00228         addColorComponent(s, "r", c.red, 0);
00229         addColorComponent(s, "g", c.green, 0);
00230         addColorComponent(s, "b", c.blue, 0);
00231         addColorComponent(s, "a", c.alpha, 255);
00232 }
00233 
00234 
00235 
00236 void
00237 getFontFromString
00238 (
00239 IN const char * info,
00240 OUT font_t& font
00241 )
00242 {
00243         ASSERT(info, "null");
00244         font.clear();
00245 
00246         dictionary_t data;
00247         getDictionaryFromString(info, "font information", data);
00248 
00249         font.face_name = unescape(getOptionalValue(data, "faceName", "Helvetica"));
00250         font.point_size = atof(getOptionalValue(data, "size", "12.0"));
00251         font.bold = getBoolean(data, "bold");
00252         font.italic = getBoolean(data, "italic");
00253         font.underline = getBoolean(data, "underline");
00254         font.strikeout = getBoolean(data, "strikeout");
00255 }
00256 
00257 
00258 
00259 void
00260 getStringFromFont
00261 (
00262 IN const font_t& font,
00263 OUT std::string& out
00264 )
00265 {
00266         out.clear();
00267 
00268         std::ostringstream oss;
00269         oss << "faceName " << escape(font.face_name.c_str());
00270         oss << " size " << font.point_size;
00271         addBooleanIfTrue(oss, "bold", font.bold);
00272         addBooleanIfTrue(oss, "italic", font.italic);
00273         addBooleanIfTrue(oss, "underline", font.underline);
00274         addBooleanIfTrue(oss, "strikeout", font.strikeout);
00275 
00276         out = oss.str();
00277 }
00278 
00279 
00280 
00281 void
00282 getDisplayStringFromFont
00283 (
00284 IN const font_t& font,
00285 OUT std::string& out
00286 )
00287 {
00288         out.clear();
00289 
00290         std::ostringstream oss;
00291         oss << font.face_name << " " << font.point_size << "pt";
00292         addPrettyIfTrue(oss, "bold", font.bold);
00293         addPrettyIfTrue(oss, "italic", font.italic);
00294         addPrettyIfTrue(oss, "underline", font.underline);
00295         addPrettyIfTrue(oss, "strikeout", font.strikeout);
00296 
00297         out = oss.str();
00298 }
00299 
00300 
00301 };      // objtree namespace
00302