Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/gs/src/gstext.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1998, 2000 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: gstext.c,v 1.19 2004/12/22 18:52:23 igor Exp $ */
18
/* Driver text interface support */
19
#include "memory_.h"
20
#include "gstypes.h"
21
#include "gdebug.h"
22
#include "gserror.h"
23
#include "gserrors.h"
24
#include "gsmemory.h"
25
#include "gsstruct.h"
26
#include "gstypes.h"
27
#include "gxfcache.h"
28
#include "gxdevcli.h"
29
#include "gxdcolor.h"		/* for gs_state_color_load */
30
#include "gxfont.h"		/* for init_fstack */
31
#include "gxpath.h"
32
#include "gxtext.h"
33
#include "gzstate.h"
34
 
35
/* GC descriptors */
36
public_st_gs_text_params();
37
public_st_gs_text_enum();
38
 
39
private 
40
ENUM_PTRS_WITH(text_params_enum_ptrs, gs_text_params_t *tptr) return 0;
41
case 0:
42
if (tptr->operation & TEXT_FROM_STRING) {
43
    return ENUM_CONST_STRING2(tptr->data.bytes, tptr->size);
44
}
45
if (tptr->operation & TEXT_FROM_BYTES)
46
    return ENUM_OBJ(tptr->data.bytes);
47
if (tptr->operation & TEXT_FROM_CHARS)
48
    return ENUM_OBJ(tptr->data.chars);
49
if (tptr->operation & TEXT_FROM_GLYPHS)
50
    return ENUM_OBJ(tptr->data.glyphs);
51
return ENUM_OBJ(NULL);
52
case 1:
53
return ENUM_OBJ(tptr->operation & TEXT_REPLACE_WIDTHS ?
54
		tptr->x_widths : NULL);
55
case 2:
56
return ENUM_OBJ(tptr->operation & TEXT_REPLACE_WIDTHS ?
57
		tptr->y_widths : NULL);
58
ENUM_PTRS_END
59
private RELOC_PTRS_WITH(text_params_reloc_ptrs, gs_text_params_t *tptr)
60
{
61
    if (tptr->operation & TEXT_FROM_STRING) {
62
	gs_const_string str;
63
 
64
	str.data = tptr->data.bytes;
65
	str.size = tptr->size;
66
	RELOC_CONST_STRING_VAR(str);
67
	tptr->data.bytes = str.data;
68
    } else if (tptr->operation & TEXT_FROM_BYTES)
69
	RELOC_OBJ_VAR(tptr->data.bytes);
70
    else if (tptr->operation & TEXT_FROM_CHARS)
71
	RELOC_OBJ_VAR(tptr->data.chars);
72
    else if (tptr->operation & TEXT_FROM_GLYPHS)
73
	RELOC_OBJ_VAR(tptr->data.glyphs);
74
    if (tptr->operation & TEXT_REPLACE_WIDTHS) {
75
	RELOC_OBJ_VAR(tptr->x_widths);
76
	RELOC_OBJ_VAR(tptr->y_widths);
77
    }
78
}
79
RELOC_PTRS_END
80
 
81
private ENUM_PTRS_WITH(text_enum_enum_ptrs, gs_text_enum_t *eptr)
82
{
83
    if (index == 8) {
84
	if (eptr->pair != 0)
85
	    ENUM_RETURN(eptr->pair - eptr->pair->index);
86
	else
87
	    ENUM_RETURN(0);
88
    }
89
    index -= 9;
90
    if (index <= eptr->fstack.depth)
91
	ENUM_RETURN(eptr->fstack.items[index].font);
92
    index -= eptr->fstack.depth + 1;
93
     return ENUM_USING(st_gs_text_params, &eptr->text, sizeof(eptr->text), index);
94
}
95
case 0: return ENUM_OBJ(gx_device_enum_ptr(eptr->dev));
96
case 1: return ENUM_OBJ(gx_device_enum_ptr(eptr->imaging_dev));
97
ENUM_PTR3(2, gs_text_enum_t, pis, orig_font, path);
98
ENUM_PTR3(5, gs_text_enum_t, pdcolor, pcpath, current_font);
99
ENUM_PTRS_END
100
 
