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