1%%	options
2
3copyright owner	=	Dirk Krause
4copyright year	=	2017-xxxx
5SPDX-License-Identifier:	BSD-3-Clause
6
7
8%%	header
9
10/**	@file dk4gra.h	Graphics output (PS/EPS/PDF/PGF).
11
12This module contains functions to create PS/EPS/PDF/PGF graphics.
13
14Coordinates are specified in PS points, called bp in LaTeX.
1572 PS points are one inch.
16
17The origin is in the lower left corner, x values grow to the right,
18y values grow to top.
19
20Colors specified as double values are in the range from 0.0 to 1.0.
21
22For each object to draw follow an algorithm like
23
24@code
25dk4_bb_t	bb;
26
27dk4gra_set_line_width(...);
28dk4gra_set_line_style(...);
29dk4gra_set_line_cap(...);
30dk4gra_set_line_join(...);
31dk4gra_set_stroke_...(...);
32dk4gra_set_fill_...(...);
33
34if (want_a_pattern_filled_object) {
35	dk4bb_init(&bb);
36	dk4gra_prepare_fill(...);
37	construct_path(...);
38	dk4gra_fill(...);
39	dk4gra_set_gs_for_pattern_only(gra, 1, ...);
40	dk4gra_gsave(...);
41	construct_path(..., &bb, ...);
42	dk4gra_clip(...);
43	dk4gra_pattern(..., bb.xmin, bb.xmax, bb.ymin, bb.ymax, ...);
44	dk4gra_grestore(...);
45	dk4gra_set_gs_for_pattern_only(gra, 0, ...);
46	if (want_a_stroked_object) {
47		dk4gra_prepare_stroke(...);
48		construct_path(...);
49		dk4gra_stroke(...);
50	}
51}
52else {
53	if (want_a_filled_object) {
54		if (want_a_stroked_object) {
55			if (0 != dk4gra_can_fill_and_stroke(...)) {
56				dk4gra_prepare_fill_and_stroke(...);
57				construct_path(...);
58				dk4gra_fill_and_stroke(...);
59			}
60			else {
61				dk4gra_prepare_fill(...);
62				construct_path(...);
63				dk4gra_fill(...);
64				dk4gra_prepare_stroke(...);
65				construct_path(...);
66				dk4gra_stroke(...);
67			}
68		}
69		else {
70			dk4gra_prepare_fill(...);
71			construct_path(...);
72			dk4gra_fill(...);
73		}
74	}
75	else {
76		if (want_a_stroked_object) {
77			dk4gra_prepare_stroke(...);
78			construct_path(...);
79			dk4gra_stroke(...);
80		}
81	}
82}
83@endcode
84
85The dk4gra_set_fill_...() and dk4gra_set_stroke_...() functions set color
86space and color values. You must use the same color space for both
87fill and stroke color.
88*/
89
90
91
92#ifndef	DK4CONF_H_INCLUDED
93#if DK4_BUILDING_DKTOOLS4
94#include "dk4conf.h"
95#else
96#include <dktools-4/dk4conf.h>
97#endif
98#endif
99
100#ifndef	DK4MEM_H_INCLUDED
101#if DK4_BUILDING_DKTOOLS4
102#include <libdk4base/dk4mem.h>
103#else
104#include <dktools-4/dk4mem.h>
105#endif
106#endif
107
108#ifndef	DK4FONT_H_INCLUDED
109#if DK4_BUILDING_DKTOOLS4
110#include <libdk4gra/dk4font.h>
111#else
112#include <dktools-4/dk4font.h>
113#endif
114#endif
115
116#ifndef	DK4ALIGN_H_INCLUDED
117#if DK4_BUILDING_DKTOOLS4
118#include <libdk4gra/dk4align.h>
119#else
120#include <dktools-4/dk4align.h>
121#endif
122#endif
123
124#ifndef	DK4ERROR_H_INCLUDED
125#if DK4_BUILDING_DKTOOLS4
126#include <libdk4base/dk4error.h>
127#else
128#include <dktools-4/dk4error.h>
129#endif
130#endif
131
132#ifndef	DK4BB_H_INCLUDED
133#if DK4_BUILDING_DKTOOLS4
134#include <libdk4gra/dk4bb.h>
135#else
136#include <dktools-4/dk4bb.h>
137#endif
138#endif
139
140#ifndef	DK4BIFTY_H_INCLUDED
141#if DK4_BUILDING_DKTOOLS4
142#include <libdk4bif/dk4bifty.h>
143#else
144#include <dktools-4/dk4bifty.h>
145#endif
146#endif
147
148#ifndef	DK4CS_H_INCLUDED
149#if DK4_BUILDING_DKTOOLS4
150#include <libdk4bif/dk4cs.h>
151#else
152#include <dktools-4/dk4cs.h>
153#endif
154#endif
155
156#ifndef	DK4MEMBF_H_INCLUDED
157#if DK4_BUILDING_DKTOOLS4
158#include <libdk4c/dk4membuf.h>
159#else
160#include <dktools-4/dk4membuf.h>
161#endif
162#endif
163
164#ifndef	DK4MBSTRM_H_INCLUDED
165#if DK4_BUILDING_DKTOOLS4
166#include <libdk4c/dk4mbstrm.h>
167#else
168#include <dktools-4/dk4mbstrm.h>
169#endif
170#endif
171
172#ifndef	DK4FONTC_H_INCLUDED
173#if DK4_BUILDING_DKTOOLS4
174#include <libdk4gra/dk4fontc.h>
175#else
176#include <dktools-4/dk4fontc.h>
177#endif
178#endif
179
180#ifndef	DK4UC2L_H_INCLUDED
181#if DK4_BUILDING_DKTOOLS4
182#include <libdk4lat/dk4uc2l.h>
183#else
184#include <dktools-4/dk4uc2l.h>
185#endif
186#endif
187
188
189
190/**	Epsilon value for coordinates.
191	All values smaller than this are treated as 0.0.
192*/
193#define	DK4_GRA_EPSILON_COORDINATES		1.0e-5
194
195/**	Epsilon value for line widths.
196	Line width differing less are treated as equal.
197*/
198#define	DK4_GRA_EPSILON_LINEWIDTH		1.0e-3
199
200/**	Epsilon value for miter limits.
201	Miter limits differing less are treated as equal.
202*/
203#define	DK4_GRA_EPSILON_MITERLIMIT		1.0e-3
204
205
206/**	Flags for adding images to a page.
207*/
208enum {
209							/**	The image is the only page contents.
210								For PS output the gsave operator, clipping
211								and white filling at start of page are
212								removed, the grestore at end of page too.
213							*/
214	DK4_GRA_IMG_FLAG_ONLY_PAGE_CONTENTS		= 0x0001 ,
215
216							/**	Fill image background with color from background
217								chunk before applying image data.
218								Only in effect when producing PDF output in
219								DK4_CS_RGB_ALPHA or DK4_CS_GRAY_ALPHA
220								color space.
221							*/
222	DK4_GRA_IMG_FLAG_FILL_BACKGROUND		= 0x0002 ,
223
224							/**	Allow colored output.
225								Otherwise grayscaled output is enforced.
226							*/
227	DK4_GRA_IMG_FLAG_COLOR					= 0x0004 ,
228
229							/**	Allow LZW compression in PS language
230								level 2 output.
231							*/
232	DK4_GRA_IMG_FLAG_LZW					= 0x0008 ,
233
234							/**	Allow to use DCT encoded data from JPEG
235								files directly.
236							*/
237	DK4_GRA_IMG_FLAG_DCT					= 0x0010 ,
238
239							/**	Set image interpolation flag to allow
240								PS/PDF renderers to optimize representation.
241							*/
242	DK4_GRA_IMG_FLAG_INTERPOLATION			= 0x0020 ,
243
244							/**	Set image interpolation flag when directly
245								using DCT encoded data from JPEG files.
246							*/
247	DK4_GRA_IMG_FLAG_DCT_INTERPOLATION		= 0x0040 ,
248
249							/**	Analyze number of bits per component, reduce
250								if possible without quality loss.
251							*/
252	DK4_GRA_IMG_FLAG_ANALYZE_BPC			= 0x0080 ,
253
254							/**	Analyze use of colors, switch to grayscale
255								if possible without quality loss.
256							*/
257	DK4_GRA_IMG_FLAG_ANALYZE_COLOR			= 0x0100 ,
258
259							/**	Analyze use of alpha channel data, ignore
260								alpha data if all pixels have full opacity.
261							*/
262	DK4_GRA_IMG_FLAG_ANALYZE_ALPHA			= 0x0200 ,
263
264							/**	Allow to rotate the image to fit paper size.
265							*/
266	DK4_GRA_IMG_FLAG_ALLOW_ROTATION			= 0x0400 ,
267
268							/**	Ignore image resolution saved in file.
269							*/
270	DK4_GRA_IMG_FLAG_IGNORE_RESOLUTION		= 0x0800 ,
271
272							/**	Ignore aspect ratio, allow distorsion while
273								filling the specified image range completely.
274							*/
275	DK4_GRA_IMG_FLAG_IGNORE_ASPECT_RATIO	= 0x1000,
276
277							/**	Allow re-use of DCT-encoded data from JPEG
278								files even when shrinking the image for
279								size restrictions.
280							*/
281	DK4_GRA_IMG_FLAG_DCT_RS					= 0x2000
282
283};
284
285
286
287/**	Text flags for use with
288	dk4gra_pgf_simple_text(),
289	dk4gra_pgf_special_text(),
290	dk4gra_app_pgf_simple_text(),
291	dk4gra_app_pgf_special_text(),
292	dk4pppt_simple_text(),
293	and dk4pppt_special_text(), can be or-combined.
294*/
295enum {
296									/**	Draw oval box around text.
297									*/
298	DK4_GRA_TEXT_FLAG_OVAL_BOX		=	0x0001 ,
299
300									/**	Put white box around text and oval box.
301									*/
302	DK4_GRA_TEXT_FLAG_WHITE_BOX		=	0x0002
303};
304
305
306
307/**	Output driver to choose.
308*/
309typedef enum {
310	DK4_GRA_DRIVER_PDF		= 0,	/**< Produce PDF file. */
311	DK4_GRA_DRIVER_EPS ,			/**< Produce EPS file. */
312	DK4_GRA_DRIVER_PS ,				/**< Produce PS file. */
313	DK4_GRA_DRIVER_PGF ,			/**< Produce PGF file. */
314	DK4_GRA_DRIVER_BB				/**< Produce bounding box file. */
315} dk4_gra_driver_t;
316
317
318
319/**	Intended purpose for output.
320*/
321typedef enum {
322	DK4_GRA_PURPOSE_OBJECT	= 0 ,	/**< Object to include in a document. */
323	DK4_GRA_PURPOSE_IMAGE ,			/**< Standalone image. */
324	DK4_GRA_PURPOSE_DOCUMENT		/**< Document for viewing or printing. */
325} dk4_gra_purpose_t;
326
327
328
329/**	Line styles.
330*/
331typedef enum {
332	DK4_GRA_LS_SOLID		= 0 ,	/**< Solid line. */
333	DK4_GRA_LS_DASH ,				/**< Dashed line. */
334	DK4_GRA_LS_DOT ,				/**< Dotted line. */
335	DK4_GRA_LS_DASH_DOT ,			/**< Dash dot line. */
336	DK4_GRA_LS_DASH_DOT_DOT ,		/**< Dash dot dot line. */
337	DK4_GRA_LS_DASH_DOT_DOT_DOT		/**< Dash dot dot dot line. */
338} dk4_gra_ls_t;
339
340
341/**	Line cap styles.
342*/
343typedef enum {
344	DK4_GRA_LC_BUTTED	= 0,	/**< Line finished exactly at point. */
345	DK4_GRA_LC_ROUNDED ,		/**< Half circle added at each line end. */
346	DK4_GRA_LC_PROJECTING		/**< Half square added at each line end. */
347} dk4_gra_lc_t;
348
349
350/**	Line join styles.
351*/
352typedef enum {
353	DK4_GRA_LJ_MITERED	= 0,	/**< Pointed. */
354	DK4_GRA_LJ_ROUNDED ,		/**< Rounded. */
355	DK4_GRA_LJ_BEVELED			/**< Cutted point. */
356} dk4_gra_lj_t;
357
358
359/**	Flags for new pages. Or-combinations allowed.
360*/
361enum {
362								/**	Do not set clip path.
363								*/
364	DK4_GRA_PAGE_FLAG_NO_CLIP	= 0x0001 ,
365
366								/**	Do not fill background in white.
367								*/
368	DK4_GRA_PAGE_FLAG_NO_BG		= 0x0002 ,
369
370								/**	Use uncompressed PDF page stream.
371									Intended for debugging purposes only.
372								*/
373	DK4_GRA_PAGE_FLAG_NOT_COMPRESSED	= 0x0004 ,
374
375								/**	Use front side and back side of paper.
376								*/
377	DK4_GRA_DOC_FLAG_DUPLEX				= 0x0200 ,
378
379								/**	Use front side and back side of paper,
380									binding like a calendar.
381								*/
382	DK4_GRA_DOC_FLAG_TUMBLE				= 0x0400 ,
383
384								/**	Force use of grayscaled output
385									instead of colors.
386								*/
387	DK4_GRA_DOC_FLAG_FORCE_GRAY			= 0x0800 ,
388
389								/**	Use PS level 2 instead of level 3.
390								*/
391	DK4_GRA_DOC_FLAG_PS2				= 0x1000 ,
392
393								/**	Produce document structuring comments.
394								*/
395	DK4_GRA_DOC_FLAG_PS_DSC				= 0x2000 ,
396
397								/**	Produce EPS instead of normal PS.
398								*/
399	DK4_GRA_DOC_FLAG_EPS				= 0x4000
400};
401
402
403
404/**	Fill patterns.
405*/
406typedef enum {
407	/**	Diagonal lines 30 degrees to the left.
408	*/
409	DK4_GRA_PATTERN_30_DEGREE_LEFT	= 0,
410
411	/**	Diagonal lines 30 degrees to the right.
412	*/
413	DK4_GRA_PATTERN_30_DEGREE_RIGHT ,
414
415	/**	Crosshatch of lines 30 degrees to the left and right.
416	*/
417	DK4_GRA_PATTERN_30_DEGREE_SIEVE ,
418
419	/**	Diagonal lines 45 degrees to the left.
420	*/
421	DK4_GRA_PATTERN_45_DEGREE_LEFT ,
422
423	/**	Diagonal lines 45 degrees to the left.
424	*/
425	DK4_GRA_PATTERN_45_DEGREE_RIGHT ,
426
427	/**	Crosshatch of lines 45 degrees to the left and right.
428	*/
429	DK4_GRA_PATTERN_45_DEGREE_SIEVE ,
430
431	/**	Horizontal bricks.
432	*/
433	DK4_GRA_PATTERN_HORIZONTAL_BRICKS ,
434
435	/**	Vertical bricks.
436	*/
437	DK4_GRA_PATTERN_VERTICAL_BRICKS ,
438
439	/**	Horizontal lines.
440	*/
441	DK4_GRA_PATTERN_HORIZONTAL_LINES ,
442
443	/**	Vertical lines.
444	*/
445	DK4_GRA_PATTERN_VERTICAL_LINES ,
446
447	/**	Crosshatch of horizontal and vertical lines.
448	*/
449	DK4_GRA_PATTERN_HORIZONTAL_VERTICAL_SIEVE ,
450
451	/**	Horizontal shingles skewed to the left.
452	*/
453	DK4_GRA_PATTERN_HORIZONTAL_SHINGLES_LEFT ,
454
455	/**	Horizontal shingles skewed to the right.
456	*/
457	DK4_GRA_PATTERN_HORIZONTAL_SHINGLES_RIGHT ,
458
459	/**	Vertical shingles skewed to one side.
460	*/
461	DK4_GRA_PATTERN_VERTICAL_SHINGLES_1 ,
462
463	/**	Vertical shingles skewed to the other side.
464	*/
465	DK4_GRA_PATTERN_VERTICAL_SHINGLES_2 ,
466
467	/**	Large fish scales.
468	*/
469	DK4_GRA_PATTERN_LARGE_FISH_SCALES ,
470
471	/**	Small fish scales.
472	*/
473	DK4_GRA_PATTERN_SMALL_FISH_SCALES ,
474
475	/**	Circles.
476	*/
477	DK4_GRA_PATTERN_CIRCLES ,
478
479	/**	Hexagons.
480	*/
481	DK4_GRA_PATTERN_HEXAGONS ,
482
483	/**	Octagons.
484	*/
485	DK4_GRA_PATTERN_OCTAGONS ,
486
487	/**	Horizontal tire treads.
488	*/
489	DK4_GRA_PATTERN_HORIZONTAL_TIRES ,
490
491	/**	Vertical tire treads.
492	*/
493	DK4_GRA_PATTERN_VERTICAL_TIRES
494
495} dk4_gra_pattern_t;
496
497
498
499/**	Maximum pattern number.
500*/
501enum {
502	/**	Maximum pattern number.
503	*/
504	DK4_GRA_PATTERN_MAX = DK4_GRA_PATTERN_VERTICAL_TIRES
505};
506
507
508
509/**	Type of preamble line to add.
510*/
511enum {
512	DK4_GRA_PREAMBLE_FONT	= 0 ,	/**< Line to load font package. */
513	DK4_GRA_PREAMBLE_PACKAGE ,		/**< Line to load other packages. */
514	DK4_GRA_PREAMBLE_OTHER			/**< Any other configuration line. */
515};
516
517
518
519/**	Output structure to produce a PS or EPS file.
520*/
521typedef struct {
522	int				 llev;		/**< PS language level. */
523	int				 dsc;		/**< Flag: Write DSC comments. */
524	int				 fspd;		/**< Flag: Use setpagedevice for paper size. */
525	int				 fdu;		/**< Flag: Duplex. */
526	int				 ftu;		/**< Flag: Duplex and tumble. */
527} dk4_gra_ps_output_t;
528
529
530
531/**	Output structure to produce a PDF file.
532*/
533typedef struct {
534	dk4_sto_t		*s_imagno;	/**< Images container by object number. */
535	dk4_sto_it_t	*i_imagno;	/**< Images iterator. */
536	dk4_sto_t		*s_images;	/**< Images container by data source. */
537	dk4_sto_it_t	*i_images;	/**< Images iterator. */
538	dk4_sto_t		*s_objpos;	/**< Object positions container. */
539	dk4_sto_it_t	*i_objpos;	/**< Object positions iterator. */
540	size_t			 nextobj;	/**< Object number of next XObject. */
541	size_t			 unxo;		/**< Number of XObjects without file name. */
542} dk4_gra_pdf_output_t;
543
544
545
546/**	Output structure to produce a PGF file.
547*/
548typedef struct {
549	dk4_font_collector_t	*fc;		/**< Font collector. */
550	dk4_sto_t				*s_imagno;	/**< Images container by number. */
551	dk4_sto_it_t			*i_imagno;	/**< Images iterator. */
552	dk4_sto_t				*s_images;	/**< Images container by data source. */
553	dk4_sto_it_t			*i_images;	/**< Images iterator. */
554	dk4_sto_t				*s_prelfo;	/**< Containter for font setup. */
555	dk4_sto_it_t			*i_prelfo;	/**< Font setup iterator. */
556	dk4_sto_t				*s_prelpa;	/**< Container for packages. */
557	dk4_sto_it_t			*i_prelpa;	/**< Packages iterator. */
558	dk4_sto_t				*s_prelot;	/**< Container for other setup. */
559	dk4_sto_it_t			*i_prelot;	/**< Other setup iterator. */
560	double					 dfs;		/**< Document font size. */
561	size_t					 n_images;	/**< Next image number. */
562	size_t					 n_prelfo;	/**< Number of font setup lines. */
563	size_t					 n_prelpa;	/**< Number of package setup lines. */
564	size_t					 n_prelot;	/**< Number of other setup lines. */
565	int						 sa;		/**< Flag: Produce standalone doc. */
566} dk4_gra_pgf_output_t;
567
568
569
570/**	Union of output structure types.
571*/
572typedef union {
573	dk4_gra_ps_output_t		 ps;		/**< Produce PS/EPS output. */
574	dk4_gra_pdf_output_t	 pdf;		/**< Produce PDF output. */
575	dk4_gra_pgf_output_t	 pgf;		/**< Produce PGF output. */
576} dk4_gra_all_output_t;
577
578
579
580/**	Output structure to produce a graphics file.
581*/
582typedef struct {
583	dk4_gra_all_output_t	 out;	/**< Output structure. */
584	dk4_cs_conv_ctx_t		 cscctx;	/**< Color space conversion context. */
585	dk4_sto_t				*s_pages;	/**< Pages container. */
586	dk4_sto_it_t			*i_pages;	/**< Iterator through container. */
587	dkChar					*fn;	/**< Output file name. */
588	void					*curpg;	/**< Current page. */
589	double					 cur_x;	/**< Current x position. */
590	double					 cur_y;	/**< Current y position. */
591	double					 patlw;	/**< Pattern line width. */
592	size_t					 pages;	/**< Number of pages. */
593	size_t					 w;		/**< Image width. */
594	size_t					 h;		/**< Image height. */
595	int						 dr;	/**< Output driver. */
596	int						 gscp;	/**< Flag: Graphics state pattern clip. */
597	int						 eor;	/**< Flag: Use even-odd-rule fill clip. */
598	int						 le;	/**< Previous error. */
599	int						 lec;	/**< Previous error code. */
600	int						 len;	/**< Number how often previous error. */
601	int						 docfl;	/**< Document flag set. */
602} dk4_gra_t;
603
604
605
606/**	Point coordinates in a graphics.
607*/
608typedef struct {
609	double	x;						/**< X value. */
610	double	y;						/**< Y value. */
611} dk4_gra_point_t;
612
613
614
615#ifdef	__cplusplus
616extern "C" {
617#endif
618
619
620/**	Open output structure to create a PDF file.
621	@param	fn		File name for output file, NULL for standard output.
622	@param	w		Image width in bp.
623	@param	h		Image height in bp.
624	@param	docfl	Document flags.
625	The flags can contain both document and page flags, page flags
626	here are applied as default page flags for pages added by the
627	dk4gra_page() function.
628
629	The following document flags are available:
630
631					- DK4_GRA_DOC_FLAG_PS2<br>
632					  to produce PS level 2 instead of level 3,
633					- DK4_GRA_DOC_FLAG_EPS<br>
634					  to produce EPS instead of PS,
635					- DK4_GRA_DOC_FLAG_PS_DSC<br>
636					  to write document structuring comments,
637					- DK4_GRA_DOC_FLAG_FORCE_GRAY<br>
638					  to enforce grayscaled output.
639
640	The following page flags are available:
641
642					- DK4_GRA_PAGE_FLAG_NO_CLIP<br>
643					  to skip setting the clip path to page size,
644					- DK4_GRA_PAGE_FLAG_NO_BG<br>
645					  to skip filling the page with a white background,
646					- DK4_GRA_PAGE_FLAG_NOT_COMPRESSED<br>
647					  to create an uncompressed page contents stream
648					  in PDF output (intended for debugging only).
649
650	@param	erp		Error report, may be NULL.
651	@return	Valid pointer to new structure on success, NULL on error.
652
653	Error codes:
654	- DK4_E_INVALID_ARGUMENTS<br>
655	  if fn is NULL, w or h is 0,
656	- DK4_E_MATH_OVERFLOW<br>
657	  on numeric overflow in memory size calculation,
658	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
659	  if there is not enough memory available.
660*/
661
662dk4_gra_t *
663dk4gra_open_pdf(
664	const dkChar	*fn,
665	size_t			 w,
666	size_t			 h,
667	int				 docfl,
668	dk4_er_t		*erp
669);
670
671
672/**	Open output structure to create a PS or EPS file.
673	@param	fn		File name for output file, NULL for standard output.
674	@param	w		Image width in bp.
675	@param	h		Image height in bp.
676	@param	docfl	Document flags.
677	The flags can contain both document and page flags, page flags
678	here are applied as default page flags for pages added by the
679	dk4gra_page() function.
680	@param	erp		Error report, may be NULL.
681	@return	Valid pointer to new structure on success, NULL on error.
682
683	Error codes:
684	- DK4_E_INVALID_ARGUMENTS<br>
685	  if fn is NULL, w or h is 0 or ll is neither 2 nor 3.
686	- DK4_E_MATH_OVERFLOW<br>
687	  on numeric overflow in memory size calculation,
688	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
689	  if there is not enough memory available.
690*/
691
692dk4_gra_t *
693dk4gra_open_ps(
694	const dkChar	*fn,
695	size_t			 w,
696	size_t			 h,
697	int				 docfl,
698	dk4_er_t		*erp
699);
700
701
702/**	Open output structure to create a PGF file.
703	@param	fn		File name for output file, NULL for standard output.
704	@param	w		Image width in bp.
705	@param	h		Image height in bp.
706	@param	docfl	Document flags.
707	The flags can contain both document and page flags, page flags
708	here are applied as default page flags for pages added by the
709	dk4gra_page() function.
710	@param	sa		Flag: Produce standalone TeX file.
711	@param	erp		Error report, may be NULL.
712	@return	Valid pointer to new structure on success, NULL on error.
713
714	Error codes:
715
716	- DK4_E_INVALID_ARGUMENTS<br>
717	  if fn is NULL, w or h is 0,
718	- DK4_E_MATH_OVERFLOW<br>
719	  on numeric overflow in memory size calculation,
720	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
721	  if there is not enough memory available.
722*/
723
724dk4_gra_t *
725dk4gra_open_pgf(
726	const dkChar	*fn,
727	size_t			 w,
728	size_t			 h,
729	int				 docfl,
730	int				 sa,
731	dk4_er_t		*erp
732);
733
734
735/**	Set color space conversion context.
736	@param	gra		Output structure.
737	@param	ctx		Color space conversion context to copy.
738	@param	backptr	Address of success variable to reset on error.
739	@param	erp		Error report, may be NULL.
740
741	Error codes:
742	- DK4_E_INVALID_ARGUMENTS<br>
743	  if gra or ctx is NULL.
744*/
745
746void
747dk4gra_set_color_conversion(
748	dk4_gra_t				*gra,
749	dk4_cs_conv_ctx_t const	*ctx,
750	int						*backptr,
751	dk4_er_t				*erp
752);
753
754
755/**	Write output file and close output structure.
756	@param	gra		Output structure.
757	@param	erp		Error report, may be NULL.
758	@param	backptr	Address of success variable to reset on errors.
759
760	Error codes:
761	- DK4_E_INVALID_ARGUMENTS<br>
762	  if gra is NULL or in a state allowing this operation,
763	- DK4_E_WRITE_FAILED<br>
764	  if writing one ore multiple bytes to the stream failed,
765	- DK4_E_FLUSH_FAILED<br>
766	  if flushing data downwards failed.
767
768*/
769
770void
771dk4gra_write_and_close(
772	dk4_gra_t		*gra,
773	int				*backptr,
774	dk4_er_t		*erp
775);
776
777
778/**	Write output file and close output structure.
779	@param	fout	Output file already opened.
780	@param	gra		Output structure.
781	@param	erp		Error report, may be NULL.
782	@param	backptr	Address of success variable to reset on errors.
783
784	Error codes:
785	- DK4_E_INVALID_ARGUMENTS<br>
786	  if gra is NULL,
787	- DK4_E_INVALID_ARGUMENTS<br>
788	  if gra is not in a state allowing this operation,
789	- DK4_E_WRITE_FAILED<br>
790	  if writing one ore multiple bytes to the stream failed,
791	- DK4_E_FLUSH_FAILED<br>
792	  if flushing data downwards failed.
793*/
794void
795dk4gra_write_file_and_close(
796	FILE			*fout,
797	dk4_gra_t		*gra,
798	int				*backptr,
799	dk4_er_t		*erp
800);
801
802
803/**	Close output structure (without writing output file).
804	You might want to use this function instead of dk4gra_write_and_close()
805	if the drawing functions indicated an error.
806	@param	gra	Output structure.
807
808*/
809
810void
811dk4gra_close(
812	dk4_gra_t		*gra
813);
814
815
816/**	Start new page.
817	Default flags are used for the page:
818	- The clip path is set to the image dimensions.
819	- Background is filled white.
820	- For PDF the contents stream is compressed.
821	To start a new page with different setup, use dk4gra_page_with_flags()
822	instead and specify flags.
823	@param	gra		Output structure.
824	@param	erp		Error report, may be NULL.
825	@param	backptr	Address of success variable to reset on errors.
826
827	Error codes:
828	- DK4_E_INVALID_ARGUMENTS<br>
829	  if gra is NULL, or in a state allowing this operation,
830	- DK4_E_MATH_OVERFLOW<br>
831	  on numeric overflow in memory size calculation,
832	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
833	  if there is not enough memory available,
834	- DK4_E_WRITE_FAILED<br>
835	  if writing one ore multiple bytes to the stream failed,
836	- DK4_E_FLUSH_FAILED<br>
837	  if flushing data downwards failed.
838*/
839
840void
841dk4gra_page(
842	dk4_gra_t		*gra,
843	int				*backptr,
844	dk4_er_t		*erp
845);
846
847
848/**	Start new page with non-default setup.
849	@param	gra		Output structure.
850	@param	flags	Or-combined flags:
851					- DK4_GRA_PAGE_FLAG_NO_CLIP<br>
852					  to avoid setting the clip path at start of page,
853					- DK4_GRA_PAGE_FLAG_NO_BG<br>
854					  to avoid white background filling,
855					- DK4_GRA_PAGE_FLAG_NOT_COMPRESSED<br>
856					  to avoid compression of page content stream in PDF.
857	@param	backptr	Address of success variable to reset on errors.
858	@param	erp		Error report, may be NULL.
859
860	Error codes:
861	- DK4_E_INVALID_ARGUMENTS<br>
862	  if gra is NULL or not in a state allowing this operation,
863	- DK4_E_MATH_OVERFLOW<br>
864	  on numeric overflow in memory size calculation,
865	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
866	  if there is not enough memory available,
867	- DK4_E_WRITE_FAILED<br>
868	  if writing one ore multiple bytes to the stream failed,
869	- DK4_E_FLUSH_FAILED<br>
870	  if flushing data downwards failed.
871*/
872
873void
874dk4gra_page_with_flags(
875	dk4_gra_t		*gra,
876	int				 flags,
877	int				*backptr,
878	dk4_er_t		*erp
879);
880
881
882/**	Set flag for simplified gsave/grestore handling.
883	Set this flag, if you use gsave and grestore only when dealing
884	with clip path for pattern filling.
885	@param	gra	Output structure.
886	@param	val	New flag value.
887	@param	erp	Error report, may be NULL.
888
889	Error codes:
890	- DK4_E_INVALID_ARGUMENTS<br>
891	  if gra is NULL.
892*/
893void
894dk4gra_set_gs_for_pattern_only(
895	dk4_gra_t		*gra,
896	int				 val,
897	dk4_er_t		*erp
898);
899
900
901/**	Save current graphics state (especially clip path).
902	@param	gra		Output structure.
903	@param	erp		Error report, may be NULL.
904	@param	backptr	Address of success variable to reset on errors.
905
906	Error codes:
907	- DK4_E_INVALID_ARGUMENTS<br>
908	  if gra is NULL or not in a state allowing this operation,
909	- DK4_E_MATH_OVERFLOW<br>
910	  on numeric overflow in memory size calculation,
911	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
912	  if there is not enough memory available,
913	- DK4_E_WRITE_FAILED<br>
914	  if writing one ore multiple bytes to the stream failed,
915	- DK4_E_FLUSH_FAILED<br>
916	  if flushing data downwards failed.
917*/
918
919void
920dk4gra_gsave(
921	dk4_gra_t		*gra,
922	int				*backptr,
923	dk4_er_t		*erp
924);
925
926
927/**	Restore graphics state (especially clip path).
928	@param	gra		Output structure.
929	@param	backptr	Address of success variable to reset on errors.
930	@param	erp		Error report, may be NULL.
931
932	Error codes:
933	- DK4_E_INVALID_ARGUMENTS<br>
934	  if gra is NULL or not in a state allowing this operation,
935	- DK4_E_MATH_OVERFLOW<br>
936	  on numeric overflow in memory size calculation,
937	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
938	  if there is not enough memory available,
939	- DK4_E_WRITE_FAILED<br>
940	  if writing one ore multiple bytes to the stream failed,
941	- DK4_E_FLUSH_FAILED<br>
942	  if flushing data downwards failed.
943*/
944
945void
946dk4gra_grestore(
947	dk4_gra_t		*gra,
948	int				*backptr,
949	dk4_er_t		*erp
950);
951
952
953
954/**	Set line width.
955	@param	gra		Output structure.
956	@param	lw		Line width in bp.
957	@param	backptr	Address of success variable to reset on errors.
958	@param	erp		Error report, may be NULL.
959
960	Error codes:
961	- DK4_E_INVALID_ARGUMENTS<br>
962	  if gra is NULL or not in a state allowing this operation.
963*/
964
965void
966dk4gra_set_line_width(
967	dk4_gra_t		*gra,
968	double			 lw,
969	int				*backptr,
970	dk4_er_t		*erp
971);
972
973
974/**	Set line style.
975	@param	gra		Output structure.
976	@param	ls		Line style.
977	@param	sv		Style value (dash length in bp).
978	@param	backptr	Address of success variable to reset on errors.
979	@param	erp		Error report, may be NULL.
980
981	Error codes:
982	- DK4_E_INVALID_ARGUMENTS<br>
983	  if gra is NULL or not in a state allowing this operation.
984*/
985
986void
987dk4gra_set_line_style(
988	dk4_gra_t		*gra,
989	dk4_gra_ls_t	 ls,
990	double			 sv,
991	int				*backptr,
992	dk4_er_t		*erp
993);
994
995
996/**	Set line cap.
997	@param	gra		Output structure.
998	@param	lc		Line cap type.
999	@param	backptr	Address of success variable to reset on errors.
1000	@param	erp		Error report, may be NULL.
1001
1002	Error codes:
1003	- DK4_E_INVALID_ARGUMENTS<br>
1004	  if gra is NULL or not in a state allowing this operation.
1005*/
1006
1007void
1008dk4gra_set_line_cap(
1009	dk4_gra_t		*gra,
1010	dk4_gra_lc_t	 lc,
1011	int				*backptr,
1012	dk4_er_t		*erp
1013);
1014
1015
1016/**	Set line join.
1017	@param	gra		Output structure.
1018	@param	lj		Line join type.
1019	@param	ml		Miter limit, only used if lj is DK4_GRA_LJ_MITERED.
1020	@param	backptr	Address of success variable to reset on errors.
1021	@param	erp		Error report, may be NULL.
1022
1023	Error codes:
1024	- DK4_E_INVALID_ARGUMENTS<br>
1025	  if gra is NULL or not in a state allowing this operation.
1026*/
1027
1028void
1029dk4gra_set_line_join(
1030	dk4_gra_t		*gra,
1031	dk4_gra_lj_t	 lj,
1032	double			 ml,
1033	int				*backptr,
1034	dk4_er_t		*erp
1035);
1036
1037
1038/**	Set fill color to gray.
1039	@param	gra		Output structure.
1040	@param	g		Gray value in interval 0 to 1.
1041	@param	backptr	Address of success variable to reset on errors.
1042	@param	erp		Error report, may be NULL.
1043
1044	Error codes:
1045	- DK4_E_INVALID_ARGUMENTS<br>
1046	  if gra is NULL or not in a state allowing this operation.
1047*/
1048
1049void
1050dk4gra_set_fill_gray(
1051	dk4_gra_t		*gra,
1052	double			 g,
1053	int				*backptr,
1054	dk4_er_t		*erp
1055);
1056
1057
1058/**	Set fill color to RGB.
1059	@param	gra		Output structure.
1060	@param	r		Red value in interval 0 to 1.
1061	@param	g		Green value in interval 0 to 1.
1062	@param	b		Blue value in interval 0 to 1.
1063	@param	backptr	Address of success variable to reset on errors.
1064	@param	erp		Error report, may be NULL.
1065
1066	Error codes:
1067	- DK4_E_INVALID_ARGUMENTS<br>
1068	  if gra is NULL or not in a state allowing this operation.
1069*/
1070
1071void
1072dk4gra_set_fill_rgb(
1073	dk4_gra_t		*gra,
1074	double			 r,
1075	double			 g,
1076	double			 b,
1077	int				*backptr,
1078	dk4_er_t		*erp
1079);
1080
1081
1082/**	Set fill color to CMYK.
1083	@param	gra		Output structure.
1084	@param	c		Cyan value in interval 0 to 1.
1085	@param	m		Magenta value in interval 0 to 1.
1086	@param	y		Yellow value in interval 0 to 1.
1087	@param	k		Black value in interval 0 to 1.
1088	@param	backptr	Address of success variable to reset on errors.
1089	@param	erp		Error report, may be NULL.
1090
1091	Error codes:
1092	- DK4_E_INVALID_ARGUMENTS<br>
1093	  if gra is NULL or not in a state allowing this operation.
1094*/
1095
1096void
1097dk4gra_set_fill_cmyk(
1098	dk4_gra_t		*gra,
1099	double			 c,
1100	double			 m,
1101	double			 y,
1102	double			 k,
1103	int				*backptr,
1104	dk4_er_t		*erp
1105);
1106
1107
1108/**	Set stroke color to gray.
1109	@param	gra		Output structure.
1110	@param	g		Gray value in interval 0 to 1.
1111	@param	backptr	Address of success variable to reset on errors.
1112	@param	erp		Error report, may be NULL.
1113
1114	Error codes:
1115	- DK4_E_INVALID_ARGUMENTS<br>
1116	  if gra is NULL or not in a state allowing this operation.
1117*/
1118
1119void
1120dk4gra_set_stroke_gray(
1121	dk4_gra_t		*gra,
1122	double			 g,
1123	int				*backptr,
1124	dk4_er_t		*erp
1125);
1126
1127
1128/**	Set stroke color to RGB.
1129	@param	gra		Output structure.
1130	@param	r		Red value in interval 0 to 1.
1131	@param	g		Green value in interval 0 to 1.
1132	@param	b		Blue value in interval 0 to 1.
1133	@param	backptr	Address of success variable to reset on errors.
1134	@param	erp		Error report, may be NULL.
1135
1136	Error codes:
1137	- DK4_E_INVALID_ARGUMENTS<br>
1138	  if gra is NULL or not in a state allowing this operation.
1139*/
1140
1141void
1142dk4gra_set_stroke_rgb(
1143	dk4_gra_t		*gra,
1144	double			 r,
1145	double			 g,
1146	double			 b,
1147	int				*backptr,
1148	dk4_er_t		*erp
1149);
1150
1151
1152/**	Set stroke color to CMYK.
1153	@param	gra		Output structure.
1154	@param	c		Cyan value in interval 0 to 1.
1155	@param	m		Magenta value in interval 0 to 1.
1156	@param	y		Yellow value in interval 0 to 1.
1157	@param	k		Black value in interval 0 to 1.
1158	@param	backptr	Address of success variable to reset on errors.
1159	@param	erp		Error report, may be NULL.
1160
1161	Error codes:
1162	- DK4_E_INVALID_ARGUMENTS<br>
1163	  if gra is NULL or not in a state allowing this operation.
1164*/
1165
1166void
1167dk4gra_set_stroke_cmyk(
1168	dk4_gra_t		*gra,
1169	double			 c,
1170	double			 m,
1171	double			 y,
1172	double			 k,
1173	int				*backptr,
1174	dk4_er_t		*erp
1175);
1176
1177
1178
1179/**	Prepare output structure for a fill operation.
1180	Use this function before you start to construct a path you plan to fill.
1181	@param	gra		Output structure.
1182	@param	backptr	Address of success variable to reset on errors.
1183	@param	erp		Error report, may be NULL.
1184
1185	Error codes:
1186	- DK4_E_INVALID_ARGUMENTS<br>
1187	  if gra is NULL or not in a state allowing this operation,
1188	- DK4_E_MATH_OVERFLOW<br>
1189	  on numeric overflow in memory size calculation,
1190	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1191	  if there is not enough memory available,
1192	- DK4_E_WRITE_FAILED<br>
1193	  if writing one ore multiple bytes to the stream failed,
1194	- DK4_E_FLUSH_FAILED<br>
1195	  if flushing data downwards failed.
1196*/
1197
1198void
1199dk4gra_prepare_fill(
1200	dk4_gra_t	*gra,
1201	int			*backptr,
1202	dk4_er_t	*erp
1203);
1204
1205
1206/**	Prepare output structure for a stroke operation.
1207	Use this function before you start to construct a path you plan to stroke.
1208	@param	gra		Output structure.
1209	@param	backptr	Address of success variable to reset on errors.
1210	@param	erp		Error report, may be NULL.
1211
1212	Error codes:
1213	- DK4_E_INVALID_ARGUMENTS<br>
1214	  if gra is NULL or not in a state allowing this operation,
1215	- DK4_E_MATH_OVERFLOW<br>
1216	  on numeric overflow in memory size calculation,
1217	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1218	  if there is not enough memory available,
1219	- DK4_E_WRITE_FAILED<br>
1220	  if writing one ore multiple bytes to the stream failed,
1221	- DK4_E_FLUSH_FAILED<br>
1222	  if flushing data downwards failed.
1223*/
1224
1225void
1226dk4gra_prepare_stroke(
1227	dk4_gra_t	*gra,
1228	int			*backptr,
1229	dk4_er_t	*erp
1230);
1231
1232
1233/**	Prepare output structure for a combined fill and stroke operation.
1234	Use this function before you start to construct a path you plan to
1235	fill and stroke.
1236	@param	gra		Output structure.
1237	@param	backptr	Address of success variable to reset on errors.
1238	@param	erp		Error report, may be NULL.
1239
1240	Error codes:
1241	- DK4_E_INVALID_ARGUMENTS<br>
1242	  if gra is NULL or not in a state allowing this operation,
1243	- DK4_E_MATH_OVERFLOW<br>
1244	  on numeric overflow in memory size calculation,
1245	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1246	  if there is not enough memory available,
1247	- DK4_E_WRITE_FAILED<br>
1248	  if writing one ore multiple bytes to the stream failed,
1249	- DK4_E_FLUSH_FAILED<br>
1250	  if flushing data downwards failed.
1251*/
1252
1253void
1254dk4gra_prepare_fill_and_stroke(
1255	dk4_gra_t	*gra,
1256	int			*backptr,
1257	dk4_er_t	*erp
1258);
1259
1260
1261/**	Check whether a combined fill and close operation is available
1262	for an output structure.
1263	@param	gra	Output structure to test.
1264	@return	1 if a fill-and-close operation is available, 0 otherwise.
1265*/
1266
1267int
1268dk4gra_can_fill_and_stroke(
1269	const dk4_gra_t	*gra
1270);
1271
1272
1273/**	Fill current path.
1274	Note: Use dk4gra_prepare_fill() before you start to construct a path
1275	you plan to fill.
1276	The value of the even-odd-rule flag is used to choose either
1277	even-odd-rule or nonzero-winding-rule, the dk4gra_set_eorule() function
1278	can be used to set the flag.
1279	@param	gra		Output structure.
1280	@param	backptr	Address of success variable to reset on errors.
1281	@param	erp		Error report, may be NULL.
1282
1283	Error codes:
1284	- DK4_E_INVALID_ARGUMENTS<br>
1285	  if gra is NULL or not in a state allowing this operation,
1286	- DK4_E_MATH_OVERFLOW<br>
1287	  on numeric overflow in memory size calculation,
1288	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1289	  if there is not enough memory available,
1290	- DK4_E_WRITE_FAILED<br>
1291	  if writing one ore multiple bytes to the stream failed,
1292	- DK4_E_FLUSH_FAILED<br>
1293	  if flushing data downwards failed.
1294*/
1295
1296void
1297dk4gra_fill(
1298	dk4_gra_t		*gra,
1299	int				*backptr,
1300	dk4_er_t		*erp
1301);
1302
1303
1304/**	Stroke current path.
1305	Note: Use dk4gra_prepare_stroke() before you start to construct a path
1306	you plan to stroke.
1307	@param	gra		Output structure.
1308	@param	backptr	Address of success variable to reset on errors.
1309	@param	erp		Error report, may be NULL.
1310
1311	Error codes:
1312	- DK4_E_INVALID_ARGUMENTS<br>
1313	  if gra is NULL or not in a state allowing this operation,
1314	- DK4_E_MATH_OVERFLOW<br>
1315	  on numeric overflow in memory size calculation,
1316	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1317	  if there is not enough memory available,
1318	- DK4_E_WRITE_FAILED<br>
1319	  if writing one ore multiple bytes to the stream failed,
1320	- DK4_E_FLUSH_FAILED<br>
1321	  if flushing data downwards failed.
1322*/
1323
1324void
1325dk4gra_stroke(
1326	dk4_gra_t		*gra,
1327	int				*backptr,
1328	dk4_er_t		*erp
1329);
1330
1331
1332/**	Fill and stroke current path.
1333	Note: Use dk4gra_prepare_fill_and_stroke() before you start to construct
1334	a path you plan to fill and stroke.
1335	The value of the even-odd-rule flag is used to choose either
1336	even-odd-rule or nonzero-winding-rule, the dk4gra_set_eorule() function
1337	can be used to set the flag.
1338	@param	gra		Output structure.
1339	@param	backptr	Address of success variable to reset on errors.
1340	@param	erp		Error report, may be NULL.
1341
1342	Error codes:
1343	- DK4_E_INVALID_ARGUMENTS<br>
1344	  if gra is NULL or not in a state allowing this operation,
1345	- DK4_E_MATH_OVERFLOW<br>
1346	  on numeric overflow in memory size calculation,
1347	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1348	  if there is not enough memory available,
1349	- DK4_E_WRITE_FAILED<br>
1350	  if writing one ore multiple bytes to the stream failed,
1351	- DK4_E_FLUSH_FAILED<br>
1352	  if flushing data downwards failed.
1353*/
1354
1355void
1356dk4gra_fill_and_stroke(
1357	dk4_gra_t		*gra,
1358	int				*backptr,
1359	dk4_er_t		*erp
1360);
1361
1362
1363/**	Use current path for clipping.
1364	The value of the even-odd-rule flag is used to choose either
1365	even-odd-rule or nonzero-winding-rule, the dk4gra_set_eorule() function
1366	can be used to set the flag.
1367	@param	gra		Output structure.
1368	@param	backptr	Address of success variable to reset on errors.
1369	@param	erp		Error report, may be NULL.
1370
1371	Error codes:
1372	- DK4_E_INVALID_ARGUMENTS<br>
1373	  if gra is NULL or not in a state allowing this operation,
1374	- DK4_E_MATH_OVERFLOW<br>
1375	  on numeric overflow in memory size calculation,
1376	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1377	  if there is not enough memory available,
1378	- DK4_E_WRITE_FAILED<br>
1379	  if writing one ore multiple bytes to the stream failed,
1380	- DK4_E_FLUSH_FAILED<br>
1381	  if flushing data downwards failed.
1382*/
1383
1384void
1385dk4gra_clip(
1386	dk4_gra_t		*gra,
1387	int				*backptr,
1388	dk4_er_t		*erp
1389);
1390
1391/**	Set line width for pattern drawing.
1392	The pattern line width should be in range 0.0 to 2.0.
1393	@param	gra	Output structure.
1394	@param	plw	New pattern line width in bp.
1395*/
1396
1397void
1398dk4gra_set_pattern_line_width(
1399	dk4_gra_t	*gra,
1400	double		 plw
1401);
1402
1403/**	Pattern a region (clipping should be set to the path).
1404	@param	gra		Output structure.
1405	@param	xl		Left y coordinate.
1406	@param	xr		Right x coordinate.
1407	@param	yb		Bottom y coordinate.
1408	@param	yt		Top y coordinate.
1409	@param	pn		Pattern number.
1410	@param	backptr	Address of success variable to reset on errors.
1411	@param	erp		Error report, may be NULL.
1412
1413	Error codes:
1414	- DK4_E_INVALID_ARGUMENTS<br>
1415	  if gra is NULL or not in a state allowing this operation,
1416	- DK4_E_MATH_OVERFLOW<br>
1417	  on numeric overflow in memory size calculation,
1418	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1419	  if there is not enough memory available,
1420	- DK4_E_WRITE_FAILED<br>
1421	  if writing one ore multiple bytes to the stream failed,
1422	- DK4_E_FLUSH_FAILED<br>
1423	  if flushing data downwards failed.
1424*/
1425
1426void
1427dk4gra_pattern(
1428	dk4_gra_t			*gra,
1429	double				 xl,
1430	double				 xr,
1431	double				 yb,
1432	double				 yt,
1433	dk4_gra_pattern_t	 pn,
1434	int					*backptr,
1435	dk4_er_t			*erp
1436);
1437
1438/**	Set flag for even-odd-rule.
1439	If this flag is on, the even-odd-rule is used for filling and
1440	clipping. Otherwise the nonzero-winding rule is used.
1441	By default this flag is turned on when creating a dk4_gra_t structure.
1442	@param	gra		Output structure.
1443	@param	val		New flag value.
1444*/
1445void
1446dk4gra_set_eorule(
1447	dk4_gra_t	*gra,
1448	int			 val
1449);
1450
1451/**	Start a new path and move to first point.
1452	@param	gra		Output structure.
1453	@param	x		X coordinate of start point.
1454	@param	y		Y coordinate of start point.
1455	@param	bbptr	Bounding box, may be NULL.
1456	@param	backptr	Address of success variable to reset on errors.
1457	@param	erp		Error report, may be NULL.
1458
1459	Error codes:
1460	- DK4_E_INVALID_ARGUMENTS<br>
1461	  if gra is NULL or not in a state allowing this operation,
1462	- DK4_E_MATH_OVERFLOW<br>
1463	  on numeric overflow in memory size calculation,
1464	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1465	  if there is not enough memory available,
1466	- DK4_E_WRITE_FAILED<br>
1467	  if writing one ore multiple bytes to the stream failed,
1468	- DK4_E_FLUSH_FAILED<br>
1469	  if flushing data downwards failed.
1470*/
1471
1472void
1473dk4gra_newpath_moveto(
1474	dk4_gra_t		*gra,
1475	double			 x,
1476	double			 y,
1477	dk4_bb_t		*bbptr,
1478	int				*backptr,
1479	dk4_er_t		*erp
1480);
1481
1482
1483/**	Add line from current point to new point to path.
1484	@param	gra		Output structure.
1485	@param	x		X coordinate of new point.
1486	@param	y		Y coordinate of new point.
1487	@param	bbptr	Bounding box, may be NULL.
1488	@param	backptr	Address of success variable to reset on errors.
1489	@param	erp		Error report, may be NULL.
1490
1491	Error codes:
1492	- DK4_E_INVALID_ARGUMENTS<br>
1493	  if gra is NULL or not in a state allowing this operation,
1494	- DK4_E_MATH_OVERFLOW<br>
1495	  on numeric overflow in memory size calculation,
1496	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1497	  if there is not enough memory available,
1498	- DK4_E_WRITE_FAILED<br>
1499	  if writing one ore multiple bytes to the stream failed,
1500	- DK4_E_FLUSH_FAILED<br>
1501	  if flushing data downwards failed.
1502*/
1503
1504void
1505dk4gra_lineto(
1506	dk4_gra_t		*gra,
1507	double			 x,
1508	double			 y,
1509	dk4_bb_t		*bbptr,
1510	int				*backptr,
1511	dk4_er_t		*erp
1512);
1513
1514
1515/**	Add Bezier curve segment from current point to new point in path.
1516	@param	gra		Output structure.
1517	@param	xc1		X coordinate of first control point.
1518	@param	yc1		Y coordinate of first control point.
1519	@param	xc2		X coordinate of second control point.
1520	@param	yc2		Y coordinate of second control point.
1521	@param	x		X coordinate of new point.
1522	@param	y		Y coordinate of new point.
1523	@param	bbptr	Bounding box, may be NULL.
1524	@param	backptr	Address of success variable to reset on errors.
1525	@param	erp		Error report, may be NULL.
1526
1527	Error codes:
1528	- DK4_E_INVALID_ARGUMENTS<br>
1529	  if gra is NULL or not in a state allowing this operation,
1530	- DK4_E_MATH_OVERFLOW<br>
1531	  on numeric overflow in memory size calculation,
1532	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1533	  if there is not enough memory available,
1534	- DK4_E_WRITE_FAILED<br>
1535	  if writing one ore multiple bytes to the stream failed,
1536	- DK4_E_FLUSH_FAILED<br>
1537	  if flushing data downwards failed.
1538*/
1539
1540void
1541dk4gra_curveto(
1542	dk4_gra_t		*gra,
1543	double			 xc1,
1544	double			 yc1,
1545	double			 xc2,
1546	double			 yc2,
1547	double			 x,
1548	double			 y,
1549	dk4_bb_t		*bbptr,
1550	int				*backptr,
1551	dk4_er_t		*erp
1552);
1553
1554
1555/**	Close current path.
1556	@param	gra		Output structure.
1557	@param	backptr	Address of success variable to reset on errors.
1558	@param	erp		Error report, may be NULL.
1559
1560	Error codes:
1561	- DK4_E_INVALID_ARGUMENTS<br>
1562	  if gra is NULL or not in a state allowing this operation,
1563	- DK4_E_MATH_OVERFLOW<br>
1564	  on numeric overflow in memory size calculation,
1565	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1566	  if there is not enough memory available,
1567	- DK4_E_WRITE_FAILED<br>
1568	  if writing one ore multiple bytes to the stream failed,
1569	- DK4_E_FLUSH_FAILED<br>
1570	  if flushing data downwards failed.
1571*/
1572
1573void
1574dk4gra_closepath(
1575	dk4_gra_t		*gra,
1576	int				*backptr,
1577	dk4_er_t		*erp
1578);
1579
1580
1581/**	Create path for a circle.
1582	@param	gra		Output structure.
1583	@param	xc		Center point x coordinate.
1584	@param	yc		Center point y coordinate.
1585	@param	r		Radius.
1586	@param	bbptr	Bounding box, may be NULL.
1587	@param	backptr	Address of success variable to reset on errors.
1588	@param	erp		Error report, may be NULL.
1589
1590	Error codes:
1591	- DK4_E_INVALID_ARGUMENTS<br>
1592	  if gra is NULL or not in a state allowing this operation,
1593	- DK4_E_MATH_OVERFLOW<br>
1594	  on numeric overflow in memory size calculation,
1595	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1596	  if there is not enough memory available,
1597	- DK4_E_WRITE_FAILED<br>
1598	  if writing one ore multiple bytes to the stream failed,
1599	- DK4_E_FLUSH_FAILED<br>
1600	  if flushing data downwards failed.
1601*/
1602
1603void
1604dk4gra_circle(
1605	dk4_gra_t		*gra,
1606	double			 xc,
1607	double			 yc,
1608	double			 r,
1609	dk4_bb_t		*bbptr,
1610	int				*backptr,
1611	dk4_er_t		*erp
1612);
1613
1614
1615/**	Create path for rectangle parallel to axes, optionally with
1616	rounded corners.
1617	@param	gra		Output structure.
1618	@param	xl		Left x coordinate.
1619	@param	xr		Right x coordinate.
1620	@param	yb		Bottom y coordinate.
1621	@param	yt		Top y coordinate.
1622	@param	r		Corner radius, maximum is a half of the smaller side length.
1623					Use negative values to avoid rounded corners.
1624	@param	bbptr	Bounding box, may be NULL.
1625	@param	backptr	Address of success variable to reset on errors.
1626	@param	erp		Error report, may be NULL.
1627
1628	Error codes:
1629	- DK4_E_INVALID_ARGUMENTS<br>
1630	  if gra is NULL or not in a state allowing this operation,
1631	- DK4_E_MATH_OVERFLOW<br>
1632	  on numeric overflow in memory size calculation,
1633	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1634	  if there is not enough memory available,
1635	- DK4_E_WRITE_FAILED<br>
1636	  if writing one ore multiple bytes to the stream failed,
1637	- DK4_E_FLUSH_FAILED<br>
1638	  if flushing data downwards failed.
1639*/
1640
1641void
1642dk4gra_rectangle(
1643	dk4_gra_t		*gra,
1644	double			 xl,
1645	double			 xr,
1646	double			 yb,
1647	double			 yt,
1648	double			 r,
1649	dk4_bb_t		*bbptr,
1650	int				*backptr,
1651	dk4_er_t		*erp
1652);
1653
1654
1655/**	Add path for an arc.
1656	@param	gra		Output structure.
1657	@param	xc		Center point x coordinate.
1658	@param	yc		Center point y coordinate.
1659	@param	ra		Radius.
1660	@param	start	Start angle in degree.
1661	@param	end		End angle in degree.
1662	@param	cl		Flag: Draw closed arc (piece of cake) instead of simple arc.
1663	@param	bbptr	Bounding box, may be NULL.
1664	@param	backptr	Address of success variable to reset on errors.
1665	@param	erp		Error report, may be NULL.
1666
1667	Error codes:
1668	- DK4_E_INVALID_ARGUMENTS<br>
1669	  if gra is NULL or not in a state allowing this operation,
1670	- DK4_E_MATH_OVERFLOW<br>
1671	  on numeric overflow in memory size calculation,
1672	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1673	  if there is not enough memory available,
1674	- DK4_E_WRITE_FAILED<br>
1675	  if writing one ore multiple bytes to the stream failed,
1676	- DK4_E_FLUSH_FAILED<br>
1677	  if flushing data downwards failed.
1678*/
1679
1680void
1681dk4gra_arc(
1682	dk4_gra_t		*gra,
1683	double			 xc,
1684	double			 yc,
1685	double			 ra,
1686	double			 start,
1687	double			 end,
1688	int				 cl,
1689	dk4_bb_t		*bbptr,
1690	int				*backptr,
1691	dk4_er_t		*erp
1692);
1693
1694
1695/**	Create path for an ellipse.
1696	@param	gra		Output structure.
1697	@param	xc		Center point x coordinate.
1698	@param	yc		Center point y coordinate.
1699	@param	rx		Radius in x direction.
1700	@param	ry		Radius in y direction.
1701	@param	rot		Rotation counterclockwise in degree.
1702	@param	bbptr	Bounding box, may be NULL.
1703	@param	backptr	Address of success variable to reset on errors.
1704	@param	erp		Error report, may be NULL.
1705
1706	Error codes:
1707	- DK4_E_INVALID_ARGUMENTS<br>
1708	  if gra is NULL or not in a state allowing this operation,
1709	- DK4_E_MATH_OVERFLOW<br>
1710	  on numeric overflow in memory size calculation,
1711	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1712	  if there is not enough memory available,
1713	- DK4_E_WRITE_FAILED<br>
1714	  if writing one ore multiple bytes to the stream failed,
1715	- DK4_E_FLUSH_FAILED<br>
1716	  if flushing data downwards failed.
1717*/
1718
1719void
1720dk4gra_ellipse(
1721	dk4_gra_t		*gra,
1722	double			 xc,
1723	double			 yc,
1724	double			 rx,
1725	double			 ry,
1726	double			 rot,
1727	dk4_bb_t		*bbptr,
1728	int				*backptr,
1729	dk4_er_t		*erp
1730);
1731
1732
1733/**	Add simple (non-special) text to PGF graphics.
1734	The text is shown in the current fill color (non-stroking color)
1735	unless a color is specified in colspec.
1736	@param	gra		Output structure, must be initialized for PGF.
1737	@param	x		X coordinate.
1738	@param	y		Y coordinate.
1739	@param	rot		Rotation counterclockwise in degree.
1740	@param	txt		Text to show.
1741	@param	colspec	Color specification, may be NULL to use fill color.
1742	@param	ie		Text encoding, only used for char text.
1743	@param	ha		Horizontal alignment.
1744	@param	va		Vertical alignment.
1745	@param	fno		Font number.
1746	@param	fsz		Font size in pt.
1747	@param	fex		Flag: Use exact font (1) or similar font (0).
1748	@param	uc2l	UC to LaTeX conversion structure.
1749	@param	flags	Text flags DK4_GRA_TEXT_FLAG_xxx, can be or-combined.
1750	@param	backptr	Address of success variable to reset on errors.
1751	@param	erp		Error report, may be NULL.
1752
1753	Error codes:
1754	- DK4_E_INVALID_ARGUMENTS<br>
1755	  if gra is NULL or not in a state allowing this operation,
1756	- DK4_E_MATH_OVERFLOW<br>
1757	  on numeric overflow in memory size calculation,
1758	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1759	  if there is not enough memory available,
1760	- DK4_E_WRITE_FAILED<br>
1761	  if writing one ore multiple bytes to the stream failed,
1762	- DK4_E_FLUSH_FAILED<br>
1763	  if flushing data downwards failed.
1764*/
1765
1766void
1767dk4gra_pgf_simple_text(
1768	dk4_gra_t			*gra,
1769	double				 x,
1770	double				 y,
1771	double				 rot,
1772	const dkChar		*txt,
1773	const char			*colspec,
1774	int					 ie,
1775	dk4_text_align_h_t	 ha,
1776	dk4_text_align_v_t	 va,
1777	int					 fno,
1778	double				 fsz,
1779	dk4_gra_tf_t		 fex,
1780	dk4_uc2l_t			*uc2l,
1781	int					 flags,
1782	int					*backptr,
1783	dk4_er_t			*erp
1784);
1785
1786
1787/**	Add simple (non-special) text to PGF graphics.
1788	The text is shown in the current fill color (non-stroking color)
1789	unless a color is specified in colspec.
1790	@param	gra		Output structure, must be initialized for PGF.
1791	@param	x		X coordinate.
1792	@param	y		Y coordinate.
1793	@param	rot		Rotation counterclockwise in degree.
1794	@param	txt		Text to show.
1795	@param	colspec	Color specification, may be NULL to use fill color.
1796	@param	ha		Horizontal alignment.
1797	@param	va		Vertical alignment.
1798	@param	fno		Font number.
1799	@param	fsz		Font size in pt.
1800	@param	fex		Flag: Use exact font (1) or similar font (0).
1801	@param	uc2l	UC to LaTeX conversion structure.
1802	@param	flags	Text flags DK4_GRA_TEXT_FLAG_xxx, can be or-combined.
1803	@param	backptr	Address of success variable to reset on errors.
1804	@param	erp		Error report, may be NULL.
1805
1806	Error codes:
1807	- DK4_E_INVALID_ARGUMENTS<br>
1808	  if gra is NULL or not in a state allowing this operation,
1809	- DK4_E_MATH_OVERFLOW<br>
1810	  on numeric overflow in memory size calculation,
1811	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1812	  if there is not enough memory available,
1813	- DK4_E_WRITE_FAILED<br>
1814	  if writing one ore multiple bytes to the stream failed,
1815	- DK4_E_FLUSH_FAILED<br>
1816	  if flushing data downwards failed.
1817*/
1818
1819void
1820dk4gra_pgf_simple_utf8_text(
1821	dk4_gra_t			*gra,
1822	double				 x,
1823	double				 y,
1824	double				 rot,
1825	const char			*txt,
1826	const char			*colspec,
1827	dk4_text_align_h_t	 ha,
1828	dk4_text_align_v_t	 va,
1829	int					 fno,
1830	double				 fsz,
1831	dk4_gra_tf_t		 fex,
1832	dk4_uc2l_t			*uc2l,
1833	int					 flags,
1834	int					*backptr,
1835	dk4_er_t			*erp
1836);
1837
1838
1839/**	Add special text to PGF graphics.
1840	The text is shown in the current fill color (non-stroking color)
1841	unless a color is specified in colspec.
1842	@param	gra		Output structure, must be initialized for PGF.
1843	@param	x		X coordinate.
1844	@param	y		Y coordinate.
1845	@param	rot		Rotation counterclockwise in degree.
1846	@param	txt		Text to show.
1847	@param	colspec	Color specification, may be NULL to use fill color.
1848	@param	ha		Horizontal alignment.
1849	@param	va		Vertical alignment.
1850	@param	fno		Font number.
1851	@param	fsz		Font size.
1852	@param	fex		Flag: Use exact font.
1853	@param	flags	Text flags DK4_GRA_TEXT_FLAG_xxx, can be or-combined.
1854	@param	backptr	Address of success variable to reset on errors.
1855	@param	erp		Error report, may be NULL.
1856
1857	Error codes:
1858	- DK4_E_INVALID_ARGUMENTS<br>
1859	  if gra is NULL or not in a state allowing this operation,
1860	- DK4_E_MATH_OVERFLOW<br>
1861	  on numeric overflow in memory size calculation,
1862	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1863	  if there is not enough memory available,
1864	- DK4_E_WRITE_FAILED<br>
1865	  if writing one ore multiple bytes to the stream failed,
1866	- DK4_E_FLUSH_FAILED<br>
1867	  if flushing data downwards failed.
1868*/
1869
1870void
1871dk4gra_pgf_special_text(
1872	dk4_gra_t			*gra,
1873	double				 x,
1874	double				 y,
1875	double				 rot,
1876	const char			*txt,
1877	const char			*colspec,
1878	dk4_text_align_h_t	 ha,
1879	dk4_text_align_v_t	 va,
1880	int					 fno,
1881	double				 fsz,
1882	dk4_gra_tf_t		 fex,
1883	int					 flags,
1884	int					*backptr,
1885	dk4_er_t			*erp
1886);
1887
1888
1889/**	Set the font size for the documentclass line.
1890	@param	gra		Output structure, must be initialized for PGF.
1891	@param	fs		Font size in pt.
1892	@param	backptr	Address of success variable to reset on error.
1893	@param	erp		Error report, may be NULL.
1894*/
1895void
1896dk4gra_pgf_doc_font_size(
1897	dk4_gra_t			*gra,
1898	double				 fs,
1899	int					*backptr,
1900	dk4_er_t			*erp
1901);
1902
1903
1904/**	Add a preamble line.
1905	For font setup and package setup the lines added by this function
1906	replace the default contents.
1907	For other setup the lines added by this function are appended
1908	after the default contents.
1909	@param	gra		Output structure, must be initialized for PGF.
1910	@param	line	Line text without trailing newline.
1911	@param	tp		Line type: DK4_GRA_PREAMBLE_FONT, DK4_GRA_PREAMBLE_PACKAGE,
1912					or DK4_GRA_PREAMBLE_OTHER.
1913	@param	backptr	Address of success variable to reset on error.
1914	@param	erp		Error report, may be NULL.
1915*/
1916
1917void
1918dk4gra_pgf_doc_preamble_line(
1919	dk4_gra_t	*gra,
1920	const char	*line,
1921	int			 tp,
1922	int			*backptr,
1923	dk4_er_t	*erp
1924);
1925
1926
1927/**	Add bitmap image with coordinates transformations already calculated.
1928	@param	gra		Output structure.
1929	@param	cotra	Array containing 5 elements for coordinates transformations.
1930	@param	bif		Bitmap image file.
1931	@param	fn		Image file name.
1932	@param	fno		Frame number. The frame number given here is used
1933	by the PDF output driver only. You must call
1934	dk4bif_set_current_frame() on the bitmap image file before calling
1935	this function.
1936	@param	ifl		Image flags.
1937	@param	backptr	Address of success variable to reset on errors.
1938	@param	erp		Error report, may be NULL.
1939
1940	Error codes:
1941	- DK4_E_INVALID_ARGUMENTS<br>
1942	  if gra is NULL or bif is NULL or a frame number other than 0
1943	  was specified for PGF output or gra is
1944	  not in a state allowing this operation,
1945	- DK4_E_MATH_OVERFLOW<br>
1946	  on numeric overflow in memory size calculation,
1947	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1948	  if there is not enough memory available,
1949	- DK4_E_WRITE_FAILED<br>
1950	  if writing one ore multiple bytes to the stream failed,
1951	- DK4_E_FLUSH_FAILED<br>
1952	  if flushing data downwards failed.
1953*/
1954void
1955dk4gra_bif_cotra_image(
1956	dk4_gra_t			*gra,
1957	double				*cotra,
1958	dk4_bif_t			*bif,
1959	const dkChar		*fn,
1960	size_t				 fno,
1961	int					 ifl,
1962	int					*backptr,
1963	dk4_er_t			*erp
1964);
1965
1966
1967/**	Add bitmap image XFig style from opened bitmap image file.
1968	@param	gra		Output structure.
1969	@param	xl		Left x coordinate.
1970	@param	xr		Right x coordinate.
1971	@param	yb		Bottom y coordinate.
1972	@param	yt		Top y coordinate.
1973	@param	bif		Bitmap image file.
1974	@param	fn		Image file name.
1975	@param	fno		Frame number (0 for first frame).
1976	@param	pos		Image positioning:
1977	- 0 not rotated, not flipped,
1978	- 1 rotated 90 degree counterclockwise, not flipped,
1979	- 2 rotated 180 degree counterclockwise, not flipped,
1980	- 3 rotated 270 degree counterclockwise, not flipped,
1981	- 4 not rotated, flipped,
1982	- 5 rotated 90 degree counterclockwise, flipped,
1983	- 6 rotated 180 degree counterclockwise, flipped,
1984	- 7 rotated 270 degree counterclockwise, flipped.
1985	@param	ifl		Image flags.
1986	@param	bbptr	Bounding box, may be NULL.
1987	@param	backptr	Address of success variable to reset on errors.
1988	@param	erp		Error report, may be NULL.
1989
1990	Error codes:
1991	- DK4_E_INVALID_ARGUMENTS<br>
1992	  if gra is NULL or bif is NULL or a frame number other than 0
1993	  was specified for PGF output or gra is
1994	  not in a state allowing this operation,
1995	- DK4_E_MATH_OVERFLOW<br>
1996	  on numeric overflow in memory size calculation,
1997	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
1998	  if there is not enough memory available,
1999	- DK4_E_WRITE_FAILED<br>
2000	  if writing one ore multiple bytes to the stream failed,
2001	- DK4_E_FLUSH_FAILED<br>
2002	  if flushing data downwards failed.
2003*/
2004
2005void
2006dk4gra_bif_fig_image(
2007	dk4_gra_t			*gra,
2008	double				 xl,
2009	double				 xr,
2010	double				 yb,
2011	double				 yt,
2012	dk4_bif_t			*bif,
2013	const dkChar		*fn,
2014	size_t				 fno,
2015	int					 pos,
2016	int					 ifl,
2017	dk4_bb_t			*bbptr,
2018	int					*backptr,
2019	dk4_er_t			*erp
2020);
2021
2022
2023/**	Add bitmap image from opened bitmap image file.
2024	@param	gra		Output structure.
2025	@param	xl		Left x coordinate.
2026	@param	xr		Right x coordinate.
2027	@param	yb		Bottom y coordinate.
2028	@param	yt		Top y coordinate.
2029	@param	bif		Bitmap image file data.
2030	@param	fn		Image file name.
2031	@param	fno		Frame number (0 for first frame).
2032	@param	ifl		Image flags.
2033	@param	bbptr	Bounding box, may be NULL.
2034	@param	backptr	Address of success variable to reset on errors.
2035	@param	erp		Error report, may be NULL.
2036
2037	Error codes:
2038	- DK4_E_INVALID_ARGUMENTS<br>
2039	  if gra is NULL or bif is NULL or gra is
2040	  not in a state allowing this operation,
2041	- DK4_E_MATH_OVERFLOW<br>
2042	  on numeric overflow in memory size calculation,
2043	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
2044	  if there is not enough memory available,
2045	- DK4_E_WRITE_FAILED<br>
2046	  if writing one ore multiple bytes to the stream failed,
2047	- DK4_E_FLUSH_FAILED<br>
2048	  if flushing data downwards failed.
2049*/
2050
2051void
2052dk4gra_bif_image(
2053	dk4_gra_t			*gra,
2054	double				 xl,
2055	double				 xr,
2056	double				 yb,
2057	double				 yt,
2058	dk4_bif_t			*bif,
2059	const dkChar		*fn,
2060	size_t				 fno,
2061	int					 ifl,
2062	dk4_bb_t			*bbptr,
2063	int					*backptr,
2064	dk4_er_t			*erp
2065);
2066
2067
2068/**	Add bitmap image specified by file name.
2069	@param	gra		Output structure.
2070	@param	xl		Left x coordinate.
2071	@param	xr		Right x coordinate.
2072	@param	yb		Bottom y coordinate.
2073	@param	yt		Top y coordinate.
2074	@param	fn		Image file name.
2075	@param	fno		Frame number (0 for first frame).
2076	@param	ctx		Bitmap image conversion context, may be NULL.
2077	@param	ifl		Image flags.
2078	@param	bbptr	Bounding box, may be NULL.
2079	@param	backptr	Address of success variable to reset on errors.
2080	@param	erp		Error report, may be NULL.
2081
2082	Error codes:
2083	- DK4_E_INVALID_ARGUMENTS<br>
2084	  if gra is NULL or bif is NULL or gra is
2085	  not in a state allowing this operation,
2086	- DK4_E_MATH_OVERFLOW<br>
2087	  on numeric overflow in memory size calculation,
2088	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
2089	  if there is not enough memory available,
2090	- DK4_E_WRITE_FAILED<br>
2091	  if writing one ore multiple bytes to the stream failed,
2092	- DK4_E_FLUSH_FAILED<br>
2093	  if flushing data downwards failed.
2094*/
2095
2096void
2097dk4gra_image(
2098	dk4_gra_t			*gra,
2099	double				 xl,
2100	double				 xr,
2101	double				 yb,
2102	double				 yt,
2103	const dkChar		*fn,
2104	size_t				 fno,
2105	dk4_cs_conv_ctx_t	*ctx,
2106	int					 ifl,
2107	dk4_bb_t			*bbptr,
2108	int					*backptr,
2109	dk4_er_t			*erp
2110);
2111
2112
2113/**	Add bitmap image XFig style specified by file name.
2114	@param	gra		Output structure.
2115	@param	xl		Left x coordinate.
2116	@param	xr		Right x coordinate.
2117	@param	yb		Bottom y coordinate.
2118	@param	yt		Top y coordinate.
2119	@param	fn		Image file name.
2120	@param	fno		Frame number (0 for first frame).
2121	@param	ctx		Bitmap image conversion context, may be NULL.
2122	@param	pos		Image positioning:
2123	- 0 not rotated, not flipped,
2124	- 1 rotated 90 degree counterclockwise, not flipped,
2125	- 2 rotated 180 degree counterclockwise, not flipped,
2126	- 3 rotated 270 degree counterclockwise, not flipped,
2127	- 4 not rotated, flipped,
2128	- 5 rotated 90 degree counterclockwise, flipped,
2129	- 6 rotated 180 degree counterclockwise, flipped,
2130	- 7 rotated 270 degree counterclockwise, flipped.
2131	@param	ifl		Image flags.
2132	@param	bbptr	Bounding box, may be NULL.
2133	@param	backptr	Address of success variable to reset on errors.
2134	@param	erp		Error report, may be NULL.
2135
2136	Error codes:
2137	- DK4_E_INVALID_ARGUMENTS<br>
2138	  if gra is NULL or bif is NULL or gra is
2139	  not in a state allowing this operation,
2140	- DK4_E_MATH_OVERFLOW<br>
2141	  on numeric overflow in memory size calculation,
2142	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
2143	  if there is not enough memory available,
2144	- DK4_E_WRITE_FAILED<br>
2145	  if writing one ore multiple bytes to the stream failed,
2146	- DK4_E_FLUSH_FAILED<br>
2147	  if flushing data downwards failed.
2148*/
2149
2150void
2151dk4gra_fig_image(
2152	dk4_gra_t			*gra,
2153	double				 xl,
2154	double				 xr,
2155	double				 yb,
2156	double				 yt,
2157	const dkChar		*fn,
2158	size_t				 fno,
2159	dk4_cs_conv_ctx_t	*ctx,
2160	int					 pos,
2161	int					 ifl,
2162	dk4_bb_t			*bbptr,
2163	int					*backptr,
2164	dk4_er_t			*erp
2165);
2166
2167
2168#ifdef	__cplusplus
2169}
2170#endif
2171
2172
2173/**	Number of points to calculate for a circle or ellipse.
2174*/
2175enum {
2176							/**	Number of points to calculate for a circle
2177								or ellipse.
2178							*/
2179	DK4_GRA_CIRCLE_POINTS	= 24
2180};
2181
2182
2183/* vim: set ai sw=4 ts=4 : */
2184
2185%%	module
2186
2187
2188#include "dk4conf.h"
2189
2190#if	DK4_HAVE_FCNTL_H
2191#ifndef	FCNTL_H_INCLUDED
2192#include <fcntl.h>
2193#define	FCNTL_H_INCLUDED 1
2194#endif
2195#endif
2196
2197#if	DK4_HAVE_IO_H
2198#ifndef	IO_H_INCLUDED
2199#include <io.h>
2200#define	IO_H_INCLUDED 1
2201#endif
2202#endif
2203
2204#if	DK4_HAVE_MATH_H
2205#ifndef	MATH_H_INCLUDED
2206#if	DK4_ON_WINDOWS
2207#ifndef	_USE_MATH_DEFINES
2208#define	_USE_MATH_DEFINES 1
2209#endif
2210#endif
2211#include <math.h>
2212#define	MATH_H_INCLUDED 1
2213#endif
2214#endif
2215
2216#if	DK4_HAVE_FLOAT_H
2217#ifndef	FLOAT_H_INCLUDED
2218#include <float.h>
2219#define	FLOAT_H_INCLUDED 1
2220#endif
2221#endif
2222
2223#if	DK4_HAVE_ERRNO_H
2224#ifndef	ERRNO_H_INCLUDED
2225#include <errno.h>
2226#define	ERRNO_H_INCLUDED 1
2227#endif
2228#endif
2229
2230#ifndef	DK4MATH_H_INCLUDED
2231#include <libdk4c/dk4math.h>
2232#endif
2233
2234#ifndef	DK4UC2L_H_INCLUDED
2235#include <libdk4lat/dk4uc2l.h>
2236#endif
2237
2238#ifndef	DK4GRA_H_INCLUDED
2239#include <libdk4gra/dk4gra.h>
2240#endif
2241
2242#ifndef	DK4GRAT_H_INCLUDED
2243#include <libdk4gra/dk4grat.h>
2244#endif
2245
2246#ifndef	GRA_H_INCLUDED
2247#include <libdk4gra/gra.h>
2248#endif
2249
2250#ifndef	DK4BIF_H_INCLUDED
2251#include <libdk4bif/dk4bif.h>
2252#endif
2253
2254#ifndef	DK4FOPD_H_INCLUDED
2255#include <libdk4c/dk4fopd.h>
2256#endif
2257
2258#ifndef	DK4FOPT_H_INCLUDED
2259#include <libdk4c/dk4fopt.h>
2260#endif
2261
2262#ifndef	DK4ISADM_H_INCLUDED
2263#include <libdk4c/dk4isadm.h>
2264#endif
2265
2266#if DK4_HAVE_ASSERT_H
2267#ifndef	ASSERT_H_INCLUDED
2268#include <assert.h>
2269#define	ASSERT_H_INCLUDED 1
2270#endif
2271#endif
2272
2273
2274$!trace-include
2275
2276
2277
2278static
2279void
2280dk4gra_i_save_attributes(
2281	dk4_gra_t	*gra
2282)
2283{
2284#if	DK4_USE_ASSERT
2285	assert(NULL != gra);
2286#endif
2287	switch (gra->dr) {
2288		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2289			dk4gra_eps_save_attributes(gra);
2290		} break;
2291		case DK4_GRA_DRIVER_PGF : {
2292			dk4gra_pgf_save_attributes(gra);
2293		} break;
2294		default : {
2295			dk4gra_pdf_save_attributes(gra);
2296		} break;
2297	}
2298}
2299
2300
2301
2302static
2303void
2304dk4gra_i_restore_attributes(
2305	dk4_gra_t	*gra
2306)
2307{
2308#if	DK4_USE_ASSERT
2309	assert(NULL != gra);
2310#endif
2311	switch (gra->dr) {
2312		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2313			dk4gra_eps_restore_attributes(gra);
2314		} break;
2315		case DK4_GRA_DRIVER_PGF : {
2316			dk4gra_pgf_restore_attributes(gra);
2317		} break;
2318		default : {
2319			dk4gra_pdf_restore_attributes(gra);
2320		} break;
2321	}
2322}
2323
2324
2325
2326static
2327void
2328dk4gra_i_reset_attributes(
2329	dk4_gra_t	*gra
2330)
2331{
2332#if	DK4_USE_ASSERT
2333	assert(NULL != gra);
2334#endif
2335	switch (gra->dr) {
2336		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2337			dk4gra_eps_reset_attributes(gra);
2338		} break;
2339		case DK4_GRA_DRIVER_PGF : {
2340			dk4gra_pgf_reset_attributes(gra);
2341		} break;
2342		default : {
2343			dk4gra_pdf_reset_attributes(gra);
2344		} break;
2345	}
2346}
2347
2348
2349
2350static
2351double
2352dk4gra_i_to_range(double x, double min, double max)
2353{
2354	if (min > x) { x = min; }
2355	if (max < x) { x = max; }
2356	return x;
2357}
2358
2359
2360
2361void
2362dk4gra_close(
2363	dk4_gra_t		*gra
2364)
2365{
2366	$? "+ dk4gra_close"
2367#if	DK4_USE_ASSERT
2368	assert(NULL != gra);
2369#endif
2370	if (NULL == gra) {
2371		goto finished;
2372	}
2373	switch (gra->dr) {
2374		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2375			dk4gra_eps_close(gra);
2376		} break;
2377		case DK4_GRA_DRIVER_PGF : {
2378			dk4gra_pgf_close(gra);
2379		} break;
2380		default : {
2381			dk4gra_pdf_close(gra);
2382		} break;
2383	}
2384	finished:
2385	$? "- dk4gra_close"
2386	return;
2387}
2388
2389
2390
2391dk4_gra_t *
2392dk4gra_open_pdf(
2393	const dkChar	*fn,
2394	size_t			 w,
2395	size_t			 h,
2396	int				 docfl,
2397	dk4_er_t		*erp
2398)
2399{
2400	dk4_gra_t	*back = NULL;
2401	$? "+ dk4gra_open_pdf \"%!ds\"", TR_STR(fn)
2402#if	DK4_USE_ASSERT
2403	assert(NULL != fn);
2404#endif
2405	if ((0 == w) || (0 == h)) {
2406		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2407		goto finished;
2408	}
2409	back = dk4gra_pdf_open(fn, w, h, docfl, erp);
2410	finished:
2411	$? "- dk4gra_open_pdf %d", TR_IPTR(back)
2412	return back;
2413}
2414
2415
2416
2417dk4_gra_t *
2418dk4gra_open_ps(
2419	const dkChar	*fn,
2420	size_t			 w,
2421	size_t			 h,
2422	int				 docfl,
2423	dk4_er_t		*erp
2424)
2425{
2426	dk4_gra_t	*back	= NULL;
2427	$? "+ dk4gra_open_ps"
2428#if	DK4_USE_ASSERT
2429	assert(NULL != fn);
2430#endif
2431	if ((0 == w) || (0 == h)) {
2432		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2433		goto finished;
2434	}
2435	back = dk4gra_eps_open(fn, w, h, docfl, erp);
2436	finished:
2437	$? "- dk4gra_open_ps %d", TR_IPTR(back)
2438	return back;
2439}
2440
2441
2442
2443
2444dk4_gra_t *
2445dk4gra_open_pgf(
2446	const dkChar	*fn,
2447	size_t			 w,
2448	size_t			 h,
2449	int				 docfl,
2450	int				 sa,
2451	dk4_er_t		*erp
2452)
2453{
2454	dk4_gra_t	*back = NULL;
2455	$? "+ dk4gra_open_pgf"
2456#if	DK4_USE_ASSERT
2457	assert(NULL != fn);
2458#endif
2459	if ((0 == w) || (0 == h)) {
2460		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2461		goto finished;
2462	}
2463	back = dk4gra_pgf_open(fn, w, h, docfl, sa, erp);
2464	finished:
2465	$? "- dk4gra_open_pgf %d", TR_IPTR(back)
2466	return back;
2467}
2468
2469
2470
2471void
2472dk4gra_set_color_conversion(
2473	dk4_gra_t				*gra,
2474	dk4_cs_conv_ctx_t const	*ctx,
2475	int						*backptr,
2476	dk4_er_t				*erp
2477)
2478{
2479	int		 back = 0;
2480#if	DK4_USE_ASSERT
2481	assert(NULL != gra);
2482#endif
2483	if ((NULL != gra) && (NULL != ctx)) {
2484		DK4_MEMCPY(&(gra->cscctx),ctx,sizeof(dk4_cs_conv_ctx_t));
2485		back = 1;
2486	}
2487	else {
2488		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2489	}
2490	if ((0 == back) && (NULL != backptr)) { *backptr = 0; }
2491}
2492
2493
2494
2495void
2496dk4gra_write_file_and_close(
2497	FILE			*fout,
2498	dk4_gra_t		*gra,
2499	int				*backptr,
2500	dk4_er_t		*erp
2501)
2502{
2503	int		 back	= 0;
2504	$? "+ dk4gra_write_file_and_close"
2505#if	DK4_USE_ASSERT
2506	assert(NULL != gra);
2507	assert(NULL != fout);
2508#endif
2509	if (NULL == gra) {
2510		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2511		goto finished;
2512	}
2513	if ((NULL == gra->s_pages) || (NULL == gra->i_pages)) {
2514		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2515		dk4gra_close(gra);
2516		goto finished;
2517	}
2518	if ((0 == gra->pages) || (NULL == gra->curpg)) {
2519		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2520		dk4gra_close(gra);
2521		goto finished;
2522	}
2523
2524	switch (gra->dr) {
2525		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2526			back = dk4gra_eps_write_file_and_close(fout, gra, erp);
2527		} break;
2528		case DK4_GRA_DRIVER_PGF : {
2529			back = dk4gra_pgf_write_file_and_close(fout, gra, erp);
2530		} break;
2531		default : {
2532			back = dk4gra_pdf_write_file_and_close(fout, gra, erp);
2533		} break;
2534	}
2535
2536	finished:
2537	$? "- dk4gra_write_file_and_close %d", back
2538	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
2539}
2540
2541
2542
2543void
2544dk4gra_write_and_close(
2545	dk4_gra_t		*gra,
2546	int				*backptr,
2547	dk4_er_t		*erp
2548)
2549{
2550	FILE	*fout	=	NULL;				/* Output file to write */
2551	int		 tests	=	DK4_FOPEN_SC_USER;	/* Tests for opening file */
2552	int		 back	=	0;
2553#if	DK4_ON_WINDOWS
2554	int		 oldm	=	_O_TEXT;			/* Previous DOS stdout mode */
2555#endif
2556	$? "+ dk4gra_write_and_close"
2557#if	DK4_USE_ASSERT
2558	assert(NULL != gra);
2559#endif
2560	if (NULL == gra) {
2561		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2562		goto finished;
2563	}
2564	if ((NULL == gra->s_pages) || (NULL == gra->i_pages)) {
2565		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2566		dk4gra_close(gra);
2567		goto finished;
2568	}
2569	if ((0 == gra->pages) || (NULL == gra->curpg)) {
2570		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2571		dk4gra_close(gra);
2572		goto finished;
2573	}
2574
2575	/*	Open and write output file if name specified, otherwise
2576		write to standard output.
2577	*/
2578	if (NULL != gra->fn) {
2579		if (0 != dk4isadmin()) { tests = DK4_FOPEN_SC_PRIVILEGED; }
2580		fout = dk4fopen(gra->fn, dkT("wb"), tests, erp);
2581		if (NULL != fout) {
2582			back = 1;
2583			dk4gra_write_file_and_close(fout, gra, &back, erp);
2584			if (0 != fclose(fout)) {
2585				dk4error_set_simple_error_code(erp, DK4_E_CLOSE_FAILED);
2586				back = 0;
2587			}
2588		}
2589		else {
2590			dk4gra_close(gra);
2591		}
2592	}
2593	else {
2594		back = 1;
2595#if	DK4_ON_WINDOWS
2596		oldm = _setmode(_fileno(stdout), _O_BINARY);
2597#endif
2598		dk4gra_write_file_and_close(stdout, gra, &back, erp);
2599#if	DK4_ON_WINDOWS
2600		_setmode(_fileno(stdout), oldm);
2601#endif
2602	}
2603
2604	finished:
2605	$? "- dk4gra_write_and_close %d", back
2606	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
2607}
2608
2609
2610
2611void
2612dk4gra_page_with_flags(
2613	dk4_gra_t		*gra,
2614	int				 flags,
2615	int				*backptr,
2616	dk4_er_t		*erp
2617)
2618{
2619	int		 back = 0;
2620	$? "+ dk4gra_page"
2621#if	DK4_USE_ASSERT
2622	assert(NULL != gra);
2623#endif
2624	if (NULL == gra) {
2625		$? "! gra"
2626		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2627		goto finished;
2628	}
2629	gra->cur_x = 0.0;
2630	gra->cur_y = 0.0;
2631	if ((NULL == gra->s_pages) || (NULL == gra->i_pages)) {
2632		$? "! s_pages, i_pages"
2633		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2634		goto finished;
2635	}
2636	switch (gra->dr) {
2637		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2638			$? ". eps driver"
2639			back = dk4gra_eps_page(gra, flags, erp);
2640		} break;
2641		case DK4_GRA_DRIVER_PGF : {
2642			$? ". pgf driver"
2643			back = dk4gra_pgf_page(gra, flags, erp);
2644		} break;
2645		default : {
2646			$? ". pdf driver"
2647			back = dk4gra_pdf_page(gra, flags, erp);
2648		} break;
2649	}
2650	finished:
2651	$? "- dk4gra_page %d", back
2652	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
2653}
2654
2655
2656
2657void
2658dk4gra_page(
2659	dk4_gra_t		*gra,
2660	int				*backptr,
2661	dk4_er_t		*erp
2662)
2663{
2664#if	DK4_USE_ASSERT
2665	assert(NULL != gra);
2666#endif
2667	dk4gra_page_with_flags(gra, gra->docfl, backptr, erp);
2668}
2669
2670
2671
2672void
2673dk4gra_i_gsave(
2674	dk4_gra_t		*gra,
2675	int				*backptr,
2676	dk4_er_t		*erp
2677)
2678{
2679#if	DK4_USE_ASSERT
2680	assert(NULL != gra);
2681#endif
2682	switch (gra->dr) {
2683		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2684			if (0 == dk4gra_eps_gsave(gra, erp)) {
2685				if (NULL != backptr) { *backptr = 0; }
2686			}
2687		} break;
2688		case DK4_GRA_DRIVER_PGF : {
2689			if (0 == dk4gra_pgf_gsave(gra, erp)) {
2690				if (NULL != backptr) { *backptr = 0; }
2691			}
2692		} break;
2693		default : {
2694			if (0 == dk4gra_pdf_gsave(gra, erp)) {
2695				if (NULL != backptr) { *backptr = 0; }
2696			}
2697		} break;
2698	}
2699}
2700
2701
2702
2703void
2704dk4gra_i_grestore(
2705	dk4_gra_t		*gra,
2706	int				 res,
2707	int				*backptr,
2708	dk4_er_t		*erp
2709)
2710{
2711#if	DK4_USE_ASSERT
2712	assert(NULL != gra);
2713#endif
2714	switch (gra->dr) {
2715		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2716			if (0 == dk4gra_eps_grestore(gra, erp)) {
2717				if (NULL != backptr) { *backptr = 0; }
2718			}
2719		} break;
2720		case DK4_GRA_DRIVER_PGF : {
2721			if (0 == dk4gra_pgf_grestore(gra, erp)) {
2722				if (NULL != backptr) { *backptr = 0; }
2723			}
2724		} break;
2725		default : {
2726			if (0 == dk4gra_pdf_grestore(gra, erp)) {
2727				if (NULL != backptr) { * backptr = 0; }
2728			}
2729		} break;
2730	}
2731	if ((0 != gra->gscp) && (0 != res)) {
2732		dk4gra_i_reset_attributes(gra);
2733	}
2734}
2735
2736
2737
2738void
2739dk4gra_i_prepare_fill(
2740	dk4_gra_t	*gra,
2741	int			*backptr,
2742	dk4_er_t	*erp
2743)
2744{
2745#if	DK4_USE_ASSERT
2746	assert(NULL != gra);
2747#endif
2748	switch (gra->dr) {
2749		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2750			if (0 == dk4gra_eps_prepare_fill(gra, erp)) {
2751				if (NULL != backptr) { *backptr = 0; }
2752			}
2753		} break;
2754		case DK4_GRA_DRIVER_PGF : {
2755			if (0 == dk4gra_pgf_prepare_fill(gra, erp)) {
2756				if (NULL != backptr) { *backptr = 0; }
2757			}
2758		} break;
2759		default : {
2760			if (0 == dk4gra_pdf_prepare_fill(gra, erp)) {
2761				if (NULL != backptr) { *backptr = 0; }
2762			}
2763		} break;
2764	}
2765}
2766
2767
2768void
2769dk4gra_i_prepare_stroke(
2770	dk4_gra_t	*gra,
2771	int			*backptr,
2772	dk4_er_t	*erp
2773)
2774{
2775#if	DK4_USE_ASSERT
2776	assert(NULL != gra);
2777#endif
2778	switch (gra->dr) {
2779		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2780			if (0 == dk4gra_eps_prepare_stroke(gra, erp)) {
2781				if (NULL != backptr) { *backptr = 0; }
2782			}
2783		} break;
2784		case DK4_GRA_DRIVER_PGF : {
2785			if (0 == dk4gra_pgf_prepare_stroke(gra, erp)) {
2786				if (NULL != backptr) { *backptr = 0; }
2787			}
2788		} break;
2789		default : {
2790			if (0 == dk4gra_pdf_prepare_stroke(gra, erp)) {
2791				if (NULL != backptr) { *backptr = 0; }
2792			}
2793		} break;
2794	}
2795}
2796
2797
2798void
2799dk4gra_i_prepare_fill_and_stroke(
2800	dk4_gra_t	*gra,
2801	int			*backptr,
2802	dk4_er_t	*erp
2803)
2804{
2805#if	DK4_USE_ASSERT
2806	assert(NULL != gra);
2807#endif
2808	switch (gra->dr) {
2809		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2810			dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2811			if (NULL != backptr) { *backptr = 0; }
2812		} break;
2813		case DK4_GRA_DRIVER_PGF : {
2814			if (0 == dk4gra_pgf_prepare_fill_and_stroke(gra, erp)) {
2815				if (NULL != backptr) { *backptr = 0; }
2816			}
2817		} break;
2818		default : {
2819			if (0 == dk4gra_pdf_prepare_fill_and_stroke(gra, erp)) {
2820				if (NULL != backptr) { *backptr = 0; }
2821			}
2822		} break;
2823	}
2824}
2825
2826
2827
2828void
2829dk4gra_i_fill(
2830	dk4_gra_t		*gra,
2831	int				*backptr,
2832	dk4_er_t		*erp
2833)
2834{
2835#if	DK4_USE_ASSERT
2836	assert(NULL != gra);
2837#endif
2838	switch (gra->dr) {
2839		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2840			if (0 == dk4gra_eps_fill(gra, erp)) {
2841				if (NULL != backptr) { *backptr = 0; }
2842			}
2843		} break;
2844		case DK4_GRA_DRIVER_PGF : {
2845			if (0 == dk4gra_pgf_fill(gra, erp)) {
2846				if (NULL != backptr) { *backptr = 0; }
2847			}
2848		} break;
2849		default : {
2850			if (0 == dk4gra_pdf_fill(gra, erp)) {
2851				if (NULL != backptr) { *backptr = 0; }
2852			}
2853		} break;
2854	}
2855}
2856
2857
2858
2859void
2860dk4gra_i_stroke(
2861	dk4_gra_t		*gra,
2862	int				*backptr,
2863	dk4_er_t		*erp
2864)
2865{
2866#if	DK4_USE_ASSERT
2867	assert(NULL != gra);
2868#endif
2869	switch (gra->dr) {
2870		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2871			if (0 == dk4gra_eps_stroke(gra, erp)) {
2872				if (NULL != backptr) { *backptr = 0; }
2873			}
2874		} break;
2875		case DK4_GRA_DRIVER_PGF : {
2876			if (0 == dk4gra_pgf_stroke(gra, erp)) {
2877				if (NULL != backptr) { *backptr = 0; }
2878			}
2879		} break;
2880		default : {
2881			if (0 == dk4gra_pdf_stroke(gra, erp)) {
2882				if (NULL != backptr) { *backptr = 0; }
2883			}
2884		} break;
2885	}
2886}
2887
2888
2889
2890void
2891dk4gra_i_fill_and_stroke(
2892	dk4_gra_t		*gra,
2893	int				*backptr,
2894	dk4_er_t		*erp
2895)
2896{
2897#if	DK4_USE_ASSERT
2898	assert(NULL != gra);
2899#endif
2900	switch (gra->dr) {
2901		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2902			dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2903			if (NULL != backptr) {*backptr = 0; }
2904		} break;
2905		case DK4_GRA_DRIVER_PGF : {
2906			if (0 == dk4gra_pgf_fill_and_stroke(gra, erp)) {
2907				if (NULL != backptr) { *backptr = 0; }
2908			}
2909		} break;
2910		default : {
2911			if (0 == dk4gra_pdf_fill_and_stroke(gra, erp)) {
2912				if (NULL != backptr) {*backptr = 0; }
2913			}
2914		} break;
2915	}
2916}
2917
2918
2919
2920void
2921dk4gra_i_clip(
2922	dk4_gra_t		*gra,
2923	int				*backptr,
2924	dk4_er_t		*erp
2925)
2926{
2927#if	DK4_USE_ASSERT
2928	assert(NULL != gra);
2929#endif
2930	switch (gra->dr) {
2931		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2932			if (0 == dk4gra_eps_clip(gra, erp)) {
2933				if (NULL != backptr) { *backptr = 0; }
2934			}
2935		} break;
2936		case DK4_GRA_DRIVER_PGF : {
2937			if (0 == dk4gra_pgf_clip(gra, erp)) {
2938				if (NULL != backptr) { *backptr = 0; }
2939			}
2940		} break;
2941		default : {
2942			if (0 == dk4gra_pdf_clip(gra, erp)) {
2943				if (NULL != backptr) { *backptr = 0; }
2944			}
2945		} break;
2946	}
2947}
2948
2949
2950
2951void
2952dk4gra_set_eorule(
2953	dk4_gra_t	*gra,
2954	int			 val
2955)
2956{
2957#if	DK4_USE_ASSERT
2958	assert(NULL != gra);
2959#endif
2960	if (NULL != gra) {
2961		gra->eor = val;
2962	}
2963}
2964
2965
2966
2967void
2968dk4gra_i_newpath_moveto(
2969	dk4_gra_t		*gra,
2970	double			 x,
2971	double			 y,
2972	int				*backptr,
2973	dk4_er_t		*erp
2974)
2975{
2976	$? "+ dk4gra_i_newpath_moveto"
2977#if	DK4_USE_ASSERT
2978	assert(NULL != gra);
2979#endif
2980	switch (gra->dr) {
2981		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
2982			$? ". PS/EPS"
2983			if (0 == dk4gra_eps_newpath_moveto(gra, x, y, erp)) {
2984				if (NULL != backptr) { *backptr = 0; }
2985			}
2986		} break;
2987		case DK4_GRA_DRIVER_PGF : {
2988			$? ". PGF"
2989			if (0 == dk4gra_pgf_newpath_moveto(gra, x, y, erp)) {
2990				if (NULL != backptr) { *backptr = 0; }
2991			}
2992		} break;
2993		default : {
2994			$? ". PDF"
2995			if (0 == dk4gra_pdf_newpath_moveto(gra, x, y, erp)) {
2996				if (NULL != backptr) { *backptr = 0; }
2997			}
2998		} break;
2999	}
3000	$? "- dk4gra_i_newpath_moveto"
3001}
3002
3003
3004
3005void
3006dk4gra_i_lineto(
3007	dk4_gra_t		*gra,
3008	double			 x,
3009	double			 y,
3010	int				*backptr,
3011	dk4_er_t		*erp
3012)
3013{
3014	$? "+ dk4gra_i_lineto"
3015#if	DK4_USE_ASSERT
3016	assert(NULL != gra);
3017#endif
3018	switch (gra->dr) {
3019		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3020			if (0 == dk4gra_eps_lineto(gra, x, y, erp)) {
3021				if (NULL != backptr) { *backptr = 0; }
3022			}
3023		} break;
3024		case DK4_GRA_DRIVER_PGF : {
3025			if (0 == dk4gra_pgf_lineto(gra, x, y, erp)) {
3026				if (NULL != backptr) { *backptr = 0; }
3027			}
3028		} break;
3029		default : {
3030			if (0 == dk4gra_pdf_lineto(gra, x, y, erp)) {
3031				if (NULL != backptr) { *backptr = 0; }
3032			}
3033		} break;
3034	}
3035	$? "- dk4gra_i_lineto"
3036}
3037
3038
3039
3040void
3041dk4gra_i_curveto(
3042	dk4_gra_t		*gra,
3043	double			 xc1,
3044	double			 yc1,
3045	double			 xc2,
3046	double			 yc2,
3047	double			 x,
3048	double			 y,
3049	int				*backptr,
3050	dk4_er_t		*erp
3051)
3052{
3053	$? "+ dk4gra_i_curveto"
3054#if	DK4_USE_ASSERT
3055	assert(NULL != gra);
3056#endif
3057	switch (gra->dr) {
3058		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3059			if (0 == dk4gra_eps_curveto(gra,xc1,yc1,xc2,yc2,x,y,erp)) {
3060				if (NULL != backptr) { *backptr = 0; }
3061			}
3062		} break;
3063		case DK4_GRA_DRIVER_PGF : {
3064			if (0 == dk4gra_pgf_curveto(gra,xc1,yc1,xc2,yc2,x,y,erp)) {
3065				if (NULL != backptr) { *backptr = 0; }
3066			}
3067		} break;
3068		default : {
3069			if (0 == dk4gra_pdf_curveto(gra,xc1,yc1,xc2,yc2,x,y,erp)) {
3070				if (NULL != backptr) { *backptr = 0; }
3071			}
3072		} break;
3073	}
3074	$? "- dk4gra_i_curveto"
3075}
3076
3077
3078
3079void
3080dk4gra_i_closepath(
3081	dk4_gra_t		*gra,
3082	int				*backptr,
3083	dk4_er_t		*erp
3084)
3085{
3086	$? "+ dk4gra_i_closepath"
3087#if	DK4_USE_ASSERT
3088	assert(NULL != gra);
3089#endif
3090	switch (gra->dr) {
3091		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3092			if (0 == dk4gra_eps_closepath(gra, erp)) {
3093				if (NULL != backptr) { *backptr = 0; }
3094			}
3095		} break;
3096		case DK4_GRA_DRIVER_PGF : {
3097			if (0 == dk4gra_pgf_closepath(gra, erp)) {
3098				if (NULL != backptr) { *backptr = 0; }
3099			}
3100		} break;
3101		default : {
3102			if (0 == dk4gra_pdf_closepath(gra, erp)) {
3103				if (NULL != backptr) { *backptr = 0; }
3104			}
3105		} break;
3106	}
3107	$? "- dk4gra_i_closepath"
3108}
3109
3110
3111
3112void
3113dk4gra_i_ellipse(
3114	dk4_gra_t		*gra,
3115	double			 xc,
3116	double			 yc,
3117	double			 rx,
3118	double			 ry,
3119	double			 rot,
3120	dk4_bb_t		*bbptr,
3121	int				*backptr,
3122	dk4_er_t		*erp
3123)
3124{
3125	dk4_gra_point_t	points[DK4_GRA_CIRCLE_POINTS];	/* Points for circle */
3126	size_t			i;	/* Index of current point */
3127	size_t			c1;	/* Index of first control point after point */
3128	size_t			c2;	/* Index of second control point after point */
3129	size_t			c3;	/* Index of third control point after point */
3130#if	DK4_USE_ASSERT
3131	assert(NULL != gra);
3132#endif
3133
3134	/*	2017-10-31
3135		The TikZ and PGF manual explains that the pgfpathellipse command will
3136		apply coordinate transformations to all coordinates.
3137		So better calculate the curve ourselves.
3138	*/
3139
3140	if (	0 == dk4gratool_points_for_ellipse(
3141				points, DK4_GRA_CIRCLE_POINTS, xc, yc, rx, ry, rot, erp
3142			)
3143	) {
3144		if (NULL != backptr) { *backptr = 0; }
3145		goto finished;
3146	}
3147	/*	Construct path as cycle of Bezier segments
3148	*/
3149	for (i = 0; i < ((DK4_GRA_CIRCLE_POINTS) / 3); i++) {
3150		if (0 == i) {
3151			dk4gra_i_newpath_moveto(gra,points[0].x,points[0].y,backptr,erp);
3152		}
3153		c1 = 3 * i + 1;
3154		c2 = 3 * i + 2;
3155		c3 = 3 * i + 3;
3156		if (DK4_GRA_CIRCLE_POINTS <= c3) { c3 = 0; }
3157		dk4gra_i_curveto(
3158			gra, points[c1].x, points[c1].y,
3159			points[c2].x, points[c2].y, points[c3].x, points[c3].y, backptr, erp
3160		);
3161	}
3162	dk4gra_i_closepath(gra, backptr, erp);
3163	if (NULL != bbptr) {
3164		for (i = 0; i < ((DK4_GRA_CIRCLE_POINTS) / 3); i++) {
3165			c1 = 3 * i + 1;
3166			c2 = 3 * i + 2;
3167			c3 = 3 * i + 3;
3168			if (DK4_GRA_CIRCLE_POINTS <= c3) { c3 = 0; }
3169			dk4bb_add_bezier(
3170				bbptr,
3171				points[i].x, points[i].y, points[c1].x, points[c1].y,
3172				points[c2].x, points[c2].y, points[c3].x, points[c3].y
3173			);
3174		}
3175		$? ". test 1"
3176		$? ". xmin=%g", bbptr->xmin
3177		$? ". xmax=%g", bbptr->xmax
3178		$? ". ymin=%g", bbptr->ymin
3179		$? ". ymax=%g", bbptr->ymax
3180		dk4bb_add_rotated_ellipse(bbptr, xc, yc, rx, ry, rot);
3181		$? ". test 2"
3182		$? ". xmin=%g", bbptr->xmin
3183		$? ". xmax=%g", bbptr->xmax
3184		$? ". ymin=%g", bbptr->ymin
3185		$? ". ymax=%g", bbptr->ymax
3186	}
3187
3188	finished:
3189	return;
3190}
3191
3192
3193
3194void
3195dk4gra_i_circle(
3196	dk4_gra_t		*gra,
3197	double			 xc,
3198	double			 yc,
3199	double			 r,
3200	int				*backptr,
3201	dk4_er_t		*erp
3202)
3203{
3204	$? "+ dk4gra_i_circle"
3205#if	DK4_USE_ASSERT
3206	assert(NULL != gra);
3207#endif
3208	switch (gra->dr) {
3209		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3210			if (0 == dk4gra_eps_circle(gra, xc, yc, r, erp)) {
3211				if (NULL != backptr) { *backptr = 0; }
3212			}
3213		} break;
3214		case DK4_GRA_DRIVER_PGF : {
3215			if (0 == dk4gra_pgf_circle(gra, xc, yc, r, erp)) {
3216				if (NULL != backptr) { *backptr = 0; }
3217			}
3218		} break;
3219		default : {
3220			dk4gra_i_ellipse(gra, xc, yc, r, r, 0.0, NULL, backptr, erp);
3221		} break;
3222	}
3223	$? "- dk4gra_i_circle"
3224}
3225
3226
3227
3228void
3229dk4gra_i_rectangle(
3230	dk4_gra_t		*gra,
3231	double			 xl,
3232	double			 xr,
3233	double			 yb,
3234	double			 yt,
3235	double			 r,
3236	int				*backptr,
3237	dk4_er_t		*erp
3238)
3239{
3240	double	 dx;		/* Width */
3241	double	 dy;		/* Height */
3242	double	 xc1;		/* Control point coordinates for rounded corners */
3243	double	 yc1;
3244	double	 xc2;
3245	double	 yc2;
3246	$? "+ dk4gra_i_rectangle"
3247#if	DK4_USE_ASSERT
3248	assert(NULL != gra);
3249#endif
3250	$!trace-code	if (NULL != backptr) {
3251	$? ". *backptr = %d", *backptr
3252	$!trace-code	}
3253	if (0.0 < r) {
3254		dx = xr - xl;
3255		dy = yt - yb;
3256		dx = 0.4999 * fabs(dx);
3257		dy = 0.4999 * fabs(dy);
3258		if (r > dx) {					$? ". r = %g   dx = %g", r, dx
3259			r = dx;
3260#if	0
3261			/*	Silently correct radius
3262			*/
3263			if (NULL != backptr) {		$? "! r > dx"
3264				*backptr = 0;
3265			}
3266#endif
3267		}
3268		if (r > dy) {					$? ". r = %g   dy = %g", r, dy
3269			r = dy;
3270#if	0
3271			/*	Silently correct radius
3272			*/
3273			if (NULL != backptr) {		$? "! r > dy"
3274				*backptr = 0;
3275			}
3276#endif
3277		}
3278	}
3279	switch (gra->dr) {
3280		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3281			if (0 == dk4gra_eps_rectangle(gra, xl, xr, yb, yt, r, erp)) {
3282				if (NULL != backptr) {	$? "! dk4gra_eps_rectangle"
3283					*backptr = 0;
3284				}
3285			}
3286		} break;
3287		case DK4_GRA_DRIVER_PGF : {
3288			if (0 == dk4gra_pgf_rectangle(gra, xl, xr, yb, yt, r, erp)) {
3289				if (NULL != backptr) {	$? "! dk4gra_pgf_rectangle"
3290					*backptr = 0;
3291				}
3292			}
3293		} break;
3294		default : {
3295			if (0.0 >= r) {
3296				dk4gra_i_newpath_moveto(gra, xl, yb, backptr, erp);
3297				dk4gra_i_lineto(gra, xr, yb, backptr, erp);
3298				dk4gra_i_lineto(gra, xr, yt, backptr, erp);
3299				dk4gra_i_lineto(gra, xl, yt, backptr, erp);
3300				dk4gra_i_closepath(gra, backptr, erp);
3301			}
3302			else {
3303				dk4gra_i_newpath_moveto(gra, (xl + r), yb, backptr, erp);
3304				dk4gra_i_lineto(gra, (xr - r), yb, backptr, erp);
3305				xc1 = xr - (1.0 - KAPPA_4) * r;
3306				yc1 = yb;
3307				xc2 = xr;
3308				yc2 = yb + (1.0 - KAPPA_4) * r;
3309				dk4gra_i_curveto(gra,xc1,yc1,xc2,yc2,xr,(yb+r),backptr,erp);
3310				dk4gra_i_lineto(gra, xr, (yt - r), backptr, erp);
3311				xc1 = xr;
3312				yc1 = yt - (1.0 - KAPPA_4) * r;
3313				xc2 = xr - (1.0 - KAPPA_4) * r;
3314				yc2 = yt;
3315				dk4gra_i_curveto(gra,xc1,yc1,xc2,yc2,(xr-r),yt,backptr,erp);
3316				dk4gra_i_lineto(gra, (xl+r), yt, backptr, erp);
3317				xc1 = xl + (1.0 - KAPPA_4) * r;
3318				yc1 = yt;
3319				xc2 = xl;
3320				yc2 = yt - (1.0 - KAPPA_4) * r;
3321				dk4gra_i_curveto(gra,xc1,yc1,xc2,yc2,xl,(yt-r),backptr,erp);
3322				dk4gra_i_lineto(gra, xl, (yb + r), backptr, erp);
3323				xc1 = xl;
3324				yc1 = yb + (1.0 - KAPPA_4) * r;
3325				xc2 = xl + (1.0 - KAPPA_4) * r;
3326				yc2 = yb;
3327				dk4gra_i_curveto(gra,xc1,yc1,xc2,yc2,(xl+r),yb,backptr,erp);
3328				dk4gra_i_closepath(gra, backptr, erp);
3329			}
3330		} break;
3331	}
3332	$? "- dk4gra_i_rectangle"
3333}
3334
3335
3336
3337void
3338dk4gra_i_arc(
3339	dk4_gra_t		*gra,
3340	double			 xc,
3341	double			 yc,
3342	double			 ra,
3343	double			 start,
3344	double			 end,
3345	int				 cl,
3346	int				*backptr,
3347	dk4_er_t		*erp
3348)
3349{
3350	double				 angdiff;		/* Angle difference end - start */
3351	double				 x0;			/* Start of current arc segment */
3352	double				 y0;			/* Start of current arc segment */
3353	double				 dxdt0;			/* First x derivative at start */
3354	double				 dydt0;			/* First y derivative at start */
3355	double				 x1;			/* End of current arg segment */
3356	double				 y1;			/* End of current arg segment */
3357	double				 dxdt1;			/* First x derivative at end */
3358	double				 dydt1;			/* First y derivative at end */
3359	double				 segcalc;		/* Number of segments */
3360	double				 seglgt;		/* Angle per segment */
3361	double				 kappa;			/* Kappa value */
3362	double				 segend;		/* Angle at end of segment */
3363	size_t				 segments;		/* Number of segments */
3364	size_t				 i;				/* Current segment to draw */
3365	$? "+ dk4gra_i_arc"
3366#if	DK4_USE_ASSERT
3367	assert(NULL != gra);
3368#endif
3369	switch (gra->dr) {
3370		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3371			if (0 == dk4gra_eps_arc(gra, xc, yc, ra, start, end, cl, erp)) {
3372				if (NULL != backptr) { *backptr = 0; }
3373			}
3374		} break;
3375		/*	2017-10-31
3376			The TikZ and PGF manual warns the computation done by the
3377			pgfpatharcto command are numerically very unstable and the arc
3378			will not necessary end at the intended end point.
3379			So we do not use that command and do the necessary calculations
3380			ourselves in the default branch.
3381		*/
3382		default : {
3383			start *= M_PI;
3384			end   *= M_PI;
3385			start /= 180.0;
3386			end   /= 180.0;
3387			angdiff = end - start;
3388			segcalc	= angdiff * 4.0 / M_PI;
3389			segments	= (size_t)ceil(segcalc);
3390			seglgt = angdiff / (double)segments;
3391			kappa = dk4gratool_kappa_for_angle(seglgt);
3392			x0 = xc + ra * cos(start);
3393			y0 = yc + ra * sin(start);
3394			dxdt0 = -1.0 * ra * seglgt * sin(start);
3395			dydt0 = ra * seglgt * cos(start);
3396			dk4gra_i_newpath_moveto(gra, x0, y0, backptr, erp);
3397			for (i = 0; i < segments; i++) {
3398				segend = start + angdiff * (double)(i + 1) / (double)segments;
3399				x1 = xc + ra * cos(segend);
3400				y1 = yc + ra * sin(segend);
3401				dxdt1 = -1.0 * ra * seglgt * sin(segend);
3402				dydt1 = ra * seglgt * cos(segend);
3403				dk4gra_i_curveto(gra,
3404					x0 + kappa * dxdt0,
3405					y0 + kappa * dydt0,
3406					x1 - kappa * dxdt1,
3407					y1 - kappa * dydt1,
3408					x1,
3409					y1,
3410					backptr, erp
3411				);
3412				x0 = x1;
3413				y0 = y1;
3414				dxdt0 = dxdt1;
3415				dydt0 = dydt1;
3416			}
3417			if (0 != cl) {
3418				dk4gra_i_lineto(gra, xc, yc, backptr, erp);
3419				dk4gra_i_closepath(gra, backptr, erp);
3420			}
3421		} break;
3422	}
3423	$? "- dk4gra_i_arc"
3424}
3425
3426
3427void
3428dk4gra_gsave(
3429	dk4_gra_t		*gra,
3430	int				*backptr,
3431	dk4_er_t		*erp
3432)
3433{
3434	int		 back = 0;
3435	$? "+ dk4gra_gsave"
3436#if	DK4_USE_ASSERT
3437	assert(NULL != gra);
3438#endif
3439	if (NULL == gra) {
3440		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3441		goto finished;
3442	}
3443	if (NULL == gra->curpg) {
3444		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3445		goto finished;
3446	}
3447	back = 1;
3448	dk4gra_i_gsave(gra, &back, erp);
3449
3450	finished:
3451	$? "- dk4gra_gsave %d", back
3452	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
3453}
3454
3455
3456
3457void
3458dk4gra_grestore(
3459	dk4_gra_t		*gra,
3460	int				*backptr,
3461	dk4_er_t		*erp
3462)
3463{
3464	int		 back = 0;
3465	$? "+ dk4gra_grestore"
3466#if	DK4_USE_ASSERT
3467	assert(NULL != gra);
3468#endif
3469	if (NULL == gra) {
3470		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3471		goto finished;
3472	}
3473	if (NULL == gra->curpg) {
3474		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3475		goto finished;
3476	}
3477	back = 1;
3478	dk4gra_i_grestore(gra, 1, &back, erp);
3479
3480	finished:
3481	$? "- dk4gra_grestore %d", back
3482	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
3483}
3484
3485
3486
3487void
3488dk4gra_set_gs_for_pattern_only(
3489	dk4_gra_t		*gra,
3490	int				 val,
3491	dk4_er_t		*erp
3492)
3493{
3494#if	DK4_USE_ASSERT
3495	assert(NULL != gra);
3496#endif
3497	if (NULL != gra) {
3498		gra->gscp = ((0 != val) ? (1) : (0));
3499	}
3500	else {
3501		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3502	}
3503}
3504
3505
3506
3507void
3508dk4gra_set_line_width(
3509	dk4_gra_t		*gra,
3510	double			 lw,
3511	int				*backptr,
3512	dk4_er_t		*erp
3513)
3514{
3515	int		 back = 0;
3516	$? "+ dk4gra_set_line_width"
3517#if	DK4_USE_ASSERT
3518	assert(NULL != gra);
3519#endif
3520	if (NULL == gra) {
3521		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3522		goto finished;
3523	}
3524	if (NULL == gra->curpg) {
3525		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3526		goto finished;
3527	}
3528	switch (gra->dr) {
3529		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3530			back = dk4gra_eps_set_line_width(gra, lw, erp);
3531		} break;
3532		case DK4_GRA_DRIVER_PGF : {
3533			back = dk4gra_pgf_set_line_width(gra, lw, erp);
3534		} break;
3535		default : {
3536			back = dk4gra_pdf_set_line_width(gra, lw, erp);
3537		} break;
3538	}
3539	finished:
3540	$? "- dk4gra_set_line_width %d", back
3541	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
3542}
3543
3544
3545
3546void
3547dk4gra_set_line_style(
3548	dk4_gra_t		*gra,
3549	dk4_gra_ls_t	 ls,
3550	double			 sv,
3551	int				*backptr,
3552	dk4_er_t		*erp
3553)
3554{
3555	int		 back = 0;
3556	$? "+ dk4gra_set_line_style"
3557#if	DK4_USE_ASSERT
3558	assert(NULL != gra);
3559#endif
3560	if (NULL == gra) {
3561		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3562		goto finished;
3563	}
3564	if (NULL == gra->curpg) {
3565		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3566		goto finished;
3567	}
3568	switch (gra->dr) {
3569		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3570			back = dk4gra_eps_set_line_style(gra, ls, sv, erp);
3571		} break;
3572		case DK4_GRA_DRIVER_PGF : {
3573			back = dk4gra_pgf_set_line_style(gra, ls, sv, erp);
3574		} break;
3575		default : {
3576			back = dk4gra_pdf_set_line_style(gra, ls, sv, erp);
3577		} break;
3578	}
3579	finished:
3580	$? "- dk4gra_set_line_style %d", back
3581	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
3582}
3583
3584
3585
3586void
3587dk4gra_set_line_cap(
3588	dk4_gra_t		*gra,
3589	dk4_gra_lc_t	 lc,
3590	int				*backptr,
3591	dk4_er_t		*erp
3592)
3593{
3594	int		 back = 0;
3595	$? "+ dk4gra_set_line_cap"
3596#if	DK4_USE_ASSERT
3597	assert(NULL != gra);
3598#endif
3599	if (NULL == gra) {
3600		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3601		goto finished;
3602	}
3603	if (NULL == gra->curpg) {
3604		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3605		goto finished;
3606	}
3607	switch (gra->dr) {
3608		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3609			back = dk4gra_eps_set_line_cap(gra, lc, erp);
3610		} break;
3611		case DK4_GRA_DRIVER_PGF : {
3612			back = dk4gra_pgf_set_line_cap(gra, lc, erp);
3613		} break;
3614		default : {
3615			back = dk4gra_pdf_set_line_cap(gra, lc, erp);
3616		} break;
3617	}
3618	finished:
3619	$? "- dk4gra_set_line_cap %d", back
3620	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
3621}
3622
3623
3624
3625void
3626dk4gra_set_line_join(
3627	dk4_gra_t		*gra,
3628	dk4_gra_lj_t	 lj,
3629	double			 ml,
3630	int				*backptr,
3631	dk4_er_t		*erp
3632)
3633{
3634	int		 back = 0;
3635	$? "+ dk4gra_set_line_join"
3636#if	DK4_USE_ASSERT
3637	assert(NULL != gra);
3638#endif
3639	if (NULL == gra) {
3640		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3641		goto finished;
3642	}
3643	if (NULL == gra->curpg) {
3644		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3645		goto finished;
3646	}
3647	switch (gra->dr) {
3648		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3649			back = dk4gra_eps_set_line_join(gra, lj, ml, erp);
3650		} break;
3651		case DK4_GRA_DRIVER_PGF : {
3652			back = dk4gra_pgf_set_line_join(gra, lj, ml, erp);
3653		} break;
3654		default : {
3655			back = dk4gra_pdf_set_line_join(gra, lj, ml, erp);
3656		} break;
3657	}
3658	finished:
3659	$? "- dk4gra_set_line_join %d", back
3660	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
3661}
3662
3663
3664
3665void
3666dk4gra_set_fill_gray(
3667	dk4_gra_t		*gra,
3668	double			 g,
3669	int				*backptr,
3670	dk4_er_t		*erp
3671)
3672{
3673	int		 back = 0;
3674	$? "+ dk4gra_set_fill_gray"
3675#if	DK4_USE_ASSERT
3676	assert(NULL != gra);
3677#endif
3678	if (NULL == gra) {
3679		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3680		goto finished;
3681	}
3682	if (NULL == gra->curpg) {
3683		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3684		goto finished;
3685	}
3686	g = dk4gra_i_to_range(g, 0.0, 1.0);
3687	switch (gra->dr) {
3688		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3689			back = dk4gra_eps_set_fill_gray(gra, g, erp);
3690		} break;
3691		case DK4_GRA_DRIVER_PGF : {
3692			back = dk4gra_pgf_set_fill_gray(gra, g, erp);
3693		} break;
3694		default : {
3695			back = dk4gra_pdf_set_fill_gray(gra, g, erp);
3696		} break;
3697	}
3698	finished:
3699	$? "- dk4gra_set_fill_gray %d", back
3700	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
3701}
3702
3703
3704
3705void
3706dk4gra_set_fill_rgb(
3707	dk4_gra_t		*gra,
3708	double			 r,
3709	double			 g,
3710	double			 b,
3711	int				*backptr,
3712	dk4_er_t		*erp
3713)
3714{
3715	double	 array1[4];
3716	double	 array2[4];
3717	double	 array3[4];
3718	size_t	 i;
3719	int		 back = 0;
3720	$? "+ dk4gra_set_fill_rgb"
3721#if	DK4_USE_ASSERT
3722	assert(NULL != gra);
3723#endif
3724	if (NULL == gra) {
3725		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3726		goto finished;
3727	}
3728	if (NULL == gra->curpg) {
3729		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3730		goto finished;
3731	}
3732	r = dk4gra_i_to_range(r, 0.0, 1.0);
3733	g = dk4gra_i_to_range(g, 0.0, 1.0);
3734	b = dk4gra_i_to_range(b, 0.0, 1.0);
3735	if (0 != (DK4_GRA_DOC_FLAG_FORCE_GRAY & (gra->docfl))) {
3736		for (i = 0; i < 4 ; i++) { array1[i] = array2[i] = array3[i] = 0.0; }
3737		array1[0] = r; array1[1] = g; array1[2] = b;
3738		dk4cs_color_convert(
3739			array2, DK4_CS_GRAY, 4,		array1, DK4_CS_RGB, 3,
3740			array3, 3,					&(gra->cscctx), erp
3741		);
3742		array2[0] = dk4gra_i_to_range(array2[0], 0.0, 1.0);
3743		switch (gra->dr) {
3744			case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3745				back = dk4gra_eps_set_fill_gray(gra, array2[0], erp);
3746			} break;
3747			case DK4_GRA_DRIVER_PGF : {
3748				back = dk4gra_pgf_set_fill_gray(gra, array2[0], erp);
3749			} break;
3750			default : {
3751				back = dk4gra_pdf_set_fill_gray(gra, array2[0], erp);
3752			} break;
3753		}
3754	}
3755	else {
3756		switch (gra->dr) {
3757			case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3758				back = dk4gra_eps_set_fill_rgb(gra, r, g, b, erp);
3759			} break;
3760			case DK4_GRA_DRIVER_PGF : {
3761				back = dk4gra_pgf_set_fill_rgb(gra, r, g, b, erp);
3762			} break;
3763			default : {
3764				back = dk4gra_pdf_set_fill_rgb(gra, r, g, b, erp);
3765			} break;
3766		}
3767	}
3768
3769	finished:
3770	$? "- dk4gra_set_fill_rgb %d", back
3771	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
3772}
3773
3774
3775
3776void
3777dk4gra_set_fill_cmyk(
3778	dk4_gra_t		*gra,
3779	double			 c,
3780	double			 m,
3781	double			 y,
3782	double			 k,
3783	int				*backptr,
3784	dk4_er_t		*erp
3785)
3786{
3787	double	 array1[4];
3788	double	 array2[4];
3789	double	 array3[4];
3790	size_t	 i;
3791	int		 back = 0;
3792	$? "+ dk4gra_set_fill_cmyk"
3793#if	DK4_USE_ASSERT
3794	assert(NULL != gra);
3795#endif
3796	if (NULL == gra) {
3797		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3798		goto finished;
3799	}
3800	if (NULL == gra->curpg) {
3801		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3802		goto finished;
3803	}
3804	c = dk4gra_i_to_range(c, 0.0, 1.0);
3805	m = dk4gra_i_to_range(m, 0.0, 1.0);
3806	y = dk4gra_i_to_range(y, 0.0, 1.0);
3807	k = dk4gra_i_to_range(k, 0.0, 1.0);
3808	if (0 != (DK4_GRA_DOC_FLAG_FORCE_GRAY & (gra->docfl))) {
3809		for (i = 0; i < 4 ; i++) { array1[i] = array2[i] = array3[i] = 0.0; }
3810		array1[0] = c; array1[1] = m; array1[2] = y; array1[3] = k;
3811		dk4cs_color_convert(
3812			array2, DK4_CS_GRAY, 4,		array1, DK4_CS_CMYK, 4,
3813			array3, 4,					&(gra->cscctx), erp
3814		);
3815		array2[0] = dk4gra_i_to_range(array2[0], 0.0, 1.0);
3816		switch (gra->dr) {
3817			case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3818				back = dk4gra_eps_set_fill_gray(gra, array2[0], erp);
3819			} break;
3820			case DK4_GRA_DRIVER_PGF : {
3821				back = dk4gra_pgf_set_fill_gray(gra, array2[0], erp);
3822			} break;
3823			default : {
3824				back = dk4gra_pdf_set_fill_gray(gra, array2[0], erp);
3825			} break;
3826		}
3827	}
3828	else {
3829		switch (gra->dr) {
3830			case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3831				back = dk4gra_eps_set_fill_cmyk(gra, c, m, y, k, erp);
3832			} break;
3833			case DK4_GRA_DRIVER_PGF : {
3834				back = dk4gra_pgf_set_fill_cmyk(gra, c, m, y, k, erp);
3835			} break;
3836			default : {
3837				back = dk4gra_pdf_set_fill_cmyk(gra, c, m, y, k, erp);
3838			} break;
3839		}
3840	}
3841
3842	finished:
3843	$? "- dk4gra_set_fill_cmyk %d", back
3844	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
3845}
3846
3847
3848
3849void
3850dk4gra_set_stroke_gray(
3851	dk4_gra_t		*gra,
3852	double			 g,
3853	int				*backptr,
3854	dk4_er_t		*erp
3855)
3856{
3857	int		 back = 0;
3858	$? "+ dk4gra_set_stroke_gray"
3859#if	DK4_USE_ASSERT
3860	assert(NULL != gra);
3861#endif
3862	if (NULL == gra) {
3863		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3864		goto finished;
3865	}
3866	if (NULL == gra->curpg) {
3867		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3868		goto finished;
3869	}
3870	g = dk4gra_i_to_range(g, 0.0, 1.0);
3871	switch (gra->dr) {
3872		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3873			back = dk4gra_eps_set_stroke_gray(gra, g, erp);
3874		} break;
3875		case DK4_GRA_DRIVER_PGF : {
3876			back = dk4gra_pgf_set_stroke_gray(gra, g, erp);
3877		} break;
3878		default : {
3879			back = dk4gra_pdf_set_stroke_gray(gra, g, erp);
3880		} break;
3881	}
3882	finished:
3883	$? "- dk4gra_set_stroke_gray %d", back
3884	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
3885}
3886
3887
3888
3889void
3890dk4gra_set_stroke_rgb(
3891	dk4_gra_t		*gra,
3892	double			 r,
3893	double			 g,
3894	double			 b,
3895	int				*backptr,
3896	dk4_er_t		*erp
3897)
3898{
3899	double	 array1[4];
3900	double	 array2[4];
3901	double	 array3[4];
3902	size_t	 i;
3903	int		 back = 0;
3904	$? "+ dk4gra_set_stroke_rgb"
3905#if	DK4_USE_ASSERT
3906	assert(NULL != gra);
3907#endif
3908	if (NULL == gra) {
3909		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3910		goto finished;
3911	}
3912	if (NULL == gra->curpg) {
3913		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3914		goto finished;
3915	}
3916	r = dk4gra_i_to_range(r, 0.0, 1.0);
3917	g = dk4gra_i_to_range(g, 0.0, 1.0);
3918	b = dk4gra_i_to_range(b, 0.0, 1.0);
3919	if (0 != (DK4_GRA_DOC_FLAG_FORCE_GRAY & (gra->docfl))) {
3920		/*
3921			Force gray
3922		*/
3923		for (i = 0; i < 4 ; i++) { array1[i] = array2[i] = array3[i] = 0.0; }
3924		array1[0] = r; array1[1] = g; array1[2] = b;
3925		dk4cs_color_convert(
3926			array2, DK4_CS_GRAY, 4,		array1, DK4_CS_RGB, 3,
3927			array3, 3,					&(gra->cscctx), erp
3928		);
3929		array2[0] = dk4gra_i_to_range(array2[0], 0.0, 1.0);
3930		switch (gra->dr) {
3931			case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3932				back = dk4gra_eps_set_stroke_gray(gra, array2[0], erp);
3933			} break;
3934			case DK4_GRA_DRIVER_PGF : {
3935				back = dk4gra_pgf_set_stroke_gray(gra, array2[0], erp);
3936			} break;
3937			default : {
3938				back = dk4gra_pdf_set_stroke_gray(gra, array2[0], erp);
3939			} break;
3940		}
3941	}
3942	else {
3943		/*
3944			RGB allowed
3945		*/
3946		switch (gra->dr) {
3947			case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3948				back = dk4gra_eps_set_stroke_rgb(gra, r, g, b, erp);
3949			} break;
3950			case DK4_GRA_DRIVER_PGF : {
3951				back = dk4gra_pgf_set_stroke_rgb(gra, r, g, b, erp);
3952			} break;
3953			default : {
3954				back = dk4gra_pdf_set_stroke_rgb(gra, r, g, b, erp);
3955			} break;
3956		}
3957	}
3958
3959	finished:
3960	$? "- dk4gra_set_stroke_rgb %d", back
3961	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
3962}
3963
3964
3965
3966void
3967dk4gra_set_stroke_cmyk(
3968	dk4_gra_t		*gra,
3969	double			 c,
3970	double			 m,
3971	double			 y,
3972	double			 k,
3973	int				*backptr,
3974	dk4_er_t		*erp
3975)
3976{
3977	double	 array1[4];
3978	double	 array2[4];
3979	double	 array3[4];
3980	size_t	 i;
3981	int		 back = 0;
3982	$? "+ dk4gra_set_stroke_cmyk"
3983#if	DK4_USE_ASSERT
3984	assert(NULL != gra);
3985#endif
3986	if (NULL == gra) {
3987		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3988		goto finished;
3989	}
3990	if (NULL == gra->curpg) {
3991		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
3992		goto finished;
3993	}
3994	c = dk4gra_i_to_range(c, 0.0, 1.0);
3995	m = dk4gra_i_to_range(m, 0.0, 1.0);
3996	y = dk4gra_i_to_range(y, 0.0, 1.0);
3997	k = dk4gra_i_to_range(k, 0.0, 1.0);
3998	if (0 != (DK4_GRA_DOC_FLAG_FORCE_GRAY & (gra->docfl))) {
3999		/*
4000			Force gray
4001		*/
4002		for (i = 0; i < 4 ; i++) { array1[i] = array2[i] = array3[i] = 0.0; }
4003		array1[0] = c; array1[1] = m; array1[2] = y; array1[3] = k;
4004		dk4cs_color_convert(
4005			array2, DK4_CS_GRAY, 4,		array1, DK4_CS_CMYK, 3,
4006			array3, 3,					&(gra->cscctx), erp
4007		);
4008		array2[0] = dk4gra_i_to_range(array2[0], 0.0, 1.0);
4009		switch (gra->dr) {
4010			case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
4011				back = dk4gra_eps_set_stroke_gray(gra, array2[0], erp);
4012			} break;
4013			case DK4_GRA_DRIVER_PGF : {
4014				back = dk4gra_pgf_set_stroke_gray(gra, array2[0], erp);
4015			} break;
4016			default : {
4017				back = dk4gra_pdf_set_stroke_gray(gra, array2[0], erp);
4018			} break;
4019		}
4020	}
4021	else {
4022		/*
4023			CMYK allowed
4024		*/
4025		switch (gra->dr) {
4026			case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
4027				back = dk4gra_eps_set_stroke_cmyk(gra, c, m, y, k, erp);
4028			} break;
4029			case DK4_GRA_DRIVER_PGF : {
4030				back = dk4gra_pgf_set_stroke_cmyk(gra, c, m, y, k, erp);
4031			} break;
4032			default : {
4033				back = dk4gra_pdf_set_stroke_cmyk(gra, c, m, y, k, erp);
4034			} break;
4035		}
4036	}
4037
4038	finished:
4039	$? "- dk4gra_set_stroke_cmyk %d", back
4040	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4041}
4042
4043
4044
4045
4046void
4047dk4gra_prepare_fill(
4048	dk4_gra_t	*gra,
4049	int			*backptr,
4050	dk4_er_t	*erp
4051)
4052{
4053	int		 back = 0;
4054	$? "+ dk4gra_prepare_fill"
4055#if	DK4_USE_ASSERT
4056	assert(NULL != gra);
4057#endif
4058	if (NULL == gra) {
4059		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4060		goto finished;
4061	}
4062	if (NULL == gra->curpg) {
4063		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4064		goto finished;
4065	}
4066	back = 1;
4067	dk4gra_i_prepare_fill(gra, &back, erp);
4068
4069	finished:
4070	$? "- dk4gra_prepare_fill %d", back
4071	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4072}
4073
4074
4075
4076void
4077dk4gra_prepare_stroke(
4078	dk4_gra_t	*gra,
4079	int			*backptr,
4080	dk4_er_t	*erp
4081)
4082{
4083	int		 back = 0;
4084	$? "+ dk4gra_prepare_stroke"
4085#if	DK4_USE_ASSERT
4086	assert(NULL != gra);
4087#endif
4088	if (NULL == gra) {
4089		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4090		goto finished;
4091	}
4092	if (NULL == gra->curpg) {
4093		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4094		goto finished;
4095	}
4096	back = 1;
4097	dk4gra_i_prepare_stroke(gra, &back, erp);
4098
4099	finished:
4100	$? "- dk4gra_prepare_stroke %d", back
4101	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4102}
4103
4104
4105
4106void
4107dk4gra_prepare_fill_and_stroke(
4108	dk4_gra_t	*gra,
4109	int			*backptr,
4110	dk4_er_t	*erp
4111)
4112{
4113	int		 back = 0;
4114	$? "+ dk4gra_prepare_fill_and_stroke"
4115#if	DK4_USE_ASSERT
4116	assert(NULL != gra);
4117#endif
4118	if (NULL == gra) {
4119		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4120		goto finished;
4121	}
4122	if (NULL == gra->curpg) {
4123		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4124		goto finished;
4125	}
4126	back = 1;
4127	dk4gra_i_prepare_fill_and_stroke(gra, &back, erp);
4128
4129	finished:
4130	$? "- dk4gra_prepare_fill_and_stroke %d", back
4131	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4132}
4133
4134
4135
4136int
4137dk4gra_can_fill_and_stroke(
4138	const dk4_gra_t	*gra
4139)
4140{
4141	int		 back = 0;
4142	$? "+ dk4gra_can_fill_and_stroke"
4143#if	DK4_USE_ASSERT
4144	assert(NULL != gra);
4145#endif
4146	switch (gra->dr) {
4147		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
4148			back = 0;
4149		} break;
4150		case DK4_GRA_DRIVER_PGF : {
4151			back = 1;
4152		} break;
4153		default : {
4154			back = 1;
4155		} break;
4156	}
4157	$? "- dk4gra_can_fill_and_stroke %d", back
4158	return back;
4159}
4160
4161
4162
4163void
4164dk4gra_fill(
4165	dk4_gra_t		*gra,
4166	int				*backptr,
4167	dk4_er_t		*erp
4168)
4169{
4170	int		 back = 0;
4171	$? "+ dk4gra_fill"
4172#if	DK4_USE_ASSERT
4173	assert(NULL != gra);
4174#endif
4175	if (NULL == gra) {
4176		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4177		goto finished;
4178	}
4179	if (NULL == gra->curpg) {
4180		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4181		goto finished;
4182	}
4183	back = 1;
4184	dk4gra_i_fill(gra, &back, erp);
4185
4186	finished:
4187	$? "- dk4gra_fill %d", back
4188	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4189}
4190
4191
4192
4193void
4194dk4gra_stroke(
4195	dk4_gra_t		*gra,
4196	int				*backptr,
4197	dk4_er_t		*erp
4198)
4199{
4200	int		 back = 0;
4201	$? "+ dk4gra_stroke"
4202#if	DK4_USE_ASSERT
4203	assert(NULL != gra);
4204#endif
4205	if (NULL == gra) {
4206		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4207		goto finished;
4208	}
4209	if (NULL == gra->curpg) {
4210		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4211		goto finished;
4212	}
4213	back = 1;
4214	dk4gra_i_stroke(gra, &back, erp);
4215
4216	finished:
4217	$? "- dk4gra_stroke %d", back
4218	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4219}
4220
4221
4222
4223void
4224dk4gra_fill_and_stroke(
4225	dk4_gra_t		*gra,
4226	int				*backptr,
4227	dk4_er_t		*erp
4228)
4229{
4230	int		 back = 0;
4231	$? "+ dk4gra_fill_and_stroke"
4232#if	DK4_USE_ASSERT
4233	assert(NULL != gra);
4234#endif
4235	if (NULL == gra) {
4236		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4237		goto finished;
4238	}
4239	if (NULL == gra->curpg) {
4240		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4241		goto finished;
4242	}
4243	back = 1;
4244	dk4gra_i_fill_and_stroke(gra, &back, erp);
4245
4246	finished:
4247	$? "- dk4gra_fill_and_stroke %d", back
4248	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4249}
4250
4251
4252
4253void
4254dk4gra_clip(
4255	dk4_gra_t		*gra,
4256	int				*backptr,
4257	dk4_er_t		*erp
4258)
4259{
4260	int		 back = 0;
4261	$? "+ dk4gra_clip"
4262#if	DK4_USE_ASSERT
4263	assert(NULL != gra);
4264#endif
4265	if (NULL == gra) {
4266		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4267		goto finished;
4268	}
4269	if (NULL == gra->curpg) {
4270		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4271		goto finished;
4272	}
4273	back = 1;
4274	dk4gra_i_clip(gra, &back, erp);
4275
4276	finished:
4277	$? "- dk4gra_clip %d", back
4278	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4279}
4280
4281
4282
4283void
4284dk4gra_newpath_moveto(
4285	dk4_gra_t		*gra,
4286	double			 x,
4287	double			 y,
4288	dk4_bb_t		*bbptr,
4289	int				*backptr,
4290	dk4_er_t		*erp
4291)
4292{
4293	int		 back = 0;
4294	$? "+ dk4gra_newpath_moveto"
4295#if	DK4_USE_ASSERT
4296	assert(NULL != gra);
4297#endif
4298	if (NULL == gra) {
4299		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4300		goto finished;
4301	}
4302	gra->cur_x = x;
4303	gra->cur_y = y;
4304	if (NULL != bbptr) {
4305		dk4bb_add_x(bbptr, x);
4306		dk4bb_add_y(bbptr, y);
4307	}
4308	if (NULL == gra->curpg) {
4309		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4310		goto finished;
4311	}
4312	back = 1;
4313	dk4gra_i_newpath_moveto(gra, x, y, &back, erp);
4314	finished:
4315	$? "- dk4gra_newpath_moveto %d", back
4316	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4317}
4318
4319
4320
4321void
4322dk4gra_lineto(
4323	dk4_gra_t		*gra,
4324	double			 x,
4325	double			 y,
4326	dk4_bb_t		*bbptr,
4327	int				*backptr,
4328	dk4_er_t		*erp
4329)
4330{
4331	int		 back = 0;
4332	$? "+ dk4gra_lineto"
4333#if	DK4_USE_ASSERT
4334	assert(NULL != gra);
4335#endif
4336	if (NULL == gra) {
4337		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4338		goto finished;
4339	}
4340	gra->cur_x = x;
4341	gra->cur_y = y;
4342	if (NULL != bbptr) {
4343		dk4bb_add_x(bbptr, x);
4344		dk4bb_add_y(bbptr, y);
4345	}
4346	if (NULL == gra->curpg) {
4347		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4348		goto finished;
4349	}
4350	back = 1;
4351	dk4gra_i_lineto(gra, x, y, &back, erp);
4352	finished:
4353	$? "- dk4gra_lineto %d", back
4354	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4355}
4356
4357
4358
4359void
4360dk4gra_curveto(
4361	dk4_gra_t		*gra,
4362	double			 xc1,
4363	double			 yc1,
4364	double			 xc2,
4365	double			 yc2,
4366	double			 x,
4367	double			 y,
4368	dk4_bb_t		*bbptr,
4369	int				*backptr,
4370	dk4_er_t		*erp
4371)
4372{
4373	int		 back = 0;
4374	$? "+ dk4gra_curveto"
4375#if	DK4_USE_ASSERT
4376	assert(NULL != gra);
4377#endif
4378	if (NULL == gra) {
4379		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4380		goto finished;
4381	}
4382	if (NULL != bbptr) {
4383		dk4bb_add_bezier(
4384			bbptr, gra->cur_x, gra->cur_y, xc1, yc1, xc2, yc2, x, y
4385		);
4386	}
4387	gra->cur_x = x;
4388	gra->cur_y = y;
4389	if (NULL == gra->curpg) {
4390		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4391		goto finished;
4392	}
4393	back = 1;
4394	dk4gra_i_curveto(gra, xc1, yc1, xc2, yc2, x, y, &back, erp);
4395	finished:
4396	$? "- dk4gra_curveto %d", back
4397	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4398}
4399
4400
4401
4402void
4403dk4gra_closepath(
4404	dk4_gra_t		*gra,
4405	int				*backptr,
4406	dk4_er_t		*erp
4407)
4408{
4409	int		 back = 0;
4410	$? "+ dk4gra_closepath"
4411#if	DK4_USE_ASSERT
4412	assert(NULL != gra);
4413#endif
4414	if (NULL == gra) {
4415		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4416		goto finished;
4417	}
4418	if (NULL == gra->curpg) {
4419		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4420		goto finished;
4421	}
4422	back = 1;
4423	dk4gra_i_closepath(gra, &back, erp);
4424	finished:
4425	$? "- dk4gra_closepath %d", back
4426	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4427}
4428
4429
4430
4431void
4432dk4gra_circle(
4433	dk4_gra_t		*gra,
4434	double			 xc,
4435	double			 yc,
4436	double			 r,
4437	dk4_bb_t		*bbptr,
4438	int				*backptr,
4439	dk4_er_t		*erp
4440)
4441{
4442	int		 back = 0;
4443	$? "+ dk4gra_circle"
4444#if	DK4_USE_ASSERT
4445	assert(NULL != gra);
4446#endif
4447	if ((NULL == gra) || (0.0 >= r)) {
4448		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4449		goto finished;
4450	}
4451	if (NULL != bbptr) {
4452		dk4bb_add_x(bbptr, xc - r); dk4bb_add_x(bbptr, xc + r);
4453		dk4bb_add_y(bbptr, yc - r); dk4bb_add_y(bbptr, yc + r);
4454	}
4455	if (NULL == gra->curpg) {
4456		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4457		goto finished;
4458	}
4459	back = 1;
4460	dk4gra_i_circle(gra, xc, yc, r, &back, erp);
4461
4462	finished:
4463	$? "- dk4gra_circle %d", back
4464	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4465}
4466
4467
4468void
4469dk4gra_rectangle(
4470	dk4_gra_t		*gra,
4471	double			 xl,
4472	double			 xr,
4473	double			 yb,
4474	double			 yt,
4475	double			 r,
4476	dk4_bb_t		*bbptr,
4477	int				*backptr,
4478	dk4_er_t		*erp
4479)
4480{
4481	int		 back = 0;
4482	$? "+ dk4gra_rectangle"
4483#if	DK4_USE_ASSERT
4484	assert(NULL != gra);
4485#endif
4486	if (NULL == gra) {
4487		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4488		goto finished;
4489	}
4490	if (NULL != bbptr) {
4491		dk4bb_add_x(bbptr, xl); dk4bb_add_x(bbptr, xr);
4492		dk4bb_add_y(bbptr, yb); dk4bb_add_y(bbptr, yt);
4493	}
4494	if (NULL == gra->curpg) {
4495		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4496		goto finished;
4497	}
4498	back = 1;
4499	dk4gra_i_rectangle(gra, xl, xr, yb, yt, r, &back, erp);
4500
4501	finished:
4502	$? "- dk4gra_rectangle %d", back
4503	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4504}
4505
4506
4507
4508void
4509dk4gra_arc(
4510	dk4_gra_t		*gra,
4511	double			 xc,
4512	double			 yc,
4513	double			 ra,
4514	double			 start,
4515	double			 end,
4516	int				 cl,
4517	dk4_bb_t		*bbptr,
4518	int				*backptr,
4519	dk4_er_t		*erp
4520)
4521{
4522	int		 back = 0;
4523	$? "+ dk4gra_arc"
4524#if	DK4_USE_ASSERT
4525	assert(NULL != gra);
4526#endif
4527	if ((NULL == gra) || (0.0 >= ra)) {
4528		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4529		goto finished;
4530	}
4531	if (NULL != bbptr) {
4532		dk4bb_add_x(bbptr, xc + ra * cos((M_PI * start)/ 180.0));
4533		dk4bb_add_y(bbptr, yc + ra * sin((M_PI * start)/ 180.0));
4534		dk4bb_add_x(bbptr, xc + ra * cos((M_PI *   end)/ 180.0));
4535		dk4bb_add_y(bbptr, yc + ra * sin((M_PI *   end)/ 180.0));
4536	}
4537	if (NULL == gra->curpg) {
4538		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4539		goto finished;
4540	}
4541	back = 1;
4542	dk4gra_i_arc(gra, xc, yc, ra, start, end, cl, &back, erp);
4543	finished:
4544	$? "- dk4gra_arc %d", back
4545	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4546}
4547
4548
4549
4550void
4551dk4gra_ellipse(
4552	dk4_gra_t		*gra,
4553	double			 xc,
4554	double			 yc,
4555	double			 rx,
4556	double			 ry,
4557	double			 rot,
4558	dk4_bb_t		*bbptr,
4559	int				*backptr,
4560	dk4_er_t		*erp
4561)
4562{
4563	int		 		back = 0;
4564	$? "+ dk4gra_ellipse"
4565#if	DK4_USE_ASSERT
4566	assert(NULL != gra);
4567#endif
4568	rot *= M_PI;
4569	rot /= 180.0;
4570	if ((NULL == gra) || (0.0 >= rx) || (0.0 >= ry)) {
4571		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4572		goto finished;
4573	}
4574	if (NULL == gra->curpg) {
4575		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4576		goto finished;
4577	}
4578	back = 1;
4579	dk4gra_i_ellipse(gra, xc, yc, rx, ry, rot, bbptr, &back, erp);
4580
4581	finished:
4582	$? "- dk4gra_ellipse %d", back
4583	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4584}
4585
4586
4587
4588void
4589dk4gra_pattern(
4590	dk4_gra_t			*gra,
4591	double				 xl,
4592	double				 xr,
4593	double				 yb,
4594	double				 yt,
4595	dk4_gra_pattern_t	 pn,
4596	int					*backptr,
4597	dk4_er_t			*erp
4598)
4599{
4600	double	 		val[16];	/* Values passed to EPS pattern functions */
4601	double	 		y01;		/* Temporary value */
4602	double	 		y02;		/* Temporary value */
4603	dk4_gra_lc_t	lc;			/* Line cap used while drawing the pattern */
4604	dk4_gra_lj_t	lj;			/* Line join used while drawing the pattern */
4605	dk4_gra_ls_t	ls;			/* Line style used while drawing the pattern */
4606	int		 		back = 0;
4607	$? "+ dk4gra_pattern"
4608#if	DK4_USE_ASSERT
4609	assert(NULL != gra);
4610#endif
4611	if (NULL == gra) {
4612		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4613		goto finished;
4614	}
4615	if (NULL == gra->curpg) {
4616		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4617		goto finished;
4618	}
4619	/*	Extend pattern area for line width
4620	*/
4621#if	VERSION_BEFORE_20181212
4622	xl -= 0.9; xr += 0.9; yb -= 0.9; yt += 0.9;
4623#else
4624	xl -= gra->patlw; xr += gra->patlw; yb -= gra->patlw; yt += gra->patlw;
4625#endif
4626	/*
4627		Calculate arguments for EPS pattern functions
4628	*/
4629	val[0] = xl;
4630	val[1] = xr;
4631	val[2] = yb;
4632	val[3] = yt;
4633	val[4] = 3.6;
4634	switch (pn) {
4635		case DK4_GRA_PATTERN_30_DEGREE_RIGHT : {
4636			/* ys = yb - (xe - xs) / sqrt(3) */
4637			val[2] -= ((val[1] - val[0]) / sqrt(3.0));
4638			val[4] = 7.2 / sqrt(3.0);
4639			y01 = val[2] - val[0] / sqrt(3.0);
4640			y02 = y01 / val[4];
4641			y02 = floor(y02);
4642			y02 = y02 * val[4];
4643			val[2] -= (y01 - y02);
4644		} break;
4645		case DK4_GRA_PATTERN_30_DEGREE_SIEVE : {
4646			/* ys = yb - (xe - xs) / sqrt(3) */
4647			val[2] -= ((val[1] - val[0]) / sqrt(3.0));
4648			val[4] = 7.2 / sqrt(3.0);
4649			y01 = val[2] + val[1] / sqrt(3.0);
4650			y02 = y01 / val[4];
4651			y02 = floor(y02);
4652			y02 = y02 * val[4];
4653			val[2] -= (y01 - y02);
4654			y01 = val[0] - val[2] * sqrt(3.0);
4655			y02 = y01 / 7.2;
4656			y02 = floor(y02);
4657			y02 = y02 * 7.2;
4658			val[0] -= (y01 - y02);
4659			val[2] -= val[4];
4660		} break;
4661		case DK4_GRA_PATTERN_45_DEGREE_LEFT : {
4662			val[2] -= (val[1] - val[0]);
4663			val[4] = 3.6 * M_SQRT2;
4664			y01 = val[2] + val[1];
4665			y02 = y01 / val[4];
4666			y02 = floor(y02);
4667			y02 *= val[4];
4668			val[2] -= (y01 - y02);
4669		} break;
4670		case DK4_GRA_PATTERN_45_DEGREE_RIGHT : {
4671			val[2] -= (val[1] - val[0]);
4672			val[4] = 3.6 * M_SQRT2;
4673			y01 = val[2] - val[0];
4674			y02 = y01 / val[4];
4675			y02 = floor(y02);
4676			y02 *= val[4];
4677			val[2] -= (y01 - y02);
4678		} break;
4679		case DK4_GRA_PATTERN_45_DEGREE_SIEVE : {
4680			val[2] -= (val[1] - val[0]);
4681			val[4] = 3.6 * M_SQRT2;
4682			y01 = val[2] + val[1];
4683			y02 = y01 / val[4];
4684			y02 = floor(y02);
4685			y02 *= val[4];
4686			val[2] -= (y01 - y02);
4687			y01 = val[0] - val[2];
4688			y02 = y01 / val[4];
4689			y02 = floor(y02);
4690			y02 *= val[4];
4691			val[0] -= (y01 - y02);
4692			val[2] -= val[4];
4693		} break;
4694		case DK4_GRA_PATTERN_HORIZONTAL_BRICKS : {
4695			y01 = val[2] / 7.2;
4696			y01 = floor(y01);
4697			val[2] = y01 * 7.2;
4698			y01 = val[0] / 14.4;
4699			y01 = floor(y01);
4700			val[0] = y01 * 14.4;
4701			val[4] = 7.2;
4702		} break;
4703		case DK4_GRA_PATTERN_VERTICAL_BRICKS : {
4704			y01 = val[2] / 14.4;
4705			y01 = floor(y01);
4706			val[2] = y01 * 14.4;
4707			y01 = val[0] / 7.2;
4708			y01 = floor(y01);
4709			val[0] = y01 * 7.2;
4710			val[4] = 7.2;
4711		} break;
4712		case DK4_GRA_PATTERN_HORIZONTAL_LINES : {
4713			y01 = val[2] / 3.6;
4714			y01 = floor(y01);
4715			val[2] = y01 * 3.6;
4716		} break;
4717		case DK4_GRA_PATTERN_VERTICAL_LINES : {
4718			y01 = val[0] / 3.6;
4719			y01 = floor(y01);
4720			val[0] = y01 * 3.6;
4721		} break;
4722		case DK4_GRA_PATTERN_HORIZONTAL_VERTICAL_SIEVE : {
4723			y01 = val[2] / 3.6;
4724			y01 = floor(y01);
4725			val[2] = y01 * 3.6;
4726			y01 = val[0] / 3.6;
4727			y01 = floor(y01);
4728			val[0] = y01 * 3.6;
4729		} break;
4730		case DK4_GRA_PATTERN_HORIZONTAL_SHINGLES_LEFT : {
4731			y01 = val[2] / 28.8;
4732			y01 = floor(y01);
4733			val[2] = y01 * 28.8;
4734			y01 = val[0] / 14.4;
4735			y01 = floor(y01);
4736			val[0] = y01 * 14.4;
4737			val[4] = 7.2;
4738		} break;
4739		case DK4_GRA_PATTERN_HORIZONTAL_SHINGLES_RIGHT : {
4740			y01 = val[2] / 28.8;
4741			y01 = floor(y01);
4742			val[2] = y01 * 28.8;
4743			y01 = val[0] / 14.4;
4744			y01 = floor(y01);
4745			val[0] = y01 * 14.4;
4746			val[4] = 7.2;
4747		} break;
4748		case DK4_GRA_PATTERN_VERTICAL_SHINGLES_1 : {
4749			y01 = val[2] / 14.4;
4750			y01 = floor(y01);
4751			val[2] = y01 * 14.4;
4752			y01 = val[0] / 28.8;
4753			y01 = floor(y01);
4754			val[0] = y01 * 28.8;
4755			val[4] = 7.2;
4756		} break;
4757		case DK4_GRA_PATTERN_VERTICAL_SHINGLES_2 : {
4758			y01 = val[2] / 14.4;
4759			y01 = floor(y01);
4760			val[2] = y01 * 14.4;
4761			y01 = val[0] / 28.8;
4762			y01 = floor(y01);
4763			val[0] = y01 * 28.8;
4764			val[4] = 7.2;
4765		} break;
4766		case DK4_GRA_PATTERN_LARGE_FISH_SCALES : {
4767			/* xs xe ys ye dx dy r a1 a2 */
4768			val[4] = 14.54;
4769			val[5] = 3.7;
4770			val[6] = 9.0;
4771			val[7] = 216.1;
4772			val[8] = 323.9;
4773			y01 = val[0] / val[4];
4774			y01 = floor(y01);
4775			val[0] = y01 * val[4];
4776			y01 = val[2] / (2 * val[5]);
4777			y01 = floor(y01);
4778			val[2] = 2.0 * y01 * val[5];
4779		} break;
4780		case DK4_GRA_PATTERN_SMALL_FISH_SCALES : {
4781			/* xs xe ys ye dx dy r a1 a2 */
4782			val[4] = 7.2;
4783			val[5] = 3.6;
4784			val[6] = 3.6;
4785			val[7] = 180.0;
4786			val[8] = 360.0;
4787			y01 = val[0] / val[4];
4788			y01 = floor(y01);
4789			val[0] = y01 * val[4];
4790			y01 = val[2] / (2 * val[5]);
4791			y01 = floor(y01);
4792			val[2] = 2.0 * y01 * val[5];
4793		} break;
4794		case DK4_GRA_PATTERN_CIRCLES : {
4795			val[4] = 7.2;
4796			y01 = val[0] / 14.4;
4797			y01 = floor(y01);
4798			val[0] = 14.4 * y01;
4799			y01 = val[2] / 14.4;
4800			y01 = floor(y01);
4801			val[2] = 14.4 * y01;
4802		} break;
4803		case DK4_GRA_PATTERN_HEXAGONS : {
4804			/* xs xe ys ye dx dy */
4805			val[4] = 21.6;
4806			val[5] = 12.47;
4807			y01 = val[0] / 21.6;
4808			y01 = floor(y01);
4809			val[0] = y01 * 21.6;
4810			y01 = val[2] / 12.47;
4811			y01 = floor(y01);
4812			val[2] = y01 * 12.47;
4813		} break;
4814		case DK4_GRA_PATTERN_OCTAGONS : {
4815			/* xs xe ys ye dx co */
4816			/*	2020-08-10	Bugfix
4817				Pattern size too small, increased now.
4818			*/
4819			val[4] = 14.4;	/* previously 7.2; */
4820			val[5] = 4.22;	/* previously 2.11; */
4821			y01 = val[0] / val[4];
4822			y01 = floor(y01);
4823			val[0] = y01 * val[4];
4824			y01 = val[2] / val[4];
4825			y01 = floor(y01);
4826			val[2] = y01 * val[4];
4827		} break;
4828		case DK4_GRA_PATTERN_HORIZONTAL_TIRES : {
4829			val[4] = 7.2;
4830			y01 = val[0] / val[4];
4831			y01 = floor(y01);
4832			val[0] = y01 * val[4];
4833			y01 = val[2] / val[4];
4834			y01 = floor(y01);
4835			val[2] = y01 * val[4];
4836		} break;
4837		case DK4_GRA_PATTERN_VERTICAL_TIRES : {
4838			val[4] = 7.2;
4839			y01 = val[0] / val[4];
4840			y01 = floor(y01);
4841			val[0] = y01 * val[4];
4842			y01 = val[2] / val[4];
4843			y01 = floor(y01);
4844			val[2] = y01 * val[4];
4845		} break;
4846		/* DK4_GRA_PATTERN_30_DEGREE_LEFT */
4847		default : {
4848			/* ys = yb - (xe - xs) / sqrt(3) */
4849			val[2] -= ((val[1] - val[0]) / sqrt(3.0));
4850			val[4] = 7.2 / sqrt(3.0);
4851			y01 = val[2] + val[1] / sqrt(3.0);
4852			y02 = y01 / val[4];
4853			y02 = floor(y02);
4854			y02 = y02 * val[4];
4855			val[2] -= (y01 - y02);
4856		} break;
4857	}
4858
4859	back = 1;
4860
4861	/*	Save attributes and graphics state
4862	*/
4863	dk4gra_i_save_attributes(gra);
4864	dk4gra_i_gsave(gra, &back, erp);
4865
4866	/*	Set attributes for stroking
4867	*/
4868	dk4gra_set_line_width(gra, gra->patlw, &back, erp);
4869	lc = DK4_GRA_LC_ROUNDED;
4870	dk4gra_set_line_cap(gra, lc, &back, erp);
4871	lj = DK4_GRA_LJ_MITERED;
4872	switch (pn) {
4873		case DK4_GRA_PATTERN_LARGE_FISH_SCALES:
4874		case DK4_GRA_PATTERN_SMALL_FISH_SCALES: {
4875			lj = DK4_GRA_LJ_ROUNDED;
4876		} break;
4877		default : {
4878			/* Intentionally empty to avoid compiler warnings. */
4879		} break;
4880	}
4881	dk4gra_set_line_join(gra, lj, 10.0, &back, erp);
4882	ls = DK4_GRA_LS_SOLID;
4883	dk4gra_set_line_style(gra, ls, 3.6, &back, erp);
4884	dk4gra_prepare_stroke(gra, &back, erp);
4885
4886	/*
4887		Driver specific pattern functions
4888	*/
4889	switch (gra->dr) {
4890		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
4891			if (0 == dk4gra_eps_pattern(gra, pn, val, erp)) {
4892				back = 0;
4893			}
4894		} break;
4895		default : {
4896			dk4gra_i_pattern(gra, xl, xr, yb, yt, pn, val, &back, erp);
4897		} break;
4898	}
4899
4900	/*	Restore graphics state and attributes
4901	*/
4902	dk4gra_i_grestore(gra, 0, &back, erp);
4903	dk4gra_i_restore_attributes(gra);
4904
4905
4906	finished:
4907	$? "- dk4gra_pattern %d", back
4908	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
4909}
4910
4911
4912
4913void
4914dk4gra_bif_cotra_image(
4915	dk4_gra_t			*gra,
4916	double				*cotra,
4917	dk4_bif_t			*bif,
4918	const dkChar		*fn,
4919	size_t				 fno,
4920	int					 ifl,
4921	int					*backptr,
4922	dk4_er_t			*erp
4923)
4924{
4925
4926	int					 cs;			/* Color space */
4927	int					 back = 0;
4928	dk4_px_bit_depth_t	 bpc;			/* Number of bits per component */
4929
4930	$? "+ dk4gra_bif_cotra_image \"%!ds\"", TR_STR(fn)
4931#if	DK4_USE_ASSERT
4932	assert(NULL != gra);
4933	assert(NULL != bif);
4934	assert(NULL != cotra);
4935#endif
4936	/*
4937		Check arguments
4938	*/
4939	if ((NULL == gra) || (NULL == cotra) || (NULL == bif)) {
4940		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4941		goto finished;
4942	}
4943	/*	When enforcing grayscaled output, do not write colored image
4944	*/
4945	if (0 != (DK4_GRA_DOC_FLAG_FORCE_GRAY & (gra->docfl))) {
4946		ifl &= (~(DK4_GRA_IMG_FLAG_COLOR));
4947	}
4948	/*	Direct re-use of DCT encoded data requires a file name
4949	*/
4950	if (NULL == fn) {
4951		ifl &= (~(DK4_GRA_IMG_FLAG_DCT));
4952	}
4953	/*	Direct re-use of DCT encoded data requires given bits per component
4954	*/
4955	bpc = dk4bif_get_original_bit_depth(bif);
4956	if (8 != bpc) {
4957		if (4 != bpc) {
4958			if (2 != bpc) {
4959				if (1 != bpc) {
4960					ifl &= (~(DK4_GRA_IMG_FLAG_DCT));
4961				}
4962			}
4963		}
4964	}
4965	/*	Direct re-use of DCT encoded data restricts color spaces
4966	*/
4967	cs = dk4bif_get_color_space(bif);
4968	if (DK4_CS_GRAY != cs) {
4969		if (DK4_CS_RGB != cs) {
4970			if (DK4_CS_CMYK != cs) {
4971				ifl &= (~(DK4_GRA_IMG_FLAG_DCT));
4972			}
4973		}
4974	}
4975	/*	Direct re-use of DCT encoded data impossible for colored
4976		images when enforcing grayscaled output
4977	*/
4978	if ((DK4_CS_GRAY != cs) && (0 == (DK4_GRA_IMG_FLAG_COLOR & ifl))) {
4979		ifl &= (~(DK4_GRA_IMG_FLAG_DCT));
4980	}
4981
4982	switch (gra->dr) {
4983		case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
4984			back = dk4gra_eps_bif_fig_image(
4985				gra, cotra, bif, fn,
4986				ifl, erp
4987			);
4988		} break;
4989		case DK4_GRA_DRIVER_PGF : {
4990			if (NULL != fn) {
4991				back = dk4gra_pgf_bif_fig_image(
4992					gra, cotra, bif, fn,
4993					ifl, erp
4994				);
4995			}
4996			else {
4997				dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
4998			}
4999		} break;
5000		default : {	/* PDF */
5001			back = dk4gra_pdf_bif_fig_image(
5002				gra, cotra, bif, fn, fno,
5003				ifl, erp
5004			);
5005		} break;
5006	}
5007
5008	finished:
5009	$? "- dk4gra_bif_cotra_image %d", back
5010	if ((0 == back) && (NULL != backptr)) { *backptr = 0; }
5011}
5012
5013
5014void
5015dk4gra_bif_fig_image(
5016	dk4_gra_t			*gra,
5017	double				 xl,
5018	double				 xr,
5019	double				 yb,
5020	double				 yt,
5021	dk4_bif_t			*bif,
5022	const dkChar		*fn,
5023	size_t				 fno,
5024	int					 pos,
5025	int					 ifl,
5026	dk4_bb_t			*bbptr,
5027	int					*backptr,
5028	dk4_er_t			*erp
5029)
5030{
5031	double	 val[8];			/* Values passed to low level functions */
5032	double	 w;					/* Image width */
5033	double	 h;					/* Image height */
5034	double	 xres;				/* X resolution */
5035	double	 yres;				/* Y resolution */
5036	int		 res;				/* Operation result */
5037	int		 cs;				/* Color space */
5038	int		 back	= 0;
5039	dk4_px_bit_depth_t	 bpc;
5040	$? "+ dk4gra_bif_fig_image"
5041#if	DK4_USE_ASSERT
5042	assert(NULL != gra);
5043	assert(NULL != bif);
5044#endif
5045	$? ". xl     = %lg", xl
5046	$? ". xr     = %lg", xr
5047	$? ". yb     = %lg", yb
5048	$? ". yt     = %lg", yt
5049	$? ". bif    = %d", TR_IPTR(bif)
5050	$? ". fn     = \"%!ds\"", TR_STR(fn)
5051	$? ". fno    = %u", (unsigned)fno
5052	$? ". ipol   = %d", (DK4_GRA_IMG_FLAG_INTERPOLATION & ifl)
5053	$? ". ignres = %d", (DK4_GRA_IMG_FLAG_IGNORE_RESOLUTION & ifl)
5054	$? ". ignar  = %d", (DK4_GRA_IMG_FLAG_IGNORE_ASPECT_RATIO & ifl)
5055	$? ". pos    = %d", pos
5056	$? ". oiop   = %d", (DK4_GRA_IMG_FLAG_ONLY_PAGE_CONTENTS & ifl)
5057	$? ". alzw   = %d", (DK4_GRA_IMG_FLAG_LZW & ifl)
5058	$? ". ajpg   = %d", (DK4_GRA_IMG_FLAG_DCT & ifl)
5059	$? ". ijpg   = %d", (DK4_GRA_IMG_FLAG_DCT_INTERPOLATION & ifl)
5060	$? ". acol   = %d", (DK4_GRA_IMG_FLAG_COLOR & ifl)
5061	$? ". anb    = %d", (DK4_GRA_IMG_FLAG_ANALYZE_BPC & ifl)
5062	$? ". anc    = %d", (DK4_GRA_IMG_FLAG_ANALYZE_COLOR & ifl)
5063	$? ". ana    = %d", (DK4_GRA_IMG_FLAG_ANALYZE_ALPHA & ifl)
5064	$? ". fbgf   = %d", (DK4_GRA_IMG_FLAG_FILL_BACKGROUND & ifl)
5065
5066	/*	2018-03-19
5067		Removed (NULL == fn)
5068	*/
5069	if ((NULL == gra) || (NULL == bif)) {
5070		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
5071		goto finished;
5072	}
5073	if ((xr <= xl) || (yt <= yb)) {
5074		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
5075		goto finished;
5076	}
5077	if (0 != (DK4_GRA_DOC_FLAG_FORCE_GRAY & (gra->docfl))) {
5078		ifl &= (~(DK4_GRA_IMG_FLAG_COLOR));
5079	}
5080	if (NULL != bbptr) {
5081		dk4bb_add_x(bbptr, xl); dk4bb_add_x(bbptr, xr);
5082		dk4bb_add_y(bbptr, yb); dk4bb_add_y(bbptr, yt);
5083	}
5084	/*	Select frame
5085	*/
5086	if (0 == dk4bif_set_current_frame(bif, fno)) {
5087		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
5088		goto finished;
5089	}
5090	/*	Retrieve image dimensions
5091	*/
5092	w = (double)dk4bif_get_width(bif);
5093	h = (double)dk4bif_get_height(bif);
5094	if (0 == (DK4_GRA_IMG_FLAG_IGNORE_RESOLUTION & ifl)) {
5095		xres = dk4bif_get_xres(bif);
5096		yres = dk4bif_get_yres(bif);
5097		if ((isgreater(xres, 0.0)) && (isgreater(yres, 0.0))) {
5098			w = (72.0 * w) / xres;
5099			h = (72.0 * h) / yres;
5100#if	DK4_HAVE_ISFINITE
5101			if ((!(isfinite(w))) || (!(isfinite(h)))) {
5102				w = (double)dk4bif_get_width(bif);
5103				h = (double)dk4bif_get_height(bif);
5104			}
5105#else
5106#if	DK4_HAVE__FINITE
5107			if ((!(_finite(w))) || (!(_finite(h)))) {
5108				w = (double)dk4bif_get_width(bif);
5109				h = (double)dk4bif_get_height(bif);
5110			}
5111#endif
5112#endif
5113		}
5114	}
5115	/*
5116		Calculate coordinate system transformations
5117	*/
5118	res = dk4gratool_calculate_transformations(
5119		val, xl, xr, yb, yt, w, h,
5120		((0 == (DK4_GRA_IMG_FLAG_IGNORE_ASPECT_RATIO & ifl)) ? (1) : (0)),
5121		pos, erp
5122	);
5123	if (0 == res) {
5124		goto finished;
5125	}
5126	/*	Direct re-use of DCT encoded data from JPEG requires file name
5127	*/
5128	if (NULL == fn) {
5129		ifl &= (~(DK4_GRA_IMG_FLAG_DCT));
5130	}
5131	/*	DCT encoding restricts usable number of bits per component
5132	*/
5133	bpc = dk4bif_get_original_bit_depth(bif);
5134	if (8 != bpc) {
5135		if (4 != bpc) {
5136			if (2 != bpc) {
5137				if (1 != bpc) {
5138					ifl &= (~(DK4_GRA_IMG_FLAG_DCT));
5139				}
5140			}
5141		}
5142	}
5143	/*	DCT encoding restricts color spaces
5144	*/
5145	cs = dk4bif_get_color_space(bif);
5146	if (DK4_CS_GRAY != cs) {
5147		if (DK4_CS_RGB != cs) {
5148			if (DK4_CS_CMYK != cs) {
5149				ifl &= (~(DK4_GRA_IMG_FLAG_DCT));
5150			}
5151		}
5152	}
5153	/*	Direct re-use of DCT encoded data from colored image
5154		not possible when enforcing grayscaled output
5155	*/
5156	if ((DK4_CS_GRAY != cs) && (0 == (DK4_GRA_IMG_FLAG_COLOR & ifl))) {
5157		ifl &= (~(DK4_GRA_IMG_FLAG_DCT));
5158	}
5159	/*	Can not specify frame number in PGF output, only frame 0
5160		can be used
5161	*/
5162	if ((DK4_GRA_DRIVER_PGF == gra->dr) && (0 != fno)) {
5163		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
5164		goto finished;
5165	}
5166	/*	Call function to produce output with given coordinates transformation
5167	*/
5168	back = 1;
5169	dk4gra_bif_cotra_image(
5170		gra, val, bif, fn, fno,
5171		ifl, &back, erp
5172	);
5173
5174	finished:
5175	$? "- dk4gra_bif_fig_image %d", back
5176	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
5177}
5178
5179
5180
5181void
5182dk4gra_bif_image(
5183	dk4_gra_t			*gra,
5184	double				 xl,
5185	double				 xr,
5186	double				 yb,
5187	double				 yt,
5188	dk4_bif_t			*bif,
5189	const dkChar		*fn,
5190	size_t				 fno,
5191	int					 ifl,
5192	dk4_bb_t			*bbptr,
5193	int					*backptr,
5194	dk4_er_t			*erp
5195)
5196{
5197	double	 xres = 1.0;		/* X resolution */
5198	double	 yres = 1.0;		/* Y resolution */
5199	double	 w;					/* Width */
5200	double	 h;					/* Height */
5201	double	 xdiff;				/* Available X space */
5202	double	 ydiff;				/* Available Y space */
5203	int		 pos	= 0;		/* Image position */
5204	int		 back	= 0;
5205	$? "+ dk4gra_bif_image"
5206#if	DK4_USE_ASSERT
5207	assert(NULL != gra);
5208	assert(NULL != bif);
5209#endif
5210	$? ". xl     = %lg", xl
5211	$? ". xr     = %lg", xr
5212	$? ". yb     = %lg", yb
5213	$? ". yt     = %lg", yt
5214	$? ". bif    = %d", TR_IPTR(bif)
5215	$? ". fn     = \"%!ds\"", TR_STR(fn)
5216	$? ". fno    = %u", (unsigned)fno
5217	$? ". ipol   = %d", (DK4_GRA_IMG_FLAG_INTERPOLATION & ifl)
5218	$? ". ignres = %d", (DK4_GRA_IMG_FLAG_IGNORE_RESOLUTION & ifl)
5219	$? ". ignar  = %d", (DK4_GRA_IMG_FLAG_IGNORE_ASPECT_RATIO & ifl)
5220	$? ". arot   = %d", (DK4_GRA_IMG_FLAG_ALLOW_ROTATION & ifl)
5221	$? ". oiop   = %d", (DK4_GRA_IMG_FLAG_ONLY_PAGE_CONTENTS & ifl)
5222	$? ". alzw   = %d", (DK4_GRA_IMG_FLAG_LZW & ifl)
5223	$? ". ajpg   = %d", (DK4_GRA_IMG_FLAG_DCT & ifl)
5224	$? ". ijpg   = %d", (DK4_GRA_IMG_FLAG_DCT_INTERPOLATION & ifl)
5225	$? ". acol   = %d", (DK4_GRA_IMG_FLAG_COLOR & ifl)
5226	$? ". anb    = %d", (DK4_GRA_IMG_FLAG_ANALYZE_BPC & ifl)
5227	$? ". anc    = %d", (DK4_GRA_IMG_FLAG_ANALYZE_COLOR & ifl)
5228	$? ". ana    = %d", (DK4_GRA_IMG_FLAG_ANALYZE_ALPHA & ifl)
5229	$? ". fbgf   = %d", (DK4_GRA_IMG_FLAG_FILL_BACKGROUND & ifl)
5230	/*	2018-03-19
5231		Removed (NULL == fn)
5232	*/
5233	if ((NULL == gra) || (NULL == bif)) {
5234		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
5235		goto finished;
5236	}	$? ". gra, bif, fn ok"
5237	if ((xr <= xl) || (yt <= yb)) {
5238		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
5239		goto finished;
5240	}	$? ". xl, yt ok"
5241	if (NULL != bbptr) {
5242		dk4bb_add_x(bbptr, xl); dk4bb_add_x(bbptr, xr);
5243		dk4bb_add_y(bbptr, yb); dk4bb_add_y(bbptr, yt);
5244	}
5245	if (0 != (DK4_GRA_DOC_FLAG_FORCE_GRAY & (gra->docfl))) {
5246		ifl &= (~(DK4_GRA_IMG_FLAG_COLOR));
5247	}
5248	if (0 == (DK4_GRA_IMG_FLAG_IGNORE_ASPECT_RATIO & ifl)) {
5249		if (0 != (DK4_GRA_IMG_FLAG_ALLOW_ROTATION & ifl)) {
5250			if (0 != dk4bif_set_current_frame(bif, fno)) {
5251				xdiff = fabs(xr - xl);
5252				ydiff = fabs(yt - yb);
5253				w = (double)dk4bif_get_width(bif);
5254				h = (double)dk4bif_get_height(bif);
5255				if (0 == (DK4_GRA_IMG_FLAG_IGNORE_RESOLUTION & ifl)) {
5256					xres = dk4bif_get_xres(bif);
5257					yres = dk4bif_get_yres(bif);
5258					if ((isgreater(xres, 0.0)) && (isgreater(yres, 0.0))) {
5259						w = (72.0 * w) / xres;
5260						h = (72.0 * h) / yres;
5261					}
5262				}
5263#if	DK4_HAVE_ISFINITE
5264				if ((isfinite(w)) && (isfinite(h)))
5265#else
5266#if	DK4_HAVE__FINITE
5267				if ((_finite(w)) && (_finite(h)))
5268#else
5269
5270#endif
5271#endif
5272				{
5273					if ((isgreater(w, h)) && (isless(xdiff, ydiff))) {
5274						pos = 1;
5275					}
5276					else {
5277						if ((isless(w, h)) && (isgreater(xdiff, ydiff))) {
5278							pos = 1;
5279						}
5280					}
5281				}
5282#if (DK4_HAVE_ISFINITE) || (DK4_HAVE__FINITE)
5283				else {
5284					/* ERROR: Width and height calculation failed */
5285					dk4error_set_simple_error_code(erp,DK4_E_MATH_OVERFLOW);
5286				}
5287#endif
5288			}
5289			else {
5290				/* ERROR: Frame number does not exist! */
5291				dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
5292			}
5293			back = 1;
5294			dk4gra_bif_fig_image(
5295				gra, xl, xr, yb, yt, bif, fn, fno,
5296				pos, ifl, bbptr, &back, erp
5297			);
5298		}
5299		else {
5300			back = 1;
5301			dk4gra_bif_fig_image(
5302				gra, xl, xr, yb, yt, bif, fn, fno,
5303				pos, ifl, bbptr, &back, erp
5304			);
5305		}
5306	}
5307	else {
5308		back = 1;
5309		dk4gra_bif_fig_image(
5310			gra, xl, xr, yb, yt, bif, fn, fno,
5311			pos, ifl, bbptr, &back, erp
5312		);
5313	}
5314	finished:
5315	$? "- dk4gra_bif_image %d", back
5316	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
5317}
5318
5319
5320
5321void
5322dk4gra_fig_image(
5323	dk4_gra_t			*gra,
5324	double				 xl,
5325	double				 xr,
5326	double				 yb,
5327	double				 yt,
5328	const dkChar		*fn,
5329	size_t				 fno,
5330	dk4_cs_conv_ctx_t	*ctx,
5331	int					 pos,
5332	int					 ifl,
5333	dk4_bb_t			*bbptr,
5334	int					*backptr,
5335	dk4_er_t			*erp
5336)
5337{
5338	dk4_bif_t	*bifptr	= NULL;		/* Bitmap image file */
5339	int			 ho		= 0;		/* Flag: Read header only */
5340	int			 back	= 0;
5341	$? "+ dk4gra_fig_image"
5342#if	DK4_USE_ASSERT
5343	assert(NULL != gra);
5344	assert(NULL != fn);
5345#endif
5346	$? ". xl     = %lg", xl
5347	$? ". xr     = %lg", xr
5348	$? ". yb     = %lg", yb
5349	$? ". yt     = %lg", yt
5350	$? ". fn     = \"%!ds\"", TR_STR(fn)
5351	$? ". fno    = %u", (unsigned)fno
5352	$? ". ctx    = %i", TR_IPTR(ctx)
5353	$? ". ipol   = %d", (DK4_GRA_IMG_FLAG_INTERPOLATION & ifl)
5354	$? ". ignres = %d", (DK4_GRA_IMG_FLAG_IGNORE_RESOLUTION & ifl)
5355	$? ". ignar  = %d", (DK4_GRA_IMG_FLAG_IGNORE_ASPECT_RATIO & ifl)
5356	$? ". pos    = %d", pos
5357	$? ". oiop   = %d", (DK4_GRA_IMG_FLAG_ONLY_PAGE_CONTENTS & ifl)
5358	$? ". alzw   = %d", (DK4_GRA_IMG_FLAG_LZW & ifl)
5359	$? ". ajpg   = %d", (DK4_GRA_IMG_FLAG_DCT & ifl)
5360	$? ". ijpg   = %d", (DK4_GRA_IMG_FLAG_DCT_INTERPOLATION & ifl)
5361	$? ". acol   = %d", (DK4_GRA_IMG_FLAG_COLOR & ifl)
5362	$? ". anb    = %d", (DK4_GRA_IMG_FLAG_ANALYZE_BPC & ifl)
5363	$? ". anc    = %d", (DK4_GRA_IMG_FLAG_ANALYZE_COLOR & ifl)
5364	$? ". ana    = %d", (DK4_GRA_IMG_FLAG_ANALYZE_ALPHA & ifl)
5365	$? ". fbgf   = %d", (DK4_GRA_IMG_FLAG_FILL_BACKGROUND & ifl)
5366	if ((NULL == gra) || (NULL == fn)) {
5367		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
5368		goto finished;
5369	}
5370	if ((xr <= xl) || (yt <= yb)) {
5371		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
5372		goto finished;
5373	}
5374	if (NULL == ctx) {
5375		ctx = &(gra->cscctx);
5376	}
5377	if (NULL != bbptr) {
5378		dk4bb_add_x(bbptr, xl); dk4bb_add_x(bbptr, xr);
5379		dk4bb_add_y(bbptr, yb); dk4bb_add_y(bbptr, yt);
5380	}
5381	if (DK4_GRA_DRIVER_PGF == gra->dr) {
5382		ho = 1;
5383	}
5384	if (
5385		(0 != (DK4_GRA_IMG_FLAG_DCT & ifl))
5386		&& (DK4_BIF_TYPE_JPEG == dk4bif_type_for_suffix(fn))
5387	) {
5388		if (0 != (DK4_GRA_IMG_FLAG_COLOR & ifl)) {
5389			ho = 1;
5390		}
5391	}
5392	bifptr = dk4bif_open(fn, ho, ctx, erp);
5393	if (NULL == bifptr) {
5394		goto finished;
5395	}
5396	back = 1;
5397	if (0 != (DK4_GRA_DOC_FLAG_FORCE_GRAY & (gra->docfl))) {
5398		ifl &= (~(DK4_GRA_IMG_FLAG_COLOR));
5399	}
5400	dk4gra_bif_fig_image(
5401		gra, xl, xr, yb, yt, bifptr, fn, fno,
5402		pos, ifl, bbptr, &back, erp
5403	);
5404
5405	finished:
5406	if (NULL != bifptr) {
5407		dk4bif_close(bifptr);
5408	}
5409	$? "- dk4gra_fig_image %d", back
5410	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
5411}
5412
5413
5414
5415void
5416dk4gra_image(
5417	dk4_gra_t			*gra,
5418	double				 xl,
5419	double				 xr,
5420	double				 yb,
5421	double				 yt,
5422	const dkChar		*fn,
5423	size_t				 fno,
5424	dk4_cs_conv_ctx_t	*ctx,
5425	int					 ifl,
5426	dk4_bb_t			*bbptr,
5427	int					*backptr,
5428	dk4_er_t			*erp
5429)
5430{
5431	dk4_bif_t	*bifptr	= NULL;		/* Bitmap image */
5432	int			 back	= 0;		/* Function result */
5433	int			 ho		= 0;		/* Flag: Read image header only */
5434	$? "+ dk4gra_image"
5435#if	DK4_USE_ASSERT
5436	assert(NULL != gra);
5437	assert(NULL != fn);
5438#endif
5439	$? ". xl     = %lg", xl
5440	$? ". xr     = %lg", xr
5441	$? ". yb     = %lg", yb
5442	$? ". yt     = %lg", yt
5443	$? ". fn     = \"%!ds\"", TR_STR(fn)
5444	$? ". fno    = %u", (unsigned)fno
5445	$? ". ctx    = %i", TR_IPTR(ctx)
5446	$? ". ipol   = %d", (DK4_GRA_IMG_FLAG_INTERPOLATION & ifl)
5447	$? ". ignres = %d", (DK4_GRA_IMG_FLAG_IGNORE_RESOLUTION & ifl)
5448	$? ". ignar  = %d", (DK4_GRA_IMG_FLAG_IGNORE_ASPECT_RATIO & ifl)
5449	$? ". arot   = %d", (DK4_GRA_IMG_FLAG_ALLOW_ROTATION & ifl)
5450	$? ". oiop   = %d", (DK4_GRA_IMG_FLAG_ONLY_PAGE_CONTENTS & ifl)
5451	$? ". alzw   = %d", (DK4_GRA_IMG_FLAG_LZW & ifl)
5452	$? ". ajpg   = %d", (DK4_GRA_IMG_FLAG_DCT & ifl)
5453	$? ". ijpg   = %d", (DK4_GRA_IMG_FLAG_DCT_INTERPOLATION & ifl)
5454	$? ". acol   = %d", (DK4_GRA_IMG_FLAG_COLOR & ifl)
5455	$? ". anb    = %d", (DK4_GRA_IMG_FLAG_ANALYZE_BPC & ifl)
5456	$? ". anc    = %d", (DK4_GRA_IMG_FLAG_ANALYZE_COLOR & ifl)
5457	$? ". ana    = %d", (DK4_GRA_IMG_FLAG_ANALYZE_ALPHA & ifl)
5458	$? ". fbgf   = %d",	(DK4_GRA_IMG_FLAG_FILL_BACKGROUND & ifl)
5459	/*
5460		Check argument
5461	*/
5462	if ((NULL == gra) || (NULL == fn)) {
5463		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
5464		goto finished;
5465	}	$? ". gra and fn ok"
5466	if ((xr <= xl) || (yt <= yb)) {
5467		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
5468		goto finished;
5469	}	$? ". xr and yb ok"
5470	if (NULL == ctx) {
5471		ctx = &(gra->cscctx);
5472	}
5473	if (NULL != bbptr) {
5474		dk4bb_add_x(bbptr, xl); dk4bb_add_x(bbptr, xr);
5475		dk4bb_add_y(bbptr, yb); dk4bb_add_y(bbptr, yt);
5476	}
5477	/*	Open bitmap file
5478	*/
5479	if (DK4_GRA_DRIVER_PGF == gra->dr) {
5480		ho = 1;
5481	}
5482	if (
5483		(0 != (DK4_GRA_IMG_FLAG_DCT & ifl))
5484		&& (DK4_BIF_TYPE_JPEG == dk4bif_type_for_suffix(fn))
5485	) {
5486		if (0 != (DK4_GRA_IMG_FLAG_COLOR & ifl)) {
5487			ho = 1;
5488		}
5489	}
5490	bifptr = dk4bif_open(fn, ho, ctx, erp);
5491	if (NULL == bifptr) {			$? "! failed to open bitmap file"
5492		goto finished;
5493	}	$? ". bitmap file opened"
5494	/*	Process  bitmap file
5495	*/
5496	back = 1;
5497	if (0 != (DK4_GRA_DOC_FLAG_FORCE_GRAY & (gra->docfl))) {
5498		ifl &= (~(DK4_GRA_IMG_FLAG_COLOR));
5499	}
5500	dk4gra_bif_image(
5501		gra, xl, xr, yb, yt, bifptr, fn, fno,
5502		ifl, bbptr, &back, erp
5503	);
5504
5505	/*	Clean up and exit
5506	*/
5507	finished:
5508	$? ". cleanup section"
5509	if (NULL != bifptr) {			$? ". close bitmap file"
5510		dk4bif_close(bifptr);
5511	}
5512	$? "- dk4gra_image %d", back
5513	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
5514}
5515
5516
5517
5518void
5519dk4gra_set_pattern_line_width(
5520	dk4_gra_t	*gra,
5521	double		 plw
5522)
5523{
5524#if	DK4_USE_ASSERT
5525	assert(NULL != gra);
5526#endif
5527	if (NULL != gra) {
5528		if (0.0 < plw) {
5529			gra->patlw = plw;
5530		}
5531	}
5532}
5533
5534
5535
5536/* vim: set ai sw=4 ts=4 : */
5537