101
private RELOC_PTRS_WITH(text_enum_reloc_ptrs, gs_text_enum_t *eptr)
102
{
103
    int i;
104
 
105
    RELOC_USING(st_gs_text_params, &eptr->text, sizeof(eptr->text));
106
    eptr->dev = gx_device_reloc_ptr(eptr->dev, gcst);
107
    eptr->imaging_dev = gx_device_reloc_ptr(eptr->imaging_dev, gcst);
108
    RELOC_PTR3(gs_text_enum_t, pis, orig_font, path);
109
    RELOC_PTR3(gs_text_enum_t, pdcolor, pcpath, current_font);
110
    if (eptr->pair != NULL)
111
	eptr->pair = (cached_fm_pair *)RELOC_OBJ(eptr->pair - eptr->pair->index) +
112
			     eptr->pair->index;
113
    for (i = 0; i <= eptr->fstack.depth; i++)
114
	RELOC_PTR(gs_text_enum_t, fstack.items[i].font);
115
}
116
RELOC_PTRS_END
117
 
118
/* Begin processing text. */
119
int
120
gx_device_text_begin(gx_device * dev, gs_imager_state * pis,
121
		     const gs_text_params_t * text, gs_font * font,
122
		     gx_path * path,	/* unless DO_NONE & !RETURN_WIDTH */
123
		     const gx_device_color * pdcolor,	/* DO_DRAW */
124
		     const gx_clip_path * pcpath,	/* DO_DRAW */
125
		     gs_memory_t * mem, gs_text_enum_t ** ppte)
126
{
127
    if (TEXT_PARAMS_ARE_INVALID(text))
128
	return_error(gs_error_rangecheck);
129
    {
130
	gx_path *tpath =
131
	    ((text->operation & TEXT_DO_NONE) &&
132
	     !(text->operation & TEXT_RETURN_WIDTH) ? 0 : path);
133
	const gx_clip_path *tcpath =
134
	    (text->operation & TEXT_DO_DRAW ? pcpath : 0);
135
 
136
	/* A high level device need to know an initial device color 
137
	   for accumulates a charstring of a Type 3 font.
138
	   Since the accumulation may happen while stringwidth. 
139
	   we pass the device color unconditionally. */
140
	return dev_proc(dev, text_begin)
141
	    (dev, pis, text, font, tpath, pdcolor, tcpath, mem, ppte);
142
    }
143
}
144
 
145
/* 
146
 * Initialize a newly created text enumerator.  Implementations of
147
 * text_begin must call this just after allocating the enumerator.
148
 */
149
private int
150
gs_text_enum_init_dynamic(gs_text_enum_t *pte, gs_font *font)
151
{
152
    pte->current_font = font;
153
    pte->index = 0;
154
    pte->xy_index = 0;
155
    pte->FontBBox_as_Metrics2.x = pte->FontBBox_as_Metrics2.y = 0;
156
    pte->pair = 0;
157
    pte->device_disabled_grid_fitting = 0;
158
    pte->outer_CID = GS_NO_GLYPH;
159
    return font->procs.init_fstack(pte, font);
160
}
161
int
162
gs_text_enum_init(gs_text_enum_t *pte, const gs_text_enum_procs_t *procs,
163
		  gx_device *dev, gs_imager_state *pis,
164
		  const gs_text_params_t *text, gs_font *font, gx_path *path,
165
		  const gx_device_color *pdcolor, const gx_clip_path *pcpath,
166
		  gs_memory_t *mem)
167
{
168
    int code;
169
 
170
    pte->text = *text;
171
    pte->dev = dev;
172
    pte->imaging_dev = NULL;
173
    pte->pis = pis;
174
    pte->orig_font = font;
175
    pte->path = path;
176
    pte->pdcolor = pdcolor;
177
    pte->pcpath = pcpath;
178
    pte->memory = mem;
179
    pte->procs = procs;
180
    /* text_begin procedure sets rc */
181
    /* init_dynamic sets current_font */
182
    pte->log2_scale.x = pte->log2_scale.y = 0;
183
    /* init_dynamic sets index, xy_index, fstack */
184
    code = gs_text_enum_init_dynamic(pte, font);
185
    if (code >= 0)
186
	rc_increment(dev);
187
    return code;
188
}
189
 
