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)", pFont->info.nprops, sizeof(FontPropRec));
242 prop_string_size = 0;
243 for (i = 0; i < pFont->info.nprops; i++) {
244 offsetProps[i].name = prop_string_size;
245 prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].name)) + 1;
246 if (pFont->info.isStringProp[i]) {
247 offsetProps[i].value = prop_string_size;
248 prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].value)) + 1;
250 offsetProps[i].value = pFont->info.props[i].value;
252 format = PCF_FORMAT(pFont->bit, pFont->byte, pFont->glyph, pFont->scan);
262 table->format = PCF_DEFAULT_FORMAT | format;
263 size = S32 + S32 + (S32 + S8 + S32) * pFont->info.nprops;
264 prop_pad = Pad(size);
265 table->size = RoundUp(size) + S32 +
266 RoundUp(prop_string_size);
269 case PCF_ACCELERATORS:
270 if (bitmapFont->bitmapExtra->info.inkMetrics)
271 table->format = PCF_ACCEL_W_INKBOUNDS | format;
273 table->format = PCF_DEFAULT_FORMAT | format;
278 if (CanCompressMetrics(minbounds, maxbounds)) {
279 table->format = PCF_COMPRESSED_METRICS | format;
280 size = S32 + S16 + bitmapFont->num_chars * (5 * S8);
281 table->size = RoundUp(size);
283 table->format = PCF_DEFAULT_FORMAT | format;
284 table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
289 table->format = PCF_DEFAULT_FORMAT | format;
290 size = S32 + S32 + bitmapFont->num_chars * S32 +
291 GLYPHPADOPTIONS * S32 +
292 bitmapFont->bitmapExtra->bitmapsSizes[PCF_GLYPH_PAD_INDEX(format)];
293 table->size = RoundUp(size);
296 case PCF_INK_METRICS:
297 if (bitmapFont->ink_metrics) {
298 if (CanCompressMetrics(ink_minbounds, ink_maxbounds)) {
299 table->format = PCF_COMPRESSED_METRICS | format;
300 size = S32 + S16 + bitmapFont->num_chars * (5 * S8);
301 table->size = RoundUp(size);
303 table->format = PCF_DEFAULT_FORMAT | format;
304 table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
309 case PCF_BDF_ENCODINGS:
310 table->format = PCF_DEFAULT_FORMAT | format;
311 nencodings = (pFont->info.lastRow - pFont->info.firstRow + 1) *
312 (pFont->info.lastCol - pFont->info.firstCol + 1);
313 size = S32 + 5 * S16 + nencodings * S16;
314 table->size = RoundUp(size);
318 table->format = PCF_DEFAULT_FORMAT | format;
319 table->size = S32 + S32 + bitmapFont->num_chars * S32;
322 case PCF_GLYPH_NAMES:
323 table->format = PCF_DEFAULT_FORMAT | format;
324 glyph_string_size = 0;
325 for (i = 0; i < bitmapFont->num_chars; i++)
326 glyph_string_size += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1;
327 table->size = S32 + S32 + bitmapFont->num_chars * S32 +
328 S32 + RoundUp(glyph_string_size);
331 case PCF_BDF_ACCELERATORS:
332 if (pFont->info.inkMetrics)
333 table->format = PCF_ACCEL_W_INKBOUNDS | format;
335 table->format = PCF_DEFAULT_FORMAT | format;
341 ntables = table - tables;
343 header_size = S32 + S32 + ntables * (4 * S32);
344 offset = header_size;
345 for (cur_table = 0, table = tables;
347 cur_table++, table++) {
348 table->offset = offset;
349 offset += table->size;
351 current_position = 0;
352 pcfWriteTOC(file, tables, ntables);
353 for (cur_table = 0, table = tables;
355 cur_table++, table++) {
356 if (current_position > table->offset) {
357 printf("can't go backwards... %d > %d\n",
358 (int)current_position, (int)table->offset);
362 while (current_position < table->offset)
363 pcfPutINT8(file, format, '\0');
364 pcfPutLSB32(file, table->format);
365 switch (table->type) {
367 pcfPutINT32(file, format, pFont->info.nprops);
368 for (i = 0; i < pFont->info.nprops; i++) {
369 pcfPutINT32(file, format, offsetProps[i].name);
370 pcfPutINT8(file, format, pFont->info.isStringProp[i]);
371 pcfPutINT32(file, format, offsetProps[i].value);
373 for (i = 0; i < prop_pad; i++)
374 pcfPutINT8(file, format, 0);
375 pcfPutINT32(file, format, prop_string_size);
376 for (i = 0; i < pFont->info.nprops; i++) {
377 atom_name = pcfNameForAtom(pFont->info.props[i].name);
378 pcfWrite(file, atom_name, strlen(atom_name) + 1);
379 if (pFont->info.isStringProp[i]) {
380 atom_name = pcfNameForAtom(pFont->info.props[i].value);
381 pcfWrite(file, atom_name, strlen(atom_name) + 1);
385 case PCF_ACCELERATORS:
386 pcfPutAccel(file, table->format, &bitmapFont->bitmapExtra->info);
389 if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) {
390 pcfPutINT16(file, format, bitmapFont->num_chars);
391 for (i = 0; i < bitmapFont->num_chars; i++)
392 pcfPutCompressedMetric(file, format, &bitmapFont->metrics[i].metrics);
394 pcfPutINT32(file, format, bitmapFont->num_chars);
395 for (i = 0; i < bitmapFont->num_chars; i++)
396 pcfPutMetric(file, format, &bitmapFont->metrics[i].metrics);
400 pcfPutINT32(file, format, bitmapFont->num_chars);
401 glyph = PCF_GLYPH_PAD(format);
403 for (i = 0; i < bitmapFont->num_chars; i++) {
404 pcfPutINT32(file, format, offset);
405 offset += BYTES_FOR_GLYPH(&bitmapFont->metrics[i], glyph);
407 for (i = 0; i < GLYPHPADOPTIONS; i++) {
408 pcfPutINT32(file, format,
409 bitmapFont->bitmapExtra->bitmapsSizes[i]);
411 for (i = 0; i < bitmapFont->num_chars; i++)
412 pcfPutBitmap(file, format, &bitmapFont->metrics[i]);
414 case PCF_INK_METRICS:
415 if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) {
416 pcfPutINT16(file, format, bitmapFont->num_chars);
417 for (i = 0; i < bitmapFont->num_chars; i++)
418 pcfPutCompressedMetric(file, format, &bitmapFont->ink_metrics[i]);
420 pcfPutINT32(file, format, bitmapFont->num_chars);
421 for (i = 0; i < bitmapFont->num_chars; i++)
422 pcfPutMetric(file, format, &bitmapFont->ink_metrics[i]);
425 case PCF_BDF_ENCODINGS:
426 pcfPutINT16(file, format, pFont->info.firstCol);
427 pcfPutINT16(file, format, pFont->info.lastCol);
428 pcfPutINT16(file, format, pFont->info.firstRow);
429 pcfPutINT16(file, format, pFont->info.lastRow);
430 pcfPutINT16(file, format, pFont->info.defaultCh);
431 for (i = 0; i < nencodings; i++) {
432 if (ACCESSENCODING(bitmapFont->encoding,i))
433 pcfPutINT16(file, format,
434 ACCESSENCODING(bitmapFont->encoding, i) -
435 bitmapFont->metrics);
437 pcfPutINT16(file, format, 0xFFFF);
441 pcfPutINT32(file, format, bitmapFont->num_chars);
442 for (i = 0; i < bitmapFont->num_chars; i++)
443 pcfPutINT32(file, format, bitmapFont->bitmapExtra->sWidths[i]);
445 case PCF_GLYPH_NAMES:
446 pcfPutINT32(file, format, bitmapFont->num_chars);
448 for (i = 0; i < bitmapFont->num_chars; i++) {
449 pcfPutINT32(file, format, offset);
450 offset += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1;
452 pcfPutINT32(file, format, offset);
453 for (i = 0; i < bitmapFont->num_chars; i++) {
454 atom_name = pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i]);
455 pcfWrite(file, atom_name, strlen(atom_name) + 1);
458 case PCF_BDF_ACCELERATORS:
459 pcfPutAccel(file, table->format, &pFont->info);