summaryrefslogtreecommitdiff
path: root/base/gstext.h
blob: da57efa26c7239f74bebd267ee471ec8a09b119b (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
/* Copyright (C) 2001-2023 Artifex Software, Inc.
   All Rights Reserved.

   This software is provided AS-IS with no warranty, either express or
   implied.

   This software is distributed under license and may not be copied,
   modified or distributed except as expressly authorized under the terms
   of the license contained in the file LICENSE in this distribution.

   Refer to licensing information at http://www.artifex.com or contact
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
   CA 94129, USA, for further information.
*/


/* Driver interface for text */

#ifndef gstext_INCLUDED
#  define gstext_INCLUDED

#include "gsccode.h"
#include "gscpm.h"
#include "gsdevice.h"
#include "gsfont.h"
#include "gsdcolor.h"
#include "gxpath.h"

/*
 * Note that text display must return information to the generic code:
 *	If TEXT_RETURN_WIDTH or TEXT_DO_CHARWIDTH, the string escapement
 *	  (a.k.a. "width");
 *	If TEXT_DO_*_CHARPATH, the entire character description;
 *	If TEXT_DO_*_CHARBOXPATH, the character bounding box.
 */

/*
 * Define the set of possible text operations.  While we define this as
 * a bit mask for convenience in testing, only certain combinations are
 * meaningful.  Specifically, the following are errors:
 *      - No FROM or DO.
 *      - More than one FROM or DO.
 *	- FROM_SINGLE with size != 1.
 *      - Both ADD_TO and REPLACE.
 */
#define TEXT_HAS_MORE_THAN_ONE_(op, any)\
  ( ((op) & any) & (((op) & any) - 1) )
#define TEXT_OPERATION_IS_INVALID(op)\
  (!((op) & TEXT_FROM_ANY) ||\
   !((op) & TEXT_DO_ANY) ||\
   TEXT_HAS_MORE_THAN_ONE_(op, TEXT_FROM_ANY) ||\
   TEXT_HAS_MORE_THAN_ONE_(op, TEXT_DO_ANY) ||\
   /* We permit TEXT_ADD_TO_SPACE_WIDTHS (used to implement PDF Tw state in pdfi) \
    * with TEXT_REPLACE_WIDTHS (used to implement xyshow and the Widths override in pdfi) \
    */\
   (((op) & TEXT_ADD_TO_ALL_WIDTHS) && ((op) & TEXT_REPLACE_WIDTHS))\
   )
#define TEXT_PARAMS_ARE_INVALID(params)\
  (TEXT_OPERATION_IS_INVALID((params)->operation) ||\
   ( ((params)->operation & TEXT_FROM_ANY_SINGLE) && ((params)->size != 1) )\
   )

        /* Define the representation of the text itself. */
#define TEXT_FROM_STRING          0x00001
#define TEXT_FROM_BYTES           0x00002
#define TEXT_FROM_CHARS           0x00004
#define TEXT_FROM_GLYPHS          0x00008
#define TEXT_FROM_SINGLE_CHAR     0x00010
#define TEXT_FROM_SINGLE_GLYPH    0x00020
#define TEXT_FROM_ANY_SINGLE	/* only for testing and masking */\
  (TEXT_FROM_SINGLE_CHAR | TEXT_FROM_SINGLE_GLYPH)
#define TEXT_FROM_ANY	/* only for testing and masking */\
  (TEXT_FROM_STRING | TEXT_FROM_BYTES | TEXT_FROM_CHARS | TEXT_FROM_GLYPHS |\
   TEXT_FROM_ANY_SINGLE)
        /* Define how to compute escapements. */
#define TEXT_ADD_TO_ALL_WIDTHS    0x00040
#define TEXT_ADD_TO_SPACE_WIDTH   0x00080
#define TEXT_ADD_ANY	/* only for testing and masking */\
  (TEXT_ADD_TO_ALL_WIDTHS | TEXT_ADD_TO_SPACE_WIDTH)
#define TEXT_REPLACE_WIDTHS       0x00100
        /* Define what result should be produced. */
#define TEXT_DO_NONE              0x00200	/* stringwidth or cshow only */
#define TEXT_DO_DRAW              0x00400
#define TEXT_DO_CHARWIDTH         0x00800	/* rmoveto by width */
#define TEXT_DO_FALSE_CHARPATH    0x01000
#define TEXT_DO_TRUE_CHARPATH     0x02000
#define TEXT_DO_FALSE_CHARBOXPATH 0x04000
#define TEXT_DO_TRUE_CHARBOXPATH  0x08000
#define TEXT_DO_ANY_CHARPATH	/* only for testing and masking */\
  (TEXT_DO_CHARWIDTH | TEXT_DO_FALSE_CHARPATH | TEXT_DO_TRUE_CHARPATH |\
   TEXT_DO_FALSE_CHARBOXPATH | TEXT_DO_TRUE_CHARBOXPATH)
#define TEXT_DO_ANY	/* only for testing and masking */\
  (TEXT_DO_NONE | TEXT_DO_DRAW | TEXT_DO_ANY_CHARPATH)
        /* Define whether the client intervenes between characters. */
#define TEXT_INTERVENE            0x10000
        /* Define whether to return the width. */
#define TEXT_RETURN_WIDTH         0x20000
        /* PDF mode "3 Tr" */
#define TEXT_RENDER_MODE_3        0x40000
/* Do not pull a glyph from the glyph cache */
#define TEXT_NO_CACHE             0x80000

/*
 * Define the structure of parameters passed in for text display.
 * Note that the implementation does not modify any of these; the client
 * must not modify them after initialization.
 */
typedef struct gs_text_params_s {
    /* The client must set the following in all cases. */
    uint operation;		/* TEXT_xxx mask */
    union sd_ {
        const byte *bytes;	/* FROM_STRING, FROM_BYTES */
        const gs_char *chars;	/* FROM_CHARS */
        const gs_glyph *glyphs;	/* FROM_GLYPHS */
        gs_char d_char;		/* FROM_SINGLE_CHAR */
        gs_glyph d_glyph;	/* FROM_SINGLE_GLYPH */
    } data;
    uint size;			/* number of data elements, */
                                /* must be 1 if FROM_SINGLE */
    /* The following are used only in the indicated cases. */
    gs_point delta_all;		/* ADD_TO_ALL_WIDTHS */
    gs_point delta_space;	/* ADD_TO_SPACE_WIDTH */
    union s_ {
        gs_char s_char;		/* ADD_TO_SPACE_WIDTH & !FROM_GLYPHS */
        gs_glyph s_glyph;	/* ADD_TO_SPACE_WIDTH & FROM_GLYPHS */
    } space;
    /*
     * If x_widths == y_widths, widths are taken in pairs; note that in this
     * case, widths_size is the number of widths, not the number of pairs.
     * Either one may be NULL, meaning widths = 0.
     */
    const float *x_widths;	/* REPLACE_WIDTHS */
    const float *y_widths;	/* REPLACE_WIDTHS */
    uint widths_size;		/* REPLACE_WIDTHS */
} gs_text_params_t;

#define st_gs_text_params_max_ptrs 3
/*extern_st(st_gs_text_params); */
#define public_st_gs_text_params() /* in gstext.c */\
  gs_public_st_composite(st_gs_text_params, gs_text_params_t,\
    "gs_text_params", text_params_enum_ptrs, text_params_reloc_ptrs)

/* Assuming REPLACE_WIDTHS is set, return the width of the i'th character. */
int gs_text_replaced_width(const gs_text_params_t *text, uint index,
                           gs_point *pwidth);

/*
 * Define the abstract type for the structure that tracks the state of text
 * processing.
 */
typedef struct gs_text_enum_s gs_text_enum_t;

/*
 * Define the driver procedure for text.  This procedure must allocate
 * the enumerator (see gxtext.h) and initialize the procs and rc members.
 */
#define dev_t_proc_text_begin(proc, dev_t)\
  int proc(dev_t *dev,\
    gs_gstate *pgs,\
    const gs_text_params_t *text,\
    gs_font *font,\
    const gx_clip_path *pcpath,		/* if DO_DRAW */\
    gs_text_enum_t **ppte)
#define dev_proc_text_begin(proc)\
  dev_t_proc_text_begin(proc, gx_device)

/*
 * Begin processing text.  This calls the device procedure, and also
 * initializes the common parts of the enumerator.
 */
dev_proc_text_begin(gx_device_text_begin);

/* Begin processing text with a graphics state. */
int gs_text_begin(gs_gstate * pgs, const gs_text_params_t * text,
                  gs_memory_t * mem, gs_text_enum_t ** ppenum);

/*
 * Update the device color to be used with text (because a kshow or
 * cshow procedure may have changed the current color).
 */
int gs_text_update_dev_color(gs_gstate * pgs, gs_text_enum_t * pte);

/* Begin the PostScript-equivalent text operators. */
int
gs_show_begin(gs_gstate *, const byte *, uint,
              gs_memory_t *, gs_text_enum_t **),
    gs_ashow_begin(gs_gstate *, double, double, const byte *, uint,
                   gs_memory_t *, gs_text_enum_t **),
    gs_widthshow_begin(gs_gstate *, double, double, gs_char,
                       const byte *, uint,
                       gs_memory_t *, gs_text_enum_t **),
    gs_awidthshow_begin(gs_gstate *, double, double, gs_char,
                        double, double, const byte *, uint,
                        gs_memory_t *, gs_text_enum_t **),
    gs_kshow_begin(gs_gstate *, const byte *, uint,
                   gs_memory_t *, gs_text_enum_t **),
    gs_xyshow_begin(gs_gstate *, const byte *, uint,
                    const float *, const float *, uint,
                    gs_memory_t *, gs_text_enum_t **),
    gs_glyphshow_begin(gs_gstate *, gs_glyph,
                       gs_memory_t *, gs_text_enum_t **),
    gs_cshow_begin(gs_gstate *, const byte *, uint,
                   gs_memory_t *, gs_text_enum_t **),
    gs_stringwidth_begin(gs_gstate *, const byte *, uint,
                         gs_memory_t *, gs_text_enum_t **),
    gs_charpath_begin(gs_gstate *, const byte *, uint, bool,
                      gs_memory_t *, gs_text_enum_t **),
    gs_glyphpath_begin(gs_gstate *, gs_glyph, bool,
                       gs_memory_t *, gs_text_enum_t **),
    gs_glyphwidth_begin(gs_gstate *, gs_glyph,
                        gs_memory_t *, gs_text_enum_t **),
    gs_charboxpath_begin(gs_gstate *, const byte *, uint, bool,
                         gs_memory_t *, gs_text_enum_t **);

/* Retrieve text params from enumerator. */
gs_text_params_t *gs_get_text_params(gs_text_enum_t *pte);

/*
 * Restart text processing with new parameters.
 */
int gs_text_restart(gs_text_enum_t *pte, const gs_text_params_t *text);

/*
 * Resync text processing with new parameters and string position.
 */
int gs_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom);