190
/*
191
 * Copy the dynamically changing elements from one enumerator to another.
192
 * This is useful primarily for enumerators that sometimes pass the
193
 * operation to a subsidiary enumerator.
194
 */
195
void
196
gs_text_enum_copy_dynamic(gs_text_enum_t *pto, const gs_text_enum_t *pfrom,
197
			  bool for_return)
198
{
199
    int depth = pfrom->fstack.depth;
200
 
201
    pto->current_font = pfrom->current_font;
202
    pto->index = pfrom->index;
203
    pto->xy_index = pfrom->xy_index;
204
    pto->fstack.depth = depth;
205
    pto->FontBBox_as_Metrics2 = pfrom->FontBBox_as_Metrics2;
206
    pto->pair = pfrom->pair;
207
    pto->device_disabled_grid_fitting = pfrom->device_disabled_grid_fitting;
208
    pto->outer_CID = pfrom->outer_CID;
209
    if (depth >= 0)
210
	memcpy(pto->fstack.items, pfrom->fstack.items,
211
	       (depth + 1) * sizeof(pto->fstack.items[0]));
212
    if (for_return) {
213
	pto->cmap_code = pfrom->cmap_code;
214
	pto->returned = pfrom->returned;
215
    }
216
}
217
 
218
/* Begin processing text based on a graphics state. */
219
int
220
gs_text_begin(gs_state * pgs, const gs_text_params_t * text,
221
	      gs_memory_t * mem, gs_text_enum_t ** ppte)
222
{
223
    gx_clip_path *pcpath = 0;
224
    int code;
225
 
226
    if (text->operation & TEXT_DO_DRAW) {
227
	code = gx_effective_clip_path(pgs, &pcpath);
228
	if (code < 0)
229
	    return code;
230
    }
231
    /* We must load device color even with no TEXT_DO_DRAW,
232
       because a high level device accumulates a charstring 
233
       of a Type 3 font while stringwidth. 
234
       Unfortunately we can't effectively know a leaf font type here,
235
       so we load the color unconditionally . */
236
    gx_set_dev_color(pgs);
237
    code = gs_state_color_load(pgs);
238
    if (code < 0)
239
	return code;
240
    return gx_device_text_begin(pgs->device, (gs_imager_state *) pgs,
241
				text, pgs->font, pgs->path, pgs->dev_color,
242
				pcpath, mem, ppte);
243
}
244
 
245
/*
246
 * Update the device color to be used with text (because a kshow or
247
 * cshow procedure may have changed the current color).
248
 */
249
int
250
gs_text_update_dev_color(gs_state * pgs, gs_text_enum_t * pte)
251
{
252
    /*
253
     * The text enumerator holds a device color pointer, which may be a
254
     * null pointer or a pointer to the same device color as the graphic
255
     * state points to. In the former case the text is not to be
256
     * rendered, and hence of no interest here. In the latter case the
257
     * update of the graphic state color will update the text color as
258
     * well.
259
     */
260
    if (pte->pdcolor != 0)
261
        gx_set_dev_color(pgs);
262
    return 0;
263
}
264
 
265
private inline uint text_do_draw(gs_state * pgs)
266
{
267
    return (pgs->text_rendering_mode == 3 ? TEXT_DO_NONE : TEXT_DO_DRAW);
268
}
269
 
270
/* Begin PostScript-equivalent text operations. */
271
int
272
gs_show_begin(gs_state * pgs, const byte * str, uint size,
273
	      gs_memory_t * mem, gs_text_enum_t ** ppte)
