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