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