274
{
275
    gs_text_params_t text;
276
 
277
    text.operation = TEXT_FROM_STRING | text_do_draw(pgs) | TEXT_RETURN_WIDTH;
278
    text.data.bytes = str, text.size = size;
279
    return gs_text_begin(pgs, &text, mem, ppte);
280
}
281
int
282
gs_ashow_begin(gs_state * pgs, floatp ax, floatp ay, const byte * str, uint size,
283
	       gs_memory_t * mem, gs_text_enum_t ** ppte)
284
{
285
    gs_text_params_t text;
286
 
287
    text.operation = TEXT_FROM_STRING | TEXT_ADD_TO_ALL_WIDTHS |
288
	text_do_draw(pgs) | TEXT_RETURN_WIDTH;
289
    text.data.bytes = str, text.size = size;
290
    text.delta_all.x = ax;
291
    text.delta_all.y = ay;
292
    return gs_text_begin(pgs, &text, mem, ppte);
293
}
294
int
295
gs_widthshow_begin(gs_state * pgs, floatp cx, floatp cy, gs_char chr,
296
		   const byte * str, uint size,
297
		   gs_memory_t * mem, gs_text_enum_t ** ppte)
298
{
299
    gs_text_params_t text;
300
 
301
    text.operation = TEXT_FROM_STRING | TEXT_ADD_TO_SPACE_WIDTH |
302
	text_do_draw(pgs) | TEXT_RETURN_WIDTH;
303
    text.data.bytes = str, text.size = size;
304
    text.delta_space.x = cx;
305
    text.delta_space.y = cy;
306
    text.space.s_char = chr;
307
    return gs_text_begin(pgs, &text, mem, ppte);
308
}
309
int
310
gs_awidthshow_begin(gs_state * pgs, floatp cx, floatp cy, gs_char chr,
311
		    floatp ax, floatp ay, const byte * str, uint size,
312
		    gs_memory_t * mem, gs_text_enum_t ** ppte)
313
{
314
    gs_text_params_t text;
315
 
316
    text.operation = TEXT_FROM_STRING |
317
	TEXT_ADD_TO_ALL_WIDTHS | TEXT_ADD_TO_SPACE_WIDTH |
318
	text_do_draw(pgs) | TEXT_RETURN_WIDTH;
319
    text.data.bytes = str, text.size = size;
320
    text.delta_space.x = cx;
321
    text.delta_space.y = cy;
322
    text.space.s_char = chr;
323
    text.delta_all.x = ax;
324
    text.delta_all.y = ay;
325
    return gs_text_begin(pgs, &text, mem, ppte);
326
}
327
int
328
gs_kshow_begin(gs_state * pgs, const byte * str, uint size,
329
	       gs_memory_t * mem, gs_text_enum_t ** ppte)
330
{
331
    gs_text_params_t text;
332
 
333
    text.operation = TEXT_FROM_STRING | text_do_draw(pgs) | TEXT_INTERVENE |
334
	TEXT_RETURN_WIDTH;
335
    text.data.bytes = str, text.size = size;
336
    return gs_text_begin(pgs, &text, mem, ppte);
337
}
338
int
339
gs_xyshow_begin(gs_state * pgs, const byte * str, uint size,
340
		const float *x_widths, const float *y_widths,
341
		uint widths_size, gs_memory_t * mem, gs_text_enum_t ** ppte)
342
{
343
    gs_text_params_t text;
344
 
345
    text.operation = TEXT_FROM_STRING | TEXT_REPLACE_WIDTHS |
346
	text_do_draw(pgs) | TEXT_RETURN_WIDTH;
347
    text.data.bytes = str, text.size = size;
348
    text.x_widths = x_widths;
349
    text.y_widths = y_widths;
350
    text.widths_size = widths_size;
351
    return gs_text_begin(pgs, &text, mem, ppte);
352
}
353
 
354
private void
355
setup_FontBBox_as_Metrics2 (gs_text_enum_t * pte, gs_font * pfont)
356
{
357
    /* When we exec a operator like `show' that has a a chance to get
358
       a glyph from a char, we can set FontBBox_as_Metrics2 in
359
       gschar0.c:gs_type0_next_char_glyph.  In other hand, when we
360
       exec a operator like `glyphshow' that get a glyph directly from
361
       an input file, gschar0.c:gs_type0_next_char_glyph is exec'ed.
362
       For the later case, we set up FontBBox_as_Metrics2 with using
363
       this procedure.. */
364
    if (pfont->FontType == ft_CID_encrypted
365
	|| pfont->FontType == ft_CID_TrueType)
366
        pte->FontBBox_as_Metrics2 = ((gs_font_base *)pfont)->FontBBox.q;
367
}
368
 
