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