Commit | Line | Data |
---|---|---|
769b15cf WJ |
1 | /* Copyright (C) 1989, 1990 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
19 | ||
20 | /* gspaint.c */ | |
21 | /* Painting procedures for GhostScript library */ | |
22 | #include "gx.h" | |
23 | #include "gserrors.h" | |
24 | #include "gxfixed.h" | |
25 | #include "gxmatrix.h" /* for gs_state */ | |
26 | #include "gspaint.h" | |
27 | #include "gzpath.h" | |
28 | #include "gzstate.h" | |
29 | #include "gzdevice.h" | |
30 | #include "gzcolor.h" | |
31 | #include "gxcpath.h" | |
32 | #include "gxdevmem.h" | |
33 | #include "gximage.h" | |
34 | ||
35 | /* Erase the page */ | |
36 | int | |
37 | gs_erasepage(gs_state *pgs) | |
38 | { device *pdev = pgs->device; | |
39 | gx_device *dev = pdev->info; | |
40 | (*dev->procs->fill_rectangle)(dev, 0, 0, dev->width, dev->height, pdev->white); | |
41 | return 0; | |
42 | } | |
43 | ||
44 | /* Fill using the winding number rule */ | |
45 | int | |
46 | gs_fill(gs_state *pgs) | |
47 | { return gs_fill_adjust(pgs, (fixed)0); | |
48 | } | |
49 | /* This is a hack, see gx_fill_path and gs_type1_interpret. */ | |
50 | int | |
51 | gs_fill_adjust(gs_state *pgs, fixed adjust) | |
52 | { int code; | |
53 | /* If we're inside a charpath, just merge the current path */ | |
54 | /* into the parent's path. */ | |
55 | if ( pgs->in_charpath ) | |
56 | code = gx_path_add_path(pgs->saved->path, pgs->path); | |
57 | else | |
58 | { gx_color_load(pgs->dev_color, pgs); | |
59 | code = gx_fill_path(pgs->path, pgs->dev_color, pgs, | |
60 | gx_rule_winding_number, adjust); | |
61 | if ( !code ) gs_newpath(pgs); | |
62 | } | |
63 | return code; | |
64 | } | |
65 | ||
66 | /* Fill using the even/odd rule */ | |
67 | int | |
68 | gs_eofill(gs_state *pgs) | |
69 | { int code; | |
70 | /* If we're inside a charpath, just merge the current path */ | |
71 | /* into the parent's path. */ | |
72 | if ( pgs->in_charpath ) | |
73 | code = gx_path_add_path(pgs->saved->path, pgs->path); | |
74 | else | |
75 | { gx_color_load(pgs->dev_color, pgs); | |
76 | code = gx_fill_path(pgs->path, pgs->dev_color, pgs, | |
77 | gx_rule_even_odd, (fixed)0); | |
78 | if ( !code ) gs_newpath(pgs); | |
79 | } | |
80 | return code; | |
81 | } | |
82 | ||
83 | /* Stroke the current path */ | |
84 | int | |
85 | gs_stroke(gs_state *pgs) | |
86 | { int code; | |
87 | /* If we're inside a charpath, just merge the current path */ | |
88 | /* into the parent's path. */ | |
89 | if ( pgs->in_charpath ) | |
90 | code = gx_path_add_path(pgs->saved->path, pgs->path); | |
91 | else | |
92 | { gx_color_load(pgs->dev_color, pgs); | |
93 | code = gx_stroke_fill(pgs->path, pgs); | |
94 | if ( !code ) gs_newpath(pgs); | |
95 | } | |
96 | return code; | |
97 | } | |
98 | ||
99 | /* Compute the stroked outline of the current path */ | |
100 | int | |
101 | gs_strokepath(gs_state *pgs) | |
102 | { gx_path spath; | |
103 | int code; | |
104 | gx_path_init(&spath, &pgs->memory_procs); | |
105 | code = gx_stroke_add(pgs->path, &spath, pgs); | |
106 | if ( code < 0 ) return code; | |
107 | gx_path_release(pgs->path); | |
108 | *pgs->path = spath; | |
109 | return 0; | |
110 | } | |
111 | ||
112 | /* Render a sampled image */ | |
113 | int | |
114 | gs_colorimage(gs_state *pgs, int width, int height, int bps, int spp, | |
115 | gs_matrix *pmat, byte *data) | |
116 | { gs_image_enum *penum = | |
117 | (gs_image_enum *)gs_malloc(1, gs_image_enum_sizeof, "gs_[color]image"); | |
118 | int code; | |
119 | if ( penum == 0 ) return_error(gs_error_VMerror); | |
120 | if ( (code = gs_image_init(penum, pgs, width, height, bps, spp, pmat)) < 0 ) | |
121 | { gs_free((char *)penum, 1, gs_image_enum_sizeof, "gs_[color]image"); | |
122 | return code; | |
123 | } | |
124 | if ( spp > 0 ) | |
125 | { uint size = | |
126 | (((uint)width * bps * spp + 7) >> 3) * (uint)height; | |
127 | code = gs_image_next(penum, data, size); | |
128 | } | |
129 | else | |
130 | { /* Deliver the colors separately */ | |
131 | uint plane_size = | |
132 | (((uint)width * bps + 7) >> 3) * (uint)height; | |
133 | byte *plane_data = data; | |
134 | int count = spp; | |
135 | do | |
136 | { code = gs_image_next(penum, plane_data, plane_size); | |
137 | if ( code < 0 ) return code; | |
138 | plane_data += plane_size; | |
139 | } | |
140 | while ( ++count ); | |
141 | } | |
142 | gs_free((char *)penum, 1, gs_image_enum_sizeof, "gs_[color]image"); | |
143 | return (code < 0 ? code : 0); | |
144 | } | |
145 | int | |
146 | gs_image(gs_state *pgs, int width, int height, int bps, | |
147 | gs_matrix *pmat, byte *data) | |
148 | { return gs_colorimage(pgs, width, height, bps, 1, pmat, data); | |
149 | } | |
150 | ||
151 | /* Render a mask */ | |
152 | int | |
153 | gs_imagemask(gs_state *pgs, int width, int height, int invert, | |
154 | gs_matrix *pmat, byte *data, int adjust) | |
155 | { gs_image_enum *penum = | |
156 | (gs_image_enum *)gs_malloc(1, gs_image_enum_sizeof, "gs_imagemask"); | |
157 | int code; | |
158 | uint size = (((uint)width + 7) >> 3) * (uint)height; | |
159 | if ( penum == 0 ) return_error(gs_error_VMerror); | |
160 | if ( (code = gs_imagemask_init(penum, pgs, width, height, invert, pmat, adjust)) < 0 ) | |
161 | { gs_free((char *)penum, 1, gs_image_enum_sizeof, "gs_imagemask"); | |
162 | return code; | |
163 | } | |
164 | code = gs_image_next(penum, data, size); | |
165 | gs_free((char *)penum, 1, gs_image_enum_sizeof, "gs_imagemask"); | |
166 | return (code < 0 ? code : 0); | |
167 | } |