1 /* Copyright (C) 1999, 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: gschar.c,v 1.6 2002/06/16 05:48:55 lpd Exp $ */ 18 /* Character writing "operators" for Ghostscript library */ 19 #include "gx.h" 20 #include "gserrors.h" 21 #include "gsstruct.h" 22 #include "gsmatrix.h" /* for gscoord.h */ 23 #include "gscoord.h" /* for gs_idtransform */ 24 #include "gzstate.h" 25 #include "gxdevice.h" 26 #include "gxdevmem.h" 27 #include "gxchar.h" 28 #include "gxfont.h" 29 30 /* Forward declarations */ 31 private int show_n_begin(gs_show_enum *penum, gs_state *pgs, int code, 32 gs_text_enum_t *pte); 33 34 /* Structure descriptors */ 35 extern_st(st_gs_show_enum); 36 37 /* ------ String writing operators ------ */ 38 39 /* Free the contents of a show enumerator. */ 40 void 41 gs_show_enum_release(gs_show_enum * penum, gs_memory_t * emem) 42 { 43 if (penum->text.operation) /* otherwise, never initialized */ 44 penum->procs->release((gs_text_enum_t *)penum, "gs_show_enum_release"); 45 if (emem != 0) 46 gs_free_object(emem, penum, "gs_show_enum_release"); 47 } 48 49 /* show[_n] */ 50 int 51 gs_show_n_init(gs_show_enum * penum, gs_state * pgs, 52 const char *str, uint size) 53 { 54 gs_text_enum_t *pte; 55 int code = gs_show_begin(pgs, (const byte *)str, size, pgs->memory, &pte); 56 57 return show_n_begin(penum, pgs, code, pte); 58 } 59 60 /* ashow[_n] */ 61 int 62 gs_ashow_n_init(gs_show_enum * penum, gs_state * pgs, 63 floatp ax, floatp ay, const char *str, uint size) 64 { 65 gs_text_enum_t *pte; 66 int code = gs_ashow_begin(pgs, ax, ay, (const byte *)str, size, 67 pgs->memory, &pte); 68 69 return show_n_begin(penum, pgs, code, pte); 70 } 71 72 /* widthshow[_n] */ 73 int 74 gs_widthshow_n_init(gs_show_enum * penum, gs_state * pgs, 75 floatp cx, floatp cy, gs_char chr, 76 const char *str, uint size) 77 { 78 gs_text_enum_t *pte; 79 int code = gs_widthshow_begin(pgs, cx, cy, chr, (const byte *)str, size, 80 pgs->memory, &pte); 81 82 return show_n_begin(penum, pgs, code, pte); 83 } 84 85 /* awidthshow[_n] */ 86 int 87 gs_awidthshow_n_init(gs_show_enum * penum, gs_state * pgs, 88 floatp cx, floatp cy, gs_char chr, floatp ax, floatp ay, 89 const char *str, uint size) 90 { 91 gs_text_enum_t *pte; 92 int code = gs_awidthshow_begin(pgs, cx, cy, chr, ax, ay, 93 (const byte *)str, size, pgs->memory, &pte); 94 95 return show_n_begin(penum, pgs, code, pte); 96 } 97 98 /* kshow[_n] */ 99 int 100 gs_kshow_n_init(gs_show_enum * penum, 101 gs_state * pgs, const char *str, uint size) 102 { 103 gs_text_enum_t *pte; 104 int code; 105 106 switch (pgs->font->FontType) { 107 case ft_composite: 108 case ft_CID_encrypted: 109 case ft_CID_user_defined: 110 case ft_CID_TrueType: 111 case ft_CID_bitmap: 112 return_error(gs_error_invalidfont); 113 default: 114 break; 115 } 116 code = gs_kshow_begin(pgs, (const byte *)str, size, pgs->memory, &pte); 117 return show_n_begin(penum, pgs, code, pte); 118 } 119 120 /* xyshow[_n] */ 121 int 122 gs_xyshow_n_init(gs_show_enum * penum, 123 gs_state * pgs, const char *str, uint size) 124 { 125 gs_text_enum_t *pte; 126 int code = gs_xyshow_begin(pgs, (const byte *)str, size, NULL, NULL, 0, 127 pgs->memory, &pte); 128 129 return show_n_begin(penum, pgs, code, pte); 130 } 131 132 /* glyphshow */ 133 int 134 gs_glyphshow_init(gs_show_enum * penum, gs_state * pgs, gs_glyph glyph) 135 { 136 gs_text_enum_t *pte; 137 int code = gs_glyphshow_begin(pgs, glyph, pgs->memory, &pte); 138 139 return show_n_begin(penum, pgs, code, pte); 140 } 141 int 142 gs_glyphpath_init(gs_show_enum * penum, gs_state * pgs, gs_glyph glyph, 143 bool stroke_path) 144 { 145 gs_text_enum_t *pte; 146 int code = gs_glyphpath_begin(pgs, glyph, stroke_path, pgs->memory, &pte); 147 148 return show_n_begin(penum, pgs, code, pte); 149 } 150 int 151 gs_glyphwidth_init(gs_show_enum * penum, gs_state * pgs, gs_glyph glyph) 152 { 153 gs_text_enum_t *pte; 154 int code = gs_glyphwidth_begin(pgs, glyph, pgs->memory, &pte); 155 156 return show_n_begin(penum, pgs, code, pte); 157 } 158 159 /* ------ Related operators ------ */ 160 161 /* cshow[_n] */ 162 int 163 gs_cshow_n_init(gs_show_enum * penum, 164 gs_state * pgs, const char *str, uint size) 165 { 166 gs_text_enum_t *pte; 167 int code = gs_cshow_begin(pgs, (const byte *)str, size, pgs->memory, &pte); 168 169 return show_n_begin(penum, pgs, code, pte); 170 } 171 172 /* stringwidth[_n] */ 173 int 174 gs_stringwidth_n_init(gs_show_enum * penum, gs_state * pgs, 175 const char *str, uint size) 176 { 177 gs_text_enum_t *pte; 178 int code = gs_stringwidth_begin(pgs, (const byte *)str, size, 179 pgs->memory, &pte); 180 181 return show_n_begin(penum, pgs, code, pte); 182 } 183 184 /* charpath[_n] */ 185 int 186 gs_charpath_n_init(gs_show_enum * penum, gs_state * pgs, 187 const char *str, uint size, bool stroke_path) 188 { 189 gs_text_enum_t *pte; 190 int code = gs_charpath_begin(pgs, (const byte *)str, size, stroke_path, 191 pgs->memory, &pte); 192 193 return show_n_begin(penum, pgs, code, pte); 194 } 195 196 /* charboxpath[_n] */ 197 int 198 gs_charboxpath_n_init(gs_show_enum * penum, gs_state * pgs, 199 const char *str, uint size, bool use_boxes) 200 { 201 gs_text_enum_t *pte; 202 int code = gs_charboxpath_begin(pgs, (const byte *)str, size, use_boxes, 203 pgs->memory, &pte); 204 205 return show_n_begin(penum, pgs, code, pte); 206 } 207 208 /* ------ Width/cache operators ------ */ 209 210 /* setcachedevice */ 211 /* The elements of pw are: wx, wy, llx, lly, urx, ury. */ 212 /* Note that this returns 1 if we just set up the cache device. */ 213 int 214 gs_setcachedevice_double(gs_show_enum *penum, gs_state *pgs, const double *pw) 215 { 216 if (penum->pgs != pgs) 217 return_error(gs_error_rangecheck); 218 return gs_text_setcachedevice((gs_text_enum_t *)penum, pw); 219 } 220 /* The _float procedure is strictly for backward compatibility. */ 221 int 222 gs_setcachedevice_float(gs_show_enum * penum, gs_state * pgs, const float *pw) 223 { 224 double w[6]; 225 int i; 226 227 for (i = 0; i < 6; ++i) 228 w[i] = pw[i]; 229 return gs_setcachedevice_double(penum, pgs, w); 230 } 231 232 /* setcachedevice2 */ 233 /* The elements of pw2 are: w0x, w0y, llx, lly, urx, ury, w1x, w1y, vx, vy. */ 234 /* Note that this returns 1 if we just set up the cache device. */ 235 int 236 gs_setcachedevice2_double(gs_show_enum * penum, gs_state * pgs, 237 const double *pw2) 238 { 239 if (penum->pgs != pgs) 240 return_error(gs_error_rangecheck); 241 return gs_text_setcachedevice2((gs_text_enum_t *)penum, pw2); 242 } 243 /* The _float procedure is strictly for backward compatibility. */ 244 int 245 gs_setcachedevice2_float(gs_show_enum * penum, gs_state * pgs, const float *pw2) 246 { 247 double w2[10]; 248 int i; 249 250 for (i = 0; i < 10; ++i) 251 w2[i] = pw2[i]; 252 return gs_setcachedevice2_double(penum, pgs, w2); 253 } 254 255 /* setcharwidth */ 256 /* Note that this returns 1 if the current show operation is */ 257 /* non-displaying (stringwidth or cshow). */ 258 int 259 gs_setcharwidth(gs_show_enum * penum, gs_state * pgs, 260 floatp wx, floatp wy) 261 { 262 double w[2]; 263 264 if (penum->pgs != pgs) 265 return_error(gs_error_rangecheck); 266 w[0] = wx, w[1] = wy; 267 return gs_text_setcharwidth((gs_text_enum_t *)penum, w); 268 } 269 270 /* ------ Enumerator ------ */ 271 272 /* Do the next step of a show (or stringwidth) operation */ 273 int 274 gs_show_next(gs_show_enum * penum) 275 { 276 return gs_text_process((gs_text_enum_t *)penum); 277 } 278 279 /* 280 * Return true if we only need the width from the rasterizer 281 * and can short-circuit the full rendering of the character, 282 * false if we need the actual character bits. 283 */ 284 bool 285 gs_show_width_only(const gs_show_enum * penum) 286 { 287 return gs_text_is_width_only((const gs_text_enum_t *)penum); 288 } 289 290 /* ------ Accessors ------ */ 291 292 /* Return the current character for rendering. */ 293 gs_char 294 gs_show_current_char(const gs_show_enum * penum) 295 { 296 return gs_text_current_char((const gs_text_enum_t *)penum); 297 } 298 299 /* Return the current glyph for rendering. */ 300 gs_glyph 301 gs_show_current_glyph(const gs_show_enum * penum) 302 { 303 return gs_text_current_glyph((const gs_text_enum_t *)penum); 304 } 305 306 /* Return the width of the just-enumerated character (for cshow). */ 307 int 308 gs_show_current_width(const gs_show_enum * penum, gs_point * ppt) 309 { 310 return gs_text_current_width((const gs_text_enum_t *)penum, ppt); 311 } 312 313 /* Return the just-displayed character for kerning. */ 314 gs_char 315 gs_kshow_previous_char(const gs_show_enum * penum) 316 { 317 return gs_text_current_char((const gs_text_enum_t *)penum); 318 } 319 320 /* Return the about-to-be-displayed character for kerning. */ 321 gs_char 322 gs_kshow_next_char(const gs_show_enum * penum) 323 { 324 return penum->text.data.bytes[penum->index]; 325 } 326 327 /* Return the accumulated width for stringwidth. */ 328 void 329 gs_show_width(const gs_show_enum * penum, gs_point * ppt) 330 { 331 gs_text_total_width((const gs_text_enum_t *)penum, ppt); 332 } 333 334 /* ------ Internal routines ------ */ 335 336 /* 337 * Force the enumerator to be a gs_show_enum *, which the current 338 * implementation code requires. 339 */ 340 private int 341 show_n_begin(gs_show_enum *penum, gs_state *pgs, int code, gs_text_enum_t *pte) 342 { 343 if (code < 0) 344 return code; 345 if (gs_object_type(pgs->memory, pte) != &st_gs_show_enum) { 346 /* Use the default implementation. */ 347 gx_device *dev = pgs->device; 348 gs_text_params_t text; 349 gs_memory_t *mem = pte->memory; 350 dev_proc_text_begin((*text_begin)) = dev_proc(dev, text_begin); 351 352 text = pte->text; 353 gs_text_release(pte, "show_n_begin"); 354 /* Temporarily reset the text_begin procedure to the default. */ 355 set_dev_proc(dev, text_begin, gx_default_text_begin); 356 code = gs_text_begin(pgs, &text, mem, &pte); 357 set_dev_proc(dev, text_begin, text_begin); 358 if (code < 0) 359 return code; 360 } 361 /* Now we know pte points to a gs_show_enum. */ 362 *penum = *(gs_show_enum *)pte; 363 gs_free_object(pgs->memory, pte, "show_n_begin"); 364 return code; 365 } 366