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