1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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
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
83 * this is a duplicate code from sft.c but it is left here for performance reasons
86 #define _inline static __inline__
88 #define _inline static
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
)
102 t
= (ptr
+offset
)[0] << 8 | (ptr
+offset
)[1];
104 t
= (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
110 _inline sal_uInt16
GetUInt16( const sal_uInt8
* ptr
, sal_uInt32 offset
, int bigendian
)
116 t
= (ptr
+offset
)[0] << 8 | (ptr
+offset
)[1];
118 t
= (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
124 _inline sal_Int32
GetInt32( const sal_uInt8
* ptr
, sal_uInt32 offset
, int bigendian
)
130 t
= (ptr
+offset
)[0] << 24 | (ptr
+offset
)[1] << 16 |
131 (ptr
+offset
)[2] << 8 | (ptr
+offset
)[3];
133 t
= (ptr
+offset
)[3] << 24 | (ptr
+offset
)[2] << 16 |
134 (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
140 _inline sal_uInt32
GetUInt32( const sal_uInt8
* ptr
, sal_uInt32 offset
, int bigendian
)
147 t
= (ptr
+offset
)[0] << 24 | (ptr
+offset
)[1] << 16 |
148 (ptr
+offset
)[2] << 8 | (ptr
+offset
)[3];
150 t
= (ptr
+offset
)[3] << 24 | (ptr
+offset
)[2] << 16 |
151 (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
158 _inline
void PutInt16(sal_Int16 val
, sal_uInt8
*ptr
, sal_uInt32 offset
, int bigendian
)
163 ptr
[offset
] = (sal_uInt8
)((val
>> 8) & 0xFF);
164 ptr
[offset
+1] = (sal_uInt8
)(val
& 0xFF);
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
)
176 ptr
[offset
] = (sal_uInt8
)((val
>> 8) & 0xFF);
177 ptr
[offset
+1] = (sal_uInt8
)(val
& 0xFF);
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
)
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);
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
)
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);
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
;
244 static sal_uInt32
CheckSum(sal_uInt32
*ptr
, sal_uInt32 length
)
247 sal_uInt32
*endptr
= ptr
+ ((length
+ 3) & (sal_uInt32
) ~3) / 4;
249 while (ptr
< endptr
) sum
+= *ptr
++;
254 _inline
void *smalloc(sal_uInt32 size
)
256 void *res
= malloc(size
);
261 _inline
void *scalloc(sal_uInt32 n
, sal_uInt32 size
)
263 void *res
= calloc(n
, size
);
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
);
284 int AddTable(TrueTypeCreator
*_this
, TrueTypeTable
*table
)
287 listAppend(_this
->tables
, table
);
292 void RemoveTable(TrueTypeCreator
*_this
, sal_uInt32 tag
)
296 if (listCount(_this
->tables
)) {
297 listToFirst(_this
->tables
);
299 if (((TrueTypeTable
*) listCurrent(_this
->tables
))->tag
== tag
) {
300 listRemove(_this
->tables
);
302 if (listNext(_this
->tables
)) {
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;
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
);
343 } while (searchRange
<= numTables
);
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
);
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
) {
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; */
383 p
= (sal_uInt32
*) ttf
;
384 for (i
= 0; i
< (int)s
/ 4; i
++) checkSumAdjustment
+= p
[i
];
385 PutUInt32(0xB1B0AFBA - checkSumAdjustment
, head
, 8, 1);
393 int StreamToFile(TrueTypeCreator
*_this
, const char* fname
)
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
) {
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
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 */
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 */
467 sal_uInt32 nbytes
; /* number of bytes in loca table */
468 sal_uInt8
*ptr
; /* pointer to the data */
473 sal_uInt32 italicAngle
;
474 sal_Int16 underlinePosition
;
475 sal_Int16 underlineThickness
;
476 sal_uInt32 isFixedPitch
;
477 void *ptr
; /* format-specific pointer */
481 /* allocate memory for a TT table */
482 static sal_uInt8
*ttmalloc(sal_uInt32 nbytes
)
486 n
= (nbytes
+ 3) & (sal_uInt32
) ~3;
487 sal_uInt8
* res
= (sal_uInt8
*)malloc(n
);
494 static void FreeGlyphData(void *ptr
)
496 GlyphData
*p
= (GlyphData
*) ptr
;
497 if (p
->ptr
) free(p
->ptr
);
501 static void TrueTypeTableDispose_generic(TrueTypeTable
*_this
)
505 tdata_generic
*pdata
= (tdata_generic
*) _this
->data
;
506 if (pdata
->nbytes
) free(pdata
->ptr
);
513 static void TrueTypeTableDispose_head(TrueTypeTable
*_this
)
516 if (_this
->data
) free(_this
->data
);
521 static void TrueTypeTableDispose_hhea(TrueTypeTable
*_this
)
524 if (_this
->data
) free(_this
->data
);
529 static void TrueTypeTableDispose_loca(TrueTypeTable
*_this
)
533 tdata_loca
*p
= (tdata_loca
*) _this
->data
;
534 if (p
->ptr
) free(p
->ptr
);
541 static void TrueTypeTableDispose_maxp(TrueTypeTable
*_this
)
544 if (_this
->data
) free(_this
->data
);
549 static void TrueTypeTableDispose_glyf(TrueTypeTable
*_this
)
552 if (_this
->data
) listDispose((list
) _this
->data
);
557 static void TrueTypeTableDispose_cmap(TrueTypeTable
*_this
)
564 t
= (table_cmap
*) _this
->data
;
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
);
580 static void TrueTypeTableDispose_name(TrueTypeTable
*_this
)
583 if (_this
->data
) listDispose((list
) _this
->data
);
588 static void TrueTypeTableDispose_post(TrueTypeTable
*_this
)
591 tdata_post
*p
= (tdata_post
*) _this
->data
;
593 if (p
->format
== 0x00030000) {
596 fprintf(stderr
, "Unsupported format of a 'post' table: %08X.\n", (int)p
->format
);
604 /* destructor vtable */
608 void (*f
)(TrueTypeTable
*);
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
)
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
;
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
;
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
;
654 static int GetRawData_loca(TrueTypeTable
*_this
, sal_uInt8
**ptr
, sal_uInt32
*len
, sal_uInt32
*tag
)
658 assert(_this
->data
!= 0);
660 p
= (tdata_loca
*) _this
->data
;
662 if (p
->nbytes
== 0) return TTCR_ZEROGLYPHS
;
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
;
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 */
691 if (listCount(l
) == 0) return TTCR_ZEROGLYPHS
;
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
);
703 n
= ((GlyphData
*) listCurrent(l
))->nbytes
;
705 memcpy(p
, ((GlyphData
*) listCurrent(l
))->ptr
, n
);
708 } while (listNext(l
));
711 *ptr
= _this
->rawdata
;
718 static sal_uInt8
*PackCmapType0(CmapSubTable
*s
, sal_uInt32
*length
)
720 sal_uInt8
* ptr
= (sal_uInt8
*)smalloc(262);
721 sal_uInt8
*p
= ptr
+ 6;
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
++) {
731 for (j
= 0; j
< s
->n
; j
++) {
733 g
= (sal_uInt16
) s
->xg
[j
];
736 p
[i
] = (sal_uInt8
) g
;
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;
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
++) {
757 for (j
= 0; j
< s
->n
; j
++) {
759 g
= (sal_uInt16
) s
->xg
[j
];
762 PutUInt16( g
, p
, 2*i
, 1 );
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
);
776 return PackCmapType0(s
, length
);
779 static int GetRawData_cmap(TrueTypeTable
*_this
, sal_uInt8
**ptr
, sal_uInt32
*len
, sal_uInt32
*tag
)
790 t
= (table_cmap
*) _this
->data
;
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
);
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
]);
830 static int GetRawData_name(TrueTypeTable
*_this
, sal_uInt8
**ptr
, sal_uInt32
*len
, sal_uInt32
*tag
)
833 sal_Int16 i
=0, n
; /* number of Name Records */
842 l
= (list
) _this
->data
;
845 if ((n
= (sal_Int16
)listCount(l
)) == 0) return TTCR_NONAMES
;
847 NameRecord
* nr
= (NameRecord
*)scalloc(n
, sizeof(NameRecord
));
852 memcpy(nr
+i
, listCurrent(l
), sizeof(NameRecord
));
853 stringLen
+= nr
[i
].slen
;
855 } while (listNext(l
));
857 if (stringLen
> 65535) {
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);
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"); }; */
888 _this
->rawdata
= name
;
891 *len
= (sal_uInt16
)nameLen
;
894 /*{int j; for(j=0; j<nameLen; j++) printf("%c", name[j]); }; */
899 static int GetRawData_post(TrueTypeTable
*_this
, sal_uInt8
**ptr
, sal_uInt32
*len
, sal_uInt32
*tag
)
901 tdata_post
*p
= (tdata_post
*) _this
->data
;
903 sal_uInt32 postLen
= 0;
906 if (_this
->rawdata
) free(_this
->rawdata
);
908 if (p
->format
== 0x00030000) {
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);
918 fprintf(stderr
, "Unrecognized format of a post table: %08X.\n", (int)p
->format
);
919 ret
= TTCR_POSTFORMAT
;
922 *ptr
= _this
->rawdata
= post
;
935 int (*f
)(TrueTypeTable
*, sal_uInt8
**, sal_uInt32
*, sal_uInt32
*);
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
,
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
;
975 pdata
->ptr
= ttmalloc(nbytes
);
976 memcpy(pdata
->ptr
, ptr
, nbytes
);
988 TrueTypeTable
*TrueTypeTableNew_head(sal_uInt32 fontRevision
,
990 sal_uInt16 unitsPerEm
,
991 const sal_uInt8
* created
,
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
;
1021 TrueTypeTable
*TrueTypeTableNew_hhea(sal_Int16 ascender
,
1022 sal_Int16 descender
,
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
;
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
;
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
;
1079 TrueTypeTable
*TrueTypeTableNew_glyf(void)
1081 TrueTypeTable
* table
= (TrueTypeTable
*)smalloc(sizeof(TrueTypeTable
));
1082 list l
= listNewEmpty();
1086 listSetElementDtor(l
, (list_destructor
)FreeGlyphData
);
1090 table
->tag
= T_glyf
;
1095 TrueTypeTable
*TrueTypeTableNew_cmap(void)
1097 TrueTypeTable
* table
= (TrueTypeTable
*)smalloc(sizeof(TrueTypeTable
));
1098 table_cmap
* cmap
= (table_cmap
*)smalloc(sizeof(table_cmap
));
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
;
1108 table
->tag
= T_cmap
;
1113 static void DisposeNameRecord(void *ptr
)
1116 NameRecord
*nr
= (NameRecord
*) ptr
;
1117 if (nr
->sptr
) free(nr
->sptr
);
1122 static NameRecord
* NameRecordNewCopy(NameRecord
*nr
)
1124 NameRecord
* p
= (NameRecord
*)smalloc(sizeof(NameRecord
));
1126 memcpy(p
, nr
, sizeof(NameRecord
));
1129 p
->sptr
= (sal_uInt8
*)smalloc(p
->slen
);
1130 memcpy(p
->sptr
, nr
->sptr
, p
->slen
);
1136 TrueTypeTable
*TrueTypeTableNew_name(int n
, NameRecord
*nr
)
1138 TrueTypeTable
* table
= (TrueTypeTable
*)smalloc(sizeof(TrueTypeTable
));
1139 list l
= listNewEmpty();
1143 listSetElementDtor(l
, (list_destructor
)DisposeNameRecord
);
1147 for (i
= 0; i
< n
; i
++) {
1148 listAppend(l
, NameRecordNewCopy(nr
+i
));
1154 table
->tag
= T_name
;
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
;
1178 table
->tag
= T_post
;
1183 int GetRawData(TrueTypeTable
*_this
, sal_uInt8
**ptr
, sal_uInt32
*len
, sal_uInt32
*tag
)
1185 /* XXX do a binary search */
1193 *ptr
= 0; *len
= 0; *tag
= 0;
1195 if (_this
->rawdata
) {
1196 free(_this
->rawdata
);
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
;
1217 assert(table
->tag
== T_cmap
);
1218 t
= (table_cmap
*) table
->data
; assert(t
!= 0);
1219 s
= t
->s
; assert(s
!= 0);
1223 for (i
= 0; i
< t
->n
; i
++) {
1224 if (s
[i
].id
== id
) {
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
;
1241 for (i
= 0; i
< t
->n
; i
++) {
1242 if (s
[i
].id
> id
) break;
1246 memmove(s
+i
+1, s
+i
, t
->n
-i
);
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
));
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
;
1272 s
[i
].xc
[s
[i
].n
] = c
;
1273 s
[i
].xg
[s
[i
].n
] = g
;
1277 sal_uInt32
glyfAdd(TrueTypeTable
*table
, GlyphData
*glyphdata
, TrueTypeFont
*fnt
)
1280 sal_uInt32 currentID
;
1281 int ret
, n
, ncomponents
;
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) {
1296 ret
= n
= ((GlyphData
*) listCurrent(l
))->newID
+ 1;
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();
1307 /* glyphData->glyphID is always the first glyph on the list */
1312 /* XXX expensive! should be rewritten with sorted arrays! */
1315 if (((GlyphData
*) listCurrent(l
))->glyphID
== currentID
) {
1319 } while (listNext(l
));
1322 gd
= GetTTRawGlyphData(fnt
, currentID
);
1326 } while( ++it
!= glyphlist
.end() );
1332 sal_uInt32
glyfCount(const TrueTypeTable
*table
)
1335 assert(table
->tag
== T_glyf
);
1336 return listCount((list
) table
->data
);
1340 void nameAdd(TrueTypeTable
*table
, NameRecord
*nr
)
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
);
1359 if (((TrueTypeTable
*) listCurrent(tt
->tables
))->tag
== tag
) {
1360 return (TrueTypeTable
*)listCurrent(tt
->tables
);
1362 } while (listNext(tt
->tables
));
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' ***
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
1382 static void ProcessTables(TrueTypeCreator
*tt
)
1384 TrueTypeTable
*glyf
, *loca
, *head
, *maxp
, *hhea
;
1386 sal_uInt32 nGlyphs
, locaLen
= 0, glyfLen
= 0;
1387 sal_Int16 xMin
= 0, yMin
= 0, xMax
= 0, yMax
= 0;
1389 sal_Int16 indexToLocFormat
;
1390 sal_uInt8
*hmtxPtr
, *hheaPtr
;
1391 sal_uInt32 hmtxSize
;
1393 sal_uInt16 maxPoints
= 0, maxContours
= 0, maxCompositePoints
= 0, maxCompositeContours
= 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
);
1410 GlyphData
*gd
= (GlyphData
*) listCurrent(glyphlist
);
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
));
1454 listToFirst(glyphlist
);
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;
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
) {
1473 /* printf("X: %d -> %d.\n", index, j); */
1475 PutUInt16((sal_uInt16
) j
, ptr
, 2, 1);
1479 if (flags
& ARG_1_AND_2_ARE_WORDS
) {
1485 if (flags
& WE_HAVE_A_SCALE
) {
1487 } else if (flags
& WE_HAVE_AN_X_AND_Y_SCALE
) {
1489 } else if (flags
& WE_HAVE_A_TWO_BY_TWO
) {
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);
1502 PutUInt16((sal_uInt16
)((p1
- glyfPtr
) >> 1), p2
, 0, 1);
1507 /* fill the array of metrics */
1508 met
[i
].adv
= gd
->aw
;
1509 met
[i
].sb
= gd
->lsb
;
1511 } while (listNext(glyphlist
));
1515 if (indexToLocFormat
== 1) {
1516 PutUInt32(p1
- glyfPtr
, p2
, 0, 1);
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
;
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);
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 */
1560 * Generate an htmx table and update hhea table
1562 hhea
= FindTable(tt
, T_hhea
); assert(hhea
!= 0);
1563 hheaPtr
= (sal_uInt8
*) hhea
->data
;
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
);
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);
1580 PutUInt16(met
[i
].sb
, p1
, 0, 1);
1585 AddTable(tt
, TrueTypeTableNew(T_hmtx
, hmtxSize
, hmtxPtr
));
1586 PutUInt16((sal_uInt16
)(nGlyphs
- nlsb
), hheaPtr
, 34, 1);
1596 * TrueTypeCreator destructor. It calls destructors for all TrueTypeTables added to it.
1598 void TrueTypeCreatorDispose(vcl::TrueTypeCreator
*_this
)
1600 listDispose(_this
->tables
);
1606 * Destructor for the TrueTypeTable object.
1608 void TrueTypeTableDispose(vcl::TrueTypeTable
*_this
)
1610 /* XXX do a binary search */
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
);
1623 assert(!"Unknown TrueType table.\n");
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
));
1661 StreamToFile(ttcr
, "ttcrout.ttf");
1663 TrueTypeCreatorDispose(ttcr
);