/* 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 */