upload tizen2.0 source
[framework/uifw/xorg/lib/libxfont.git] / src / bitmap / pcfwrite.c
1 /*
2
3 Copyright 1990, 1994, 1998  The Open Group
4
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
9 documentation.
10
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13
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.
21
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
25 from The Open Group.
26
27 */
28
29 /*
30  * Author:  Keith Packard, MIT X Consortium
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #include <X11/fonts/fntfilst.h>
38 #include <X11/fonts/bitmap.h>
39 #include <X11/fonts/pcf.h>
40
41 /* Write PCF font files */
42
43 static CARD32  current_position;
44
45 static int
46 pcfWrite(FontFilePtr file, char *b, int c)
47 {
48     current_position += c;
49     return FontFileWrite(file, b, c);
50 }
51
52 static int
53 pcfPutLSB32(FontFilePtr file, int c)
54 {
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);
60 }
61
62 static int
63 pcfPutINT32(FontFilePtr file, CARD32 format, int c)
64 {
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);
71     } else {
72         (void) FontFilePutc(c, file);
73         (void) FontFilePutc(c >> 8, file);
74         (void) FontFilePutc(c >> 16, file);
75         return FontFilePutc(c >> 24, file);
76     }
77 }
78
79 static int
80 pcfPutINT16(FontFilePtr file, CARD32 format, int c)
81 {
82     current_position += 2;
83     if (PCF_BYTE_ORDER(format) == MSBFirst) {
84         (void) FontFilePutc(c >> 8, file);
85         return FontFilePutc(c, file);
86     } else {
87         (void) FontFilePutc(c, file);
88         return FontFilePutc(c >> 8, file);
89     }
90 }
91
92 /*ARGSUSED*/
93 static int
94 pcfPutINT8(FontFilePtr file, CARD32 format, int c)
95 {
96     current_position += 1;
97     return FontFilePutc(c, file);
98 }
99
100 static void
101 pcfWriteTOC(FontFilePtr file, PCFTablePtr table, int count)
102 {
103     CARD32      version;
104     int         i;
105
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);
114         table++;
115     }
116 }
117
118 static void
119 pcfPutCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric)
120 {
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);
126 }
127
128 static void
129 pcfPutMetric(FontFilePtr file, CARD32 format, xCharInfo *metric)
130 {
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);
137 }
138
139 static void
140 pcfPutBitmap(FontFilePtr file, CARD32 format, CharInfoPtr pCI)
141 {
142     int         count;
143     unsigned char *bits;
144
145     count = BYTES_FOR_GLYPH(pCI, PCF_GLYPH_PAD(format));
146     bits = (unsigned char *) pCI->bits;
147     current_position += count;
148     while (count--)
149         FontFilePutc(*bits++, file);
150 }
151
152 static void
153 pcfPutAccel(FontFilePtr file, CARD32 format, FontInfoPtr pFontInfo)
154 {
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);
171     }
172 }
173
174 #define S32 4
175 #define S16 2
176 #define S8 1
177
178 #define Pad(s)      (RoundUp(s) - (s))
179 #define RoundUp(s)  (((s) + 3) & ~3)
180
181 #define Compressable(i) (-128 <= (i) && (i) <= 127)
182
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)
189
190 #define CanCompressMetrics(min,max) (CanCompressMetric(min) && CanCompressMetric(max))
191
192 static char *
193 pcfNameForAtom(Atom a)
194 {
195     return NameForAtom(a);
196 }
197
198 int
199 pcfWriteFont(FontPtr pFont, FontFilePtr file)
200 {
201     PCFTableRec tables[32],
202                *table;
203     CARD32      mask,
204                 bit;
205     int         ntables;
206     int         size;
207     CARD32      format;
208     int         i;
209     int         cur_table;
210     int         prop_string_size;
211     int         glyph_string_size;
212     xCharInfo  *minbounds,
213                *maxbounds;
214     xCharInfo  *ink_minbounds,
215                *ink_maxbounds;
216     BitmapFontPtr  bitmapFont;
217     int         nencodings = 0;
218     int         header_size;
219     FontPropPtr offsetProps;
220     int         prop_pad = 0;
221     char       *atom_name;
222     int         glyph;
223     CARD32      offset;
224
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;
231     } else {
232         minbounds = &pFont->info.minbounds;
233         maxbounds = &pFont->info.maxbounds;
234         ink_minbounds = &pFont->info.ink_minbounds;
235         ink_maxbounds = &pFont->info.ink_maxbounds;
236     }
237     offsetProps = malloc(pFont->info.nprops * sizeof(FontPropRec));
238     if (!offsetProps) {
239         pcfError("pcfWriteFont(): Couldn't allocate offsetProps (%d*%d)",
240                  pFont->info.nprops, (int) sizeof(FontPropRec));
241         return AllocError;
242     }
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;
250         } else
251             offsetProps[i].value = pFont->info.props[i].value;
252     }
253     format = PCF_FORMAT(pFont->bit, pFont->byte, pFont->glyph, pFont->scan);
254     mask = 0xFFFFFFF;
255     ntables = 0;
256     table = tables;
257     while (mask) {
258         bit = lowbit(mask);
259         mask &= ~bit;
260         table->type = bit;
261         switch (bit) {
262         case PCF_PROPERTIES:
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);
268             table++;
269             break;
270         case PCF_ACCELERATORS:
271             if (bitmapFont->bitmapExtra->info.inkMetrics)
272                 table->format = PCF_ACCEL_W_INKBOUNDS | format;
273             else
274                 table->format = PCF_DEFAULT_FORMAT | format;
275             table->size = 100;
276             table++;
277             break;
278         case PCF_METRICS:
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);
283             } else {
284                 table->format = PCF_DEFAULT_FORMAT | format;
285                 table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
286             }
287             table++;
288             break;
289         case PCF_BITMAPS:
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);
295             table++;
296             break;
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);
303                 } else {
304                     table->format = PCF_DEFAULT_FORMAT | format;
305                     table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
306                 }
307                 table++;
308             }
309             break;
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);
316             table++;
317             break;
318         case PCF_SWIDTHS:
319             table->format = PCF_DEFAULT_FORMAT | format;
320             table->size = S32 + S32 + bitmapFont->num_chars * S32;
321             table++;
322             break;
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);
330             table++;
331             break;
332         case PCF_BDF_ACCELERATORS:
333             if (pFont->info.inkMetrics)
334                 table->format = PCF_ACCEL_W_INKBOUNDS | format;
335             else
336                 table->format = PCF_DEFAULT_FORMAT | format;
337             table->size = 100;
338             table++;
339             break;
340         }
341     }
342     ntables = table - tables;
343     offset = 0;
344     header_size = S32 + S32 + ntables * (4 * S32);
345     offset = header_size;
346     for (cur_table = 0, table = tables;
347             cur_table < ntables;
348             cur_table++, table++) {
349         table->offset = offset;
350         offset += table->size;
351     }
352     current_position = 0;
353     pcfWriteTOC(file, tables, ntables);
354     for (cur_table = 0, table = tables;
355             cur_table < ntables;
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);
360             free(offsetProps);
361             return BadFontName;
362         }
363         while (current_position < table->offset)
364             pcfPutINT8(file, format, '\0');
365         pcfPutLSB32(file, table->format);
366         switch (table->type) {
367         case PCF_PROPERTIES:
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);
373             }
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);
383                 }
384             }
385             break;
386         case PCF_ACCELERATORS:
387             pcfPutAccel(file, table->format, &bitmapFont->bitmapExtra->info);
388             break;
389         case PCF_METRICS:
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);
394             } else {
395                 pcfPutINT32(file, format, bitmapFont->num_chars);
396                 for (i = 0; i < bitmapFont->num_chars; i++)
397                     pcfPutMetric(file, format, &bitmapFont->metrics[i].metrics);
398             }
399             break;
400         case PCF_BITMAPS:
401             pcfPutINT32(file, format, bitmapFont->num_chars);
402             glyph = PCF_GLYPH_PAD(format);
403             offset = 0;
404             for (i = 0; i < bitmapFont->num_chars; i++) {
405                 pcfPutINT32(file, format, offset);
406                 offset += BYTES_FOR_GLYPH(&bitmapFont->metrics[i], glyph);
407             }
408             for (i = 0; i < GLYPHPADOPTIONS; i++) {
409                 pcfPutINT32(file, format,
410                             bitmapFont->bitmapExtra->bitmapsSizes[i]);
411             }
412             for (i = 0; i < bitmapFont->num_chars; i++)
413                 pcfPutBitmap(file, format, &bitmapFont->metrics[i]);
414             break;
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]);
420             } else {
421                 pcfPutINT32(file, format, bitmapFont->num_chars);
422                 for (i = 0; i < bitmapFont->num_chars; i++)
423                     pcfPutMetric(file, format, &bitmapFont->ink_metrics[i]);
424             }
425             break;
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);
437                 else
438                     pcfPutINT16(file, format, 0xFFFF);
439             }
440             break;
441         case PCF_SWIDTHS:
442             pcfPutINT32(file, format, bitmapFont->num_chars);
443             for (i = 0; i < bitmapFont->num_chars; i++)
444                 pcfPutINT32(file, format, bitmapFont->bitmapExtra->sWidths[i]);
445             break;
446         case PCF_GLYPH_NAMES:
447             pcfPutINT32(file, format, bitmapFont->num_chars);
448             offset = 0;
449             for (i = 0; i < bitmapFont->num_chars; i++) {
450                 pcfPutINT32(file, format, offset);
451                 offset += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1;
452             }
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);
457             }
458             break;
459         case PCF_BDF_ACCELERATORS:
460             pcfPutAccel(file, table->format, &pFont->info);
461             break;
462         }
463     }
464
465     free(offsetProps);
466     return Successful;
467 }