369
int
370
gs_glyphshow_begin(gs_state * pgs, gs_glyph glyph,
371
		   gs_memory_t * mem, gs_text_enum_t ** ppte)
372
{
373
    gs_text_params_t text;
374
    int result;
375
 
376
    text.operation = TEXT_FROM_SINGLE_GLYPH | text_do_draw(pgs) | TEXT_RETURN_WIDTH;
377
    text.data.d_glyph = glyph;
378
    text.size = 1;
379
    result = gs_text_begin(pgs, &text, mem, ppte);
380
    if (result == 0)
381
      setup_FontBBox_as_Metrics2(*ppte, pgs->font);
382
    return result;
383
}
384
int
385
gs_cshow_begin(gs_state * pgs, const byte * str, uint size,
386
	       gs_memory_t * mem, gs_text_enum_t ** ppte)
387
{
388
    gs_text_params_t text;
389
 
390
    text.operation = TEXT_FROM_STRING | TEXT_DO_NONE | TEXT_INTERVENE;
391
    text.data.bytes = str, text.size = size;
392
    return gs_text_begin(pgs, &text, mem, ppte);
393
}
394
int
395
gs_stringwidth_begin(gs_state * pgs, const byte * str, uint size,
396
		     gs_memory_t * mem, gs_text_enum_t ** ppte)
397
{
398
    gs_text_params_t text;
399
 
400
    text.operation = TEXT_FROM_STRING | TEXT_DO_NONE | TEXT_RETURN_WIDTH;
401
    text.data.bytes = str, text.size = size;
402
    return gs_text_begin(pgs, &text, mem, ppte);
403
}
404
int
405
gs_charpath_begin(gs_state * pgs, const byte * str, uint size, bool stroke_path,
406
		  gs_memory_t * mem, gs_text_enum_t ** ppte)
407
{
408
    gs_text_params_t text;
409
 
410
    text.operation = TEXT_FROM_STRING | TEXT_RETURN_WIDTH |
411
	(stroke_path ? TEXT_DO_TRUE_CHARPATH : TEXT_DO_FALSE_CHARPATH);
412
    text.data.bytes = str, text.size = size;
413
    return gs_text_begin(pgs, &text, mem, ppte);
414
}
415
int
416
gs_charboxpath_begin(gs_state * pgs, const byte * str, uint size,
417
		bool stroke_path, gs_memory_t * mem, gs_text_enum_t ** ppte)
418
{
419
    gs_text_params_t text;
420
 
421
    text.operation = TEXT_FROM_STRING | TEXT_RETURN_WIDTH |
422
	(stroke_path ? TEXT_DO_TRUE_CHARBOXPATH : TEXT_DO_FALSE_CHARBOXPATH);
423
    text.data.bytes = str, text.size = size;
424
    return gs_text_begin(pgs, &text, mem, ppte);
425
}
426
int
427
gs_glyphpath_begin(gs_state * pgs, gs_glyph glyph, bool stroke_path,
428
		   gs_memory_t * mem, gs_text_enum_t ** ppte)
429
{
430
    gs_text_params_t text;
431
    int result;
432
 
433
    text.operation = TEXT_FROM_SINGLE_GLYPH | TEXT_RETURN_WIDTH |
434
	(stroke_path ? TEXT_DO_TRUE_CHARPATH : TEXT_DO_FALSE_CHARPATH);
435
    text.data.d_glyph = glyph;
436
    text.size = 1;
437
    result = gs_text_begin(pgs, &text, mem, ppte);
438
    if (result == 0)
439
      setup_FontBBox_as_Metrics2(*ppte, pgs->font);
440
    return result;
441
}
442
int
443
gs_glyphwidth_begin(gs_state * pgs, gs_glyph glyph,
444
		    gs_memory_t * mem, gs_text_enum_t ** ppte)
