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: write_t1.c 9742 2009-05-15 12:13:25Z ken $ */
15 
16 /*
17 Functions to serialize a type 1 font as PostScript code that can then be
18 passed to FreeType via the FAPI FreeType bridge.
19 Started by Graham Asher, 26th July 2002.
20 */
21 
22 #include "wrfont.h"
23 #include "write_t1.h"
24 
25 /*
26 Public structures and functions in this file are prefixed with FF_ because they are part of
27 the FAPI FreeType implementation.
28 */
29 
write_word_entry(FAPI_font * a_fapi_font,WRF_output * a_output,const char * a_name,int a_index,int a_divisor)30 static void write_word_entry(FAPI_font* a_fapi_font,WRF_output* a_output,const char* a_name,int a_index,int a_divisor)
31 	{
32 	short x;
33 	WRF_wbyte(a_output,'/');
34 	WRF_wstring(a_output,a_name);
35 	WRF_wbyte(a_output,' ');
36 	/* Get the value and convert it from unsigned to signed by assigning it to a short. */
37 	x = a_fapi_font->get_word(a_fapi_font,a_index,0);
38 	/* Divide by the divisor to bring it back to font units. */
39 	x = (short)(x / a_divisor);
40 	WRF_wint(a_output,x);
41 	WRF_wstring(a_output," def\n");
42 	}
43 
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)44 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)
45 	{
46 	int i;
47 
48 	if (a_count <= 0)
49 		return;
50 
51 	WRF_wbyte(a_output,'/');
52 	WRF_wstring(a_output,a_name);
53 	WRF_wstring(a_output," [");
54 	for (i = 0; i < a_count; i++)
55 		{
56 		/* Get the value and convert it from unsigned to signed by assigning it to a short. */
57 		short x = a_fapi_font->get_word(a_fapi_font,a_index,i);
58 		/* Divide by the divisor to bring it back to font units. */
59 		x = (short)(x / a_divisor);
60 		WRF_wint(a_output,x);
61 		WRF_wbyte(a_output,(byte)(i == a_count - 1 ? ']' : ' '));
62 		}
63 	WRF_wstring(a_output," def\n");
64 	}
65 
66 
write_array_entry(FAPI_font * a_fapi_font,WRF_output * a_output,const char * a_name,int a_index,int a_divisor)67 static void write_array_entry(FAPI_font* a_fapi_font,WRF_output* a_output,const char* a_name,int a_index,int a_divisor)
68 	{
69 	/* NOTE that the feature index must be preceded by the count index for this to work. */
70 	int count = a_fapi_font->get_word(a_fapi_font,a_index - 1,0);
71 	write_array_entry_with_count(a_fapi_font,a_output,a_name,a_index,count,a_divisor);
72 	}
73 
write_subrs(FAPI_font * a_fapi_font,WRF_output * a_output)74 static void write_subrs(FAPI_font* a_fapi_font,WRF_output* a_output)
75 	{
76 	int i;
77 	int count = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_Subrs_count,0);
78 	if (count <= 0)
79 		return;
80 
81 	WRF_wstring(a_output,"/Subrs ");
82 	WRF_wint(a_output,count);
83 	WRF_wstring(a_output," array\n");
84 
85 	for (i = 0; i < count; i++)
86 		{
87 		long length = a_fapi_font->get_subr(a_fapi_font,i,0,0);
88 		long buffer_size;
89 		WRF_wstring(a_output,"dup ");
90 		WRF_wint(a_output,i);
91 		WRF_wbyte(a_output,' ');
92 		WRF_wint(a_output,length);
93 		WRF_wstring(a_output," RD ");
94 
95 		/* Get the subroutine into the buffer and encrypt it in place. */
96 		buffer_size = a_output->m_limit - a_output->m_count;
97 		if (buffer_size >= length)
98 			{
99 			a_fapi_font->get_subr(a_fapi_font,i,a_output->m_pos,(ushort)length);
100 			WRF_wtext(a_output,a_output->m_pos,length);
101 			}
102 		else
103 			a_output->m_count += length;
104 
105 		WRF_wstring(a_output," NP\n");
106 		}
107 
108 	WRF_wstring(a_output,"ND\n");
109 	}
110 
is_MM_font(FAPI_font * a_fapi_font)111 static int is_MM_font(FAPI_font *a_fapi_font)
112 {
113     return a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_DollarBlend,0);
114 }
115 
write_private_dictionary(FAPI_font * a_fapi_font,WRF_output * a_output)116 static void write_private_dictionary(FAPI_font* a_fapi_font,WRF_output* a_output)
117 	{
118 	a_output->m_encrypt = true;
119 
120 	/* Write 4 bytes that must encrypt to at least one character that cannot be a valid hexadecimal character. */
121 	WRF_wstring(a_output,"XXXX");
122 
123 	/*+ to do: correct size of dictionary from 8. */
124 	WRF_wstring(a_output,"dup /Private 8 dict dup begin\n");
125 
126 	WRF_wstring(a_output,"/MinFeature {16 16} def\n");
127 	WRF_wstring(a_output,"/password 5839 def\n");
128 	WRF_wstring(a_output,"/lenIV -1 def\n"); /* indicate that /subrs are not encoded. */
129 	write_word_entry(a_fapi_font,a_output,"BlueFuzz",FAPI_FONT_FEATURE_BlueFuzz,16);
130 
131 	WRF_wstring(a_output,"/BlueScale ");
132 	WRF_wfloat(a_output,a_fapi_font->get_long(a_fapi_font,FAPI_FONT_FEATURE_BlueScale,0) / 65536.0);
133 	WRF_wstring(a_output," def\n");
134 
135 	write_word_entry(a_fapi_font,a_output,"BlueShift",FAPI_FONT_FEATURE_BlueShift,16);
136 	write_array_entry(a_fapi_font,a_output,"BlueValues",FAPI_FONT_FEATURE_BlueValues,16);
137 	write_array_entry(a_fapi_font,a_output,"OtherBlues",FAPI_FONT_FEATURE_OtherBlues,16);
138 	write_array_entry(a_fapi_font,a_output,"FamilyBlues",FAPI_FONT_FEATURE_FamilyBlues,16);
139 	write_array_entry(a_fapi_font,a_output,"FamilyOtherBlues",FAPI_FONT_FEATURE_FamilyOtherBlues,16);
140 	write_word_entry(a_fapi_font,a_output,"ForceBold",FAPI_FONT_FEATURE_ForceBold,1);
141 	write_array_entry_with_count(a_fapi_font,a_output,"StdHW",FAPI_FONT_FEATURE_StdHW,1,16);
142 	write_array_entry_with_count(a_fapi_font,a_output,"StdVW",FAPI_FONT_FEATURE_StdVW,1,16);
143 	write_array_entry(a_fapi_font,a_output,"StemSnapH",FAPI_FONT_FEATURE_StemSnapH,16);
144 	write_array_entry(a_fapi_font,a_output,"StemSnapV",FAPI_FONT_FEATURE_StemSnapV,16);
145 
146 	if (is_MM_font(a_fapi_font)) {
147 	    WRF_wstring(a_output,"3 index /Blend get /Private get begin\n");
148 	    WRF_wstring(a_output,"|-\n");
149 	}
150 	write_subrs(a_fapi_font,a_output);
151 	}
152 
write_blend_dictionary(FAPI_font * a_fapi_font,WRF_output * a_output)153 static void write_blend_dictionary(FAPI_font* a_fapi_font,WRF_output* a_output)
154 {
155 }
156 
write_main_dictionary(FAPI_font * a_fapi_font,WRF_output * a_output)157 static void write_main_dictionary(FAPI_font* a_fapi_font,WRF_output* a_output)
158 	{
159 	int i;
160 	WRF_wstring(a_output,"5 dict begin\n");
161 
162     WRF_wstring(a_output,"/FontType 1 def\n");
163 
164 	WRF_wstring(a_output,"/FontMatrix [");
165 	for (i = 0; i < 6; i++)
166 		{
167 		WRF_wfloat(a_output,a_fapi_font->get_float(a_fapi_font,FAPI_FONT_FEATURE_FontMatrix,i));
168 		WRF_wbyte(a_output,(byte)(i == 5 ? ']' : ' '));
169 		}
170 	WRF_wbyte(a_output,'\n');
171 
172 	/* For now, specify standard encoding - I think GS will pass glyph indices so doesn't matter. */
173 	WRF_wstring(a_output,"/Encoding StandardEncoding def\n");
174 
175 	WRF_wstring(a_output,"/FontBBox {");
176 	for (i = 0; i < 4; i++)
177 		{
178 		short x = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_FontBBox,i);
179 		WRF_wint(a_output,x);
180 		WRF_wbyte(a_output,(byte)(i == 3 ? '}' : ' '));
181 		}
182 	WRF_wbyte(a_output,'\n');
183 	if (is_MM_font(a_fapi_font)) {
184 	    short x,x2;
185 	    float x1;
186 	    uint i, j, entries;
187 	    char Buffer[255];
188 
189 	    entries = 0;
190     	    x = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_BlendAxisTypes_count,0);
191 	    if (x)
192 		entries++;
193 	    x = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_BlendDesignPositionsArrays_count,0);
194 	    if (x)
195 		entries++;
196 	    x = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_BlendDesignMapArrays_count,0);
197 	    if (x)
198 		entries++;
199 
200 	    sprintf(Buffer, "/FontInfo %d dict dup begin\n", entries);
201 	    WRF_wstring(a_output, Buffer);
202 	    x = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_BlendAxisTypes_count,0);
203 	    if (x) {
204 		WRF_wstring(a_output, "/BlendAxisTypes [");
205 		for (i = 0;i < x;i++) {
206 		    WRF_wstring(a_output," /");
207 		    a_fapi_font->get_name(a_fapi_font,FAPI_FONT_FEATURE_BlendAxisTypes,i, (char *)&Buffer,255);
208 		    WRF_wstring(a_output,Buffer);
209 		}
210 		WRF_wstring(a_output,"] def\n");
211 	    }
212 	    x = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_BlendDesignPositionsArrays_count,0);
213 	    if (x) {
214 		WRF_wstring(a_output, "/BlendDesignPositions [");
215 		x2 = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_BlendAxisTypes_count,0);
216 		for (i = 0;i < x; i++) {
217 		    WRF_wstring(a_output,"[");
218 		    for (j = 0; j < x2; j++) {
219 			x1 = a_fapi_font->get_float(a_fapi_font,FAPI_FONT_FEATURE_BlendDesignPositionsArrayValue,i*8+j);
220 			sprintf(Buffer, "%f ", x1);
221 			WRF_wstring(a_output,Buffer);
222 		    }
223 		    WRF_wstring(a_output,"]");
224 		}
225 	    WRF_wstring(a_output, "] def\n");
226 	    }
227 	    x = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_BlendDesignMapArrays_count,0);
228 	    if (x) {
229 		WRF_wstring(a_output, "/BlendDesignMap [");
230 		for (i = 0;i < x;i++) {
231 		    x2 = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_BlendDesignMapSubArrays_count,i);
232 		    WRF_wstring(a_output,"[");
233 		    for (j = 0; j < x2; j++) {
234 			WRF_wstring(a_output,"[");
235 			x1 = a_fapi_font->get_float(a_fapi_font,FAPI_FONT_FEATURE_BlendDesignPositionsArrayValue,i*64+j*64);
236 			sprintf(Buffer, "%f ", x1);
237 			WRF_wstring(a_output,Buffer);
238 			x1 = a_fapi_font->get_float(a_fapi_font,FAPI_FONT_FEATURE_BlendDesignPositionsArrayValue,i*64+j*64 + 1);
239 			sprintf(Buffer, "%f ", x1);
240 			WRF_wstring(a_output,Buffer);
241 			WRF_wstring(a_output,"]");
242 		    }
243 		    WRF_wstring(a_output,"]");
244 		}
245 		WRF_wstring(a_output, "] def\n");
246 	    }
247 	    WRF_wstring(a_output,"end readonly def\n");
248 	    WRF_wstring(a_output,"/$Blend {");
249 	    x = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_DollarBlend_length,0);
250 	    if(a_output->m_count)
251 		a_output->m_count += x;
252 	    x = a_fapi_font->get_proc(a_fapi_font,FAPI_FONT_FEATURE_DollarBlend,0,(char *)a_output->m_pos);
253 	    if(a_output->m_pos)
254 		a_output->m_pos += x;
255 	    WRF_wstring(a_output,"} def\n");
256 	    WRF_wstring(a_output,"/$Blend {0.1 mul exch 0.45 mul add exch 0.17 mul add add} def\n");
257 	    WRF_wstring(a_output,"/WeightVector [");
258 	    x = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_WeightVector_count,0);
259 	    for (i = 0;i < x;i++) {
260 		x1 = a_fapi_font->get_float(a_fapi_font,FAPI_FONT_FEATURE_WeightVector,i);
261 		sprintf(Buffer, "%f ", x1);
262 		WRF_wstring(a_output,Buffer);
263 	    }
264 	    WRF_wstring(a_output,"] def\n");
265 	}
266 	WRF_wstring(a_output,"currentdict end\ncurrentfile eexec\n");
267 	write_private_dictionary(a_fapi_font,a_output);
268 	if (is_MM_font(a_fapi_font)) {
269 	    write_blend_dictionary(a_fapi_font, a_output);
270 	}
271 	}
272 
273 /**
274 Write a Type 1 font in textual format and return its length in bytes.
275 If a_buffer_size is less than the total length, only a_buffer_size bytes are written, but the total
276 length is returned correctly.
277 
278 The PostScript is non-standard. The main dictionary contains no /Charstrings dictionary. This
279 is supplied to FreeType using the incremental interface, There is also no /PaintType entry. This is required
280 by PostScript but FreeType doesn't use it.
281 */
FF_serialize_type1_font(FAPI_font * a_fapi_font,unsigned char * a_buffer,long a_buffer_size)282 long FF_serialize_type1_font(FAPI_font* a_fapi_font,unsigned char* a_buffer,long a_buffer_size)
283 	{
284 	WRF_output output;
285 	WRF_init(&output,a_buffer,a_buffer_size);
286 
287 	/* Leading comment identifying a Type 1 font. */
288 	WRF_wstring(&output,"%!PS-AdobeFont-1\n");
289 
290 	write_main_dictionary(a_fapi_font,&output);
291 	return output.m_count;
292 	}
293