LibreOffice Module vcl (master) 1
sft.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 * Sun Font Tools
22 *
23 * Author: Alexander Gelfenbain
24 *
25 */
26
27#include <assert.h>
28
29#include <stdlib.h>
30#include <string.h>
31#include <fcntl.h>
32#ifdef UNX
33#include <sys/mman.h>
34#include <sys/stat.h>
35#include <unistd.h>
36#endif
37#include <sft.hxx>
38#include <impfontcharmap.hxx>
39#ifdef SYSTEM_LIBFIXMATH
40#include <libfixmath/fix16.hpp>
41#else
42#include <tools/fix16.hxx>
43#endif
44#include "ttcr.hxx"
45#include "xlat.hxx"
46#include <rtl/crc.h>
47#include <rtl/ustring.hxx>
48#include <sal/log.hxx>
49#include <o3tl/safeint.hxx>
50#include <osl/endian.h>
51#include <fontsubset.hxx>
52#include <algorithm>
53
54namespace vcl
55{
56
57/*- module identification */
58
59const char * const modname = "SunTypeTools-TT";
60const char * const modver = "1.0";
61const char * const modextra = "gelf";
62
63/*- private functions, constants and data types */
64
65namespace {
66
67enum PathSegmentType {
68 PS_NOOP = 0,
69 PS_MOVETO = 1,
70 PS_LINETO = 2,
71 PS_CURVETO = 3,
72 PS_CLOSEPATH = 4
73};
74
75struct PSPathElement
76{
77 PathSegmentType type;
78 int x1, y1;
79 int x2, y2;
80 int x3, y3;
81
82 explicit PSPathElement( PathSegmentType i_eType ) : type( i_eType ),
83 x1( 0 ), y1( 0 ),
84 x2( 0 ), y2( 0 ),
85 x3( 0 ), y3( 0 )
86 {
87 }
88};
89
90/*- In horizontal writing mode right sidebearing is calculated using this formula
91 *- rsb = aw - (lsb + xMax - xMin) -*/
92struct TTGlyphMetrics {
93 sal_Int16 xMin;
94 sal_Int16 yMin;
95 sal_Int16 xMax;
96 sal_Int16 yMax;
97 sal_uInt16 aw; /*- Advance Width (horizontal writing mode) */
98 sal_Int16 lsb; /*- Left sidebearing (horizontal writing mode) */
99 sal_uInt16 ah; /*- advance height (vertical writing mode) */
100};
101
102#define HFORMAT_LINELEN 64
103
104struct HexFmt {
105 FILE *o;
106 char buffer[HFORMAT_LINELEN];
107 size_t bufpos;
108 int total;
109};
110
111struct GlyphOffsets {
112 sal_uInt32 nGlyphs; /* number of glyphs in the font + 1 */
113 sal_uInt32 *offs; /* array of nGlyphs offsets */
114};
115
116}
117
118static void *smalloc(size_t size)
119{
120 void *res = malloc(size);
121 assert(res != nullptr);
122 return res;
123}
124
125static void *scalloc(size_t n, size_t size)
126{
127 void *res = calloc(n, size);
128 assert(res != nullptr);
129 return res;
130}
131
132/*- Data access methods for data stored in big-endian format */
133static sal_Int16 GetInt16(const sal_uInt8 *ptr, size_t offset)
134{
135 sal_Int16 t;
136 assert(ptr != nullptr);
137
138 t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
139
140 return t;
141}
142
143static sal_uInt16 GetUInt16(const sal_uInt8 *ptr, size_t offset)
144{
145 sal_uInt16 t;
146 assert(ptr != nullptr);
147
148 t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
149
150 return t;
151}
152
153static sal_Int32 GetInt32(const sal_uInt8 *ptr, size_t offset)
154{
155 sal_Int32 t;
156 assert(ptr != nullptr);
157
158 t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
159 (ptr+offset)[2] << 8 | (ptr+offset)[3];
160
161 return t;
162}
163
164static sal_uInt32 GetUInt32(const sal_uInt8 *ptr, size_t offset)
165{
166 sal_uInt32 t;
167 assert(ptr != nullptr);
168
169 t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
170 (ptr+offset)[2] << 8 | (ptr+offset)[3];
171
172 return t;
173}
174
176{
177 return fix16_mul(a, b);
178}
179
181{
182 return fix16_div(a, b);
183}
184
185/*- returns a * b / c -*/
186/* XXX provide a real implementation that preserves accuracy */
188{
189 F16Dot16 res = fixedMul(a, b);
190 return fixedDiv(res, c);
191}
192
193/*- Translate units from TT to PS (standard 1/1000) -*/
194static int XUnits(int unitsPerEm, int n)
195{
196 return (n * 1000) / unitsPerEm;
197}
198
199static char toHex(sal_uInt8 nIndex)
200{
201 /* Hex Formatter functions */
202 static const char HexChars[] = "0123456789ABCDEF";
203 assert(nIndex < SAL_N_ELEMENTS(HexChars));
204 return HexChars[nIndex];
205}
206
207static HexFmt *HexFmtNew(FILE *outf)
208{
209 HexFmt* res = static_cast<HexFmt*>(smalloc(sizeof(HexFmt)));
210 res->bufpos = res->total = 0;
211 res->o = outf;
212 return res;
213}
214
215static bool HexFmtFlush(HexFmt *_this)
216{
217 bool bRet = true;
218 if (_this->bufpos) {
219 size_t nWritten = fwrite(_this->buffer, 1, _this->bufpos, _this->o);
220 bRet = nWritten == _this->bufpos;
221 _this->bufpos = 0;
222 }
223 return bRet;
224}
225
226static void HexFmtOpenString(HexFmt *_this)
227{
228 fputs("<\n", _this->o);
229}
230
231static void HexFmtCloseString(HexFmt *_this)
232{
233 HexFmtFlush(_this);
234 fputs("00\n>\n", _this->o);
235}
236
237static void HexFmtDispose(HexFmt *_this)
238{
239 HexFmtFlush(_this);
240 free(_this);
241}
242
243static void HexFmtBlockWrite(HexFmt *_this, const void *ptr, sal_uInt32 size)
244{
245 if (_this->total + size > 65534) {
246 HexFmtFlush(_this);
247 HexFmtCloseString(_this);
248 _this->total = 0;
249 HexFmtOpenString(_this);
250 }
251
252 for (sal_uInt32 i = 0; i < size; ++i) {
253 sal_uInt8 Ch = static_cast<sal_uInt8 const *>(ptr)[i];
254 _this->buffer[_this->bufpos++] = toHex(Ch >> 4);
255 _this->buffer[_this->bufpos++] = toHex(Ch & 0xF);
256 if (_this->bufpos == HFORMAT_LINELEN) {
257 HexFmtFlush(_this);
258 fputc('\n', _this->o);
259 }
260
261 }
262 _this->total += size;
263}
264
265/* Outline Extraction functions */
266
267/* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/
268static void GetMetrics(AbstractTrueTypeFont const *ttf, sal_uInt32 glyphID, TTGlyphMetrics *metrics)
269{
270 sal_uInt32 nSize;
271 const sal_uInt8* table = ttf->table(O_hmtx, nSize);
272
273 metrics->aw = metrics->lsb = metrics->ah = 0;
274 if (!table || !ttf->horzMetricCount())
275 return;
276
277 if (glyphID < ttf->horzMetricCount())
278 {
279 metrics->aw = GetUInt16(table, 4 * glyphID);
280 metrics->lsb = GetInt16(table, 4 * glyphID + 2);
281 }
282 else
283 {
284 metrics->aw = GetUInt16(table, 4 * (ttf->horzMetricCount() - 1));
285 metrics->lsb = GetInt16(table + ttf->horzMetricCount() * 4, (glyphID - ttf->horzMetricCount()) * 2);
286 }
287
288 table = ttf->table(O_vmtx, nSize);
289 if (!table || !ttf->vertMetricCount())
290 return;
291
292 if (glyphID < ttf->vertMetricCount())
293 metrics->ah = GetUInt16(table, 4 * glyphID);
294 else
295 metrics->ah = GetUInt16(table, 4 * (ttf->vertMetricCount() - 1));
296}
297
298static int GetTTGlyphOutline(AbstractTrueTypeFont *, sal_uInt32 , ControlPoint **, TTGlyphMetrics *, std::vector< sal_uInt32 >* );
299
300/* returns the number of control points, allocates the pointArray */
301static int GetSimpleTTOutline(AbstractTrueTypeFont const *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics)
302{
303 sal_uInt32 nTableSize;
304 const sal_uInt8* table = ttf->table(O_glyf, nTableSize);
305 sal_uInt8 n;
306 int i, j, z;
307
308 *pointArray = nullptr;
309
310 if (glyphID >= ttf->glyphCount())
311 return 0;
312
313 sal_uInt32 nGlyphOffset = ttf->glyphOffset(glyphID);
314 if (nGlyphOffset > nTableSize)
315 return 0;
316
317 const sal_uInt8* ptr = table + nGlyphOffset;
318 const sal_uInt32 nMaxGlyphSize = nTableSize - nGlyphOffset;
319 constexpr sal_uInt32 nContourOffset = 10;
320 if (nMaxGlyphSize < nContourOffset)
321 return 0;
322
323 const sal_Int16 numberOfContours = GetInt16(ptr, GLYF_numberOfContours_offset);
324 if( numberOfContours <= 0 ) /*- glyph is not simple */
325 return 0;
326
327 const sal_Int32 nMaxContours = (nMaxGlyphSize - nContourOffset)/2;
328 if (numberOfContours > nMaxContours)
329 return 0;
330
331 if (metrics) { /*- GetCompoundTTOutline() calls this function with NULL metrics -*/
332 metrics->xMin = GetInt16(ptr, GLYF_xMin_offset);
333 metrics->yMin = GetInt16(ptr, GLYF_yMin_offset);
334 metrics->xMax = GetInt16(ptr, GLYF_xMax_offset);
335 metrics->yMax = GetInt16(ptr, GLYF_yMax_offset);
336 GetMetrics(ttf, glyphID, metrics);
337 }
338
339 /* determine the last point and be extra safe about it. But probably this code is not needed */
340 sal_uInt16 lastPoint=0;
341 for (i=0; i<numberOfContours; i++)
342 {
343 const sal_uInt16 t = GetUInt16(ptr, nContourOffset + i * 2);
344 if (t > lastPoint)
345 lastPoint = t;
346 }
347
348 sal_uInt32 nInstLenOffset = nContourOffset + numberOfContours * 2;
349 if (nInstLenOffset + 2 > nMaxGlyphSize)
350 return 0;
351 sal_uInt16 instLen = GetUInt16(ptr, nInstLenOffset);
352
353 sal_uInt32 nOffset = nContourOffset + 2 * numberOfContours + 2 + instLen;
354 if (nOffset > nMaxGlyphSize)
355 return 0;
356 const sal_uInt8* p = ptr + nOffset;
357
358 sal_uInt32 nBytesRemaining = nMaxGlyphSize - nOffset;
359 const sal_uInt32 palen = lastPoint+1;
360
361 //at a minimum its one byte per entry
362 if (palen > nBytesRemaining || lastPoint > nBytesRemaining-1)
363 {
364 SAL_WARN("vcl.fonts", "Font " << OUString::createFromAscii(ttf->fileName()) <<
365 "claimed a palen of "
366 << palen << " but max bytes remaining is " << nBytesRemaining);
367 return 0;
368 }
369
370 ControlPoint* pa = static_cast<ControlPoint*>(calloc(palen, sizeof(ControlPoint)));
371
372 i = 0;
373 while (i <= lastPoint) {
374 if (!nBytesRemaining)
375 {
376 SAL_WARN("vcl.fonts", "short read");
377 break;
378 }
379 sal_uInt8 flag = *p++;
380 --nBytesRemaining;
381 pa[i++].flags = static_cast<sal_uInt32>(flag);
382 if (flag & 8) { /*- repeat flag */
383 if (!nBytesRemaining)
384 {
385 SAL_WARN("vcl.fonts", "short read");
386 break;
387 }
388 n = *p++;
389 --nBytesRemaining;
390 // coverity[tainted_data : FALSE] - i > lastPoint extra checks the n loop bound
391 for (j=0; j<n; j++) {
392 if (i > lastPoint) { /*- if the font is really broken */
393 free(pa);
394 return 0;
395 }
396 pa[i++].flags = flag;
397 }
398 }
399 }
400
401 /*- Process the X coordinate */
402 z = 0;
403 for (i = 0; i <= lastPoint; i++) {
404 if (pa[i].flags & 0x02) {
405 if (!nBytesRemaining)
406 {
407 SAL_WARN("vcl.fonts", "short read");
408 break;
409 }
410 if (pa[i].flags & 0x10) {
411 z += static_cast<int>(*p++);
412 } else {
413 z -= static_cast<int>(*p++);
414 }
415 --nBytesRemaining;
416 } else if ( !(pa[i].flags & 0x10)) {
417 if (nBytesRemaining < 2)
418 {
419 SAL_WARN("vcl.fonts", "short read");
420 break;
421 }
422 z += GetInt16(p, 0);
423 p += 2;
424 nBytesRemaining -= 2;
425 }
426 pa[i].x = static_cast<sal_Int16>(z);
427 }
428
429 /*- Process the Y coordinate */
430 z = 0;
431 for (i = 0; i <= lastPoint; i++) {
432 if (pa[i].flags & 0x04) {
433 if (!nBytesRemaining)
434 {
435 SAL_WARN("vcl.fonts", "short read");
436 break;
437 }
438 if (pa[i].flags & 0x20) {
439 z += *p++;
440 } else {
441 z -= *p++;
442 }
443 --nBytesRemaining;
444 } else if ( !(pa[i].flags & 0x20)) {
445 if (nBytesRemaining < 2)
446 {
447 SAL_WARN("vcl.fonts", "short read");
448 break;
449 }
450 z += GetInt16(p, 0);
451 p += 2;
452 nBytesRemaining -= 2;
453 }
454 pa[i].y = static_cast<sal_Int16>(z);
455 }
456
457 for (i=0; i<numberOfContours; i++) {
458 sal_uInt16 offset = GetUInt16(ptr, 10 + i * 2);
459 SAL_WARN_IF(offset >= palen, "vcl.fonts", "Font " << OUString::createFromAscii(ttf->fileName()) <<
460 " contour " << i << " claimed an illegal offset of "
461 << offset << " but max offset is " << palen-1);
462 if (offset >= palen)
463 continue;
464 pa[offset].flags |= 0x00008000; /*- set the end contour flag */
465 }
466
467 *pointArray = pa;
468 return lastPoint + 1;
469}
470
471static F16Dot16 fromF2Dot14(sal_Int16 n)
472{
473 // Avoid undefined shift of negative values prior to C++2a:
474 return sal_uInt32(n) << 2;
475}
476
477static int GetCompoundTTOutline(AbstractTrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >& glyphlist)
478{
479 sal_uInt16 flags, index;
480 sal_Int16 e, f;
481 sal_uInt32 nTableSize;
482 const sal_uInt8* table = ttf->table(O_glyf, nTableSize);
483 std::vector<ControlPoint> myPoints;
484 ControlPoint *nextComponent, *pa;
485 int i, np;
486 F16Dot16 a = 0x10000, b = 0, c = 0, d = 0x10000, m, n, abs1, abs2, abs3;
487
488 *pointArray = nullptr;
489
490 if (glyphID >= ttf->glyphCount())
491 return 0;
492
493 sal_uInt32 nGlyphOffset = ttf->glyphOffset(glyphID);
494 if (nGlyphOffset > nTableSize)
495 return 0;
496
497 const sal_uInt8* ptr = table + nGlyphOffset;
498 sal_uInt32 nAvailableBytes = nTableSize - nGlyphOffset;
499
500 if (GLYF_numberOfContours_offset + 2 > nAvailableBytes)
501 return 0;
502
503 if (GetInt16(ptr, GLYF_numberOfContours_offset) != -1) /* number of contours - glyph is not compound */
504 return 0;
505
506 if (metrics) {
507 metrics->xMin = GetInt16(ptr, GLYF_xMin_offset);
508 metrics->yMin = GetInt16(ptr, GLYF_yMin_offset);
509 metrics->xMax = GetInt16(ptr, GLYF_xMax_offset);
510 metrics->yMax = GetInt16(ptr, GLYF_yMax_offset);
511 GetMetrics(ttf, glyphID, metrics);
512 }
513
514 if (nAvailableBytes < 10)
515 {
516 SAL_WARN("vcl.fonts", "short read");
517 return 0;
518 }
519
520 ptr += 10;
521 nAvailableBytes -= 10;
522
523 do {
524
525 if (nAvailableBytes < 4)
526 {
527 SAL_WARN("vcl.fonts", "short read");
528 return 0;
529 }
530 flags = GetUInt16(ptr, 0);
531 /* printf("flags: 0x%X\n", flags); */
532 index = GetUInt16(ptr, 2);
533 ptr += 4;
534 nAvailableBytes -= 4;
535
536 if( std::find( glyphlist.begin(), glyphlist.end(), index ) != glyphlist.end() )
537 {
538 SAL_WARN("vcl.fonts", "Endless loop found in a compound glyph.");
539
540#if OSL_DEBUG_LEVEL > 1
541 std::ostringstream oss;
542 oss << index << " -> [";
543 for( const auto& rGlyph : glyphlist )
544 {
545 oss << (int) rGlyph << " ";
546 }
547 oss << "]";
548 SAL_INFO("vcl.fonts", oss.str());
549
550#endif
551 return 0;
552 }
553
554 glyphlist.push_back( index );
555
556 np = GetTTGlyphOutline(ttf, index, &nextComponent, nullptr, &glyphlist);
557
558 if( ! glyphlist.empty() )
559 glyphlist.pop_back();
560
561 if (np == 0)
562 {
563 /* XXX that probably indicates a corrupted font */
564 SAL_WARN("vcl.fonts", "An empty compound!");
565 /* assert(!"An empty compound"); */
566 return 0;
567 }
568
569 if ((flags & USE_MY_METRICS) && metrics)
570 GetMetrics(ttf, index, metrics);
571
572 if (flags & ARG_1_AND_2_ARE_WORDS) {
573 if (nAvailableBytes < 4)
574 {
575 SAL_WARN("vcl.fonts", "short read");
576 free(nextComponent);
577 return 0;
578 }
579 e = GetInt16(ptr, 0);
580 f = GetInt16(ptr, 2);
581 /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */
582 ptr += 4;
583 nAvailableBytes -= 4;
584 } else {
585 if (nAvailableBytes < 2)
586 {
587 SAL_WARN("vcl.fonts", "short read");
588 free(nextComponent);
589 return 0;
590 }
591 if (flags & ARGS_ARE_XY_VALUES) { /* args are signed */
592 e = static_cast<sal_Int8>(*ptr++);
593 f = static_cast<sal_Int8>(*ptr++);
594 /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */
595 } else { /* args are unsigned */
596 /* printf("!ARGS_ARE_XY_VALUES\n"); */
597 e = *ptr++;
598 f = *ptr++;
599 }
600 nAvailableBytes -= 2;
601 }
602
603 a = d = 0x10000;
604 b = c = 0;
605
606 if (flags & WE_HAVE_A_SCALE) {
607 if (nAvailableBytes < 2)
608 {
609 SAL_WARN("vcl.fonts", "short read");
610 free(nextComponent);
611 return 0;
612 }
613 a = fromF2Dot14(GetInt16(ptr, 0));
614 d = a;
615 ptr += 2;
616 nAvailableBytes -= 2;
617 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
618 if (nAvailableBytes < 4)
619 {
620 SAL_WARN("vcl.fonts", "short read");
621 free(nextComponent);
622 return 0;
623 }
624 a = fromF2Dot14(GetInt16(ptr, 0));
625 d = fromF2Dot14(GetInt16(ptr, 2));
626 ptr += 4;
627 nAvailableBytes -= 4;
628 } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
629 if (nAvailableBytes < 8)
630 {
631 SAL_WARN("vcl.fonts", "short read");
632 free(nextComponent);
633 return 0;
634 }
635 a = fromF2Dot14(GetInt16(ptr, 0));
636 b = fromF2Dot14(GetInt16(ptr, 2));
637 c = fromF2Dot14(GetInt16(ptr, 4));
638 d = fromF2Dot14(GetInt16(ptr, 6));
639 ptr += 8;
640 nAvailableBytes -= 8;
641 }
642
643 abs1 = (a < 0) ? -a : a;
644 abs2 = (b < 0) ? -b : b;
645 m = std::max(abs1, abs2);
646 abs3 = abs1 - abs2;
647 if (abs3 < 0) abs3 = -abs3;
648 if (abs3 <= 33) m *= 2;
649
650 abs1 = (c < 0) ? -c : c;
651 abs2 = (d < 0) ? -d : d;
652 n = std::max(abs1, abs2);
653 abs3 = abs1 - abs2;
654 if (abs3 < 0) abs3 = -abs3;
655 if (abs3 <= 33) n *= 2;
656
657 SAL_WARN_IF(np && (!m || !n), "vcl.fonts", "Parsing error in " << OUString::createFromAscii(ttf->fileName()) <<
658 ": divide by zero");
659
660 if (m != 0 && n != 0) {
661 for (i=0; i<np; i++) {
662 F16Dot16 t;
663 ControlPoint cp;
664 cp.flags = nextComponent[i].flags;
665 const sal_uInt16 x = nextComponent[i].x;
666 const sal_uInt16 y = nextComponent[i].y;
667 t = o3tl::saturating_add(o3tl::saturating_add(fixedMulDiv(a, x << 16, m), fixedMulDiv(c, y << 16, m)), sal_Int32(sal_uInt16(e) << 16));
668 cp.x = static_cast<sal_Int16>(fixedMul(t, m) >> 16);
669 t = o3tl::saturating_add(o3tl::saturating_add(fixedMulDiv(b, x << 16, n), fixedMulDiv(d, y << 16, n)), sal_Int32(sal_uInt16(f) << 16));
670 cp.y = static_cast<sal_Int16>(fixedMul(t, n) >> 16);
671
672 myPoints.push_back( cp );
673 }
674 }
675
676 free(nextComponent);
677
678 } while (flags & MORE_COMPONENTS);
679
680 // #i123417# some fonts like IFAOGrec have no outline points in some compound glyphs
681 // so this unlikely but possible scenario should be handled gracefully
682 if( myPoints.empty() )
683 return 0;
684
685 np = myPoints.size();
686 if (np > 0)
687 {
688 pa = static_cast<ControlPoint*>(calloc(np, sizeof(ControlPoint)));
689 assert(pa != nullptr);
690
691 memcpy(pa, myPoints.data(), np * sizeof(ControlPoint));
692
693 *pointArray = pa;
694 }
695 return np;
696}
697
698/* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect,
699 * but Get{Simple|Compound}GlyphOutline returns 0 in such a case.
700 *
701 * NOTE: glyphlist is the stack of glyphs traversed while constructing
702 * a composite glyph. This is a safeguard against endless recursion
703 * in corrupted fonts.
704 */
705static int GetTTGlyphOutline(AbstractTrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >* glyphlist)
706{
707 sal_uInt32 glyflength;
708 const sal_uInt8 *table = ttf->table(O_glyf, glyflength);
709 sal_Int16 numberOfContours;
710 int res;
711 *pointArray = nullptr;
712
713 if (metrics)
714 memset(metrics, 0, sizeof(TTGlyphMetrics));
715
716 if (glyphID >= ttf->glyphCount())
717 return -1;
718
719 sal_uInt32 nNextOffset = ttf->glyphOffset(glyphID + 1);
720 if (nNextOffset > glyflength)
721 return -1;
722
723 sal_uInt32 nOffset = ttf->glyphOffset(glyphID);
724 if (nOffset > nNextOffset)
725 return -1;
726
727 int length = nNextOffset - nOffset;
728 if (length == 0) { /*- empty glyphs still have hmtx and vmtx metrics values */
729 if (metrics) GetMetrics(ttf, glyphID, metrics);
730 return 0;
731 }
732
733 const sal_uInt8* ptr = table + nOffset;
734 const sal_uInt32 nMaxGlyphSize = glyflength - nOffset;
735
736 if (nMaxGlyphSize < 2)
737 return -1;
738
739 numberOfContours = GetInt16(ptr, 0);
740
741 if (numberOfContours >= 0)
742 {
743 res=GetSimpleTTOutline(ttf, glyphID, pointArray, metrics);
744 }
745 else
746 {
747 std::vector< sal_uInt32 > aPrivList { glyphID };
748 res = GetCompoundTTOutline(ttf, glyphID, pointArray, metrics, glyphlist ? *glyphlist : aPrivList );
749 }
750
751 return res;
752}
753
754/*- returns the number of items in the path -*/
755
756static int BSplineToPSPath(ControlPoint const *srcA, int srcCount, PSPathElement **path)
757{
758 std::vector< PSPathElement > aPathList;
759 int nPathCount = 0;
760 PSPathElement p( PS_NOOP );
761
762 int x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2, y2, curx, cury;
763 bool lastOff = false; /*- last point was off-contour */
764 int scflag = 1; /*- start contour flag */
765 bool ecflag = false; /*- end contour flag */
766 int cp = 0; /*- current point */
767 int StartContour = 0, EndContour = 1;
768
769 *path = nullptr;
770
771 /* if (srcCount > 0) for(;;) */
772 while (srcCount > 0) { /*- srcCount does not get changed inside the loop. */
773 if (scflag) {
774 int l = cp;
775 StartContour = cp;
776 while (!(srcA[l].flags & 0x8000)) l++;
777 EndContour = l;
778 if (StartContour == EndContour) {
779 if (cp + 1 < srcCount) {
780 cp++;
781 continue;
782 } else {
783 break;
784 }
785 }
786 p = PSPathElement(PS_MOVETO);
787 if (!(srcA[cp].flags & 1)) {
788 if (!(srcA[EndContour].flags & 1)) {
789 p.x1 = x0 = (srcA[cp].x + srcA[EndContour].x + 1) / 2;
790 p.y1 = y0 = (srcA[cp].y + srcA[EndContour].y + 1) / 2;
791 } else {
792 p.x1 = x0 = srcA[EndContour].x;
793 p.y1 = y0 = srcA[EndContour].y;
794 }
795 } else {
796 p.x1 = x0 = srcA[cp].x;
797 p.y1 = y0 = srcA[cp].y;
798 cp++;
799 }
800 aPathList.push_back( p );
801 lastOff = false;
802 scflag = 0;
803 }
804
805 curx = srcA[cp].x;
806 cury = srcA[cp].y;
807
808 if (srcA[cp].flags & 1)
809 {
810 if (lastOff)
811 {
812 p = PSPathElement(PS_CURVETO);
813 p.x1 = x0 + (2 * (x1 - x0) + 1) / 3;
814 p.y1 = y0 + (2 * (y1 - y0) + 1) / 3;
815 p.x2 = x1 + (curx - x1 + 1) / 3;
816 p.y2 = y1 + (cury - y1 + 1) / 3;
817 p.x3 = curx;
818 p.y3 = cury;
819 aPathList.push_back( p );
820 }
821 else
822 {
823 if (x0 != curx || y0 != cury)
824 { /* eliminate empty lines */
825 p = PSPathElement(PS_LINETO);
826 p.x1 = curx;
827 p.y1 = cury;
828 aPathList.push_back( p );
829 }
830 }
831 x0 = curx; y0 = cury; lastOff = false;
832 }
833 else
834 {
835 if (lastOff)
836 {
837 x2 = (x1 + curx + 1) / 2;
838 y2 = (y1 + cury + 1) / 2;
839 p = PSPathElement(PS_CURVETO);
840 p.x1 = x0 + (2 * (x1 - x0) + 1) / 3;
841 p.y1 = y0 + (2 * (y1 - y0) + 1) / 3;
842 p.x2 = x1 + (x2 - x1 + 1) / 3;
843 p.y2 = y1 + (y2 - y1 + 1) / 3;
844 p.x3 = x2;
845 p.y3 = y2;
846 aPathList.push_back( p );
847 x0 = x2; y0 = y2;
848 x1 = curx; y1 = cury;
849 } else {
850 x1 = curx; y1 = cury;
851 }
852 lastOff = true;
853 }
854
855 if (ecflag) {
856 aPathList.emplace_back(PS_CLOSEPATH );
857 scflag = 1;
858 ecflag = false;
859 cp = EndContour + 1;
860 if (cp >= srcCount) break;
861 continue;
862 }
863
864 if (cp == EndContour) {
865 cp = StartContour;
866 ecflag = true;
867 } else {
868 cp++;
869 }
870 }
871
872 if( (nPathCount = static_cast<int>(aPathList.size())) > 0)
873 {
874 *path = static_cast<PSPathElement*>(calloc(nPathCount, sizeof(PSPathElement)));
875 assert(*path != nullptr);
876 memcpy( *path, aPathList.data(), nPathCount * sizeof(PSPathElement) );
877 }
878
879 return nPathCount;
880}
881
882/*- Extracts a string from the name table and allocates memory for it -*/
883
884static char *nameExtract( const sal_uInt8* name, int nTableSize, int n, int dbFlag, sal_Unicode** ucs2result )
885{
886 char *res;
887 const sal_uInt8* ptr = name + GetUInt16(name, 4) + GetUInt16(name + 6, 12 * n + 10);
888 int len = GetUInt16(name+6, 12 * n + 8);
889
890 // sanity check
891 const sal_uInt8* end_table = name+nTableSize;
892 const int available_space = ptr > end_table ? 0 : (end_table - ptr);
893 if( (len <= 0) || len > available_space)
894 {
895 if( ucs2result )
896 *ucs2result = nullptr;
897 return nullptr;
898 }
899
900 if( ucs2result )
901 *ucs2result = nullptr;
902 if (dbFlag) {
903 res = static_cast<char*>(malloc(1 + len/2));
904 assert(res != nullptr);
905 for (int i = 0; i < len/2; i++)
906 res[i] = *(ptr + i * 2 + 1);
907 res[len/2] = 0;
908 if( ucs2result )
909 {
910 *ucs2result = static_cast<sal_Unicode*>(malloc( len+2 ));
911 for (int i = 0; i < len/2; i++ )
912 (*ucs2result)[i] = GetUInt16( ptr, 2*i );
913 (*ucs2result)[len/2] = 0;
914 }
915 } else {
916 res = static_cast<char*>(malloc(1 + len));
917 assert(res != nullptr);
918 memcpy(res, ptr, len);
919 res[len] = 0;
920 }
921
922 return res;
923}
924
925static int findname( const sal_uInt8 *name, sal_uInt16 n, sal_uInt16 platformID,
926 sal_uInt16 encodingID, sal_uInt16 languageID, sal_uInt16 nameID )
927{
928 if (n == 0) return -1;
929
930 int l = 0, r = n-1;
931 sal_uInt32 t1, t2;
932 sal_uInt32 m1, m2;
933
934 m1 = (platformID << 16) | encodingID;
935 m2 = (languageID << 16) | nameID;
936
937 do {
938 const int i = (l + r) >> 1;
939 t1 = GetUInt32(name + 6, i * 12 + 0);
940 t2 = GetUInt32(name + 6, i * 12 + 4);
941
942 if (! ((m1 < t1) || ((m1 == t1) && (m2 < t2)))) l = i + 1;
943 if (! ((m1 > t1) || ((m1 == t1) && (m2 > t2)))) r = i - 1;
944 } while (l <= r);
945
946 if (l - r == 2) {
947 return l - 1;
948 }
949
950 return -1;
951}
952
953/* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables.
954 * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033)
955 *
956 * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0)
957 * and does not have (3, 1, 1033)
958 * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will
959 * require a change in algorithm
960 *
961 * /d/fonts/fdltest/Korean/h2drrm has unsorted names and an unknown (to me) Mac LanguageID,
962 * but (1, 0, 1042) strings usable
963 * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found
964 */
965
966static void GetNames(TrueTypeFont *t)
967{
968 sal_uInt32 nTableSize;
969 const sal_uInt8* table = t->table(O_name, nTableSize);
970
971 if (nTableSize < 6)
972 {
973#if OSL_DEBUG_LEVEL > 1
974 SAL_WARN("vcl.fonts", "O_name table too small.");
975#endif
976 return;
977 }
978
979 sal_uInt16 n = GetUInt16(table, 2);
980
981 /* simple sanity check for name table entry count */
982 const size_t nMinRecordSize = 12;
983 const size_t nSpaceAvailable = nTableSize - 6;
984 const size_t nMaxRecords = nSpaceAvailable/nMinRecordSize;
985 if (n >= nMaxRecords)
986 n = 0;
987
988 int i, r;
989 bool bPSNameOK = true;
990
991 /* PostScript name: preferred Microsoft */
992 t->psname = nullptr;
993 if ((r = findname(table, n, 3, 1, 0x0409, 6)) != -1)
994 t->psname = nameExtract(table, nTableSize, r, 1, nullptr);
995 if ( ! t->psname && (r = findname(table, n, 1, 0, 0, 6)) != -1)
996 t->psname = nameExtract(table, nTableSize, r, 0, nullptr);
997 if ( ! t->psname && (r = findname(table, n, 3, 0, 0x0409, 6)) != -1)
998 {
999 // some symbol fonts like Marlett have a 3,0 name!
1000 t->psname = nameExtract(table, nTableSize, r, 1, nullptr);
1001 }
1002 // for embedded font in Ghostscript PDFs
1003 if ( ! t->psname && (r = findname(table, n, 2, 2, 0, 6)) != -1)
1004 {
1005 t->psname = nameExtract(table, nTableSize, r, 0, nullptr);
1006 }
1007 if ( ! t->psname )
1008 {
1009 if (!t->fileName().empty())
1010 {
1011 const char* pReverse = t->fileName().data() + t->fileName().length();
1012 /* take only last token of filename */
1013 while (pReverse != t->fileName() && *pReverse != '/') pReverse--;
1014 if(*pReverse == '/') pReverse++;
1015 t->psname = strdup(pReverse);
1016 assert(t->psname != nullptr);
1017 for (i=strlen(t->psname) - 1; i > 0; i--)
1018 {
1019 /*- Remove the suffix -*/
1020 if (t->psname[i] == '.' ) {
1021 t->psname[i] = 0;
1022 break;
1023 }
1024 }
1025 }
1026 else
1027 t->psname = strdup( "Unknown" );
1028 }
1029
1030 /* Font family and subfamily names: preferred Apple */
1031 t->family = nullptr;
1032 if ((r = findname(table, n, 0, 0, 0, 1)) != -1)
1033 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
1034 if ( ! t->family && (r = findname(table, n, 3, 1, 0x0409, 1)) != -1)
1035 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
1036 if ( ! t->family && (r = findname(table, n, 1, 0, 0, 1)) != -1)
1037 t->family = nameExtract(table, nTableSize, r, 0, nullptr);
1038 if ( ! t->family && (r = findname(table, n, 3, 1, 0x0411, 1)) != -1)
1039 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
1040 if ( ! t->family && (r = findname(table, n, 3, 0, 0x0409, 1)) != -1)
1041 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
1042 if ( ! t->family )
1043 {
1044 t->family = strdup(t->psname);
1045 assert(t->family != nullptr);
1046 }
1047
1048 t->subfamily = nullptr;
1049 t->usubfamily = nullptr;
1050 if ((r = findname(table, n, 1, 0, 0, 2)) != -1)
1051 t->subfamily = nameExtract(table, nTableSize, r, 0, &t->usubfamily);
1052 if ( ! t->subfamily && (r = findname(table, n, 3, 1, 0x0409, 2)) != -1)
1053 t->subfamily = nameExtract(table, nTableSize, r, 1, &t->usubfamily);
1054 if ( ! t->subfamily )
1055 {
1056 t->subfamily = strdup("");
1057 }
1058
1059 /* #i60349# sanity check psname
1060 * psname practically has to be 7bit ASCII and should not contain spaces
1061 * there is a class of broken fonts which do not fulfill that at all, so let's try
1062 * if the family name is 7bit ASCII and take it instead if so
1063 */
1064 /* check psname */
1065 for( i = 0; t->psname[i] != 0 && bPSNameOK; i++ )
1066 if( t->psname[ i ] < 33 || (t->psname[ i ] & 0x80) )
1067 bPSNameOK = false;
1068 if( bPSNameOK )
1069 return;
1070
1071 /* check if family is a suitable replacement */
1072 if( !(t->ufamily && t->family) )
1073 return;
1074
1075 bool bReplace = true;
1076
1077 for( i = 0; t->ufamily[ i ] != 0 && bReplace; i++ )
1078 if( t->ufamily[ i ] < 33 || t->ufamily[ i ] > 127 )
1079 bReplace = false;
1080 if( bReplace )
1081 {
1082 free( t->psname );
1083 t->psname = strdup( t->family );
1084 }
1085}
1086
1087/*- Public functions */
1088
1089int CountTTCFonts(const char* fname)
1090{
1091 int nFonts = 0;
1092 sal_uInt8 buffer[12];
1093 FILE* fd = fopen(fname, "rb");
1094 if( fd ) {
1095 if (fread(buffer, 1, 12, fd) == 12) {
1096 if(GetUInt32(buffer, 0) == T_ttcf )
1097 nFonts = GetUInt32(buffer, 8);
1098 }
1099 fclose(fd);
1100 }
1101 return nFonts;
1102}
1103
1104#if !defined(_WIN32)
1105SFErrCodes OpenTTFontFile(const char* fname, sal_uInt32 facenum, TrueTypeFont** ttf,
1106 const FontCharMapRef xCharMap)
1107{
1108 SFErrCodes ret;
1109 int fd = -1;
1110 struct stat st;
1111
1112 if (!fname || !*fname) return SFErrCodes::BadFile;
1113
1114 *ttf = new TrueTypeFont(fname, xCharMap);
1115 if( ! *ttf )
1116 return SFErrCodes::Memory;
1117
1118 if( (*ttf)->fileName().empty() )
1119 {
1120 ret = SFErrCodes::Memory;
1121 goto cleanup;
1122 }
1123
1124 fd = open(fname, O_RDONLY);
1125
1126 if (fd == -1) {
1127 ret = SFErrCodes::BadFile;
1128 goto cleanup;
1129 }
1130
1131 if (fstat(fd, &st) == -1) {
1132 ret = SFErrCodes::FileIo;
1133 goto cleanup;
1134 }
1135
1136 (*ttf)->fsize = st.st_size;
1137
1138 /* On Mac OS, most likely will happen if a Mac user renames a font file
1139 * to be .ttf when it's really a Mac resource-based font.
1140 * Size will be 0, but fonts smaller than 4 bytes would be broken anyway.
1141 */
1142 if ((*ttf)->fsize == 0) {
1143 ret = SFErrCodes::BadFile;
1144 goto cleanup;
1145 }
1146
1147 if (((*ttf)->ptr = static_cast<sal_uInt8 *>(mmap(nullptr, (*ttf)->fsize, PROT_READ, MAP_SHARED, fd, 0))) == MAP_FAILED) {
1148 ret = SFErrCodes::Memory;
1149 goto cleanup;
1150 }
1151
1152 ret = (*ttf)->open(facenum);
1153
1154cleanup:
1155 if (fd != -1) close(fd);
1156 if (ret != SFErrCodes::Ok)
1157 {
1158 delete *ttf;
1159 *ttf = nullptr;
1160 }
1161 return ret;
1162}
1163#endif
1164
1165SFErrCodes OpenTTFontBuffer(const void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont** ttf,
1166 const FontCharMapRef xCharMap)
1167{
1168 *ttf = new TrueTypeFont(nullptr, xCharMap);
1169 if( *ttf == nullptr )
1170 return SFErrCodes::Memory;
1171
1172 (*ttf)->fsize = nLen;
1173 (*ttf)->ptr = const_cast<sal_uInt8 *>(static_cast<sal_uInt8 const *>(pBuffer));
1174
1175 SFErrCodes ret = (*ttf)->open(facenum);
1176 if (ret != SFErrCodes::Ok)
1177 {
1178 delete *ttf;
1179 *ttf = nullptr;
1180 }
1181 return ret;
1182}
1183
1184namespace {
1185
1186bool withinBounds(sal_uInt32 tdoffset, sal_uInt32 moreoffset, sal_uInt32 len, sal_uInt32 available)
1187{
1188 sal_uInt32 result;
1189 if (o3tl::checked_add(tdoffset, moreoffset, result))
1190 return false;
1191 if (o3tl::checked_add(result, len, result))
1192 return false;
1193 return result <= available;
1194}
1195}
1196
1198 : m_nGlyphs(0xFFFFFFFF)
1199 , m_nHorzMetrics(0)
1200 , m_nVertMetrics(0)
1201 , m_nUnitsPerEm(0)
1202 , m_xCharMap(xCharMap)
1203{
1204 if (pFileName)
1205 m_sFileName = pFileName;
1206}
1207
1209{
1210}
1211
1212TrueTypeFont::TrueTypeFont(const char* pFileName, const FontCharMapRef xCharMap)
1213 : AbstractTrueTypeFont(pFileName, xCharMap)
1214 , fsize(-1)
1215 , ptr(nullptr)
1216 , psname(nullptr)
1217 , family(nullptr)
1218 , ufamily(nullptr)
1219 , subfamily(nullptr)
1220 , usubfamily(nullptr)
1221 , ntables(0)
1222{
1223}
1224
1226{
1227#if !defined(_WIN32)
1228 if (!fileName().empty())
1229 munmap(ptr, fsize);
1230#endif
1231 free(psname);
1232 free(family);
1233 free(ufamily);
1234 free(subfamily);
1235 free(usubfamily);
1236}
1237
1238void CloseTTFont(TrueTypeFont* ttf) { delete ttf; }
1239
1240sal_uInt32 AbstractTrueTypeFont::glyphOffset(sal_uInt32 glyphID) const
1241{
1242 if (m_aGlyphOffsets.empty()) // the O_CFF and Bitmap cases
1243 return 0;
1244 return m_aGlyphOffsets[glyphID];
1245}
1246
1248{
1250 return SFErrCodes::TtFormat;
1251
1252 sal_uInt32 table_size;
1253 const sal_uInt8* table = this->table(O_maxp, table_size);
1254 m_nGlyphs = table_size >= 6 ? GetUInt16(table, 4) : 0;
1255
1256 table = this->table(O_head, table_size);
1257 if (table_size < HEAD_Length)
1258 return SFErrCodes::TtFormat;
1259
1262
1263 if (((indexfmt != 0) && (indexfmt != 1)) || (m_nUnitsPerEm <= 0))
1264 return SFErrCodes::TtFormat;
1265
1266 if (hasTable(O_glyf) && (table = this->table(O_loca, table_size))) /* TTF or TTF-OpenType */
1267 {
1268 int k = (table_size / (indexfmt ? 4 : 2)) - 1;
1269 if (k < static_cast<int>(m_nGlyphs)) /* Hack for broken Chinese fonts */
1270 m_nGlyphs = k;
1271
1272 m_aGlyphOffsets.clear();
1273 m_aGlyphOffsets.reserve(m_nGlyphs + 1);
1274 for (int i = 0; i <= static_cast<int>(m_nGlyphs); ++i)
1275 m_aGlyphOffsets.push_back(indexfmt ? GetUInt32(table, i << 2) : static_cast<sal_uInt32>(GetUInt16(table, i << 1)) << 1);
1276 }
1277 else if (this->table(O_CFF, table_size)) /* PS-OpenType */
1278 {
1279 int k = (table_size / 2) - 1; /* set a limit here, presumably much lower than the table size, but establishes some sort of physical bound */
1280 if (k < static_cast<int>(m_nGlyphs))
1281 m_nGlyphs = k;
1282
1283 m_aGlyphOffsets.clear();
1284 /* TODO: implement to get subsetting */
1285 }
1286 else {
1287 // Bitmap font, accept for now.
1288 m_aGlyphOffsets.clear();
1289 /* TODO: implement to get subsetting */
1290 }
1291
1292 table = this->table(O_hhea, table_size);
1293 m_nHorzMetrics = (table && table_size >= 36) ? GetUInt16(table, 34) : 0;
1294
1295 table = this->table(O_vhea, table_size);
1296 m_nVertMetrics = (table && table_size >= 36) ? GetUInt16(table, 34) : 0;
1297
1298 if (!m_xCharMap.is())
1299 {
1300 CmapResult aCmapResult;
1301 table = this->table(O_cmap, table_size);
1302 if (!ParseCMAP(table, table_size, aCmapResult))
1303 return SFErrCodes::TtFormat;
1304 m_xCharMap = new FontCharMap(aCmapResult);
1305 }
1306
1307 return SFErrCodes::Ok;
1308}
1309
1311{
1312 if (fsize < 4)
1313 return SFErrCodes::TtFormat;
1314
1315 int i;
1316 sal_uInt32 length, tag;
1317 sal_uInt32 tdoffset = 0; /* offset to TableDirectory in a TTC file. For TTF files is 0 */
1318
1319 sal_uInt32 TTCTag = GetInt32(ptr, 0);
1320
1321 if ((TTCTag == 0x00010000) || (TTCTag == T_true)) {
1322 tdoffset = 0;
1323 } else if (TTCTag == T_otto) { /* PS-OpenType font */
1324 tdoffset = 0;
1325 } else if (TTCTag == T_ttcf) { /* TrueType collection */
1326 if (!withinBounds(12, 4 * facenum, sizeof(sal_uInt32), fsize))
1327 return SFErrCodes::FontNo;
1328 sal_uInt32 Version = GetUInt32(ptr, 4);
1329 if (Version != 0x00010000 && Version != 0x00020000) {
1330 return SFErrCodes::TtFormat;
1331 }
1332 if (facenum >= GetUInt32(ptr, 8))
1333 return SFErrCodes::FontNo;
1334 tdoffset = GetUInt32(ptr, 12 + 4 * facenum);
1335 } else {
1336 return SFErrCodes::TtFormat;
1337 }
1338
1339 if (withinBounds(tdoffset, 0, 4 + sizeof(sal_uInt16), fsize))
1340 ntables = GetUInt16(ptr + tdoffset, 4);
1341
1342 if (ntables >= 128 || ntables == 0)
1343 return SFErrCodes::TtFormat;
1344
1345 /* parse the tables */
1346 for (i = 0; i < static_cast<int>(ntables); i++)
1347 {
1348 int nIndex;
1349 const sal_uInt32 nStart = tdoffset + 12;
1350 const sal_uInt32 nOffset = 16 * i;
1351 if (withinBounds(nStart, nOffset, sizeof(sal_uInt32), fsize))
1352 tag = GetUInt32(ptr + nStart, nOffset);
1353 else
1354 tag = static_cast<sal_uInt32>(-1);
1355 switch( tag ) {
1356 case T_maxp: nIndex = O_maxp; break;
1357 case T_glyf: nIndex = O_glyf; break;
1358 case T_head: nIndex = O_head; break;
1359 case T_loca: nIndex = O_loca; break;
1360 case T_name: nIndex = O_name; break;
1361 case T_hhea: nIndex = O_hhea; break;
1362 case T_hmtx: nIndex = O_hmtx; break;
1363 case T_cmap: nIndex = O_cmap; break;
1364 case T_vhea: nIndex = O_vhea; break;
1365 case T_vmtx: nIndex = O_vmtx; break;
1366 case T_OS2 : nIndex = O_OS2; break;
1367 case T_post: nIndex = O_post; break;
1368 case T_cvt : nIndex = O_cvt; break;
1369 case T_prep: nIndex = O_prep; break;
1370 case T_fpgm: nIndex = O_fpgm; break;
1371 case T_gsub: nIndex = O_gsub; break;
1372 case T_CFF: nIndex = O_CFF; break;
1373 default: nIndex = -1; break;
1374 }
1375
1376 if ((nIndex >= 0) && withinBounds(nStart, nOffset, 12 + sizeof(sal_uInt32), fsize))
1377 {
1378 sal_uInt32 nTableOffset = GetUInt32(ptr + nStart, nOffset + 8);
1379 length = GetUInt32(ptr + nStart, nOffset + 12);
1380 m_aTableList[nIndex].pData = ptr + nTableOffset;
1381 m_aTableList[nIndex].nSize = length;
1382 }
1383 }
1384
1385 /* Fixup offsets when only a TTC extract was provided */
1386 if (facenum == sal_uInt32(~0))
1387 {
1388 sal_uInt8* pHead = const_cast<sal_uInt8*>(m_aTableList[O_head].pData);
1389 if (!pHead)
1390 return SFErrCodes::TtFormat;
1391
1392 /* limit Head candidate to TTC extract's limits */
1393 if (pHead > ptr + (fsize - 54))
1394 pHead = ptr + (fsize - 54);
1395
1396 /* TODO: find better method than searching head table's magic */
1397 sal_uInt8* p = nullptr;
1398 for (p = pHead + 12; p > ptr; --p)
1399 {
1400 if( p[0]==0x5F && p[1]==0x0F && p[2]==0x3C && p[3]==0xF5 ) {
1401 int nDelta = (pHead + 12) - p;
1402 if( nDelta )
1403 for( int j = 0; j < NUM_TAGS; ++j )
1404 if (hasTable(j))
1405 m_aTableList[j].pData -= nDelta;
1406 break;
1407 }
1408 }
1409 if (p <= ptr)
1410 return SFErrCodes::TtFormat;
1411 }
1412
1413 /* Check the table offsets after TTC correction */
1414 for (i=0; i<NUM_TAGS; i++) {
1415 /* sanity check: table must lay completely within the file
1416 * at this point one could check the checksum of all contained
1417 * tables, but this would be quite time intensive.
1418 * Try to fix tables, so we can cope with minor problems.
1419 */
1420
1421 if (m_aTableList[i].pData < ptr)
1422 {
1423#if OSL_DEBUG_LEVEL > 1
1424 SAL_WARN_IF(m_aTableList[i].pData, "vcl.fonts", "font file " << fileName()
1425 << " has bad table offset "
1427 << "d (tagnum=" << i << ").");
1428#endif
1429 m_aTableList[i].nSize = 0;
1430 m_aTableList[i].pData = nullptr;
1431 }
1432 else if (const_cast<sal_uInt8*>(m_aTableList[i].pData) + m_aTableList[i].nSize > ptr + fsize)
1433 {
1434 sal_PtrDiff nMaxLen = (ptr + fsize) - m_aTableList[i].pData;
1435 if( nMaxLen < 0 )
1436 nMaxLen = 0;
1437 m_aTableList[i].nSize = nMaxLen;
1438#if OSL_DEBUG_LEVEL > 1
1439 SAL_WARN("vcl.fonts", "font file " << fileName()
1440 << " has too big table (tagnum=" << i << ").");
1441#endif
1442 }
1443 }
1444
1445 /* At this point TrueTypeFont is constructed, now need to verify the font format
1446 and read the basic font properties */
1447
1448 SFErrCodes ret = indexGlyphData();
1449 if (ret != SFErrCodes::Ok)
1450 return ret;
1451
1452 GetNames(this);
1453
1454 return SFErrCodes::Ok;
1455}
1456
1457int GetTTGlyphPoints(AbstractTrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray)
1458{
1459 return GetTTGlyphOutline(ttf, glyphID, pointArray, nullptr, nullptr);
1460}
1461
1462int GetTTGlyphComponents(AbstractTrueTypeFont *ttf, sal_uInt32 glyphID, std::vector< sal_uInt32 >& glyphlist)
1463{
1464 int n = 1;
1465
1466 if (glyphID >= ttf->glyphCount())
1467 return 0;
1468
1469 sal_uInt32 glyflength;
1470 const sal_uInt8* glyf = ttf->table(O_glyf, glyflength);
1471
1472 sal_uInt32 nNextOffset = ttf->glyphOffset(glyphID + 1);
1473 if (nNextOffset > glyflength)
1474 return 0;
1475
1476 sal_uInt32 nOffset = ttf->glyphOffset(glyphID);
1477 if (nOffset > nNextOffset)
1478 return 0;
1479
1480 const sal_uInt8* ptr = glyf + nOffset;
1481 const sal_uInt8* nptr = glyf + nNextOffset;
1482 if (nptr <= ptr)
1483 return 0;
1484
1485 if (std::find(glyphlist.begin(), glyphlist.end(), glyphID) != glyphlist.end())
1486 {
1487 SAL_WARN("vcl.fonts", "Endless loop found in a compound glyph.");
1488 return 0;
1489 }
1490
1491 glyphlist.push_back( glyphID );
1492
1493 sal_uInt32 nRemainingData = glyflength - nOffset;
1494
1495 if (nRemainingData >= 10 && GetInt16(ptr, 0) == -1) {
1496 sal_uInt16 flags, index;
1497 ptr += 10;
1498 nRemainingData -= 10;
1499 do {
1500 if (nRemainingData < 4)
1501 {
1502 SAL_WARN("vcl.fonts", "short read");
1503 break;
1504 }
1505 flags = GetUInt16(ptr, 0);
1506 index = GetUInt16(ptr, 2);
1507
1508 ptr += 4;
1509 nRemainingData -= 4;
1510 n += GetTTGlyphComponents(ttf, index, glyphlist);
1511
1512 sal_uInt32 nAdvance;
1513 if (flags & ARG_1_AND_2_ARE_WORDS) {
1514 nAdvance = 4;
1515 } else {
1516 nAdvance = 2;
1517 }
1518
1519 if (flags & WE_HAVE_A_SCALE) {
1520 nAdvance += 2;
1521 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
1522 nAdvance += 4;
1523 } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
1524 nAdvance += 8;
1525 }
1526 if (nRemainingData < nAdvance)
1527 {
1528 SAL_WARN("vcl.fonts", "short read");
1529 break;
1530 }
1531 ptr += nAdvance;
1532 nRemainingData -= nAdvance;
1533 } while (flags & MORE_COMPONENTS);
1534 }
1535
1536 return n;
1537}
1538
1539SFErrCodes CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname,
1540 sal_uInt16 const *glyphArray, sal_uInt8 *encoding, int nGlyphs,
1541 int wmode)
1542{
1543 ControlPoint *pa;
1544 PSPathElement *path;
1545 int i, j, n;
1546 sal_uInt32 nSize;
1547 const sal_uInt8* table = ttf->table(O_head, nSize);
1548 TTGlyphMetrics metrics;
1549 int UPEm = ttf->unitsPerEm();
1550
1551 const char * const h01 = "%%!PS-AdobeFont-%d.%d-%d.%d\n";
1552 const char * const h02 = "%% Creator: %s %s %s\n";
1553 const char * const h09 = "%% Original font name: %s\n";
1554
1555 const char * const h10 =
1556 "30 dict begin\n"
1557 "/PaintType 0 def\n"
1558 "/FontType 3 def\n"
1559 "/StrokeWidth 0 def\n";
1560
1561 const char * const h11 = "/FontName (%s) cvn def\n";
1562
1563 /*
1564 const char *h12 = "%/UniqueID %d def\n";
1565 */
1566 const char * const h13 = "/FontMatrix [.001 0 0 .001 0 0] def\n";
1567 const char * const h14 = "/FontBBox [%d %d %d %d] def\n";
1568
1569 const char * const h15=
1570 "/Encoding 256 array def\n"
1571 " 0 1 255 {Encoding exch /.notdef put} for\n";
1572
1573 const char * const h16 = " Encoding %d /glyph%d put\n";
1574 const char * const h17 = "/XUID [103 0 0 16#%08" SAL_PRIXUINT32 " %d 16#%08" SAL_PRIXUINT32 " 16#%08" SAL_PRIXUINT32 "] def\n";
1575
1576 const char * const h30 = "/CharProcs %d dict def\n";
1577 const char * const h31 = " CharProcs begin\n";
1578 const char * const h32 = " /.notdef {} def\n";
1579 const char * const h33 = " /glyph%d {\n";
1580 const char * const h34 = " } bind def\n";
1581 const char * const h35 = " end\n";
1582
1583 const char * const h40 =
1584 "/BuildGlyph {\n"
1585 " exch /CharProcs get exch\n"
1586 " 2 copy known not\n"
1587 " {pop /.notdef} if\n"
1588 " get exec\n"
1589 "} bind def\n"
1590 "/BuildChar {\n"
1591 " 1 index /Encoding get exch get\n"
1592 " 1 index /BuildGlyph get exec\n"
1593 "} bind def\n"
1594 "currentdict end\n";
1595
1596 const char * const h41 = "(%s) cvn exch definefont pop\n";
1597
1598 if ((nGlyphs <= 0) || (nGlyphs > 256)) return SFErrCodes::GlyphNum;
1599 if (!glyphArray) return SFErrCodes::BadArg;
1600 if (!fname) fname = ttf->psname;
1601
1602 fprintf(outf, h01, GetInt16(table, 0), GetUInt16(table, 2), GetInt16(table, 4), GetUInt16(table, 6));
1603 fprintf(outf, h02, modname, modver, modextra);
1604 fprintf(outf, h09, ttf->psname);
1605
1606 fprintf(outf, "%s", h10);
1607 fprintf(outf, h11, fname);
1608/* fprintf(outf, h12, 4000000); */
1609
1610 /* XUID generation:
1611 * 103 0 0 C1 C2 C3 C4
1612 * C1 - CRC-32 of the entire source TrueType font
1613 * C2 - number of glyphs in the subset
1614 * C3 - CRC-32 of the glyph array
1615 * C4 - CRC-32 of the encoding array
1616 *
1617 * All CRC-32 numbers are presented as hexadecimal numbers
1618 */
1619
1620 fprintf(outf, h17, rtl_crc32(0, ttf->ptr, ttf->fsize), nGlyphs, rtl_crc32(0, glyphArray, nGlyphs * 2), rtl_crc32(0, encoding, nGlyphs));
1621 fprintf(outf, "%s", h13);
1622 fprintf(outf, h14, XUnits(UPEm, GetInt16(table, 36)), XUnits(UPEm, GetInt16(table, 38)), XUnits(UPEm, GetInt16(table, 40)), XUnits(UPEm, GetInt16(table, 42)));
1623 fprintf(outf, "%s", h15);
1624
1625 for (i = 0; i < nGlyphs; i++) {
1626 fprintf(outf, h16, encoding[i], i);
1627 }
1628
1629 fprintf(outf, h30, nGlyphs+1);
1630 fprintf(outf, "%s", h31);
1631 fprintf(outf, "%s", h32);
1632
1633 for (i = 0; i < nGlyphs; i++) {
1634 fprintf(outf, h33, i);
1635 int r = GetTTGlyphOutline(ttf, glyphArray[i] < ttf->glyphCount() ? glyphArray[i] : 0, &pa, &metrics, nullptr);
1636
1637 if (r > 0) {
1638 n = BSplineToPSPath(pa, r, &path);
1639 } else {
1640 n = 0; /* glyph might have zero contours but valid metrics ??? */
1641 path = nullptr;
1642 if (r < 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */
1643 continue;
1644 }
1645 }
1646 fprintf(outf, "\t%d %d %d %d %d %d setcachedevice\n",
1647 wmode == 0 ? XUnits(UPEm, metrics.aw) : 0,
1648 wmode == 0 ? 0 : -XUnits(UPEm, metrics.ah),
1649 XUnits(UPEm, metrics.xMin),
1650 XUnits(UPEm, metrics.yMin),
1651 XUnits(UPEm, metrics.xMax),
1652 XUnits(UPEm, metrics.yMax));
1653
1654 for (j = 0; j < n; j++)
1655 {
1656 switch (path[j].type)
1657 {
1658 case PS_MOVETO:
1659 fprintf(outf, "\t%d %d moveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1));
1660 break;
1661
1662 case PS_LINETO:
1663 fprintf(outf, "\t%d %d lineto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1));
1664 break;
1665
1666 case PS_CURVETO:
1667 fprintf(outf, "\t%d %d %d %d %d %d curveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1), XUnits(UPEm, path[j].x2), XUnits(UPEm, path[j].y2), XUnits(UPEm, path[j].x3), XUnits(UPEm, path[j].y3));
1668 break;
1669
1670 case PS_CLOSEPATH:
1671 fprintf(outf, "\tclosepath\n");
1672 break;
1673 case PS_NOOP:
1674 break;
1675 }
1676 }
1677 if (n > 0) fprintf(outf, "\tfill\n"); /* if glyph is not a whitespace character */
1678
1679 fprintf(outf, "%s", h34);
1680
1681 free(pa);
1682 free(path);
1683 }
1684 fprintf(outf, "%s", h35);
1685
1686 fprintf(outf, "%s", h40);
1687 fprintf(outf, h41, fname);
1688
1689 return SFErrCodes::Ok;
1690}
1691
1693 const char *fname,
1694 sal_uInt16 const *glyphArray,
1695 sal_uInt8 const *encoding,
1696 int nGlyphs)
1697{
1698 TrueTypeCreator *ttcr;
1699 TrueTypeTable *head=nullptr, *hhea=nullptr, *maxp=nullptr, *cvt=nullptr, *prep=nullptr, *glyf=nullptr, *fpgm=nullptr, *cmap=nullptr, *name=nullptr, *post = nullptr, *os2 = nullptr;
1700 int i;
1701 SFErrCodes res;
1702
1704
1707 NameRecord *names = nullptr;
1708 int n = GetTTNameRecords(ttf, &names);
1709 name = TrueTypeTableNew_name(n, names);
1710 DisposeNameRecords(names, n);
1711
1713 sal_uInt32 nTableSize;
1714 const sal_uInt8* p = ttf->table(O_maxp, nTableSize);
1715 maxp = TrueTypeTableNew_maxp(p, nTableSize);
1716
1718 p = ttf->table(O_hhea, nTableSize);
1719 if (p && nTableSize >= HHEA_caretSlopeRun_offset + 2)
1721 else
1722 hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
1723
1726 p = ttf->table(O_head, nTableSize);
1727 assert(p != nullptr);
1735
1738 glyf = TrueTypeTableNew_glyf();
1739 sal_uInt32* gID = static_cast<sal_uInt32*>(scalloc(nGlyphs, sizeof(sal_uInt32)));
1740
1741 for (i = 0; i < nGlyphs; i++) {
1742 gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf);
1743 }
1744
1746 cmap = TrueTypeTableNew_cmap();
1747
1748 for (i=0; i < nGlyphs; i++) {
1749 cmapAdd(cmap, 0x010000, encoding[i], gID[i]);
1750 }
1751
1753 if ((p = ttf->table(O_cvt, nTableSize)) != nullptr)
1754 cvt = TrueTypeTableNew(T_cvt, nTableSize, p);
1755
1757 if ((p = ttf->table(O_prep, nTableSize)) != nullptr)
1758 prep = TrueTypeTableNew(T_prep, nTableSize, p);
1759
1761 if ((p = ttf->table(O_fpgm, nTableSize)) != nullptr)
1762 fpgm = TrueTypeTableNew(T_fpgm, nTableSize, p);
1763
1765 if ((p = ttf->table(O_post, nTableSize)) != nullptr)
1766 {
1767 sal_Int32 nItalic = (POST_italicAngle_offset + 4 < nTableSize) ?
1769 sal_Int16 nPosition = (POST_underlinePosition_offset + 2 < nTableSize) ?
1771 sal_Int16 nThickness = (POST_underlineThickness_offset + 2 < nTableSize) ?
1773 sal_uInt32 nFixedPitch = (POST_isFixedPitch_offset + 4 < nTableSize) ?
1775
1776 post = TrueTypeTableNew_post(0x00030000,
1777 nItalic, nPosition,
1778 nThickness, nFixedPitch);
1779 }
1780 else
1781 post = TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0);
1782
1783 AddTable(ttcr, name); AddTable(ttcr, maxp); AddTable(ttcr, hhea);
1784 AddTable(ttcr, head); AddTable(ttcr, glyf); AddTable(ttcr, cmap);
1785 AddTable(ttcr, cvt ); AddTable(ttcr, prep); AddTable(ttcr, fpgm);
1786 AddTable(ttcr, post); AddTable(ttcr, os2);
1787
1788 res = StreamToFile(ttcr, fname);
1789#if OSL_DEBUG_LEVEL > 1
1790 SAL_WARN_IF(res != SFErrCodes::Ok, "vcl.fonts", "StreamToFile: error code: "
1791 << (int) res << ".");
1792#endif
1793
1795 free(gID);
1796
1797 return res;
1798}
1799
1800static GlyphOffsets *GlyphOffsetsNew(sal_uInt8 *sfntP, sal_uInt32 sfntLen)
1801{
1802 GlyphOffsets* res = static_cast<GlyphOffsets*>(smalloc(sizeof(GlyphOffsets)));
1803 sal_uInt8 *loca = nullptr;
1804 sal_uInt16 numTables = GetUInt16(sfntP, 4);
1805 sal_uInt32 locaLen = 0;
1806 sal_Int16 indexToLocFormat = 0;
1807
1808 sal_uInt32 nMaxPossibleTables = sfntLen / (3*sizeof(sal_uInt32)); /*the three GetUInt32 calls*/
1809 if (numTables > nMaxPossibleTables)
1810 {
1811 SAL_WARN( "vcl.fonts", "GlyphOffsetsNew claimed to have "
1812 << numTables << " tables, but that's impossibly large");
1813 numTables = nMaxPossibleTables;
1814 }
1815
1816 for (sal_uInt16 i = 0; i < numTables; i++) {
1817 sal_uInt32 nLargestFixedOffsetPos = 12 + 16 * i + 12;
1818 sal_uInt32 nMinSize = nLargestFixedOffsetPos + sizeof(sal_uInt32);
1819 if (nMinSize > sfntLen)
1820 {
1821 SAL_WARN( "vcl.fonts", "GlyphOffsetsNew claimed to have "
1822 << numTables << " tables, but only space for " << i);
1823 break;
1824 }
1825
1826 sal_uInt32 tag = GetUInt32(sfntP, 12 + 16 * i);
1827 sal_uInt32 off = GetUInt32(sfntP, 12 + 16 * i + 8);
1828 sal_uInt32 len = GetUInt32(sfntP, nLargestFixedOffsetPos);
1829
1830 if (tag == T_loca) {
1831 loca = sfntP + off;
1832 locaLen = len;
1833 } else if (tag == T_head) {
1834 indexToLocFormat = GetInt16(sfntP + off, 50);
1835 }
1836 }
1837
1838 res->nGlyphs = locaLen / ((indexToLocFormat == 1) ? 4 : 2);
1839 assert(res->nGlyphs != 0);
1840 res->offs = static_cast<sal_uInt32*>(scalloc(res->nGlyphs, sizeof(sal_uInt32)));
1841
1842 for (sal_uInt32 i = 0; i < res->nGlyphs; i++) {
1843 if (indexToLocFormat == 1) {
1844 res->offs[i] = GetUInt32(loca, i * 4);
1845 } else {
1846 res->offs[i] = GetUInt16(loca, i * 2) << 1;
1847 }
1848 }
1849 return res;
1850}
1851
1852static void GlyphOffsetsDispose(GlyphOffsets *_this)
1853{
1854 if (_this) {
1855 free(_this->offs);
1856 free(_this);
1857 }
1858}
1859
1860static void DumpSfnts(FILE *outf, sal_uInt8 *sfntP, sal_uInt32 sfntLen)
1861{
1862 if (sfntLen < 12)
1863 {
1864 SAL_WARN( "vcl.fonts", "DumpSfnts sfntLen is too short: "
1865 << sfntLen << " legal min is: " << 12);
1866 return;
1867 }
1868
1869 const sal_uInt32 nSpaceForTables = sfntLen - 12;
1870 const sal_uInt32 nTableSize = 16;
1871 const sal_uInt32 nMaxPossibleTables = nSpaceForTables/nTableSize;
1872
1873 HexFmt *h = HexFmtNew(outf);
1874 sal_uInt16 i, numTables = GetUInt16(sfntP, 4);
1875 GlyphOffsets *go = GlyphOffsetsNew(sfntP, sfntLen);
1876 sal_uInt8 const pad[] = {0,0,0,0}; /* zeroes */
1877
1878 if (numTables > nMaxPossibleTables)
1879 {
1880 SAL_WARN( "vcl.fonts", "DumpSfnts claimed to have "
1881 << numTables << " tables, but only space for " << nMaxPossibleTables);
1882 numTables = nMaxPossibleTables;
1883 }
1884
1885 assert(numTables <= 9); /* Type42 has 9 required tables */
1886
1887 sal_uInt32* offs = static_cast<sal_uInt32*>(scalloc(numTables, sizeof(sal_uInt32)));
1888
1889 fputs("/sfnts [", outf);
1891 HexFmtBlockWrite(h, sfntP, 12); /* stream out the Offset Table */
1892 HexFmtBlockWrite(h, sfntP+12, 16 * numTables); /* stream out the Table Directory */
1893
1894 for (i=0; i<numTables; i++)
1895 {
1896 sal_uInt32 nLargestFixedOffsetPos = 12 + 16 * i + 12;
1897 sal_uInt32 nMinSize = nLargestFixedOffsetPos + sizeof(sal_uInt32);
1898 if (nMinSize > sfntLen)
1899 {
1900 SAL_WARN( "vcl.fonts", "DumpSfnts claimed to have "
1901 << numTables << " tables, but only space for " << i);
1902 break;
1903 }
1904
1905 sal_uInt32 tag = GetUInt32(sfntP, 12 + 16 * i);
1906 sal_uInt32 off = GetUInt32(sfntP, 12 + 16 * i + 8);
1907 if (off > sfntLen)
1908 {
1909 SAL_WARN( "vcl.fonts", "DumpSfnts claims offset of "
1910 << off << " but max possible is " << sfntLen);
1911 break;
1912 }
1913 sal_uInt8 *pRecordStart = sfntP + off;
1914 sal_uInt32 len = GetUInt32(sfntP, nLargestFixedOffsetPos);
1915 sal_uInt32 nMaxLenPossible = sfntLen - off;
1916 if (len > nMaxLenPossible)
1917 {
1918 SAL_WARN( "vcl.fonts", "DumpSfnts claims len of "
1919 << len << " but only space for " << nMaxLenPossible);
1920 break;
1921 }
1922
1923 if (tag != T_glyf)
1924 {
1925 HexFmtBlockWrite(h, pRecordStart, len);
1926 }
1927 else
1928 {
1929 sal_uInt8 *glyf = pRecordStart;
1930 sal_uInt8 *eof = pRecordStart + nMaxLenPossible;
1931 for (sal_uInt32 j = 0; j < go->nGlyphs - 1; j++)
1932 {
1933 sal_uInt32 nStartOffset = go->offs[j];
1934 sal_uInt8 *pSubRecordStart = glyf + nStartOffset;
1935 if (pSubRecordStart > eof)
1936 {
1937 SAL_WARN( "vcl.fonts", "DumpSfnts start glyf claims offset of "
1938 << pSubRecordStart - sfntP << " but max possible is " << eof - sfntP);
1939 break;
1940 }
1941
1942 sal_uInt32 nEndOffset = go->offs[j + 1];
1943 sal_uInt8 *pSubRecordEnd = glyf + nEndOffset;
1944 if (pSubRecordEnd > eof)
1945 {
1946 SAL_WARN( "vcl.fonts", "DumpSfnts end glyf offset of "
1947 << pSubRecordEnd - sfntP << " but max possible is " << eof - sfntP);
1948 break;
1949 }
1950
1951 sal_uInt32 l = pSubRecordEnd - pSubRecordStart;
1952 HexFmtBlockWrite(h, pSubRecordStart, l);
1953 }
1954 }
1955 HexFmtBlockWrite(h, pad, (4 - (len & 3)) & 3);
1956 }
1958 fputs("] def\n", outf);
1961 free(offs);
1962}
1963
1965 FILE *outf,
1966 const char *psname,
1967 sal_uInt16 const *glyphArray,
1968 sal_uInt8 *encoding,
1969 int nGlyphs)
1970{
1971 TrueTypeCreator *ttcr;
1972 TrueTypeTable *head=nullptr, *hhea=nullptr, *maxp=nullptr, *cvt=nullptr, *prep=nullptr, *glyf=nullptr, *fpgm=nullptr;
1973 int i;
1974 SFErrCodes res;
1975
1976 sal_uInt16 ver;
1977 sal_Int32 rev;
1978
1979 sal_uInt8 *sfntP;
1980 sal_uInt32 sfntLen;
1981 int UPEm = ttf->unitsPerEm();
1982
1983 if (nGlyphs >= 256) return SFErrCodes::GlyphNum;
1984
1985 assert(psname != nullptr);
1986
1988
1989 /* head */
1990 sal_uInt32 nTableSize;
1991 const sal_uInt8* p = ttf->table(O_head, nTableSize);
1992 const sal_uInt8* headP = p;
1993 assert(p != nullptr);
1997
1999 p = ttf->table(O_hhea, nTableSize);
2000 if (p)
2002 else
2003 hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2004
2006 p = ttf->table(O_maxp, nTableSize);
2007 maxp = TrueTypeTableNew_maxp(p, nTableSize);
2008
2010 if ((p = ttf->table(O_cvt, nTableSize)) != nullptr)
2011 cvt = TrueTypeTableNew(T_cvt, nTableSize, p);
2012
2014 if ((p = ttf->table(O_prep, nTableSize)) != nullptr)
2015 prep = TrueTypeTableNew(T_prep, nTableSize, p);
2016
2018 if ((p = ttf->table(O_fpgm, nTableSize)) != nullptr)
2019 fpgm = TrueTypeTableNew(T_fpgm, nTableSize, p);
2020
2022 glyf = TrueTypeTableNew_glyf();
2023 sal_uInt16* gID = static_cast<sal_uInt16*>(scalloc(nGlyphs, sizeof(sal_uInt32)));
2024
2025 for (i = 0; i < nGlyphs; i++) {
2026 gID[i] = static_cast<sal_uInt16>(glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf));
2027 }
2028
2029 AddTable(ttcr, head); AddTable(ttcr, hhea); AddTable(ttcr, maxp); AddTable(ttcr, cvt);
2030 AddTable(ttcr, prep); AddTable(ttcr, glyf); AddTable(ttcr, fpgm);
2031
2032 if ((res = StreamToMemory(ttcr, &sfntP, &sfntLen)) != SFErrCodes::Ok) {
2034 free(gID);
2035 return res;
2036 }
2037
2038 fprintf(outf, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", static_cast<int>(ver), static_cast<int>(ver & 0xFF), static_cast<int>(rev>>16), static_cast<int>(rev & 0xFFFF));
2039 fprintf(outf, "%%%%Creator: %s %s %s\n", modname, modver, modextra);
2040 fprintf(outf, "%%- Font subset generated from a source font file: '%s'\n", ttf->fileName().data());
2041 fprintf(outf, "%%- Original font name: %s\n", ttf->psname);
2042 fprintf(outf, "%%- Original font family: %s\n", ttf->family);
2043 fprintf(outf, "%%- Original font sub-family: %s\n", ttf->subfamily);
2044 fprintf(outf, "11 dict begin\n");
2045 fprintf(outf, "/FontName (%s) cvn def\n", psname);
2046 fprintf(outf, "/PaintType 0 def\n");
2047 fprintf(outf, "/FontMatrix [1 0 0 1 0 0] def\n");
2048 fprintf(outf, "/FontBBox [%d %d %d %d] def\n", XUnits(UPEm, GetInt16(headP, HEAD_xMin_offset)), XUnits(UPEm, GetInt16(headP, HEAD_yMin_offset)), XUnits(UPEm, GetInt16(headP, HEAD_xMax_offset)), XUnits(UPEm, GetInt16(headP, HEAD_yMax_offset)));
2049 fprintf(outf, "/FontType 42 def\n");
2050 fprintf(outf, "/Encoding 256 array def\n");
2051 fprintf(outf, " 0 1 255 {Encoding exch /.notdef put} for\n");
2052
2053 for (i = 1; i<nGlyphs; i++) {
2054 fprintf(outf, "Encoding %d /glyph%u put\n", encoding[i], gID[i]);
2055 }
2056 fprintf(outf, "/XUID [103 0 1 16#%08X %u 16#%08X 16#%08X] def\n", static_cast<unsigned int>(rtl_crc32(0, ttf->ptr, ttf->fsize)), static_cast<unsigned int>(nGlyphs), static_cast<unsigned int>(rtl_crc32(0, glyphArray, nGlyphs * 2)), static_cast<unsigned int>(rtl_crc32(0, encoding, nGlyphs)));
2057
2058 DumpSfnts(outf, sfntP, sfntLen);
2059
2060 /* dump charstrings */
2061 fprintf(outf, "/CharStrings %d dict dup begin\n", nGlyphs);
2062 fprintf(outf, "/.notdef 0 def\n");
2063 for (i = 1; i < static_cast<int>(glyfCount(glyf)); i++) {
2064 fprintf(outf,"/glyph%d %d def\n", i, i);
2065 }
2066 fprintf(outf, "end readonly def\n");
2067
2068 fprintf(outf, "FontName currentdict end definefont pop\n");
2070 free(gID);
2071 free(sfntP);
2072 return SFErrCodes::Ok;
2073}
2074
2075std::unique_ptr<sal_uInt16[]> GetTTSimpleGlyphMetrics(AbstractTrueTypeFont const *ttf, const sal_uInt16 *glyphArray, int nGlyphs, bool vertical)
2076{
2077 const sal_uInt8* pTable;
2078 sal_uInt32 n;
2079 sal_uInt32 nTableSize;
2080
2081 if (!vertical)
2082 {
2083 n = ttf->horzMetricCount();
2084 pTable = ttf->table(O_hmtx, nTableSize);
2085 }
2086 else
2087 {
2088 n = ttf->vertMetricCount();
2089 pTable = ttf->table(O_vmtx, nTableSize);
2090 }
2091
2092 if (!nGlyphs || !glyphArray) return nullptr; /* invalid parameters */
2093 if (!n || !pTable) return nullptr; /* the font does not contain the requested metrics */
2094
2095 std::unique_ptr<sal_uInt16[]> res(new sal_uInt16[nGlyphs]);
2096
2097 const int UPEm = ttf->unitsPerEm();
2098 for( int i = 0; i < nGlyphs; ++i) {
2099 sal_uInt32 nAdvOffset;
2100 sal_uInt16 glyphID = glyphArray[i];
2101
2102 if (glyphID < n) {
2103 nAdvOffset = 4 * glyphID;
2104 } else {
2105 nAdvOffset = 4 * (n - 1);
2106 }
2107
2108 if (nAdvOffset >= nTableSize || UPEm == 0)
2109 res[i] = 0; /* better than a crash for buggy fonts */
2110 else
2111 res[i] = static_cast<sal_uInt16>(
2112 XUnits( UPEm, GetUInt16( pTable, nAdvOffset) ) );
2113 }
2114
2115 return res;
2116}
2117
2118// TODO, clean up table parsing and re-use it elsewhere in this file.
2119void GetTTFontMetrics(const uint8_t *pHhea, size_t nHhea,
2120 const uint8_t *pOs2, size_t nOs2,
2121 TTGlobalFontInfo *info)
2122{
2123 /* There are 3 different versions of OS/2 table: original (68 bytes long),
2124 * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,)
2125 * Apple's documentation recommends looking at the table length.
2126 */
2127 if (nOs2 >= OS2_V0_length)
2128 {
2135 }
2136
2137 if (nHhea >= HHEA_lineGap_offset + 2) {
2138 info->ascender = GetInt16(pHhea, HHEA_ascender_offset);
2140 info->linegap = GetInt16(pHhea, HHEA_lineGap_offset);
2141 }
2142}
2143
2144bool GetTTGlobalFontHeadInfo(const AbstractTrueTypeFont *ttf, int& xMin, int& yMin, int& xMax, int& yMax, sal_uInt16& macStyle)
2145{
2146 sal_uInt32 table_size;
2147 const sal_uInt8* table = ttf->table(O_head, table_size);
2148 if (table_size < 46)
2149 return false;
2150
2151 const int UPEm = ttf->unitsPerEm();
2152 if (UPEm == 0)
2153 return false;
2154 xMin = XUnits(UPEm, GetInt16(table, HEAD_xMin_offset));
2155 yMin = XUnits(UPEm, GetInt16(table, HEAD_yMin_offset));
2156 xMax = XUnits(UPEm, GetInt16(table, HEAD_xMax_offset));
2157 yMax = XUnits(UPEm, GetInt16(table, HEAD_yMax_offset));
2159 return true;
2160}
2161
2163{
2164 int UPEm = ttf->unitsPerEm();
2165
2166 memset(info, 0, sizeof(TTGlobalFontInfo));
2167
2168 info->family = ttf->family;
2169 info->ufamily = ttf->ufamily;
2170 info->subfamily = ttf->subfamily;
2171 info->usubfamily = ttf->usubfamily;
2172 info->psname = ttf->psname;
2173 info->symbolEncoded = ttf->GetCharMap()->isSymbolic();
2174
2175 sal_uInt32 table_size;
2176 const sal_uInt8* table = ttf->table(O_OS2, table_size);
2177 if (table_size >= 42)
2178 {
2181
2182 if (table_size >= OS2_V0_length && UPEm != 0) {
2188 /* sanity check; some fonts treat winDescent as signed
2189 * violating the standard */
2190 if( info->winDescent > 5*UPEm )
2192 }
2195 }
2196
2197 table = ttf->table(O_post, table_size);
2198 if (table_size >= 12 + sizeof(sal_uInt32))
2199 {
2202 }
2203
2204 GetTTGlobalFontHeadInfo(ttf, info->xMin, info->yMin, info->xMax, info->yMax, info->macStyle);
2205
2206 table = ttf->table(O_hhea, table_size);
2207 if (table_size >= 10 && UPEm != 0)
2208 {
2212 }
2213}
2214
2216{
2217 if (glyphID >= ttf->glyphCount())
2218 return nullptr;
2219
2220 sal_uInt32 hmtxlength;
2221 const sal_uInt8* hmtx = ttf->table(O_hmtx, hmtxlength);
2222
2223 if (!hmtxlength)
2224 return nullptr;
2225
2226 sal_uInt32 glyflength;
2227 const sal_uInt8* glyf = ttf->table(O_glyf, glyflength);
2228 int n;
2229
2230 /* #127161# check the glyph offsets */
2231 sal_uInt32 nNextOffset = ttf->glyphOffset(glyphID + 1);
2232 if (nNextOffset > glyflength)
2233 return nullptr;
2234
2235 sal_uInt32 nOffset = ttf->glyphOffset(glyphID);
2236 if (nOffset > nNextOffset)
2237 return nullptr;
2238
2239 sal_uInt32 length = nNextOffset - nOffset;
2240
2241 GlyphData* d = static_cast<GlyphData*>(malloc(sizeof(GlyphData))); assert(d != nullptr);
2242
2243 if (length > 0) {
2244 const sal_uInt8* srcptr = glyf + ttf->glyphOffset(glyphID);
2245 const size_t nChunkLen = ((length + 1) & ~1);
2246 d->ptr = static_cast<sal_uInt8*>(malloc(nChunkLen)); assert(d->ptr != nullptr);
2247 memcpy(d->ptr, srcptr, length);
2248 memset(d->ptr + length, 0, nChunkLen - length);
2249 d->compflag = (GetInt16( srcptr, 0 ) < 0);
2250 } else {
2251 d->ptr = nullptr;
2252 d->compflag = false;
2253 }
2254
2255 d->glyphID = glyphID;
2256 d->nbytes = static_cast<sal_uInt16>((length + 1) & ~1);
2257
2258 /* now calculate npoints and ncontours */
2259 ControlPoint *cp;
2260 n = GetTTGlyphPoints(ttf, glyphID, &cp);
2261 if (n > 0)
2262 {
2263 int m = 0;
2264 for (int i = 0; i < n; i++)
2265 {
2266 if (cp[i].flags & 0x8000)
2267 m++;
2268 }
2269 d->npoints = static_cast<sal_uInt16>(n);
2270 d->ncontours = static_cast<sal_uInt16>(m);
2271 free(cp);
2272 } else {
2273 d->npoints = 0;
2274 d->ncontours = 0;
2275 }
2276
2277 /* get advance width and left sidebearing */
2278 sal_uInt32 nAwOffset;
2279 sal_uInt32 nLsboffset;
2280 if (glyphID < ttf->horzMetricCount()) {
2281 nAwOffset = 4 * glyphID;
2282 nLsboffset = 4 * glyphID + 2;
2283 } else {
2284 nAwOffset = 4 * (ttf->horzMetricCount() - 1);
2285 nLsboffset = (ttf->horzMetricCount() * 4) + ((glyphID - ttf->horzMetricCount()) * 2);
2286 }
2287
2288 if (nAwOffset + 2 <= hmtxlength)
2289 d->aw = GetUInt16(hmtx, nAwOffset);
2290 else
2291 {
2292 SAL_WARN("vcl.fonts", "hmtx offset " << nAwOffset << " not available");
2293 d->aw = 0;
2294 }
2295 if (nLsboffset + 2 <= hmtxlength)
2296 d->lsb = GetInt16(hmtx, nLsboffset);
2297 else
2298 {
2299 SAL_WARN("vcl.fonts", "hmtx offset " << nLsboffset << " not available");
2300 d->lsb = 0;
2301 }
2302
2303 return d;
2304}
2305
2307{
2308 sal_uInt32 nTableSize;
2309 const sal_uInt8* table = ttf->table(O_name, nTableSize);
2310
2311 if (nTableSize < 6)
2312 {
2313#if OSL_DEBUG_LEVEL > 1
2314 SAL_WARN("vcl.fonts", "O_name table too small.");
2315#endif
2316 return 0;
2317 }
2318
2319 sal_uInt16 n = GetUInt16(table, 2);
2320 sal_uInt32 nStrBase = GetUInt16(table, 4);
2321 int i;
2322
2323 *nr = nullptr;
2324 if (n == 0) return 0;
2325
2326 const sal_uInt32 remaining_table_size = nTableSize-6;
2327 const sal_uInt32 nMinRecordSize = 12;
2328 const sal_uInt32 nMaxRecords = remaining_table_size / nMinRecordSize;
2329 if (n > nMaxRecords)
2330 {
2331 SAL_WARN("vcl.fonts", "Parsing error in " << OUString::createFromAscii(ttf->fileName()) <<
2332 ": " << nMaxRecords << " max possible entries, but " <<
2333 n << " claimed, truncating");
2334 n = nMaxRecords;
2335 }
2336
2337 NameRecord* rec = static_cast<NameRecord*>(calloc(n, sizeof(NameRecord)));
2338 assert(rec);
2339
2340 for (i = 0; i < n; i++) {
2341 sal_uInt32 nLargestFixedOffsetPos = 6 + 10 + 12 * i;
2342 sal_uInt32 nMinSize = nLargestFixedOffsetPos + sizeof(sal_uInt16);
2343 if (nMinSize > nTableSize)
2344 {
2345 SAL_WARN( "vcl.fonts", "Font " << OUString::createFromAscii(ttf->fileName()) << " claimed to have "
2346 << n << " name records, but only space for " << i);
2347 n = i;
2348 break;
2349 }
2350
2351 rec[i].platformID = GetUInt16(table, 6 + 0 + 12 * i);
2352 rec[i].encodingID = GetUInt16(table, 6 + 2 + 12 * i);
2353 rec[i].languageID = LanguageType(GetUInt16(table, 6 + 4 + 12 * i));
2354 rec[i].nameID = GetUInt16(table, 6 + 6 + 12 * i);
2355 rec[i].slen = GetUInt16(table, 6 + 8 + 12 * i);
2356 sal_uInt32 nStrOffset = GetUInt16(table, nLargestFixedOffsetPos);
2357 if (rec[i].slen) {
2358 if (nStrBase + nStrOffset + rec[i].slen >= nTableSize)
2359 {
2360 rec[i].sptr = nullptr;
2361 rec[i].slen = 0;
2362 continue;
2363 }
2364
2365 const sal_uInt32 rec_string = nStrBase + nStrOffset;
2366 const size_t available_space = rec_string > nTableSize ? 0 : (nTableSize - rec_string);
2367 if (rec[i].slen <= available_space)
2368 {
2369 rec[i].sptr = static_cast<sal_uInt8 *>(malloc(rec[i].slen)); assert(rec[i].sptr != nullptr);
2370 memcpy(rec[i].sptr, table + rec_string, rec[i].slen);
2371 }
2372 else
2373 {
2374 rec[i].sptr = nullptr;
2375 rec[i].slen = 0;
2376 }
2377 } else {
2378 rec[i].sptr = nullptr;
2379 }
2380 // some fonts have 3.0 names => fix them to 3.1
2381 if( (rec[i].platformID == 3) && (rec[i].encodingID == 0) )
2382 rec[i].encodingID = 1;
2383 }
2384
2385 *nr = rec;
2386 return n;
2387}
2388
2390{
2391 int i;
2392 for (i = 0; i < n; i++) {
2393 if (nr[i].sptr) free(nr[i].sptr);
2394 }
2395 free(nr);
2396}
2397
2398template<size_t N> static void
2399append(std::bitset<N> & rSet, size_t const nOffset, sal_uInt32 const nValue)
2400{
2401 for (size_t i = 0; i < 32; ++i)
2402 {
2403 rSet.set(nOffset + i, (nValue & (1U << i)) != 0);
2404 }
2405}
2406
2408 std::optional<std::bitset<UnicodeCoverage::MAX_UC_ENUM>> &rUnicodeRange,
2409 std::optional<std::bitset<CodePageCoverage::MAX_CP_ENUM>> &rCodePageRange,
2410 const unsigned char* pTable, size_t nLength)
2411{
2412 bool bRet = false;
2413 // parse OS/2 header
2415 {
2416 rUnicodeRange = std::bitset<UnicodeCoverage::MAX_UC_ENUM>();
2417 append(*rUnicodeRange, 0, GetUInt32(pTable, OS2_ulUnicodeRange1_offset));
2418 append(*rUnicodeRange, 32, GetUInt32(pTable, OS2_ulUnicodeRange2_offset));
2419 append(*rUnicodeRange, 64, GetUInt32(pTable, OS2_ulUnicodeRange3_offset));
2420 append(*rUnicodeRange, 96, GetUInt32(pTable, OS2_ulUnicodeRange4_offset));
2421 bRet = true;
2422 if (nLength >= OS2_V1_length)
2423 {
2424 rCodePageRange = std::bitset<CodePageCoverage::MAX_CP_ENUM>();
2425 append(*rCodePageRange, 0, GetUInt32(pTable, OS2_ulCodePageRange1_offset));
2426 append(*rCodePageRange, 32, GetUInt32(pTable, OS2_ulCodePageRange2_offset));
2427 }
2428 }
2429 return bRet;
2430}
2431
2432} // namespace vcl
2433
2434int TestFontSubset(const void* data, sal_uInt32 size)
2435{
2436 int nResult = -1;
2437 vcl::TrueTypeFont* pTTF = nullptr;
2438 if (OpenTTFontBuffer(data, size, 0, &pTTF) == vcl::SFErrCodes::Ok)
2439 {
2441 GetTTGlobalFontInfo(pTTF, &aInfo);
2442
2443 sal_uInt16 aGlyphIds[ 256 ] = {};
2444 sal_uInt8 aEncoding[ 256 ] = {};
2445
2446 for (sal_uInt16 c = 32; c < 256; ++c)
2447 {
2448 aEncoding[c] = c;
2449 aGlyphIds[c] = c - 31;
2450 }
2451
2452 CreateTTFromTTGlyphs(pTTF, nullptr, aGlyphIds, aEncoding, 256);
2453
2454
2455 // cleanup
2456 CloseTTFont( pTTF );
2457 // success
2458 nResult = 0;
2459 }
2460
2461 return nResult;
2462}
2463
2464/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XPropertyListType t
double d
bool is() const
virtual bool hasTable(sal_uInt32 ord) const =0
sal_uInt32 m_nHorzMetrics
Definition: sft.hxx:725
virtual ~AbstractTrueTypeFont()
Definition: sft.cxx:1208
sal_uInt32 vertMetricCount() const
Definition: sft.hxx:742
std::string const & fileName() const
Definition: sft.hxx:738
sal_uInt32 horzMetricCount() const
Definition: sft.hxx:741
sal_uInt32 m_nVertMetrics
Definition: sft.hxx:726
const FontCharMapRef & GetCharMap() const
Definition: sft.hxx:744
virtual const sal_uInt8 * table(sal_uInt32 ord, sal_uInt32 &size) const =0
sal_uInt32 m_nUnitsPerEm
Definition: sft.hxx:727
sal_uInt32 glyphCount() const
Definition: sft.hxx:739
sal_uInt32 m_nGlyphs
Definition: sft.hxx:724
sal_uInt32 glyphOffset(sal_uInt32 glyphID) const
Definition: sft.cxx:1240
FontCharMapRef m_xCharMap
Definition: sft.hxx:729
AbstractTrueTypeFont(const char *fileName=nullptr, const FontCharMapRef xCharMap=nullptr)
Definition: sft.cxx:1197
std::string m_sFileName
Definition: sft.hxx:723
std::vector< sal_uInt32 > m_aGlyphOffsets
Definition: sft.hxx:728
SFErrCodes indexGlyphData()
Definition: sft.cxx:1247
sal_uInt32 unitsPerEm() const
Definition: sft.hxx:743
const sal_uInt8 * table(sal_uInt32 ord, sal_uInt32 &size) const override
Definition: sft.hxx:781
~TrueTypeFont() override
Definition: sft.cxx:1225
sal_Unicode * ufamily
Definition: sft.hxx:766
sal_uInt8 * ptr
Definition: sft.hxx:762
sal_Unicode * usubfamily
Definition: sft.hxx:768
sal_Int32 fsize
Definition: sft.hxx:761
bool hasTable(sal_uInt32 ord) const override
Definition: sft.hxx:777
char * family
Definition: sft.hxx:765
char * psname
Definition: sft.hxx:764
TrueTypeFont(const char *pFileName=nullptr, const FontCharMapRef xCharMap=nullptr)
Definition: sft.cxx:1212
char * subfamily
Definition: sft.hxx:767
sal_uInt32 ntables
Definition: sft.hxx:770
SFErrCodes open(sal_uInt32 facenum)
Definition: sft.cxx:1310
std::array< struct TTFontTable_, NUM_TAGS > m_aTableList
Definition: sft.hxx:758
bool close
float y
float x
float z
TOOLS_DLLPUBLIC fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1)
TOOLS_DLLPUBLIC fix16_t fix16_div(fix16_t inArg0, fix16_t inArg1)
sal_Int16 nValue
bool ParseCMAP(const unsigned char *pCmap, int nLength, CmapResult &rResult)
Definition: fontcharmap.cxx:96
SFErrCodes OpenTTFontBuffer(const void *pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont **ttf, const FontCharMapRef xCharMap)
TrueTypeFont constructor.
Definition: sft.cxx:1165
std::unique_ptr< sal_uInt16[]> GetTTSimpleGlyphMetrics(AbstractTrueTypeFont const *ttf, const sal_uInt16 *glyphArray, int nGlyphs, bool vertical)
Queries glyph metrics.
Definition: sft.cxx:2075
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:2215
int CountTTCFonts(const char *fname)
Get the number of fonts contained in a TrueType collection.
Definition: sft.cxx:1089
int GetTTNameRecords(AbstractTrueTypeFont const *ttf, NameRecord **nr)
Extracts all Name Records from the font and stores them in an allocated array of NameRecord structs.
Definition: sft.cxx:2306
void DisposeNameRecords(NameRecord *nr, int n)
Deallocates previously allocated array of NameRecords.
Definition: sft.cxx:2389
int GetTTGlyphPoints(AbstractTrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray)
Extracts TrueType control points, and stores them in an allocated array pointed to by *pointArray.
Definition: sft.cxx:1457
SFErrCodes CreateTTFromTTGlyphs(AbstractTrueTypeFont *ttf, const char *fname, sal_uInt16 const *glyphArray, sal_uInt8 const *encoding, int nGlyphs)
Generates a new TrueType font and dumps it to outf file.
Definition: sft.cxx:1692
bool GetTTGlobalFontHeadInfo(const AbstractTrueTypeFont *ttf, int &xMin, int &yMin, int &xMax, int &yMax, sal_uInt16 &macStyle)
Returns part of the head table info, normally collected by GetTTGlobalFontInfo.
Definition: sft.cxx:2144
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:1462
void CloseTTFont(TrueTypeFont *ttf)
TrueTypeFont destructor.
Definition: sft.cxx:1238
SFErrCodes CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, sal_uInt16 const *glyphArray, sal_uInt8 *encoding, int nGlyphs, int wmode)
Generates a new PostScript Type 3 font and dumps it to outf file.
Definition: sft.cxx:1539
SFErrCodes CreateT42FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *psname, sal_uInt16 const *glyphArray, sal_uInt8 *encoding, int nGlyphs)
Generates a new PostScript Type42 font and dumps it to outf file.
Definition: sft.cxx:1964
void GetTTFontMetrics(const uint8_t *pHhea, size_t nHhea, const uint8_t *pOs2, size_t nOs2, TTGlobalFontInfo *info)
Returns fonts metrics.
Definition: sft.cxx:2119
void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info)
Returns global font information about the TrueType font.
Definition: sft.cxx:2162
SFErrCodes OpenTTFontFile(const char *fname, sal_uInt32 facenum, TrueTypeFont **ttf, const FontCharMapRef xCharMap)
TrueTypeFont constructor.
Definition: sft.cxx:1105
const char * name
sal_Int32 nIndex
void * p
sal_Int64 n
uno_Any a
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
#define SAL_N_ELEMENTS(arr)
std::unique_ptr< sal_Int32[]> pData
@ table
size
tDoubleVectorPair cleanup(const css::uno::Sequence< double > &rXValues, const css::uno::Sequence< double > &rYValues, Pred aPred)
int i
index
m
std::enable_if< std::is_signed< T >::value, bool >::type checked_add(T a, T b, T &result)
T saturating_add(T a, T b)
constexpr int HHEA_ascender_offset
Definition: sft.hxx:310
constexpr int OS2_ulCodePageRange1_offset
Definition: sft.hxx:278
constexpr int OS2_ulUnicodeRange4_offset
Definition: sft.hxx:271
static void GetMetrics(AbstractTrueTypeFont const *ttf, sal_uInt32 glyphID, TTGlyphMetrics *metrics)
Definition: sft.cxx:268
static void HexFmtBlockWrite(HexFmt *_this, const void *ptr, sal_uInt32 size)
Definition: sft.cxx:243
constexpr int OS2_fsType_offset
Definition: sft.hxx:265
constexpr sal_uInt32 T_ttcf
Definition: sft.hxx:429
constexpr int O_vmtx
Definition: sft.hxx:711
constexpr int O_prep
Definition: sft.hxx:715
constexpr int O_fpgm
Definition: sft.hxx:716
constexpr int HHEA_lineGap_offset
Definition: sft.hxx:312
constexpr int OS2_typoDescender_offset
Definition: sft.hxx:274
static char toHex(sal_uInt8 nIndex)
Definition: sft.cxx:199
constexpr int HEAD_lowestRecPPEM_offset
Definition: sft.hxx:373
constexpr int OS2_Legacy_length
Definition: sft.hxx:259
static void HexFmtCloseString(HexFmt *_this)
Definition: sft.cxx:231
constexpr int OS2_usWeightClass_offset
Definition: sft.hxx:263
constexpr int HEAD_fontRevision_offset
Definition: sft.hxx:363
constexpr sal_uInt32 T_post
Definition: sft.hxx:444
constexpr sal_uInt32 T_cvt
Definition: sft.hxx:445
constexpr sal_uInt32 T_vhea
Definition: sft.hxx:441
constexpr sal_uInt32 T_loca
Definition: sft.hxx:436
constexpr int HEAD_majorVersion_offset
Definition: sft.hxx:362
constexpr int OS2_winAscent_offset
Definition: sft.hxx:276
constexpr int HEAD_yMax_offset
Definition: sft.hxx:371
constexpr int HHEA_caretSlopeRise_offset
Definition: sft.hxx:313
constexpr sal_uInt32 T_otto
Definition: sft.hxx:430
constexpr int GLYF_xMax_offset
Definition: sft.hxx:425
SFErrCodes
Return value of OpenTTFont() and CreateT3FromTTGlyphs()
Definition: sft.hxx:61
@ FontNo
incorrect logical font number of a TTC font
@ TtFormat
incorrect TrueType font format
@ Memory
memory allocation error
@ FileIo
file I/O error
@ GlyphNum
incorrect number of glyphs
@ BadFile
file not found
@ BadArg
incorrect arguments
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:860
constexpr int OS2_typoAscender_offset
Definition: sft.hxx:273
constexpr int OS2_typoLineGap_offset
Definition: sft.hxx:275
constexpr sal_uInt32 T_true
Definition: sft.hxx:428
constexpr sal_uInt32 T_prep
Definition: sft.hxx:446
constexpr sal_uInt32 T_glyf
Definition: sft.hxx:434
constexpr int O_OS2
Definition: sft.hxx:712
static char * nameExtract(const sal_uInt8 *name, int nTableSize, int n, int dbFlag, sal_Unicode **ucs2result)
Definition: sft.cxx:884
constexpr int O_vhea
Definition: sft.hxx:710
const char *const modextra
Definition: sft.cxx:61
constexpr int OS2_ulUnicodeRange3_offset
Definition: sft.hxx:270
static F16Dot16 fixedMul(F16Dot16 a, F16Dot16 b)
Definition: sft.cxx:175
static int XUnits(int unitsPerEm, int n)
Definition: sft.cxx:194
constexpr int GLYF_numberOfContours_offset
Definition: sft.hxx:422
static void GetNames(TrueTypeFont *t)
Definition: sft.cxx:966
constexpr int O_hhea
Definition: sft.hxx:707
const char *const modname
Definition: sft.cxx:59
constexpr int OS2_ulCodePageRange2_offset
Definition: sft.hxx:279
constexpr sal_uInt32 T_hhea
Definition: sft.hxx:438
static GlyphOffsets * GlyphOffsetsNew(sal_uInt8 *sfntP, sal_uInt32 sfntLen)
Definition: sft.cxx:1800
constexpr int OS2_panoseNbBytes_offset
Definition: sft.hxx:267
constexpr int NUM_TAGS
Definition: sft.hxx:719
static void append(std::bitset< N > &rSet, size_t const nOffset, sal_uInt32 const nValue)
Definition: sft.cxx:2399
constexpr int OS2_fsSelection_offset
Definition: sft.hxx:272
constexpr int OS2_ulUnicodeRange2_offset
Definition: sft.hxx:269
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:892
TrueTypeTable * TrueTypeTableNew_name(int n, NameRecord const *nr)
Creates a new 'name' table.
Definition: ttcr.cxx:1006
const char *const modver
Definition: sft.cxx:60
constexpr int HEAD_created_offset
Definition: sft.hxx:367
constexpr int GLYF_yMax_offset
Definition: sft.hxx:426
constexpr int HHEA_caretSlopeRun_offset
Definition: sft.hxx:314
constexpr int O_cmap
Definition: sft.hxx:709
constexpr int HEAD_flags_offset
Definition: sft.hxx:365
void(* f)(TrueTypeTable *)
Definition: ttcr.cxx:482
constexpr int HEAD_unitsPerEm_offset
Definition: sft.hxx:366
constexpr int O_gsub
Definition: sft.hxx:717
SFErrCodes StreamToMemory(TrueTypeCreator *_this, sal_uInt8 **ptr, sal_uInt32 *length)
Writes a TrueType font generated by the TrueTypeCreator to a segment of memory that this method alloc...
Definition: ttcr.cxx:191
TrueTypeTable * TrueTypeTableNew(sal_uInt32 tag, sal_uInt32 nbytes, const sal_uInt8 *ptr)
Creates a new raw TrueType table.
Definition: ttcr.cxx:838
constexpr int O_post
Definition: sft.hxx:713
static void GlyphOffsetsDispose(GlyphOffsets *_this)
Definition: sft.cxx:1852
bool getTTCoverage(std::optional< std::bitset< UnicodeCoverage::MAX_UC_ENUM > > &rUnicodeRange, std::optional< std::bitset< CodePageCoverage::MAX_CP_ENUM > > &rCodePageRange, const unsigned char *pTable, size_t nLength)
Definition: sft.cxx:2407
constexpr int O_loca
Definition: sft.hxx:705
constexpr int HEAD_xMax_offset
Definition: sft.hxx:370
TrueTypeTable * TrueTypeTableNew_maxp(const sal_uInt8 *maxp, int size)
Creates a new 'maxp' table based on an existing maxp table.
Definition: ttcr.cxx:935
constexpr sal_uInt32 T_head
Definition: sft.hxx:435
static sal_Int16 GetInt16(const sal_uInt8 *ptr, size_t offset)
Definition: sft.cxx:133
constexpr int HEAD_yMin_offset
Definition: sft.hxx:369
constexpr sal_uInt32 T_gsub
Definition: sft.hxx:448
constexpr int HEAD_fontDirectionHint_offset
Definition: sft.hxx:374
constexpr int HEAD_xMin_offset
Definition: sft.hxx:368
static sal_uInt32 GetUInt32(const sal_uInt8 *ptr, size_t offset)
Definition: sft.cxx:164
sal_uInt32 glyfCount(const TrueTypeTable *table)
Query the number of glyphs currently stored in the 'glyf' table.
Definition: ttcr.cxx:1198
constexpr int O_CFF
Definition: sft.hxx:718
constexpr int POST_isFixedPitch_offset
Definition: sft.hxx:331
constexpr int POST_underlinePosition_offset
Definition: sft.hxx:329
constexpr int GLYF_yMin_offset
Definition: sft.hxx:424
static F16Dot16 fixedDiv(F16Dot16 a, F16Dot16 b)
Definition: sft.cxx:180
static HexFmt * HexFmtNew(FILE *outf)
Definition: sft.cxx:207
SFErrCodes StreamToFile(TrueTypeCreator *_this, const char *fname)
Writes a TrueType font generated by the TrueTypeCreator to a file.
Definition: ttcr.cxx:270
static int GetCompoundTTOutline(AbstractTrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 > &glyphlist)
Definition: sft.cxx:477
constexpr int OS2_V1_length
Definition: sft.hxx:261
void TrueTypeCreatorNewEmpty(sal_uInt32 tag, TrueTypeCreator **_this)
TrueTypeCreator constructor.
Definition: ttcr.cxx:148
constexpr int POST_italicAngle_offset
Definition: sft.hxx:328
constexpr sal_uInt32 T_maxp
Definition: sft.hxx:433
static void DumpSfnts(FILE *outf, sal_uInt8 *sfntP, sal_uInt32 sfntLen)
Definition: sft.cxx:1860
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:1029
static int GetTTGlyphOutline(AbstractTrueTypeFont *, sal_uInt32, ControlPoint **, TTGlyphMetrics *, std::vector< sal_uInt32 > *)
Definition: sft.cxx:705
TrueTypeTable * TrueTypeTableNew_glyf()
Creates a new empty 'glyf' table.
Definition: ttcr.cxx:950
static void * smalloc(size_t size)
Definition: sft.cxx:118
constexpr sal_uInt32 T_OS2
Definition: sft.hxx:443
constexpr sal_uInt32 T_CFF
Definition: sft.hxx:449
constexpr int GLYF_xMin_offset
Definition: sft.hxx:423
constexpr int HEAD_indexToLocFormat_offset
Definition: sft.hxx:375
static F16Dot16 fromF2Dot14(sal_Int16 n)
Definition: sft.cxx:471
constexpr sal_uInt32 T_hmtx
Definition: sft.hxx:439
constexpr sal_uInt32 T_name
Definition: sft.hxx:437
constexpr int O_maxp
Definition: sft.hxx:702
constexpr int HEAD_macStyle_offset
Definition: sft.hxx:372
sal_uInt32 tag
Definition: ttcr.cxx:481
static sal_uInt16 GetUInt16(const sal_uInt8 *ptr, size_t offset)
Definition: sft.cxx:143
static int GetSimpleTTOutline(AbstractTrueTypeFont const *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics)
Definition: sft.cxx:301
static int BSplineToPSPath(ControlPoint const *srcA, int srcCount, PSPathElement **path)
Definition: sft.cxx:756
constexpr sal_uInt32 T_fpgm
Definition: sft.hxx:447
static void * scalloc(size_t n, size_t size)
Definition: sft.cxx:125
static sal_Int32 GetInt32(const sal_uInt8 *ptr, size_t offset)
Definition: sft.cxx:153
static void HexFmtOpenString(HexFmt *_this)
Definition: sft.cxx:226
constexpr int O_cvt
Definition: sft.hxx:714
constexpr int POST_underlineThickness_offset
Definition: sft.hxx:330
constexpr int HHEA_descender_offset
Definition: sft.hxx:311
constexpr int OS2_ulUnicodeRange1_offset
Definition: sft.hxx:268
constexpr int HEAD_Length
Definition: sft.hxx:360
static int findname(const sal_uInt8 *name, sal_uInt16 n, sal_uInt16 platformID, sal_uInt16 encodingID, sal_uInt16 languageID, sal_uInt16 nameID)
Definition: sft.cxx:925
constexpr int O_name
Definition: sft.hxx:706
constexpr int O_glyf
Definition: sft.hxx:703
constexpr int OS2_panose_offset
Definition: sft.hxx:266
static void HexFmtDispose(HexFmt *_this)
Definition: sft.cxx:237
static bool HexFmtFlush(HexFmt *_this)
Definition: sft.cxx:215
constexpr int O_head
Definition: sft.hxx:704
sal_uInt32 glyfAdd(TrueTypeTable *table, GlyphData *glyphdata, AbstractTrueTypeFont *fnt)
Add a glyph to a glyf table.
Definition: ttcr.cxx:1144
constexpr sal_uInt32 T_cmap
Definition: sft.hxx:440
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:1078
constexpr sal_uInt32 T_vmtx
Definition: sft.hxx:442
constexpr int OS2_winDescent_offset
Definition: sft.hxx:277
void AddTable(TrueTypeCreator *_this, TrueTypeTable *table)
Adds a TrueType table to the TrueType creator.
Definition: ttcr.cxx:160
static F16Dot16 fixedMulDiv(F16Dot16 a, F16Dot16 b, F16Dot16 c)
Definition: sft.cxx:187
constexpr int OS2_usWidthClass_offset
Definition: sft.hxx:264
@ WE_HAVE_A_TWO_BY_TWO
Definition: sft.hxx:108
@ ARG_1_AND_2_ARE_WORDS
Definition: sft.hxx:102
@ WE_HAVE_A_SCALE
Definition: sft.hxx:105
@ MORE_COMPONENTS
Definition: sft.hxx:106
@ WE_HAVE_AN_X_AND_Y_SCALE
Definition: sft.hxx:107
@ USE_MY_METRICS
Definition: sft.hxx:110
@ ARGS_ARE_XY_VALUES
Definition: sft.hxx:103
constexpr int O_hmtx
Definition: sft.hxx:708
sal_Int32 F16Dot16
fixed: 16.16
Definition: sft.hxx:57
constexpr int OS2_V0_length
Definition: sft.hxx:260
TrueTypeTable * TrueTypeTableNew_cmap()
Creates a new empty 'cmap' table.
Definition: ttcr.cxx:966
sal_Int32 h
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
#define HFORMAT_LINELEN
Definition: sft.cxx:102
int TestFontSubset(const void *data, sal_uInt32 size)
Definition: sft.cxx:2434
Sun Font Tools.
static SfxItemSet & rSet
ControlPoint structure used by GetTTGlyphPoints()
Definition: sft.hxx:178
sal_Int16 y
Y coordinate in EmSquare units
Definition: sft.hxx:184
sal_Int16 x
X coordinate in EmSquare units
Definition: sft.hxx:183
sal_uInt32 flags
00000000 00000000 e0000000 bbbbbbbb
Definition: sft.hxx:179
Structure used by the TrueType Creator and GetRawGlyphData()
Definition: sft.hxx:122
Structure used by the TrueType Creator and CreateTTFromTTGlyphs()
Definition: sft.hxx:136
sal_uInt16 slen
String length in bytes
Definition: sft.hxx:141
sal_uInt16 encodingID
Platform-specific encoding ID
Definition: sft.hxx:138
LanguageType languageID
Language ID
Definition: sft.hxx:139
sal_uInt16 platformID
Platform ID
Definition: sft.hxx:137
sal_uInt8 * sptr
Pointer to string data (not zero-terminated!)
Definition: sft.hxx:142
sal_uInt16 nameID
Name ID
Definition: sft.hxx:140
Return value of GetTTGlobalFontInfo()
Definition: sft.hxx:147
int italicAngle
in counter-clockwise degrees * 65536
Definition: sft.hxx:157
int ascender
typographic ascent.
Definition: sft.hxx:162
int typoDescender
OS/2 portable typographic descender
Definition: sft.hxx:167
int yMin
global bounding box: yMin
Definition: sft.hxx:159
int winAscent
ascender metric for Windows
Definition: sft.hxx:169
int xMin
global bounding box: xMin
Definition: sft.hxx:158
int typoAscender
OS/2 portable typographic ascender
Definition: sft.hxx:166
sal_uInt8 panose[10]
PANOSE classification number
Definition: sft.hxx:172
int width
value of WidthClass or 0 if can't be determined
Definition: sft.hxx:155
sal_Unicode * ufamily
family name UCS2
Definition: sft.hxx:149
int typoLineGap
OS/2 portable typographic line gap
Definition: sft.hxx:168
int weight
value of WeightClass or 0 if can't be determined
Definition: sft.hxx:154
int xMax
global bounding box: xMax
Definition: sft.hxx:160
sal_uInt32 typeFlags
type flags (copyright bits)
Definition: sft.hxx:173
int winDescent
descender metric for Windows
Definition: sft.hxx:170
char * psname
PostScript name
Definition: sft.hxx:152
char * subfamily
subfamily name
Definition: sft.hxx:150
int linegap
typographic line gap. Negative values are treated as zero in Win 3.1, System 6 and System 7.
Definition: sft.hxx:164
int descender
typographic descent.
Definition: sft.hxx:163
bool symbolEncoded
true: MS symbol encoded
Definition: sft.hxx:171
char * family
family name
Definition: sft.hxx:148
int pitch
0: proportional font, otherwise: monospaced
Definition: sft.hxx:156
sal_uInt16 fsSelection
OS/2 fsSelection.
Definition: sft.hxx:174
sal_Unicode * usubfamily
subfamily name UCS2
Definition: sft.hxx:151
sal_uInt16 macStyle
macstyle bits from 'HEAD' table
Definition: sft.hxx:153
int yMax
global bounding box: yMax
Definition: sft.hxx:161
void TrueTypeCreatorDispose(vcl::TrueTypeCreator *_this)
TrueTypeCreator destructor.
Definition: ttcr.cxx:1459
TrueType font creator.
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
signed char sal_Int8
Any result
ResultType type
sal_Int32 nLength