445
{
446
    gs_text_params_t text;
447
    int result;
448
 
449
    text.operation = TEXT_FROM_SINGLE_GLYPH | TEXT_DO_NONE | TEXT_RETURN_WIDTH;
450
    text.data.d_glyph = glyph;
451
    text.size = 1;
452
    result = gs_text_begin(pgs, &text, mem, ppte);
453
    if (result == 0)
454
      setup_FontBBox_as_Metrics2(*ppte, pgs->font);
455
    return result;
456
}
457
 
458
/* Restart processing with different parameters. */
459
int
460
gs_text_restart(gs_text_enum_t *pte, const gs_text_params_t *text)
461
{
462
    gs_text_enum_t tenum;
463
 
464
    tenum = *pte;
465
    tenum.text = *text;
466
    gs_text_enum_init_dynamic(&tenum, pte->orig_font);
467
    setup_FontBBox_as_Metrics2(pte, pte->orig_font);
468
    return gs_text_resync(pte, &tenum);
469
}
470
 
471
/*
472
 * Resync text processing with new parameters and string position.
473
 */
474
int
475
gs_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom)
476
{
477
    return pte->procs->resync(pte, pfrom);
478
}
479
 
480
/* Process text after 'begin'. */
481
int
482
gs_text_process(gs_text_enum_t * pte)
483
{
484
    return pte->procs->process(pte);
485
}
486
 
487
/* Access elements of the enumerator. */
488
gs_font *
489
gs_text_current_font(const gs_text_enum_t *pte)
490
{
491
    return pte->current_font;
492
}
493
gs_char
494
gs_text_current_char(const gs_text_enum_t *pte)
495
{
496
    return pte->returned.current_char;
497
}
498
gs_char
499
gs_text_next_char(const gs_text_enum_t *pte)
500
{
501
    const uint operation = pte->text.operation;
502
 
503
    if (pte->index >= pte->text.size)
504
	return gs_no_char;	/* rangecheck */
505
    if (operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES))
506
	return pte->text.data.bytes[pte->index];
507
    if (operation & TEXT_FROM_CHARS)
508
	return pte->text.data.chars[pte->index];
509
    return gs_no_char;		/* rangecheck */
510
}
511
gs_glyph
512
gs_text_current_glyph(const gs_text_enum_t *pte)
513
{
514
    return pte->returned.current_glyph;
515
}
516
int 
517
gs_text_total_width(const gs_text_enum_t *pte, gs_point *pwidth)
518
{
519
    *pwidth = pte->returned.total_width;
520
    return 0;
521
}
522
 
523
/* Assuming REPLACE_WIDTHS is set, return the width of the i'th character. */
524
int
525
gs_text_replaced_width(const gs_text_params_t *text, uint index,
526
		       gs_point *pwidth)
527
{
528
    const float *x_widths = text->x_widths;
529
    const float *y_widths = text->y_widths;
530
 
531
    if (index > text->size)
532
	return_error(gs_error_rangecheck);
533
    if (x_widths == y_widths) {
534
	if (x_widths) {
535
	    index *= 2;
536
	    pwidth->x = x_widths[index];
537
	    pwidth->y = x_widths[index + 1];
538
	}
539
	else
540
	    pwidth->x = pwidth->y = 0;
541
    } else {
542
	pwidth->x = (x_widths ? x_widths[index] : 0.0);
543
	pwidth->y = (y_widths ? y_widths[index] : 0.0);
544
    }
545
    return 0;
546
}
547
 
548
/* Determine whether only the width is needed. */
549
bool
550
gs_text_is_width_only(const gs_text_enum_t * pte)
551
{
552
    return pte->procs->is_width_only(pte);
553
}
554
 
555
/* Return the width of the current character. */
556
int
557
gs_text_current_width(const gs_text_enum_t * pte, gs_point *pwidth)
558
{
559
    return pte->procs->current_width(pte, pwidth);
560
}
561
 
