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
39struct TableEntry {
40 sal_uInt32 tag;
41 sal_uInt32 length;
43};
44
45/*- Data access macros for data stored in big-endian or little-endian format */
46static sal_Int16 GetInt16( const sal_uInt8* ptr, sal_uInt32 offset)
47{
48 assert(ptr != nullptr);
49 sal_Int16 t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
50 return t;
51}
52
53static sal_uInt16 GetUInt16( const sal_uInt8* ptr, sal_uInt32 offset)
54{
55 assert(ptr != nullptr);
56 sal_uInt16 t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
57 return t;
58}
59
60static void PutInt16(sal_Int16 val, sal_uInt8 *ptr, sal_uInt32 offset)
61{
62 assert(ptr != nullptr);
63
64 ptr[offset] = static_cast<sal_uInt8>((val >> 8) & 0xFF);
65 ptr[offset+1] = static_cast<sal_uInt8>(val & 0xFF);
66}
67
68static void PutUInt16(sal_uInt16 val, sal_uInt8 *ptr, sal_uInt32 offset)
69{
70 assert(ptr != nullptr);
71
72 ptr[offset] = static_cast<sal_uInt8>((val >> 8) & 0xFF);
73 ptr[offset+1] = static_cast<sal_uInt8>(val & 0xFF);
74}
75
76static void PutUInt32(sal_uInt32 val, sal_uInt8 *ptr, sal_uInt32 offset)
77{
78 assert(ptr != nullptr);
79
80 ptr[offset] = static_cast<sal_uInt8>((val >> 24) & 0xFF);
81 ptr[offset+1] = static_cast<sal_uInt8>((val >> 16) & 0xFF);
82 ptr[offset+2] = static_cast<sal_uInt8>((val >> 8) & 0xFF);
83 ptr[offset+3] = static_cast<sal_uInt8>(val & 0xFF);
84}
85
86static int TableEntryCompareF(const void *l, const void *r)
87{
88 sal_uInt32 const ltag(static_cast<TableEntry const*>(l)->tag);
89 sal_uInt32 const rtag(static_cast<TableEntry const*>(r)->tag);
90 return (ltag == rtag) ? 0 : (ltag < rtag) ? -1 : 1;
91}
92
93namespace {
94struct NameRecordCompareF
95{
96 bool operator()(const NameRecord& l, const NameRecord& r) const
97 {
98 if (l.platformID != r.platformID) {
99 return l.platformID < r.platformID;
100 } else if (l.encodingID != r.encodingID) {
101 return l.encodingID < r.encodingID;
102 } else if (l.languageID != r.languageID) {
103 return l.languageID < r.languageID;
104 } else if (l.nameID != r.nameID) {
105 return l.nameID < r.nameID;
106 }
107 return false;
108 }
109};
110}
111
112static sal_uInt32 CheckSum(sal_uInt32 *ptr, sal_uInt32 length)
113{
114 sal_uInt32 sum = 0;
115 sal_uInt32 *endptr = ptr + ((length + 3) & sal_uInt32(~3)) / 4;
116
117 while (ptr < endptr) sum += *ptr++;
118
119 return sum;
120}
121
122/*
123 * Public functions
124 */
125
127{
128 this->m_tag = _tag;
129}
130
131void TrueTypeCreator::AddTable(std::unique_ptr<TrueTypeTable> table)
132{
133 if (table != nullptr) {
134 this->m_tables.push_back(std::move(table));
135 }
136}
137
138void TrueTypeCreator::RemoveTable(sal_uInt32 tableTag)
139{
140 for (auto it = this->m_tables.begin(); it != this->m_tables.end(); )
141 {
142 if ((*it)->m_tag == tableTag)
143 {
144 it = this->m_tables.erase(it);
145 }
146 else
147 ++it;
148 }
149}
150
151SFErrCodes TrueTypeCreator::StreamToMemory(std::vector<sal_uInt8>& rOutBuffer)
152{
153 sal_uInt16 searchRange=1, entrySelector=0, rangeShift;
154 sal_uInt32 s, offset, checkSumAdjustment = 0;
155 sal_uInt32 *p;
156 sal_uInt8 *head = nullptr; /* saved pointer to the head table data for checkSumAdjustment calculation */
157
158 if (this->m_tables.empty())
160
162
163 /* ProcessTables() adds 'loca' and 'hmtx' */
164
165 sal_uInt16 numTables = this->m_tables.size();
166
167 std::unique_ptr<TableEntry[]> te(new TableEntry[numTables]);
168
169 int teIdx = 0;
170 for (auto const & e : this->m_tables)
171 {
172 e->GetRawData(&te[teIdx]);
173 ++teIdx;
174 }
175
176 qsort(te.get(), numTables, sizeof(TableEntry), TableEntryCompareF);
177
178 do {
179 searchRange *= 2;
180 entrySelector++;
181 } while (searchRange <= numTables);
182
183 searchRange *= 8;
184 entrySelector--;
185 rangeShift = numTables * 16 - searchRange;
186
187 s = offset = 12 + 16 * numTables;
188
189 for (int i = 0; i < numTables; ++i) {
190 s += (te[i].length + 3) & sal_uInt32(~3);
191 /* if ((te[i].length & 3) != 0) s += (4 - (te[i].length & 3)) & 3; */
192 }
193
194 rOutBuffer.resize(s);
195 sal_uInt8* ttf = rOutBuffer.data();
196
197 /* Offset Table */
198 PutUInt32(this->m_tag, ttf, 0);
199 PutUInt16(numTables, ttf, 4);
200 PutUInt16(searchRange, ttf, 6);
201 PutUInt16(entrySelector, ttf, 8);
202 PutUInt16(rangeShift, ttf, 10);
203
204 /* Table Directory */
205 for (int i = 0; i < numTables; ++i) {
206 PutUInt32(te[i].tag, ttf + 12, 16 * i);
207 PutUInt32(CheckSum(reinterpret_cast<sal_uInt32 *>(te[i].data), te[i].length), ttf + 12, 16 * i + 4);
208 PutUInt32(offset, ttf + 12, 16 * i + 8);
209 PutUInt32(te[i].length, ttf + 12, 16 * i + 12);
210
211 if (te[i].tag == T_head) {
212 head = ttf + offset;
213 }
214
215 memcpy(ttf+offset, te[i].data, (te[i].length + 3) & sal_uInt32(~3) );
216 offset += (te[i].length + 3) & sal_uInt32(~3);
217 /* if ((te[i].length & 3) != 0) offset += (4 - (te[i].length & 3)) & 3; */
218 }
219
220 te.reset();
221
222 p = reinterpret_cast<sal_uInt32 *>(ttf);
223 for (int i = 0; i < static_cast<int>(s) / 4; ++i) checkSumAdjustment += p[i];
224 PutUInt32(0xB1B0AFBA - checkSumAdjustment, head, 8);
225
226 return SFErrCodes::Ok;
227}
228
229/*
230 * TrueTypeTable private methods
231 */
232
233/* Table data points to
234 * --------------------------------------------
235 * generic tdata_generic struct
236 * 'head' HEAD_Length bytes of memory
237 * 'hhea' HHEA_Length bytes of memory
238 * 'loca' tdata_loca struct
239 * 'maxp' MAXP_Version1Length bytes of memory
240 * 'glyf' list of GlyphData structs (defined in sft.h)
241 * 'name' list of NameRecord structs (defined in sft.h)
242 * 'post' tdata_post struct
243 *
244 */
245
246#define CMAP_SUBTABLE_INIT 10
247#define CMAP_SUBTABLE_INCR 10
248
249namespace {
250
251struct CmapSubTable {
252 sal_uInt32 id; /* subtable ID (platform/encoding ID) */
253 std::vector<std::pair<sal_uInt32, sal_uInt32>> mappings; /* character to glyph mapping array */
254};
255
256}
257
259 sal_uInt32 n; /* number of used CMAP sub-tables */
260 sal_uInt32 m; /* number of allocated CMAP sub-tables */
261 std::unique_ptr<CmapSubTable[]> s; /* sorted array of sub-tables */
262};
263
265 sal_uInt32 nbytes; /* number of bytes in loca table */
266 std::unique_ptr<sal_uInt8[]> ptr; /* pointer to the data */
267};
268
269/* allocate memory for a TT table */
270static std::unique_ptr<sal_uInt8[]> ttmalloc(sal_uInt32 nbytes)
271{
272 sal_uInt32 n = (nbytes + 3) & sal_uInt32(~3);
273 return std::make_unique<sal_uInt8[]>(n);
274}
275
277
279{
280}
281
283{
284}
285
287{
288}
289
291{
292}
293
295{
296}
297
299{
300}
301
303{
304}
305
307{
308}
309
311{
312 if (m_format == 0x00030000) {
313 /* do nothing */
314 } else {
315 SAL_WARN("vcl.fonts", "Unsupported format of a 'post' table: "
316 << std::setfill('0')
317 << std::setw(8)
318 << std::hex
319 << std::uppercase
320 << static_cast<int>(m_format) << ".");
321 }
322}
323
324
326{
327 te->data = this->m_ptr.get();
328 te->length = this->m_nbytes;
329 te->tag = this->m_tag;
330
331 return TTCR_OK;
332}
333
335{
336 te->length = HEAD_Length;
337 te->data = this->m_head.get();
338 te->tag = T_head;
339
340 return TTCR_OK;
341}
342
344{
345 te->length = HHEA_Length;
346 te->data = this->m_hhea.get();
347 te->tag = T_hhea;
348
349 return TTCR_OK;
350}
351
353{
354 assert(this->m_loca != nullptr);
355
356 if (m_loca->nbytes == 0) return TTCR_ZEROGLYPHS;
357
358 te->data = m_loca->ptr.get();
359 te->length = m_loca->nbytes;
360 te->tag = T_loca;
361
362 return TTCR_OK;
363}
364
366{
368 te->data = this->m_maxp.get();
369 te->tag = T_maxp;
370
371 return TTCR_OK;
372}
373
375{
376 sal_uInt32 n, nbytes = 0;
377 /* sal_uInt16 curID = 0; */ /* to check if glyph IDs are sequential and start from zero */
378
379 te->data = nullptr;
380 te->length = 0;
381 te->tag = 0;
382
383 if (m_list.size() == 0) return TTCR_ZEROGLYPHS;
384
385 for (const std::unique_ptr<GlyphData>& pGlyph : m_list)
386 {
387 /* if (((GlyphData *) listCurrent(l))->glyphID != curID++) return TTCR_GLYPHSEQ; */
388 nbytes += pGlyph->nbytes;
389 }
390
391 m_rawdata = ttmalloc(nbytes);
392
393 auto p = m_rawdata.get();
394 for (const std::unique_ptr<GlyphData>& pGlyph : m_list)
395 {
396 n = pGlyph->nbytes;
397 if (n != 0) {
398 memcpy(p, pGlyph->ptr.get(), n);
399 p += n;
400 }
401 }
402
403 te->length = nbytes;
404 te->data = m_rawdata.get();
405 te->tag = T_glyf;
406
407 return TTCR_OK;
408}
409
410/* cmap packers */
411static std::unique_ptr<sal_uInt8[]> PackCmapType0(CmapSubTable const *s, sal_uInt32 *length)
412{
413 std::unique_ptr<sal_uInt8[]> ptr(new sal_uInt8[262]);
414 sal_uInt8 *p = ptr.get() + 6;
415
416 PutUInt16(0, ptr.get(), 0);
417 PutUInt16(262, ptr.get(), 2);
418 PutUInt16(0, ptr.get(), 4);
419
420 for (sal_uInt32 i = 0; i < 256; i++) {
421 sal_uInt16 g = 0;
422 for (const auto& [ch, glyph] : s->mappings) {
423 if (ch == i) {
424 g = static_cast<sal_uInt16>(glyph);
425 }
426 }
427 p[i] = static_cast<sal_uInt8>(g);
428 }
429 *length = 262;
430 return ptr;
431}
432
433static std::unique_ptr<sal_uInt8[]> PackCmapType6(CmapSubTable const *s, sal_uInt32 *length)
434{
435 std::unique_ptr<sal_uInt8[]> ptr(new sal_uInt8[s->mappings.size()*2 + 10]);
436 sal_uInt8 *p = ptr.get() + 10;
437
438 PutUInt16(6, ptr.get(), 0);
439 PutUInt16(static_cast<sal_uInt16>(s->mappings.size()*2+10), ptr.get(), 2);
440 PutUInt16(0, ptr.get(), 4);
441 PutUInt16(0, ptr.get(), 6);
442 PutUInt16(static_cast<sal_uInt16>(s->mappings.size()), ptr.get(), 8 );
443
444 for (size_t i = 0; i < s->mappings.size(); i++) {
445 sal_uInt16 g = 0;
446 for (const auto& [ch, glyph] : s->mappings) {
447 if (ch == i) {
448 g = static_cast<sal_uInt16>(glyph);
449 }
450 }
451 PutUInt16( g, p, 2*i );
452 }
453 *length = s->mappings.size()*2+10;
454 return ptr;
455}
456
457/* XXX it only handles Format 0 encoding tables */
458static std::unique_ptr<sal_uInt8[]> PackCmap(CmapSubTable const *s, sal_uInt32 *length)
459{
460 if (s->mappings.back().second > 0xff)
461 return PackCmapType6(s, length);
462 else
463 return PackCmapType0(s, length);
464}
465
467{
468 sal_uInt32 i;
469 sal_uInt32 tlen = 0;
470 sal_uInt32 l;
471 sal_uInt32 cmapsize;
472 sal_uInt8 *cmap;
473 sal_uInt32 coffset;
474
475 assert(m_cmap);
476 assert(m_cmap->n != 0);
477
478 std::unique_ptr<std::unique_ptr<sal_uInt8[]>[]> subtables(new std::unique_ptr<sal_uInt8[]>[m_cmap->n]);
479 std::unique_ptr<sal_uInt32[]> sizes(new sal_uInt32[m_cmap->n]);
480
481 for (i = 0; i < m_cmap->n; i++) {
482 subtables[i] = PackCmap(m_cmap->s.get()+i, &l);
483 sizes[i] = l;
484 tlen += l;
485 }
486
487 cmapsize = tlen + 4 + 8 * m_cmap->n;
488 this->m_rawdata = ttmalloc(cmapsize);
489 cmap = this->m_rawdata.get();
490
491 PutUInt16(0, cmap, 0);
492 PutUInt16(static_cast<sal_uInt16>(m_cmap->n), cmap, 2);
493 coffset = 4 + m_cmap->n * 8;
494
495 for (i = 0; i < m_cmap->n; i++) {
496 PutUInt16(static_cast<sal_uInt16>(m_cmap->s[i].id >> 16), cmap + 4, i * 8);
497 PutUInt16(static_cast<sal_uInt16>(m_cmap->s[i].id & 0xFF), cmap + 4, 2 + i * 8);
498 PutUInt32(coffset, cmap + 4, 4 + i * 8);
499 memcpy(cmap + coffset, subtables[i].get(), sizes[i]);
500 subtables[i].reset();
501 coffset += sizes[i];
502 }
503
504 subtables.reset();
505 sizes.reset();
506
507 te->data = cmap;
508 te->length = cmapsize;
509 te->tag = T_cmap;
510
511 return TTCR_OK;
512}
513
515{
516 sal_Int16 i=0, n; /* number of Name Records */
517 int stringLen = 0;
518 sal_uInt8 *p1, *p2;
519
520 te->data = nullptr;
521 te->length = 0;
522 te->tag = 0;
523
524 if ((n = static_cast<sal_Int16>(m_list.size())) == 0) return TTCR_NONAMES;
525
526 std::vector<NameRecord> nr = m_list;
527
528 for (const NameRecord & rName : m_list)
529 stringLen += rName.sptr.size();
530
531 if (stringLen > 65535) {
532 return TTCR_NAMETOOLONG;
533 }
534
535 std::sort(nr.begin(), nr.end(), NameRecordCompareF());
536
537 int nameLen = stringLen + 12 * n + 6;
538 std::unique_ptr<sal_uInt8[]> name = ttmalloc(nameLen);
539
540 PutUInt16(0, name.get(), 0);
541 PutUInt16(n, name.get(), 2);
542 PutUInt16(static_cast<sal_uInt16>(6 + 12 * n), name.get(), 4);
543
544 p1 = name.get() + 6;
545 p2 = p1 + 12 * n;
546
547 for (i = 0; i < n; i++) {
548 PutUInt16(nr[i].platformID, p1, 0);
549 PutUInt16(nr[i].encodingID, p1, 2);
550 PutUInt16(static_cast<sal_uInt16>(nr[i].languageID), p1, 4);
551 PutUInt16(nr[i].nameID, p1, 6);
552 PutUInt16(nr[i].sptr.size(), p1, 8);
553 PutUInt16(static_cast<sal_uInt16>(p2 - (name.get() + 6 + 12 * n)), p1, 10);
554 if (nr[i].sptr.size()) {
555 memcpy(p2, nr[i].sptr.data(), nr[i].sptr.size());
556 }
557 /* {int j; for(j=0; j<nr[i].slen; j++) printf("%c", nr[i].sptr[j]); printf("\n"); }; */
558 p2 += nr[i].sptr.size();
559 p1 += 12;
560 }
561
562 nr.clear();
563 this->m_rawdata = std::move(name);
564
565 te->data = this->m_rawdata.get();
566 te->length = static_cast<sal_uInt16>(nameLen);
567 te->tag = T_name;
568
569 /*{int j; for(j=0; j<nameLen; j++) printf("%c", name[j]); }; */
570
571 return TTCR_OK;
572}
573
575{
576 std::unique_ptr<sal_uInt8[]> post;
577 sal_uInt32 postLen = 0;
578 int ret;
579
580 this->m_rawdata.reset();
581
582 if (m_format == 0x00030000) {
583 postLen = 32;
584 post = ttmalloc(postLen);
585 PutUInt32(0x00030000, post.get(), 0);
586 PutUInt32(m_italicAngle, post.get(), 4);
587 PutUInt16(m_underlinePosition, post.get(), 8);
588 PutUInt16(m_underlineThickness, post.get(), 10);
589 PutUInt16(static_cast<sal_uInt16>(m_isFixedPitch), post.get(), 12);
590 ret = TTCR_OK;
591 } else {
592 SAL_WARN("vcl.fonts", "Unrecognized format of a post table: "
593 << std::setfill('0')
594 << std::setw(8)
595 << std::hex
596 << std::uppercase
597 << static_cast<int>(m_format) << ".");
598 ret = TTCR_POSTFORMAT;
599 }
600
601 this->m_rawdata = std::move(post);
602 te->data = this->m_rawdata.get();
603 te->length = postLen;
604 te->tag = T_post;
605
606 return ret;
607}
608
609/*
610 * TrueTypeTable public methods
611 */
612
613/* Note: Type42 fonts only need these tables:
614 * head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm
615 *
616 * Microsoft required tables
617 * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post, OS/2
618 *
619 * Apple required tables
620 * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post
621 *
622 */
623
625 sal_uInt32 nbytes,
626 const sal_uInt8* ptr)
627 : TrueTypeTable(tag),
628 m_nbytes(nbytes)
629{
630 if (nbytes) {
631 m_ptr = ttmalloc(nbytes);
632 memcpy(m_ptr.get(), ptr, nbytes);
633 }
634}
635
637 sal_uInt32 nbytes,
638 std::unique_ptr<sal_uInt8[]> ptr)
639 : TrueTypeTable(tag),
640 m_nbytes(nbytes)
641{
642 if (nbytes) {
643 m_ptr = std::move(ptr);
644 }
645}
646
648 sal_uInt16 flags,
649 sal_uInt16 unitsPerEm,
650 const sal_uInt8* created,
651 sal_uInt16 macStyle,
652 sal_uInt16 lowestRecPPEM,
653 sal_Int16 fontDirectionHint)
655 , m_head(ttmalloc(HEAD_Length))
656{
657 assert(created != nullptr);
658
659 sal_uInt8* ptr = m_head.get();
660
661 PutUInt32(0x00010000, ptr, 0); /* version */
662 PutUInt32(fontRevision, ptr, 4);
663 PutUInt32(0x5F0F3CF5, ptr, 12); /* magic number */
664 PutUInt16(flags, ptr, 16);
665 PutUInt16(unitsPerEm, ptr, 18);
666 memcpy(ptr+20, created, 8); /* Created Long Date */
667 memset(ptr+28, 0, 8); /* Modified Long Date */
668 PutUInt16(macStyle, ptr, 44);
669 PutUInt16(lowestRecPPEM, ptr, 46);
670 PutUInt16(fontDirectionHint, ptr, 48);
671 PutUInt16(0, ptr, 52); /* glyph data format: 0 */
672}
673
675 sal_Int16 descender,
676 sal_Int16 linegap,
677 sal_Int16 caretSlopeRise,
678 sal_Int16 caretSlopeRun)
680 m_hhea(ttmalloc(HHEA_Length))
681{
682 sal_uInt8* ptr = m_hhea.get();
683
684 PutUInt32(0x00010000, ptr, 0); /* version */
685 PutUInt16(ascender, ptr, 4);
686 PutUInt16(descender, ptr, 6);
687 PutUInt16(linegap, ptr, 8);
688 PutUInt16(caretSlopeRise, ptr, 18);
689 PutUInt16(caretSlopeRun, ptr, 20);
690 PutUInt16(0, ptr, 22); /* reserved 1 */
691 PutUInt16(0, ptr, 24); /* reserved 2 */
692 PutUInt16(0, ptr, 26); /* reserved 3 */
693 PutUInt16(0, ptr, 28); /* reserved 4 */
694 PutUInt16(0, ptr, 30); /* reserved 5 */
695 PutUInt16(0, ptr, 32); /* metricDataFormat */
696}
697
700 m_loca(new tdata_loca)
701{
702 this->m_loca->nbytes = 0;
703 this->m_loca->ptr = nullptr;
704}
705
708{
710
711 if (maxp && size == MAXP_Version1Length) {
712 memcpy(this->m_maxp.get(), maxp, MAXP_Version1Length);
713 }
714}
715
718{
719}
720
723 , m_cmap(new table_cmap)
724{
725 m_cmap->n = 0;
727 m_cmap->s.reset(new CmapSubTable[CMAP_SUBTABLE_INIT]);
728}
729
730TrueTypeTableName::TrueTypeTableName(std::vector<NameRecord> nr)
732 , m_list(std::move(nr))
733{
734}
735
737 sal_Int32 italicAngle,
738 sal_Int16 underlinePosition,
739 sal_Int16 underlineThickness,
740 sal_uInt32 isFixedPitch)
742{
743 assert(format == 0x00030000); /* Only format 3.0 is supported at this time */
744
745 m_format = format;
746 m_italicAngle = italicAngle;
747 m_underlinePosition = underlinePosition;
748 m_underlineThickness = underlineThickness;
749 m_isFixedPitch = isFixedPitch;
750}
751
752void TrueTypeTableCmap::cmapAdd(sal_uInt32 id, sal_uInt32 c, sal_uInt32 g)
753{
754 sal_uInt32 i, found;
755 CmapSubTable *s;
756
757 assert(m_cmap);
758 s = m_cmap->s.get(); assert(s != nullptr);
759
760 found = 0;
761
762 for (i = 0; i < m_cmap->n; i++) {
763 if (s[i].id == id) {
764 found = 1;
765 break;
766 }
767 }
768
769 if (!found) {
770 if (m_cmap->n == m_cmap->m) {
771 std::unique_ptr<CmapSubTable[]> tmp(new CmapSubTable[m_cmap->m + CMAP_SUBTABLE_INCR]);
772 for (sal_uInt32 j = 0; j != m_cmap->m; ++j) {
773 tmp[j] = std::move(s[j]);
774 }
776 s = tmp.get();
777 m_cmap->s = std::move(tmp);
778 }
779
780 for (i = 0; i < m_cmap->n; i++) {
781 if (s[i].id > id) break;
782 }
783
784 if (i < m_cmap->n) {
785 for (sal_uInt32 j = m_cmap->n; j != i; --j) {
786 s[j + 1] = std::move(s[j]);
787 }
788 }
789
790 m_cmap->n++;
791
792 s[i].id = id;
793 }
794
795 s[i].mappings.emplace_back(c, g);
796}
797
798sal_uInt32 TrueTypeTableGlyf::glyfAdd(std::unique_ptr<GlyphData> glyphdata, AbstractTrueTypeFont *fnt)
799{
800 sal_uInt32 currentID;
801 int ret, n, ncomponents;
802
803 if (!glyphdata) return sal_uInt32(~0);
804
805 std::vector< sal_uInt32 > glyphlist;
806
807 ncomponents = GetTTGlyphComponents(fnt, glyphdata->glyphID, glyphlist);
808
809 if (m_list.size() > 0) {
810 ret = n = m_list.back()->newID + 1;
811 } else {
812 ret = n = 0;
813 }
814 glyphdata->newID = n++;
815 m_list.push_back(std::move(glyphdata));
816
817 if (ncomponents > 1 && glyphlist.size() > 1 )
818 {
819 std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin();
820 ++it;
821 /* glyphData->glyphID is always the first glyph on the list */
822 do
823 {
824 int found = 0;
825 currentID = *it;
826 /* XXX expensive! should be rewritten with sorted arrays! */
827 for (const std::unique_ptr<GlyphData>& pGlyph : m_list)
828 {
829 if (pGlyph->glyphID == currentID) {
830 found = 1;
831 break;
832 }
833 }
834
835 if (!found) {
836 std::unique_ptr<GlyphData> gd = GetTTRawGlyphData(fnt, currentID);
837 gd->newID = n++;
838 m_list.push_back(std::move(gd));
839 }
840 } while( ++it != glyphlist.end() );
841 }
842
843 return ret;
844}
845
847{
848 for (const std::unique_ptr<TrueTypeTable>& p : this->m_tables)
849 if (p->m_tag == tableTag) {
850 return p.get();
851 }
852
853 return nullptr;
854}
855
856/* This function processes all the tables and synchronizes them before creating
857 * the output TrueType stream.
858 *
859 * *** It adds two TrueType tables to the font: 'loca' and 'hmtx' ***
860 *
861 * It does:
862 *
863 * - Re-numbers glyph IDs and creates 'glyf', 'loca', and 'hmtx' tables.
864 * - Calculates xMin, yMin, xMax, and yMax and stores values in 'head' table.
865 * - Stores indexToLocFormat in 'head'
866 * - updates 'maxp' table
867 * - Calculates advanceWidthMax, minLSB, minRSB, xMaxExtent and numberOfHMetrics
868 * in 'hhea' table
869 *
870 */
872{
873 TrueTypeTableHhea *hhea = nullptr;
874 TrueTypeTableMaxp *maxp = nullptr;
875 TrueTypeTableHead *head = nullptr;
876 std::unique_ptr<TrueTypeTableLoca> loca;
877 TrueTypeTableGlyf *glyf = nullptr;
878 sal_uInt32 nGlyphs, locaLen = 0, glyfLen = 0;
879 sal_Int16 xMin = 0, yMin = 0, xMax = 0, yMax = 0;
880 sal_uInt32 i = 0;
881 sal_Int16 indexToLocFormat;
882 std::unique_ptr<sal_uInt8[]> hmtxPtr;
883 sal_uInt8 *hheaPtr;
884 sal_uInt32 hmtxSize;
885 sal_uInt8 *p1, *p2;
886 sal_uInt16 maxPoints = 0, maxContours = 0, maxCompositePoints = 0, maxCompositeContours = 0;
887 int nlsb = 0;
888 std::unique_ptr<sal_uInt32[]> gid; /* array of old glyphIDs */
889
890 glyf = static_cast<TrueTypeTableGlyf*>(FindTable(T_glyf));
891 std::vector<std::unique_ptr<GlyphData>>& glyphlist = glyf->m_list;
892 nGlyphs = glyphlist.size();
893 if (!nGlyphs)
894 {
895 SAL_WARN("vcl.fonts", "no glyphs found in ProcessTables");
896 return;
897 }
898 gid.reset(new sal_uInt32[nGlyphs]);
899
902
903 /* XXX Need to make sure that composite glyphs do not break during glyph renumbering */
904
905 for (const std::unique_ptr<GlyphData>& gd : glyphlist)
906 {
907 glyfLen += gd->nbytes;
908 /* XXX if (gd->nbytes & 1) glyfLen++; */
909
910 assert(gd->newID == i);
911 gid[i++] = gd->glyphID;
912 /* gd->glyphID = i++; */
913
914 /* printf("IDs: %d %d.\n", gd->glyphID, gd->newID); */
915
916 if (gd->nbytes >= 10) {
917 sal_Int16 z = GetInt16(gd->ptr.get(), 2);
918 if (z < xMin) xMin = z;
919
920 z = GetInt16(gd->ptr.get(), 4);
921 if (z < yMin) yMin = z;
922
923 z = GetInt16(gd->ptr.get(), 6);
924 if (z > xMax) xMax = z;
925
926 z = GetInt16(gd->ptr.get(), 8);
927 if (z > yMax) yMax = z;
928 }
929
930 if (!gd->compflag) { /* non-composite glyph */
931 if (gd->npoints > maxPoints) maxPoints = gd->npoints;
932 if (gd->ncontours > maxContours) maxContours = gd->ncontours;
933 } else { /* composite glyph */
934 if (gd->npoints > maxCompositePoints) maxCompositePoints = gd->npoints;
935 if (gd->ncontours > maxCompositeContours) maxCompositeContours = gd->ncontours;
936 }
937
938 }
939
940 indexToLocFormat = (glyfLen / 2 > 0xFFFF) ? 1 : 0;
941 locaLen = indexToLocFormat ? (nGlyphs + 1) << 2 : (nGlyphs + 1) << 1;
942
943 std::unique_ptr<sal_uInt8[]> glyfPtr = ttmalloc(glyfLen);
944 std::unique_ptr<sal_uInt8[]> locaPtr = ttmalloc(locaLen);
945 std::unique_ptr<TTSimpleGlyphMetrics[]> met(new TTSimpleGlyphMetrics[nGlyphs]);
946 i = 0;
947
948 p1 = glyfPtr.get();
949 p2 = locaPtr.get();
950 for (const std::unique_ptr<GlyphData>& gd : glyphlist)
951 {
952 if (gd->compflag && gd->nbytes > 10) { /* re-number all components */
953 sal_uInt16 flags, index;
954 sal_uInt8 *ptr = gd->ptr.get() + 10;
955 size_t nRemaining = gd->nbytes - 10;
956 do {
957 if (nRemaining < 4)
958 {
959 SAL_WARN("vcl.fonts", "truncated font");
960 break;
961 }
962 flags = GetUInt16(ptr, 0);
963 index = GetUInt16(ptr, 2);
964
965 /* XXX use the sorted array of old to new glyphID mapping and do a binary search */
966 sal_uInt32 j;
967 for (j = 0; j < nGlyphs; j++) {
968 if (gid[j] == index) {
969 break;
970 }
971 }
972 /* printf("X: %d -> %d.\n", index, j); */
973
974 PutUInt16(static_cast<sal_uInt16>(j), ptr, 2);
975
976 ptr += 4;
977 nRemaining -= 4;
978
979 sal_uInt32 nAdvance = 0;
980 if (flags & ARG_1_AND_2_ARE_WORDS) {
981 nAdvance += 4;
982 } else {
983 nAdvance += 2;
984 }
985
986 if (flags & WE_HAVE_A_SCALE) {
987 nAdvance += 2;
988 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
989 nAdvance += 4;
990 } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
991 nAdvance += 8;
992 }
993
994 if (nRemaining < nAdvance)
995 {
996 SAL_WARN("vcl.fonts", "truncated font");
997 break;
998 }
999
1000 ptr += nAdvance;
1001 nRemaining -= nAdvance;
1002
1003 } while (flags & MORE_COMPONENTS);
1004 }
1005
1006 if (gd->nbytes != 0) {
1007 memcpy(p1, gd->ptr.get(), gd->nbytes);
1008 }
1009 if (indexToLocFormat == 1) {
1010 PutUInt32(p1 - glyfPtr.get(), p2, 0);
1011 p2 += 4;
1012 } else {
1013 PutUInt16(static_cast<sal_uInt16>((p1 - glyfPtr.get()) >> 1), p2, 0);
1014 p2 += 2;
1015 }
1016 p1 += gd->nbytes;
1017
1018 /* fill the array of metrics */
1019 met[i].adv = gd->aw;
1020 met[i].sb = gd->lsb;
1021 i++;
1022 }
1023
1024 gid.reset();
1025
1026 if (indexToLocFormat == 1) {
1027 PutUInt32(p1 - glyfPtr.get(), p2, 0);
1028 } else {
1029 PutUInt16(static_cast<sal_uInt16>((p1 - glyfPtr.get()) >> 1), p2, 0);
1030 }
1031
1032 glyf->m_rawdata = std::move(glyfPtr);
1033
1034 loca.reset(new TrueTypeTableLoca());
1035 loca->m_loca->ptr = std::move(locaPtr);
1036 loca->m_loca->nbytes = locaLen;
1037
1038 AddTable(std::move(loca));
1039
1040 head = static_cast<TrueTypeTableHead*>(FindTable(T_head));
1041 sal_uInt8* const pHeadData = head->m_head.get();
1042 PutInt16(xMin, pHeadData, HEAD_xMin_offset);
1043 PutInt16(yMin, pHeadData, HEAD_yMin_offset);
1044 PutInt16(xMax, pHeadData, HEAD_xMax_offset);
1045 PutInt16(yMax, pHeadData, HEAD_yMax_offset);
1046 PutInt16(indexToLocFormat, pHeadData, HEAD_indexToLocFormat_offset);
1047
1048 maxp = static_cast<TrueTypeTableMaxp*>(FindTable(T_maxp));
1049
1050 sal_uInt8* const pMaxpData = maxp->m_maxp.get();
1051 PutUInt16(static_cast<sal_uInt16>(nGlyphs), pMaxpData, MAXP_numGlyphs_offset);
1052 PutUInt16(maxPoints, pMaxpData, MAXP_maxPoints_offset);
1053 PutUInt16(maxContours, pMaxpData, MAXP_maxContours_offset);
1054 PutUInt16(maxCompositePoints, pMaxpData, MAXP_maxCompositePoints_offset);
1055 PutUInt16(maxCompositeContours, pMaxpData, MAXP_maxCompositeContours_offset);
1056
1057 /*
1058 * Generate an htmx table and update hhea table
1059 */
1060 hhea = static_cast<TrueTypeTableHhea*>(FindTable(T_hhea)); assert(hhea != nullptr);
1061 hheaPtr = hhea->m_hhea.get();
1062 if (nGlyphs > 2) {
1063 for (i = nGlyphs - 1; i > 0; i--) {
1064 if (met[i].adv != met[i-1].adv) break;
1065 }
1066 nlsb = nGlyphs - 1 - i;
1067 }
1068 hmtxSize = (nGlyphs - nlsb) * 4 + nlsb * 2;
1069 hmtxPtr = ttmalloc(hmtxSize);
1070 p1 = hmtxPtr.get();
1071
1072 for (i = 0; i < nGlyphs; i++) {
1073 if (i < nGlyphs - nlsb) {
1074 PutUInt16(met[i].adv, p1, 0);
1075 PutUInt16(met[i].sb, p1, 2);
1076 p1 += 4;
1077 } else {
1078 PutUInt16(met[i].sb, p1, 0);
1079 p1 += 2;
1080 }
1081 }
1082
1083 AddTable(std::make_unique<TrueTypeTableGeneric>(T_hmtx, hmtxSize, std::move(hmtxPtr)));
1084 PutUInt16(static_cast<sal_uInt16>(nGlyphs - nlsb), hheaPtr, 34);
1085}
1086
1091{
1092}
1093
1094} // namespace vcl
1095
1096#ifdef TEST_TTCR
1097static sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) {
1098 return (a << 24) | (b << 16) | (c << 8) | d;
1099}
1100
1101int main()
1102{
1103 TrueTypeCreator *ttcr;
1104 sal_uInt8 *t1, *t2, *t3, *t4, *t5, *t6;
1105
1106 TrueTypeCreatorNewEmpty(mkTag('t','r','u','e'), &ttcr);
1107
1108 t1 = malloc(1000); memset(t1, 'a', 1000);
1109 t2 = malloc(2000); memset(t2, 'b', 2000);
1110 t3 = malloc(3000); memset(t3, 'c', 3000);
1111 t4 = malloc(4000); memset(t4, 'd', 4000);
1112 t5 = malloc(5000); memset(t5, 'e', 5000);
1113 t6 = malloc(6000); memset(t6, 'f', 6000);
1114
1115 AddTable(ttcr, TrueTypeTableNew(T_maxp, 1000, t1));
1116 AddTable(ttcr, TrueTypeTableNew(T_OS2, 2000, t2));
1117 AddTable(ttcr, TrueTypeTableNew(T_cmap, 3000, t3));
1118 AddTable(ttcr, TrueTypeTableNew(T_loca, 4000, t4));
1119 AddTable(ttcr, TrueTypeTableNew(T_hhea, 5000, t5));
1120 AddTable(ttcr, TrueTypeTableNew(T_glyf, 6000, t6));
1121
1122 free(t1);
1123 free(t2);
1124 free(t3);
1125 free(t4);
1126 free(t5);
1127 free(t6);
1128
1129 StreamToFile(ttcr, "ttcrout.ttf");
1130
1131 TrueTypeCreatorDispose(ttcr);
1132 return 0;
1133}
1134#endif
1135
1136/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XPropertyListType t
double d
sal_uInt32 m_tag
TrueType file tag.
Definition: ttcr.hxx:86
TrueTypeTable * FindTable(sal_uInt32 tag)
Definition: ttcr.cxx:846
TrueTypeCreator(sal_uInt32 tag)
TrueTypeCreator constructor.
Definition: ttcr.cxx:126
void ProcessTables()
Definition: ttcr.cxx:871
void RemoveTable(sal_uInt32 tag)
Removes a TrueType table from the TrueType creator if it is stored there.
Definition: ttcr.cxx:138
~TrueTypeCreator()
TrueTypeCreator destructor.
Definition: ttcr.cxx:1090
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:151
void AddTable(std::unique_ptr< TrueTypeTable > table)
Adds a TrueType table to the TrueType creator.
Definition: ttcr.cxx:131
std::vector< std::unique_ptr< TrueTypeTable > > m_tables
List of table tags and pointers.
Definition: ttcr.hxx:87
void cmapAdd(sal_uInt32 id, sal_uInt32 c, sal_uInt32 g)
Add a character/glyph pair to a cmap table.
Definition: ttcr.cxx:752
virtual int GetRawData(TableEntry *) override
This function converts the data of a TrueType table to a raw array of bytes.
Definition: ttcr.cxx:466
virtual ~TrueTypeTableCmap() override
Definition: ttcr.cxx:302
std::unique_ptr< table_cmap > m_cmap
Definition: ttcr.hxx:252
virtual int GetRawData(TableEntry *) override
This function converts the data of a TrueType table to a raw array of bytes.
Definition: ttcr.cxx:325
std::unique_ptr< sal_uInt8[]> m_ptr
Definition: ttcr.hxx:133
TrueTypeTableGeneric(sal_uInt32 tag, sal_uInt32 nbytes, const sal_uInt8 *ptr)
Creates a new raw TrueType table.
Definition: ttcr.cxx:624
virtual ~TrueTypeTableGeneric() override
Definition: ttcr.cxx:278
Creates a new empty 'glyf' table.
Definition: ttcr.hxx:211
sal_uInt32 glyfAdd(std::unique_ptr< GlyphData > glyphdata, AbstractTrueTypeFont *fnt)
Add a glyph to a glyf table.
Definition: ttcr.cxx:798
std::vector< std::unique_ptr< GlyphData > > m_list
Definition: ttcr.hxx:233
virtual int GetRawData(TableEntry *) override
This function converts the data of a TrueType table to a raw array of bytes.
Definition: ttcr.cxx:374
virtual ~TrueTypeTableGlyf() override
Definition: ttcr.cxx:298
Creates a new 'head' table for a TrueType font.
Definition: ttcr.hxx:143
std::unique_ptr< sal_uInt8[]> m_head
Definition: ttcr.hxx:155
TrueTypeTableHead(sal_uInt32 fontRevision, sal_uInt16 flags, sal_uInt16 unitsPerEm, const sal_uInt8 *created, sal_uInt16 macStyle, sal_uInt16 lowestRecPPEM, sal_Int16 fontDirectionHint)
Definition: ttcr.cxx:647
virtual ~TrueTypeTableHead() override
Definition: ttcr.cxx:282
virtual int GetRawData(TableEntry *) override
This function converts the data of a TrueType table to a raw array of bytes.
Definition: ttcr.cxx:334
Creates a new 'hhea' table for a TrueType font.
Definition: ttcr.hxx:163
TrueTypeTableHhea(sal_Int16 ascender, sal_Int16 descender, sal_Int16 linegap, sal_Int16 caretSlopeRise, sal_Int16 caretSlopeRun)
Definition: ttcr.cxx:674
virtual ~TrueTypeTableHhea() override
Definition: ttcr.cxx:286
std::unique_ptr< sal_uInt8[]> m_hhea
Definition: ttcr.hxx:173
virtual int GetRawData(TableEntry *) override
This function converts the data of a TrueType table to a raw array of bytes.
Definition: ttcr.cxx:343
Creates a new empty 'loca' table for a TrueType font.
Definition: ttcr.hxx:182
virtual ~TrueTypeTableLoca() override
Definition: ttcr.cxx:290
std::unique_ptr< tdata_loca > m_loca
Definition: ttcr.hxx:188
virtual int GetRawData(TableEntry *) override
This function converts the data of a TrueType table to a raw array of bytes.
Definition: ttcr.cxx:352
Creates a new 'maxp' table based on an existing maxp table.
Definition: ttcr.hxx:198
virtual int GetRawData(TableEntry *) override
This function converts the data of a TrueType table to a raw array of bytes.
Definition: ttcr.cxx:365
virtual ~TrueTypeTableMaxp() override
Definition: ttcr.cxx:294
TrueTypeTableMaxp(const sal_uInt8 *maxp, int size)
Definition: ttcr.cxx:706
std::unique_ptr< sal_uInt8[]> m_maxp
Definition: ttcr.hxx:204
TrueTypeTableName(std::vector< NameRecord > nr)
Definition: ttcr.cxx:730
virtual ~TrueTypeTableName() override
Definition: ttcr.cxx:306
std::vector< NameRecord > m_list
Definition: ttcr.hxx:268
virtual int GetRawData(TableEntry *) override
This function converts the data of a TrueType table to a raw array of bytes.
Definition: ttcr.cxx:514
sal_Int16 m_underlineThickness
Definition: ttcr.hxx:288
sal_uInt32 m_italicAngle
Definition: ttcr.hxx:286
virtual int GetRawData(TableEntry *) override
This function converts the data of a TrueType table to a raw array of bytes.
Definition: ttcr.cxx:574
TrueTypeTablePost(sal_Int32 format, sal_Int32 italicAngle, sal_Int16 underlinePosition, sal_Int16 underlineThickness, sal_uInt32 isFixedPitch)
Definition: ttcr.cxx:736
sal_uInt32 m_isFixedPitch
Definition: ttcr.hxx:289
virtual ~TrueTypeTablePost() override
Definition: ttcr.cxx:310
sal_uInt32 m_format
Definition: ttcr.hxx:285
sal_Int16 m_underlinePosition
Definition: ttcr.hxx:287
std::unique_ptr< sal_uInt8[]> m_rawdata
Definition: ttcr.hxx:109
virtual ~TrueTypeTable()
Definition: ttcr.cxx:276
sal_uInt32 m_tag
Definition: ttcr.hxx:108
float z
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:1487
std::unique_ptr< 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:2332
const char * name
void * p
sal_Int64 n
#define SAL_WARN(area, stream)
@ table
size
int i
index
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
constexpr sal_uInt32 T_post
Definition: sft.hxx:447
constexpr sal_uInt32 T_loca
Definition: sft.hxx:439
static std::unique_ptr< sal_uInt8[]> PackCmap(CmapSubTable const *s, sal_uInt32 *length)
Definition: ttcr.cxx:458
constexpr int HHEA_Length
Definition: sft.hxx:311
constexpr int HEAD_yMax_offset
Definition: sft.hxx:374
SFErrCodes
Return value of OpenTTFont() and CreateT3FromTTGlyphs()
Definition: sft.hxx:65
@ TtFormat
incorrect TrueType font format
constexpr int MAXP_maxCompositePoints_offset
Definition: sft.hxx:404
constexpr sal_uInt32 T_glyf
Definition: sft.hxx:437
static void PutUInt32(sal_uInt32 val, sal_uInt8 *ptr, sal_uInt32 offset)
Definition: ttcr.cxx:76
constexpr int MAXP_Version1Length
Definition: sft.hxx:399
static void PutInt16(sal_Int16 val, sal_uInt8 *ptr, sal_uInt32 offset)
Definition: ttcr.cxx:60
static std::unique_ptr< sal_uInt8[]> PackCmapType0(CmapSubTable const *s, sal_uInt32 *length)
Definition: ttcr.cxx:411
constexpr sal_uInt32 T_hhea
Definition: sft.hxx:441
constexpr int MAXP_maxCompositeContours_offset
Definition: sft.hxx:405
static int TableEntryCompareF(const void *l, const void *r)
Definition: ttcr.cxx:86
static void PutUInt16(sal_uInt16 val, sal_uInt8 *ptr, sal_uInt32 offset)
Definition: ttcr.cxx:68
constexpr int MAXP_maxPoints_offset
Definition: sft.hxx:402
static sal_uInt32 CheckSum(sal_uInt32 *ptr, sal_uInt32 length)
Definition: ttcr.cxx:112
@ TTCR_OK
no error
Definition: ttcr.hxx:46
@ TTCR_POSTFORMAT
unsupported format of a 'post' table
Definition: ttcr.hxx:51
@ TTCR_ZEROGLYPHS
At least one glyph should be defined
Definition: ttcr.hxx:47
@ TTCR_NONAMES
'name' table does not contain any names
Definition: ttcr.hxx:49
@ TTCR_NAMETOOLONG
'name' table is too long (string data > 64K)
Definition: ttcr.hxx:50
constexpr int HEAD_xMax_offset
Definition: sft.hxx:373
constexpr sal_uInt32 T_head
Definition: sft.hxx:438
static sal_Int16 GetInt16(const sal_uInt8 *ptr, size_t offset)
Definition: sft.cxx:144
constexpr int HEAD_yMin_offset
Definition: sft.hxx:372
constexpr int MAXP_maxContours_offset
Definition: sft.hxx:403
constexpr int HEAD_xMin_offset
Definition: sft.hxx:371
constexpr int MAXP_numGlyphs_offset
Definition: sft.hxx:401
static std::unique_ptr< sal_uInt8[]> ttmalloc(sal_uInt32 nbytes)
Definition: ttcr.cxx:270
static std::unique_ptr< sal_uInt8[]> PackCmapType6(CmapSubTable const *s, sal_uInt32 *length)
Definition: ttcr.cxx:433
constexpr sal_uInt32 T_maxp
Definition: sft.hxx:436
constexpr sal_uInt32 T_OS2
Definition: sft.hxx:446
constexpr int HEAD_indexToLocFormat_offset
Definition: sft.hxx:378
constexpr sal_uInt32 T_hmtx
Definition: sft.hxx:442
constexpr sal_uInt32 T_name
Definition: sft.hxx:440
static sal_uInt16 GetUInt16(const sal_uInt8 *ptr, size_t offset)
Definition: sft.cxx:154
constexpr int HEAD_Length
Definition: sft.hxx:363
constexpr sal_uInt32 T_cmap
Definition: sft.hxx:443
@ WE_HAVE_A_TWO_BY_TWO
Definition: sft.hxx:112
@ ARG_1_AND_2_ARE_WORDS
Definition: sft.hxx:106
@ WE_HAVE_A_SCALE
Definition: sft.hxx:109
@ MORE_COMPONENTS
Definition: sft.hxx:110
@ WE_HAVE_AN_X_AND_Y_SCALE
Definition: sft.hxx:111
Structure used by the TrueType Creator and CreateTTFromTTGlyphs()
Definition: sft.hxx:140
Structure used by GetTTSimpleCharMetrics() functions.
Definition: sft.hxx:119
sal_uInt32 tag
Definition: ttcr.cxx:40
sal_uInt32 length
Definition: ttcr.cxx:41
sal_uInt8 * data
Definition: ttcr.cxx:42
sal_uInt32 m
Definition: ttcr.cxx:260
sal_uInt32 n
Definition: ttcr.cxx:259
std::unique_ptr< CmapSubTable[]> s
Definition: ttcr.cxx:261
sal_uInt32 nbytes
Definition: ttcr.cxx:265
std::unique_ptr< sal_uInt8[]> ptr
Definition: ttcr.cxx:266
#define CMAP_SUBTABLE_INIT
Definition: ttcr.cxx:246
#define CMAP_SUBTABLE_INCR
Definition: ttcr.cxx:247
TrueType font creator.
unsigned char sal_uInt8