1 /* Copyright (C) 1998, 1999 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: zcfont.c,v 1.2.6.2.2.1 2003/01/17 00:49:05 giles Exp $ */
20 /* Composite font-related character operators */
21 #include "ghost.h"
22 #include "oper.h"
23 #include "gsmatrix.h"		/* for gxfont.h */
24 #include "gxfixed.h"		/* for gxfont.h */
25 #include "gxfont.h"
26 #include "gxtext.h"
27 #include "estack.h"
28 #include "ichar.h"
29 #include "ifont.h"
30 #include "igstate.h"
31 #include "store.h"
32 
33 /* Forward references */
34 private int cshow_continue(P1(i_ctx_t *));
35 private int cshow_restore_font(P1(i_ctx_t *));
36 
37 /* <proc> <string> cshow - */
38 private int
zcshow(i_ctx_t * i_ctx_p)39 zcshow(i_ctx_t *i_ctx_p)
40 {
41     os_ptr op = osp;
42     os_ptr proc_op = op - 1;
43     os_ptr str_op = op;
44     gs_text_enum_t *penum;
45     int code;
46 
47     /*
48      * Even though this is not documented anywhere by Adobe,
49      * some Adobe interpreters apparently allow the string and
50      * the procedure to be provided in either order!
51      */
52     if (r_is_proc(proc_op))
53 	;
54     else if (r_is_proc(op)) {	/* operands reversed */
55 	proc_op = op;
56 	str_op = op - 1;
57     } else {
58 	check_op(2);
59 	return_error(e_typecheck);
60     }
61     if ((code = op_show_setup(i_ctx_p, str_op)) != 0 ||
62 	(code = gs_cshow_begin(igs, str_op->value.bytes, r_size(str_op),
63 			       imemory, &penum)) < 0)
64 	return code;
65     if ((code = op_show_finish_setup(i_ctx_p, penum, 2, NULL)) < 0) {
66 	ifree_object(penum, "op_show_enum_setup");
67 	return code;
68     }
69     sslot = *proc_op;		/* save kerning proc */
70     pop(2);
71     return cshow_continue(i_ctx_p);
72 }
73 private int
cshow_continue(i_ctx_t * i_ctx_p)74 cshow_continue(i_ctx_t *i_ctx_p)
75 {
76     os_ptr op = osp;
77     gs_text_enum_t *penum = senum;
78     int code;
79 
80     check_estack(4);		/* in case we call the procedure */
81     code = gs_text_process(penum);
82     if (code != TEXT_PROCESS_INTERVENE) {
83 	code = op_show_continue_dispatch(i_ctx_p, 0, code);
84 	if (code == o_push_estack)	/* must be TEXT_PROCESS_RENDER */
85 	    make_op_estack(esp - 1, cshow_continue);
86 	return code;
87     }
88     /* Push the character code and width, and call the procedure. */
89     {
90 	ref *pslot = &sslot;
91 	gs_point wpt;
92 	gs_font *font = gs_text_current_font(penum);
93 	gs_font *root_font = gs_rootfont(igs);
94 	gs_font *scaled_font;
95 	uint font_space = r_space(pfont_dict(font));
96 	uint root_font_space = r_space(pfont_dict(root_font));
97 	int fdepth = penum->fstack.depth;
98 
99 	gs_text_current_width(penum, &wpt);
100 	if (font == root_font)
101 	    scaled_font = font;
102 	else if (fdepth > 0) {
103 	  /* Construct a scaled version of the leaf font.
104 	     If font stack is deep enough, get the matrix for scaling
105 	     from the immediate parent of current font.
106 	     (The font matrix of root font is not good for the purpose
107 	     in some case.)
108 	     assert (penum->fstack.items[fdepth].font == font
109 	             && penum->fstack.items[0].font == root_font); */
110 	  uint save_space = idmemory->current_space;
111 	  gs_font * immediate_parent = penum->fstack.items[fdepth - 1].font;
112 
113 	  ialloc_set_space(idmemory, font_space);
114 	  code = gs_makefont(font->dir, font,
115 			     &immediate_parent->FontMatrix,
116 			     &scaled_font);
117 	  ialloc_set_space(idmemory, save_space);
118 	  if (code < 0)
119 	    return code;
120 	}
121 	else {
122 	    /* Construct a scaled version of the leaf font. */
123 	    uint save_space = idmemory->current_space;
124 
125 	    ialloc_set_space(idmemory, font_space);
126 	    code = gs_makefont(font->dir, font, &root_font->FontMatrix,
127 			       &scaled_font);
128 	    ialloc_set_space(idmemory, save_space);
129 	    if (code < 0)
130 		return code;
131 	}
132 	push(3);
133 	make_int(op - 2, gs_text_current_char(penum) & 0xff);
134 	make_real(op - 1, wpt.x);
135 	make_real(op, wpt.y);
136 	make_struct(&ssfont, font_space, font);
137 	make_struct(&srfont, root_font_space, root_font);
138 	push_op_estack(cshow_restore_font);
139 	/* cshow does not change rootfont for user procedure */
140 	gs_set_currentfont(igs, scaled_font);
141 	*++esp = *pslot;	/* user procedure */
142     }
143     return o_push_estack;
144 }
145 private int
cshow_restore_font(i_ctx_t * i_ctx_p)146 cshow_restore_font(i_ctx_t *i_ctx_p)
147 {
148     /* We must restore both the root font and the current font. */
149     gs_setfont(igs, r_ptr(&srfont, gs_font));
150     gs_set_currentfont(igs, r_ptr(&ssfont, gs_font));
151     return cshow_continue(i_ctx_p);
152 }
153 
154 /* - rootfont <font> */
155 private int
zrootfont(i_ctx_t * i_ctx_p)156 zrootfont(i_ctx_t *i_ctx_p)
157 {
158     os_ptr op = osp;
159 
160     push(1);
161     *op = *pfont_dict(gs_rootfont(igs));
162     return 0;
163 }
164 
165 /* ------ Initialization procedure ------ */
166 
167 const op_def zcfont_op_defs[] =
168 {
169     {"2cshow", zcshow},
170     {"0rootfont", zrootfont},
171 		/* Internal operators */
172     {"0%cshow_continue", cshow_continue},
173     {"0%cshow_restore_font", cshow_restore_font},
174     op_def_end(0)
175 };
176