1 /* Copyright (C) 1998, 1999 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: zcfont.c,v 1.6 2002/06/16 03:43:50 lpd Exp $ */
18 /* Composite font-related character operators */
19 #include "ghost.h"
20 #include "oper.h"
21 #include "gsmatrix.h" /* for gxfont.h */
22 #include "gxfixed.h" /* for gxfont.h */
23 #include "gxfont.h"
24 #include "gxtext.h"
25 #include "estack.h"
26 #include "ichar.h"
27 #include "ifont.h"
28 #include "igstate.h"
29 #include "store.h"
30
31 /* Forward references */
32 private int cshow_continue(i_ctx_t *);
33 private int cshow_restore_font(i_ctx_t *);
34
35 /* <proc> <string> cshow - */
36 private int
zcshow(i_ctx_t * i_ctx_p)37 zcshow(i_ctx_t *i_ctx_p)
38 {
39 os_ptr op = osp;
40 os_ptr proc_op = op - 1;
41 os_ptr str_op = op;
42 gs_text_enum_t *penum;
43 int code;
44
45 /*
46 * Even though this is not documented anywhere by Adobe,
47 * some Adobe interpreters apparently allow the string and
48 * the procedure to be provided in either order!
49 */
50 if (r_is_proc(proc_op))
51 ;
52 else if (r_is_proc(op)) { /* operands reversed */
53 proc_op = op;
54 str_op = op - 1;
55 } else {
56 check_op(2);
57 return_error(e_typecheck);
58 }
59 if ((code = op_show_setup(i_ctx_p, str_op)) != 0 ||
60 (code = gs_cshow_begin(igs, str_op->value.bytes, r_size(str_op),
61 imemory, &penum)) < 0)
62 return code;
63 if ((code = op_show_finish_setup(i_ctx_p, penum, 2, NULL)) < 0) {
64 ifree_object(penum, "op_show_enum_setup");
65 return code;
66 }
67 sslot = *proc_op; /* save kerning proc */
68 pop(2);
69 return cshow_continue(i_ctx_p);
70 }
71 private int
cshow_continue(i_ctx_t * i_ctx_p)72 cshow_continue(i_ctx_t *i_ctx_p)
73 {
74 os_ptr op = osp;
75 gs_text_enum_t *penum = senum;
76 int code;
77
78 check_estack(4); /* in case we call the procedure */
79 code = gs_text_process(penum);
80 if (code != TEXT_PROCESS_INTERVENE) {
81 code = op_show_continue_dispatch(i_ctx_p, 0, code);
82 if (code == o_push_estack) /* must be TEXT_PROCESS_RENDER */
83 make_op_estack(esp - 1, cshow_continue);
84 return code;
85 }
86 /* Push the character code and width, and call the procedure. */
87 {
88 ref *pslot = &sslot;
89 gs_point wpt;
90 gs_font *font = gs_text_current_font(penum);
91 gs_font *root_font = gs_rootfont(igs);
92 gs_font *scaled_font;
93 uint font_space = r_space(pfont_dict(font));
94 uint root_font_space = r_space(pfont_dict(root_font));
95 int fdepth = penum->fstack.depth;
96
97 gs_text_current_width(penum, &wpt);
98 if (font == root_font)
99 scaled_font = font;
100 else if (fdepth > 0) {
101 /* Construct a scaled version of the leaf font.
102 If font stack is deep enough, get the matrix for scaling
103 from the immediate parent of current font.
104 (The font matrix of root font is not good for the purpose
105 in some case.)
106 assert (penum->fstack.items[fdepth].font == font
107 && penum->fstack.items[0].font == root_font); */
108 uint save_space = idmemory->current_space;
109 gs_font * immediate_parent = penum->fstack.items[fdepth - 1].font;
110
111 ialloc_set_space(idmemory, font_space);
112 code = gs_makefont(font->dir, font,
113 &immediate_parent->FontMatrix,
114 &scaled_font);
115 ialloc_set_space(idmemory, save_space);
116 if (code < 0)
117 return code;
118 }
119 else {
120 /* Construct a scaled version of the leaf font. */
121 uint save_space = idmemory->current_space;
122
123 ialloc_set_space(idmemory, font_space);
124 code = gs_makefont(font->dir, font, &root_font->FontMatrix,
125 &scaled_font);
126 ialloc_set_space(idmemory, save_space);
127 if (code < 0)
128 return code;
129 }
130 push(3);
131 make_int(op - 2, gs_text_current_char(penum) & 0xff);
132 make_real(op - 1, wpt.x);
133 make_real(op, wpt.y);
134 make_struct(&ssfont, font_space, font);
135 make_struct(&srfont, root_font_space, root_font);
136 push_op_estack(cshow_restore_font);
137 /* cshow does not change rootfont for user procedure */
138 gs_set_currentfont(igs, scaled_font);
139 *++esp = *pslot; /* user procedure */
140 }
141 return o_push_estack;
142 }
143 private int
cshow_restore_font(i_ctx_t * i_ctx_p)144 cshow_restore_font(i_ctx_t *i_ctx_p)
145 {
146 /* We must restore both the root font and the current font. */
147 gs_setfont(igs, r_ptr(&srfont, gs_font));
148 gs_set_currentfont(igs, r_ptr(&ssfont, gs_font));
149 return cshow_continue(i_ctx_p);
150 }
151
152 /* - rootfont <font> */
153 private int
zrootfont(i_ctx_t * i_ctx_p)154 zrootfont(i_ctx_t *i_ctx_p)
155 {
156 os_ptr op = osp;
157
158 push(1);
159 *op = *pfont_dict(gs_rootfont(igs));
160 return 0;
161 }
162
163 /* ------ Initialization procedure ------ */
164
165 const op_def zcfont_op_defs[] =
166 {
167 {"2cshow", zcshow},
168 {"0rootfont", zrootfont},
169 /* Internal operators */
170 {"0%cshow_continue", cshow_continue},
171 {"0%cshow_restore_font", cshow_restore_font},
172 op_def_end(0)
173 };
174