xref: /plan9/sys/src/cmd/gs/src/zcfont.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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