xref: /plan9/sys/src/cmd/gs/src/write_t2.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_t2.c,v 1.7 2004/12/08 21:35:13 stefan Exp $ */
18 
19 /*
20 Functions to serialize a type 1 font so that it can then be
21 passed to FreeType via the FAPI FreeType bridge.
22 Started by Graham Asher, 9th August 2002.
23 */
24 
25 #include "wrfont.h"
26 #include "write_t2.h"
27 #include "ghost.h"
28 #include "gxfont.h"
29 #include "gxfont1.h"
30 
31 #include <assert.h>
32 
33 /*
34 Public structures and functions in this file are prefixed with FF_ because they are part of
35 the FAPI FreeType implementation.
36 */
37 
write_4_byte_int(unsigned char * a_output,long a_int)38 static void write_4_byte_int(unsigned char* a_output,long a_int)
39 	{
40 	a_output[0] = (unsigned char)(a_int >> 24);
41 	a_output[1] = (unsigned char)(a_int >> 16);
42 	a_output[2] = (unsigned char)(a_int >> 8);
43 	a_output[3] = (unsigned char)(a_int & 0xFF);
44 	}
45 
write_type2_int(WRF_output * a_output,long a_int)46 static void write_type2_int(WRF_output* a_output,long a_int)
47 	{
48 	if (a_int >= -107 && a_int <= 107)
49 		WRF_wbyte(a_output,(unsigned char)(a_int + 139));
50 	else if (a_int >= -32768 && a_int <= 32767)
51 		{
52 		if (a_int >= 108 && a_int <= 1131)
53 			a_int += 63124;
54 		else if (a_int >= -1131 && a_int <= -108)
55 			a_int = -a_int + 64148;
56 		else
57 			WRF_wbyte(a_output,28);
58 		WRF_wbyte(a_output,(unsigned char)(a_int >> 8));
59 		WRF_wbyte(a_output,(unsigned char)(a_int & 0xFF));
60 		}
61 	else
62 		{
63 		unsigned char buffer[4];
64 		WRF_wbyte(a_output,29);
65 		write_4_byte_int(buffer,a_int);
66 		WRF_wtext(a_output,buffer,4);
67 		}
68 	}
69 
write_type2_float(WRF_output * a_output,double a_float)70 static void write_type2_float(WRF_output* a_output,double a_float)
71 	{
72 	char buffer[32];
73 	const char* p = buffer;
74 	int high = true;
75 	char c = 0;
76 	sprintf(buffer,"%f",a_float);
77 	WRF_wbyte(a_output,30);
78 	for (;;)
79 		{
80 		char n = 0;
81 		if (*p >= '0' && *p <= '9')
82 			n = (char)(*p - '0');
83 		else if (*p == '.')
84 			n = 0xA;
85 		else if (*p == 'e' || *p == 'E')
86 			{
87 			if (p[1] == '-')
88 				{
89 				p++;
90 				n = 0xC;
91 				}
92 			else
93 				n = 0xB;
94 			}
95 		else if (*p == '-')
96 			n = 0xE;
97 		else if (*p == 0)
98 			n = 0xF;
99 		if (high)
100 			{
101 			if (*p == 0)
102 				WRF_wbyte(a_output,0xFF);
103 			else
104 				c = (char)(n << 4);
105 			}
106 		else
107 			{
108 			c |= n;
109 			WRF_wbyte(a_output,c);
110 			}
111 
112 		if (*p == 0)
113 			break;
114 
115 		high = !high;
116 		p++;
117 		}
118 	}
119 
write_header(WRF_output * a_output)120 static void write_header(WRF_output* a_output)
121 	{
122 	WRF_wtext(a_output,(const unsigned char*)"\x1\x0\x4\x1",4);
123 	}
124 
write_name_index(WRF_output * a_output)125 static void write_name_index(WRF_output* a_output)
126 	{
127 	/* Write a dummy name of 'x'. */
128 	WRF_wtext(a_output,(const unsigned char*)"\x0\x1\x1\x1\x2""x",6);
129 	}
130 
write_word_entry(FAPI_font * a_fapi_font,WRF_output * a_output,int a_feature_id,int a_feature_count,bool a_two_byte_op,int a_op,int a_divisor)131 static void write_word_entry(FAPI_font* a_fapi_font,WRF_output* a_output,int a_feature_id,
132 							 int a_feature_count,bool a_two_byte_op,int a_op,int a_divisor)
133 	{
134 	if (a_feature_count > 0)
135 		{
136 		int i;
137 		for (i = 0; i < a_feature_count; i++)
138 			{
139 			/* Get the value and convert it from unsigned to signed. */
140 			short x = a_fapi_font->get_word(a_fapi_font,a_feature_id,i);
141 			/* Divide by the divisor to bring it back to font units. */
142 			x = (short)(x / a_divisor);
143 			write_type2_int(a_output,x);
144 			}
145 		if (a_two_byte_op)
146 			WRF_wbyte(a_output,12);
147 		WRF_wbyte(a_output,(unsigned char)a_op);
148 		}
149 	}
150 
write_delta_array_entry(FAPI_font * a_fapi_font,WRF_output * a_output,int a_feature_id,bool a_two_byte_op,int a_op,int a_divisor)151 static void write_delta_array_entry(FAPI_font* a_fapi_font,WRF_output* a_output,int a_feature_id,
152 									bool a_two_byte_op,int a_op,int a_divisor)
153 	{
154 	int i;
155 	/* NOTE that the feature index (a_feature_id) must be preceded by the count index for this to work. */
156 	int count = a_fapi_font->get_word(a_fapi_font,a_feature_id - 1,0);
157 	if (count > 0)
158 		{
159 		short prev_value = 0;
160 		for (i = 0; i < count; i++)
161 			{
162 			/* Get the value and convert it from unsigned to signed. */
163 			short value = a_fapi_font->get_word(a_fapi_font,a_feature_id,i);
164 			/* Divide by the divisor to bring it back to font units. */
165 			value = (short)(value / a_divisor);
166 			write_type2_int(a_output,value - prev_value);
167 			prev_value = value;
168 			}
169 		if (a_two_byte_op)
170 			WRF_wbyte(a_output,12);
171 		WRF_wbyte(a_output,(unsigned char)a_op);
172 		}
173 	}
174 
write_float_entry(FAPI_font * a_fapi_font,WRF_output * a_output,int a_feature_id,int a_feature_count,bool a_two_byte_op,int a_op)175 static void write_float_entry(FAPI_font* a_fapi_font,WRF_output* a_output,int a_feature_id,int a_feature_count,bool a_two_byte_op,int a_op)
176 	{
177 	if (a_feature_count > 0)
178 		{
179 		int i;
180 		for (i = 0; i < a_feature_count; i++)
181 			{
182 			double x = a_fapi_font->get_float(a_fapi_font,a_feature_id,i);
183 			write_type2_float(a_output,x);
184 			}
185 		if (a_two_byte_op)
186 			WRF_wbyte(a_output,12);
187 		WRF_wbyte(a_output,(unsigned char)a_op);
188 		}
189 	}
190 
write_font_dict_index(FAPI_font * a_fapi_font,WRF_output * a_output,unsigned char ** a_charset_offset_ptr,unsigned char ** a_charstrings_offset_ptr,unsigned char ** a_private_dict_length_ptr)191 static void write_font_dict_index(FAPI_font* a_fapi_font,WRF_output* a_output,
192 		unsigned char** a_charset_offset_ptr,
193 		unsigned char** a_charstrings_offset_ptr,
194 		unsigned char** a_private_dict_length_ptr)
195 	{
196 	unsigned char* data_start = 0;
197 	WRF_wtext(a_output,(const unsigned char *)"\x0\x1\x2\x0\x1\x0\x0",7); /* count = 1, offset size = 2, first offset = 1, last offset = 0 (to be filled in later). */
198 	if (a_output->m_pos)
199 		data_start = a_output->m_pos;
200 	write_word_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_FontBBox,4,false,5,1);
201 	write_float_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_FontMatrix,6,true,7);
202 	write_type2_int(a_output,0); /* 0 = Standard Encoding. */
203 	WRF_wbyte(a_output,16); /* 16 = opcode for 'encoding'. */
204 	*a_charset_offset_ptr = a_output->m_pos;
205 	WRF_wtext(a_output,(const unsigned char *)"\x1d""xxxx",5); /* placeholder for the offset to the charset, which will be a 5-byte integer. */
206 	WRF_wbyte(a_output,15); /* opcode for 'charset' */
207 	*a_charstrings_offset_ptr = a_output->m_pos;
208 	WRF_wtext(a_output,(const unsigned char *)"\x1d""xxxx",5); /* placeholder for the offset to the Charstrings index, which will be a 5-byte integer. */
209 	WRF_wbyte(a_output,17); /* opcode for 'Charstrings' */
210 	*a_private_dict_length_ptr = a_output->m_pos;
211 	WRF_wtext(a_output,(const unsigned char *)"\x1d""xxxx\x1d""yyyy",10); /* placeholder for size and offset of Private dictionary, which will be 5-byte integers. */
212 	WRF_wbyte(a_output,18); /* opcode for 'Private' */
213 	if (a_output->m_pos)
214 		{
215 		int last_offset = a_output->m_pos - data_start + 1;
216 		data_start[-2] = (unsigned char)(last_offset >> 8);
217 		data_start[-1] = (unsigned char)(last_offset & 0xFF);
218 		}
219 	}
220 
221 /**
222 Write the character set. Return the number of characters.
223 For the moment this is always 1. The number cannot be obtained
224 via the FAPI interface, and FreeType doesn't need to know anything more
225 than the fact that there is at least one character.
226 */
write_charset(WRF_output * a_output,unsigned char * a_charset_offset_ptr)227 static int write_charset(WRF_output* a_output,unsigned char* a_charset_offset_ptr)
228 	{
229 	const int characters = 1;
230 	int i = 0;
231 
232 	/* Write the offset to the start of the charset to the top dictionary. */
233 	if (a_output->m_pos)
234 		write_4_byte_int(a_charset_offset_ptr + 1,a_output->m_count);
235 
236 	/*
237 	Write the charset. Write one less than the number of characters,
238 	because the first one is assumed to be .notdef. For the moment
239 	write all the others as .notdef (SID = 0) because we don't actually
240 	need the charset at the moment.
241 	*/
242 	WRF_wbyte(a_output,0); /* format = 0 */
243 	for (i = 1; i < characters; i++)
244 		{
245 		WRF_wbyte(a_output,0);
246 		WRF_wbyte(a_output,0);
247 		}
248 
249 	return characters;
250 	}
251 
252 /**
253 Write a set of empty charstrings. The only reason for the existence of the charstrings index is to tell
254 FreeType how many glyphs there are.
255 */
write_charstrings_index(WRF_output * a_output,int a_characters,unsigned char * a_charstrings_offset_ptr)256 static void write_charstrings_index(WRF_output* a_output,int a_characters,unsigned char* a_charstrings_offset_ptr)
257 	{
258 	/* Write the offset to the charstrings index to the top dictionary. */
259 	if (a_output->m_pos)
260 		write_4_byte_int(a_charstrings_offset_ptr + 1,a_output->m_count);
261 
262 	/* Write the index. */
263 	WRF_wbyte(a_output,(unsigned char)(a_characters >> 8));
264 	WRF_wbyte(a_output,(unsigned char)(a_characters & 0xFF));
265 	WRF_wbyte(a_output,1); /* offset size = 1. */
266 	while (a_characters-- >= 0)
267 		WRF_wbyte(a_output,1); /* offset = 1 */
268 	}
269 
write_subrs_index(FAPI_font * a_fapi_font,WRF_output * a_output)270 static void write_subrs_index(FAPI_font* a_fapi_font,WRF_output* a_output)
271 	{
272 	unsigned char* cur_offset = 0;
273 	unsigned char* data_start = 0;
274 	int i;
275 	int count = a_fapi_font->get_word(a_fapi_font,FAPI_FONT_FEATURE_Subrs_count,0);
276 	assert(count >= 0);
277 
278 	WRF_wbyte(a_output,(unsigned char)(count >> 8));
279 	WRF_wbyte(a_output,(unsigned char)(count & 0xFF));
280 
281 	if (count == 0)
282 		return;
283 
284 	WRF_wbyte(a_output,4); /* offset size = 4 bytes */
285 	WRF_wtext(a_output,(const unsigned char *)"\x0\x0\x0\x1",4); /* first offset = 1 */
286 
287 	if (a_output->m_pos)
288 		cur_offset = a_output->m_pos;
289 
290 	/* Write dummy bytes for the offsets at the end of each data item. */
291 	for (i = 0; i < count; i++)
292 		WRF_wtext(a_output,(const unsigned char *)"xxxx",4);
293 
294 	if (a_output->m_pos)
295 		data_start = a_output->m_pos;
296 
297 	for (i = 0; i < count; i++)
298 		{
299 		long buffer_size = a_output->m_limit - a_output->m_count;
300 		long length = a_fapi_font->get_subr(a_fapi_font,i,a_output->m_pos,(ushort)buffer_size);
301 		if (a_output->m_pos)
302 			WRF_wtext(a_output,a_output->m_pos,length);
303 		else
304 			a_output->m_count += length;
305 		if (cur_offset)
306 			{
307 			long pos = a_output->m_pos - data_start + 1;
308 			write_4_byte_int(cur_offset,pos);
309 			cur_offset += 4;
310 			}
311 		}
312 	}
313 
write_private_dict(FAPI_font * a_fapi_font,WRF_output * a_output,unsigned char * a_private_dict_length_ptr)314 static void write_private_dict(FAPI_font* a_fapi_font,WRF_output* a_output,unsigned char* a_private_dict_length_ptr)
315 	{
316 	/* Write the offset to the start of the private dictionary to the top dictionary. */
317 	unsigned char* start = a_output->m_pos;
318 	if (a_output->m_pos)
319 		write_4_byte_int(a_private_dict_length_ptr + 6,a_output->m_count);
320 
321 	write_word_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_BlueFuzz,1,true,11,16);
322 
323 	write_type2_float(a_output,a_fapi_font->get_long(a_fapi_font,FAPI_FONT_FEATURE_BlueScale,0) / 65536.0);
324 	WRF_wbyte(a_output,12);
325 	WRF_wbyte(a_output,9);
326 
327 	write_word_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_BlueShift,1,true,10,16);
328 	write_delta_array_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_BlueValues,false,6,16);
329 	write_delta_array_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_OtherBlues,false,7,16);
330 	write_delta_array_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_FamilyBlues,false,8,16);
331 	write_delta_array_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_FamilyOtherBlues,false,9,16);
332 	write_word_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_ForceBold,1,true,14,1);
333 	write_word_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_StdHW,1,false,10,16);
334 	write_word_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_StdVW,1,false,11,16);
335 	write_delta_array_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_StemSnapH,true,12,16);
336 	write_delta_array_entry(a_fapi_font,a_output,FAPI_FONT_FEATURE_StemSnapV,true,13,16);
337 
338 	/*
339 	Write the default width and the nominal width. These values are not available via
340 	the FAPI interface so we have to get a pointer to the Type 1 font structure and
341 	extract them directly.
342 	*/
343 	{
344 	gs_font_type1* t1 = (gs_font_type1*)a_fapi_font->client_font_data;
345     write_type2_float(a_output,fixed2float(t1->data.defaultWidthX));
346 	WRF_wbyte(a_output,20);
347     write_type2_float(a_output,fixed2float(t1->data.nominalWidthX));
348 	WRF_wbyte(a_output,21);
349 	}
350 
351 	/* Write the length in bytes of the private dictionary to the top dictionary. */
352 	if (a_output->m_pos)
353 		write_4_byte_int(a_private_dict_length_ptr + 1,a_output->m_pos - start);
354 	}
355 
356 /**
357 Write a Type 2 font in binary format and return its length in bytes.
358 If a_buffer_size is less than the total length, only a_buffer_size bytes are written, but the total
359 length is returned correctly.
360 */
FF_serialize_type2_font(FAPI_font * a_fapi_font,unsigned char * a_buffer,long a_buffer_size)361 long FF_serialize_type2_font(FAPI_font* a_fapi_font,unsigned char* a_buffer,long a_buffer_size)
362 	{
363 	unsigned char* charset_offset_ptr = NULL;
364 	unsigned char* charstrings_offset_ptr = NULL;
365 	unsigned char* private_dict_length_ptr = NULL;
366 	int characters = 0;
367 
368 	WRF_output output;
369 	WRF_init(&output,a_buffer,a_buffer_size);
370 
371 	write_header(&output);
372 	write_name_index(&output);
373 	write_font_dict_index(a_fapi_font,&output,&charset_offset_ptr,&charstrings_offset_ptr,&private_dict_length_ptr);
374 
375   	/* Write an empty string index. */
376   	WRF_wtext(&output,(const unsigned char *)"\x0\x0",2);
377 
378 	write_subrs_index(a_fapi_font,&output);
379 	characters = write_charset(&output,charset_offset_ptr);
380 	write_charstrings_index(&output,characters,charstrings_offset_ptr);
381 	write_private_dict(a_fapi_font,&output,private_dict_length_ptr);
382 
383 	return output.m_count;
384 	}
385