update dev300-m57
[ooovba.git] / vcl / source / fontsubset / ttcr.cxx
blob69f9698277ab6fce9f7ba7585d0e6187ad9f2558
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
29 * TrueTypeCreator method implementation
31 * @author: Alexander Gelfenbain
35 #if OSL_DEBUG_LEVEL == 0
36 # ifndef NDEBUG
37 # define NDEBUG
38 # endif
39 #endif
40 #include <assert.h>
42 #include "ttcr.hxx"
43 #include "list.h"
44 #include "string.h"
48 namespace vcl
52 * Private Data Types
55 struct _TrueTypeCreator {
56 sal_uInt32 tag; /**< TrueType file tag */
57 list tables; /**< List of table tags and pointers */
60 /* These must be #defined so that they can be used in initializers */
61 #define T_maxp 0x6D617870
62 #define T_glyf 0x676C7966
63 #define T_head 0x68656164
64 #define T_loca 0x6C6F6361
65 #define T_name 0x6E616D65
66 #define T_hhea 0x68686561
67 #define T_hmtx 0x686D7478
68 #define T_cmap 0x636D6170
69 #define T_vhea 0x76686561
70 #define T_vmtx 0x766D7478
71 #define T_OS2 0x4F532F32
72 #define T_post 0x706F7374
73 #define T_kern 0x6B65726E
74 #define T_cvt 0x63767420
76 typedef struct {
77 sal_uInt32 tag;
78 sal_uInt32 length;
79 sal_uInt8 *data;
80 } TableEntry;
83 * this is a duplicate code from sft.c but it is left here for performance reasons
85 #ifdef __GNUC__
86 #define _inline static __inline__
87 #else
88 #define _inline static
89 #endif
91 _inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) {
92 return (a << 24) | (b << 16) | (c << 8) | d;
95 /*- Data access macros for data stored in big-endian or little-endian format */
96 _inline sal_Int16 GetInt16( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian)
98 sal_Int16 t;
99 assert(ptr != 0);
101 if (bigendian) {
102 t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
103 } else {
104 t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
107 return t;
110 _inline sal_uInt16 GetUInt16( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian)
112 sal_uInt16 t;
113 assert(ptr != 0);
115 if (bigendian) {
116 t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
117 } else {
118 t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
121 return t;
124 _inline sal_Int32 GetInt32( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian)
126 sal_Int32 t;
127 assert(ptr != 0);
129 if (bigendian) {
130 t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
131 (ptr+offset)[2] << 8 | (ptr+offset)[3];
132 } else {
133 t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
134 (ptr+offset)[1] << 8 | (ptr+offset)[0];
137 return t;
140 _inline sal_uInt32 GetUInt32( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian)
142 sal_uInt32 t;
143 assert(ptr != 0);
146 if (bigendian) {
147 t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
148 (ptr+offset)[2] << 8 | (ptr+offset)[3];
149 } else {
150 t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
151 (ptr+offset)[1] << 8 | (ptr+offset)[0];
154 return t;
158 _inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian)
160 assert(ptr != 0);
162 if (bigendian) {
163 ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF);
164 ptr[offset+1] = (sal_uInt8)(val & 0xFF);
165 } else {
166 ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
167 ptr[offset] = (sal_uInt8)(val & 0xFF);
171 _inline void PutUInt16(sal_uInt16 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian)
173 assert(ptr != 0);
175 if (bigendian) {
176 ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF);
177 ptr[offset+1] = (sal_uInt8)(val & 0xFF);
178 } else {
179 ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
180 ptr[offset] = (sal_uInt8)(val & 0xFF);
184 _inline void PutUInt32(sal_uInt32 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian)
186 assert(ptr != 0);
188 if (bigendian) {
189 ptr[offset] = (sal_uInt8)((val >> 24) & 0xFF);
190 ptr[offset+1] = (sal_uInt8)((val >> 16) & 0xFF);
191 ptr[offset+2] = (sal_uInt8)((val >> 8) & 0xFF);
192 ptr[offset+3] = (sal_uInt8)(val & 0xFF);
193 } else {
194 ptr[offset+3] = (sal_uInt8)((val >> 24) & 0xFF);
195 ptr[offset+2] = (sal_uInt8)((val >> 16) & 0xFF);
196 ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
197 ptr[offset] = (sal_uInt8)(val & 0xFF);
203 _inline void PutInt32(sal_Int32 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian)
205 assert(ptr != 0);
207 if (bigendian) {
208 ptr[offset] = (sal_uInt8)((val >> 24) & 0xFF);
209 ptr[offset+1] = (sal_uInt8)((val >> 16) & 0xFF);
210 ptr[offset+2] = (sal_uInt8)((val >> 8) & 0xFF);
211 ptr[offset+3] = (sal_uInt8)(val & 0xFF);
212 } else {
213 ptr[offset+3] = (sal_uInt8)((val >> 24) & 0xFF);
214 ptr[offset+2] = (sal_uInt8)((val >> 16) & 0xFF);
215 ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
216 ptr[offset] = (sal_uInt8)(val & 0xFF);
221 static int TableEntryCompareF(const void *l, const void *r)
223 return ((const TableEntry *) l)->tag - ((const TableEntry *) r)->tag;
226 static int NameRecordCompareF(const void *l, const void *r)
228 NameRecord *ll = (NameRecord *) l;
229 NameRecord *rr = (NameRecord *) r;
231 if (ll->platformID != rr->platformID) {
232 return ll->platformID - rr->platformID;
233 } else if (ll->encodingID != rr->encodingID) {
234 return ll->encodingID - rr->encodingID;
235 } else if (ll->languageID != rr->languageID) {
236 return ll->languageID - rr->languageID;
237 } else if (ll->nameID != rr->nameID) {
238 return ll->nameID - rr->nameID;
240 return 0;
244 static sal_uInt32 CheckSum(sal_uInt32 *ptr, sal_uInt32 length)
246 sal_uInt32 sum = 0;
247 sal_uInt32 *endptr = ptr + ((length + 3) & (sal_uInt32) ~3) / 4;
249 while (ptr < endptr) sum += *ptr++;
251 return sum;
254 _inline void *smalloc(sal_uInt32 size)
256 void *res = malloc(size);
257 assert(res != 0);
258 return res;
261 _inline void *scalloc(sal_uInt32 n, sal_uInt32 size)
263 void *res = calloc(n, size);
264 assert(res != 0);
265 return res;
269 * Public functions
272 void TrueTypeCreatorNewEmpty(sal_uInt32 tag, TrueTypeCreator **_this)
274 TrueTypeCreator* ptr = (TrueTypeCreator*)smalloc(sizeof(TrueTypeCreator));
276 ptr->tables = listNewEmpty();
277 listSetElementDtor(ptr->tables, (list_destructor)TrueTypeTableDispose);
279 ptr->tag = tag;
281 *_this = ptr;
284 int AddTable(TrueTypeCreator *_this, TrueTypeTable *table)
286 if (table != 0) {
287 listAppend(_this->tables, table);
289 return SF_OK;
292 void RemoveTable(TrueTypeCreator *_this, sal_uInt32 tag)
294 int done = 0;
296 if (listCount(_this->tables)) {
297 listToFirst(_this->tables);
298 do {
299 if (((TrueTypeTable *) listCurrent(_this->tables))->tag == tag) {
300 listRemove(_this->tables);
301 } else {
302 if (listNext(_this->tables)) {
303 done = 1;
306 } while (!done);
310 static void ProcessTables(TrueTypeCreator *);
312 int StreamToMemory(TrueTypeCreator *_this, sal_uInt8 **ptr, sal_uInt32 *length)
314 sal_uInt16 numTables, searchRange=1, entrySelector=0, rangeShift;
315 sal_uInt32 s, offset, checkSumAdjustment = 0;
316 sal_uInt32 *p;
317 int i=0, n;
318 sal_uInt8 *head = NULL; /* saved pointer to the head table data for checkSumAdjustment calculation */
320 if ((n = listCount(_this->tables)) == 0) return SF_TTFORMAT;
322 ProcessTables(_this);
324 /* ProcessTables() adds 'loca' and 'hmtx' */
326 n = listCount(_this->tables);
327 numTables = (sal_uInt16) n;
330 TableEntry* te = (TableEntry*)scalloc(n, sizeof(TableEntry));
332 listToFirst(_this->tables);
333 for (i = 0; i < n; i++) {
334 GetRawData((TrueTypeTable *) listCurrent(_this->tables), &te[i].data, &te[i].length, &te[i].tag);
335 listNext(_this->tables);
338 qsort(te, n, sizeof(TableEntry), TableEntryCompareF);
340 do {
341 searchRange *= 2;
342 entrySelector++;
343 } while (searchRange <= numTables);
345 searchRange *= 8;
346 entrySelector--;
347 rangeShift = numTables * 16 - searchRange;
349 s = offset = 12 + 16 * n;
351 for (i = 0; i < n; i++) {
352 s += (te[i].length + 3) & (sal_uInt32) ~3;
353 /* if ((te[i].length & 3) != 0) s += (4 - (te[i].length & 3)) & 3; */
356 sal_uInt8* ttf = (sal_uInt8*)smalloc(s);
358 /* Offset Table */
359 PutUInt32(_this->tag, ttf, 0, 1);
360 PutUInt16(numTables, ttf, 4, 1);
361 PutUInt16(searchRange, ttf, 6, 1);
362 PutUInt16(entrySelector, ttf, 8, 1);
363 PutUInt16(rangeShift, ttf, 10, 1);
365 /* Table Directory */
366 for (i = 0; i < n; i++) {
367 PutUInt32(te[i].tag, ttf + 12, 16 * i, 1);
368 PutUInt32(CheckSum((sal_uInt32 *) te[i].data, te[i].length), ttf + 12, 16 * i + 4, 1);
369 PutUInt32(offset, ttf + 12, 16 * i + 8, 1);
370 PutUInt32(te[i].length, ttf + 12, 16 * i + 12, 1);
372 if (te[i].tag == T_head) {
373 head = ttf + offset;
376 memcpy(ttf+offset, te[i].data, (te[i].length + 3) & (sal_uInt32) ~3 );
377 offset += (te[i].length + 3) & (sal_uInt32) ~3;
378 /* if ((te[i].length & 3) != 0) offset += (4 - (te[i].length & 3)) & 3; */
381 free(te);
383 p = (sal_uInt32 *) ttf;
384 for (i = 0; i < (int)s / 4; i++) checkSumAdjustment += p[i];
385 PutUInt32(0xB1B0AFBA - checkSumAdjustment, head, 8, 1);
387 *ptr = ttf;
388 *length = s;
390 return SF_OK;
393 int StreamToFile(TrueTypeCreator *_this, const char* fname)
395 sal_uInt8 *ptr;
396 sal_uInt32 length;
397 int r;
398 FILE* fd;
400 if ((r = StreamToMemory(_this, &ptr, &length)) != SF_OK) return r;
401 if (!fname) return SF_BADFILE;
402 if ((fd = fopen(fname, "wb")) == NULL) return SF_BADFILE;
404 if (fwrite(ptr, 1, length, fd) != length) {
405 r = SF_FILEIO;
406 } else {
407 r = SF_OK;
410 fclose(fd);
411 free(ptr);
412 return r;
418 * TrueTypeTable private methods
421 #define TABLESIZE_head 54
422 #define TABLESIZE_hhea 36
423 #define TABLESIZE_maxp 32
427 /* Table data points to
428 * --------------------------------------------
429 * generic tdata_generic struct
430 * 'head' TABLESIZE_head bytes of memory
431 * 'hhea' TABLESIZE_hhea bytes of memory
432 * 'loca' tdata_loca struct
433 * 'maxp' TABLESIZE_maxp bytes of memory
434 * 'glyf' list of GlyphData structs (defined in sft.h)
435 * 'name' list of NameRecord structs (defined in sft.h)
436 * 'post' tdata_post struct
441 #define CMAP_SUBTABLE_INIT 10
442 #define CMAP_SUBTABLE_INCR 10
443 #define CMAP_PAIR_INIT 500
444 #define CMAP_PAIR_INCR 500
446 typedef struct {
447 sal_uInt32 id; /* subtable ID (platform/encoding ID) */
448 sal_uInt32 n; /* number of used translation pairs */
449 sal_uInt32 m; /* number of allocated translation pairs */
450 sal_uInt32 *xc; /* character array */
451 sal_uInt32 *xg; /* glyph array */
452 } CmapSubTable;
454 typedef struct {
455 sal_uInt32 n; /* number of used CMAP sub-tables */
456 sal_uInt32 m; /* number of allocated CMAP sub-tables */
457 CmapSubTable *s; /* sotred array of sub-tables */
458 } table_cmap;
460 typedef struct {
461 sal_uInt32 tag;
462 sal_uInt32 nbytes;
463 sal_uInt8 *ptr;
464 } tdata_generic;
466 typedef struct {
467 sal_uInt32 nbytes; /* number of bytes in loca table */
468 sal_uInt8 *ptr; /* pointer to the data */
469 } tdata_loca;
471 typedef struct {
472 sal_uInt32 format;
473 sal_uInt32 italicAngle;
474 sal_Int16 underlinePosition;
475 sal_Int16 underlineThickness;
476 sal_uInt32 isFixedPitch;
477 void *ptr; /* format-specific pointer */
478 } tdata_post;
481 /* allocate memory for a TT table */
482 static sal_uInt8 *ttmalloc(sal_uInt32 nbytes)
484 sal_uInt32 n;
486 n = (nbytes + 3) & (sal_uInt32) ~3;
487 sal_uInt8* res = (sal_uInt8*)malloc(n);
488 assert(res != 0);
489 memset(res, 0, n);
491 return res;
494 static void FreeGlyphData(void *ptr)
496 GlyphData *p = (GlyphData *) ptr;
497 if (p->ptr) free(p->ptr);
498 free(p);
501 static void TrueTypeTableDispose_generic(TrueTypeTable *_this)
503 if (_this) {
504 if (_this->data) {
505 tdata_generic *pdata = (tdata_generic *) _this->data;
506 if (pdata->nbytes) free(pdata->ptr);
507 free(_this->data);
509 free(_this);
513 static void TrueTypeTableDispose_head(TrueTypeTable *_this)
515 if (_this) {
516 if (_this->data) free(_this->data);
517 free(_this);
521 static void TrueTypeTableDispose_hhea(TrueTypeTable *_this)
523 if (_this) {
524 if (_this->data) free(_this->data);
525 free(_this);
529 static void TrueTypeTableDispose_loca(TrueTypeTable *_this)
531 if (_this) {
532 if (_this->data) {
533 tdata_loca *p = (tdata_loca *) _this->data;
534 if (p->ptr) free(p->ptr);
535 free(_this->data);
537 free(_this);
541 static void TrueTypeTableDispose_maxp(TrueTypeTable *_this)
543 if (_this) {
544 if (_this->data) free(_this->data);
545 free(_this);
549 static void TrueTypeTableDispose_glyf(TrueTypeTable *_this)
551 if (_this) {
552 if (_this->data) listDispose((list) _this->data);
553 free(_this);
557 static void TrueTypeTableDispose_cmap(TrueTypeTable *_this)
559 table_cmap *t;
560 CmapSubTable *s;
561 sal_uInt32 i;
563 if (_this) {
564 t = (table_cmap *) _this->data;
565 if (t) {
566 s = t->s;
567 if (s) {
568 for (i = 0; i < t->m; i++) {
569 if (s[i].xc) free(s[i].xc);
570 if (s[i].xg) free(s[i].xg);
572 free(s);
574 free(t);
576 free(_this);
580 static void TrueTypeTableDispose_name(TrueTypeTable *_this)
582 if (_this) {
583 if (_this->data) listDispose((list) _this->data);
584 free(_this);
588 static void TrueTypeTableDispose_post(TrueTypeTable *_this)
590 if (_this) {
591 tdata_post *p = (tdata_post *) _this->data;
592 if (p) {
593 if (p->format == 0x00030000) {
594 /* do nothing */
595 } else {
596 fprintf(stderr, "Unsupported format of a 'post' table: %08X.\n", (int)p->format);
598 free(p);
600 free(_this);
604 /* destructor vtable */
606 static struct {
607 sal_uInt32 tag;
608 void (*f)(TrueTypeTable *);
609 } vtable1[] =
611 {0, TrueTypeTableDispose_generic},
612 {T_head, TrueTypeTableDispose_head},
613 {T_hhea, TrueTypeTableDispose_hhea},
614 {T_loca, TrueTypeTableDispose_loca},
615 {T_maxp, TrueTypeTableDispose_maxp},
616 {T_glyf, TrueTypeTableDispose_glyf},
617 {T_cmap, TrueTypeTableDispose_cmap},
618 {T_name, TrueTypeTableDispose_name},
619 {T_post, TrueTypeTableDispose_post}
623 static int GetRawData_generic(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
625 assert(_this != 0);
626 assert(_this->data != 0);
628 *ptr = ((tdata_generic *) _this->data)->ptr;
629 *len = ((tdata_generic *) _this->data)->nbytes;
630 *tag = ((tdata_generic *) _this->data)->tag;
632 return TTCR_OK;
636 static int GetRawData_head(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
638 *len = TABLESIZE_head;
639 *ptr = (sal_uInt8 *) _this->data;
640 *tag = T_head;
642 return TTCR_OK;
645 static int GetRawData_hhea(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
647 *len = TABLESIZE_hhea;
648 *ptr = (sal_uInt8 *) _this->data;
649 *tag = T_hhea;
651 return TTCR_OK;
654 static int GetRawData_loca(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
656 tdata_loca *p;
658 assert(_this->data != 0);
660 p = (tdata_loca *) _this->data;
662 if (p->nbytes == 0) return TTCR_ZEROGLYPHS;
664 *ptr = p->ptr;
665 *len = p->nbytes;
666 *tag = T_loca;
668 return TTCR_OK;
671 static int GetRawData_maxp(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
673 *len = TABLESIZE_maxp;
674 *ptr = (sal_uInt8 *) _this->data;
675 *tag = T_maxp;
677 return TTCR_OK;
680 static int GetRawData_glyf(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
682 sal_uInt32 n, nbytes = 0;
683 list l = (list) _this->data;
684 /* sal_uInt16 curID = 0; */ /* to check if glyph IDs are sequential and start from zero */
685 sal_uInt8 *p;
687 *ptr = 0;
688 *len = 0;
689 *tag = 0;
691 if (listCount(l) == 0) return TTCR_ZEROGLYPHS;
693 listToFirst(l);
694 do {
695 /* if (((GlyphData *) listCurrent(l))->glyphID != curID++) return TTCR_GLYPHSEQ; */
696 nbytes += ((GlyphData *) listCurrent(l))->nbytes;
697 } while (listNext(l));
699 p = _this->rawdata = ttmalloc(nbytes);
701 listToFirst(l);
702 do {
703 n = ((GlyphData *) listCurrent(l))->nbytes;
704 if (n != 0) {
705 memcpy(p, ((GlyphData *) listCurrent(l))->ptr, n);
706 p += n;
708 } while (listNext(l));
710 *len = nbytes;
711 *ptr = _this->rawdata;
712 *tag = T_glyf;
714 return TTCR_OK;
717 /* cmap packers */
718 static sal_uInt8 *PackCmapType0(CmapSubTable *s, sal_uInt32 *length)
720 sal_uInt8* ptr = (sal_uInt8*)smalloc(262);
721 sal_uInt8 *p = ptr + 6;
722 sal_uInt32 i, j;
723 sal_uInt16 g;
725 PutUInt16(0, ptr, 0, 1);
726 PutUInt16(262, ptr, 2, 1);
727 PutUInt16(0, ptr, 4, 1);
729 for (i = 0; i < 256; i++) {
730 g = 0;
731 for (j = 0; j < s->n; j++) {
732 if (s->xc[j] == i) {
733 g = (sal_uInt16) s->xg[j];
736 p[i] = (sal_uInt8) g;
738 *length = 262;
739 return ptr;
742 static sal_uInt8 *PackCmapType6(CmapSubTable *s, sal_uInt32 *length)
744 sal_uInt8* ptr = (sal_uInt8*)smalloc(s->n*2 + 10);
745 sal_uInt8 *p = ptr + 10;
746 sal_uInt32 i, j;
747 sal_uInt16 g;
749 PutUInt16(6, ptr, 0, 1);
750 PutUInt16((sal_uInt16)(s->n*2+10), ptr, 2, 1);
751 PutUInt16(0, ptr, 4, 1);
752 PutUInt16(0, ptr, 6, 1);
753 PutUInt16((sal_uInt16)(s->n), ptr, 8, 1 );
755 for (i = 0; i < s->n; i++) {
756 g = 0;
757 for (j = 0; j < s->n; j++) {
758 if (s->xc[j] == i) {
759 g = (sal_uInt16) s->xg[j];
762 PutUInt16( g, p, 2*i, 1 );
764 *length = s->n*2+10;
765 return ptr;
770 /* XXX it only handles Format 0 encoding tables */
771 static sal_uInt8 *PackCmap(CmapSubTable *s, sal_uInt32 *length)
773 if( s->xg[s->n-1] > 0xff )
774 return PackCmapType6(s, length);
775 else
776 return PackCmapType0(s, length);
779 static int GetRawData_cmap(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
781 table_cmap *t;
782 sal_uInt32 i;
783 sal_uInt32 tlen = 0;
784 sal_uInt32 l;
785 sal_uInt32 cmapsize;
786 sal_uInt8 *cmap;
787 sal_uInt32 coffset;
789 assert(_this != 0);
790 t = (table_cmap *) _this->data;
791 assert(t != 0);
792 assert(t->n != 0);
794 sal_uInt8** subtables = (sal_uInt8**)scalloc(t->n, sizeof(sal_uInt8 *));
795 sal_uInt32* sizes = (sal_uInt32*)scalloc(t->n, sizeof(sal_uInt32));
797 for (i = 0; i < t->n; i++) {
798 subtables[i] = PackCmap(t->s+i, &l);
799 sizes[i] = l;
800 tlen += l;
803 cmapsize = tlen + 4 + 8 * t->n;
804 _this->rawdata = cmap = ttmalloc(cmapsize);
806 PutUInt16(0, cmap, 0, 1);
807 PutUInt16((sal_uInt16)t->n, cmap, 2, 1);
808 coffset = 4 + t->n * 8;
810 for (i = 0; i < t->n; i++) {
811 PutUInt16((sal_uInt16)(t->s[i].id >> 16), cmap + 4, i * 8, 1);
812 PutUInt16((sal_uInt16)(t->s[i].id & 0xFF), cmap + 4, 2 + i * 8, 1);
813 PutUInt32(coffset, cmap + 4, 4 + i * 8, 1);
814 memcpy(cmap + coffset, subtables[i], sizes[i]);
815 free(subtables[i]);
816 coffset += sizes[i];
819 free(subtables);
820 free(sizes);
822 *ptr = cmap;
823 *len = cmapsize;
824 *tag = T_cmap;
826 return TTCR_OK;
830 static int GetRawData_name(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
832 list l;
833 sal_Int16 i=0, n; /* number of Name Records */
834 int stringLen = 0;
835 sal_uInt8 *p1, *p2;
837 *ptr = 0;
838 *len = 0;
839 *tag = 0;
841 assert(_this != 0);
842 l = (list) _this->data;
843 assert(l != 0);
845 if ((n = (sal_Int16)listCount(l)) == 0) return TTCR_NONAMES;
847 NameRecord* nr = (NameRecord*)scalloc(n, sizeof(NameRecord));
849 listToFirst(l);
851 do {
852 memcpy(nr+i, listCurrent(l), sizeof(NameRecord));
853 stringLen += nr[i].slen;
854 i++;
855 } while (listNext(l));
857 if (stringLen > 65535) {
858 free(nr);
859 return TTCR_NAMETOOLONG;
862 qsort(nr, n, sizeof(NameRecord), NameRecordCompareF);
864 int nameLen = stringLen + 12 * n + 6;
865 sal_uInt8* name = (sal_uInt8*)ttmalloc(nameLen);
867 PutUInt16(0, name, 0, 1);
868 PutUInt16(n, name, 2, 1);
869 PutUInt16((sal_uInt16)(6 + 12 * n), name, 4, 1);
871 p1 = name + 6;
872 p2 = p1 + 12 * n;
874 for (i = 0; i < n; i++) {
875 PutUInt16(nr[i].platformID, p1, 0, 1);
876 PutUInt16(nr[i].encodingID, p1, 2, 1);
877 PutUInt16(nr[i].languageID, p1, 4, 1);
878 PutUInt16(nr[i].nameID, p1, 6, 1);
879 PutUInt16(nr[i].slen, p1, 8, 1);
880 PutUInt16((sal_uInt16)(p2 - (name + 6 + 12 * n)), p1, 10, 1);
881 memcpy(p2, nr[i].sptr, nr[i].slen);
882 /* {int j; for(j=0; j<nr[i].slen; j++) printf("%c", nr[i].sptr[j]); printf("\n"); }; */
883 p2 += nr[i].slen;
884 p1 += 12;
887 free(nr);
888 _this->rawdata = name;
890 *ptr = name;
891 *len = (sal_uInt16)nameLen;
892 *tag = T_name;
894 /*{int j; for(j=0; j<nameLen; j++) printf("%c", name[j]); }; */
896 return TTCR_OK;
899 static int GetRawData_post(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
901 tdata_post *p = (tdata_post *) _this->data;
902 sal_uInt8 *post = 0;
903 sal_uInt32 postLen = 0;
904 int ret;
906 if (_this->rawdata) free(_this->rawdata);
908 if (p->format == 0x00030000) {
909 postLen = 32;
910 post = ttmalloc(postLen);
911 PutUInt32(0x00030000, post, 0, 1);
912 PutUInt32(p->italicAngle, post, 4, 1);
913 PutUInt16(p->underlinePosition, post, 8, 1);
914 PutUInt16(p->underlineThickness, post, 10, 1);
915 PutUInt16((sal_uInt16)p->isFixedPitch, post, 12, 1);
916 ret = TTCR_OK;
917 } else {
918 fprintf(stderr, "Unrecognized format of a post table: %08X.\n", (int)p->format);
919 ret = TTCR_POSTFORMAT;
922 *ptr = _this->rawdata = post;
923 *len = postLen;
924 *tag = T_post;
926 return ret;
933 static struct {
934 sal_uInt32 tag;
935 int (*f)(TrueTypeTable *, sal_uInt8 **, sal_uInt32 *, sal_uInt32 *);
936 } vtable2[] =
938 {0, GetRawData_generic},
939 {T_head, GetRawData_head},
940 {T_hhea, GetRawData_hhea},
941 {T_loca, GetRawData_loca},
942 {T_maxp, GetRawData_maxp},
943 {T_glyf, GetRawData_glyf},
944 {T_cmap, GetRawData_cmap},
945 {T_name, GetRawData_name},
946 {T_post, GetRawData_post}
952 * TrueTypeTable public methods
955 /* Note: Type42 fonts only need these tables:
956 * head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm
958 * Microsoft required tables
959 * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post, OS/2
961 * Apple required tables
962 * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post
966 TrueTypeTable *TrueTypeTableNew(sal_uInt32 tag,
967 sal_uInt32 nbytes,
968 const sal_uInt8* ptr)
970 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
971 tdata_generic* pdata = (tdata_generic*)smalloc(sizeof(tdata_generic));
972 pdata->nbytes = nbytes;
973 pdata->tag = tag;
974 if (nbytes) {
975 pdata->ptr = ttmalloc(nbytes);
976 memcpy(pdata->ptr, ptr, nbytes);
977 } else {
978 pdata->ptr = 0;
981 table->tag = 0;
982 table->data = pdata;
983 table->rawdata = 0;
985 return table;
988 TrueTypeTable *TrueTypeTableNew_head(sal_uInt32 fontRevision,
989 sal_uInt16 flags,
990 sal_uInt16 unitsPerEm,
991 const sal_uInt8* created,
992 sal_uInt16 macStyle,
993 sal_uInt16 lowestRecPPEM,
994 sal_Int16 fontDirectionHint)
996 assert(created != 0);
998 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
999 sal_uInt8* ptr = (sal_uInt8*)ttmalloc(TABLESIZE_head);
1002 PutUInt32(0x00010000, ptr, 0, 1); /* version */
1003 PutUInt32(fontRevision, ptr, 4, 1);
1004 PutUInt32(0x5F0F3CF5, ptr, 12, 1); /* magic number */
1005 PutUInt16(flags, ptr, 16, 1);
1006 PutUInt16(unitsPerEm, ptr, 18, 1);
1007 memcpy(ptr+20, created, 8); /* Created Long Date */
1008 memset(ptr+28, 0, 8); /* Modified Long Date */
1009 PutUInt16(macStyle, ptr, 44, 1);
1010 PutUInt16(lowestRecPPEM, ptr, 46, 1);
1011 PutUInt16(fontDirectionHint, ptr, 48, 1);
1012 PutUInt16(0, ptr, 52, 1); /* glyph data format: 0 */
1014 table->data = (void *) ptr;
1015 table->tag = T_head;
1016 table->rawdata = 0;
1018 return table;
1021 TrueTypeTable *TrueTypeTableNew_hhea(sal_Int16 ascender,
1022 sal_Int16 descender,
1023 sal_Int16 linegap,
1024 sal_Int16 caretSlopeRise,
1025 sal_Int16 caretSlopeRun)
1027 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1028 sal_uInt8* ptr = (sal_uInt8*)ttmalloc(TABLESIZE_hhea);
1030 PutUInt32(0x00010000, ptr, 0, 1); /* version */
1031 PutUInt16(ascender, ptr, 4, 1);
1032 PutUInt16(descender, ptr, 6, 1);
1033 PutUInt16(linegap, ptr, 8, 1);
1034 PutUInt16(caretSlopeRise, ptr, 18, 1);
1035 PutUInt16(caretSlopeRun, ptr, 20, 1);
1036 PutUInt16(0, ptr, 22, 1); /* reserved 1 */
1037 PutUInt16(0, ptr, 24, 1); /* reserved 2 */
1038 PutUInt16(0, ptr, 26, 1); /* reserved 3 */
1039 PutUInt16(0, ptr, 28, 1); /* reserved 4 */
1040 PutUInt16(0, ptr, 30, 1); /* reserved 5 */
1041 PutUInt16(0, ptr, 32, 1); /* metricDataFormat */
1043 table->data = (void *) ptr;
1044 table->tag = T_hhea;
1045 table->rawdata = 0;
1047 return table;
1050 TrueTypeTable *TrueTypeTableNew_loca(void)
1052 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1053 table->data = smalloc(sizeof(tdata_loca));
1055 ((tdata_loca *)table->data)->nbytes = 0;
1056 ((tdata_loca *)table->data)->ptr = 0;
1058 table->tag = T_loca;
1059 table->rawdata = 0;
1061 return table;
1064 TrueTypeTable *TrueTypeTableNew_maxp( const sal_uInt8* maxp, int size)
1066 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1067 table->data = ttmalloc(TABLESIZE_maxp);
1069 if (maxp && size == TABLESIZE_maxp) {
1070 memcpy(table->data, maxp, TABLESIZE_maxp);
1073 table->tag = T_maxp;
1074 table->rawdata = 0;
1076 return table;
1079 TrueTypeTable *TrueTypeTableNew_glyf(void)
1081 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1082 list l = listNewEmpty();
1084 assert(l != 0);
1086 listSetElementDtor(l, (list_destructor)FreeGlyphData);
1088 table->data = l;
1089 table->rawdata = 0;
1090 table->tag = T_glyf;
1092 return table;
1095 TrueTypeTable *TrueTypeTableNew_cmap(void)
1097 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1098 table_cmap* cmap = (table_cmap*)smalloc(sizeof(table_cmap));
1100 cmap->n = 0;
1101 cmap->m = CMAP_SUBTABLE_INIT;
1102 cmap->s = (CmapSubTable *) scalloc(CMAP_SUBTABLE_INIT, sizeof(CmapSubTable));
1103 memset(cmap->s, 0, sizeof(CmapSubTable) * CMAP_SUBTABLE_INIT);
1105 table->data = (table_cmap *) cmap;
1107 table->rawdata = 0;
1108 table->tag = T_cmap;
1110 return table;
1113 static void DisposeNameRecord(void *ptr)
1115 if (ptr != 0) {
1116 NameRecord *nr = (NameRecord *) ptr;
1117 if (nr->sptr) free(nr->sptr);
1118 free(ptr);
1122 static NameRecord* NameRecordNewCopy(NameRecord *nr)
1124 NameRecord* p = (NameRecord*)smalloc(sizeof(NameRecord));
1126 memcpy(p, nr, sizeof(NameRecord));
1128 if (p->slen) {
1129 p->sptr = (sal_uInt8*)smalloc(p->slen);
1130 memcpy(p->sptr, nr->sptr, p->slen);
1133 return p;
1136 TrueTypeTable *TrueTypeTableNew_name(int n, NameRecord *nr)
1138 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1139 list l = listNewEmpty();
1141 assert(l != 0);
1143 listSetElementDtor(l, (list_destructor)DisposeNameRecord);
1145 if (n != 0) {
1146 int i;
1147 for (i = 0; i < n; i++) {
1148 listAppend(l, NameRecordNewCopy(nr+i));
1152 table->data = l;
1153 table->rawdata = 0;
1154 table->tag = T_name;
1156 return table;
1159 TrueTypeTable *TrueTypeTableNew_post(sal_uInt32 format,
1160 sal_uInt32 italicAngle,
1161 sal_Int16 underlinePosition,
1162 sal_Int16 underlineThickness,
1163 sal_uInt32 isFixedPitch)
1165 assert(format == 0x00030000); /* Only format 3.0 is supported at this time */
1166 TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1167 tdata_post* post = (tdata_post*)smalloc(sizeof(tdata_post));
1169 post->format = format;
1170 post->italicAngle = italicAngle;
1171 post->underlinePosition = underlinePosition;
1172 post->underlineThickness = underlineThickness;
1173 post->isFixedPitch = isFixedPitch;
1174 post->ptr = 0;
1176 table->data = post;
1177 table->rawdata = 0;
1178 table->tag = T_post;
1180 return table;
1183 int GetRawData(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
1185 /* XXX do a binary search */
1186 unsigned int i;
1188 assert(_this != 0);
1189 assert(ptr != 0);
1190 assert(len != 0);
1191 assert(tag != 0);
1193 *ptr = 0; *len = 0; *tag = 0;
1195 if (_this->rawdata) {
1196 free(_this->rawdata);
1197 _this->rawdata = 0;
1200 for(i=0; i < sizeof(vtable2)/sizeof(*vtable2); i++) {
1201 if (_this->tag == vtable2[i].tag) {
1202 return vtable2[i].f(_this, ptr, len, tag);
1206 assert(!"Unknwon TrueType table.\n");
1207 return TTCR_UNKNOWN;
1210 void cmapAdd(TrueTypeTable *table, sal_uInt32 id, sal_uInt32 c, sal_uInt32 g)
1212 sal_uInt32 i, found;
1213 table_cmap *t;
1214 CmapSubTable *s;
1216 assert(table != 0);
1217 assert(table->tag == T_cmap);
1218 t = (table_cmap *) table->data; assert(t != 0);
1219 s = t->s; assert(s != 0);
1221 found = 0;
1223 for (i = 0; i < t->n; i++) {
1224 if (s[i].id == id) {
1225 found = 1;
1226 break;
1230 if (!found) {
1231 if (t->n == t->m) {
1232 CmapSubTable* tmp = (CmapSubTable*)scalloc(t->m + CMAP_SUBTABLE_INCR, sizeof(CmapSubTable));
1233 memset(tmp, 0, t->m + CMAP_SUBTABLE_INCR * sizeof(CmapSubTable));
1234 memcpy(tmp, s, sizeof(CmapSubTable) * t->m);
1235 t->m += CMAP_SUBTABLE_INCR;
1236 free(s);
1237 s = tmp;
1238 t->s = s;
1241 for (i = 0; i < t->n; i++) {
1242 if (s[i].id > id) break;
1245 if (i < t->n) {
1246 memmove(s+i+1, s+i, t->n-i);
1249 t->n++;
1251 s[i].id = id;
1252 s[i].n = 0;
1253 s[i].m = CMAP_PAIR_INIT;
1254 s[i].xc = (sal_uInt32*)scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32));
1255 s[i].xg = (sal_uInt32*)scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32));
1258 if (s[i].n == s[i].m) {
1259 sal_uInt32* tmp1 = (sal_uInt32*)scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32));
1260 sal_uInt32* tmp2 = (sal_uInt32*)scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32));
1261 assert(tmp1 != 0);
1262 assert(tmp2 != 0);
1263 memcpy(tmp1, s[i].xc, sizeof(sal_uInt32) * s[i].m);
1264 memcpy(tmp2, s[i].xg, sizeof(sal_uInt32) * s[i].m);
1265 s[i].m += CMAP_PAIR_INCR;
1266 free(s[i].xc);
1267 free(s[i].xg);
1268 s[i].xc = tmp1;
1269 s[i].xg = tmp2;
1272 s[i].xc[s[i].n] = c;
1273 s[i].xg[s[i].n] = g;
1274 s[i].n++;
1277 sal_uInt32 glyfAdd(TrueTypeTable *table, GlyphData *glyphdata, TrueTypeFont *fnt)
1279 list l;
1280 sal_uInt32 currentID;
1281 int ret, n, ncomponents;
1282 GlyphData *gd;
1284 assert(table != 0);
1285 assert(table->tag == T_glyf);
1287 if (!glyphdata) return (sal_uInt32)~0;
1289 std::vector< sal_uInt32 > glyphlist;
1291 ncomponents = GetTTGlyphComponents(fnt, glyphdata->glyphID, glyphlist);
1293 l = (list) table->data;
1294 if (listCount(l) > 0) {
1295 listToLast(l);
1296 ret = n = ((GlyphData *) listCurrent(l))->newID + 1;
1297 } else {
1298 ret = n = 0;
1300 glyphdata->newID = n++;
1301 listAppend(l, glyphdata);
1303 if (ncomponents > 1 && glyphlist.size() > 1 )
1305 std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin();
1306 ++it;
1307 /* glyphData->glyphID is always the first glyph on the list */
1310 int found = 0;
1311 currentID = *it;
1312 /* XXX expensive! should be rewritten with sorted arrays! */
1313 listToFirst(l);
1314 do {
1315 if (((GlyphData *) listCurrent(l))->glyphID == currentID) {
1316 found = 1;
1317 break;
1319 } while (listNext(l));
1321 if (!found) {
1322 gd = GetTTRawGlyphData(fnt, currentID);
1323 gd->newID = n++;
1324 listAppend(l, gd);
1326 } while( ++it != glyphlist.end() );
1329 return ret;
1332 sal_uInt32 glyfCount(const TrueTypeTable *table)
1334 assert(table != 0);
1335 assert(table->tag == T_glyf);
1336 return listCount((list) table->data);
1340 void nameAdd(TrueTypeTable *table, NameRecord *nr)
1342 list l;
1344 assert(table != 0);
1345 assert(table->tag == T_name);
1347 l = (list) table->data;
1349 listAppend(l, NameRecordNewCopy(nr));
1352 static TrueTypeTable *FindTable(TrueTypeCreator *tt, sal_uInt32 tag)
1354 if (listIsEmpty(tt->tables)) return 0;
1356 listToFirst(tt->tables);
1358 do {
1359 if (((TrueTypeTable *) listCurrent(tt->tables))->tag == tag) {
1360 return (TrueTypeTable*)listCurrent(tt->tables);
1362 } while (listNext(tt->tables));
1364 return 0;
1367 /* This function processes all the tables and synchronizes them before creating
1368 * the output TrueType stream.
1370 * *** It adds two TrueType tables to the font: 'loca' and 'hmtx' ***
1372 * It does:
1374 * - Re-numbers glyph IDs and creates 'glyf', 'loca', and 'hmtx' tables.
1375 * - Calculates xMin, yMin, xMax, and yMax and stores values in 'head' table.
1376 * - Stores indexToLocFormat in 'head'
1377 * - updates 'maxp' table
1378 * - Calculates advanceWidthMax, minLSB, minRSB, xMaxExtent and numberOfHMetrics
1379 * in 'hhea' table
1382 static void ProcessTables(TrueTypeCreator *tt)
1384 TrueTypeTable *glyf, *loca, *head, *maxp, *hhea;
1385 list glyphlist;
1386 sal_uInt32 nGlyphs, locaLen = 0, glyfLen = 0;
1387 sal_Int16 xMin = 0, yMin = 0, xMax = 0, yMax = 0;
1388 sal_uInt32 i = 0;
1389 sal_Int16 indexToLocFormat;
1390 sal_uInt8 *hmtxPtr, *hheaPtr;
1391 sal_uInt32 hmtxSize;
1392 sal_uInt8 *p1, *p2;
1393 sal_uInt16 maxPoints = 0, maxContours = 0, maxCompositePoints = 0, maxCompositeContours = 0;
1394 int nlsb = 0;
1395 sal_uInt32 *gid; /* array of old glyphIDs */
1397 glyf = FindTable(tt, T_glyf);
1398 glyphlist = (list) glyf->data;
1399 nGlyphs = listCount(glyphlist);
1400 assert(nGlyphs != 0);
1401 gid = (sal_uInt32*)scalloc(nGlyphs, sizeof(sal_uInt32));
1403 RemoveTable(tt, T_loca);
1404 RemoveTable(tt, T_hmtx);
1406 /* XXX Need to make sure that composite glyphs do not break during glyph renumbering */
1408 listToFirst(glyphlist);
1409 do {
1410 GlyphData *gd = (GlyphData *) listCurrent(glyphlist);
1411 sal_Int16 z;
1412 glyfLen += gd->nbytes;
1413 /* XXX if (gd->nbytes & 1) glyfLen++; */
1416 assert(gd->newID == i);
1417 gid[i++] = gd->glyphID;
1418 /* gd->glyphID = i++; */
1420 /* printf("IDs: %d %d.\n", gd->glyphID, gd->newID); */
1422 if (gd->nbytes != 0) {
1423 z = GetInt16(gd->ptr, 2, 1);
1424 if (z < xMin) xMin = z;
1426 z = GetInt16(gd->ptr, 4, 1);
1427 if (z < yMin) yMin = z;
1429 z = GetInt16(gd->ptr, 6, 1);
1430 if (z > xMax) xMax = z;
1432 z = GetInt16(gd->ptr, 8, 1);
1433 if (z > yMax) yMax = z;
1436 if (gd->compflag == 0) { /* non-composite glyph */
1437 if (gd->npoints > maxPoints) maxPoints = gd->npoints;
1438 if (gd->ncontours > maxContours) maxContours = gd->ncontours;
1439 } else { /* composite glyph */
1440 if (gd->npoints > maxCompositePoints) maxCompositePoints = gd->npoints;
1441 if (gd->ncontours > maxCompositeContours) maxCompositeContours = gd->ncontours;
1444 } while (listNext(glyphlist));
1446 indexToLocFormat = (glyfLen / 2 > 0xFFFF) ? 1 : 0;
1447 locaLen = indexToLocFormat ? (nGlyphs + 1) << 2 : (nGlyphs + 1) << 1;
1449 sal_uInt8* glyfPtr = ttmalloc(glyfLen);
1450 sal_uInt8* locaPtr = ttmalloc(locaLen);
1451 TTSimpleGlyphMetrics* met = (TTSimpleGlyphMetrics*)scalloc(nGlyphs, sizeof(TTSimpleGlyphMetrics));
1452 i = 0;
1454 listToFirst(glyphlist);
1455 p1 = glyfPtr;
1456 p2 = locaPtr;
1457 do {
1458 GlyphData *gd = (GlyphData *) listCurrent(glyphlist);
1460 if (gd->compflag) { /* re-number all components */
1461 sal_uInt16 flags, index;
1462 sal_uInt8 *ptr = gd->ptr + 10;
1463 do {
1464 sal_uInt32 j;
1465 flags = GetUInt16(ptr, 0, 1);
1466 index = GetUInt16(ptr, 2, 1);
1467 /* XXX use the sorted array of old to new glyphID mapping and do a binary search */
1468 for (j = 0; j < nGlyphs; j++) {
1469 if (gid[j] == index) {
1470 break;
1473 /* printf("X: %d -> %d.\n", index, j); */
1475 PutUInt16((sal_uInt16) j, ptr, 2, 1);
1477 ptr += 4;
1479 if (flags & ARG_1_AND_2_ARE_WORDS) {
1480 ptr += 4;
1481 } else {
1482 ptr += 2;
1485 if (flags & WE_HAVE_A_SCALE) {
1486 ptr += 2;
1487 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
1488 ptr += 4;
1489 } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
1490 ptr += 8;
1492 } while (flags & MORE_COMPONENTS);
1495 if (gd->nbytes != 0) {
1496 memcpy(p1, gd->ptr, gd->nbytes);
1498 if (indexToLocFormat == 1) {
1499 PutUInt32(p1 - glyfPtr, p2, 0, 1);
1500 p2 += 4;
1501 } else {
1502 PutUInt16((sal_uInt16)((p1 - glyfPtr) >> 1), p2, 0, 1);
1503 p2 += 2;
1505 p1 += gd->nbytes;
1507 /* fill the array of metrics */
1508 met[i].adv = gd->aw;
1509 met[i].sb = gd->lsb;
1510 i++;
1511 } while (listNext(glyphlist));
1513 free(gid);
1515 if (indexToLocFormat == 1) {
1516 PutUInt32(p1 - glyfPtr, p2, 0, 1);
1517 } else {
1518 PutUInt16((sal_uInt16)((p1 - glyfPtr) >> 1), p2, 0, 1);
1521 glyf->rawdata = glyfPtr;
1523 loca = TrueTypeTableNew_loca(); assert(loca != 0);
1524 ((tdata_loca *) loca->data)->ptr = locaPtr;
1525 ((tdata_loca *) loca->data)->nbytes = locaLen;
1527 AddTable(tt, loca);
1529 head = FindTable(tt, T_head);
1530 sal_uInt8* const pHeadData = (sal_uInt8*)head->data;
1531 PutInt16(xMin, pHeadData, 36, 1);
1532 PutInt16(yMin, pHeadData, 38, 1);
1533 PutInt16(xMax, pHeadData, 40, 1);
1534 PutInt16(yMax, pHeadData, 42, 1);
1535 PutInt16(indexToLocFormat, pHeadData, 50, 1);
1537 maxp = FindTable(tt, T_maxp);
1539 sal_uInt8* const pMaxpData = (sal_uInt8*)maxp->data;
1540 PutUInt16((sal_uInt16)nGlyphs, pMaxpData, 4, 1);
1541 PutUInt16(maxPoints, pMaxpData, 6, 1);
1542 PutUInt16(maxContours, pMaxpData, 8, 1);
1543 PutUInt16(maxCompositePoints, pMaxpData, 10, 1);
1544 PutUInt16(maxCompositeContours, pMaxpData, 12, 1);
1546 #if 0
1547 /* XXX do not overwrite the existing data. Fix: re-calculate these numbers here */
1548 PutUInt16(2, maxp->data, 14, 1); /* maxZones is always 2 */
1549 PutUInt16(0, maxp->data, 16, 1); /* maxTwilightPoints */
1550 PutUInt16(0, maxp->data, 18, 1); /* maxStorage */
1551 PutUInt16(0, maxp->data, 20, 1); /* maxFunctionDefs */
1552 PutUint16(0, maxp->data, 22, 1); /* maxInstructionDefs */
1553 PutUint16(0, maxp->data, 24, 1); /* maxStackElements */
1554 PutUint16(0, maxp->data, 26, 1); /* maxSizeOfInstructions */
1555 PutUint16(0, maxp->data, 28, 1); /* maxComponentElements */
1556 PutUint16(0, maxp->data, 30, 1); /* maxComponentDepth */
1557 #endif
1560 * Generate an htmx table and update hhea table
1562 hhea = FindTable(tt, T_hhea); assert(hhea != 0);
1563 hheaPtr = (sal_uInt8 *) hhea->data;
1564 if (nGlyphs > 2) {
1565 for (i = nGlyphs - 1; i > 0; i--) {
1566 if (met[i].adv != met[i-1].adv) break;
1568 nlsb = nGlyphs - 1 - i;
1570 hmtxSize = (nGlyphs - nlsb) * 4 + nlsb * 2;
1571 hmtxPtr = ttmalloc(hmtxSize);
1572 p1 = hmtxPtr;
1574 for (i = 0; i < nGlyphs; i++) {
1575 if (i < nGlyphs - nlsb) {
1576 PutUInt16(met[i].adv, p1, 0, 1);
1577 PutUInt16(met[i].sb, p1, 2, 1);
1578 p1 += 4;
1579 } else {
1580 PutUInt16(met[i].sb, p1, 0, 1);
1581 p1 += 2;
1585 AddTable(tt, TrueTypeTableNew(T_hmtx, hmtxSize, hmtxPtr));
1586 PutUInt16((sal_uInt16)(nGlyphs - nlsb), hheaPtr, 34, 1);
1587 free(hmtxPtr);
1588 free(met);
1591 } // namespace vcl
1593 extern "C"
1596 * TrueTypeCreator destructor. It calls destructors for all TrueTypeTables added to it.
1598 void TrueTypeCreatorDispose(vcl::TrueTypeCreator *_this)
1600 listDispose(_this->tables);
1601 free(_this);
1606 * Destructor for the TrueTypeTable object.
1608 void TrueTypeTableDispose(vcl::TrueTypeTable *_this)
1610 /* XXX do a binary search */
1611 unsigned int i;
1613 assert(_this != 0);
1615 if (_this->rawdata) free(_this->rawdata);
1617 for(i=0; i < sizeof(vcl::vtable1)/sizeof(*vcl::vtable1); i++) {
1618 if (_this->tag == vcl::vtable1[i].tag) {
1619 vcl::vtable1[i].f(_this);
1620 return;
1623 assert(!"Unknown TrueType table.\n");
1628 #ifdef TEST_TTCR
1629 int main(void)
1631 TrueTypeCreator *ttcr;
1632 sal_uInt8 *t1, *t2, *t3, *t4, *t5, *t6, *t7;
1634 TrueTypeCreatorNewEmpty(mkTag('t','r','u','e'), &ttcr);
1636 t1 = malloc(1000); memset(t1, 'a', 1000);
1637 t2 = malloc(2000); memset(t2, 'b', 2000);
1638 t3 = malloc(3000); memset(t3, 'c', 3000);
1639 t4 = malloc(4000); memset(t4, 'd', 4000);
1640 t5 = malloc(5000); memset(t5, 'e', 5000);
1641 t6 = malloc(6000); memset(t6, 'f', 6000);
1642 t7 = malloc(7000); memset(t7, 'g', 7000);
1644 AddTable(ttcr, TrueTypeTableNew(0x6D617870, 1000, t1));
1645 AddTable(ttcr, TrueTypeTableNew(0x4F532F32, 2000, t2));
1646 AddTable(ttcr, TrueTypeTableNew(0x636D6170, 3000, t3));
1647 AddTable(ttcr, TrueTypeTableNew(0x6C6F6361, 4000, t4));
1648 AddTable(ttcr, TrueTypeTableNew(0x68686561, 5000, t5));
1649 AddTable(ttcr, TrueTypeTableNew(0x676C7966, 6000, t6));
1650 AddTable(ttcr, TrueTypeTableNew(0x6B65726E, 7000, t7));
1652 free(t1);
1653 free(t2);
1654 free(t3);
1655 free(t4);
1656 free(t5);
1657 free(t6);
1658 free(t7);
1661 StreamToFile(ttcr, "ttcrout.ttf");
1663 TrueTypeCreatorDispose(ttcr);
1664 return 0;
1666 #endif