1 #ifndef __drvbase_h
2 #define __drvbase_h
3 /*
4 drvbase.h : This file is part of pstoedit Base class for all specific
5 driver classes/backends. All virtual functions have to be implemented by
6 the specific driver class. See drvSAMPL.cpp
7
8 Copyright (C) 1993 - 2014 Wolfgang Glunz, wglunz35_AT_pstoedit.net
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
24 */
25 /*
26 // ============================================================================
27 //
28 // = LIBRARY
29 // pstoedit
30 //
31 // = FILENAME
32 // drvbase.h
33 //
34 // = RCSID
35 // $Id$
36 */
37
38 #ifndef cppcomp_h
39 #include "cppcomp.h"
40 #endif
41
42
43 #include I_fstream
44 #include I_stdio
45 #include I_stdlib
46 #include I_string_h
47 USESTD
48
49 #ifndef assert
50 #include <assert.h>
51 #endif
52 #include "pstoeditoptions.h"
53 #ifndef miscutil_h
54 #include "miscutil.h"
55 #endif
56
57 #if defined(HAVE_STL) && !defined(USE_FIXED_ARRAY)
58 #include <vector>
59 #endif
60
61 // for compatibility checking
62 static const unsigned int drvbaseVersion = 108;
63 // 101 introduced the driverOK function
64 // 102 introduced the font optimization (lasttextinfo_)
65 // 103 introduced the -ssp support and the virtual pathscanbemerged
66 // 104 introduced the fontmatrix handling
67 // 105 introduced the miterlimit Info and outputPageSize
68 // 106 introduced some new utility functions for transformation (*_trans*)
69 // 107 new driver descriptions -- added info about clipping
70 // 108 new driver descriptions -- added info about driver options
71
72 const unsigned int maxPages = 10000; // maximum number of pages - needed for the array of bounding boxes
73 #if defined(HAVE_STL) && !defined(USE_FIXED_ARRAY)
74 // we can use std::vector
75 #else
76 const unsigned int maxPoints = 80000; // twice the maximal number of points in a path
77 const unsigned int maxElements = maxPoints/2;
78 const unsigned int maxSegments = maxPoints/2;// at least half of maxpoints (if we only have segments with one point)
79 #endif
80
81 class DLLEXPORT Point
82 {
83 public:
Point(float x,float y)84 Point(float x, float y) : x_(x),y_(y) {}
Point()85 Point() : x_(0.0f), y_(0.0f) {}; // for arrays
86 float x_;
87 float y_;
88 bool operator==(const Point & p2) const {
89 return (x_ == p2.x_) && (y_ == p2.y_); //lint !e777
90 }
91 bool operator!=(const Point & p2) const {
92 return !(*this == p2);
93 }
94 Point operator+(const Point & p) const { return Point (x_+p.x_,y_+p.y_); }
95 const Point & operator+=(const Point & p) { x_+=p.x_; y_+=p.y_; return *this; }
96 Point operator*(float f) const { return Point (x_*f,y_*f); }
97
98 #if 0
99 friend bool operator==(const Point & p1, const Point & p2) {
100 return (p1.x_ == p2.x_) && (p1.y_ == p2.y_); //lint !e777
101 }
102 #endif
103 #ifdef BUGGYGPP
104 Point transform(const float * matrix) const;
105 #else
106 Point transform(const float matrix[6]) const;
107 #endif
108
109 friend ostream & operator<<(ostream & out,const Point &p) {
110 return out << "x: " << p.x_ << " y: " << p.y_ ;
111 }
112
113 private:
114 };
115
116 struct DLLEXPORT BBox // holds two points describing a Bounding Box
117 {
118 public:
119 Point ll;
120 Point ur;
121
122 friend ostream & operator<<(ostream & out,const BBox &bb) {
123 return out << "LL: " << bb.ll << " UR: " << bb.ur ;
124 }
125
126 };
127
128 // image needs Point !
129 #include "psimage.h"
130
131 static const char emptyDashPattern[] = "[ ] 0.0";
132
133 class basedrawingelement; // forward
134 class DriverDescription ; // forward
135
136 class DLLEXPORT drvbase
137 // = TITLE
138 // Base class for backends to pstoedit
139 //
140 // = CLASS TYPE
141 // Abstract
142 //
143 // = AUDIENCE
144 // Developers of new backends
145 //
146 // = DESCRIPTION
147 // Abstract base class for backends to pstoedit.
148 // This class defines the virtual functions that every backend has
149 // to implement and some functions that are common to all backends
150 //
151 {
152 friend class sub_path; // needs PathInfo
153 friend class sub_path_list;
154 public:
155 // = PUBLIC TYPES
156
157 //lint -esym(578,drvbase::fill,fill)
158 enum showtype { stroke, fill, eofill };
159 enum cliptype { clip , eoclip };
160 enum linetype { solid=0, dashed, dotted, dashdot, dashdotdot }; // corresponding to the CGM patterns
161 struct DLLEXPORT TextInfo {
162 float x;
163 float y;
164 float FontMatrix[6];
165 float x_end; // pen coordinates after show in PostScript
166 float y_end; //
167 RSString thetext;
168 RSString glyphnames;
169 bool is_non_standard_font;
170 RSString currentFontName;
171 RSString currentFontUnmappedName;
172 RSString currentFontFamilyName;
173 RSString currentFontFullName;
174 RSString currentFontWeight;
175 float currentFontSize;
176 float currentFontAngle;
177 float currentR; // Colors
178 float currentG;
179 float currentB;
180 RSString colorName; // extracted from PostScript colorspace if /Separation type
181 float cx; // next five items correspond to the
182 float cy; // params for the awidthshow operator
183 int Char; // of PostScript
184 float ax;
185 float ay;
186 bool mappedtoIsoLatin1;
187 bool remappedfont; // was remapped via fontmap
samefontTextInfo188 bool samefont(const TextInfo& cmp) const {
189 return ( currentFontName == cmp.currentFontName ) && //lint !e1702
190 // ( currentFontFamilyName == cmp.currentFontFamilyName ) &&
191 // ( currentFontFullName == cmp.currentFontFullName ) &&
192 ( currentFontWeight == cmp.currentFontWeight ) && //lint !e1702
193 ( currentFontSize == cmp.currentFontSize ) && //lint !e777 // testing floats for ==
194 ( currentFontAngle == cmp.currentFontAngle ) ; //lint !e777 // testing floats for ==
195 }
196
samecolorTextInfo197 bool samecolor(const TextInfo& cmp) const {
198 return ( currentR == cmp.currentR ) && //lint !e777 // testing floats for ==
199 ( currentG == cmp.currentG ) && //lint !e777 // testing floats for ==
200 ( currentB == cmp.currentB ); //lint !e777 // testing floats for ==
201 }
TextInfoTextInfo202 TextInfo() :
203 x(0.0f),
204 y(0.0f),
205 x_end(0.0f),
206 y_end(0.0f),
207 // thetext(0), // use standard ctor
208 is_non_standard_font(false),
209 currentFontSize(10.0f),
210 currentFontAngle(0.0f),
211 currentR(0.0f),
212 currentG(0.0f),
213 currentB(0.0f),
214 colorName(""),
215 cx(0.0f),
216 cy(0.0f),
217 Char(32), // 32 means space
218 ax(0.0f),
219 ay(0.0f),
220 mappedtoIsoLatin1(true),
221 remappedfont(false) {
222 for (int i = 0; i < 6 ; i++ ) FontMatrix[i] = 0.0f;
223 }
~TextInfoTextInfo224 ~TextInfo() { }
225 private:
226 // declared but not defined
227 // const TextInfo & operator = (const TextInfo &); // default is ok
228 // TextInfo(const TextInfo &); // default is ok
229 };
230
231 private:
232 // = PRIVATE TYPES
233
234 protected:
235 // = PROTECTED TYPES
236
237 struct DLLEXPORT PathInfo {
238 showtype currentShowType;
239 linetype currentLineType;
240 unsigned int currentLineCap; // Shape of line ends for stroke (0 = butt, 1 = round, 2 = square)
241 unsigned int currentLineJoin;
242 float currentMiterLimit;
243 unsigned int nr;
244 #if defined(HAVE_STL) && !defined(USE_FIXED_ARRAY)
245 std::vector<basedrawingelement *> path;
246 #else
247 basedrawingelement * * path; // a path is an array of pointers to basedrawingelements
248 #endif
249 bool isPolygon; // whether current path was closed via closepath or not
250 unsigned int numberOfElementsInPath;
251 unsigned int subpathoffset; // normally 0, but if subpathes are simulated
252 // then this is set to the begin of the current subpath
253 // before show_path is executed
254 float currentLineWidth;
255 float edgeR; // edge colors
256 float edgeG;
257 float edgeB;
258 float fillR; // fill colors
259 float fillG;
260 float fillB;
261 RSString colorName;
262 bool pathWasMerged; // true, if this path is a result of a merge operation
263 RSString dashPattern; // just the dump of currentdash as string
PathInfoPathInfo264 PathInfo() :
265 currentShowType(drvbase::stroke),
266 currentLineType(drvbase::solid),
267 currentLineCap(0),
268 currentLineJoin(0),
269 currentMiterLimit(10.0f),
270 nr(0),
271 path(0),
272 isPolygon(false),
273 numberOfElementsInPath(0),
274 subpathoffset(0),
275 currentLineWidth(0.0f),
276 edgeR(0.0f),
277 edgeG(0.0f),
278 edgeB(0.0f),
279 fillR(0.0f),
280 fillG(0.0f),
281 fillB(0.0f),
282 colorName(""),
283 pathWasMerged(false),
284 dashPattern(emptyDashPattern)
285 {
286 #if defined(HAVE_STL) && !defined(USE_FIXED_ARRAY)
287 #else
288 path = new basedrawingelement *[maxElements];
289 #endif
290 }
291
~PathInfoPathInfo292 virtual ~PathInfo() { // added virtual because of windows memory handling
293 // the path content is deleted by clear
294 clear();
295 #if defined(HAVE_STL) && !defined(USE_FIXED_ARRAY)
296 // use std dtor
297 #else
298 delete [] path;
299 #endif
300 }
301 void addtopath(basedrawingelement * newelement,
302 ostream & errf);
303 void clear();
304 void copyInfo(const PathInfo & p);
305 // copies the whole path state except the path array
306 void rearrange();
307 // rearrange subpaths for backends which do not support them
308 private:
309 // Inhibitors (declared, but not defined)
310 const PathInfo& operator=(const PathInfo&);
311 PathInfo(const PathInfo &);
312 };
313
314 //lint -esym(1712,SaveRestoreInfo) // no default ctor
315 class DLLEXPORT SaveRestoreInfo {
316 public:
317 unsigned int clippathlevel; // number of clippathes since opening (=save)
318 unsigned int savelevel;
319 SaveRestoreInfo * previous;
320 SaveRestoreInfo * next;
SaveRestoreInfo(SaveRestoreInfo * parent)321 SaveRestoreInfo(SaveRestoreInfo * parent) : clippathlevel(0), previous(parent), next(NIL)
322 {
323 if (parent) {
324 parent->next=this;
325 savelevel = parent->savelevel + 1;
326 } else {
327 savelevel = 0;
328 }
329 }
330 };
331
332 public:
333 // = PUBLIC DATA
334
335 const DriverDescription& driverdesc; // reference to the derived class' driverdescription
336
337 ProgramOptions* DOptions_ptr;
338
339 PSImage imageInfo;
340
341 static FontMapper& theFontMapper();
342
343 static bool Verbose(); // need a wrapper function because static initialized data cannot be DLLEXPORTed
344 static void SetVerbose(bool param);
345 static unsigned int &totalNumberOfPages();
346
347 static BBox * bboxes() ; // [maxPages]; // array of bboxes - maxpages long
348 static RSString& pstoeditHomeDir(); // usually the place where the binary is installed
349 static RSString& pstoeditDataDir(); // where the fmp and other data files are stored
350
351 protected:
352 // = PROTECTED DATA
353
354 ostream & outf; // the output stream
355 ostream & errf; // the error stream
356 const RSString inFileName; // full name of input file
357 const RSString outFileName; // full name of output file
358
359 RSString outDirName; // output path with trailing slash or backslash
360 RSString outBaseName; // just the basename (no path, no suffix)
361 unsigned int d_argc;
362 const char ** d_argv; // array of driver argument strings
363 class PsToEditOptions & globaloptions; /* non const because driver can also add an option during ctor */
364 float currentDeviceHeight; // normally 792 pt (US Letter); used for flipping y values.
365 float currentDeviceWidth;
366 float x_offset;
367 float y_offset;
368 friend class PSFrontEnd; // PSFrontEnd needs access to currentPageNumber
369 unsigned int currentPageNumber;
370 bool domerge;
371 const char * defaultFontName; // name of default font
372 bool ctorOK; // indicated Constructor failure
373 // returned via driverOK() function
374
375 SaveRestoreInfo saveRestoreInfo;
376 SaveRestoreInfo * currentSaveLevel;
377
378 private:
379 // = PRIVATE DATA
380 static bool verbose; // access via Verbose()
381 bool page_empty; // indicates whether the current page is empty or not
382 char * driveroptions; // string containing options for backend
383 PathInfo PI1,PI2,clippath; // pi1 and pi2 are filled alternatively (to allow merge), clippath when a clippath is read
384 PathInfo * currentPath; // for filling from lexer
385 PathInfo * last_currentPath; // need to save during usage of currentPath for clippath
386 protected: // for drvrtf
387 PathInfo * outputPath; // for output driver
388 private:
389 PathInfo * lastPath; // for merging
390 TextInfo textInfo_; // this is used both by the lexer to fill in text related info
391 // but also by the backends for query of info, e.g. via "fontchanged"
392 TextInfo mergedTextInfo; // for collecting pieces of text when doing text merge
393 TextInfo lastTextInfo_; // for saving font settings. This is the last really dumped text
394
395 public:
396 // = PUBLIC METHODS
397
398 // = CONSTRUCTION, DESTRUCTION AND COPYING
399
400 drvbase(
401 const char * driverOptions_p,
402 ostream & theoutStream,
403 ostream & theerrStream,
404 const char* nameOfInputFile_p,
405 const char* nameOfOutputFile_p,
406 PsToEditOptions & globaloptions_p,
407 const class DriverDescription & driverdesc_p
408 ); // constructor
409 virtual ~drvbase(); // destructor
410
411 // = BACKEND GENERIC FUNCTIONS
412 // These functions are not backend specific and should not have to be
413 // changed for new backends
414
415 void startup(bool merge);
416
417 virtual void finalize();
418 // needed because base destructor will be called after derived destructor
419 // and thus the base destructor could no longer use the backend.
420 // virtual because so we can achieve that it is called in the
421 // context (DLL) of the real backend. Otherwise it would be called
422 // in the context of the main program which causes memory problems
423 // under windows since the plugins are NOT and extension DLL
424 //
425
setdefaultFontName(const char * n)426 void setdefaultFontName(const char * n) {defaultFontName = n;}
427
428 virtual bool textIsWorthToPrint(const RSString & thetext) const; // in the default implementation full blank strings are ignored
429
430 virtual bool textCanBeMerged(const TextInfo & text1, const TextInfo & text2) const; // checked whether two pieces of text can be merged into one.
431
setCurrentDeviceHeight(const float deviceHeight)432 void setCurrentDeviceHeight(const float deviceHeight)
433 { currentDeviceHeight = deviceHeight; }
434
setCurrentDeviceWidth(const float deviceWidth)435 void setCurrentDeviceWidth(const float deviceWidth)
436 { currentDeviceWidth = deviceWidth; }
437
getScale()438 float getScale() const { return 1.0f; }
439
l_transX(float x)440 inline long l_transX (float x) const {
441 return (long)((x + x_offset) + .5); // rounded long
442 }
443
l_transY(float y)444 inline long l_transY (float y) const {
445 return (long)((-1.0f*y + y_offset) + .5); // rounded long, mirrored
446 }
447
i_transX(float x)448 inline int i_transX (float x) const {
449 return (int)((x + x_offset) + .5); // rounded int
450 }
451
i_transY(float y)452 inline int i_transY (float y) const {
453 return (int)((-1.0f*y + y_offset) + .5); // rounded int, mirrored
454 }
455
f_transX(float x)456 inline float f_transX (float x) const {
457 return (x + x_offset) ;
458 }
459
f_transY(float y)460 inline float f_transY (float y) const {
461 return (-1.0f*y + y_offset) ;
462 }
463
464 const RSString & getPageSize() const; // { return globaloptions.outputPageSize; }
465
466 bool close_output_file_and_reopen_in_binary_mode(); //
467
fontchanged()468 bool fontchanged() const { return ! textInfo_.samefont(lastTextInfo_); }
textcolorchanged()469 bool textcolorchanged() const { return ! textInfo_.samecolor(lastTextInfo_); }
470
setColorName(const char * const name)471 void setColorName(const char * const name) {
472 textInfo_.colorName = name ;
473 currentPath->colorName = name;
474 }
setRGB(const float R,const float G,const float B)475 void setRGB(const float R,const float G, const float B)
476 {
477 if ( ( R > 1.0 ) || ( G > 1.0 ) || ( B > 1.0 ) ||
478 ( R < 0.0 ) || ( G < 0.0 ) || ( B < 0.0 ) ) {
479 errf << "Warning: color value out of range (0..1). Color change ignored." << R << ' ' << G << ' ' << B << endl;
480 } else {
481 textInfo_.currentR = R ; textInfo_.currentG = G; textInfo_.currentB = B;
482 currentPath->edgeR = R ; currentPath->edgeG = G; currentPath->edgeB = B;
483 currentPath->fillR = R ; currentPath->fillG = G; currentPath->fillB = B;
484 }
485 }
486
487 void showpage();
488
489 const BBox & getCurrentBBox() const;
490
491 void beginClipPath();
492 void endClipPath(cliptype clipmode) ;
493 // virtuals - to be implemented by backends
494 virtual void ClipPath(cliptype clipmode);
495 virtual void Save();
496 virtual void Restore();
497
498 // = DRAWING RELATED METHODS
499
500 void addtopath(basedrawingelement * newelement);
501 void removeFromElementFromPath();
502
numberOfElementsInPath()503 unsigned int &numberOfElementsInPath() { return outputPath->numberOfElementsInPath; }
numberOfElementsInPath()504 unsigned int numberOfElementsInPath() const { return outputPath->numberOfElementsInPath; }
505
506 const basedrawingelement & pathElement(unsigned int index) const;
507
setCurrentLineType(const linetype how)508 void setCurrentLineType(const linetype how)
509 { currentPath->currentLineType = how; }
510
setCurrentLineWidth(const float linewidth)511 void setCurrentLineWidth(const float linewidth)
512 { currentPath->currentLineWidth = linewidth; }
513
setDash(const char * const dash)514 void setDash(const char * const dash)
515 { currentPath->dashPattern.assign(dash); }
516
setIsPolygon(bool what)517 void setIsPolygon(bool what) { currentPath->isPolygon=what; } // whether current path was closed via closepath or not
518
setPathNumber(unsigned int nr)519 void setPathNumber(unsigned int nr) { currentPath->nr=nr; }
520
setCurrentLineJoin(const unsigned int joinType)521 void setCurrentLineJoin(const unsigned int joinType)
522 { currentPath->currentLineJoin = joinType; }
523
setCurrentMiterLimit(const float miterLimit)524 void setCurrentMiterLimit(const float miterLimit)
525 { currentPath->currentMiterLimit = miterLimit; }
526
setCurrentLineCap(const unsigned int capType)527 void setCurrentLineCap(const unsigned int capType)
528 { currentPath->currentLineCap = capType; }
529
setCurrentShowType(const showtype how)530 void setCurrentShowType(const showtype how)
531 { currentPath->currentShowType = how; }
532
533 void dumpPath(bool doFlushText = true); // shows current path
534
535 //lint -esym(578,flushall) // flushall hides same name in stdio
536 enum flushmode_t { flushall, flushtext, flushpath };
537
538 void flushOutStanding( flushmode_t flushmode = flushall);
539
540 void dumpRearrangedPathes(); // show the current subpathes after calling rearrange
541
542 unsigned int nrOfSubpaths() const;
543
544 void dumpImage(); // shows current image
545
546 // = TEXT RELATED METHODS
547
548 void setCurrentWidthParams( const float ax,
549 const float ay,
550 const int Char,
551 const float cx,
552 const float cy,
553 const float x_end = 0.0f,
554 const float y_end = 0.0f);
555
setMappedtoisolatin1(const bool mapped)556 void setMappedtoisolatin1 ( const bool mapped )
557 { textInfo_.mappedtoIsoLatin1 = mapped; }
558
559 void setCurrentFontName(const char *const Name,bool is_non_standard_font);
560
561 void setCurrentFontFamilyName(const char *const Name);
562
563 void setCurrentFontFullName(const char *const Name);
564
565 void setCurrentFontWeight(const char *const Name);
566
567 void setCurrentFontSize(const float Size);
568
569 void setCurrentFontAngle(float value);
570
getCurrentFontMatrix()571 const float * getCurrentFontMatrix() const { return textInfo_.FontMatrix; }
setCurrentFontMatrix(const float mat[6])572 void setCurrentFontMatrix(const float mat[6]) { for (unsigned short i = 0; i< 6; i++) textInfo_.FontMatrix[i] = mat[i]; }
573
574 // the push*Text methods set the textinfo_ member and then call the
575 // showOrMergeText(textinfo_) ;
576 void pushText(const size_t len,
577 const char *const thetext,
578 const float x,
579 const float y,
580 const char * const glyphnames=0);
581
582 void pushHEXText(const char *const thetext,
583 const float x,
584 const float y,
585 const char * const glyphnames=0);
586
587 void flushTextBuffer(bool useMergeBuffer); // flushes text from the text (merge) buffer
588 void showOrMergeText();
589
590 // = BACKEND SPECIFIC FUNCTIONS
591
592 // If a backend only deals with a special set of font names
593 // the following function must return a 0 terminated list
594 // of font names.
knownFontNames()595 virtual const char * const * knownFontNames() const { return 0; }
596
597 // The next functions are virtual with a default empty implementation
598
show_image(const PSImage &)599 virtual void show_image(const PSImage & /* imageinfo */) {
600 cerr << "show_image called, although backend does not support images" << endl;
601 //unused(&imageinfo);
602 }
603
604 // if during construction something may go wrong, a backend can
605 // overwrite this function and return false in case of an error.
606 // or it can just set the ctorOK to false.
driverOK()607 virtual bool driverOK() const { return ctorOK; } // some
608
609 // needed to check for pseude drivers which do not have a real backend
610 // but instead just do the job in the gs frontend.
withbackend()611 virtual bool withbackend() const { return true; }
612
613 protected:
614 // = PROTECTED METHODS
615
currentShowType()616 showtype currentShowType() const { return outputPath->currentShowType; }
currentLineType()617 linetype currentLineType() const { return outputPath->currentLineType; }
currentLineCap()618 unsigned int currentLineCap() const { return outputPath->currentLineCap; }
currentLineJoin()619 unsigned int currentLineJoin() const { return outputPath->currentLineJoin; }
currentMiterLimit()620 float currentMiterLimit() const { return outputPath->currentMiterLimit; }
isPolygon()621 bool isPolygon() const { return outputPath->isPolygon;} // whether current path was closed via closepath or not
622 virtual bool pathsCanBeMerged (const PathInfo & p1, const PathInfo & p2) const;
pathWasMerged()623 bool pathWasMerged() const { return outputPath->pathWasMerged; }
currentLineWidth()624 float currentLineWidth() const { return outputPath->currentLineWidth; }
currentNr()625 unsigned int currentNr() const { return outputPath->nr; }
edgeR()626 float edgeR() const { return outputPath->edgeR; } // edge colors
edgeG()627 float edgeG() const { return outputPath->edgeG; }
edgeB()628 float edgeB() const { return outputPath->edgeB; }
fillR()629 float fillR() const { return outputPath->fillR; } // fill colors
fillG()630 float fillG() const { return outputPath->fillG; }
fillB()631 float fillB() const { return outputPath->fillB; }
currentColorName()632 const RSString & currentColorName() const { return outputPath->colorName; }
dashPattern()633 const char * dashPattern() const { return outputPath->dashPattern.c_str(); }
currentR()634 float currentR() const { return outputPath->fillR; } // backends that do not support merging
currentG()635 float currentG() const { return outputPath->fillG; } // do not need to differentiate and
currentB()636 float currentB() const { return outputPath->fillB; } // can use these functions.
637 void add_to_page();
638
639 private:
640 // = PRIVATE METHODS
641
642 void guess_linetype();
643
644 bool is_a_rectangle() const;
645
646
647 // = BACKEND SPECIFIC FUNCTIONS
648
649 // These next functions are pure virtual and thus need to be implemented for every new backend.
650
651 virtual void close_page() = 0;
652 // writes a trailer whenever a page is finished (triggered by showpage)
653
654 virtual void open_page() = 0;
655 // writes a page header whenever a new page is needed
656
657 virtual void show_path() = 0;
658
659 void show_or_convert_path();
660
661 void simulate_fill();
662
663 // the next functions are virtual with default implementations
664
665 virtual void show_text(const TextInfo & textinfo) ;
666
667 virtual void show_rectangle(
668 const float llx,
669 const float lly,
670 const float urx,
671 const float ury);
672 // writes a rectangle at points (llx,lly) (urx,ury)
673
674
675 // = INHIBITORS (declared, but not defined)
676 drvbase(); // avoid default ctor
677 drvbase(const drvbase &);
678 drvbase & operator=(const drvbase&);
679
680 };
681
682 //lint -esym(1712,DashPattern) // no default ctor
683 class DLLEXPORT DashPattern {
684 public:
685 DashPattern(const char * patternAsSetDashString);
686 ~DashPattern();
687 const RSString dashString;
688 int nrOfEntries;
689 float * numbers;
690 float offset;
691
692 private:
693 NOCOPYANDASSIGN(DashPattern)
694 DashPattern();
695 };
696
697 typedef const char * (*makeColorNameType)(float r, float g, float b);
698 const unsigned int maxcolors = 10000 ; // maximum number of colors
699
700 //lint -esym(1712,ColorTable) // no default ctor
701 class DLLEXPORT ColorTable
702 {
703 public:
704 ColorTable(const char * const * defaultColors,
705 const unsigned int numberOfDefaultColors,
706 makeColorNameType makeColorName);
707 ~ColorTable();
708 unsigned int getColorIndex(float r, float g, float b) ; // non const
709 const char * getColorString(float r, float g, float b); // non const ;
710 bool isKnownColor(float r, float g, float b) const;
711 const char * getColorString(unsigned int index) const;
712
713 private:
714 const char * const * const defaultColors_;
715 const unsigned int numberOfDefaultColors_;
716 char * newColors[maxcolors];
717 const makeColorNameType makeColorName_ ;
718
719 NOCOPYANDASSIGN(ColorTable)
720 };
721
722
723
724 #ifdef __TCPLUSPLUS__
725 // turbo C++ has problems with enum for template parameters
726 typedef unsigned int Dtype;
727 const Dtype moveto = 1;
728 const Dtype lineto = 2;
729 const Dtype closepath = 3;
730 const Dtype curveto = 4;
731 #else
732 enum Dtype {moveto, lineto, closepath, curveto};
733 #endif
734 // closepath is only generated if backend supportes subpathes
735 // curveto is only generated if backend supportes it
736
737 //lint -esym(1769,basedrawingelement)
738 // default ctor sufficient since no members anyway
739
740 class DLLEXPORT basedrawingelement
741 {
742 public:
743 // default ctor sufficient since no members anyway
744 // basedrawingelement(unsigned int size_p) /*: size(size_p) */ {}
745 virtual const Point &getPoint(unsigned int i) const = 0;
746 virtual Dtype getType() const = 0;
747 friend ostream & operator<<(ostream & out, const basedrawingelement &elem);
748 bool operator==(const basedrawingelement& bd2) const;
749 virtual unsigned int getNrOfPoints() const = 0;
750 virtual basedrawingelement* clone() const = 0; // make a copy
751 // deleteyourself is needed because under Windows, the deletion
752 // of memory needs to be done by the same dll which did the allocation.
753 // this is not simply achieved if plugins are loaded as DLL.
deleteyourself()754 virtual void deleteyourself() { delete this; }
~basedrawingelement()755 virtual ~basedrawingelement() {}
756 private:
757 // const unsigned int size;
758 };
759
760
copyPoints(unsigned int nr,const Point src[],Point target[])761 inline void copyPoints(unsigned int nr, const Point src[], Point target[])
762 {
763 // needed because CenterLine cannot inline for loops
764 for (unsigned int i = 0 ; i < nr ; i++ ) target[i] = src[i];
765 }
766
767 template <unsigned int nr, Dtype curtype>
768 class drawingelement : public basedrawingelement
769 {
770 public:
771 // CenterLine !!!!
772 // "drvbase.h", line 455: sorry, not implemented: cannot expand inline function drawingelement
773 // <1 , 0 >::drawingelement__pt__19_XCUiL11XC5DtypeL10(Point*) with for statement in inline
774
775 drawingelement(float x_1, float y_1, float x_2 = 0.0, float y_2 = 0.0, float x_3 = 0.0, float y_3 = 0.0)
basedrawingelement()776 : basedrawingelement()
777 {
778 #if defined (__GNUG__) || defined (_MSC_VER) && _MSC_VER >= 1100
779 const Point p[] = {Point(x_1,y_1),Point(x_2,y_2),Point(x_3,y_3)};
780 copyPoints(nr,p,points);
781 #else
782 // Turbo C++ hangs if the other solution is used.
783 // and the HP CC compiler does not like it either
784 // so use this for all compilers besides GNU and MS VC++
785 // This, however, is somewhat slower than the solution above
786 Point * p = new Point[3];
787 p[0] = Point(x_1,y_1);
788 p[1] = Point(x_2,y_2);
789 p[2] = Point(x_3,y_3);
790 copyPoints(nr,p,points);
791 delete [] p;
792 #endif
793
794 }
795
drawingelement(const Point p[])796 drawingelement(const Point p[])
797 : basedrawingelement()
798 {
799 // for (unsigned int i = 0 ; i < nr ; i++ ) points[i] = p[i];
800 copyPoints(nr,p,points);
801 }
drawingelement(const drawingelement<nr,curtype> & orig)802 drawingelement(const drawingelement<nr,curtype> & orig)
803 : basedrawingelement() //lint !e1724 // Argument to copy constructor for class drawingelement<<1>,<2>> should be a const reference
804 { // copy ctor
805 if (orig.getType() != curtype ) {
806 cerr << "illegal usage of copy ctor of drawingelement" << endl;
807 exit(1);
808 } else {
809 copyPoints(nr,orig.points,points);
810 }
811 }
clone()812 virtual basedrawingelement* clone() const {
813 return new drawingelement<nr,curtype>(*this);
814 }
getPoint(unsigned int i)815 const Point &getPoint(unsigned int i) const {
816 #ifndef _lint
817 assert( (i+1) < (nr+1) );
818 // nr can be 0 - so unsigned i could never be < 0
819 // but if nr==0, i==0 is also invalid. (logically i has to be <nr)
820 #endif
821 return points[i];
822 }
getType()823 virtual Dtype getType() const { return (Dtype) curtype; }
824 // This cast (Dtype) is necessary
825 // to eliminate a compiler warning
826 // from the SparcCompiler 4.1.
827 // although curtype is of type Dtype
getNrOfPoints()828 virtual unsigned int getNrOfPoints() const { return nr; }
829 private:
830 Point points[(nr > 0) ? nr : (unsigned int)1]; //lint !e62 //Incompatible types (basic) for operator ':'
831 const drawingelement<nr,curtype> & operator=( const drawingelement<nr,curtype> & rhs ); // not implemented
832 };
833
834
835 // CenterLine !!!!
836 // "drvbase.h", line 477: sorry, not implemented: cannot expand inline function
837 // drawingelement <3 , 3 >::drawingelement__pt__19_XCUiL13XC5DtypeL13(Point*) with for statement in inline
838
839 #if 0
840 template <unsigned int nr, Dtype curtype>
841 inline drawingelement<nr,curtype>::drawingelement(Point p[])
842 : basedrawingelement()
843 {
844 for (unsigned int i = 0 ; i < nr ; i++ ) points[i] = p[i];
845 }
846 #endif
847
848 typedef drawingelement<(unsigned int) 1,moveto> Moveto;
849 typedef drawingelement<(unsigned int) 1,lineto> Lineto;
850 typedef drawingelement<(unsigned int) 1,closepath> Closepath;
851 typedef drawingelement<(unsigned int) 3,curveto> Curveto;
852
853
854 #define derivedConstructor(Class) \
855 Class(const char * driveroptions_p, \
856 ostream & theoutStream, \
857 ostream & theerrStream, \
858 const char* nameOfInputFile_p, \
859 const char* nameOfOutputFile_p, \
860 PsToEditOptions & globaloptions_p, /* non const because driver can also add options */ \
861 const class DriverDescription & descref)
862
863 // use of static_cast instead of dynamic_cast, because some tools complain about problems then since
864 // in theory dynamic_cast could return 0
865 #define constructBase drvbase(driveroptions_p,theoutStream,theerrStream,nameOfInputFile_p,nameOfOutputFile_p,globaloptions_p,descref), options(static_cast<DriverOptions*>(DOptions_ptr))
866
867
868 class DLLEXPORT DescriptionRegister
869 {
870 enum {maxelems = 100 };
871 public:
DescriptionRegister()872 DescriptionRegister() :ind(0) {
873 for (int i = 0; i < maxelems; i++) rp[i] = 0;
874 // cout << " R constructed " << (void *) this << endl;
875 }
876 #if 0
877 // removed - since otherwise one gets a runtime error when the .so is unloaded
878 // (happens with g++ only). This is a noop anyway.
879 ~DescriptionRegister() {
880 // cout << " R destructed " << (void *) this << endl;
881 }
882 #endif
883
884 static DescriptionRegister& getInstance();
885
886 void registerDriver(DriverDescription* xp);
887 void mergeRegister(ostream & out,const DescriptionRegister & src,const char * filename);
888 void explainformats(ostream & out,bool withdetails=false) const;
889 void listdrivers(ostream &out) const;
890 const DriverDescription * getDriverDescForName(const char * drivername) const;
891 const DriverDescription * getDriverDescForSuffix(const char * suffix) const;
892
893 DriverDescription* rp[maxelems];
894
nrOfDescriptions()895 int nrOfDescriptions() const { return ind; }
896 private:
897
898 int ind;
899
900 NOCOPYANDASSIGN(DescriptionRegister)
901 };
902
903 //extern DLLEXPORT DescriptionRegister* globalRp;
904 extern "C" DLLEXPORT DescriptionRegister * getglobalRp(void);
905
906 //extern __declspec ( dllexport) "C" {
907 //not needed // DescriptionRegister* getglobalRp();
908 typedef DescriptionRegister* (*getglobalRpFuncPtr)(void);
909 //}
910
911 //class Rinit
912 //{
913 //public:
914 // Rinit() { if (!globalRp) {globalRp = new DescriptionRegister; ref = 1 ; } else { ref++;} }
915 // ~Rinit() { ref--; if (ref == 0) delete globalRp; }
916 //
917 //private:
918 // static int ref;
919 //};
920
921 //static Rinit Rinit_var;
922
923 //now in drvdesc.h typedef bool (*checkfuncptr)();
924 // static bool nocheck() { return true; }
925
926 typedef bool (*checkfuncptr)(void);
927 class drvbase;
928
929 struct OptionDescription {
NameOptionDescription930 OptionDescription(const char * n = 0, const char * p = 0, const char * d = 0) :Name(n), Parameter(p), Description(d) {}
931 const char * const Name;
932 const char * const Parameter; // e.g. "String" or "numeric", or 0 (implicitly a boolean option then (no argument)
933 const char * const Description; //
934 private:
935 // OptionDescription(const OptionDescription&);
936 const OptionDescription& operator=(const OptionDescription&);
937 // no special copy ctor, assignment op or dtor needed since this class is NOT owner of the (static) strings.
938 };
939
940 // An Array of OptionDescription is delimited by an element where Name is 0
941 //FIXME const OptionDescription endofoptions(0,0,0);
942
943 //FIXME const OptionDescription nodriverspecificoptions[] = {OptionDescription("driver has no further options",0,0),endofoptions};
944
945
946 //lint -esym(1712,DriverDescription) // no default ctor
947 class DLLEXPORT DriverDescription {
948 public:
949 enum opentype {noopen, normalopen, binaryopen};
950 enum imageformat { noimage, png, bmp, eps, memoryeps }; // format to be used for transfer of raster images
951
952 DriverDescription(const char * const s_name,
953 const char * const short_expl,
954 const char * const long_expl,
955 const char * const suffix_p,
956 const bool backendSupportsSubPathes_p,
957 const bool backendSupportsCurveto_p,
958 const bool backendSupportsMerging_p, // merge a separate outline and filling of a polygon -> 1. element
959 const bool backendSupportsText_p,
960 const imageformat backendDesiredImageFormat_p,
961 const opentype backendFileOpenType_p,
962 const bool backendSupportsMultiplePages_p,
963 const bool backendSupportsClipping_p,
964 const bool nativedriver_p = true,
965 checkfuncptr checkfunc_p = 0);
~DriverDescription()966 virtual ~DriverDescription() {
967 // symbolicname = NIL; // these are const
968 // explanation= NIL;
969 // suffix= NIL;
970 // additionalInfo= NIL;
971 } //lint !e1540
972
973 virtual drvbase * CreateBackend (const char * const driveroptions_P,
974 ostream & theoutStream,
975 ostream & theerrStream,
976 const char* const nameOfInputFile,
977 const char* const nameOfOutputFile,
978 PsToEditOptions & globaloptions_p
979 ) const = 0;
980 virtual ProgramOptions * createDriverOptions() const = 0;
981
getdrvbaseVersion()982 virtual unsigned int getdrvbaseVersion() const { return 0; } // this is only needed for the driverless backends (ps/dump/gs)
983
984 const char * additionalInfo() const;
985 // Data members
986 const char * const symbolicname;
987 const char * const short_explanation;
988 const char * const long_explanation;
989 const char * const suffix;
990
991 const bool backendSupportsSubPathes;
992 const bool backendSupportsCurveto;
993 const bool backendSupportsMerging; // merge a separate outline and filling of a polygon -> 1. element
994 const bool backendSupportsText;
995 const imageformat backendDesiredImageFormat;
996 const opentype backendFileOpenType;
997 const bool backendSupportsMultiplePages;
998 const bool backendSupportsClipping;
999 const bool nativedriver;
1000 RSString filename;
1001 // where this driver is loaded from
1002 // Note: formerly this was a RSString - but that caused problems under X64 / Windows
1003 // it seems as constructing and deleting heap during start-up phase when not all DLLs are fully initialized
1004 // can cause these problems (well - I know then order of init among DLLs/SOs is not guaranteed by C++)
1005 // But the passed strings are temporary - so we need to take a copy to the heap (without destroying it later -> small leak)
1006
1007 const checkfuncptr checkfunc;
1008
1009 static const char * currentfilename; // the name of the file from which the plugin is loaded
1010
1011 NOCOPYANDASSIGN(DriverDescription)
1012 };
1013
1014 class DescriptionRegister;
1015
1016 //lint -esym(1712,DriverDescription*) // no default ctor
1017 template <class T>
1018 class DLLEXPORT DriverDescriptionT : public DriverDescription {
1019 public:
1020 DriverDescriptionT(const char * s_name,
1021 const char * short_expl_p,
1022 const char * long_expl_p,
1023 const char * suffix_p,
1024 const bool backendSupportsSubPathes_p,
1025 const bool backendSupportsCurveto_p,
1026 const bool backendSupportsMerging_p, // merge a separate outline and filling of a polygon -> 1. element
1027 const bool backendSupportsText_p,
1028 const imageformat backendDesiredImageFormat_p, // supports images from a PNG files
1029 const DriverDescription::opentype backendFileOpenType_p,
1030 const bool backendSupportsMultiplePages_p,
1031 const bool backendSupportsClipping_p,
1032 const bool nativedriver_p = true,
1033 checkfuncptr checkfunc_p = 0 ):
DriverDescription(s_name,short_expl_p,long_expl_p,suffix_p,backendSupportsSubPathes_p,backendSupportsCurveto_p,backendSupportsMerging_p,backendSupportsText_p,backendDesiredImageFormat_p,backendFileOpenType_p,backendSupportsMultiplePages_p,backendSupportsClipping_p,nativedriver_p,checkfunc_p)1034 DriverDescription(
1035 s_name,
1036 short_expl_p,
1037 long_expl_p,
1038 suffix_p,
1039 backendSupportsSubPathes_p,
1040 backendSupportsCurveto_p,
1041 backendSupportsMerging_p,
1042 backendSupportsText_p,
1043 backendDesiredImageFormat_p,
1044 backendFileOpenType_p,
1045 backendSupportsMultiplePages_p,
1046 backendSupportsClipping_p,
1047 nativedriver_p,
1048 checkfunc_p
1049 )
1050 {}
CreateBackend(const char * const driveroptions_P,ostream & theoutStream,ostream & theerrStream,const char * const nameOfInputFile,const char * const nameOfOutputFile,PsToEditOptions & globaloptions_p)1051 virtual drvbase * CreateBackend (
1052 const char * const driveroptions_P,
1053 ostream & theoutStream,
1054 ostream & theerrStream,
1055 const char* const nameOfInputFile,
1056 const char* const nameOfOutputFile,
1057 PsToEditOptions & globaloptions_p /* non const because driver can also add arguments */
1058 ) const
1059 {
1060 drvbase * backend = new T(driveroptions_P, theoutStream, theerrStream, nameOfInputFile, nameOfOutputFile, globaloptions_p, *this);
1061 return backend;
1062 }
1063
createDriverOptions()1064 ProgramOptions * createDriverOptions() const {
1065 // ProgramOptions * p = ;
1066 // cerr << "creating driver options" << (void*) p << endl;
1067 return new typename T::DriverOptions;
1068 }
1069
1070
1071 // virtual void DeleteBackend(drvbase * & ptr) const { delete (T*) ptr; ptr = 0; }
getdrvbaseVersion()1072 virtual unsigned int getdrvbaseVersion() const { return drvbaseVersion; }
1073
1074 private:
1075 // typedef DriverDescriptionT<T> SHORTNAME;
1076 // NOCOPYANDASSIGN(SHORTNAME)
1077 NOCOPYANDASSIGN(DriverDescriptionT<T>)
1078 };
1079
1080 #if !( (defined (__GNUG__) && (__GNUC__>=3) && defined (HAVE_STL)) || defined (_MSC_VER) && (_MSC_VER >= 1300) )
1081 // 1300 is MSVC.net (7.0)
1082 // 1200 is MSVC 6.0
1083 //G++3.0 comes with a STL lib that includes a definition of min and max
1084
1085 // some systems have a minmax.h which is indirectly included
1086 #ifdef min
1087 #undef min
1088 #endif
1089 #ifdef max
1090 #undef max
1091 #endif
1092
1093 #ifndef min
1094 template <class T>
min(T x,T y)1095 inline T min(T x, T y)
1096 {
1097 return (x<y) ? x:y;
1098 }
1099 #endif
1100
1101 #ifndef max
1102 template <class T>
max(T x,T y)1103 inline T max(T x, T y)
1104 {
1105 return (x>y) ? x:y;
1106 }
1107 #endif
1108
1109 #endif
1110
1111
bezpnt(float t,float z1,float z2,float z3,float z4)1112 inline float bezpnt(float t, float z1, float z2, float z3, float z4)
1113 {
1114 // Determine ordinate on Bezier curve at length "t" on curve
1115 if (t <= 0.0f) {
1116 return z1; // t = 0.0f;
1117 }
1118 if (t >= 1.0f) {
1119 return z4; // t = 1.0f;
1120 }
1121 const float t1 = (1.0f - t);
1122 return t1 * t1 * t1 * z1 + 3.0f * t * t1 * t1 * z2 + 3.0f * t * t * t1 * z3 + t * t * t * z4;
1123 }
1124
PointOnBezier(float t,const Point & p1,const Point & p2,const Point & p3,const Point & p4)1125 inline Point PointOnBezier(float t, const Point & p1, const Point & p2, const Point & p3, const Point & p4)
1126 {
1127 return Point(bezpnt(t,p1.x_,p2.x_,p3.x_,p4.x_), bezpnt(t,p1.y_,p2.y_,p3.y_,p4.y_));
1128 }
1129
1130
1131
1132
1133 #endif
1134
1135
1136
1137
1138
1139
1140
1141