xref: /plan9/sys/src/cmd/gs/src/write_t1.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1989, 2000 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: write_t1.c,v 1.5 2004/12/08 21:35:13 stefan Exp $ */
18 
19 /*
20 Functions to serialize a type 1 font as PostScript code that can then be
21 passed to FreeType via the FAPI FreeType bridge.
22 Started by Graham Asher, 26th July 2002.
23 */
24 
25 #include "wrfont.h"
26 #include "write_t1.h"
27 
28 #include <assert.h>
29 
30 /*
31 Public structures and functions in this file are prefixed with FF_ because they are part of
32 the FAPI FreeType implementation.
33 */
34 
write_word_entry(FAPI_font * a_fapi_font,WRF_output * a_output,const char * a_name,int a_index,int a_divisor)35 static void write_word_entry(FAPI_font* a_fapi_font,WRF_output* a_output,const char* a_name,int a_index,int a_divisor)
36 	{
37 	short x;
38 	WRF_wbyte(a_output,'/');
39 	WRF_wstring(a_output,a_name);
40 	WRF_wbyte(a_output,' ');
41 	/* Get the value and convert it from unsigned to signed by assigning it to a short. */
42 	x = a_fapi_font->get_word(a_fapi_font,a_index,0);
43 	/* Divide by the divisor to bring it back to font units. */
44 	x = (short)(x / a_divisor);
45 	WRF_wint(a_output,x);
46 	WRF_wstring(a_output," def\n");
47 	}
48 
write_array_entry_with_count(FAPI_font * a_fapi_font,WRF_output * a_output,const char * a_name,int a_index,int a_count,int a_divisor)49 static void write_array_entry_with_count(FAPI_font* a_fapi_font,WRF_output* a_output,const char* a_name,int a_index,int a_count,int a_divisor)
50 	{
51 	int i;
52 
53 	assert(a_count >= 0);
54 	if (a_count == 0)
55 		return;
56 
57 	WRF_wbyte(a_output,'/');
58 	WRF_wstring(a_output,a_name);
59 	WRF_wstring(a_output," [");
60 	for (i = 0; i < a_count; i++)
61 		{
62 		/* Get the value and convert it from unsigned to signed by assigning it to a short. */
63 		short x = a_fapi_font->get_word(a_fapi_font,a_index,i);
64 		/* Divide by the divisor to bring it back to font units. */
65 		x = (short)(x / a_divisor);
66 		WRF_wint(a_output,x);
67 		WRF_wbyte(a_output,(byte)(i == a_count - 1 ? ']' : ' '));
68 		}
69 	WRF_wstring(a_output," def\n");
70 	}
71 
72 
write_array_entry(FAPI_font * a_fapi_font,WRF_output * a_output,const char * a_name,int a_index,int a_divisor)73 static void write_array_entry(FAPI_font* a_fapi_font,WRF_output* a_output,const char* a_name,int a_index,int a_divisor)
74 	{
75 	/* NOTE that the feature index must be preceded by the count index for this to work. */
76 	int count = a_fapi_font->get_word(a_fapi_font,a_index - 1,0);
77 	write_array_entry_with_count(a_fapi_font,a_output,a_name,a_index,count,a_divisor);
78 	}
79 
write_subrs(FAPI_font * a_fapi_font,WRF_output * a_output)80 static void write_subrs(FAPI_font* a_fapi_font,WRF_output* a_output)
81 	{
82 	int i;
83 	int count = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_Subrs_count,0);
84 	assert(count >= 0);
85 	if (count == 0)
86 		return;
87 
88 	WRF_wstring(a_output,"/Subrs ");
89 	WRF_wint(a_output,count);
90 	WRF_wstring(a_output," array\n");
91 
92 	for (i = 0; i < count; i++)
93 		{
94 		long length = a_fapi_font->get_subr(a_fapi_font,i,0,0);
95 		long buffer_size;
96 		WRF_wstring(a_output,"dup ");
97 		WRF_wint(a_output,i);
98 		WRF_wbyte(a_output,' ');
99 		WRF_wint(a_output,length);
100 		WRF_wstring(a_output," RD ");
101 
102 		/* Get the subroutine into the buffer and encrypt it in place. */
103 		buffer_size = a_output->m_limit - a_output->m_count;
104 		if (buffer_size >= length)
105 			{
106 			a_fapi_font->get_subr(a_fapi_font,i,a_output->m_pos,(ushort)length);
107 			WRF_wtext(a_output,a_output->m_pos,length);
108 			}
109 		else
110 			a_output->m_count += length;
111 
112 		WRF_wstring(a_output," NP\n");
113 		}
114 
115 	WRF_wstring(a_output,"ND\n");
116 	}
117 
write_private_dictionary(FAPI_font * a_fapi_font,WRF_output * a_output)118 static void write_private_dictionary(FAPI_font* a_fapi_font,WRF_output* a_output)
119 	{
120 	assert(!a_output->m_encrypt);
121 	a_output->m_encrypt = true;
122 
123 	/* Write 4 bytes that must encrypt to at least one character that cannot be a valid hexadecimal character. */
124 	WRF_wstring(a_output,"XXXX");
125 
126 	/*+ to do: correct size of dictionary from 8. */
127 	WRF_wstring(a_output,"dup /Private 8 dict dup begin\n");
128 
129 	WRF_wstring(a_output,"/MinFeature {16 16} def\n");
130 	WRF_wstring(a_output,"/password 5839 def\n");
131 	WRF_wstring(a_output,"/lenIV -1 def\n"); /* indicate that /subrs are not encoded. */
132 	write_word_entry(a_fapi_font,a_output,"BlueFuzz",FAPI_FONT_FEATURE_BlueFuzz,16);
133 
134 	WRF_wstring(a_output,"/BlueScale ");
135 	WRF_wfloat(a_output,a_fapi_font->get_long(a_fapi_font,FAPI_FONT_FEATURE_BlueScale,0) / 65536.0);
136 	WRF_wstring(a_output," def\n");
137 
138 	write_word_entry(a_fapi_font,a_output,"BlueShift",FAPI_FONT_FEATURE_BlueShift,16);
139 	write_array_entry(a_fapi_font,a_output,"BlueValues",FAPI_FONT_FEATURE_BlueValues,16);
140 	write_array_entry(a_fapi_font,a_output,"OtherBlues",FAPI_FONT_FEATURE_OtherBlues,16);
141 	write_array_entry(a_fapi_font,a_output,"FamilyBlues",FAPI_FONT_FEATURE_FamilyBlues,16);
142 	write_array_entry(a_fapi_font,a_output,"FamilyOtherBlues",FAPI_FONT_FEATURE_FamilyOtherBlues,16);
143 	write_word_entry(a_fapi_font,a_output,"ForceBold",FAPI_FONT_FEATURE_ForceBold,1);
144 	write_array_entry_with_count(a_fapi_font,a_output,"StdHW",FAPI_FONT_FEATURE_StdHW,1,16);
145 	write_array_entry_with_count(a_fapi_font,a_output,"StdVW",FAPI_FONT_FEATURE_StdVW,1,16);
146 	write_array_entry(a_fapi_font,a_output,"StemSnapH",FAPI_FONT_FEATURE_StemSnapH,16);
147 	write_array_entry(a_fapi_font,a_output,"StemSnapV",FAPI_FONT_FEATURE_StemSnapV,16);
148 
149 	write_subrs(a_fapi_font,a_output);
150 	}
151 
write_main_dictionary(FAPI_font * a_fapi_font,WRF_output * a_output)152 static void write_main_dictionary(FAPI_font* a_fapi_font,WRF_output* a_output)
153 	{
154 	int i;
155 	WRF_wstring(a_output,"5 dict begin\n");
156 
157     WRF_wstring(a_output,"/FontType 1 def\n");
158 
159 	WRF_wstring(a_output,"/FontMatrix [");
160 	for (i = 0; i < 6; i++)
161 		{
162 		WRF_wfloat(a_output,a_fapi_font->get_float(a_fapi_font,FAPI_FONT_FEATURE_FontMatrix,i));
163 		WRF_wbyte(a_output,(byte)(i == 5 ? ']' : ' '));
164 		}
165 	WRF_wbyte(a_output,'\n');
166 
167 	/* For now, specify standard encoding - I think GS will pass glyph indices so doesn't matter. */
168 	WRF_wstring(a_output,"/Encoding StandardEncoding def\n");
169 
170 	WRF_wstring(a_output,"/FontBBox {");
171 	for (i = 0; i < 4; i++)
172 		{
173 		short x = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_FontBBox,i);
174 		WRF_wint(a_output,x);
175 		WRF_wbyte(a_output,(byte)(i == 3 ? '}' : ' '));
176 		}
177 	WRF_wbyte(a_output,'\n');
178 	WRF_wstring(a_output,"currentdict end\ncurrentfile eexec\n");
179 	write_private_dictionary(a_fapi_font,a_output);
180 	}
181 
182 /**
183 Write a Type 1 font in textual format and return its length in bytes.
184 If a_buffer_size is less than the total length, only a_buffer_size bytes are written, but the total
185 length is returned correctly.
186 
187 The PostScript is non-standard. The main dictionary contains no /Charstrings dictionary. This
188 is supplied to FreeType using the incremental interface, There is also no /PaintType entry. This is required
189 by PostScript but FreeType doesn't use it.
190 */
FF_serialize_type1_font(FAPI_font * a_fapi_font,unsigned char * a_buffer,long a_buffer_size)191 long FF_serialize_type1_font(FAPI_font* a_fapi_font,unsigned char* a_buffer,long a_buffer_size)
192 	{
193 	WRF_output output;
194 	WRF_init(&output,a_buffer,a_buffer_size);
195 
196 	/* Leading comment identifying a Type 1 font. */
197 	WRF_wstring(&output,"%!PS-AdobeFont-1\n");
198 
199 	write_main_dictionary(a_fapi_font,&output);
200 	return output.m_count;
201 	}
202