562
/* Set text metrics and optionally enable caching. */
563
int
564
gs_text_set_cache(gs_text_enum_t * pte, const double *values,
565
		  gs_text_cache_control_t control)
566
{
567
    return pte->procs->set_cache(pte, values, control);
568
}
569
int
570
gs_text_setcharwidth(gs_text_enum_t * pte, const double wxy[2])
571
{
572
    return pte->procs->set_cache(pte, wxy, TEXT_SET_CHAR_WIDTH);
573
}
574
int
575
gs_text_setcachedevice(gs_text_enum_t * pte, const double wbox[6])
576
{
577
    return pte->procs->set_cache(pte, wbox, TEXT_SET_CACHE_DEVICE);
578
}
579
int
580
gs_text_setcachedevice2(gs_text_enum_t * pte, const double wbox2[10])
581
{
582
    return pte->procs->set_cache(pte, wbox2, TEXT_SET_CACHE_DEVICE2);
583
}
584
 
585
/* Retry processing the last character without caching. */
586
int
587
gs_text_retry(gs_text_enum_t * pte)
588
{
589
    return pte->procs->retry(pte);
590
}
591
 
592
/* Release the text processing structures. */
593
void
594
gx_default_text_release(gs_text_enum_t *pte, client_name_t cname)
595
{
596
    rc_decrement_only(pte->dev, cname);
597
    rc_decrement_only(pte->imaging_dev, cname);
598
}
599
void
600
rc_free_text_enum(gs_memory_t * mem, void *obj, client_name_t cname)
601
{
602
    gs_text_enum_t *pte = obj;
603
 
604
    pte->procs->release(pte, cname);
605
    rc_free_struct_only(mem, obj, cname);
606
}
607
void
608
gs_text_release(gs_text_enum_t * pte, client_name_t cname)
609
{
610
    rc_decrement_only(pte, cname);
611
}
612
 
613
/* ---------------- Default font rendering procedures ---------------- */
614
 
615
/* Default fstack initialization procedure. */
616
int
617
gs_default_init_fstack(gs_text_enum_t *pte, gs_font *pfont)
618
{
619
    pte->fstack.depth = -1;
620
    return 0;
621
}
622
 
623
/* Default next-glyph procedure. */
624
int
625
gs_default_next_char_glyph(gs_text_enum_t *pte, gs_char *pchr, gs_glyph *pglyph)
626
{
627
    if (pte->index >= pte->text.size)
628
	return 2;
629
    if (pte->text.operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) {
630
	/* ordinary string */
631
	*pchr = pte->text.data.bytes[pte->index];
632
	if (pte->outer_CID != GS_NO_GLYPH)
633
	    *pglyph = pte->outer_CID;
634
	else
635
	    *pglyph = gs_no_glyph;
636
    } else if (pte->text.operation & TEXT_FROM_SINGLE_GLYPH) {
637
	/* glyphshow or glyphpath */
638
	*pchr = gs_no_char;
639
	*pglyph = pte->text.data.d_glyph;
640
    } else if (pte->text.operation & TEXT_FROM_GLYPHS) {
641
	*pchr = gs_no_char;
642
	*pglyph = pte->text.data.glyphs[pte->index];
643
    } else if (pte->text.operation & TEXT_FROM_SINGLE_CHAR) {
644
	*pchr = pte->text.data.d_char;
645
	*pglyph = gs_no_glyph;
646
    } else if (pte->text.operation & TEXT_FROM_CHARS) {
647
	*pchr = pte->text.data.chars[pte->index];
648
	*pglyph = gs_no_glyph;
649
    } else
650
	return_error(gs_error_rangecheck); /* shouldn't happen */
651
    pte->index++;
652
    return 0;
653
}
654
 
655
/* Dummy (ineffective) BuildChar/BuildGlyph procedure */
656
int
657
gs_no_build_char(gs_text_enum_t *pte, gs_state *pgs, gs_font *pfont,
658
		 gs_char chr, gs_glyph glyph)
659
{
660
    return 1;			/* failure, but not error */
661
}