1 // cfdg.h
2 // this file is part of Context Free
3 // ---------------------
4 // Copyright (C) 2005-2008 Mark Lentczner - markl@glyphic.com
5 // Copyright (C) 2005-2013 John Horigan - john@glyphic.com
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 //
21 // John Horigan can be contacted at john@glyphic.com or at
22 // John Horigan, 1209 Villa St., Mountain View, CA 94041-1123, USA
23 //
24 // Mark Lentczner can be contacted at markl@glyphic.com or at
25 // Mark Lentczner, 1209 Villa St., Mountain View, CA 94041-1123, USA
26 //
27 //
28 
29 
30 #ifndef INCLUDE_CFDG_H
31 #define INCLUDE_CFDG_H
32 
33 #include <iosfwd>
34 #include <string>
35 #include <time.h>
36 #include <vector>
37 #include "agg2/agg_trans_affine.h"
38 #include "agg2/agg_color_rgba.h"
39 #include "agg2/agg_path_storage.h"
40 #include "agg2/agg_pixfmt_rgba.h"
41 #include "location.hh"
42 #include "stacktype.h"
43 #include "Rand64.h"
44 #include "config.h"
45 #include <exception>
46 #include <memory>
47 #include <cstdint>
48 #include <cstddef>
49 
50 #define _unused(x) ((void)(x))
51 
52 using RGBA8 = agg::rgba16;
53 
54 namespace AST { class ASTcompiledPath; class ASTrule; class ASTparameter;
55     using SymmList = std::vector<agg::trans_affine>;
56     struct CommandInfo;
57 }
58 namespace agg { struct trans_affine_time; }
59 class Shape;
60 class tiledCanvas;
61 class Builder;
62 
63 class DeferUntilRuntime : public std::exception {
64 public:
65     virtual const char* what() const noexcept;
66 };
67 class CfdgError : public std::exception {
68 public:
69     virtual const char* what() const noexcept;
70     CfdgError& operator=(const CfdgError& e) noexcept;
71     yy::location    where;
72     static yy::location Default;
73 
74     static void     Error(const yy::location& errLoc, const char* msg, Builder* b = nullptr);
75     static void     Warning(const yy::location& errLoc, const char* msg);
76 
77     CfdgError(const yy::location& loc, const char* msg);
78     CfdgError(const char* msg);
79 private:
80     const char* mMsg;
81 };
82 
83 class AbstractSystem {
84     public:
85         enum TempType { ShapeTemp = 0, ExpansionTemp = 1, MergeTemp = 2, MovieTemp = 3, NumberofTempTypes = 4 };
86         enum SystemSize : std::uint64_t {
87 #if defined(_WIN64) || defined(__x86_64__)
88             MaximumMemory = 17179869184ULL,     // 16GB
89             SystemIs64bit = 1
90 #else
91             MaximumMemory = 2147483648ULL,      //  2GB
92             SystemIs64bit = 0
93 #endif
94         };
95 
96 #ifdef _WIN32
97         using FileChar = wchar_t;
98 #define FileFormat "%S"
99 #define FileStr(x) L##x
100 #else
101         using FileChar = char;
102 #define FileFormat "%s"
103 #define FileStr(x) x
104 #endif
105 
106         using FileString = std::basic_string<FileChar>;
107         using istr_ptr = std::unique_ptr<std::istream>;
108         using ostr_ptr = std::unique_ptr<std::ostream>;
109 
110         int cfdgVersion = 2;
111         bool mFirstCfdgRead = true;
112 
113         virtual void message(const char* fmt, ...) = 0;
114         virtual void syntaxError(const CfdgError& err) = 0;
115         virtual bool error(bool errorOccurred = true) { return errorOccurred; };
116         virtual void catastrophicError(const char* what) = 0;
isGuiProgram()117         virtual bool isGuiProgram() { return true; }
118 
119         virtual istr_ptr openFileForRead(const std::string& path) = 0;
120         virtual istr_ptr tempFileForRead(const FileString& path);
121         virtual ostr_ptr tempFileForWrite(TempType tt, FileString& nameOut) = 0;
122         virtual const FileChar* tempFileDirectory() = 0;
123             // caller must delete returned streams when done
124         virtual std::vector<FileString> findTempFiles() = 0;
125         virtual int deleteTempFile(const FileString& name) = 0;
126         virtual std::size_t getPhysicalMemory() = 0;
127 
128         virtual std::string relativeFilePath(
129             const std::string& base, const std::string& rel) = 0;
130 
131         virtual std::wstring normalize(const std::string&) = 0;
132 
133         struct Stats {
134             int     shapeCount;     // finished shapes in image
135             int     toDoCount;      // unfinished shapes still to expand
136 
137             bool    inOutput;       // true if we are in the output loop
138             bool    fullOutput;     // not an incremental output
139             bool    finalOutput;    // the last output
140             bool    showProgress;
141             int     outputCount;    // number to be output
142             int     outputDone;     // number output so far
143             clock_t outputTime;
144 
145             bool    animating;      // inside the animation loop
146             AbstractSystem* mSystem;
147 
StatsStats148             Stats()
149                 : shapeCount(0), toDoCount(0), inOutput(false),
150                   fullOutput(false), finalOutput(false), showProgress(false),
151                   outputCount(0), outputDone(0), outputTime(0), animating(false),
152                   mSystem(nullptr) {}
~StatsStats153             ~Stats()
154             {
155                 // Cancel system progress bar if it is being displayed
156                 if (mSystem && (showProgress || inOutput)) {
157                     showProgress = inOutput = false;
158                     mSystem->stats(*this);
159                 }
160             }
161         };
162 
163         virtual void orphan() = 0;
164 
165         virtual void stats(const Stats&);
166 
167         virtual ~AbstractSystem();
168     protected:
169         static const FileChar* TempPrefixes[NumberofTempTypes];
170         static const FileChar* TempSuffixes[NumberofTempTypes];
171         static const FileChar* TempPrefixAll;
clearAndCR()172         virtual void clearAndCR() {};
173 };
174 
175 class Canvas {
176     public:
start(bool,const agg::rgba &,int,int)177         virtual void start(bool , const agg::rgba& , int , int )
178         { mTime = clock(); }
end()179         virtual void end()
180         { mTime = clock() - mTime; }
181 
182         virtual void primitive(int, RGBA8 , agg::trans_affine , agg::comp_op_e ) = 0;
183         virtual void path(RGBA8, agg::trans_affine, const AST::CommandInfo& ) = 0;
184 
Canvas(int width,int height)185         Canvas(int width, int height)
186         : mWidth(width), mHeight(height), mError(false) {}
187         virtual ~Canvas();
188 
189         int mWidth;
190         int mHeight;
191         clock_t mTime;
192         bool mError;
193         std::string mFileName;
194 };
195 
196 class Renderer;
197 class CFDG;
198 
199 using cfdg_ptr = std::shared_ptr<CFDG>;
200 using renderer_ptr = std::unique_ptr<Renderer>;
201 
202 class CFDG {
203     public:
204         enum frieze_t { no_frieze = 0, frieze_x, frieze_y };
205         static cfdg_ptr ParseFile(const char* fname, AbstractSystem*,
206                                   int variation, std::string defs = "");
207         virtual ~CFDG();
208 
209         virtual renderer_ptr renderer(const cfdg_ptr& ptr,
210                 int width, int height, double minSize,
211                 int variation, double border = 2.0
212             ) = 0;
213             // caller must delete returned object
214 
215         bool usesColor;
216         bool usesAlpha;
217         bool uses16bitColor;
218         bool usesBlendMode;
219         bool usesTime;
220         bool usesFrameTime;
221         static const CfgArray<std::string>  ParamNames;
222         static CFG lookupCfg(const std::string& name);
223         static const std::string& getCfgName(int c);
224         static std::string ShapeToString(int shape);
225         static const AST::ASTparameters* ShapeToParams(int shape);
226         virtual bool isTiled(agg::trans_affine* tr = nullptr, double* x = nullptr, double* y = nullptr) const = 0;
227         virtual frieze_t isFrieze(agg::trans_affine* tr = nullptr, double* x = nullptr, double* y = nullptr) const = 0;
228         virtual bool isSized(double* x = nullptr, double* y = nullptr) const = 0;
229         virtual bool isTimed(agg::trans_affine_time* t = nullptr) const = 0;
230         virtual const agg::rgba& getBackgroundColor() = 0;
231         virtual void serialize(std::ostream&) = 0;
232 
233     protected:
CFDG()234         CFDG()
235         : usesColor(false), usesAlpha(false), uses16bitColor(false),
236           usesBlendMode(false), usesTime(false), usesFrameTime(false)
237         { }
238 };
239 
240 
241 class Renderer {
242     public:
243     // OS interface
244         virtual ~Renderer();
245 
246         virtual void setMaxShapes(int n) = 0;
247         virtual void resetBounds() = 0;
248         virtual void resetSize(int x, int y) = 0;
249 
250         virtual double run(Canvas* canvas, bool partialDraw) = 0;
251         virtual void draw(Canvas* canvas) = 0;
252         virtual void animate(Canvas* canvas, int frames, int frame, bool zoom) = 0;
253 
254         volatile bool requestStop;     // stop ASAP
255         volatile bool requestFinishUp; // stop expanding, and do final output
256         volatile bool requestUpdate;   // call stats() soon
257 
258         int m_width;
259         int m_height;
260         std::unique_ptr<tiledCanvas> m_tiledCanvas;
261 
262         static double Infinity;
263         static bool   AbortEverything;
264         static unsigned ParamCount;
265     protected:
266         Renderer(int w, int h);
267 };
268 
269 #endif
270