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