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