1 /* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: zchar32.c,v 1.5 2004/08/19 19:33:09 stefan Exp $ */
18 /* Type 32 font glyph operators */
19 #include "ghost.h"
20 #include "oper.h"
21 #include "gsccode.h" /* for gxfont.h */
22 #include "gsmatrix.h"
23 #include "gsutil.h"
24 #include "gxfixed.h"
25 #include "gxfont.h"
26 #include "gxfcache.h"
27 #include "ifont.h"
28 #include "igstate.h"
29 #include "store.h"
30
31 /* ([wx wy llx lly urx ury] | [w0x w0y llx lly urx ury w1x w1y vx vy]) */
32 /* <bitmap> <cid> <type32font> <str22> .makeglyph32 <<same with substr>> */
33 private int
zmakeglyph32(i_ctx_t * i_ctx_p)34 zmakeglyph32(i_ctx_t *i_ctx_p)
35 {
36 os_ptr op = osp;
37 bool long_form;
38 uint msize;
39 double metrics[10];
40 int wx, llx, lly, urx, ury;
41 int width, height, raster;
42 gs_font *pfont;
43 int code;
44 byte *str;
45
46 check_array(op[-4]);
47 msize = r_size(op - 4);
48 switch (msize) {
49 case 10:
50 long_form = true;
51 break;
52 case 6:
53 long_form = false;
54 break;
55 default:
56 return_error(e_rangecheck);
57 }
58 code = num_params(op[-4].value.refs + msize - 1, msize, metrics);
59 if (code < 0)
60 return code;
61 if (~code & 0x3c) /* check llx .. ury for integers */
62 return_error(e_typecheck);
63 check_read_type(op[-3], t_string);
64 llx = (int)metrics[2];
65 lly = (int)metrics[3];
66 urx = (int)metrics[4];
67 ury = (int)metrics[5];
68 width = urx - llx;
69 height = ury - lly;
70 raster = (width + 7) >> 3;
71 if (width < 0 || height < 0 || r_size(op - 3) != raster * height)
72 return_error(e_rangecheck);
73 check_int_leu(op[-2], 65535);
74 code = font_param(op - 1, &pfont);
75 if (code < 0)
76 return code;
77 if (pfont->FontType != ft_CID_bitmap)
78 return_error(e_invalidfont);
79 check_write_type(*op, t_string);
80 if (r_size(op) < 22)
81 return_error(e_rangecheck);
82 str = op->value.bytes;
83 if (long_form || metrics[0] != (wx = (int)metrics[0]) ||
84 metrics[1] != 0 || height == 0 ||
85 ((wx | width | height | (llx + 128) | (lly + 128)) & ~255) != 0
86 ) {
87 /* Use the long form. */
88 int i, n = (long_form ? 10 : 6);
89
90 str[0] = 0;
91 str[1] = long_form;
92 for (i = 0; i < n; ++i) {
93 int v = (int)metrics[i]; /* no floating point widths yet */
94
95 str[2 + 2 * i] = (byte)(v >> 8);
96 str[2 + 2 * i + 1] = (byte)v;
97 }
98 r_set_size(op, 2 + n * 2);
99 } else {
100 /* Use the short form. */
101 str[0] = (byte)width;
102 str[1] = (byte)height;
103 str[2] = (byte)wx;
104 str[3] = (byte)(llx + 128);
105 str[4] = (byte)(lly + 128);
106 r_set_size(op, 5);
107 }
108 return code;
109 }
110
111 /* <cid_min> <cid_max> <type32font> .removeglyphs - */
112 typedef struct {
113 gs_glyph cid_min, cid_max;
114 gs_font *font;
115 } font_cid_range_t;
116 private bool
select_cid_range(const gs_memory_t * mem,cached_char * cc,void * range_ptr)117 select_cid_range(const gs_memory_t *mem, cached_char * cc, void *range_ptr)
118 {
119 const font_cid_range_t *range = range_ptr;
120
121 return (cc->code >= range->cid_min &&
122 cc->code <= range->cid_max &&
123 cc->pair->font == range->font);
124 }
125 private int
zremoveglyphs(i_ctx_t * i_ctx_p)126 zremoveglyphs(i_ctx_t *i_ctx_p)
127 {
128 os_ptr op = osp;
129 int code;
130 font_cid_range_t range;
131
132 check_int_leu(op[-2], 65535);
133 check_int_leu(op[-1], 65535);
134 code = font_param(op, &range.font);
135 if (code < 0)
136 return code;
137 if (range.font->FontType != ft_CID_bitmap)
138 return_error(e_invalidfont);
139 range.cid_min = gs_min_cid_glyph + op[-2].value.intval;
140 range.cid_max = gs_min_cid_glyph + op[-1].value.intval;
141 gx_purge_selected_cached_chars(range.font->dir, select_cid_range,
142 &range);
143 pop(3);
144 return 0;
145 }
146
147 /* <str5/14/22> .getmetrics32 <width> <height> <wx> ... <ury> 5/14 */
148 /* <str5/14/22> .getmetrics32 <width> <height> <w0x> ... <vy> 22 */
149 private int
zgetmetrics32(i_ctx_t * i_ctx_p)150 zgetmetrics32(i_ctx_t *i_ctx_p)
151 {
152 os_ptr op = osp;
153 const byte *data;
154 uint size;
155 int i, n = 6;
156 os_ptr wop;
157
158 check_read_type(*op, t_string);
159 data = op->value.const_bytes;
160 size = r_size(op);
161 if (size < 5)
162 return_error(e_rangecheck);
163 if (data[0]) {
164 /* Short form. */
165 int llx = (int)data[3] - 128, lly = (int)data[4] - 128;
166
167 n = 6;
168 size = 5;
169 push(8);
170 make_int(op - 6, data[2]); /* wx */
171 make_int(op - 5, 0); /* wy */
172 make_int(op - 4, llx);
173 make_int(op - 3, lly);
174 make_int(op - 2, llx + data[0]); /* urx */
175 make_int(op - 1, lly + data[1]); /* ury */
176 } else {
177 if (data[1]) {
178 /* Long form, both WModes. */
179 if (size < 22)
180 return_error(e_rangecheck);
181 n = 10;
182 size = 22;
183 } else {
184 /* Long form, WMode = 0 only. */
185 if (size < 14)
186 return_error(e_rangecheck);
187 n = 6;
188 size = 14;
189 }
190 push(2 + n);
191 for (i = 0; i < n; ++i)
192 make_int(op - n + i,
193 ((int)((data[2 * i + 2] << 8) + data[2 * i + 3]) ^ 0x8000)
194 - 0x8000);
195 }
196 wop = op - n;
197 make_int(wop - 2, wop[4].value.intval - wop[2].value.intval);
198 make_int(wop - 1, wop[5].value.intval - wop[3].value.intval);
199 make_int(op, size);
200 return 0;
201 }
202
203 /* ------ Initialization procedure ------ */
204
205 const op_def zchar32_op_defs[] =
206 {
207 {"1.getmetrics32", zgetmetrics32},
208 {"4.makeglyph32", zmakeglyph32},
209 {"3.removeglyphs", zremoveglyphs},
210 op_def_end(0)
211 };
212