1%%	options
2
3copyright owner	=	Dirk Krause
4copyright year	=	2017-xxxx
5SPDX-License-Identifier:	BSD-3-Clause
6
7%%	module
8
9#include "dk4conf.h"
10
11#if	DK4_HAVE_MATH_H
12#ifndef	MATH_H_INCLUDED
13#if	DK4_ON_WINDOWS
14#ifndef	_USE_MATH_DEFINES
15#define	_USE_MATH_DEFINES 1
16#endif
17#endif
18#include <math.h>
19#define	MATH_H_INCLUDED 1
20#endif
21#endif
22
23#ifndef	DK4MEM_H_INCLUDED
24#include <libdk4base/dk4mem.h>
25#endif
26
27#ifndef	DK4MEMBF_H_INCLUDED
28#include <libdk4c/dk4membf.h>
29#endif
30
31#ifndef	DK4MBSTRM_H_INCLUDED
32#include <libdk4c/dk4mbstrm.h>
33#endif
34
35#ifndef	DK4GRA_H_INCLUDED
36#include <libdk4gra/dk4gra.h>
37#endif
38
39#ifndef	GRA_H_INCLUDED
40#include <libdk4gra/gra.h>
41#endif
42
43#ifndef	DK4MAO8D_H_INCLUDED
44#include <libdk4maio8d/dk4mao8d.h>
45#endif
46
47#ifndef	DK4MAO8DNS_H_INCLUDED
48#include <libdk4c/dk4mao8dns.h>
49#endif
50
51#if DK4_HAVE_ASSERT_H
52#ifndef	ASSERT_H_INCLUDED
53#include <assert.h>
54#define	ASSERT_H_INCLUDED 1
55#endif
56#endif
57
58
59$!trace-include
60
61
62
63/**	Constant text fragments.
64*/
65static const char * const dk4gra_eps_c8_kw[] = {
66$!string-table
67#
68#	0	Newline
69#
70\n
71#
72#	1	gsave
73#
74gsave\n
75#
76#	2	grestore
77#
78grestore\n
79#
80#	3	space
81#
82
83#
84#	4	setlinewidth
85#
86 setlinewidth\n
87#
88#	5	setcmykcolor
89#
90 setcmykcolor\n
91#
92#	6	setrgbcolor
93#
94 setrgbcolor\n
95#
96#	7	setgray
97#
98 setgray\n
99#
100#	8	dash for solid line
101#
102[] 0 setdash\n
103#
104#	9 10 11	Dash array.
105#
106[
107]
108 setdash\n
109#
110#	12 13 14	Line cap
111#
1120 setlinecap\n
1131 setlinecap\n
1142 setlinecap\n
115#
116#	15 16 17	Line join
117#
1180 setlinejoin\n
1191 setlinejoin\n
1202 setlinejoin\n
121#
122#	18 19		fill
123#
124fill\n
125eofill\n
126#
127#	20			stroke
128#
129stroke\n
130#
131#	21 22		clip
132#
133clip\n
134eoclip\n
135#
136#	23			newpath
137#
138newpath\n
139#
140#	24			moveto
141#
142 moveto\n
143#
144#	25			lineto
145#
146 lineto\n
147#
148#	26			curveto
149#
150 curveto\n
151#
152#	27			closepath
153#
154closepath\n
155#
156#	28			circle
157#
158 0 360 arc closepath\n
159#
160#	29			arc
161#
162 arc\n
163#
164#	30 31		PS EPSF
165#
166%!PS-Adobe-3.0 EPSF-3.0\n
167%!PS-Adobe-2.0 EPSF-2.0\n
168#
169#	32 33		PS
170#
171%!PS-Adobe-3.0\n
172%!PS-Adobe-2.0\n
173#
174#	34 35	LanguageLevel
175#
176\%\%LanguageLevel: 3\n
177\%\%LanguageLevel: 2\n
178#
179#	36		BoundingBox
180#
181\%\%BoundingBox: 0 0
182#
183#	37		Pages
184#
185\%\%Pages:
186#
187#	38		PageOrder
188#
189\%\%PageOrder: Ascend\n
190#
191#	39		DocumentData
192#
193\%\%DocumentData: Clean7Bit\n
194#
195#	40		EndComments BeginProlog EndProlog
196#
197\%\%EndComments\n\%\%BeginProlog\n\%\%EndProlog\n
198#
199#	41		Trailer EOF
200#
201\%\%Trailer\n\%\%EOF\n
202#
203#	42		Page
204#
205\%\%Page:
206#
207#	43 44	begin dict
208#
209 dict begin\n
210end\n
211#
212#	45		showpage
213#
214showpage\n
215#
216#	46		0 0 moveto
217#
2180 0 moveto\n
219#
220#	47		0
221#
2220
223#
224#	48		1 setlinecap
225#
2261 setlinecap\n
227#
228#	49		white background fill color
229#
2301 setgray\n
231#
232#	50
233#
234 setmiterlimit\n
235#
236#	51-52	Begin and end setup
237#
238\%\%BeginSetup\n
239\%\%EndSetup\n
240#
241#	53-54	Begin and end feature
242#
243\%\%BeginFeature: *PageSize BmppPage\n
244\%\%EndFeature\n
245#
246#	55-56	Page size
247#
248<< /PageSize [
249] /ImagingBBox null >> setpagedevice\n
250#
251#	57-58
252#
253\%\%BeginFeature: *Duplex DuplexNoTumble\n
254<< /Duplex true /Tumble false >> setpagedevice\n
255#
256#	59-60
257#
258\%\%BeginFeature: *Duplex DuplexTumble\n
259<< /Duplex true /Tumble true >> setpagedevice\n
260$!end
261};
262
263
264
265/**	Write double value to page memory stream.
266	@param	bptr	Current page.
267	@param	v		Value to write.
268	@param	backptr	Address of success variable to reset on errors.
269	@param	erp		Error report, may be NULL.
270	@return	1 on success, 0 on error.
271
272	Error codes:
273	- DK4_E_INVALID_ARGUMENTS<br>
274	  if os is NULL.
275	- DK4_E_WRITE_FAILED<br>
276	  if writing one ore multiple bytes to the stream failed,
277	- DK4_E_FLUSH_FAILED<br>
278	  if flushing data downwards failed,
279	- DK4_E_MATH_OVERFLOW<br>
280	  if the exponent is out of range for integer values,<br>
281	- DK4_E_SYNTAX<br>
282	  if input contains invalid characters.
283*/
284static
285void
286dk4gra_eps_double_value(
287	dk4_gra_ps_page_t	*bptr,
288	double				 v,
289	int					*backptr,
290	dk4_er_t			*erp
291
292)
293{
294#if	DK4_USE_ASSERT
295	assert(NULL != bptr);
296#endif
297	dk4gratool_stream_double(bptr->memstrm, v, backptr, erp);
298}
299
300
301
302/**	Write a fixed keyword from dk4gra_eps_c8_kw to page memory stream.
303	@param	bptr	Current page.
304	@param	i		Index of keyword in array.
305	@param	backptr	Address of success variable to reset on errors.
306	@param	erp		Error report, may be NULL.
307	@return	1 on success, 0 on error.
308
309	Error codes:
310	- DK4_E_INVALID_ARGUMENTS<br>
311	  if str is NULL or the stream is not opened for writing,
312	- DK4_E_WRITE_FAILED<br>
313	  if writing one ore multiple bytes to the stream failed,
314	- DK4_E_FLUSH_FAILED<br>
315	  if flushing data downwards failed.
316*/
317static
318void
319dk4gra_eps_kw(
320	dk4_gra_ps_page_t	*bptr,
321	size_t				 i,
322	int					*backptr,
323	dk4_er_t			*erp
324)
325{
326#if	DK4_USE_ASSERT
327	assert(NULL != bptr);
328#endif
329	dk4gratool_stream_string(bptr->memstrm, dk4gra_eps_c8_kw[i], backptr, erp);
330}
331
332
333/**	Delete a PS/EPS page structure.
334	@param	bptr	Page structure to delete.
335*/
336static
337void
338dk4gra_eps_page_delete(
339	dk4_gra_ps_page_t	*bptr
340)
341{
342	$? "+ dk4gra_eps_page_delete %d", TR_IPTR(bptr)
343#if	DK4_USE_ASSERT
344	assert(NULL != bptr);
345#endif
346	if (NULL != bptr) {
347		/*
348			Release all resources
349		*/
350		if (NULL != bptr->memstrm) {		$? ". close memory stream"
351			dk4stream_close(bptr->memstrm, NULL);
352		}
353		bptr->memstrm = NULL;
354		if (NULL != bptr->membuf) {			$? ". close memory buffer"
355			dk4membuf_close(bptr->membuf);
356		}
357		bptr->membuf = NULL;
358		/*
359			Free memory for page structure itself
360		*/
361		dk4mem_free(bptr);
362	}
363	$? "- dk4gra_eps_page_delete"
364}
365
366
367
368/**	Create new page structure, allocated related resources.
369	@param	pageno	Page number of new page.
370	@param	flags	Page flags.
371	@param	erp		Error report, may be NULL.
372	@return	Valid pointer to new page structure on success, NULL on error.
373
374	Error codes:
375	- DK4_E_MATH_OVERFLOW<br>
376	  on numeric overflow when calculating the product of elsize and nelem,
377	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
378	  with mem.elsize and mem.nelem set if there is not enough memory
379	  available.
380*/
381static
382dk4_gra_ps_page_t *
383dk4gra_eps_page_new(
384	size_t		 pageno,
385	int			 flags,
386	dk4_er_t	*erp
387)
388{
389	dk4_gra_ps_page_t	*back	= NULL;
390	size_t				 i		= 0;		/* Traverse patterns */
391	int					 ok		= 0;
392	$? "+ dk4gra_eps_page_new"
393	back = dk4mem_new(dk4_gra_ps_page_t,1,erp);
394	if (NULL != back) {
395		/*
396			Initialize all components
397		*/
398		dk4gratool_initialize_attributes(&(back->attr));
399		back->membuf	= NULL;
400		back->memstrm	= NULL;
401		back->flags		= flags;
402		for (i = 0; i < 22; i++) {
403			back->patu[i] = 0x00;
404		}
405		back->pageno = pageno;
406		back->spip = 0;
407		back->cont = 0;
408		/*
409			Allocate resources for memory buffer and stream
410		*/
411		back->membuf = dk4membuf_open(erp);
412		if (NULL != back->membuf) {
413			back->memstrm = dk4stream_open_membuf_writer(back->membuf, erp);
414			if (NULL != back->memstrm) {
415				ok = 1;
416			}
417		}
418		if (0 == ok) {
419			dk4gra_eps_page_delete(back);
420			back = NULL;
421		}
422	}
423	$? "- dk4gra_eps_page_new %d", TR_IPTR(back)
424	return back;
425}
426
427
428
429/**	Write several double values to page memory stream and add keyword.
430	@param	bptr	Current page.
431	@param	da		Array of double values.
432	@param	szda	Number of elements in array.
433	@param	kwi		Index of keyword to add.
434	@param	backptr	Address of success variable to reset on errors.
435	@param	erp		Error report, may be NULL.
436
437	Error codes:
438	- DK4_E_INVALID_ARGUMENTS<br>
439	  if gra, bptr or da or the current page or the page stream on the
440	  current page is NULL,
441	- DK4_E_WRITE_FAILED<br>
442	  if writing one ore multiple bytes to the stream failed,
443	- DK4_E_FLUSH_FAILED<br>
444	  if flushing data downwards failed.
445	- DK4_E_MATH_OVERFLOW<br>
446	  if the exponent in one of the double values is out of range for
447	  integer values,<br>
448	- DK4_E_SYNTAX<br>
449	  if the text representation of the double value
450	  contains invalid characters.
451*/
452static
453void
454dk4gra_eps_values_and_keyword(
455	dk4_gra_ps_page_t	*bptr,
456	double				*da,
457	size_t				 szda,
458	size_t				 kwi,
459	int					*backptr,
460	dk4_er_t			*erp
461)
462{
463	size_t		i;				/* Traverse da */
464	int			back	= 1;
465#if	DK4_USE_ASSERT
466	assert(NULL != bptr);
467	assert(NULL != da);
468	assert(0 < szda);
469#endif
470	for (i = 0; i < szda; i++) {
471		if (0 != i) {
472			dk4gra_eps_kw(bptr, 3, &back, erp);
473		}
474		dk4gra_eps_double_value(bptr, da[i], &back, erp);
475	}
476	if (0 < kwi) {
477		dk4gra_eps_kw(bptr, kwi, &back, erp);
478	}
479	if ((NULL != backptr) && (0 == back)) { *backptr = 0; }
480}
481
482
483
484/**	Set new color if necessary.
485	@param	bptr				Current page.
486	@param	p_col_active		Currently active color.
487	@param	p_col_requested		Requested color.
488	@param	erp					Error report, may be NULL.
489	@return	1 on success, 0 on error.
490
491	Error codes:
492	- DK4_E_INVALID_ARGUMENTS<br>
493	  if gra, bptr or da or the current page or the page stream on the
494	  current page is NULL,
495	- DK4_E_WRITE_FAILED<br>
496	  if writing one ore multiple bytes to the stream failed,
497	- DK4_E_FLUSH_FAILED<br>
498	  if flushing data downwards failed.
499	- DK4_E_MATH_OVERFLOW<br>
500	  if the exponent in one of the double values is out of range for
501	  integer values,<br>
502	- DK4_E_SYNTAX<br>
503	  if the text representation of the double value
504	  contains invalid characters.
505*/
506static
507int
508dk4gra_eps_set_color_if_necessary(
509	dk4_gra_ps_page_t	*bptr,
510	dk4gra_col_t		*p_col_active,
511	dk4gra_col_t		*p_col_requested,
512	dk4_er_t			*erp
513)
514{
515	double	 val[4];			/* Color components */
516	int		 back	= 0;
517	$? "+ dk4gra_eps_set_color_if_necessary"
518#if	DK4_USE_ASSERT
519	assert(NULL != bptr);
520	assert(NULL != p_col_active);
521	assert(NULL != p_col_requested);
522#endif
523	if (0 == dk4gratool_colors_differ(p_col_active, p_col_requested)) {
524		back = 1;
525		goto finished;
526	}
527	dk4mem_cpy(p_col_active, p_col_requested, sizeof(dk4gra_col_t), NULL);
528	switch (p_col_active->what) {
529		case DK4_GRA_COL_SPEC_CMYK : {
530			val[0] = p_col_active->data.cmyk.c;
531			val[1] = p_col_active->data.cmyk.m;
532			val[2] = p_col_active->data.cmyk.y;
533			val[3] = p_col_active->data.cmyk.k;
534			back = 1;
535			dk4gra_eps_values_and_keyword(bptr, val, 4, 5, &back, erp);
536		} break;
537		case DK4_GRA_COL_SPEC_RGB : {
538			val[0] = p_col_active->data.rgb.r;
539			val[1] = p_col_active->data.rgb.g;
540			val[2] = p_col_active->data.rgb.b;
541			back = 1;
542			dk4gra_eps_values_and_keyword(bptr, val, 3, 6, &back, erp);
543		} break;
544		case DK4_GRA_COL_SPEC_GRAY : {
545			val[0] = p_col_active->data.gray;
546			back = 1;
547			dk4gra_eps_values_and_keyword(bptr, val, 1, 7, &back, erp);
548		} break;
549	}
550
551	finished:
552	$? "- dk4gra_eps_set_color_if_necessary %d", back
553	return back;
554}
555
556
557
558/**	Write dash setup.
559	@param	bptr	Current page in gra.
560	@param	da		Array of double values for stroke and gap lengths.
561	@param	sz		Number of elements in array.
562	@param	offset	Offset to start dash pattern.
563	@param	erp		Error report, may be NULL.
564	@return	1 on success, 0 on error.
565
566	Error codes:
567	- DK4_E_INVALID_ARGUMENTS<br>
568	  if the contents stream of the current page
569	  is NULL or the stream is not opened for writing,
570	- DK4_E_WRITE_FAILED<br>
571	  if writing one ore multiple bytes to the stream failed,
572	- DK4_E_FLUSH_FAILED<br>
573	  if flushing data downwards failed.
574	- DK4_E_MATH_OVERFLOW<br>
575	  if the exponent of a doublevalue is out of range for integer values,<br>
576	- DK4_E_SYNTAX<br>
577	  if a double value converted to string contains invalid characters.
578*/
579static
580int
581dk4gra_eps_dash_out(
582	dk4_gra_ps_page_t	*bptr,
583	double				*da,
584	size_t				 sz,
585	double				 offset,
586	dk4_er_t			*erp
587)
588{
589	size_t	 i;				/* Traverse dash length array da */
590	int		 back	= 1;
591
592#if	DK4_USE_ASSERT
593	assert(NULL != bptr);
594	assert(NULL != da);
595	assert(0 < sz);
596#endif
597	dk4gra_eps_kw(bptr, 9, &back, erp);
598	for (i = 0; i < sz; i++) {
599		if (0 != i) {
600			dk4gra_eps_kw(bptr, 3, &back, erp);
601		}
602		dk4gra_eps_double_value(bptr, da[i], &back, erp);
603	}
604	dk4gra_eps_kw(bptr, 10, &back, erp);
605	dk4gra_eps_kw(bptr, 3, &back, erp);
606	dk4gra_eps_double_value(bptr, offset, &back, erp);
607	dk4gra_eps_kw(bptr, 11, &back, erp);
608	return back;
609}
610
611
612
613/**	Put string to output file, on error set return code and error code.
614	@param	fout	Output file.
615	@param	str		String to write.
616	@param	pret	Address of return code variable.
617	@param	erp		Error report, may be NULL.
618
619	Error codes:
620	- DK4_E_WRITE_FAILED<br>
621	  if the write attempt failed.
622*/
623static
624void
625dk4gra_eps_string_to_file(
626	FILE		*fout,
627	const char	*str,
628	int			*pret,
629	dk4_er_t	*erp
630)
631{
632#if	DK4_USE_ASSERT
633	assert(NULL != fout);
634	assert(NULL != str);
635#endif
636	if (EOF == fputs(str, fout)) {
637		*pret = 0;
638		dk4error_set_simple_error_code(erp, DK4_E_WRITE_FAILED);
639	}
640}
641
642
643
644/**	Construct path for page border.
645	@param	fout	Output file to write.
646	@param	gra		Output structure.
647	@param	backptr	Address of success variable to reset on errors.
648	@param	erp		Error report, may be NULL.
649
650	Error codes:
651	- DK4_E_INVALID_ARGUMENTS<br>
652	  if arguments are invalid,
653	- DK4_E_BUFFER_TOO_SMALL<br>
654	  if the destination buffer size is too small for the result,
655	- DK4_E_BUG<br>
656	  if an internal buffer is too small (should not happen),
657	- DK4_E_WRITE_FAILED<br>
658	  if the write attempt failed.
659*/
660static
661void
662dk4gra_eps_page_border_path(
663	FILE		*fout,
664	dk4_gra_t	*gra,
665	int			*backptr,
666	dk4_er_t	*erp
667)
668{
669	char	b1[16*sizeof(dk4_um_t)];	/* Width as text */
670	char	b2[16*sizeof(dk4_um_t)];	/* Height as text */
671#if	DK4_USE_ASSERT
672	assert(NULL != gra);
673	assert(NULL != fout);
674#endif
675	(void)dk4ma_write_c8_decimal_unsigned(b1, sizeof(b1), gra->w, 0, erp);
676	(void)dk4ma_write_c8_decimal_unsigned(b2, sizeof(b2), gra->h, 0, erp);
677	/* 0 0 moveto */
678	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[23], backptr, erp);
679	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[46], backptr, erp);
680	/* w 0 lineto */
681	dk4gra_eps_string_to_file(fout, b1, backptr, erp);
682	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[3], backptr, erp);
683	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[47], backptr, erp);
684	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[25], backptr, erp);
685	/* w h lineto */
686	dk4gra_eps_string_to_file(fout, b1, backptr, erp);
687	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[3], backptr, erp);
688	dk4gra_eps_string_to_file(fout, b2, backptr, erp);
689	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[25], backptr, erp);
690	/* 0 h lineto */
691	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[47], backptr, erp);
692	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[3], backptr, erp);
693	dk4gra_eps_string_to_file(fout, b2, backptr, erp);
694	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[25], backptr, erp);
695	/* closepath */
696	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[27], backptr, erp);
697}
698
699
700/**	Write one page to output file.
701	@param	fout	Output file.
702	@param	gra		Output structure.
703	@param	bptr	Current page.
704	@param	erp		Error report, may be NULL.
705	@return	1 on success, 0 on error.
706*/
707static
708int
709dk4gra_eps_one_page_to_file(
710	FILE				*fout,
711	dk4_gra_t			*gra,
712	dk4_gra_ps_page_t	*bptr,
713	dk4_er_t			*erp
714)
715{
716	char		 		 b1[8*sizeof(dk4_um_t)];	/* Page no as text */
717	char		 		 b2[8*sizeof(dk4_um_t)];	/* Pages number as text */
718	const char * const	*pproc;						/* Pattern procedure name */
719	size_t				 numpat		=	0;			/* Number of used pats */
720	size_t				 i			=	0;			/* Traverse used pats */
721	int					 back		=	1;
722
723#if	DK4_USE_ASSERT
724	assert(NULL != gra);
725	assert(NULL != fout);
726#endif
727	/*	%%Page: 1 1
728	*/
729	if (0 != gra->out.ps.dsc) {
730		(void)dk4ma_write_c8_decimal_unsigned(
731			b1, sizeof(b1), (bptr->pageno + 1), 0, erp
732		);
733		(void)dk4ma_write_c8_decimal_unsigned(
734			b2, sizeof(b2), gra->pages, 0, erp
735		);
736		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[42], &back, erp);
737		dk4gra_eps_string_to_file(fout, b1, &back, erp);
738		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[3], &back, erp);
739		dk4gra_eps_string_to_file(fout, b2, &back, erp);
740		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[0], &back, erp);
741	}
742
743	/*	Count number of used patterns.
744	*/
745	for (i = 0; i <= DK4_GRA_PATTERN_MAX; i++) {
746		if (0 != bptr->patu[i]) { numpat++; }
747	}
748
749	/*	xxx dict begin
750	*/
751	if (0 != numpat) {
752		(void)dk4ma_write_c8_decimal_unsigned(b1, sizeof(b1), numpat, 0, erp);
753		dk4gra_eps_string_to_file(fout, b1, &back, erp);
754		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[43], &back, erp);
755		for (i = 0; i <= DK4_GRA_PATTERN_MAX; i++) {
756			if (0 != bptr->patu[i]) {
757				pproc = dk4gra_eps_pattern_procedure(i);
758				while (NULL != *pproc) {
759					if (EOF == fputs(*(pproc++), fout)) { back = 0; }
760					if (EOF == fputc('\n', fout)) { back = 0; }
761				}
762			}
763		}
764	}
765
766	/*	gsave
767	*/
768	if (0 == bptr->spip) {
769		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[1], &back, erp);
770	}
771
772	/*	clip path
773	*/
774	if (
775		(0 == ((bptr->flags) & DK4_GRA_PAGE_FLAG_NO_CLIP))
776		&& (0 == bptr->spip)
777	) {
778		/* construct path */
779		dk4gra_eps_page_border_path(fout, gra, &back, erp);
780		/* clip */
781		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[21], &back, erp);
782	}
783
784	/*	white page background
785	*/
786	if (
787		(0 == ((bptr->flags) & DK4_GRA_PAGE_FLAG_NO_BG))
788		&& (0 == bptr->spip)
789	) {
790		/* white color */
791		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[49], &back, erp);
792		bptr->attr.col_stroke_active.what = DK4_GRA_COL_SPEC_GRAY;
793		bptr->attr.col_stroke_active.data.gray = 1.0;
794		/* construct path */
795		dk4gra_eps_page_border_path(fout, gra, &back, erp);
796		/* fill */
797		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[18], &back, erp);
798	}
799
800	/*	page contents
801	*/
802	if (NULL != bptr->memstrm) {
803		if (0 == dk4stream_close(bptr->memstrm, erp)) {
804			back = 0;
805		}
806		bptr->memstrm = NULL;
807	}
808	if (NULL != bptr->membuf) {
809		if (0 == dk4membuf_to_file(fout, bptr->membuf, erp)) {
810			back = 0;
811		}
812	}
813
814	/*	grestore
815	*/
816	if (0 == bptr->spip) {
817		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[2], &back, erp);
818	}
819
820	/*	end
821	*/
822	if (0 != numpat) {
823		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[44], &back, erp);
824	}
825
826	/*	showpage
827	*/
828	if ((DK4_GRA_DRIVER_EPS != gra->dr) && (0 == bptr->spip)) {
829		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[45], &back, erp);
830	}
831
832	return back;
833}
834
835
836
837/**	Write pattern instance.
838	@param	bptr	Current page.
839	@param	da		Array of values.
840	@param	szda	Size of da array (number of elements).
841	@param	pname	Pattern name.
842	@param	erp		Error report, may be NULL.
843	@return	1 on success, 0 on error.
844*/
845static
846int
847dk4gra_eps_write_pattern_instance(
848	dk4_gra_ps_page_t	*bptr,
849	const double		*da,
850	size_t				 szda,
851	const char			*pname,
852	dk4_er_t			*erp
853)
854{
855	size_t	 i;				/* Traverse da array */
856	int		 res;			/* Operation result */
857	int		 back = 1;
858#if	DK4_USE_ASSERT
859	assert(NULL != bptr);
860	assert(NULL != da);
861	assert(0 < szda);
862	assert(NULL != pname);
863#endif
864	for (i = 0; i < szda; i++) {
865		if (0 != i) {
866			dk4gra_eps_kw(bptr, 3, &back, erp);
867		}
868		res = dk4ma_write_c8_double_no_sci_to_stream(
869			bptr->memstrm, *(da++), DK4_GRA_EPSILON_COORDINATES, 0, 1, erp
870		);
871		if (0 == res) { back = 0; }
872	}
873	if (0 < i) {
874		dk4gra_eps_kw(bptr, 3, &back, erp);
875	}
876	res = dk4stream_write_char_string(bptr->memstrm, pname, erp);
877	if (0 == res) { back = 0; }
878	dk4gra_eps_kw(bptr, 0, &back, erp);
879	return back;
880}
881
882
883
884/**	Compare page structures by number or a page against a number.
885	@param	l	Left page object.
886	@param	r	Right page object or page number.
887	@param	cr	Comparison criteria (0=page/page, 1=page/number).
888	@return	Comparison result.
889*/
890static
891int
892dk4gra_eps_compare_pages_by_number(const void *l, const void *r, int cr)
893{
894	const	dk4_gra_ps_page_t	*pl;		/* Left side object */
895	const	dk4_gra_ps_page_t	*pr;		/* Right side object */
896	const	size_t				*ppno;		/* Address of a page number */
897
898	int		 back	= 0;
899	if (NULL != l) {
900		if (NULL != r) {
901			pl = (const dk4_gra_ps_page_t *)l;
902			switch (cr) {
903				case 1: {
904					ppno = (const size_t *)r;
905					if (pl->pageno > *ppno) {
906						back = 1;
907					}
908					else {
909						if (pl->pageno < *ppno) {
910							back = -1;
911						}
912					}
913				} break;
914				default : {
915					pr = (const dk4_gra_ps_page_t *)r;
916					if (pl->pageno > pr->pageno) {
917						back = 1;
918					}
919					else {
920						if (pl->pageno < pr->pageno) {
921							back = -1;
922						}
923					}
924				} break;
925			}
926		}
927		else {
928			back = 1;
929		}
930	}
931	else {
932		if (NULL != r) {
933			back = -1;
934		}
935	}
936	return back;
937}
938
939
940
941/**	Write PS/EPS contents to file.
942	@param	fout	File, opened for write access.
943	@param	gra		Output structure.
944	@param	erp		Error report, may be NULL.
945
946	Error codes:
947	- DK4_E_WRITE_FAILED<br>
948	  if the write attempt failed.
949	- DK4_E_FLUSH_FAILED<br>
950	  if flushing data downwards failed,
951	- DK4_E_CLOSE_FAILED<br>
952	  if closing downward data failed,
953	- DK4_E_BUFFER_TOO_SMALL<br>
954	  if an internal buffer in this function is too small (should not happen).
955	- DK4_E_BUG<br>
956	  if an internal buffer in dk4ma_write_c8_decimal_unsigned()
957	  is too small (should not happen).
958*/
959static
960int
961dk4gra_eps_file(
962	FILE		*fout,
963	dk4_gra_t	*gra,
964	dk4_er_t	*erp
965)
966{
967	char				 b1[8*sizeof(dk4_um_t)];	/* Buffer for numbers */
968	char				 b2[8*sizeof(dk4_um_t)];	/* Buffer for numbers */
969	dk4_gra_ps_page_t	*bptr;						/* Current page */
970	int					 back	= 1;
971	$? "+ dk4gra_eps_file"
972#if	DK4_USE_ASSERT
973	assert(NULL != gra);
974	assert(NULL != fout);
975#endif
976	/*	Document header
977		---------------
978	*/
979
980	/*	%!PS-Adobe-2.0 (EPSF...)
981	*/
982	if (DK4_GRA_DRIVER_EPS == gra->dr) {
983		dk4gra_eps_string_to_file(
984			fout, dk4gra_eps_c8_kw[(3 == gra->out.ps.llev) ? (30) : (31)],
985			&back, erp
986		);
987	}
988	else {
989		dk4gra_eps_string_to_file(
990			fout, dk4gra_eps_c8_kw[(3 == gra->out.ps.llev) ? (32) : (33)],
991			&back, erp
992		);
993	}
994
995	/*	%%LanguageLevel
996	*/
997	dk4gra_eps_string_to_file(
998		fout, dk4gra_eps_c8_kw[(3 == gra->out.ps.llev) ? (34) : (35)],
999		&back, erp
1000	);
1001
1002	/*	%%BoundingBox
1003	*/
1004	(void)dk4ma_write_c8_decimal_unsigned(b1, sizeof(b1), gra->w, 0, erp);
1005	(void)dk4ma_write_c8_decimal_unsigned(b2, sizeof(b2), gra->h, 0, erp);
1006	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[36], &back, erp);
1007	dk4gra_eps_string_to_file(fout, b1, &back, erp);
1008	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[3], &back, erp);
1009	dk4gra_eps_string_to_file(fout, b2, &back, erp);
1010	dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[0], &back, erp);
1011
1012
1013	if (0 != gra->out.ps.dsc) {
1014
1015		/*	%%Title			-- ignored
1016		*/
1017
1018		/*	%%Creator		-- ignored
1019		*/
1020
1021		/*	%%CreationDate	-- ignored
1022		*/
1023
1024		/*	%%Pages
1025		*/
1026		(void)dk4ma_write_c8_decimal_unsigned(
1027			b1, sizeof(b1), gra->pages, 0, erp
1028		);
1029		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[37], &back, erp);
1030		dk4gra_eps_string_to_file(fout, b1, &back, erp);
1031		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[0], &back, erp);
1032
1033
1034		/*	%%PageOrder
1035		*/
1036		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[38], &back, erp);
1037
1038		/*	%%DocumentData
1039		*/
1040		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[39], &back, erp);
1041
1042		/*	%%EndComments BeginProlog EndProlog
1043		*/
1044		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[40], &back, erp);
1045
1046		/*	Page setup for PS documents
1047		*/
1048		if (DK4_GRA_DRIVER_PS == gra->dr) {
1049			dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[51], &back, erp);
1050			/*
1051				Paper size
1052			*/
1053			(void)dk4ma_write_c8_decimal_unsigned(b1,sizeof(b1),gra->w,0,erp);
1054			(void)dk4ma_write_c8_decimal_unsigned(b2,sizeof(b2),gra->h,0,erp);
1055			dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[53], &back, erp);
1056			dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[55], &back, erp);
1057			dk4gra_eps_string_to_file(fout, b1, &back, erp);
1058			dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[3], &back, erp);
1059			dk4gra_eps_string_to_file(fout, b2, &back, erp);
1060			dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[56], &back, erp);
1061			dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[54], &back, erp);
1062			/*
1063				Duplex (and tumble)
1064			*/
1065			if (0 != (DK4_GRA_DOC_FLAG_TUMBLE & (gra->docfl))) {
1066				dk4gra_eps_string_to_file(fout,dk4gra_eps_c8_kw[59],&back,erp);
1067				dk4gra_eps_string_to_file(fout,dk4gra_eps_c8_kw[60],&back,erp);
1068				dk4gra_eps_string_to_file(fout,dk4gra_eps_c8_kw[54],&back,erp);
1069			}
1070			else {
1071				if (0 != (DK4_GRA_DOC_FLAG_DUPLEX & (gra->docfl))) {
1072				dk4gra_eps_string_to_file(fout,dk4gra_eps_c8_kw[57],&back,erp);
1073				dk4gra_eps_string_to_file(fout,dk4gra_eps_c8_kw[58],&back,erp);
1074				dk4gra_eps_string_to_file(fout,dk4gra_eps_c8_kw[54],&back,erp);
1075				}
1076			}
1077			dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[52], &back, erp);
1078		}
1079
1080	}
1081
1082	/*	Pages
1083		-----
1084	*/
1085	dk4sto_it_reset(gra->i_pages);
1086	do {
1087		bptr = (dk4_gra_ps_page_t *)dk4sto_it_next(gra->i_pages);
1088		if (NULL != bptr) {
1089			if (0 == dk4gra_eps_one_page_to_file(fout, gra, bptr, erp)) {
1090				back = 0;
1091			}
1092		}
1093	} while (NULL != bptr);
1094
1095
1096	/*	Document trailer
1097		----------------
1098	*/
1099
1100	if (0 != gra->out.ps.dsc) {
1101		/*	%%Trailer	%%EOF
1102		*/
1103		dk4gra_eps_string_to_file(fout, dk4gra_eps_c8_kw[41], &back, erp);
1104	}
1105
1106	/*	Ctrl-D
1107	*/
1108	if (DK4_GRA_DRIVER_PS == gra->dr) {
1109		if (EOF == fputc(0x04, fout)) {
1110			back = 0;
1111			dk4error_set_simple_error_code(erp, DK4_E_WRITE_FAILED);
1112		}
1113	}
1114
1115	$? "- dk4gra_eps_file %d", back
1116	return back;
1117}
1118
1119
1120
1121void
1122dk4gra_eps_close(
1123	dk4_gra_t		*gra
1124)
1125{
1126	dk4_gra_ps_page_t	*bptr;		/* Current page to release */
1127
1128	$? "+ dk4gra_eps_close"
1129#if	DK4_USE_ASSERT
1130	assert(NULL != gra);
1131#endif
1132	if (NULL == gra) {
1133		goto finished;
1134	}
1135	if (NULL != gra->s_pages) {
1136		if (NULL != gra->i_pages) {
1137			dk4sto_it_reset(gra->i_pages);
1138			do {
1139				bptr = (dk4_gra_ps_page_t *)dk4sto_it_next(gra->i_pages);
1140				if (NULL != bptr) {
1141					dk4gra_eps_page_delete(bptr);
1142				}
1143			} while (NULL != bptr);
1144			dk4sto_it_close(gra->i_pages);
1145			gra->i_pages = NULL;
1146		}
1147		dk4sto_close(gra->s_pages);
1148		gra->s_pages = NULL;
1149	}
1150	dk4gratool_close(gra);
1151
1152	finished:
1153	$? "- dk4gra_eps_close"
1154	return;
1155}
1156
1157
1158
1159dk4_gra_t *
1160dk4gra_eps_open(
1161	const dkChar	*fn,
1162	size_t			 w,
1163	size_t			 h,
1164	int				 docfl,
1165	dk4_er_t		*erp
1166)
1167{
1168	dk4_gra_t	*back	= NULL;
1169	int			 ok		= 0;
1170	$? "+ dk4gra_eps_open_ps"
1171#if	DK4_USE_ASSERT
1172	assert(NULL != fn);
1173#endif
1174
1175	/*	Open output structure, set up default components
1176	*/
1177	back = dk4gratool_open(fn, w, h, docfl, erp);
1178	if (NULL == back) {
1179		goto finished;
1180	}
1181
1182	/*	Set driver
1183	*/
1184	if (0 != (DK4_GRA_DOC_FLAG_EPS & docfl)) {
1185		back->dr = DK4_GRA_DRIVER_EPS;
1186	}
1187	else {
1188		back->dr = DK4_GRA_DRIVER_PS;
1189	}
1190	if (0 != (DK4_GRA_DOC_FLAG_PS_DSC & docfl)) {
1191		back->out.ps.dsc = 1;
1192	}
1193	if (0 != (DK4_GRA_DOC_FLAG_PS2 & docfl)) {
1194		back->out.ps.llev = 2;
1195	}
1196	else {
1197		back->out.ps.llev = 3;
1198	}
1199	back->out.ps.fspd = 0;
1200	back->out.ps.fdu  = 0;
1201	back->out.ps.ftu  = 0;
1202
1203	/*	Set up container and iterator for pages
1204	*/
1205	back->s_pages = dk4sto_open(erp);
1206	if (NULL == back->s_pages) {
1207		goto finished;
1208	}
1209	(void)dk4sto_set_comp(back->s_pages, dk4gra_eps_compare_pages_by_number, 0);
1210	back->i_pages = dk4sto_it_open(back->s_pages, erp);
1211	if (NULL == back->i_pages) {
1212		goto finished;
1213	}
1214
1215	/*	Indicate success to cleanup section
1216	*/
1217	ok = 1;
1218
1219	/*	End of function, clean up if not successful
1220	*/
1221	finished:
1222	if ((NULL != back) && (0 == ok)) {
1223		dk4gra_eps_close(back);
1224		back = NULL;
1225	}
1226	$? "- dk4gra_eps_open_ps %d", TR_IPTR(back)
1227	return back;
1228}
1229
1230
1231
1232int
1233dk4gra_eps_write_file_and_close(
1234	FILE			*fout,
1235	dk4_gra_t		*gra,
1236	dk4_er_t		*erp
1237)
1238{
1239	int		 back = 0;
1240	$? "+ dk4gra_eps_write_file_and_close"
1241#if	DK4_USE_ASSERT
1242	assert(NULL != gra);
1243	assert(NULL != fout);
1244#endif
1245	back = dk4gra_eps_file(fout, gra, erp);
1246	dk4gra_eps_close(gra);
1247	$? "- dk4gra_eps_write_file_and_close %d", back
1248	return back;
1249}
1250
1251
1252
1253int
1254dk4gra_eps_page(
1255	dk4_gra_t		*gra,
1256	int				 flags,
1257	dk4_er_t		*erp
1258)
1259{
1260	dk4_gra_ps_page_t	*curpg;		/* New current page */
1261	int		 			 back = 0;
1262	$? "+ dk4gra_eps_page"
1263#if	DK4_USE_ASSERT
1264	assert(NULL != gra);
1265#endif
1266	/*
1267		Check number of pages already defined
1268	*/
1269	if (SIZE_MAX == gra->pages) {
1270		dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
1271		goto finished;
1272	}
1273	if ((DK4_GRA_DRIVER_EPS == gra->dr) && (0 != gra->pages)) {
1274		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1275		goto finished;
1276	}
1277	/*	Create new page and add to containter and mark as current page
1278	*/
1279	curpg = dk4gra_eps_page_new(gra->pages, flags, erp);
1280	if (NULL == curpg) {
1281		goto finished;
1282	}
1283	/*	Add new page to pages container
1284	*/
1285	if (0 == dk4sto_add(gra->s_pages, curpg, erp)) {
1286		dk4gra_eps_page_delete(curpg);
1287		goto finished;
1288	}
1289	/*	Set new page as current page, indicate success
1290	*/
1291	gra->curpg = curpg;
1292	gra->pages += 1;
1293	back = 1;
1294
1295	finished:
1296	$? "- dk4gra_eps_page %d", back
1297	return back;
1298}
1299
1300
1301
1302int
1303dk4gra_eps_gsave(
1304	dk4_gra_t		*gra,
1305	dk4_er_t		*erp
1306)
1307{
1308	dk4_gra_ps_page_t	*bptr;		/* Current page */
1309	int					 back = 0;
1310	$? "+ dk4gra_eps_gsave"
1311#if	DK4_USE_ASSERT
1312	assert(NULL != gra);
1313#endif
1314	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1315	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1316		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1317		goto finished;
1318	}
1319	back = 1;
1320	dk4gra_eps_kw(bptr, 1, &back, erp);
1321	bptr->cont = 1;
1322
1323	finished:
1324	$? "- dk4gra_eps_gsave %d", back
1325	return back;
1326}
1327
1328
1329
1330int
1331dk4gra_eps_grestore(
1332	dk4_gra_t		*gra,
1333	dk4_er_t		*erp
1334)
1335{
1336	dk4_gra_ps_page_t	*bptr;		/* Current page */
1337	int					 back = 0;
1338	$? "+ dk4gra_eps_grestore"
1339#if	DK4_USE_ASSERT
1340	assert(NULL != gra);
1341#endif
1342	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1343	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1344		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1345		goto finished;
1346	}
1347	back = 1;
1348	dk4gra_eps_kw(bptr, 2, &back, erp);
1349	bptr->cont = 1;
1350
1351	finished:
1352	$? "- dk4gra_eps_grestore %d", back
1353	return back;
1354}
1355
1356
1357
1358int
1359dk4gra_eps_set_line_width(
1360	dk4_gra_t		*gra,
1361	double			 lw,
1362	dk4_er_t		*erp
1363)
1364{
1365	dk4_gra_ps_page_t	*bptr;		/* Current page */
1366	int					 back = 0;
1367	$? "+ dk4gra_eps_set_line_width"
1368#if	DK4_USE_ASSERT
1369	assert(NULL != gra);
1370#endif
1371	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1372	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1373		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1374		goto finished;
1375	}
1376	bptr->attr.lw_requested = lw;
1377	back = 1;
1378	bptr->cont = 1;
1379
1380	finished:
1381	$? "- dk4gra_eps_set_line_width %d", back
1382	return back;
1383}
1384
1385
1386
1387int
1388dk4gra_eps_set_line_style(
1389	dk4_gra_t		*gra,
1390	int				 ls,
1391	double			 sv,
1392	dk4_er_t		*erp
1393)
1394{
1395	dk4_gra_ps_page_t	*bptr;		/* Current page */
1396	int					 back = 0;
1397	$? "+ dk4gra_eps_set_line_style"
1398#if	DK4_USE_ASSERT
1399	assert(NULL != gra);
1400#endif
1401	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1402	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1403		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1404		goto finished;
1405	}
1406	bptr->attr.ls_requested = ls;
1407	bptr->attr.sv_requested = sv;
1408	back = 1;
1409	bptr->cont = 1;
1410
1411	finished:
1412	$? "- dk4gra_eps_set_line_style %d", back
1413	return back;
1414}
1415
1416
1417
1418int
1419dk4gra_eps_set_line_cap(
1420	dk4_gra_t		*gra,
1421	int				 lc,
1422	dk4_er_t		*erp
1423)
1424{
1425	dk4_gra_ps_page_t	*bptr;		/* Current page */
1426	int					 back = 0;
1427	$? "+ dk4gra_eps_set_line_cap"
1428#if	DK4_USE_ASSERT
1429	assert(NULL != gra);
1430#endif
1431	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1432	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1433		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1434		goto finished;
1435	}
1436	bptr->attr.lc_requested = lc;
1437	back = 1;
1438	bptr->cont = 1;
1439
1440	finished:
1441	$? "- dk4gra_eps_set_line_cap %d", back
1442	return back;
1443}
1444
1445
1446
1447int
1448dk4gra_eps_set_line_join(
1449	dk4_gra_t		*gra,
1450	int				 lj,
1451	double			 ml,
1452	dk4_er_t		*erp
1453)
1454{
1455	dk4_gra_ps_page_t	*bptr;		/* Current page */
1456	int					 back = 0;
1457	$? "+ dk4gra_eps_set_line_join"
1458#if	DK4_USE_ASSERT
1459	assert(NULL != gra);
1460#endif
1461	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1462	if ((NULL == bptr->memstrm) || (bptr->spip)) {
1463		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1464		goto finished;
1465	}
1466	bptr->attr.lj_requested = lj;
1467	bptr->attr.ml_requested = ml;
1468	back = 1;
1469	if (1.0 > bptr->attr.ml_requested) {
1470		bptr->attr.ml_requested = 1.0;
1471		back = 0;
1472		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1473	}
1474	bptr->cont = 1;
1475
1476	finished:
1477	$? "- dk4gra_eps_set_line_join %d", back
1478	return back;
1479}
1480
1481
1482
1483int
1484dk4gra_eps_set_fill_gray(
1485	dk4_gra_t		*gra,
1486	double			 g,
1487	dk4_er_t		*erp
1488)
1489{
1490	dk4_gra_ps_page_t	*bptr;		/* Current page */
1491	int					 back = 0;
1492	$? "+ dk4gra_eps_set_fill_gray %g", g
1493#if	DK4_USE_ASSERT
1494	assert(NULL != gra);
1495#endif
1496	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1497	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1498		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1499		goto finished;
1500	}
1501	dk4gratool_set_color_requested(
1502		&(bptr->attr.col_fill_requested),
1503		DK4_GRA_COL_SPEC_GRAY, g, 0.0, 0.0, 0.0
1504	);
1505	back = 1;
1506	bptr->cont = 1;
1507
1508	finished:
1509	$? "- dk4gra_eps_set_fill_gray %d", back
1510	return back;
1511}
1512
1513
1514
1515int
1516dk4gra_eps_set_fill_rgb(
1517	dk4_gra_t		*gra,
1518	double			 r,
1519	double			 g,
1520	double			 b,
1521	dk4_er_t		*erp
1522)
1523{
1524	dk4_gra_ps_page_t	*bptr;		/* Current page */
1525	int					 back = 0;
1526	$? "+ dk4gra_eps_set_fill_rgb %g %g %g", r, g, b
1527#if	DK4_USE_ASSERT
1528	assert(NULL != gra);
1529#endif
1530	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1531	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1532		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1533		goto finished;
1534	}
1535	dk4gratool_set_color_requested(
1536		&(bptr->attr.col_fill_requested),
1537		DK4_GRA_COL_SPEC_RGB, r, g, b, 0.0
1538	);
1539	back = 1;
1540	bptr->cont = 1;
1541
1542	finished:
1543	$? "- dk4gra_eps_set_fill_rgb %d", back
1544	return back;
1545}
1546
1547
1548
1549int
1550dk4gra_eps_set_fill_cmyk(
1551	dk4_gra_t		*gra,
1552	double			 c,
1553	double			 m,
1554	double			 y,
1555	double			 k,
1556	dk4_er_t		*erp
1557)
1558{
1559	dk4_gra_ps_page_t	*bptr;		/* Current page */
1560	int					 back = 0;
1561	$? "+ dk4gra_eps_set_fill_cmyk %g %g %g %g", c, m, y, k
1562#if	DK4_USE_ASSERT
1563	assert(NULL != gra);
1564#endif
1565	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1566	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1567		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1568		goto finished;
1569	}
1570	dk4gratool_set_color_requested(
1571		&(bptr->attr.col_fill_requested),
1572		DK4_GRA_COL_SPEC_CMYK, c, m, y, k
1573	);
1574	back = 1;
1575	bptr->cont = 1;
1576
1577	finished:
1578	$? "- dk4gra_eps_set_fill_cmyk %d", back
1579	return back;
1580}
1581
1582
1583
1584int
1585dk4gra_eps_set_stroke_gray(
1586	dk4_gra_t		*gra,
1587	double			 g,
1588	dk4_er_t		*erp
1589)
1590{
1591	dk4_gra_ps_page_t	*bptr;		/* Current page */
1592	int					 back = 0;
1593	$? "+ dk4gra_eps_set_stroke_gray %g", g
1594#if	DK4_USE_ASSERT
1595	assert(NULL != gra);
1596#endif
1597	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1598	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1599		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1600		goto finished;
1601	}
1602	dk4gratool_set_color_requested(
1603		&(bptr->attr.col_stroke_requested),
1604		DK4_GRA_COL_SPEC_GRAY, g, 0.0, 0.0, 0.0
1605	);
1606	back = 1;
1607	bptr->cont = 1;
1608
1609	finished:
1610	$? "- dk4gra_eps_set_stroke_gray %d", back
1611	return back;
1612}
1613
1614
1615
1616int
1617dk4gra_eps_set_stroke_rgb(
1618	dk4_gra_t		*gra,
1619	double			 r,
1620	double			 g,
1621	double			 b,
1622	dk4_er_t		*erp
1623)
1624{
1625	dk4_gra_ps_page_t	*bptr;		/* Current page */
1626	int					 back = 0;
1627	$? "+ dk4gra_eps_set_stroke_rgb %g %g %g", r, g, b
1628#if	DK4_USE_ASSERT
1629	assert(NULL != gra);
1630#endif
1631	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1632	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1633		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1634		goto finished;
1635	}
1636	dk4gratool_set_color_requested(
1637		&(bptr->attr.col_stroke_requested),
1638		DK4_GRA_COL_SPEC_RGB, r, g, b, 0.0
1639	);
1640	back = 1;
1641	bptr->cont = 1;
1642
1643	finished:
1644	$? "- dk4gra_eps_set_stroke_rgb %d", back
1645	return back;
1646}
1647
1648
1649
1650int
1651dk4gra_eps_set_stroke_cmyk(
1652	dk4_gra_t		*gra,
1653	double			 c,
1654	double			 m,
1655	double			 y,
1656	double			 k,
1657	dk4_er_t		*erp
1658)
1659{
1660	dk4_gra_ps_page_t	*bptr;		/* Current page */
1661	int					 back = 0;
1662	$? "+ dk4gra_eps_set_stroke_cmyk %g %g %g %g", c, m, y, k
1663#if	DK4_USE_ASSERT
1664	assert(NULL != gra);
1665#endif
1666	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1667	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1668		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1669		goto finished;
1670	}
1671	dk4gratool_set_color_requested(
1672		&(bptr->attr.col_stroke_requested),
1673		DK4_GRA_COL_SPEC_CMYK, c, m, y, k
1674	);
1675	back = 1;
1676	bptr->cont = 1;
1677
1678	finished:
1679	$? "- dk4gra_eps_set_stroke_cmyk %d", back
1680	return back;
1681}
1682
1683
1684
1685int
1686dk4gra_eps_prepare_fill(
1687	dk4_gra_t	*gra,
1688	dk4_er_t	*erp
1689)
1690{
1691	dk4_gra_ps_page_t	*bptr;		/* Current page */
1692	int					 back = 0;
1693	$? "+ dk4gra_eps_prepare_fill"
1694#if	DK4_USE_ASSERT
1695	assert(NULL != gra);
1696#endif
1697	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1698	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1699		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1700		goto finished;
1701	}
1702	/*
1703		Fill color
1704	*/
1705	back = dk4gra_eps_set_color_if_necessary(
1706		bptr,
1707		&(bptr->attr.col_stroke_active), &(bptr->attr.col_fill_requested),
1708		erp
1709	);
1710	bptr->cont = 1;
1711
1712	finished:
1713	$? "- dk4gra_eps_prepare_fill %d", back
1714	return back;
1715}
1716
1717
1718
1719int
1720dk4gra_eps_prepare_stroke(
1721	dk4_gra_t	*gra,
1722	dk4_er_t	*erp
1723)
1724{
1725	double				 da[8];			/* Dash array */
1726	dk4_gra_ps_page_t	*bptr;			/* Current page */
1727	double				 gw;			/* Gap width */
1728	size_t				 lci;			/* Line cap index */
1729	int					 res;			/* Operation result */
1730	int					 back	= 0;	/* Function result */
1731	int					 lwc	= 0;	/* Flag: Line width was changed */
1732	$? "+ dk4gra_eps_prepare_stroke"
1733#if	DK4_USE_ASSERT
1734	assert(NULL != gra);
1735#endif
1736	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1737	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1738		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1739		goto finished;
1740	}
1741	/*	Stroke color
1742	*/
1743	back = dk4gra_eps_set_color_if_necessary(
1744		bptr,
1745		&(bptr->attr.col_stroke_active), &(bptr->attr.col_stroke_requested),
1746		erp
1747	);
1748	/*	Line width
1749	*/
1750	if (
1751		DK4_GRA_EPSILON_LINEWIDTH
1752		< fabs(bptr->attr.lw_active - bptr->attr.lw_requested)
1753	) {
1754		dk4gra_eps_double_value(bptr, bptr->attr.lw_requested, &back, erp);
1755		dk4gra_eps_kw(bptr, 4, &back, erp);
1756		lwc = 1;
1757		bptr->attr.lw_active = bptr->attr.lw_requested;
1758	}
1759	/*	Line style
1760	*/
1761	res = dk4gratool_line_style_differs(
1762		bptr->attr.ls_active, bptr->attr.ls_requested,
1763		bptr->attr.sv_active, bptr->attr.sv_requested,
1764		lwc
1765	);
1766	if (0 != res) {
1767		bptr->attr.ls_active = bptr->attr.ls_requested;
1768		bptr->attr.sv_active = bptr->attr.sv_requested;
1769		gw = (bptr->attr.sv_active + bptr->attr.lw_active) / 2.0;
1770		if ((2.0 * bptr->attr.lw_active) < gw) {
1771			gw = 2.0 * bptr->attr.lw_active;
1772		}
1773		switch (bptr->attr.lc_requested) {
1774			case DK4_GRA_LC_ROUNDED : case DK4_GRA_LC_PROJECTING : {
1775				gw += bptr->attr.lw_requested;
1776			} break;
1777		}
1778		switch (bptr->attr.ls_active) {
1779			case DK4_GRA_LS_DASH : {
1780				da[0] = bptr->attr.sv_active;
1781				da[1] = gw;
1782				res = dk4gra_eps_dash_out(
1783					bptr, da, 2, (bptr->attr.sv_active / 2.0), erp
1784				);
1785				if (0 == res) { back = 0; }
1786			} break;
1787			case DK4_GRA_LS_DOT : {
1788				da[0] = da[1] = bptr->attr.lw_active;
1789				res = dk4gra_eps_dash_out(bptr, da, 2, 0.0, erp);
1790				if (0 == res) { back = 0; }
1791			} break;
1792			case DK4_GRA_LS_DASH_DOT : {
1793				da[0] = bptr->attr.sv_active;
1794				da[1] = gw;
1795				da[2] = bptr->attr.lw_active;
1796				da[3] = gw;
1797				res = dk4gra_eps_dash_out(
1798					bptr, da, 4, (bptr->attr.sv_active / 2.0), erp
1799				);
1800				if (0 == res) { back = 0; }
1801			} break;
1802			case DK4_GRA_LS_DASH_DOT_DOT : {
1803				da[0] = bptr->attr.sv_active;
1804				da[1] = gw;
1805				da[2] = bptr->attr.lw_active;
1806				da[3] = gw;
1807				da[4] = bptr->attr.lw_active;
1808				da[5] = gw;
1809				res = dk4gra_eps_dash_out(
1810					bptr, da, 6, (bptr->attr.sv_active / 2.0), erp
1811				);
1812				if (0 == res) { back = 0; }
1813			} break;
1814			case DK4_GRA_LS_DASH_DOT_DOT_DOT : {
1815				da[0] = bptr->attr.sv_active;
1816				da[1] = gw;
1817				da[2] = bptr->attr.lw_active;
1818				da[3] = gw;
1819				da[4] = bptr->attr.lw_active;
1820				da[5] = gw;
1821				da[6] = bptr->attr.lw_active;
1822				da[7] = gw;
1823				res = dk4gra_eps_dash_out(
1824					bptr, da, 8, (bptr->attr.sv_active / 2.0), erp
1825				);
1826				if (0 == res) { back = 0; }
1827			} break;
1828			default : {
1829				dk4gra_eps_kw(bptr, 8, &back, erp);
1830			} break;
1831		}
1832	}
1833	/*	Line cap
1834	*/
1835	if (bptr->attr.lc_active != bptr->attr.lc_requested) {
1836		bptr->attr.lc_active = bptr->attr.lc_requested;
1837		switch (bptr->attr.lc_active) {
1838			case DK4_GRA_LC_ROUNDED : {
1839				lci = 13;
1840			} break;
1841			case DK4_GRA_LC_PROJECTING : {
1842				lci = 14;
1843			} break;
1844			default : {
1845				lci = 12;
1846			} break;
1847		}
1848		dk4gra_eps_kw(bptr, lci, &back, erp);
1849	}
1850	/*	Line join
1851	*/
1852	if (bptr->attr.lj_active != bptr->attr.lj_requested) {
1853		bptr->attr.lj_active = bptr->attr.lj_requested;
1854		switch (bptr->attr.lj_active) {
1855			case DK4_GRA_LJ_ROUNDED : {
1856				lci = 16;
1857			} break;
1858			case DK4_GRA_LJ_BEVELED : {
1859				lci = 17;
1860			} break;
1861			default : {
1862				lci = 15;
1863			} break;
1864		}
1865		dk4gra_eps_kw(bptr, lci, &back, erp);
1866	}
1867	/*	Miter limit, only if line join is mitered
1868	*/
1869	if (DK4_GRA_LJ_MITERED == bptr->attr.lj_active) {
1870		if (
1871			DK4_GRA_EPSILON_MITERLIMIT
1872			< fabs(bptr->attr.ml_active - bptr->attr.ml_requested)
1873		) {
1874			dk4gra_eps_values_and_keyword(
1875				bptr, &(bptr->attr.ml_requested), 1, 50, &back, erp
1876			);
1877			bptr->attr.ml_active = bptr->attr.ml_requested;
1878		}
1879	}
1880	bptr->cont = 1;
1881
1882	finished:
1883	$? "- dk4gra_eps_prepare_stroke %d", back
1884	return back;
1885}
1886
1887
1888
1889int
1890dk4gra_eps_fill(
1891	dk4_gra_t		*gra,
1892	dk4_er_t		*erp
1893)
1894{
1895	dk4_gra_ps_page_t	*bptr;		/* Current page */
1896	int					 back = 0;
1897	$? "+ dk4gra_eps_fill"
1898#if	DK4_USE_ASSERT
1899	assert(NULL != gra);
1900#endif
1901	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1902	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1903		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1904		goto finished;
1905	}
1906	back = 1;
1907	dk4gra_eps_kw(bptr, ((0 != gra->eor) ? (19) : (18)), &back, erp);
1908	bptr->cont = 1;
1909
1910	finished:
1911	$? "- dk4gra_eps_fill %d", back
1912	return back;
1913}
1914
1915
1916
1917int
1918dk4gra_eps_stroke(
1919	dk4_gra_t		*gra,
1920	dk4_er_t		*erp
1921)
1922{
1923	dk4_gra_ps_page_t	*bptr;		/* Current page */
1924	int					 back = 0;
1925	$? "+ dk4gra_eps_stroke"
1926#if	DK4_USE_ASSERT
1927	assert(NULL != gra);
1928#endif
1929	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1930	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1931		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1932		goto finished;
1933	}
1934	back = 1;
1935	dk4gra_eps_kw(bptr, 20, &back, erp);
1936	bptr->cont = 1;
1937
1938	finished:
1939	$? "- dk4gra_eps_stroke %d", back
1940	return back;
1941}
1942
1943
1944
1945int
1946dk4gra_eps_clip(
1947	dk4_gra_t		*gra,
1948	dk4_er_t		*erp
1949)
1950{
1951	dk4_gra_ps_page_t	*bptr;		/* Current page */
1952	int					 back = 0;
1953	$? "+ dk4gra_eps_clip"
1954#if	DK4_USE_ASSERT
1955	assert(NULL != gra);
1956#endif
1957	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1958	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1959		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1960		goto finished;
1961	}
1962	back = 1;
1963	dk4gra_eps_kw(bptr, ((0 != gra->eor) ? (22) : (21)), &back, erp);
1964	bptr->cont = 1;
1965
1966	finished:
1967	$? "- dk4gra_eps_clip %d", back
1968	return back;
1969}
1970
1971
1972
1973int
1974dk4gra_eps_pattern(
1975	dk4_gra_t		*gra,
1976	int				 pn,
1977	double			*xval,
1978	dk4_er_t		*erp
1979)
1980{
1981	dk4_gra_ps_page_t	*bptr;		/* Current page */
1982	const char			*pname;		/* Pattern name */
1983	int					 back = 0;
1984	int					 res;		/* Operation result */
1985	$? "+ dk4gra_eps_pattern"
1986#if	DK4_USE_ASSERT
1987	assert(NULL != gra);
1988#endif
1989	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
1990	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
1991		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1992		goto finished;
1993	}
1994	if ((0 > pn) || (DK4_GRA_PATTERN_MAX < pn)) {
1995		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1996		goto finished;
1997	}
1998	/*	pn checked in previous step
1999	*/
2000	pname = dk4gra_eps_pattern_name((size_t)pn);
2001	if (NULL == pname) {
2002		dk4error_set_simple_error_code(erp, DK4_E_BUG);
2003		goto finished;
2004	}
2005	bptr->patu[pn] = 0x01;
2006
2007	back = 1;
2008
2009	switch (pn) {
2010		case DK4_GRA_PATTERN_30_DEGREE_RIGHT : {
2011			/* ys = yb - (xe - xs) / sqrt(3) */
2012			res = dk4gra_eps_write_pattern_instance(
2013				bptr, xval, 5, pname, erp
2014			); if (0 == res) { back = 0; }
2015		} break;
2016		case DK4_GRA_PATTERN_30_DEGREE_SIEVE : {
2017			/* ys = yb - (xe - xs) / sqrt(3) */
2018			res = dk4gra_eps_write_pattern_instance(
2019				bptr, xval, 5, pname, erp
2020			); if (0 == res) { back = 0; }
2021		} break;
2022		case DK4_GRA_PATTERN_45_DEGREE_LEFT : {
2023			res = dk4gra_eps_write_pattern_instance(
2024				bptr, xval, 5, pname, erp
2025			); if (0 == res) { back = 0; }
2026		} break;
2027		case DK4_GRA_PATTERN_45_DEGREE_RIGHT : {
2028			res = dk4gra_eps_write_pattern_instance(
2029				bptr, xval, 5, pname, erp
2030			); if (0 == res) { back = 0; }
2031		} break;
2032		case DK4_GRA_PATTERN_45_DEGREE_SIEVE : {
2033			res = dk4gra_eps_write_pattern_instance(
2034				bptr, xval, 5, pname, erp
2035			); if (0 == res) { back = 0; }
2036		} break;
2037		case DK4_GRA_PATTERN_HORIZONTAL_BRICKS : {
2038			res = dk4gra_eps_write_pattern_instance(
2039				bptr, xval, 5, pname, erp
2040			); if (0 == res) { back = 0; }
2041		} break;
2042		case DK4_GRA_PATTERN_VERTICAL_BRICKS : {
2043			res = dk4gra_eps_write_pattern_instance(
2044				bptr, xval, 5, pname, erp
2045			); if (0 == res) { back = 0; }
2046		} break;
2047		case DK4_GRA_PATTERN_HORIZONTAL_LINES : {
2048			res = dk4gra_eps_write_pattern_instance(
2049				bptr, xval, 5, pname, erp
2050			); if (0 == res) { back = 0; }
2051		} break;
2052		case DK4_GRA_PATTERN_VERTICAL_LINES : {
2053			res = dk4gra_eps_write_pattern_instance(
2054				bptr, xval, 5, pname, erp
2055			); if (0 == res) { back = 0; }
2056		} break;
2057		case DK4_GRA_PATTERN_HORIZONTAL_VERTICAL_SIEVE : {
2058			res = dk4gra_eps_write_pattern_instance(
2059				bptr, xval, 5, pname, erp
2060			); if (0 == res) { back = 0; }
2061		} break;
2062		case DK4_GRA_PATTERN_HORIZONTAL_SHINGLES_LEFT : {
2063			res = dk4gra_eps_write_pattern_instance(
2064				bptr, xval, 5, pname, erp
2065			); if (0 == res) { back = 0; }
2066		} break;
2067		case DK4_GRA_PATTERN_HORIZONTAL_SHINGLES_RIGHT : {
2068			res = dk4gra_eps_write_pattern_instance(
2069				bptr, xval, 5, pname, erp
2070			); if (0 == res) { back = 0; }
2071		} break;
2072		case DK4_GRA_PATTERN_VERTICAL_SHINGLES_1 : {
2073			res = dk4gra_eps_write_pattern_instance(
2074				bptr, xval, 5, pname, erp
2075			); if (0 == res) { back = 0; }
2076		} break;
2077		case DK4_GRA_PATTERN_VERTICAL_SHINGLES_2 : {
2078			res = dk4gra_eps_write_pattern_instance(
2079				bptr, xval, 5, pname, erp
2080			); if (0 == res) { back = 0; }
2081		} break;
2082		case DK4_GRA_PATTERN_LARGE_FISH_SCALES : {
2083			/* xs xe ys ye dx dy r a1 a2 */
2084			res = dk4gra_eps_write_pattern_instance(
2085				bptr, xval, 9, pname, erp
2086			); if (0 == res) { back = 0; }
2087		} break;
2088		case DK4_GRA_PATTERN_SMALL_FISH_SCALES : {
2089			/* xs xe ys ye dx dy r a1 a2 */
2090			res = dk4gra_eps_write_pattern_instance(
2091				bptr, xval, 9, pname, erp
2092			); if (0 == res) { back = 0; }
2093		} break;
2094		case DK4_GRA_PATTERN_CIRCLES : {
2095			res = dk4gra_eps_write_pattern_instance(
2096				bptr, xval, 5, pname, erp
2097			); if (0 == res) { back = 0; }
2098		} break;
2099		case DK4_GRA_PATTERN_HEXAGONS : {
2100			/* xs xe ys ye dx dy */
2101			res = dk4gra_eps_write_pattern_instance(
2102				bptr, xval, 6, pname, erp
2103			); if (0 == res) { back = 0; }
2104		} break;
2105		case DK4_GRA_PATTERN_OCTAGONS : {
2106			/* xs xe ys ye dx co */
2107			res = dk4gra_eps_write_pattern_instance(
2108				bptr, xval, 6, pname, erp
2109			); if (0 == res) { back = 0; }
2110		} break;
2111		case DK4_GRA_PATTERN_HORIZONTAL_TIRES : {
2112			res = dk4gra_eps_write_pattern_instance(
2113				bptr, xval, 5, pname, erp
2114			); if (0 == res) { back = 0; }
2115		} break;
2116		case DK4_GRA_PATTERN_VERTICAL_TIRES : {
2117			res = dk4gra_eps_write_pattern_instance(
2118				bptr, xval, 5, pname, erp
2119			); if (0 == res) { back = 0; }
2120		} break;
2121		/* DK4_GRA_PATTERN_30_DEGREE_LEFT */
2122		default : {
2123			/* ys = yb - (xe - xs) / sqrt(3) */
2124			res = dk4gra_eps_write_pattern_instance(
2125				bptr, xval, 5, pname, erp
2126			); if (0 == res) { back = 0; }
2127		} break;
2128	}
2129	bptr->cont  = 1;
2130
2131	finished:
2132	$? "- dk4gra_eps_pattern %d", back
2133	return back;
2134}
2135
2136
2137
2138int
2139dk4gra_eps_newpath_moveto(
2140	dk4_gra_t		*gra,
2141	double			 x,
2142	double			 y,
2143	dk4_er_t		*erp
2144)
2145{
2146	double				 val[4];		/* Array for function call */
2147	dk4_gra_ps_page_t	*bptr;			/* Current page */
2148	int					 back = 0;
2149	$? "+ dk4gra_eps_newpath_moveto"
2150#if	DK4_USE_ASSERT
2151	assert(NULL != gra);
2152#endif
2153	$? ". PS: %g %g moveto", x, y
2154	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
2155	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
2156		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2157		goto finished;
2158	}
2159	back = 1;
2160	dk4gra_eps_kw(bptr, 23, &back, erp);
2161	val[0] = x; val[1] = y;
2162	dk4gra_eps_values_and_keyword(bptr, val, 2, 24, &back, erp);
2163	bptr->cont = 1;
2164
2165	finished:
2166	$? "- dk4gra_eps_newpath_moveto %d", back
2167	return back;
2168}
2169
2170
2171
2172int
2173dk4gra_eps_lineto(
2174	dk4_gra_t		*gra,
2175	double			 x,
2176	double			 y,
2177	dk4_er_t		*erp
2178)
2179{
2180	double				 val[4];		/* Array for function call */
2181	dk4_gra_ps_page_t	*bptr;			/* Current page */
2182	int					 back = 0;
2183	$? "+ dk4gra_eps_lineto"
2184#if	DK4_USE_ASSERT
2185	assert(NULL != gra);
2186#endif
2187	$? ". PS: %g %g lineto", x, y
2188	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
2189	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
2190		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2191		goto finished;
2192	}
2193	val[0] = x; val[1] = y;
2194	back  = 1;
2195	dk4gra_eps_values_and_keyword(bptr, val, 2, 25, &back, erp);
2196	bptr->cont = 1;
2197
2198	finished:
2199	$? "- dk4gra_eps_lineto %d", back
2200	return back;
2201}
2202
2203
2204
2205int
2206dk4gra_eps_curveto(
2207	dk4_gra_t		*gra,
2208	double			 xc1,
2209	double			 yc1,
2210	double			 xc2,
2211	double			 yc2,
2212	double			 x,
2213	double			 y,
2214	dk4_er_t		*erp
2215)
2216{
2217	double				 val[8];		/* Array for function call */
2218	dk4_gra_ps_page_t	*bptr;			/* Current page */
2219	int					 back = 0;
2220	$? "+ dk4gra_eps_curveto"
2221#if	DK4_USE_ASSERT
2222	assert(NULL != gra);
2223#endif
2224	$? ". PS: %g %g %g %g %g %g curveto", xc1, yc1, xc2, yc2, x, y
2225	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
2226	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
2227		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2228		goto finished;
2229	}
2230	val[0] = xc1; val[1] = yc1; val[2] = xc2; val[3] = yc2;
2231	val[4] = x;   val[5] = y;
2232	back = 1;
2233	dk4gra_eps_values_and_keyword(bptr, val, 6, 26, &back, erp);
2234	bptr->cont = 1;
2235
2236	finished:
2237	$? "- dk4gra_eps_curveto %d", back
2238	return back;
2239}
2240
2241
2242
2243int
2244dk4gra_eps_closepath(
2245	dk4_gra_t		*gra,
2246	dk4_er_t		*erp
2247)
2248{
2249	dk4_gra_ps_page_t	*bptr;		/* Current page */
2250	int					 back = 0;
2251	$? "+ dk4gra_eps_closepath"
2252#if	DK4_USE_ASSERT
2253	assert(NULL != gra);
2254#endif
2255	$? ". PS: closepath"
2256	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
2257	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
2258		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2259		goto finished;
2260	}
2261	back = 1;
2262	dk4gra_eps_kw(bptr, 27, &back, erp);
2263	bptr->cont = 1;
2264
2265	finished:
2266	$? "- dk4gra_eps_closepath %d", back
2267	return back;
2268}
2269
2270
2271
2272int
2273dk4gra_eps_circle(
2274	dk4_gra_t		*gra,
2275	double			 xc,
2276	double			 yc,
2277	double			 r,
2278	dk4_er_t		*erp
2279)
2280{
2281	double				 val[8];	/* Array for function call */
2282	dk4_gra_ps_page_t	*bptr;		/* Current page */
2283	int					 back = 0;
2284	$? "+ dk4gra_eps_circle x=%g y=%g r=%g", xc, yc, r
2285#if	DK4_USE_ASSERT
2286	assert(NULL != gra);
2287#endif
2288	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
2289	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
2290		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2291		goto finished;
2292	}
2293	back = 1;
2294	dk4gra_eps_kw(bptr, 23, &back, erp);
2295	val[0] = xc + r;
2296	val[1] = yc;
2297	dk4gra_eps_values_and_keyword(bptr, val, 2, 24, &back, erp);
2298	val[0] = xc; val[1] = yc; val[2] = r;
2299	dk4gra_eps_values_and_keyword(bptr, val, 3, 28, &back, erp);
2300	bptr->cont = 1;
2301
2302	finished:
2303	$? "-dk4gra_eps_circle %d", back
2304	return back;
2305}
2306
2307
2308
2309int
2310dk4gra_eps_rectangle(
2311	dk4_gra_t		*gra,
2312	double			 xl,
2313	double			 xr,
2314	double			 yb,
2315	double			 yt,
2316	double			 r,
2317	dk4_er_t		*erp
2318)
2319{
2320	double				 val[8];	/* Array for function call */
2321	dk4_gra_ps_page_t	*bptr;		/* Current page */
2322	int					 back = 0;
2323	$? "+ dk4gra_eps_rectangle x=%g %g y=%g %g r=%g", xl, xr, yb, yt, r
2324#if	DK4_USE_ASSERT
2325	assert(NULL != gra);
2326#endif
2327	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
2328	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
2329		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2330		goto finished;
2331	}
2332
2333	/*	Correct radius if necessary
2334	*/
2335	back = 1;
2336
2337	/*	Output
2338	*/
2339	dk4gra_eps_kw(bptr, 23, &back, erp);
2340	if (0.0 < r) {
2341		val[0] = xl + r;
2342		val[1] = yb;
2343		dk4gra_eps_values_and_keyword(bptr, val, 2, 24, &back, erp);
2344		val[0] = xr - r;
2345		val[1] = yb;
2346		dk4gra_eps_values_and_keyword(bptr, val, 2, 25, &back, erp);
2347		val[0] = xr - (1.0 - KAPPA_4) * r;
2348		val[1] = yb;
2349		val[2] = xr;
2350		val[3] = yb + (1.0 - KAPPA_4) * r;
2351		val[4] = xr;
2352		val[5] = yb + r;
2353		dk4gra_eps_values_and_keyword(bptr, val, 6, 26, &back, erp);
2354		val[0] = xr;
2355		val[1] = yt - r;
2356		dk4gra_eps_values_and_keyword(bptr, val, 2, 25, &back, erp);
2357		val[0] = xr;
2358		val[1] = yt - (1.0 - KAPPA_4) * r;
2359		val[2] = xr - (1.0 - KAPPA_4) * r;
2360		val[3] = yt;
2361		val[4] = xr - r;
2362		val[5] = yt;
2363		dk4gra_eps_values_and_keyword(bptr, val, 6, 26, &back, erp);
2364		val[0] = xl + r;
2365		val[1] = yt;
2366		dk4gra_eps_values_and_keyword(bptr, val, 2, 25, &back, erp);
2367		val[0] = xl + (1.0 - KAPPA_4) * r;
2368		val[1] = yt;
2369		val[2] = xl;
2370		val[3] = yt - (1.0 - KAPPA_4) * r;
2371		val[4] = xl;
2372		val[5] = yt - r;
2373		dk4gra_eps_values_and_keyword(bptr, val, 6, 26, &back, erp);
2374		val[0] = xl;
2375		val[1] = yb + r;
2376		dk4gra_eps_values_and_keyword(bptr, val, 2, 25, &back, erp);
2377		val[0] = xl;
2378		val[1] = yb + (1.0 - KAPPA_4) * r;
2379		val[2] = xl + (1.0 - KAPPA_4) * r;
2380		val[3] = yb;
2381		val[4] = xl + r;
2382		val[5] = yb;
2383		dk4gra_eps_values_and_keyword(bptr, val, 6, 26, &back, erp);
2384		dk4gra_eps_kw(bptr, 27, &back, erp);
2385	}
2386	else {
2387		val[0] = xl; val[1] = yb;
2388		dk4gra_eps_values_and_keyword(bptr, val, 2, 24, &back, erp);
2389		val[0] = xr; val[1] = yb;
2390		dk4gra_eps_values_and_keyword(bptr, val, 2, 25, &back, erp);
2391		val[0] = xr; val[1] = yt;
2392		dk4gra_eps_values_and_keyword(bptr, val, 2, 25, &back, erp);
2393		val[0] = xl; val[1] = yt;
2394		dk4gra_eps_values_and_keyword(bptr, val, 2, 25, &back, erp);
2395		dk4gra_eps_kw(bptr, 27, &back, erp);
2396	}
2397	bptr->cont = 1;
2398
2399	finished:
2400	$? "- dk4gra_eps_rectangle %d", back
2401	return back;
2402}
2403
2404
2405
2406int
2407dk4gra_eps_arc(
2408	dk4_gra_t		*gra,
2409	double			 xc,
2410	double			 yc,
2411	double			 ra,
2412	double			 start,
2413	double			 end,
2414	int				 cl,
2415	dk4_er_t		*erp
2416)
2417{
2418	double				 val[8];	/* Array for function call */
2419	dk4_gra_ps_page_t	*bptr;		/* Current page */
2420	double				 xstart;	/* Start X coordinate */
2421	double				 ystart;	/* Start Y coordinate */
2422	int					 back = 0;
2423	$? "+ dk4gra_eps_arc x=%g y=%g r=%g a=%g b=%g cl=%d",xc,yc,ra,start,end,cl
2424#if	DK4_USE_ASSERT
2425	assert(NULL != gra);
2426#endif
2427	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
2428	if ((NULL == bptr->memstrm) || (0 != bptr->spip)) {
2429		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2430		goto finished;
2431	}
2432	xstart = (M_PI * start) / 180.0;
2433	ystart = xstart;
2434	xstart = xc + ra * cos(xstart);
2435	ystart = yc + ra * sin(ystart);
2436	back = 1;
2437	dk4gra_eps_kw(bptr, 23, &back, erp);
2438	val[0] = xstart; val[1] = ystart;
2439	dk4gra_eps_values_and_keyword(bptr, val, 2, 24, &back, erp);
2440	val[0] = xc; val[1] = yc; val[2] = ra; val[3] = start; val[4] = end;
2441	dk4gra_eps_values_and_keyword(bptr, val, 5, 29, &back, erp);
2442	if (0 != cl) {
2443		val[0] = xc; val[1] = yc;
2444		dk4gra_eps_values_and_keyword(bptr, val, 2, 25, &back, erp);
2445		dk4gra_eps_kw(bptr, 27, &back, erp);
2446	}
2447	bptr->cont = 1;
2448
2449	finished:
2450	$? "- dk4gra_eps_arc %d", back
2451	return back;
2452}
2453
2454
2455
2456void
2457dk4gra_eps_save_attributes(
2458	dk4_gra_t	*gra
2459)
2460{
2461	dk4_gra_ps_page_t	*bptr;	/* Current page */
2462#if	DK4_USE_ASSERT
2463	assert(NULL != gra);
2464#endif
2465	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
2466	dk4mem_cpy(
2467		&(bptr->catt),
2468		&(bptr->attr),
2469		sizeof(dk4gra_attributes_t),
2470		NULL
2471	);
2472}
2473
2474
2475
2476void
2477dk4gra_eps_restore_attributes(
2478	dk4_gra_t	*gra
2479)
2480{
2481	dk4_gra_ps_page_t	*bptr;	/* Current page */
2482#if	DK4_USE_ASSERT
2483	assert(NULL != gra);
2484#endif
2485	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
2486	dk4mem_cpy(
2487		&(bptr->attr),
2488		&(bptr->catt),
2489		sizeof(dk4gra_attributes_t),
2490		NULL
2491	);
2492}
2493
2494
2495
2496void
2497dk4gra_eps_reset_attributes(
2498	dk4_gra_t	*gra
2499)
2500{
2501	dk4_gra_ps_page_t	*bptr;	/* Current page */
2502#if	DK4_USE_ASSERT
2503	assert(NULL != gra);
2504#endif
2505	bptr = (dk4_gra_ps_page_t *)(gra->curpg);
2506	dk4gratool_reset_active_attributes(&(bptr->attr));
2507}
2508
2509/* vim: set ai sw=4 ts=4 : */
2510