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