summaryrefslogtreecommitdiff
path: root/gs/src/gschar.c
blob: 29d6adb8fefa8c66b07cc148c81365eb6f464a2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/* Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.

   This software is licensed to a single customer by Artifex Software Inc.
   under the terms of a specific OEM agreement.
 */

/*$RCSfile$ $Revision$ */
/* Character writing "operators" for Ghostscript library */
#include "gx.h"
#include "gserrors.h"
#include "gsstruct.h"
#include "gsmatrix.h"		/* for gscoord.h */
#include "gscoord.h"		/* for gs_idtransform */
#include "gzstate.h"
#include "gxdevice.h"
#include "gxdevmem.h"
#include "gxchar.h"
#include "gxfont.h"

/* Forward declarations */
private int show_n_begin(P4(gs_show_enum *penum, gs_state *pgs, int code,
			    gs_text_enum_t *pte));

/* Structure descriptors */
extern_st(st_gs_show_enum);

/* ------ String writing operators ------ */

/* Free the contents of a show enumerator. */
void
gs_show_enum_release(gs_show_enum * penum, gs_memory_t * emem)
{
    if (penum->text.operation)	/* otherwise, never initialized */
	penum->procs->release((gs_text_enum_t *)penum, "gs_show_enum_release");
    if (emem != 0)
	gs_free_object(emem, penum, "gs_show_enum_release");
}

/* show[_n] */
int
gs_show_n_init(gs_show_enum * penum, gs_state * pgs,
	       const char *str, uint size)
{
    gs_text_enum_t *pte;
    int code = gs_show_begin(pgs, (const byte *)str, size, pgs->memory, &pte);

    return show_n_begin(penum, pgs, code, pte);
}

/* ashow[_n] */
int
gs_ashow_n_init(gs_show_enum * penum, gs_state * pgs,
		floatp ax, floatp ay, const char *str, uint size)
{
    gs_text_enum_t *pte;
    int code = gs_ashow_begin(pgs, ax, ay, (const byte *)str, size,
			      pgs->memory, &pte);

    return show_n_begin(penum, pgs, code, pte);
}

/* widthshow[_n] */
int
gs_widthshow_n_init(gs_show_enum * penum, gs_state * pgs,
		    floatp cx, floatp cy, gs_char chr,
		    const char *str, uint size)
{
    gs_text_enum_t *pte;
    int code = gs_widthshow_begin(pgs, cx, cy, chr, (const byte *)str, size,
				  pgs->memory, &pte);

    return show_n_begin(penum, pgs, code, pte);
}

/* awidthshow[_n] */
int
gs_awidthshow_n_init(gs_show_enum * penum, gs_state * pgs,
		     floatp cx, floatp cy, gs_char chr, floatp ax, floatp ay,
		     const char *str, uint size)
{
    gs_text_enum_t *pte;
    int code = gs_awidthshow_begin(pgs, cx, cy, chr, ax, ay,
				   (const byte *)str, size, pgs->memory, &pte);

    return show_n_begin(penum, pgs, code, pte);
}

/* kshow[_n] */
int
gs_kshow_n_init(gs_show_enum * penum,
		gs_state * pgs, const char *str, uint size)
{
    gs_text_enum_t *pte;
    int code;

    switch (pgs->font->FontType) {
    case ft_composite:
    case ft_CID_encrypted:
    case ft_CID_user_defined:
    case ft_CID_TrueType:
    case ft_CID_bitmap:
	return_error(gs_error_invalidfont);
    default:
	break;
    }
    code = gs_kshow_begin(pgs, (const byte *)str, size, pgs->memory, &pte);
    return show_n_begin(penum, pgs, code, pte);
}

/* xyshow[_n] */
int
gs_xyshow_n_init(gs_show_enum * penum,
		 gs_state * pgs, const char *str, uint size)
{
    gs_text_enum_t *pte;
    int code = gs_xyshow_begin(pgs, (const byte *)str, size, NULL, NULL, 0,
			       pgs->memory, &pte);

    return show_n_begin(penum, pgs, code, pte);
}

/* glyphshow */
int
gs_glyphshow_init(gs_show_enum * penum, gs_state * pgs, gs_glyph glyph)
{
    gs_text_enum_t *pte;
    int code = gs_glyphshow_begin(pgs, glyph, pgs->memory, &pte);

    return show_n_begin(penum, pgs, code, pte);
}
int
gs_glyphpath_init(gs_show_enum * penum, gs_state * pgs, gs_glyph glyph,
		  bool stroke_path)
{
    gs_text_enum_t *pte;
    int code = gs_glyphpath_begin(pgs, glyph, stroke_path, pgs->memory, &pte);

    return show_n_begin(penum, pgs, code, pte);
}

/* ------ Related operators ------ */

/* cshow[_n] */
int
gs_cshow_n_init(gs_show_enum * penum,
		gs_state * pgs, const char *str, uint size)
{
    gs_text_enum_t *pte;
    int code = gs_cshow_begin(pgs, (const byte *)str, size, pgs->memory, &pte);

    return show_n_begin(penum, pgs, code, pte);
}

/* stringwidth[_n] */
int
gs_stringwidth_n_init(gs_show_enum * penum, gs_state * pgs,
		      const char *str, uint size)
{
    gs_text_enum_t *pte;
    int code = gs_stringwidth_begin(pgs, (const byte *)str, size,
				    pgs->memory, &pte);

    return show_n_begin(penum, pgs, code, pte);
}

/* charpath[_n] */
int
gs_charpath_n_init(gs_show_enum * penum, gs_state * pgs,
		   const char *str, uint size, bool stroke_path)
{
    gs_text_enum_t *pte;
    int code = gs_charpath_begin(pgs, (const byte *)str, size, stroke_path,
				 pgs->memory, &pte);

    return show_n_begin(penum, pgs, code, pte);
}

