LibreOffice Module vcl (master) 1
ttcr.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20/*
21 * TrueTypeCreator method implementation
22 */
23
24#include <iomanip>
25#include <assert.h>
26
27#include <sal/log.hxx>
28
29#include "ttcr.hxx"
30#include <string.h>
31
32namespace vcl
33{
34
35/*
36 * Private Data Types
37 */
38
39namespace {
40
41struct TableEntry {
42 sal_uInt32 tag;
43 sal_uInt32 length;
44 sal_uInt8 *data;
45};
46
47}
48
49/*- Data access macros for data stored in big-endian or little-endian format */
50static sal_Int16 GetInt16( const sal_uInt8* ptr, sal_uInt32 offset)
51{
52 assert(ptr != nullptr);
53 sal_Int16 t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
54 return t;
55}
56
57static sal_uInt16 GetUInt16( const sal_uInt8* ptr, sal_uInt32 offset)
58{
59 assert(ptr != nullptr);
60 sal_uInt16 t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
61 return t;
62}
63
64static void PutInt16(sal_Int16 val, sal_uInt8 *ptr, sal_uInt32 offset)
65{
66 assert(ptr != nullptr);
67
68 ptr[offset] = static_cast<sal_uInt8>((val >> 8) & 0xFF);
69 ptr[offset+1] = static_cast<sal_uInt8>(val & 0xFF);
70}
71
72static void PutUInt16(sal_uInt16 val, sal_uInt8 *ptr, sal_uInt32 offset)
73{
74 assert(ptr != nullptr);
75
76 ptr[offset] = static_cast<sal_uInt8>((val >> 8) & 0xFF);
77 ptr[offset+1] = static_cast<sal_uInt8>(val & 0xFF);
78}
79
80static void PutUInt32(sal_uInt32 val, sal_uInt8 *ptr, sal_uInt32 offset)
81{
82 assert(ptr != nullptr);
83
84 ptr[offset] = static_cast<sal_uInt8>((val >> 24) & 0xFF);
85 ptr[offset+1] = static_cast<sal_uInt8>((val >> 16) & 0xFF);
86 ptr[offset+2] = static_cast<sal_uInt8>((val >> 8) & 0xFF);
87 ptr[offset+3] = static_cast<sal_uInt8>(val & 0xFF);
88}
89
90static int TableEntryCompareF(const void *l, const void *r)
91{
92 sal_uInt32 const ltag(static_cast<TableEntry const*>(l)->tag);
93 sal_uInt32 const rtag(static_cast<TableEntry const*>(r)->tag);
94 return (ltag == rtag) ? 0 : (ltag < rtag) ? -1 : 1;
95}
96
97static int NameRecordCompareF(const void *l, const void *r)
98{
99 NameRecord const *ll = static_cast<NameRecord const *>(l);
100 NameRecord const *rr = static_cast<NameRecord const *>(r);
101
102 if (ll->platformID != rr->platformID) {
103 return (ll->platformID < rr->platformID) ? -1 : 1;
104 } else if (ll->encodingID != rr->encodingID) {
105 return (ll->encodingID < rr->encodingID) ? -1 : 1;
106 } else if (ll->languageID != rr->languageID) {
107 return (ll->languageID < rr->languageID) ? -1 : 1;
108 } else if (ll->nameID != rr->nameID) {
109 return (ll->nameID < rr->nameID) ? -1 : 1;
110 }
111 return 0;
112}
113
114static sal_uInt32 CheckSum(sal_uInt32 *ptr, sal_uInt32 length)
115{
116 sal_uInt32 sum = 0;
117 sal_uInt32 *endptr = ptr + ((length + 3) & sal_uInt32(~3)) / 4;
118
119 while (ptr < endptr) sum += *ptr++;
120
121 return sum;
122}
123
124static void *smalloc(sal_uInt32 size)
125{
126 void *res = malloc(size);
127 assert(res != nullptr);
128 return res;
129}
130
131static void *scalloc(sal_uInt32 n, sal_uInt32 size)
132{
133 void *res = calloc(n, size);
134 assert(res != nullptr);
135 return res;
136}
137
138/*
139 * Public functions
140 */
141
143{
144 this->tables = listNewEmpty();
146
147 this->tag = _tag;
148}
149
151{
152 if (table != nullptr) {
153 listAppend(this->tables, table);
154 }
155}
156
157void TrueTypeCreator::RemoveTable(sal_uInt32 tableTag)
158{
159 if (!listCount(this->tables))
160 return;
161
162 listToFirst(this->tables);
163 int done = 0;
164 do {
165 if (static_cast<TrueTypeTable *>(listCurrent(this->tables))->tag == tableTag)
166 {
167 listRemove(this->tables);
168 }
169 else
170 {
171 if (listNext(this->tables))
172 {
173 done = 1;
174 }
175 }
176 } while (!done);
177}
178
179SFErrCodes TrueTypeCreator::StreamToMemory(std::vector<sal_uInt8>& rOutBuffer)
180{
181 sal_uInt16 searchRange=1, entrySelector=0, rangeShift;
182 sal_uInt32 s, offset, checkSumAdjustment = 0;
183 sal_uInt32 *p;
184 sal_uInt8 *head = nullptr; /* saved pointer to the head table data for checkSumAdjustment calculation */
185
186 if (listIsEmpty(this->tables)) return SFErrCodes::TtFormat;
187
189
190 /* ProcessTables() adds 'loca' and 'hmtx' */
191
192 sal_uInt16 numTables = listCount(this->tables);
193
194 TableEntry* te = static_cast<TableEntry*>(scalloc(numTables, sizeof(TableEntry)));
195 TableEntry* e = te;
196
197 listToFirst(this->tables);
198 do {
199 GetRawData(static_cast<TrueTypeTable *>(listCurrent(this->tables)), &e->data, &e->length, &e->tag);
200 ++e;
201 } while (listNext(this->tables));
202
203 qsort(te, numTables, sizeof(TableEntry), TableEntryCompareF);
204
205 do {
206 searchRange *= 2;
207 entrySelector++;
208 } while (searchRange <= numTables);
209
210 searchRange *= 8;
211 entrySelector--;
212 rangeShift = numTables * 16 - searchRange;
213
214 s = offset = 12 + 16 * numTables;
215
216 for (int i = 0; i < numTables; ++i) {
217 s += (te[i].length + 3) & sal_uInt32(~3);
218 /* if ((te[i].length & 3) != 0) s += (4 - (te[i].length & 3)) & 3; */
219 }
220
221 rOutBuffer.resize(s);
222 sal_uInt8* ttf = rOutBuffer.data();
223
224 /* Offset Table */
225 PutUInt32(this->tag, ttf, 0);
226 PutUInt16(numTables, ttf, 4);
227 PutUInt16(searchRange, ttf, 6);
228 PutUInt16(entrySelector, ttf, 8);
229 PutUInt16(rangeShift, ttf, 10);
230
231 /* Table Directory */
232 for (int i = 0; i < numTables; ++i) {
233 PutUInt32(te[i].tag, ttf + 12, 16 * i);
234 PutUInt32(CheckSum(reinterpret_cast<sal_uInt32 *>(te[i].data), te[i].length), ttf + 12, 16 * i + 4);
235 PutUInt32(offset, ttf + 12, 16 * i + 8);
236 PutUInt32(te[i].length, ttf + 12, 16 * i + 12);
237
238 if (te[i].tag == T_head) {
239 head = ttf + offset;
240 }
241
242 memcpy(ttf+offset, te[i].data, (te[i].length + 3) & sal_uInt32(~3) );
243 offset += (te[i].length + 3) & sal_uInt32(~3);
244 /* if ((te[i].length & 3) != 0) offset += (4 - (te[i].length & 3)) & 3; */
245 }
246
247 free(te);
248
249 p = reinterpret_cast<sal_uInt32 *>(ttf);
250 for (int i = 0; i < static_cast<int>(s) / 4; ++i) checkSumAdjustment += p[i];
251 PutUInt32(0xB1B0AFBA - checkSumAdjustment, head, 8);
252
253 return SFErrCodes::Ok;
254}
255
257{
258 SFErrCodes r;
259 std::vector<sal_uInt8> aOutBuffer;
260
261 if ((r = StreamToMemory(aOutBuffer)) != SFErrCodes::Ok) return r;
263 if (fname)
264 {
265 FILE* fd = fopen(fname, "wb");
266 if (fd)
267 {
268 if (fwrite(aOutBuffer.data(), 1, aOutBuffer.size(), fd) != aOutBuffer.size()) {
270 } else {
271 r = SFErrCodes::Ok;
272 }
273 fclose(fd);
274 }
275 }
276 return r;
277}
278
279/*
280 * TrueTypeTable private methods
281 */
282
283/* Table data points to
284 * --------------------------------------------
285 * generic tdata_generic struct
286 * 'head' HEAD_Length bytes of memory
287 * 'hhea' HHEA_Length bytes of memory
288 * 'loca' tdata_loca struct
289 * 'maxp' MAXP_Version1Length bytes of memory
290 * 'glyf' list of GlyphData structs (defined in sft.h)
291 * 'name' list of NameRecord structs (defined in sft.h)
292 * 'post' tdata_post struct
293 *
294 */
295
296#define CMAP_SUBTABLE_INIT 10
297#define CMAP_SUBTABLE_INCR 10
298#define CMAP_PAIR_INIT 500
299#define CMAP_PAIR_INCR 500
300
301namespace {
302
303struct CmapSubTable {
304 sal_uInt32 id; /* subtable ID (platform/encoding ID) */
305 sal_uInt32 n; /* number of used translation pairs */
306 sal_uInt32 m; /* number of allocated translation pairs */
307 sal_uInt32 *xc; /* character array */
308 sal_uInt32 *xg; /* glyph array */
309};
310
311struct table_cmap {
312 sal_uInt32 n; /* number of used CMAP sub-tables */
313 sal_uInt32 m; /* number of allocated CMAP sub-tables */
314 CmapSubTable *s; /* sorted array of sub-tables */
315};
316
317struct tdata_generic {
318 sal_uInt32 tag;
319 sal_uInt32 nbytes;
320 sal_uInt8 *ptr;
321};
322
323struct tdata_loca {
324 sal_uInt32 nbytes; /* number of bytes in loca table */
325 sal_uInt8 *ptr; /* pointer to the data */
326};
327
328struct tdata_post {
329 sal_uInt32 format;
330 sal_uInt32 italicAngle;
331 sal_Int16 underlinePosition;
332 sal_Int16 underlineThickness;
333 sal_uInt32 isFixedPitch;
334 void *ptr; /* format-specific pointer */
335};
336
337}
338
339/* allocate memory for a TT table */
340static sal_uInt8 *ttmalloc(sal_uInt32 nbytes)
341{
342 sal_uInt32 n;
343
344 n = (nbytes + 3) & sal_uInt32(~3);
345 sal_uInt8* res = static_cast<sal_uInt8*>(calloc(n, 1));
346 assert(res != nullptr);
347
348 return res;
349}
350
351static void FreeGlyphData(void *ptr)
352{
353 GlyphData *p = static_cast<GlyphData *>(ptr);
354 if (p->ptr) free(p->ptr);
355 free(p);
356}
357
359{
360 if (_this) {
361 if (_this->data) {
362 tdata_generic *pdata = static_cast<tdata_generic *>(_this->data);
363 if (pdata->nbytes) free(pdata->ptr);
364 free(_this->data);
365 }
366 free(_this);
367 }
368}
369
371{
372 if (_this) {
373 if (_this->data) free(_this->data);
374 free(_this);
375 }
376}
377
379{
380 if (_this) {
381 if (_this->data) free(_this->data);
382 free(_this);
383 }
384}
385
387{
388 if (_this) {
389 if (_this->data) {
390 tdata_loca *p = static_cast<tdata_loca *>(_this->data);
391 if (p->ptr) free(p->ptr);
392 free(_this->data);
393 }
394 free(_this);
395 }
396}
397
399{
400 if (_this) {
401 if (_this->data) free(_this->data);
402 free(_this);
403 }
404}
405
407{
408 if (_this) {
409 if (_this->data) listDispose(static_cast<list>(_this->data));
410 free(_this);
411 }
412}
413
415{
416 if (!_this) return;
417
418 table_cmap *t = static_cast<table_cmap *>(_this->data);
419 if (t) {
420 CmapSubTable *s = t->s;
421 if (s) {
422 for (sal_uInt32 i = 0; i < t->m; i++) {
423 if (s[i].xc) free(s[i].xc);
424 if (s[i].xg) free(s[i].xg);
425 }
426 free(s);
427 }
428 free(t);
429 }
430 free(_this);
431}
432
434{
435 if (_this) {
436 if (_this->data) listDispose(static_cast<list>(_this->data));
437 free(_this);
438 }
439}
440
442{
443 if (!_this) return;
444
445 tdata_post *p = static_cast<tdata_post *>(_this->data);
446 if (p) {
447 if (p->format == 0x00030000) {
448 /* do nothing */
449 } else {
450 SAL_WARN("vcl.fonts", "Unsupported format of a 'post' table: "
451 << std::setfill('0')
452 << std::setw(8)
453 << std::hex
454 << std::uppercase
455 << static_cast<int>(p->format) << ".");
456 }
457 free(p);
458 }
459 free(_this);
460}
461
462/* destructor vtable */
463
464struct {
465 sal_uInt32 tag;
466 void (*f)(TrueTypeTable *);
467} const vtable1[] =
468{
478
480
481static int GetRawData_generic(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
482{
483 assert(_this != nullptr);
484 assert(_this->data != nullptr);
485
486 *ptr = static_cast<tdata_generic *>(_this->data)->ptr;
487 *len = static_cast<tdata_generic *>(_this->data)->nbytes;
488 *tag = static_cast<tdata_generic *>(_this->data)->tag;
489
490 return TTCR_OK;
491}
492
493static int GetRawData_head(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
494{
495 *len = HEAD_Length;
496 *ptr = static_cast<sal_uInt8 *>(_this->data);
497 *tag = T_head;
498
499 return TTCR_OK;
500}
501
502static int GetRawData_hhea(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
503{
504 *len = HHEA_Length;
505 *ptr = static_cast<sal_uInt8 *>(_this->data);
506 *tag = T_hhea;
507
508 return TTCR_OK;
509}
510
511static int GetRawData_loca(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
512{
513 tdata_loca *p;
514
515 assert(_this->data != nullptr);
516
517 p = static_cast<tdata_loca *>(_this->data);
518
519 if (p->nbytes == 0) return TTCR_ZEROGLYPHS;
520
521 *ptr = p->ptr;
522 *len = p->nbytes;
523 *tag = T_loca;
524
525 return TTCR_OK;
526}
527
528static int GetRawData_maxp(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
529{
530 *len = MAXP_Version1Length;
531 *ptr = static_cast<sal_uInt8 *>(_this->data);
532 *tag = T_maxp;
533
534 return TTCR_OK;
535}
536
537static int GetRawData_glyf(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
538{
539 sal_uInt32 n, nbytes = 0;
540 list l = static_cast<list>(_this->data);
541 /* sal_uInt16 curID = 0; */ /* to check if glyph IDs are sequential and start from zero */
542 sal_uInt8 *p;
543
544 *ptr = nullptr;
545 *len = 0;
546 *tag = 0;
547
548 if (listCount(l) == 0) return TTCR_ZEROGLYPHS;
549
550 listToFirst(l);
551 do {
552 /* if (((GlyphData *) listCurrent(l))->glyphID != curID++) return TTCR_GLYPHSEQ; */
553 nbytes += static_cast<GlyphData *>(listCurrent(l))->nbytes;
554 } while (listNext(l));
555
556 p = _this->rawdata = ttmalloc(nbytes);
557
558 listToFirst(l);
559 do {
560 n = static_cast<GlyphData *>(listCurrent(l))->nbytes;
561 if (n != 0) {
562 memcpy(p, static_cast<GlyphData *>(listCurrent(l))->ptr, n);
563 p += n;
564 }
565 } while (listNext(l));
566
567 *len = nbytes;
568 *ptr = _this->rawdata;
569 *tag = T_glyf;
570
571 return TTCR_OK;
572}
573
574/* cmap packers */
575static sal_uInt8 *PackCmapType0(CmapSubTable const *s, sal_uInt32 *length)
576{
577 sal_uInt8* ptr = static_cast<sal_uInt8*>(smalloc(262));
578 sal_uInt8 *p = ptr + 6;
579 sal_uInt32 i, j;
580 sal_uInt16 g;
581
582 PutUInt16(0, ptr, 0);
583 PutUInt16(262, ptr, 2);
584 PutUInt16(0, ptr, 4);
585
586 for (i = 0; i < 256; i++) {
587 g = 0;
588 for (j = 0; j < s->n; j++) {
589 if (s->xc[j] == i) {
590 g = static_cast<sal_uInt16>(s->xg[j]);
591 }
592 }
593 p[i] = static_cast<sal_uInt8>(g);
594 }
595 *length = 262;
596 return ptr;
597}
598
599static sal_uInt8 *PackCmapType6(CmapSubTable const *s, sal_uInt32 *length)
600{
601 sal_uInt8* ptr = static_cast<sal_uInt8*>(smalloc(s->n*2 + 10));
602 sal_uInt8 *p = ptr + 10;
603 sal_uInt32 i, j;
604 sal_uInt16 g;
605
606 PutUInt16(6, ptr, 0);
607 PutUInt16(static_cast<sal_uInt16>(s->n*2+10), ptr, 2);
608 PutUInt16(0, ptr, 4);
609 PutUInt16(0, ptr, 6);
610 PutUInt16(static_cast<sal_uInt16>(s->n), ptr, 8 );
611
612 for (i = 0; i < s->n; i++) {
613 g = 0;
614 for (j = 0; j < s->n; j++) {
615 if (s->xc[j] == i) {
616 g = static_cast<sal_uInt16>(s->xg[j]);
617 }
618 }
619 PutUInt16( g, p, 2*i );
620 }
621 *length = s->n*2+10;
622 return ptr;
623}
624
625/* XXX it only handles Format 0 encoding tables */
626static sal_uInt8 *PackCmap(CmapSubTable const *s, sal_uInt32 *length)
627{
628 if( s->xg[s->n-1] > 0xff )
629 return PackCmapType6(s, length);
630 else
631 return PackCmapType0(s, length);
632}
633
634static int GetRawData_cmap(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
635{
636 table_cmap *t;
637 sal_uInt32 i;
638 sal_uInt32 tlen = 0;
639 sal_uInt32 l;
640 sal_uInt32 cmapsize;
641 sal_uInt8 *cmap;
642 sal_uInt32 coffset;
643
644 assert(_this != nullptr);
645 t = static_cast<table_cmap *>(_this->data);
646 assert(t != nullptr);
647 assert(t->n != 0);
648
649 sal_uInt8** subtables = static_cast<sal_uInt8**>(scalloc(t->n, sizeof(sal_uInt8 *)));
650 sal_uInt32* sizes = static_cast<sal_uInt32*>(scalloc(t->n, sizeof(sal_uInt32)));
651
652 for (i = 0; i < t->n; i++) {
653 subtables[i] = PackCmap(t->s+i, &l);
654 sizes[i] = l;
655 tlen += l;
656 }
657
658 cmapsize = tlen + 4 + 8 * t->n;
659 _this->rawdata = cmap = ttmalloc(cmapsize);
660
661 PutUInt16(0, cmap, 0);
662 PutUInt16(static_cast<sal_uInt16>(t->n), cmap, 2);
663 coffset = 4 + t->n * 8;
664
665 for (i = 0; i < t->n; i++) {
666 PutUInt16(static_cast<sal_uInt16>(t->s[i].id >> 16), cmap + 4, i * 8);
667 PutUInt16(static_cast<sal_uInt16>(t->s[i].id & 0xFF), cmap + 4, 2 + i * 8);
668 PutUInt32(coffset, cmap + 4, 4 + i * 8);
669 memcpy(cmap + coffset, subtables[i], sizes[i]);
670 free(subtables[i]);
671 coffset += sizes[i];
672 }
673
674 free(subtables);
675 free(sizes);
676
677 *ptr = cmap;
678 *len = cmapsize;
679 *tag = T_cmap;
680
681 return TTCR_OK;
682}
683
684static int GetRawData_name(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
685{
686 list l;
687 sal_Int16 i=0, n; /* number of Name Records */
688 int stringLen = 0;
689 sal_uInt8 *p1, *p2;
690
691 *ptr = nullptr;
692 *len = 0;
693 *tag = 0;
694
695 assert(_this != nullptr);
696 l = static_cast<list>(_this->data);
697 assert(l != nullptr);
698
699 if ((n = static_cast<sal_Int16>(listCount(l))) == 0) return TTCR_NONAMES;
700
701 NameRecord* nr = static_cast<NameRecord*>(scalloc(n, sizeof(NameRecord)));
702
703 listToFirst(l);
704
705 do {
706 memcpy(nr+i, listCurrent(l), sizeof(NameRecord));
707 stringLen += nr[i].slen;
708 i++;
709 } while (listNext(l));
710
711 if (stringLen > 65535) {
712 free(nr);
713 return TTCR_NAMETOOLONG;
714 }
715
716 qsort(nr, n, sizeof(NameRecord), NameRecordCompareF);
717
718 int nameLen = stringLen + 12 * n + 6;
719 sal_uInt8* name = ttmalloc(nameLen);
720
721 PutUInt16(0, name, 0);
722 PutUInt16(n, name, 2);
723 PutUInt16(static_cast<sal_uInt16>(6 + 12 * n), name, 4);
724
725 p1 = name + 6;
726 p2 = p1 + 12 * n;
727
728 for (i = 0; i < n; i++) {
729 PutUInt16(nr[i].platformID, p1, 0);
730 PutUInt16(nr[i].encodingID, p1, 2);
731 PutUInt16(static_cast<sal_uInt16>(nr[i].languageID), p1, 4);
732 PutUInt16(nr[i].nameID, p1, 6);
733 PutUInt16(nr[i].slen, p1, 8);
734 PutUInt16(static_cast<sal_uInt16>(p2 - (name + 6 + 12 * n)), p1, 10);
735 if (nr[i].slen) {
736 memcpy(p2, nr[i].sptr, nr[i].slen);
737 }
738 /* {int j; for(j=0; j<nr[i].slen; j++) printf("%c", nr[i].sptr[j]); printf("\n"); }; */
739 p2 += nr[i].slen;
740 p1 += 12;
741 }
742
743 free(nr);
744 _this->rawdata = name;
745
746 *ptr = name;
747 *len = static_cast<sal_uInt16>(nameLen);
748 *tag = T_name;
749
750 /*{int j; for(j=0; j<nameLen; j++) printf("%c", name[j]); }; */
751
752 return TTCR_OK;
753}
754
755static int GetRawData_post(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
756{
757 tdata_post *p = static_cast<tdata_post *>(_this->data);
758 sal_uInt8 *post = nullptr;
759 sal_uInt32 postLen = 0;
760 int ret;
761
762 if (_this->rawdata) free(_this->rawdata);
763
764 if (p->format == 0x00030000) {
765 postLen = 32;
766 post = ttmalloc(postLen);
767 PutUInt32(0x00030000, post, 0);
768 PutUInt32(p->italicAngle, post, 4);
769 PutUInt16(p->underlinePosition, post, 8);
770 PutUInt16(p->underlineThickness, post, 10);
771 PutUInt16(static_cast<sal_uInt16>(p->isFixedPitch), post, 12);
772 ret = TTCR_OK;
773 } else {
774 SAL_WARN("vcl.fonts", "Unrecognized format of a post table: "
775 << std::setfill('0')
776 << std::setw(8)
777 << std::hex
778 << std::uppercase
779 << static_cast<int>(p->format) << ".");
780 ret = TTCR_POSTFORMAT;
781 }
782
783 *ptr = _this->rawdata = post;
784 *len = postLen;
785 *tag = T_post;
786
787 return ret;
788}
789
790struct {
791 sal_uInt32 tag;
792 int (*f)(TrueTypeTable *, sal_uInt8 **, sal_uInt32 *, sal_uInt32 *);
793} const vtable2[] =
794{
804
806
807/*
808 * TrueTypeTable public methods
809 */
810
811/* Note: Type42 fonts only need these tables:
812 * head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm
813 *
814 * Microsoft required tables
815 * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post, OS/2
816 *
817 * Apple required tables
818 * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post
819 *
820 */
821
823 sal_uInt32 nbytes,
824 const sal_uInt8* ptr)
825{
826 TrueTypeTable* table = static_cast<TrueTypeTable*>(smalloc(sizeof(TrueTypeTable)));
827 tdata_generic* pdata = static_cast<tdata_generic*>(smalloc(sizeof(tdata_generic)));
828 pdata->nbytes = nbytes;
829 pdata->tag = tag;
830 if (nbytes) {
831 pdata->ptr = ttmalloc(nbytes);
832 memcpy(pdata->ptr, ptr, nbytes);
833 } else {
834 pdata->ptr = nullptr;
835 }
836
837 table->tag = 0;
838 table->data = pdata;
839 table->rawdata = nullptr;
840
841 return table;
842}
843
844TrueTypeTable *TrueTypeTableNew_head(sal_uInt32 fontRevision,
845 sal_uInt16 flags,
846 sal_uInt16 unitsPerEm,
847 const sal_uInt8* created,
848 sal_uInt16 macStyle,
849 sal_uInt16 lowestRecPPEM,
850 sal_Int16 fontDirectionHint)
851{
852 assert(created != nullptr);
853
854 TrueTypeTable* table = static_cast<TrueTypeTable*>(smalloc(sizeof(TrueTypeTable)));
856
857 PutUInt32(0x00010000, ptr, 0); /* version */
858 PutUInt32(fontRevision, ptr, 4);
859 PutUInt32(0x5F0F3CF5, ptr, 12); /* magic number */
860 PutUInt16(flags, ptr, 16);
861 PutUInt16(unitsPerEm, ptr, 18);
862 memcpy(ptr+20, created, 8); /* Created Long Date */
863 memset(ptr+28, 0, 8); /* Modified Long Date */
864 PutUInt16(macStyle, ptr, 44);
865 PutUInt16(lowestRecPPEM, ptr, 46);
866 PutUInt16(fontDirectionHint, ptr, 48);
867 PutUInt16(0, ptr, 52); /* glyph data format: 0 */
868
869 table->data = static_cast<void *>(ptr);
870 table->tag = T_head;
871 table->rawdata = nullptr;
872
873 return table;
874}
875
877 sal_Int16 descender,
878 sal_Int16 linegap,
879 sal_Int16 caretSlopeRise,
880 sal_Int16 caretSlopeRun)
881{
882 TrueTypeTable* table = static_cast<TrueTypeTable*>(smalloc(sizeof(TrueTypeTable)));
884
885 PutUInt32(0x00010000, ptr, 0); /* version */
886 PutUInt16(ascender, ptr, 4);
887 PutUInt16(descender, ptr, 6);
888 PutUInt16(linegap, ptr, 8);
889 PutUInt16(caretSlopeRise, ptr, 18);
890 PutUInt16(caretSlopeRun, ptr, 20);
891 PutUInt16(0, ptr, 22); /* reserved 1 */
892 PutUInt16(0, ptr, 24); /* reserved 2 */
893 PutUInt16(0, ptr, 26); /* reserved 3 */
894 PutUInt16(0, ptr, 28); /* reserved 4 */
895 PutUInt16(0, ptr, 30); /* reserved 5 */
896 PutUInt16(0, ptr, 32); /* metricDataFormat */
897
898 table->data = static_cast<void *>(ptr);
899 table->tag = T_hhea;
900 table->rawdata = nullptr;
901
902 return table;
903}
904
906{
907 TrueTypeTable* table = static_cast<TrueTypeTable*>(smalloc(sizeof(TrueTypeTable)));
908 table->data = smalloc(sizeof(tdata_loca));
909
910 static_cast<tdata_loca *>(table->data)->nbytes = 0;
911 static_cast<tdata_loca *>(table->data)->ptr = nullptr;
912
913 table->tag = T_loca;
914 table->rawdata = nullptr;
915
916 return table;
917}
918
920{
921 TrueTypeTable* table = static_cast<TrueTypeTable*>(smalloc(sizeof(TrueTypeTable)));
923
924 if (maxp && size == MAXP_Version1Length) {
925 memcpy(table->data, maxp, MAXP_Version1Length);
926 }
927
928 table->tag = T_maxp;
929 table->rawdata = nullptr;
930
931 return table;
932}
933
935{
936 TrueTypeTable* table = static_cast<TrueTypeTable*>(smalloc(sizeof(TrueTypeTable)));
937 list l = listNewEmpty();
938
939 assert(l != nullptr);
940
942
943 table->data = l;
944 table->rawdata = nullptr;
945 table->tag = T_glyf;
946
947 return table;
948}
949
951{
952 TrueTypeTable* table = static_cast<TrueTypeTable*>(smalloc(sizeof(TrueTypeTable)));
953 table_cmap* cmap = static_cast<table_cmap*>(smalloc(sizeof(table_cmap)));
954
955 cmap->n = 0;
956 cmap->m = CMAP_SUBTABLE_INIT;
957 cmap->s = static_cast<CmapSubTable *>(scalloc(CMAP_SUBTABLE_INIT, sizeof(CmapSubTable)));
958
959 table->data = cmap;
960
961 table->rawdata = nullptr;
962 table->tag = T_cmap;
963
964 return table;
965}
966
967static void DisposeNameRecord(void *ptr)
968{
969 if (ptr != nullptr) {
970 NameRecord *nr = static_cast<NameRecord *>(ptr);
971 if (nr->sptr) free(nr->sptr);
972 free(ptr);
973 }
974}
975
977{
978 NameRecord* p = static_cast<NameRecord*>(smalloc(sizeof(NameRecord)));
979
980 memcpy(p, nr, sizeof(NameRecord));
981
982 if (p->slen) {
983 p->sptr = static_cast<sal_uInt8*>(smalloc(p->slen));
984 memcpy(p->sptr, nr->sptr, p->slen);
985 }
986
987 return p;
988}
989
991{
992 TrueTypeTable* table = static_cast<TrueTypeTable*>(smalloc(sizeof(TrueTypeTable)));
993 list l = listNewEmpty();
994
995 assert(l != nullptr);
996
998
999 if (n != 0) {
1000 int i;
1001 for (i = 0; i < n; i++) {
1003 }
1004 }
1005
1006 table->data = l;
1007 table->rawdata = nullptr;
1008 table->tag = T_name;
1009
1010 return table;
1011}
1012
1014 sal_Int32 italicAngle,
1015 sal_Int16 underlinePosition,
1016 sal_Int16 underlineThickness,
1017 sal_uInt32 isFixedPitch)
1018{
1019 assert(format == 0x00030000); /* Only format 3.0 is supported at this time */
1020 TrueTypeTable* table = static_cast<TrueTypeTable*>(smalloc(sizeof(TrueTypeTable)));
1021 tdata_post* post = static_cast<tdata_post*>(smalloc(sizeof(tdata_post)));
1022
1023 post->format = format;
1024 post->italicAngle = italicAngle;
1025 post->underlinePosition = underlinePosition;
1026 post->underlineThickness = underlineThickness;
1027 post->isFixedPitch = isFixedPitch;
1028 post->ptr = nullptr;
1029
1030 table->data = post;
1031 table->rawdata = nullptr;
1032 table->tag = T_post;
1033
1034 return table;
1035}
1036
1037int GetRawData(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
1038{
1039 /* XXX do a binary search */
1040 assert(_this != nullptr);
1041 assert(ptr != nullptr);
1042 assert(len != nullptr);
1043 assert(tag != nullptr);
1044
1045 *ptr = nullptr; *len = 0; *tag = 0;
1046
1047 if (_this->rawdata) {
1048 free(_this->rawdata);
1049 _this->rawdata = nullptr;
1050 }
1051
1052 for(size_t i=0; i < SAL_N_ELEMENTS(vtable2); i++) {
1053 if (_this->tag == vtable2[i].tag) {
1054 return vtable2[i].f(_this, ptr, len, tag);
1055 }
1056 }
1057
1058 assert(!"Unknown TrueType table.");
1059 return TTCR_UNKNOWN;
1060}
1061
1062void cmapAdd(TrueTypeTable *table, sal_uInt32 id, sal_uInt32 c, sal_uInt32 g)
1063{
1064 sal_uInt32 i, found;
1065 table_cmap *t;
1066 CmapSubTable *s;
1067
1068 assert(table != nullptr);
1069 assert(table->tag == T_cmap);
1070 t = static_cast<table_cmap *>(table->data); assert(t != nullptr);
1071 s = t->s; assert(s != nullptr);
1072
1073 found = 0;
1074
1075 for (i = 0; i < t->n; i++) {
1076 if (s[i].id == id) {
1077 found = 1;
1078 break;
1079 }
1080 }
1081
1082 if (!found) {
1083 if (t->n == t->m) {
1084 CmapSubTable* tmp = static_cast<CmapSubTable*>(scalloc(t->m + CMAP_SUBTABLE_INCR, sizeof(CmapSubTable)));
1085 memcpy(tmp, s, sizeof(CmapSubTable) * t->m);
1086 t->m += CMAP_SUBTABLE_INCR;
1087 free(s);
1088 s = tmp;
1089 t->s = s;
1090 }
1091
1092 for (i = 0; i < t->n; i++) {
1093 if (s[i].id > id) break;
1094 }
1095
1096 if (i < t->n) {
1097 memmove(s+i+1, s+i, t->n-i);
1098 }
1099
1100 t->n++;
1101
1102 s[i].id = id;
1103 s[i].n = 0;
1104 s[i].m = CMAP_PAIR_INIT;
1105 s[i].xc = static_cast<sal_uInt32*>(scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32)));
1106 s[i].xg = static_cast<sal_uInt32*>(scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32)));
1107 }
1108
1109 if (s[i].n == s[i].m) {
1110 sal_uInt32* tmp1 = static_cast<sal_uInt32*>(scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32)));
1111 sal_uInt32* tmp2 = static_cast<sal_uInt32*>(scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32)));
1112 assert(tmp1 != nullptr);
1113 assert(tmp2 != nullptr);
1114 memcpy(tmp1, s[i].xc, sizeof(sal_uInt32) * s[i].m);
1115 memcpy(tmp2, s[i].xg, sizeof(sal_uInt32) * s[i].m);
1116 s[i].m += CMAP_PAIR_INCR;
1117 free(s[i].xc);
1118 free(s[i].xg);
1119 s[i].xc = tmp1;
1120 s[i].xg = tmp2;
1121 }
1122
1123 s[i].xc[s[i].n] = c;
1124 s[i].xg[s[i].n] = g;
1125 s[i].n++;
1126}
1127
1128sal_uInt32 glyfAdd(TrueTypeTable *table, GlyphData *glyphdata, AbstractTrueTypeFont *fnt)
1129{
1130 list l;
1131 sal_uInt32 currentID;
1132 int ret, n, ncomponents;
1133
1134 assert(table != nullptr);
1135 assert(table->tag == T_glyf);
1136
1137 if (!glyphdata) return sal_uInt32(~0);
1138
1139 std::vector< sal_uInt32 > glyphlist;
1140
1141 ncomponents = GetTTGlyphComponents(fnt, glyphdata->glyphID, glyphlist);
1142
1143 l = static_cast<list>(table->data);
1144 if (listCount(l) > 0) {
1145 listToLast(l);
1146 ret = n = static_cast<GlyphData *>(listCurrent(l))->newID + 1;
1147 } else {
1148 ret = n = 0;
1149 }
1150 glyphdata->newID = n++;
1151 listAppend(l, glyphdata);
1152
1153 if (ncomponents > 1 && glyphlist.size() > 1 )
1154 {
1155 std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin();
1156 ++it;
1157 /* glyphData->glyphID is always the first glyph on the list */
1158 do
1159 {
1160 int found = 0;
1161 currentID = *it;
1162 /* XXX expensive! should be rewritten with sorted arrays! */
1163 listToFirst(l);
1164 do {
1165 if (static_cast<GlyphData *>(listCurrent(l))->glyphID == currentID) {
1166 found = 1;
1167 break;
1168 }
1169 } while (listNext(l));
1170
1171 if (!found) {
1172 GlyphData *gd = GetTTRawGlyphData(fnt, currentID);
1173 gd->newID = n++;
1174 listAppend(l, gd);
1175 }
1176 } while( ++it != glyphlist.end() );
1177 }
1178
1179 return ret;
1180}
1181
1182sal_uInt32 glyfCount(const TrueTypeTable *table)
1183{
1184 assert(table != nullptr);
1185 assert(table->tag == T_glyf);
1186 return listCount(static_cast<list>(table->data));
1187}
1188
1190{
1191 if (listIsEmpty(this->tables)) return nullptr;
1192
1193 listToFirst(this->tables);
1194
1195 do {
1196 if (static_cast<TrueTypeTable *>(listCurrent(this->tables))->tag == tableTag) {
1197 return static_cast<TrueTypeTable*>(listCurrent(this->tables));
1198 }
1199 } while (listNext(this->tables));
1200
1201 return nullptr;
1202}
1203
1204/* This function processes all the tables and synchronizes them before creating
1205 * the output TrueType stream.
1206 *
1207 * *** It adds two TrueType tables to the font: 'loca' and 'hmtx' ***
1208 *
1209 * It does:
1210 *
1211 * - Re-numbers glyph IDs and creates 'glyf', 'loca', and 'hmtx' tables.
1212 * - Calculates xMin, yMin, xMax, and yMax and stores values in 'head' table.
1213 * - Stores indexToLocFormat in 'head'
1214 * - updates 'maxp' table
1215 * - Calculates advanceWidthMax, minLSB, minRSB, xMaxExtent and numberOfHMetrics
1216 * in 'hhea' table
1217 *
1218 */
1220{
1221 TrueTypeTable *glyf, *loca, *head, *maxp, *hhea;
1222 list glyphlist;
1223 sal_uInt32 nGlyphs, locaLen = 0, glyfLen = 0;
1224 sal_Int16 xMin = 0, yMin = 0, xMax = 0, yMax = 0;
1225 sal_uInt32 i = 0;
1226 sal_Int16 indexToLocFormat;
1227 sal_uInt8 *hmtxPtr, *hheaPtr;
1228 sal_uInt32 hmtxSize;
1229 sal_uInt8 *p1, *p2;
1230 sal_uInt16 maxPoints = 0, maxContours = 0, maxCompositePoints = 0, maxCompositeContours = 0;
1231 int nlsb = 0;
1232 sal_uInt32 *gid; /* array of old glyphIDs */
1233
1234 glyf = FindTable(T_glyf);
1235 glyphlist = static_cast<list>(glyf->data);
1236 nGlyphs = listCount(glyphlist);
1237 if (!nGlyphs)
1238 {
1239 SAL_WARN("vcl.fonts", "no glyphs found in ProcessTables");
1240 return;
1241 }
1242 gid = static_cast<sal_uInt32*>(scalloc(nGlyphs, sizeof(sal_uInt32)));
1243
1246
1247 /* XXX Need to make sure that composite glyphs do not break during glyph renumbering */
1248
1249 listToFirst(glyphlist);
1250 do {
1251 GlyphData *gd = static_cast<GlyphData *>(listCurrent(glyphlist));
1252 glyfLen += gd->nbytes;
1253 /* XXX if (gd->nbytes & 1) glyfLen++; */
1254
1255 assert(gd->newID == i);
1256 gid[i++] = gd->glyphID;
1257 /* gd->glyphID = i++; */
1258
1259 /* printf("IDs: %d %d.\n", gd->glyphID, gd->newID); */
1260
1261 if (gd->nbytes >= 10) {
1262 sal_Int16 z = GetInt16(gd->ptr, 2);
1263 if (z < xMin) xMin = z;
1264
1265 z = GetInt16(gd->ptr, 4);
1266 if (z < yMin) yMin = z;
1267
1268 z = GetInt16(gd->ptr, 6);
1269 if (z > xMax) xMax = z;
1270
1271 z = GetInt16(gd->ptr, 8);
1272 if (z > yMax) yMax = z;
1273 }
1274
1275 if (!gd->compflag) { /* non-composite glyph */
1276 if (gd->npoints > maxPoints) maxPoints = gd->npoints;
1277 if (gd->ncontours > maxContours) maxContours = gd->ncontours;
1278 } else { /* composite glyph */
1279 if (gd->npoints > maxCompositePoints) maxCompositePoints = gd->npoints;
1280 if (gd->ncontours > maxCompositeContours) maxCompositeContours = gd->ncontours;
1281 }
1282
1283 } while (listNext(glyphlist));
1284
1285 indexToLocFormat = (glyfLen / 2 > 0xFFFF) ? 1 : 0;
1286 locaLen = indexToLocFormat ? (nGlyphs + 1) << 2 : (nGlyphs + 1) << 1;
1287
1288 sal_uInt8* glyfPtr = ttmalloc(glyfLen);
1289 sal_uInt8* locaPtr = ttmalloc(locaLen);
1290 TTSimpleGlyphMetrics* met = static_cast<TTSimpleGlyphMetrics*>(scalloc(nGlyphs, sizeof(TTSimpleGlyphMetrics)));
1291 i = 0;
1292
1293 listToFirst(glyphlist);
1294 p1 = glyfPtr;
1295 p2 = locaPtr;
1296 do {
1297 GlyphData *gd = static_cast<GlyphData *>(listCurrent(glyphlist));
1298
1299 if (gd->compflag && gd->nbytes > 10) { /* re-number all components */
1300 sal_uInt16 flags, index;
1301 sal_uInt8 *ptr = gd->ptr + 10;
1302 size_t nRemaining = gd->nbytes - 10;
1303 do {
1304 if (nRemaining < 4)
1305 {
1306 SAL_WARN("vcl.fonts", "truncated font");
1307 break;
1308 }
1309 flags = GetUInt16(ptr, 0);
1310 index = GetUInt16(ptr, 2);
1311
1312 /* XXX use the sorted array of old to new glyphID mapping and do a binary search */
1313 sal_uInt32 j;
1314 for (j = 0; j < nGlyphs; j++) {
1315 if (gid[j] == index) {
1316 break;
1317 }
1318 }
1319 /* printf("X: %d -> %d.\n", index, j); */
1320
1321 PutUInt16(static_cast<sal_uInt16>(j), ptr, 2);
1322
1323 ptr += 4;
1324 nRemaining -= 4;
1325
1326 sal_uInt32 nAdvance = 0;
1327 if (flags & ARG_1_AND_2_ARE_WORDS) {
1328 nAdvance += 4;
1329 } else {
1330 nAdvance += 2;
1331 }
1332
1333 if (flags & WE_HAVE_A_SCALE) {
1334 nAdvance += 2;
1335 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
1336 nAdvance += 4;
1337 } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
1338 nAdvance += 8;
1339 }
1340
1341 if (nRemaining < nAdvance)
1342 {
1343 SAL_WARN("vcl.fonts", "truncated font");
1344 break;
1345 }
1346
1347 ptr += nAdvance;
1348 nRemaining -= nAdvance;
1349
1350 } while (flags & MORE_COMPONENTS);
1351 }
1352
1353 if (gd->nbytes != 0) {
1354 memcpy(p1, gd->ptr, gd->nbytes);
1355 }
1356 if (indexToLocFormat == 1) {
1357 PutUInt32(p1 - glyfPtr, p2, 0);
1358 p2 += 4;
1359 } else {
1360 PutUInt16(static_cast<sal_uInt16>((p1 - glyfPtr) >> 1), p2, 0);
1361 p2 += 2;
1362 }
1363 p1 += gd->nbytes;
1364
1365 /* fill the array of metrics */
1366 met[i].adv = gd->aw;
1367 met[i].sb = gd->lsb;
1368 i++;
1369 } while (listNext(glyphlist));
1370
1371 free(gid);
1372
1373 if (indexToLocFormat == 1) {
1374 PutUInt32(p1 - glyfPtr, p2, 0);
1375 } else {
1376 PutUInt16(static_cast<sal_uInt16>((p1 - glyfPtr) >> 1), p2, 0);
1377 }
1378
1379 glyf->rawdata = glyfPtr;
1380
1381 loca = TrueTypeTableNew_loca(); assert(loca != nullptr);
1382 static_cast<tdata_loca *>(loca->data)->ptr = locaPtr;
1383 static_cast<tdata_loca *>(loca->data)->nbytes = locaLen;
1384
1385 AddTable(loca);
1386
1387 head = FindTable(T_head);
1388 sal_uInt8* const pHeadData = static_cast<sal_uInt8*>(head->data);
1389 PutInt16(xMin, pHeadData, HEAD_xMin_offset);
1390 PutInt16(yMin, pHeadData, HEAD_yMin_offset);
1391 PutInt16(xMax, pHeadData, HEAD_xMax_offset);
1392 PutInt16(yMax, pHeadData, HEAD_yMax_offset);
1393 PutInt16(indexToLocFormat, pHeadData, HEAD_indexToLocFormat_offset);
1394
1395 maxp = FindTable(T_maxp);
1396
1397 sal_uInt8* const pMaxpData = static_cast<sal_uInt8*>(maxp->data);
1398 PutUInt16(static_cast<sal_uInt16>(nGlyphs), pMaxpData, MAXP_numGlyphs_offset);
1399 PutUInt16(maxPoints, pMaxpData, MAXP_maxPoints_offset);
1400 PutUInt16(maxContours, pMaxpData, MAXP_maxContours_offset);
1401 PutUInt16(maxCompositePoints, pMaxpData, MAXP_maxCompositePoints_offset);
1402 PutUInt16(maxCompositeContours, pMaxpData, MAXP_maxCompositeContours_offset);
1403
1404 /*
1405 * Generate an htmx table and update hhea table
1406 */
1407 hhea = FindTable(T_hhea); assert(hhea != nullptr);
1408 hheaPtr = static_cast<sal_uInt8 *>(hhea->data);
1409 if (nGlyphs > 2) {
1410 for (i = nGlyphs - 1; i > 0; i--) {
1411 if (met[i].adv != met[i-1].adv) break;
1412 }
1413 nlsb = nGlyphs - 1 - i;
1414 }
1415 hmtxSize = (nGlyphs - nlsb) * 4 + nlsb * 2;
1416 hmtxPtr = ttmalloc(hmtxSize);
1417 p1 = hmtxPtr;
1418
1419 for (i = 0; i < nGlyphs; i++) {
1420 if (i < nGlyphs - nlsb) {
1421 PutUInt16(met[i].adv, p1, 0);
1422 PutUInt16(met[i].sb, p1, 2);
1423 p1 += 4;
1424 } else {
1425 PutUInt16(met[i].sb, p1, 0);
1426 p1 += 2;
1427 }
1428 }
1429
1430 AddTable(TrueTypeTableNew(T_hmtx, hmtxSize, hmtxPtr));
1431 PutUInt16(static_cast<sal_uInt16>(nGlyphs - nlsb), hheaPtr, 34);
1432 free(hmtxPtr);
1433 free(met);
1434}
1435
1440{
1441 listDispose(this->tables);
1442}
1443
1444} // namespace vcl
1445
1446extern "C"
1447{
1451 void TrueTypeTableDispose(void * arg)
1452 {
1453 vcl::TrueTypeTable *_this = static_cast<vcl::TrueTypeTable *>(arg);
1454 /* XXX do a binary search */
1455 assert(_this != nullptr);
1456
1457 if (_this->rawdata) free(_this->rawdata);
1458
1459 for(size_t i=0; i < SAL_N_ELEMENTS(vcl::vtable1); i++) {
1460 if (_this->tag == vcl::vtable1[i].tag) {
1461 vcl::vtable1[i].f(_this);
1462 return;
1463 }
1464 }
1465 assert(!"Unknown TrueType table.");
1466 }
1467}
1468
1469#ifdef TEST_TTCR
1470static sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) {
1471 return (a << 24) | (b << 16) | (c << 8) | d;
1472}
1473
1474int main()
1475{
1476 TrueTypeCreator *ttcr;
1477 sal_uInt8 *t1, *t2, *t3, *t4, *t5, *t6;
1478
1479 TrueTypeCreatorNewEmpty(mkTag('t','r','u','e'), &ttcr);
1480
1481 t1 = malloc(1000); memset(t1, 'a', 1000);
1482 t2 = malloc(2000); memset(t2, 'b', 2000);
1483 t3 = malloc(3000); memset(t3, 'c', 3000);
1484 t4 = malloc(4000); memset(t4, 'd', 4000);
1485 t5 = malloc(5000); memset(t5, 'e', 5000);
1486 t6 = malloc(6000); memset(t6, 'f', 6000);
1487
1488 AddTable(ttcr, TrueTypeTableNew(T_maxp, 1000, t1));
1489 AddTable(ttcr, TrueTypeTableNew(T_OS2, 2000, t2));
1490 AddTable(ttcr, TrueTypeTableNew(T_cmap, 3000, t3));
1491 AddTable(ttcr, TrueTypeTableNew(T_loca, 4000, t4));
1492 AddTable(ttcr, TrueTypeTableNew(T_hhea, 5000, t5));
1493 AddTable(ttcr, TrueTypeTableNew(T_glyf, 6000, t6));
1494
1495 free(t1);
1496 free(t2);
1497 free(t3);
1498 free(t4);
1499 free(t5);
1500 free(t6);
1501
1502 StreamToFile(ttcr, "ttcrout.ttf");
1503
1505 return 0;
1506}
1507#endif
1508
1509/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XPropertyListType t
double d
sal_uInt32 tag
TrueType file tag.
Definition: ttcr.hxx:96
TrueTypeTable * FindTable(sal_uInt32 tag)
Definition: ttcr.cxx:1189
TrueTypeCreator(sal_uInt32 tag)
TrueTypeCreator constructor.
Definition: ttcr.cxx:142
void ProcessTables()
Definition: ttcr.cxx:1219
void RemoveTable(sal_uInt32 tag)
Removes a TrueType table from the TrueType creator if it is stored there.
Definition: ttcr.cxx:157
void AddTable(TrueTypeTable *table)
Adds a TrueType table to the TrueType creator.
Definition: ttcr.cxx:150
list tables
List of table tags and pointers.
Definition: ttcr.hxx:97
~TrueTypeCreator()
TrueTypeCreator destructor.
Definition: ttcr.cxx:1439
SFErrCodes StreamToMemory(std::vector< sal_uInt8 > &rOutBuffer)
Writes a TrueType font generated by the TrueTypeCreator to a segment of memory that this method alloc...
Definition: ttcr.cxx:179
SFErrCodes StreamToFile(const char *fname)
Writes a TrueType font generated by the TrueTypeCreator to a file.
Definition: ttcr.cxx:256
float z
GlyphData * GetTTRawGlyphData(AbstractTrueTypeFont *ttf, sal_uInt32 glyphID)
Extracts raw glyph data from the 'glyf' table and returns it in an allocated GlyphData structure.
Definition: sft.cxx:2347
int GetTTGlyphComponents(AbstractTrueTypeFont *ttf, sal_uInt32 glyphID, std::vector< sal_uInt32 > &glyphlist)
For a specified glyph adds all component glyphs IDs to the list and return their number.
Definition: sft.cxx:1501
const char * name
void * p
sal_Int64 n
void listSetElementDtor(list pThis, list_destructor f)
Definition: list.cxx:108
list listAppend(list pThis, void *el)
Definition: list.cxx:177
int listCount(list pThis)
Definition: list.cxx:122
int listToLast(list pThis)
Definition: list.cxx:166
list listRemove(list pThis)
Definition: list.cxx:185
int listToFirst(list pThis)
Definition: list.cxx:155
void listDispose(list pThis)
Definition: list.cxx:101
void * listCurrent(list pThis)
Definition: list.cxx:115
list listNewEmpty()
Definition: list.cxx:89
int listNext(list pThis)
Definition: list.cxx:134
int listIsEmpty(list pThis)
Definition: list.cxx:128
#define SAL_WARN(area, stream)
#define SAL_N_ELEMENTS(arr)
@ table
size
int i
index
m
static void TrueTypeTableDispose_generic(TrueTypeTable *_this)
Definition: ttcr.cxx:358
static void TrueTypeTableDispose_name(TrueTypeTable *_this)
Definition: ttcr.cxx:433
static void * smalloc(sal_uInt32 size)
Definition: ttcr.cxx:124
static void TrueTypeTableDispose_cmap(TrueTypeTable *_this)
Definition: ttcr.cxx:414
static int GetRawData_head(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
Definition: ttcr.cxx:493
constexpr sal_uInt32 T_post
Definition: sft.hxx:446
static int GetRawData_maxp(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
Definition: ttcr.cxx:528
constexpr sal_uInt32 T_loca
Definition: sft.hxx:438
static void DisposeNameRecord(void *ptr)
Definition: ttcr.cxx:967
static int GetRawData_hhea(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
Definition: ttcr.cxx:502
static void FreeGlyphData(void *ptr)
Definition: ttcr.cxx:351
constexpr int HHEA_Length
Definition: sft.hxx:310
constexpr int HEAD_yMax_offset
Definition: sft.hxx:373
SFErrCodes
Return value of OpenTTFont() and CreateT3FromTTGlyphs()
Definition: sft.hxx:63
@ TtFormat
incorrect TrueType font format
@ FileIo
file I/O error
@ BadFile
file not found
TrueTypeTable * TrueTypeTableNew_head(sal_uInt32 fontRevision, sal_uInt16 flags, sal_uInt16 unitsPerEm, const sal_uInt8 *created, sal_uInt16 macStyle, sal_uInt16 lowestRecPPEM, sal_Int16 fontDirectionHint)
Creates a new 'head' table for a TrueType font.
Definition: ttcr.cxx:844
constexpr int MAXP_maxCompositePoints_offset
Definition: sft.hxx:403
constexpr sal_uInt32 T_glyf
Definition: sft.hxx:436
TrueTypeTable * TrueTypeTableNew_loca()
Creates a new empty 'loca' table for a TrueType font.
Definition: ttcr.cxx:905
static void PutUInt32(sal_uInt32 val, sal_uInt8 *ptr, sal_uInt32 offset)
Definition: ttcr.cxx:80
static int GetRawData_name(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
Definition: ttcr.cxx:684
constexpr int MAXP_Version1Length
Definition: sft.hxx:398
static void PutInt16(sal_Int16 val, sal_uInt8 *ptr, sal_uInt32 offset)
Definition: ttcr.cxx:64
struct vcl::@3 vtable1[]
int GetRawData(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
This function converts the data of a TrueType table to a raw array of bytes.
Definition: ttcr.cxx:1037
static sal_uInt8 * PackCmap(CmapSubTable const *s, sal_uInt32 *length)
Definition: ttcr.cxx:626
static void TrueTypeTableDispose_post(TrueTypeTable *_this)
Definition: ttcr.cxx:441
static int NameRecordCompareF(const void *l, const void *r)
Definition: ttcr.cxx:97
constexpr sal_uInt32 T_hhea
Definition: sft.hxx:440
constexpr int MAXP_maxCompositeContours_offset
Definition: sft.hxx:404
static int TableEntryCompareF(const void *l, const void *r)
Definition: ttcr.cxx:90
static void PutUInt16(sal_uInt16 val, sal_uInt8 *ptr, sal_uInt32 offset)
Definition: ttcr.cxx:72
constexpr int MAXP_maxPoints_offset
Definition: sft.hxx:401
static sal_uInt32 CheckSum(sal_uInt32 *ptr, sal_uInt32 length)
Definition: ttcr.cxx:114
TrueTypeTable * TrueTypeTableNew_hhea(sal_Int16 ascender, sal_Int16 descender, sal_Int16 linegap, sal_Int16 caretSlopeRise, sal_Int16 caretSlopeRun)
Creates a new 'hhea' table for a TrueType font.
Definition: ttcr.cxx:876
TrueTypeTable * TrueTypeTableNew_name(int n, NameRecord const *nr)
Creates a new 'name' table.
Definition: ttcr.cxx:990
static int GetRawData_glyf(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
Definition: ttcr.cxx:537
@ TTCR_OK
no error
Definition: ttcr.hxx:51
@ TTCR_UNKNOWN
Unknown TrueType table
Definition: ttcr.hxx:53
@ TTCR_POSTFORMAT
unsupported format of a 'post' table
Definition: ttcr.hxx:56
@ TTCR_ZEROGLYPHS
At least one glyph should be defined
Definition: ttcr.hxx:52
@ TTCR_NONAMES
'name' table does not contain any names
Definition: ttcr.hxx:54
@ TTCR_NAMETOOLONG
'name' table is too long (string data > 64K)
Definition: ttcr.hxx:55
static sal_uInt8 * ttmalloc(sal_uInt32 nbytes)
Definition: ttcr.cxx:340
void(* f)(TrueTypeTable *)
Definition: ttcr.cxx:466
static sal_uInt8 * PackCmapType0(CmapSubTable const *s, sal_uInt32 *length)
Definition: ttcr.cxx:575
static void TrueTypeTableDispose_hhea(TrueTypeTable *_this)
Definition: ttcr.cxx:378
TrueTypeTable * TrueTypeTableNew(sal_uInt32 tag, sal_uInt32 nbytes, const sal_uInt8 *ptr)
Creates a new raw TrueType table.
Definition: ttcr.cxx:822
constexpr int HEAD_xMax_offset
Definition: sft.hxx:372
static int GetRawData_post(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
Definition: ttcr.cxx:755
TrueTypeTable * TrueTypeTableNew_maxp(const sal_uInt8 *maxp, int size)
Creates a new 'maxp' table based on an existing maxp table.
Definition: ttcr.cxx:919
constexpr sal_uInt32 T_head
Definition: sft.hxx:437
static sal_Int16 GetInt16(const sal_uInt8 *ptr, size_t offset)
Definition: sft.cxx:144
static void TrueTypeTableDispose_loca(TrueTypeTable *_this)
Definition: ttcr.cxx:386
constexpr int HEAD_yMin_offset
Definition: sft.hxx:371
constexpr int MAXP_maxContours_offset
Definition: sft.hxx:402
constexpr int HEAD_xMin_offset
Definition: sft.hxx:370
static void TrueTypeTableDispose_glyf(TrueTypeTable *_this)
Definition: ttcr.cxx:406
constexpr int MAXP_numGlyphs_offset
Definition: sft.hxx:400
sal_uInt32 glyfCount(const TrueTypeTable *table)
Query the number of glyphs currently stored in the 'glyf' table.
Definition: ttcr.cxx:1182
static int GetRawData_cmap(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
Definition: ttcr.cxx:634
struct vcl::@4 vtable2[]
static void TrueTypeTableDispose_maxp(TrueTypeTable *_this)
Definition: ttcr.cxx:398
constexpr sal_uInt32 T_maxp
Definition: sft.hxx:435
TrueTypeTable * TrueTypeTableNew_post(sal_Int32 format, sal_Int32 italicAngle, sal_Int16 underlinePosition, sal_Int16 underlineThickness, sal_uInt32 isFixedPitch)
Creates a new 'post' table of one of the supported formats.
Definition: ttcr.cxx:1013
TrueTypeTable * TrueTypeTableNew_glyf()
Creates a new empty 'glyf' table.
Definition: ttcr.cxx:934
constexpr sal_uInt32 T_OS2
Definition: sft.hxx:445
constexpr int HEAD_indexToLocFormat_offset
Definition: sft.hxx:377
constexpr sal_uInt32 T_hmtx
Definition: sft.hxx:441
constexpr sal_uInt32 T_name
Definition: sft.hxx:439
sal_uInt32 tag
Definition: ttcr.cxx:465
static sal_uInt8 * PackCmapType6(CmapSubTable const *s, sal_uInt32 *length)
Definition: ttcr.cxx:599
static sal_uInt16 GetUInt16(const sal_uInt8 *ptr, size_t offset)
Definition: sft.cxx:154
static void * scalloc(size_t n, size_t size)
Definition: sft.cxx:136
static int GetRawData_generic(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
Definition: ttcr.cxx:481
constexpr int HEAD_Length
Definition: sft.hxx:362
static NameRecord * NameRecordNewCopy(NameRecord const *nr)
Definition: ttcr.cxx:976
sal_uInt32 glyfAdd(TrueTypeTable *table, GlyphData *glyphdata, AbstractTrueTypeFont *fnt)
Add a glyph to a glyf table.
Definition: ttcr.cxx:1128
constexpr sal_uInt32 T_cmap
Definition: sft.hxx:442
void cmapAdd(TrueTypeTable *table, sal_uInt32 id, sal_uInt32 c, sal_uInt32 g)
Add a character/glyph pair to a cmap table.
Definition: ttcr.cxx:1062
static void TrueTypeTableDispose_head(TrueTypeTable *_this)
Definition: ttcr.cxx:370
static int GetRawData_loca(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
Definition: ttcr.cxx:511
@ WE_HAVE_A_TWO_BY_TWO
Definition: sft.hxx:110
@ ARG_1_AND_2_ARE_WORDS
Definition: sft.hxx:104
@ WE_HAVE_A_SCALE
Definition: sft.hxx:107
@ MORE_COMPONENTS
Definition: sft.hxx:108
@ WE_HAVE_AN_X_AND_Y_SCALE
Definition: sft.hxx:109
TrueTypeTable * TrueTypeTableNew_cmap()
Creates a new empty 'cmap' table.
Definition: ttcr.cxx:950
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
Definition: list.cxx:46
Structure used by the TrueType Creator and GetRawGlyphData()
Definition: sft.hxx:124
sal_uInt32 glyphID
glyph ID
Definition: sft.hxx:125
bool compflag
false- if non-composite
Definition: sft.hxx:130
sal_uInt16 ncontours
number of contours
Definition: sft.hxx:132
sal_uInt16 npoints
number of points
Definition: sft.hxx:131
sal_uInt8 * ptr
pointer to glyph data
Definition: sft.hxx:127
sal_uInt16 aw
advance width
Definition: sft.hxx:128
sal_uInt32 newID
used internally by the TTCR
Definition: sft.hxx:134
sal_uInt16 nbytes
number of bytes in glyph data
Definition: sft.hxx:126
sal_Int16 lsb
left sidebearing
Definition: sft.hxx:129
Structure used by the TrueType Creator and CreateTTFromTTGlyphs()
Definition: sft.hxx:138
sal_uInt16 slen
String length in bytes
Definition: sft.hxx:143
sal_uInt16 encodingID
Platform-specific encoding ID
Definition: sft.hxx:140
LanguageType languageID
Language ID
Definition: sft.hxx:141
sal_uInt16 platformID
Platform ID
Definition: sft.hxx:139
sal_uInt8 * sptr
Pointer to string data (not zero-terminated!)
Definition: sft.hxx:144
sal_uInt16 nameID
Name ID
Definition: sft.hxx:142
Structure used by GetTTSimpleCharMetrics() functions.
Definition: sft.hxx:117
sal_Int16 sb
left or top sidebearing
Definition: sft.hxx:119
sal_uInt16 adv
advance width or height
Definition: sft.hxx:118
sal_uInt8 * rawdata
Definition: ttcr.hxx:45
sal_uInt32 tag
Definition: ttcr.hxx:44
#define CMAP_PAIR_INIT
Definition: ttcr.cxx:298
#define CMAP_SUBTABLE_INIT
Definition: ttcr.cxx:296
#define CMAP_PAIR_INCR
Definition: ttcr.cxx:299
void TrueTypeTableDispose(void *arg)
Destructor for the TrueTypeTable object.
Definition: ttcr.cxx:1451
#define CMAP_SUBTABLE_INCR
Definition: ttcr.cxx:297
TrueType font creator.
void TrueTypeCreatorDispose(vcl::TrueTypeCreator *_this)
TrueTypeCreator destructor.
unsigned char sal_uInt8