3 Copyright 1990, 1994, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
30 * Author: Keith Packard, MIT X Consortium
37 #include <X11/fonts/fntfilst.h>
38 #include <X11/fonts/bitmap.h>
39 #include <X11/fonts/pcf.h>
41 /* Write PCF font files */
43 static CARD32 current_position;
46 pcfWrite(FontFilePtr file, char *b, int c)
48 current_position += c;
49 return FontFileWrite(file, b, c);
53 pcfPutLSB32(FontFilePtr file, int c)
55 current_position += 4;
56 (void) FontFilePutc(c, file);
57 (void) FontFilePutc(c >> 8, file);
58 (void) FontFilePutc(c >> 16, file);
59 return FontFilePutc(c >> 24, file);
63 pcfPutINT32(FontFilePtr file, CARD32 format, int c)
65 current_position += 4;
66 if (PCF_BYTE_ORDER(format) == MSBFirst) {
67 (void) FontFilePutc(c >> 24, file);
68 (void) FontFilePutc(c >> 16, file);
69 (void) FontFilePutc(c >> 8, file);
70 return FontFilePutc(c, file);
72 (void) FontFilePutc(c, file);
73 (void) FontFilePutc(c >> 8, file);
74 (void) FontFilePutc(c >> 16, file);
75 return FontFilePutc(c >> 24, file);
80 pcfPutINT16(FontFilePtr file, CARD32 format, int c)
82 current_position += 2;
83 if (PCF_BYTE_ORDER(format) == MSBFirst) {
84 (void) FontFilePutc(c >> 8, file);
85 return FontFilePutc(c, file);
87 (void) FontFilePutc(c, file);
88 return FontFilePutc(c >> 8, file);
94 pcfPutINT8(FontFilePtr file, CARD32 format, int c)
96 current_position += 1;
97 return FontFilePutc(c, file);
101 pcfWriteTOC(FontFilePtr file, PCFTablePtr table, int count)
106 version = PCF_FILE_VERSION;
107 pcfPutLSB32(file, version);
108 pcfPutLSB32(file, count);
109 for (i = 0; i < count; i++) {
110 pcfPutLSB32(file, table->type);
111 pcfPutLSB32(file, table->format);
112 pcfPutLSB32(file, table->size);
113 pcfPutLSB32(file, table->offset);
119 pcfPutCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric)
121 pcfPutINT8(file, format, metric->leftSideBearing + 0x80);
122 pcfPutINT8(file, format, metric->rightSideBearing + 0x80);
123 pcfPutINT8(file, format, metric->characterWidth + 0x80);
124 pcfPutINT8(file, format, metric->ascent + 0x80);
125 pcfPutINT8(file, format, metric->descent + 0x80);
129 pcfPutMetric(FontFilePtr file, CARD32 format, xCharInfo *metric)
131 pcfPutINT16(file, format, metric->leftSideBearing);
132 pcfPutINT16(file, format, metric->rightSideBearing);
133 pcfPutINT16(file, format, metric->characterWidth);
134 pcfPutINT16(file, format, metric->ascent);
135 pcfPutINT16(file, format, metric->descent);
136 pcfPutINT16(file, format, metric->attributes);
140 pcfPutBitmap(FontFilePtr file, CARD32 format, CharInfoPtr pCI)
145 count = BYTES_FOR_GLYPH(pCI, PCF_GLYPH_PAD(format));
146 bits = (unsigned char *) pCI->bits;
147 current_position += count;
149 FontFilePutc(*bits++, file);
153 pcfPutAccel(FontFilePtr file, CARD32 format, FontInfoPtr pFontInfo)
155 pcfPutINT8(file, format, pFontInfo->noOverlap);
156 pcfPutINT8(file, format, pFontInfo->constantMetrics);
157 pcfPutINT8(file, format, pFontInfo->terminalFont);
158 pcfPutINT8(file, format, pFontInfo->constantWidth);
159 pcfPutINT8(file, format, pFontInfo->inkInside);
160 pcfPutINT8(file, format, pFontInfo->inkMetrics);
161 pcfPutINT8(file, format, pFontInfo->drawDirection);
162 pcfPutINT8(file, format, 0);
163 pcfPutINT32(file, format, pFontInfo->fontAscent);
164 pcfPutINT32(file, format, pFontInfo->fontDescent);
165 pcfPutINT32(file, format, pFontInfo->maxOverlap);
166 pcfPutMetric(file, format, &pFontInfo->minbounds);
167 pcfPutMetric(file, format, &pFontInfo->maxbounds);
168 if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) {
169 pcfPutMetric(file, format, &pFontInfo->ink_minbounds);
170 pcfPutMetric(file, format, &pFontInfo->ink_maxbounds);
178 #define Pad(s) (RoundUp(s) - (s))
179 #define RoundUp(s) (((s) + 3) & ~3)
181 #define Compressable(i) (-128 <= (i) && (i) <= 127)
183 #define CanCompressMetric(m) (Compressable((m)->leftSideBearing) && \
184 Compressable((m)->rightSideBearing) && \
185 Compressable((m)->characterWidth) && \
186 Compressable((m)->ascent) && \
187 Compressable((m)->descent) && \
188 (m)->attributes == 0)
190 #define CanCompressMetrics(min,max) (CanCompressMetric(min) && CanCompressMetric(max))
193 pcfNameForAtom(Atom a)
195 return NameForAtom(a);
199 pcfWriteFont(FontPtr pFont, FontFilePtr file)
201 PCFTableRec tables[32],
210 int prop_string_size;
211 int glyph_string_size;
212 xCharInfo *minbounds,
214 xCharInfo *ink_minbounds,
216 BitmapFontPtr bitmapFont;
219 FontPropPtr offsetProps;
225 bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
226 if (bitmapFont->bitmapExtra) {
227 minbounds = &bitmapFont->bitmapExtra->info.minbounds;
228 maxbounds = &bitmapFont->bitmapExtra->info.maxbounds;
229 ink_minbounds = &bitmapFont->bitmapExtra->info.ink_minbounds;
230 ink_maxbounds = &bitmapFont->bitmapExtra->info.ink_maxbounds;
232 minbounds = &pFont->info.minbounds;
233 maxbounds = &pFont->info.maxbounds;
234 ink_minbounds = &pFont->info.ink_minbounds;
235 ink_maxbounds = &pFont->info.ink_maxbounds;
237 offsetProps = malloc(pFont->info.nprops * sizeof(FontPropRec));
239 pcfError("pcfWriteFont(): Couldn't allocate offsetProps (%d*%d)",
240 pFont->info.nprops, (int) sizeof(FontPropRec));
243 prop_string_size = 0;
244 for (i = 0; i < pFont->info.nprops; i++) {
245 offsetProps[i].name = prop_string_size;
246 prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].name)) + 1;
247 if (pFont->info.isStringProp[i]) {
248 offsetProps[i].value = prop_string_size;
249 prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].value)) + 1;
251 offsetProps[i].value = pFont->info.props[i].value;
253 format = PCF_FORMAT(pFont->bit, pFont->byte, pFont->glyph, pFont->scan);
263 table->format = PCF_DEFAULT_FORMAT | format;
264 size = S32 + S32 + (S32 + S8 + S32) * pFont->info.nprops;
265 prop_pad = Pad(size);
266 table->size = RoundUp(size) + S32 +
267 RoundUp(prop_string_size);
270 case PCF_ACCELERATORS:
271 if (bitmapFont->bitmapExtra->info.inkMetrics)
272 table->format = PCF_ACCEL_W_INKBOUNDS | format;
274 table->format = PCF_DEFAULT_FORMAT | format;
279 if (CanCompressMetrics(minbounds, maxbounds)) {
280 table->format = PCF_COMPRESSED_METRICS | format;
281 size = S32 + S16 + bitmapFont->num_chars * (5 * S8);
282 table->size = RoundUp(size);
284 table->format = PCF_DEFAULT_FORMAT | format;
285 table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
290 table->format = PCF_DEFAULT_FORMAT | format;
291 size = S32 + S32 + bitmapFont->num_chars * S32 +
292 GLYPHPADOPTIONS * S32 +
293 bitmapFont->bitmapExtra->bitmapsSizes[PCF_GLYPH_PAD_INDEX(format)];
294 table->size = RoundUp(size);
297 case PCF_INK_METRICS:
298 if (bitmapFont->ink_metrics) {
299 if (CanCompressMetrics(ink_minbounds, ink_maxbounds)) {
300 table->format = PCF_COMPRESSED_METRICS | format;
301 size = S32 + S16 + bitmapFont->num_chars * (5 * S8);
302 table->size = RoundUp(size);
304 table->format = PCF_DEFAULT_FORMAT | format;
305 table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
310 case PCF_BDF_ENCODINGS:
311 table->format = PCF_DEFAULT_FORMAT | format;
312 nencodings = (pFont->info.lastRow - pFont->info.firstRow + 1) *
313 (pFont->info.lastCol - pFont->info.firstCol + 1);
314 size = S32 + 5 * S16 + nencodings * S16;
315 table->size = RoundUp(size);
319 table->format = PCF_DEFAULT_FORMAT | format;
320 table->size = S32 + S32 + bitmapFont->num_chars * S32;
323 case PCF_GLYPH_NAMES:
324 table->format = PCF_DEFAULT_FORMAT | format;
325 glyph_string_size = 0;
326 for (i = 0; i < bitmapFont->num_chars; i++)
327 glyph_string_size += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1;
328 table->size = S32 + S32 + bitmapFont->num_chars * S32 +
329 S32 + RoundUp(glyph_string_size);
332 case PCF_BDF_ACCELERATORS:
333 if (pFont->info.inkMetrics)
334 table->format = PCF_ACCEL_W_INKBOUNDS | format;
336 table->format = PCF_DEFAULT_FORMAT | format;
342 ntables = table - tables;
344 header_size = S32 + S32 + ntables * (4 * S32);
345 offset = header_size;
346 for (cur_table = 0, table = tables;
348 cur_table++, table++) {
349 table->offset = offset;
350 offset += table->size;
352 current_position = 0;
353 pcfWriteTOC(file, tables, ntables);
354 for (cur_table = 0, table = tables;
356 cur_table++, table++) {
357 if (current_position > table->offset) {
358 printf("can't go backwards... %d > %d\n",
359 (int)current_position, (int)table->offset);
363 while (current_position < table->offset)
364 pcfPutINT8(file, format, '\0');
365 pcfPutLSB32(file, table->format);
366 switch (table->type) {
368 pcfPutINT32(file, format, pFont->info.nprops);
369 for (i = 0; i < pFont->info.nprops; i++) {
370 pcfPutINT32(file, format, offsetProps[i].name);
371 pcfPutINT8(file, format, pFont->info.isStringProp[i]);
372 pcfPutINT32(file, format, offsetProps[i].value);
374 for (i = 0; i < prop_pad; i++)
375 pcfPutINT8(file, format, 0);
376 pcfPutINT32(file, format, prop_string_size);
377 for (i = 0; i < pFont->info.nprops; i++) {
378 atom_name = pcfNameForAtom(pFont->info.props[i].name);
379 pcfWrite(file, atom_name, strlen(atom_name) + 1);
380 if (pFont->info.isStringProp[i]) {
381 atom_name = pcfNameForAtom(pFont->info.props[i].value);
382 pcfWrite(file, atom_name, strlen(atom_name) + 1);
386 case PCF_ACCELERATORS:
387 pcfPutAccel(file, table->format, &bitmapFont->bitmapExtra->info);
390 if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) {
391 pcfPutINT16(file, format, bitmapFont->num_chars);
392 for (i = 0; i < bitmapFont->num_chars; i++)
393 pcfPutCompressedMetric(file, format, &bitmapFont->metrics[i].metrics);
395 pcfPutINT32(file, format, bitmapFont->num_chars);
396 for (i = 0; i < bitmapFont->num_chars; i++)
397 pcfPutMetric(file, format, &bitmapFont->metrics[i].metrics);
401 pcfPutINT32(file, format, bitmapFont->num_chars);
402 glyph = PCF_GLYPH_PAD(format);
404 for (i = 0; i < bitmapFont->num_chars; i++) {
405 pcfPutINT32(file, format, offset);
406 offset += BYTES_FOR_GLYPH(&bitmapFont->metrics[i], glyph);
408 for (i = 0; i < GLYPHPADOPTIONS; i++) {
409 pcfPutINT32(file, format,
410 bitmapFont->bitmapExtra->bitmapsSizes[i]);
412 for (i = 0; i < bitmapFont->num_chars; i++)
413 pcfPutBitmap(file, format, &bitmapFont->metrics[i]);
415 case PCF_INK_METRICS:
416 if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) {
417 pcfPutINT16(file, format, bitmapFont->num_chars);
418 for (i = 0; i < bitmapFont->num_chars; i++)
419 pcfPutCompressedMetric(file, format, &bitmapFont->ink_metrics[i]);
421 pcfPutINT32(file, format, bitmapFont->num_chars);
422 for (i = 0; i < bitmapFont->num_chars; i++)
423 pcfPutMetric(file, format, &bitmapFont->ink_metrics[i]);
426 case PCF_BDF_ENCODINGS:
427 pcfPutINT16(file, format, pFont->info.firstCol);
428 pcfPutINT16(file, format, pFont->info.lastCol);
429 pcfPutINT16(file, format, pFont->info.firstRow);
430 pcfPutINT16(file, format, pFont->info.lastRow);
431 pcfPutINT16(file, format, pFont->info.defaultCh);
432 for (i = 0; i < nencodings; i++) {
433 if (ACCESSENCODING(bitmapFont->encoding,i))
434 pcfPutINT16(file, format,
435 ACCESSENCODING(bitmapFont->encoding, i) -
436 bitmapFont->metrics);
438 pcfPutINT16(file, format, 0xFFFF);
442 pcfPutINT32(file, format, bitmapFont->num_chars);
443 for (i = 0; i < bitmapFont->num_chars; i++)
444 pcfPutINT32(file, format, bitmapFont->bitmapExtra->sWidths[i]);
446 case PCF_GLYPH_NAMES:
447 pcfPutINT32(file, format, bitmapFont->num_chars);
449 for (i = 0; i < bitmapFont->num_chars; i++) {
450 pcfPutINT32(file, format, offset);
451 offset += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1;
453 pcfPutINT32(file, format, offset);
454 for (i = 0; i < bitmapFont->num_chars; i++) {
455 atom_name = pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i]);
456 pcfWrite(file, atom_name, strlen(atom_name) + 1);
459 case PCF_BDF_ACCELERATORS:
460 pcfPutAccel(file, table->format, &pFont->info);