/* charboxpath[_n] */
int
gs_charboxpath_n_init(gs_show_enum * penum, gs_state * pgs,
		      const char *str, uint size, bool use_boxes)
{
    gs_text_enum_t *pte;
    int code = gs_charboxpath_begin(pgs, (const byte *)str, size, use_boxes,
				    pgs->memory, &pte);

    return show_n_begin(penum, pgs, code, pte);
}

/* ------ Width/cache operators ------ */

/* setcachedevice */
/* The elements of pw are: wx, wy, llx, lly, urx, ury. */
/* Note that this returns 1 if we just set up the cache device. */
int
gs_setcachedevice_double(gs_show_enum *penum, gs_state *pgs, const double *pw)
{
    if (penum->pgs != pgs)
	return_error(gs_error_rangecheck);
    return gs_text_setcachedevice((gs_text_enum_t *)penum, pw);
}
/* The _float procedure is strictly for backward compatibility. */
int
gs_setcachedevice_float(gs_show_enum * penum, gs_state * pgs, const float *pw)
{
    double w[6];
    int i;

    for (i = 0; i < 6; ++i)
	w[i] = pw[i];
    return gs_setcachedevice_double(penum, pgs, w);
}

/* setcachedevice2 */
/* The elements of pw2 are: w0x, w0y, llx, lly, urx, ury, w1x, w1y, vx, vy. */
/* Note that this returns 1 if we just set up the cache device. */
int
gs_setcachedevice2_double(gs_show_enum * penum, gs_state * pgs,
			  const double *pw2)
{
    if (penum->pgs != pgs)
	return_error(gs_error_rangecheck);
    return gs_text_setcachedevice2((gs_text_enum_t *)penum, pw2);
}
/* The _float procedure is strictly for backward compatibility. */
int
gs_setcachedevice2_float(gs_show_enum * penum, gs_state * pgs, const float *pw2)
{
    double w2[10];
    int i;

    for (i = 0; i < 10; ++i)
	w2[i] = pw2[i];
    return gs_setcachedevice2_double(penum, pgs, w2);
}

/* setcharwidth */
/* Note that this returns 1 if the current show operation is */
/* non-displaying (stringwidth or cshow). */
int
gs_setcharwidth(gs_show_enum * penum, gs_state * pgs,
		floatp wx, floatp wy)
{
    double w[2];

    if (penum->pgs != pgs)
	return_error(gs_error_rangecheck);
    w[0] = wx, w[1] = wy;
    return gs_text_setcharwidth((gs_text_enum_t *)penum, w);
}

/* ------ Enumerator ------ */

/* Do the next step of a show (or stringwidth) operation */
int
gs_show_next(gs_show_enum * penum)
{
    return gs_text_process((gs_text_enum_t *)penum);
}

/*
 * Return true if we only need the width from the rasterizer
 * and can short-circuit the full rendering of the character,
 * false if we need the actual character bits.
 */
bool
gs_show_width_only(const gs_show_enum * penum)
{
    return gs_text_is_width_only((const gs_text_enum_t *)penum);
}

/* ------ Accessors ------ */

/* Return the current character for rendering. */
gs_char
gs_show_current_char(const gs_show_enum * penum)
{
    return gs_text_current_char((const gs_text_enum_t *)penum);
}

/* Return the current glyph for rendering. */
gs_glyph
gs_show_current_glyph(const gs_show_enum * penum)
{
    return gs_text_current_glyph((const gs_text_enum_t *)penum);
}

/* Return the width of the just-enumerated character (for cshow). */
int
gs_show_current_width(const gs_show_enum * penum, gs_point * ppt)
{
    return gs_text_current_width((const gs_text_enum_t *)penum, ppt);
}

/* Return the just-displayed character for kerning. */
gs_char
gs_kshow_previous_char(const gs_show_enum * penum)
{
    return gs_text_current_char((const gs_text_enum_t *)penum);
}

/* Return the about-to-be-displayed character for kerning. */
gs_char
gs_kshow_next_char(const gs_show_enum * penum)
{
    return penum->text.data.bytes[penum->index];
}

/* Return the accumulated width for stringwidth. */
void
gs_show_width(const gs_show_enum * penum, gs_point * ppt)
{
    gs_text_total_width((const gs_text_enum_t *)penum, ppt);
}

/* ------ Internal routines ------ */

/*
 * Force the enumerator to be a gs_show_enum *, which the current
 * implementation code requires.
 */
private int
show_n_begin(gs_show_enum *penum, gs_state *pgs, int code, gs_text_enum_t *pte)
{
    if (code < 0)
	return code;
    if (gs_object_type(pgs->memory, pte) != &st_gs_show_enum) {
	/* Use the default implementation. */
	gx_device *dev = pgs->device;
	gs_text_params_t text;
	gs_memory_t *mem = pte->memory;
	dev_proc_text_begin((*text_begin)) = dev_proc(dev, text_begin);

	text = pte->text;
	gs_text_release(pte, "show_n_begin");
	/* Temporarily reset the text_begin procedure to the default. */
	set_dev_proc(dev, text_begin, gx_default_text_begin);
	code = gs_text_begin(pgs, &text, mem, &pte);
	set_dev_proc(dev, text_begin, text_begin);
	if (code < 0)
	    return code;
    }
    /* Now we know pte points to a gs_show_enum. */
    *penum = *(gs_show_enum *)pte;
    gs_free_object(pgs->memory, pte, "show_n_begin");
    return code;
}