/*
 * Define the possible return values from gs_text_process.  The client
 * should call text_process until it returns 0 (successful completion) or a
 * negative (error) value.
 */

        /*
         * The client must render a character: obtain the code from
         * gs_text_current_char/glyph, do whatever is necessary, and then
         * call gs_text_process again.
         */
#define TEXT_PROCESS_RENDER 1

        /*
         * The client has asked to intervene between characters.
         * Obtain the current and next codes from gs_text_current_char/glyph
         * and gs_text_next_char, do whatever is necessary, and then
         * call gs_text_process again.
         */
#define TEXT_PROCESS_INTERVENE 2

        /*
         * The device has asked to execute CDevProc.
         * Obtain the current codes from gs_text_current_char/glyph,
         * do whatever is necessary and put CDevProc results to pte->cdevproc_result,
         * and then call gs_text_process again with pte->cdevproc_result_valid=true.
         */
#define TEXT_PROCESS_CDEVPROC 3

/* Process text after 'begin'. */
int gs_text_process(gs_text_enum_t *pte);

/* Access elements of the enumerator. */
gs_font *gs_text_current_font(const gs_text_enum_t *pte);
gs_char gs_text_current_char(const gs_text_enum_t *pte);
gs_char gs_text_next_char(const gs_text_enum_t *pte);
gs_glyph gs_text_current_glyph(const gs_text_enum_t *pte);
int gs_text_total_width(const gs_text_enum_t *pte, gs_point *pwidth);

