1 // astreplacement.h 2 // this file is part of Context Free 3 // --------------------- 4 // Copyright (C) 2011-2013 John Horigan - john@glyphic.com 5 // 6 // This program is free software; you can redistribute it and/or 7 // modify it under the terms of the GNU General Public License 8 // as published by the Free Software Foundation; either version 2 9 // of the License, or (at your option) any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program; if not, write to the Free Software 18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 // 20 // John Horigan can be contacted at john@glyphic.com or at 21 // John Horigan, 1209 Villa St., Mountain View, CA 94041-1123, USA 22 // 23 // 24 25 26 #ifndef INCLUDE_ASTREPLACEMENT_H 27 #define INCLUDE_ASTREPLACEMENT_H 28 29 #include "ast.h" 30 #include "astexpression.h" 31 #include "location.hh" 32 #include "cfdg.h" 33 #include "rendererAST.h" 34 #include "shape.h" 35 #include "primShape.h" 36 #include <string> 37 #include <map> 38 #include <list> 39 #include <cstddef> 40 #include "CmdInfo.h" 41 #include "agg2/agg_path_storage.h" 42 43 #include "json_fwd.hpp" 44 using json = nlohmann::json; 45 46 namespace agg { 47 struct trans_affine; 48 } 49 50 struct StackRule; 51 class Builder; 52 53 namespace AST { 54 void to_json(json& j, const ASTparameter& m); 55 56 class ASTreplacement { 57 public: 58 enum repElemListEnum { rule = 8, replacement = 4, mixed = 3, command = 2, op = 1, empty = 0 }; 59 ASTruleSpecifier mShapeSpec; 60 int mRepType; 61 pathOpEnum mPathOp; 62 ASTmodification mChildChange; 63 yy::location mLocation; 64 void replace(Shape& s, RendererAST* r) const; 65 66 ASTreplacement(const ASTreplacement&) = delete; 67 ASTreplacement(ruleSpec_ptr shapeSpec, mod_ptr mods, 68 const yy::location& loc = CfdgError::Default, 69 repElemListEnum t = replacement) noexcept; 70 ASTreplacement(mod_ptr mods, const yy::location& loc = CfdgError::Default, 71 repElemListEnum t = replacement); 72 ASTreplacement(const std::string& s, const yy::location& loc); 73 virtual ~ASTreplacement(); 74 virtual void traverse(const Shape& parent, bool tr, RendererAST* r) const; 75 virtual void compile(CompilePhase ph, Builder* b); 76 virtual void to_json(json& j) const; 77 }; 78 79 void to_json(json& j, const ASTreplacement& p); 80 81 class ASTrepContainer { 82 public: 83 pathOpEnum mPathOp; 84 int mRepType; 85 ASTbody mBody; 86 ASTparameters mParameters; 87 bool isGlobal; 88 ASTrepContainer()89 ASTrepContainer() 90 : mPathOp(unknownPathop), mRepType(ASTreplacement::empty), 91 isGlobal(false) {}; 92 ASTrepContainer(const ASTrepContainer&) = delete; 93 ASTrepContainer& operator=(const ASTrepContainer&) = delete; 94 ASTrepContainer(ASTrepContainer&&) = delete; 95 ~ASTrepContainer(); 96 void traverse(const Shape& parent, bool tr, RendererAST* r, 97 bool getParams = false) const 98 { 99 std::size_t s = r->mStackSize; 100 if (getParams && parent.mParameters) 101 r->initStack(parent.mParameters.get()); 102 for (const rep_ptr& rep: mBody) 103 rep->traverse(parent, tr, r); 104 r->unwindStack(s, mParameters); 105 } 106 void compile(CompilePhase ph, Builder* b, ASTloop* loop = nullptr, ASTdefine* def = nullptr); 107 void addParameter(const std::string& type, int index, 108 const yy::location& typeLoc, const yy::location& nameLoc); 109 ASTparameter& addDefParameter(int index, ASTdefine* def, 110 const yy::location& nameLoc, const yy::location& expLoc); 111 void addLoopParameter(int index, const yy::location& nameLoc); 112 }; 113 114 void to_json(json& j, const ASTrepContainer& p); 115 116 class ASTloop final: public ASTreplacement { 117 public: 118 exp_ptr mLoopArgs; 119 mod_ptr mLoopModHolder; 120 std::array<double,3> mLoopData; 121 ASTrepContainer mLoopBody; 122 ASTrepContainer mFinallyBody; 123 int mLoopIndexName; 124 std::string mLoopName; 125 126 static void setupLoop(double& start, double& end, double& step, 127 const ASTexpression* e, RendererAST* rti = nullptr); 128 129 ASTloop(int nameIndex, const std::string& name, const yy::location& nameLoc, 130 exp_ptr args, const yy::location& argsLoc, 131 mod_ptr mods); 132 ~ASTloop() final; 133 void traverse(const Shape& parent, bool tr, RendererAST* r) const final; 134 void compile(CompilePhase ph, Builder* b) final; 135 void compileLoopMod(Builder* b); 136 void to_json(json& j) const final; 137 }; 138 class ASTtransform: public ASTreplacement { 139 public: 140 ASTrepContainer mBody; 141 exp_ptr mExpHolder; // strong pointer 142 bool mClone; 143 144 ASTtransform(const yy::location& loc, exp_ptr mods); 145 ~ASTtransform() final; 146 void traverse(const Shape& parent, bool tr, RendererAST* r) const final; 147 void compile(CompilePhase ph, Builder* b) final; 148 void to_json(json& j) const final; 149 }; 150 class ASTif final: public ASTreplacement { 151 public: 152 exp_ptr mCondition; 153 ASTrepContainer mThenBody; 154 ASTrepContainer mElseBody; 155 156 ASTif(exp_ptr ifCond, const yy::location& condLoc); 157 ~ASTif() final; 158 void traverse(const Shape& parent, bool tr, RendererAST* r) const final; 159 void compile(CompilePhase ph, Builder* b) final; 160 void to_json(json& j) const final; 161 }; 162 163 class ASTswitch final: public ASTreplacement { 164 public: 165 using caseType = std::int64_t; 166 using caseRange = std::pair<caseType, caseType>; 167 struct compareRange { operatorcompareRange168 bool operator()(const caseRange& a, const caseRange& b) const { 169 return a.second < b.first; 170 } 171 }; 172 using switchMap = std::map<caseRange, const ASTrepContainer*, compareRange>; 173 174 exp_ptr mSwitchExp; 175 switchMap mCaseMap; 176 std::vector<std::pair<exp_ptr, cont_ptr>> mCases; 177 ASTrepContainer mElseBody; 178 179 ASTswitch(exp_ptr switchExp, const yy::location& expLoc); 180 ~ASTswitch() final; 181 void traverse(const Shape& parent, bool tr, RendererAST* r) const final; 182 void compile(CompilePhase ph, Builder* b) final; 183 184 void unify(); 185 void to_json(json& j) const final; 186 }; 187 class ASTdefine final : public ASTreplacement { 188 public: 189 enum define_t { StackDefine, ConstDefine, ConfigDefine, FunctionDefine, LetDefine }; 190 define_t mDefineType; 191 exp_ptr mExpression; 192 int mTuplesize; 193 AST::expType mType; 194 bool isNatural; 195 ASTparameters mParameters; 196 unsigned mParamSize; 197 std::string mName; 198 int mConfigDepth; 199 200 ASTdefine(std::string& name, const yy::location& loc); 201 void traverse(const Shape& parent, bool tr, RendererAST* r) const final; 202 void compile(CompilePhase ph, Builder* b) final; 203 ~ASTdefine() final = default; 204 ASTdefine& operator=(const ASTdefine&) = delete; 205 void to_json(json& j) const final; 206 }; 207 class ASTrule final : public ASTreplacement { 208 public: 209 enum WeightTypes { NoWeight = 1, PercentWeight = 2, ExplicitWeight = 4}; 210 ASTrepContainer mRuleBody; 211 mutable cpath_ptr mCachedPath; 212 double mWeight; 213 bool isPath; 214 int mNameIndex; 215 WeightTypes weightType; 216 217 static bool compareLT(const ASTrule* a, const ASTrule* b); 218 ASTrule(int ruleIndex,double weight,bool percent,const yy::location & loc)219 ASTrule(int ruleIndex, double weight, bool percent, const yy::location& loc) 220 : ASTreplacement(nullptr, loc, rule), mCachedPath(nullptr), 221 mWeight(weight <= 0.0 ? 1.0 : weight), isPath(false), mNameIndex(ruleIndex), 222 weightType(percent ? PercentWeight : ExplicitWeight) { 223 if (weight <= 0.0) 224 CfdgError::Warning(loc, "Rule weight coerced to 1.0"); 225 }; ASTrule(int ruleIndex,const yy::location & loc)226 ASTrule(int ruleIndex, const yy::location& loc) 227 : ASTreplacement(nullptr, loc, rule), mCachedPath(nullptr), 228 mWeight(1.0), isPath(false), mNameIndex(ruleIndex), weightType(NoWeight) { }; 229 ASTrule(int i); 230 ~ASTrule() final; 231 void traversePath(const Shape& parent, RendererAST* r) const; 232 void traverseRule(Shape& parent, RendererAST* r) const; 233 void traverse(const Shape& parent, bool tr, RendererAST* r) const final; 234 void compile(CompilePhase ph, Builder* b) final; 235 void to_json(json& j) const final; 236 }; 237 class ASTpathOp final : public ASTreplacement { 238 public: 239 exp_ptr mArguments; 240 mod_ptr mOldStyleArguments; 241 int mArgCount; 242 int mFlags; 243 244 ASTpathOp(const std::string& s, mod_ptr a, const yy::location& loc); 245 ASTpathOp(const std::string& s, exp_ptr a, const yy::location& loc); 246 ~ASTpathOp() final; 247 void traverse(const Shape& parent, bool tr, RendererAST* r) const final; 248 void compile(CompilePhase ph, Builder* b) final; 249 private: 250 void pathData(double* data, RendererAST* rti) const; 251 void pathDataConst(Builder* b); 252 void makePositional(Builder* b); 253 void checkArguments(Builder* b); 254 public: 255 void to_json(json& j) const final; 256 }; 257 class ASTpathCommand final : public ASTreplacement { 258 public: 259 double mMiterLimit; 260 double mStrokeWidth; 261 exp_ptr mParameters; 262 int mFlags; 263 264 // Empty constructor ASTpathCommand()265 ASTpathCommand() : 266 ASTreplacement(nullptr), 267 mMiterLimit(4.0), mStrokeWidth(0.1), mParameters(nullptr), 268 mFlags(CF_MITER_JOIN + CF_BUTT_CAP + CF_FILL) 269 { 270 } 271 272 ASTpathCommand(const std::string& s, mod_ptr mods, exp_ptr params, 273 const yy::location& loc); 274 275 void traverse(const Shape& parent, bool tr, RendererAST* r) const final; 276 void compile(CompilePhase ph, Builder* b) final; 277 ~ASTpathCommand() final = default; 278 void to_json(json& j) const final; 279 private: 280 mutable CommandInfo mInfoCache; 281 }; 282 class ASTcompiledPath { 283 public: 284 bool mCached; 285 agg::path_storage mPath; 286 InfoCache mCommandInfo; 287 ASTpathCommand mTerminalCommand; 288 bool mUseTerminal; 289 param_ptr mParameters; 290 CommandInfo::UIDtype mPathUID; 291 292 void finish(bool setAttr, RendererAST* r); 293 void addPathOp(const ASTpathOp* pop, double data[6], const Shape& s, 294 bool tr, RendererAST* r); 295 296 ASTcompiledPath(); 297 ~ASTcompiledPath(); 298 static UIDdatatype NextPathUID(); 299 private: 300 static CommandInfo::UIDtype GlobalPathUID; 301 }; 302 } 303 304 #endif //INCLUDE_ASTREPLACEMENT_H 305