p_bezier.cpp

Go to the documentation of this file.
00001 /*
00002  * p_bezier.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  * Implementation of a bezier primitive.
00032  * (p_ stands for Primitive)
00033  */
00034 
00035 // includes --------------------------------------------------------------------
00036 #include "vgfx.h"             // all primitives should include this header first
00037 #include "drawer.h"
00038 
00039 #include "common/wave_ex.h"
00040 #include "perf/perf.h"
00041 #include "util/parsing.h"
00042 
00043 #include "bezier/bezier.h"
00044 
00045 
00046 namespace vgfx {
00047 
00048 ////////////////////////////////////////////////////////////////////////////////
00049 //
00050 //      static helper methods
00051 //
00052 ////////////////////////////////////////////////////////////////////////////////
00053 
00054 class Bezier : public Primitive {
00055 public:
00056         ~Bezier(void) throw() { }
00057 
00058         // public class methods ------------------------------------------------
00059         void initialize(IN const init_bezier_t& init);
00060 
00061         // vgfx::Primitive class interface methods -----------------------------
00062         virtual const char * getType(void) const throw() { return "bezier"; }
00063         virtual void persist(OUT std::ostream& stream) const;
00064         virtual bool doesContainerExist(IN const VecString& path) const;
00065         virtual bool canCreateContainer(IN const VecString& path) const;
00066         virtual void removeContainer(IN const VecString& path);
00067         virtual void getContainerDictionary(IN const VecString& path,
00068                                 OUT dictionary_t& data) const;
00069         virtual void setContainerDictionary(IN const VecString& path,
00070                                 IN const dictionary_t& data);
00071         virtual void recalcBoundingRect(IN const char * tag_path,
00072                                 IN Drawer * drawer,
00073                                 IN const xform_2d_t& T);
00074         virtual bool getBoundingRect(OUT rect_t& r) const throw();
00075         virtual void draw(IN Drawer * drawer,
00076                                 IN const rect_t& r_cm,
00077                                 IN const xform_2d_t& T);
00078 
00079 private:
00080         bezier::curve_t m_curve;
00081         rect_t          m_bounding;
00082 };
00083 
00084 
00085 
00086 ////////////////////////////////////////////////////////////////////////////////
00087 //
00088 //      Bezier -- public class methods
00089 //
00090 ////////////////////////////////////////////////////////////////////////////////
00091 
00092 void
00093 Bezier::initialize
00094 (
00095 IN const init_bezier_t& init
00096 )
00097 {
00098         this->setID(init.id.c_str());
00099         m_curve = init.curve;
00100 }
00101 
00102 
00103 
00104 void
00105 Bezier::recalcBoundingRect
00106 (
00107 IN const char * path,
00108 IN Drawer * drawer,
00109 IN const xform_2d_t& T
00110 )
00111 {
00112         perf::Timer timer("Bezier::recalcBoundingRect");
00113         //ASSERT(drawer, "null");
00114         bezier::getRect(m_curve, m_bounding);
00115         m_bounding.expand(0.05);        // pen width etc
00116 }
00117 
00118 
00119 
00120 bool
00121 Bezier::getBoundingRect
00122 (
00123 OUT rect_t& r
00124 )
00125 const throw()
00126 {
00127         r = m_bounding;
00128         return true;
00129 }
00130 
00131 
00132 
00133 #define WRITE_B_FIELD(q) { if (m_curve.q) { stream << " " << #q << " " << m_curve.q; } }
00134 
00135 void
00136 Bezier::persist
00137 (
00138 OUT std::ostream& stream
00139 )
00140 const
00141 {
00142         stream << "bezier id " << this->getID();
00143         WRITE_B_FIELD(x0)
00144         WRITE_B_FIELD(ax)
00145         WRITE_B_FIELD(bx)
00146         WRITE_B_FIELD(cx)
00147         WRITE_B_FIELD(y0)
00148         WRITE_B_FIELD(ay)
00149         WRITE_B_FIELD(by)
00150         WRITE_B_FIELD(cy)
00151 }
00152 
00153 
00154 
00155 bool
00156 Bezier::doesContainerExist
00157 (
00158 IN const VecString& path
00159 )
00160 const
00161 {
00162         if (path.size() > 0) {
00163                 return false;
00164         }
00165         return true;
00166 }
00167 
00168 
00169 bool
00170 Bezier::canCreateContainer
00171 (
00172 IN const VecString& path
00173 )
00174 const
00175 {
00176         return false;
00177 }
00178 
00179 
00180 void
00181 Bezier::removeContainer
00182 (
00183 IN const VecString& path
00184 )
00185 {
00186         WAVE_EX(wex);
00187         wex << "bezier curves have no removable containers";
00188 }
00189 
00190 
00191 
00192 #define ADD_B_VALUE(q) { data[ #q ] = getStringValue( m_curve.q ); }
00193 
00194 void
00195 Bezier::getContainerDictionary
00196 (
00197 IN const VecString& path,
00198 OUT dictionary_t& data
00199 )
00200 const
00201 {
00202         if (path.size() > 0) {
00203                 WAVE_EX(wex);
00204                 wex << "Bezier curves do not support subcontainers";
00205         }
00206 
00207         data.clear();
00208         ADD_B_VALUE(x0)
00209         ADD_B_VALUE(ax)
00210         ADD_B_VALUE(bx)
00211         ADD_B_VALUE(cx)
00212         ADD_B_VALUE(y0)
00213         ADD_B_VALUE(ay)
00214         ADD_B_VALUE(by)
00215         ADD_B_VALUE(cy)
00216 }
00217 
00218 
00219 
00220 #define CHECK_B_VALUE(q) { if (!strcmp(name, #q )) { m_curve.q = atof(value); continue; } }
00221 
00222 void
00223 Bezier::setContainerDictionary
00224 (
00225 IN const VecString& path,
00226 IN const dictionary_t& data
00227 )
00228 {
00229         if (path.size() > 0) {
00230                 WAVE_EX(wex);
00231                 wex << "Bezier curves do not support subcontainers";
00232         }
00233 
00234         for (dictionary_t::const_iterator i = data.begin(); i != data.end();
00235              ++i) {
00236                 const char * name = i->first.c_str();
00237                 const char * value = i->second.c_str();
00238 
00239                 CHECK_B_VALUE(x0)
00240                 CHECK_B_VALUE(ax)
00241                 CHECK_B_VALUE(bx)
00242                 CHECK_B_VALUE(cx)
00243                 CHECK_B_VALUE(y0)
00244                 CHECK_B_VALUE(ay)
00245                 CHECK_B_VALUE(by)
00246                 CHECK_B_VALUE(cy)
00247 
00248                 {
00249                         WAVE_EX(wex);
00250                         wex << "Invalid property for bezier curve: '";
00251                         wex << name << "'";
00252                 }
00253         }
00254 }
00255 
00256 
00257 
00258 void
00259 Bezier::draw
00260 (
00261 IN Drawer * drawer,
00262 IN const rect_t& r_cm,
00263 IN const xform_2d_t& T
00264 )
00265 {
00266         ASSERT(drawer, "null drawer");
00267         drawer->setTransform(T);
00268         drawer->drawBezier(m_curve);
00269 }
00270 
00271 
00272 
00273 ////////////////////////////////////////////////////////////////////////////////
00274 //
00275 //      public API
00276 //
00277 ////////////////////////////////////////////////////////////////////////////////
00278 
00279 #define SET_B_FIELD(x)   init.curve.x = atof(getOptionalValue(data, #x , "0.0"));
00280 
00281 void
00282 init_bezier_from_data
00283 (
00284 IN const dictionary_t& data,
00285 OUT init_bezier_t& init
00286 )
00287 {
00288         init.id = getRequiredValue(data, "id");
00289 
00290         SET_B_FIELD(x0)
00291         SET_B_FIELD(ax)
00292         SET_B_FIELD(bx)
00293         SET_B_FIELD(cx)
00294         SET_B_FIELD(y0)
00295         SET_B_FIELD(ay)
00296         SET_B_FIELD(by)
00297         SET_B_FIELD(cy)
00298 }
00299 
00300 
00301 
00302 smart_ptr<Primitive>
00303 create_bezier
00304 (
00305 IN const init_bezier_t& init
00306 )
00307 {
00308         smart_ptr<Bezier> local = new Bezier;
00309         ASSERT(local, "out of memory");
00310 
00311         local->initialize(init);
00312 
00313         return local;
00314 }
00315 
00316 
00317 };      // vgfx namespace
00318