/*
 * After the implementation returned TEXT_PROCESS_RENDER, determine
 * whether it needs the entire character description, or only the width
 * (escapement).
 */
bool gs_text_is_width_only(const gs_text_enum_t *pte);

/*
 * Return the width of the current character (in user space coordinates).
 */
int gs_text_current_width(const gs_text_enum_t *pte, gs_point *pwidth);

/*
 * Set text metrics and optionally enable caching.  Return 1 iff the
 * cache device was just installed.
 */
typedef enum {
    TEXT_SET_CHAR_WIDTH,	/* wx wy */
    TEXT_SET_CACHE_DEVICE,	/* wx wy llx lly urx ury */
    TEXT_SET_CACHE_DEVICE2	/* w0x w0y llx lly urx ury w1x w1y vx vy */
} gs_text_cache_control_t;
int
    gs_text_set_cache(gs_text_enum_t *pte, const double *values,
                      gs_text_cache_control_t control),
    gs_text_setcharwidth(gs_text_enum_t *pte, const double wxy[2]),
    gs_text_setcachedevice(gs_text_enum_t *pte, const double wbox[6]),
    gs_text_setcachedevice2(gs_text_enum_t *pte, const double wbox2[10]);

/* Retry processing of the last character. */
int gs_text_retry(gs_text_enum_t *pte);

/* Release the text processing structures. */
void gs_text_release(gs_gstate *pgs, gs_text_enum_t *pte, client_name_t cname);

/* Compute the number of characters in a text. */
int gs_text_count_chars(gs_gstate * pgs, gs_text_params_t *text, gs_memory_t * mem);

#endif /* gstext_INCLUDED */