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