1 /* Copyright (C) 1997, 1998, 1999 artofcode LLC. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2 of the License, or (at your
6 option) any later version.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along
14 with this program; if not, write to the Free Software Foundation, Inc.,
15 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16
17 */
18
19 /*$Id: zchar32.c,v 1.2.6.1.2.1 2003/01/17 00:49:05 giles Exp $ */
20 /* Type 32 font glyph operators */
21 #include "ghost.h"
22 #include "oper.h"
23 #include "gsccode.h" /* for gxfont.h */
24 #include "gsmatrix.h"
25 #include "gsutil.h"
26 #include "gxfixed.h"
27 #include "gxfont.h"
28 #include "gxfcache.h"
29 #include "ifont.h"
30 #include "igstate.h"
31 #include "store.h"
32
33 /* ([wx wy llx lly urx ury] | [w0x w0y llx lly urx ury w1x w1y vx vy]) */
34 /* <bitmap> <cid> <type32font> <str22> .makeglyph32 <<same with substr>> */
35 private int
zmakeglyph32(i_ctx_t * i_ctx_p)36 zmakeglyph32(i_ctx_t *i_ctx_p)
37 {
38 os_ptr op = osp;
39 bool long_form;
40 uint msize;
41 double metrics[10];
42 int wx, llx, lly, urx, ury;
43 int width, height, raster;
44 gs_font *pfont;
45 int code;
46 byte *str;
47
48 check_array(op[-4]);
49 msize = r_size(op - 4);
50 switch (msize) {
51 case 10:
52 long_form = true;
53 break;
54 case 6:
55 long_form = false;
56 break;
57 default:
58 return_error(e_rangecheck);
59 }
60 code = num_params(op[-4].value.refs + msize - 1, msize, metrics);
61 if (code < 0)
62 return code;
63 if (~code & 0x3c) /* check llx .. ury for integers */
64 return_error(e_typecheck);
65 check_read_type(op[-3], t_string);
66 llx = (int)metrics[2];
67 lly = (int)metrics[3];
68 urx = (int)metrics[4];
69 ury = (int)metrics[5];
70 width = urx - llx;
71 height = ury - lly;
72 raster = (width + 7) >> 3;
73 if (width < 0 || height < 0 || r_size(op - 3) != raster * height)
74 return_error(e_rangecheck);
75 check_int_leu(op[-2], 65535);
76 code = font_param(op - 1, &pfont);
77 if (code < 0)
78 return code;
79 if (pfont->FontType != ft_CID_bitmap)
80 return_error(e_invalidfont);
81 check_write_type(*op, t_string);
82 if (r_size(op) < 22)
83 return_error(e_rangecheck);
84 str = op->value.bytes;
85 if (long_form || metrics[0] != (wx = (int)metrics[0]) ||
86 metrics[1] != 0 || height == 0 ||
87 ((wx | width | height | (llx + 128) | (lly + 128)) & ~255) != 0
88 ) {
89 /* Use the long form. */
90 int i, n = (long_form ? 10 : 6);
91
92 str[0] = 0;
93 str[1] = long_form;
94 for (i = 0; i < n; ++i) {
95 int v = (int)metrics[i]; /* no floating point widths yet */
96
97 str[2 + 2 * i] = (byte)(v >> 8);
98 str[2 + 2 * i + 1] = (byte)v;
99 }
100 r_set_size(op, 2 + n * 2);
101 } else {
102 /* Use the short form. */
103 str[0] = (byte)width;
104 str[1] = (byte)height;
105 str[2] = (byte)wx;
106 str[3] = (byte)(llx + 128);
107 str[4] = (byte)(lly + 128);
108 r_set_size(op, 5);
109 }
110 return code;
111 }
112
113 /* <cid_min> <cid_max> <type32font> .removeglyphs - */
114 typedef struct {
115 gs_glyph cid_min, cid_max;
116 gs_font *font;
117 } font_cid_range_t;
118 private bool
select_cid_range(cached_char * cc,void * range_ptr)119 select_cid_range(cached_char * cc, void *range_ptr)
120 {
121 const font_cid_range_t *range = range_ptr;
122
123 return (cc->code >= range->cid_min &&
124 cc->code <= range->cid_max &&
125 cc->pair->font == range->font);
126 }
127 private int
zremoveglyphs(i_ctx_t * i_ctx_p)128 zremoveglyphs(i_ctx_t *i_ctx_p)
129 {
130 os_ptr op = osp;
131 int code;
132 font_cid_range_t range;
133
134 check_int_leu(op[-2], 65535);
135 check_int_leu(op[-1], 65535);
136 code = font_param(op, &range.font);
137 if (code < 0)
138 return code;
139 if (range.font->FontType != ft_CID_bitmap)
140 return_error(e_invalidfont);
141 range.cid_min = gs_min_cid_glyph + op[-2].value.intval;
142 range.cid_max = gs_min_cid_glyph + op[-1].value.intval;
143 gx_purge_selected_cached_chars(range.font->dir, select_cid_range,
144 &range);
145 pop(3);
146 return 0;
147 }
148
149 /* <str5/14/22> .getmetrics32 <width> <height> <wx> ... <ury> 5/14 */
150 /* <str5/14/22> .getmetrics32 <width> <height> <w0x> ... <vy> 22 */
151 private int
zgetmetrics32(i_ctx_t * i_ctx_p)152 zgetmetrics32(i_ctx_t *i_ctx_p)
153 {
154 os_ptr op = osp;
155 const byte *data;
156 uint size;
157 int i, n = 6;
158 os_ptr wop;
159
160 check_read_type(*op, t_string);
161 data = op->value.const_bytes;
162 size = r_size(op);
163 if (size < 5)
164 return_error(e_rangecheck);
165 if (data[0]) {
166 /* Short form. */
167 int llx = (int)data[3] - 128, lly = (int)data[4] - 128;
168
169 n = 6;
170 size = 5;
171 push(8);
172 make_int(op - 6, data[2]); /* wx */
173 make_int(op - 5, 0); /* wy */
174 make_int(op - 4, llx);
175 make_int(op - 3, lly);
176 make_int(op - 2, llx + data[0]); /* urx */
177 make_int(op - 1, lly + data[1]); /* ury */
178 } else {
179 if (data[1]) {
180 /* Long form, both WModes. */
181 if (size < 22)
182 return_error(e_rangecheck);
183 n = 10;
184 size = 22;
185 } else {
186 /* Long form, WMode = 0 only. */
187 if (size < 14)
188 return_error(e_rangecheck);
189 n = 6;
190 size = 14;
191 }
192 push(2 + n);
193 for (i = 0; i < n; ++i)
194 make_int(op - n + i,
195 ((int)((data[2 * i + 2] << 8) + data[2 * i + 3]) ^ 0x8000)
196 - 0x8000);
197 }
198 wop = op - n;
199 make_int(wop - 2, wop[4].value.intval - wop[2].value.intval);
200 make_int(wop - 1, wop[5].value.intval - wop[3].value.intval);
201 make_int(op, size);
202 return 0;
203 }
204
205 /* ------ Initialization procedure ------ */
206
207 const op_def zchar32_op_defs[] =
208 {
209 {"1.getmetrics32", zgetmetrics32},
210 {"4.makeglyph32", zmakeglyph32},
211 {"3.removeglyphs", zremoveglyphs},
212 op_def_end(0)
213 };
214