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