xref: /plan9/sys/src/cmd/gs/src/zchar32.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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