w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

unconsolidate.c
Go to the documentation of this file.
1 #include "unconsolidate.h"
2 #include "support/util.h"
3 #include "support/aglfn/aglfn.h"
4 #include "support/sha1/sha1.h"
5 
6 typedef struct {
8 } GlyphHash;
10  bufwrite8(buf, s.type);
11  switch (s.type) {
12  case VQ_STILL:
13  bufwrite32b(buf, otfcc_to_fixed(s.val.still));
14  break;
15  case VQ_DELTA:
16  bufwrite32b(buf, otfcc_to_fixed(s.val.delta.quantity));
17  bufwrite32b(buf, (uint32_t)s.val.delta.region->dimensions);
18  for (size_t j = 0; j < s.val.delta.region->dimensions; j++) {
19  const vq_AxisSpan *span = &s.val.delta.region->spans[j];
23  }
24  }
25 }
26 
27 static void hashVQ(caryll_Buffer *buf, VQ x) {
28  bufwrite32b(buf, otfcc_to_fixed(x.kernel));
29  bufwrite32b(buf, (uint32_t)x.shift.length);
30  for (size_t j = 0; j < x.shift.length; j++) {
31  hashVQS(buf, x.shift.items[j]);
32  }
33 }
34 
37  bufwrite8(buf, 'H');
38  hashVQ(buf, g->advanceWidth);
39  bufwrite8(buf, 'h');
40  hashVQ(buf, g->horizontalOrigin);
41  bufwrite8(buf, 'V');
42  hashVQ(buf, g->advanceHeight);
43  bufwrite8(buf, 'v');
44  hashVQ(buf, g->verticalOrigin);
45  // contours
46  bufwrite8(buf, 'C');
47  bufwrite8(buf, '(');
48  for (shapeid_t j = 0; j < g->contours.length; j++) {
49  bufwrite8(buf, '(');
50  glyf_Contour *c = &g->contours.items[j];
51  for (shapeid_t k = 0; k < c->length; k++) {
52  hashVQ(buf, c->items[k].x);
53  hashVQ(buf, c->items[k].y);
54  bufwrite8(buf, c->items[k].onCurve ? 1 : 0);
55  }
56  bufwrite8(buf, ')');
57  }
58  bufwrite8(buf, ')');
59  // references
60  bufwrite8(buf, 'R');
61  bufwrite8(buf, '(');
62  for (shapeid_t j = 0; j < g->references.length; j++) {
63  glyf_ComponentReference *r = &g->references.items[j];
64  GlyphHash h = nameGlyphByHash(glyf->items[r->glyph.index], glyf);
66  hashVQ(buf, r->x);
67  hashVQ(buf, r->y);
72  }
73  bufwrite8(buf, ')');
74  // stemH, stemV
75  bufwrite8(buf, 's'), bufwrite8(buf, 'H');
76  bufwrite8(buf, '(');
77  for (shapeid_t j = 0; j < g->stemH.length; j++) {
78  bufwrite32b(buf, otfcc_to_fixed(g->stemH.items[j].position));
79  bufwrite32b(buf, otfcc_to_fixed(g->stemH.items[j].width));
80  }
81  bufwrite8(buf, ')');
82  bufwrite8(buf, 's'), bufwrite8(buf, 'V');
83  bufwrite8(buf, '(');
84  for (shapeid_t j = 0; j < g->stemV.length; j++) {
85  bufwrite32b(buf, otfcc_to_fixed(g->stemV.items[j].position));
86  bufwrite32b(buf, otfcc_to_fixed(g->stemV.items[j].width));
87  }
88  bufwrite8(buf, ')');
89  // hintmask, contourmask
90  bufwrite8(buf, 'm'), bufwrite8(buf, 'H');
91  bufwrite8(buf, '(');
92  for (shapeid_t j = 0; j < g->hintMasks.length; j++) {
93  bufwrite16b(buf, g->hintMasks.items[j].contoursBefore);
94  bufwrite16b(buf, g->hintMasks.items[j].pointsBefore);
95  for (shapeid_t k = 0; k < g->stemH.length; k++) {
96  bufwrite8(buf, g->hintMasks.items[j].maskH[k]);
97  }
98  for (shapeid_t k = 0; k < g->stemV.length; k++) {
99  bufwrite8(buf, g->hintMasks.items[j].maskV[k]);
100  }
101  }
102  bufwrite8(buf, ')');
103  bufwrite8(buf, 'm'), bufwrite8(buf, 'C');
104  bufwrite8(buf, '(');
105  for (shapeid_t j = 0; j < g->contourMasks.length; j++) {
106  bufwrite16b(buf, g->contourMasks.items[j].contoursBefore);
107  bufwrite16b(buf, g->contourMasks.items[j].pointsBefore);
108  for (shapeid_t k = 0; k < g->stemH.length; k++) {
109  bufwrite8(buf, g->contourMasks.items[j].maskH[k]);
110  }
111  for (shapeid_t k = 0; k < g->stemV.length; k++) {
112  bufwrite8(buf, g->contourMasks.items[j].maskV[k]);
113  }
114  }
115  bufwrite8(buf, ')');
116  // instructions
117  bufwrite8(buf, 'I');
118  bufwrite32b(buf, g->instructionsLength);
119  bufwrite_bytes(buf, g->instructionsLength, g->instructions);
120  // Generate SHA1
121  SHA1_CTX ctx;
123  sha1_init(&ctx);
124  sha1_update(&ctx, buf->data, buflen(buf));
125  sha1_final(&ctx, hash);
126  GlyphHash h;
127  for (uint16_t j = 0; j < SHA1_BLOCK_SIZE; j++) {
128  h.hash[j] = hash[j];
129  }
130  buffree(buf);
131  return h;
132 }
133 
134 // Unconsolidation: Remove redundent data and de-couple internal data
135 // It does these things:
136 // 1. Merge hmtx data into glyf
137 // 2. Replace all glyph IDs into glyph names. Note all glyph references with
138 // same name whare one unique string entity stored in font->glyph_order.
139 // (Separate?)
142 
143  glyphid_t numGlyphs = font->glyf->length;
144  sds prefix;
145  if (options->glyph_name_prefix) {
146  prefix = sdsnew(options->glyph_name_prefix);
147  } else {
148  prefix = sdsempty();
149  }
150 
151  // pass 1: Map to existing glyph names
152  for (glyphid_t j = 0; j < numGlyphs; j++) {
153  glyf_Glyph *g = font->glyf->items[j];
154  if (options->name_glyphs_by_hash) { // name by hash
155  GlyphHash h = nameGlyphByHash(g, font->glyf);
156  sds gname = sdsempty();
157  for (uint16_t j = 0; j < SHA1_BLOCK_SIZE; j++) {
158  if (!(j % 4) && (j / 4)) {
159  gname = sdscatprintf(gname, "-%02X", h.hash[j]);
160  } else {
161  gname = sdscatprintf(gname, "%02X", h.hash[j]);
162  }
163  }
164  if (GlyphOrder.lookupName(glyph_order, gname)) {
165  // found duplicate glyph
166  glyphid_t n = 2;
167  bool stillIn = false;
168  do {
169  if (stillIn) n += 1;
170  sds newname = sdscatprintf(sdsempty(), "%s-%s%d", gname, prefix, n);
171  stillIn = GlyphOrder.lookupName(glyph_order, newname);
172  sdsfree(newname);
173  } while (stillIn);
174  sds newname = sdscatprintf(sdsempty(), "%s-%s%d", gname, prefix, n);
175  sds sharedName = GlyphOrder.setByGID(glyph_order, j, newname);
176  if (g->name) sdsfree(g->name);
177  g->name = sdsdup(sharedName);
178  sdsfree(gname);
179  } else {
180  sds sharedName = GlyphOrder.setByGID(glyph_order, j, gname);
181  if (g->name) sdsfree(g->name);
182  g->name = sdsdup(sharedName);
183  }
184  } else if (options->ignore_glyph_order || options->name_glyphs_by_gid) {
185  // ignore built-in names
186  // pass
187  } else if (g->name) {
188  sds gname = sdscatprintf(sdsempty(), "%s%s", prefix, g->name);
189  sds sharedName = GlyphOrder.setByGID(glyph_order, j, gname);
190  if (g->name) sdsfree(g->name);
191  g->name = sdsdup(sharedName);
192  }
193  }
194 
195  // pass 2: Map to `post` names
196  if (font->post != NULL && font->post->post_name_map != NULL && !options->ignore_glyph_order &&
197  !options->name_glyphs_by_gid) {
198  otfcc_GlyphOrderEntry *s, *tmp;
199  HASH_ITER(hhID, font->post->post_name_map->byGID, s, tmp) {
200  sds gname = sdscatprintf(sdsempty(), "%s%s", prefix, s->name);
201  GlyphOrder.setByGID(glyph_order, s->gid, gname);
202  }
203  }
204 
205  // pass 3: Map to AGLFN & Unicode
206  if (font->cmap && !options->name_glyphs_by_gid) {
207  otfcc_GlyphOrder *aglfn = GlyphOrder.create();
208  aglfn_setupNames(aglfn);
209 
210  cmap_Entry *s;
211  foreach_hash(s, font->cmap->unicodes) if (s->glyph.index > 0) {
212  sds name = NULL;
213  if (s->unicode > 0 && s->unicode < 0xFFFF) {
214  GlyphOrder.nameAField_Shared(aglfn, s->unicode, &name);
215  }
216  if (name == NULL) {
217  name = sdscatprintf(sdsempty(), "%suni%04X", prefix, s->unicode);
218  } else {
219  name = sdscatprintf(sdsempty(), "%s%s", prefix, name);
220  }
221  GlyphOrder.setByGID(glyph_order, s->glyph.index, name);
222  }
223 
224  GlyphOrder.free(aglfn);
225  }
226 
227  // pass 4 : Map to GID
228  for (glyphid_t j = 0; j < numGlyphs; j++) {
229  sds name;
230  if (j > 1) {
231  name = sdscatfmt(sdsempty(), "%sglyph%u", prefix, j);
232  } else if (j == 1) {
233  // GID 1 may often be ".null"
234  if (font->glyf->items[1] && !font->glyf->items[1]->contours.length &&
235  !font->glyf->items[1]->references.length) {
236  name = sdscatfmt(sdsempty(), "%s.null", prefix);
237  } else {
238  name = sdscatfmt(sdsempty(), "%sglyph%u", prefix, j);
239  }
240  } else {
241  name = sdscatfmt(sdsempty(), "%s.notdef", prefix);
242  }
243  GlyphOrder.setByGID(glyph_order, j, name);
244  }
245 
246  sdsfree(prefix);
247  return glyph_order;
248 }
249 
251  if (!gord) return;
252  for (glyphid_t j = 0; j < font->glyf->length; j++) {
253  glyf_Glyph *g = font->glyf->items[j];
254  sds glyphName = NULL;
255  GlyphOrder.nameAField_Shared(gord, j, &glyphName);
256  if (g->name) sdsfree(g->name);
257  g->name = sdsdup(glyphName);
258  }
259 }
260 
262  tableid_t totalRules = 0;
263  for (tableid_t j = 0; j < lookup->subtables.length; j++) {
264  if (!lookup->subtables.items[j]) continue;
265  if (lookup->subtables.items[j]->chaining.type == otl_chaining_poly) {
266  totalRules += lookup->subtables.items[j]->chaining.rulesCount;
267  } else if (lookup->subtables.items[j]->chaining.type == otl_chaining_canonical) {
268  totalRules += 1;
269  }
270  }
271  otl_SubtableList newsts;
272  otl_iSubtableList.init(&newsts);
273  for (tableid_t j = 0; j < lookup->subtables.length; j++) {
274  if (!lookup->subtables.items[j]) continue;
275  if (lookup->subtables.items[j]->chaining.type == otl_chaining_poly) {
276  for (tableid_t k = 0; k < lookup->subtables.items[j]->chaining.rulesCount; k++) {
277  otl_Subtable *st;
278  NEW(st);
279  st->chaining.type = otl_chaining_canonical;
280  // transfer ownership of rule
281  st->chaining.rule = *(lookup->subtables.items[j]->chaining.rules[k]);
282  FREE(lookup->subtables.items[j]->chaining.rules[k]);
283  otl_iSubtableList.push(&newsts, st);
284  }
285  FREE(lookup->subtables.items[j]->chaining.rules);
286  FREE(lookup->subtables.items[j]);
287  } else if (lookup->subtables.items[j]->chaining.type == otl_chaining_canonical) {
288  otl_Subtable *st;
289  NEW(st);
290  st->chaining.type = otl_chaining_canonical;
291  st->chaining.rule = lookup->subtables.items[j]->chaining.rule;
292  otl_iSubtableList.push(&newsts, st);
293  lookup->subtables.items[j] = NULL;
294  }
295  }
296  otl_iSubtableList.disposeDependent(&lookup->subtables, lookup);
297  lookup->subtables = newsts;
298 }
299 
301  switch (lookup->type) {
305  break;
306  default:
307  break;
308  }
309 }
310 
312  if (font->GSUB) {
313  for (uint32_t j = 0; j < font->GSUB->lookups.length; j++) {
314  otl_Lookup *lookup = font->GSUB->lookups.items[j];
315  expandChain(font, lookup, font->GSUB);
316  }
317  }
318  if (font->GPOS) {
319  for (uint32_t j = 0; j < font->GPOS->lookups.length; j++) {
320  otl_Lookup *lookup = font->GPOS->lookups.items[j];
321  expandChain(font, lookup, font->GPOS);
322  }
323  }
324 }
325 
326 static void mergeHmtx(otfcc_Font *font) {
327  // Merge hmtx table into glyf.
328  if (!(font->hhea && font->hmtx && font->glyf)) return;
329  uint32_t count_a = font->hhea->numberOfMetrics;
330  for (glyphid_t j = 0; j < font->glyf->length; j++) {
331  glyf_Glyph *g = font->glyf->items[j];
332  const pos_t adw = font->hmtx->metrics[(j < count_a ? j : count_a - 1)].advanceWidth;
333  const pos_t lsb =
334  j < count_a ? font->hmtx->metrics[j].lsb : font->hmtx->leftSideBearing[j - count_a];
335 
336  iVQ.inplacePlus(&g->advanceWidth, iVQ.createStill(adw));
337  iVQ.inplacePlus(&g->horizontalOrigin, iVQ.createStill(-lsb + g->stat.xMin));
338  }
339  table_iHmtx.free(font->hmtx);
340  font->hmtx = NULL;
341 }
342 
343 static void mergeVmtx(otfcc_Font *font) {
344  // Merge vmtx table into glyf.
345  if (!(font->vhea && font->vmtx && font->glyf)) return;
346  uint32_t count_a = font->vhea->numOfLongVerMetrics;
347 
348  pos_t *vorgs = NULL;
349 
350  if (font->VORG) {
351  NEW_CLEAN_N(vorgs, font->glyf->length);
352  for (glyphid_t j = 0; j < font->glyf->length; j++) {
353  vorgs[j] = font->VORG->defaultVerticalOrigin;
354  }
355  for (glyphid_t j = 0; j < font->VORG->numVertOriginYMetrics; j++) {
356  if (!(font->VORG->entries[j].gid < font->glyf->length)) continue;
357  vorgs[font->VORG->entries[j].gid] = font->VORG->entries[j].verticalOrigin;
358  }
359  table_iVORG.free(font->VORG);
360  font->VORG = NULL;
361  }
362 
363  for (glyphid_t j = 0; j < font->glyf->length; j++) {
364  glyf_Glyph *g = font->glyf->items[j];
365  const pos_t adh = font->vmtx->metrics[(j < count_a ? j : count_a - 1)].advanceHeight;
366  const pos_t tsb =
367  j < count_a ? font->vmtx->metrics[j].tsb : font->vmtx->topSideBearing[j - count_a];
368 
369  iVQ.inplacePlus(&g->advanceHeight, iVQ.createStill(adh));
370  iVQ.inplacePlus(&g->verticalOrigin, iVQ.createStill(vorgs ? vorgs[j] : tsb + g->stat.yMax));
371  }
372 
373  if (vorgs) FREE(vorgs);
374  table_iVmtx.free(font->vmtx);
375  font->vmtx = NULL;
376 }
377 
378 static void mergeLTSH(otfcc_Font *font) {
379  if (font->glyf && font->LTSH) {
380  for (glyphid_t j = 0; j < font->glyf->length && j < font->LTSH->numGlyphs; j++) {
381  font->glyf->items[j]->yPel = font->LTSH->yPels[j];
382  }
383  }
384 }
385 
387  // Merge metrics
388  mergeHmtx(font);
389  mergeVmtx(font);
390  mergeLTSH(font);
391  // expand chaining lookups
393  // Name glyphs
394  if (font->glyf) {
396  nameGlyphs(font, gord);
397  GlyphOrder.free(gord);
398  }
399 }
#define buflen
Definition: afm2pl.c:181
void aglfn_setupNames(otfcc_GlyphOrder *map)
Definition: aglfn.c:5
#define GlyphOrder
Definition: aglfn.c:2
#define name
#define hash
Definition: aptex.h:388
#define n
Definition: t4ht.c:1290
int h
Definition: dviconv.c:9
char * newname(char *name, const char *ext)
Definition: filenames.c:64
#define s
Definition: afcover.h:80
#define c(n)
Definition: gpos-common.c:150
const unsigned char FREE
Definition: image.cpp:34
@ otl_type_gsub_chaining
Definition: otl.h:18
@ otl_type_gpos_chaining
Definition: otl.h:30
otl_iSubtableList
Definition: otl.h:206
@ otl_chaining_canonical
Definition: otl.h:70
@ otl_chaining_poly
Definition: otl.h:72
#define NULL
Definition: ftobjs.h:61
#define NEW
Definition: gdkanji.c:77
unsigned short uint16_t
Definition: stdint.h:79
unsigned int uint32_t
Definition: stdint.h:80
unsigned char uint8_t
Definition: stdint.h:78
#define buf
#define prefix
Definition: cwebboot.c:154
#define foreach_hash(id, range)
Definition: aliases.h:39
float x
Definition: cordic.py:15
#define NEW_CLEAN_N(ptr, n)
Definition: otfcc-alloc.h:72
int k
Definition: otp-parser.c:70
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst st
int g
Definition: ppmqvga.c:68
int r
Definition: ppmqvga.c:68
double pos_t
Definition: primitives.h:24
uint16_t tableid_t
Definition: primitives.h:17
uint16_t shapeid_t
Definition: primitives.h:19
uint16_t glyphid_t
Definition: primitives.h:14
int16_t otfcc_to_f2dot14(const double x)
Definition: primitives.c:9
f16dot16 otfcc_to_fixed(const double x)
Definition: primitives.c:17
void bufwrite32b(caryll_Buffer *buf, uint32_t x)
Definition: buffer.c:82
void bufwrite8(caryll_Buffer *buf, uint8_t byte)
Definition: buffer.c:49
void buffree(caryll_Buffer *buf)
Definition: buffer.c:10
void bufwrite16b(caryll_Buffer *buf, uint16_t x)
Definition: buffer.c:58
void bufwrite_bytes(caryll_Buffer *buf, size_t size, const uint8_t *str)
Definition: buffer.c:149
caryll_Buffer * bufnew(void)
Definition: buffer.c:4
sds sdscatprintf(sds s, const char *fmt,...)
void sdsfree(sds s)
sds sdsnew(const char *init)
sds sdscatfmt(sds s, char const *fmt,...)
sds sdsdup(const sds s)
char * sds
Definition: sds.h:41
sds sdsempty(void)
Definition: sha1.h:22
Definition: vq.h:37
Definition: cmap.h:7
Definition: pbmfont.h:11
struct fontmetrics metrics
Definition: nsfix.c:69
Definition: zic.c:306
uint16 type
Definition: parsettfatt.c:198
Definition: stemdb.c:56
Definition: otl.h:253
glyf_GlyphPtr * items
Definition: glyf.d:18132
Definition: table.h:30
pos_t peak
Definition: region.h:12
pos_t start
Definition: region.h:11
pos_t end
Definition: region.h:13
Definition: vq.h:13
static HashMap< PermString, int > glyph_order(-1)
int j
Definition: t4ht.c:1589
static GlyphHash nameGlyphByHash(glyf_Glyph *g, table_glyf *glyf)
Definition: unconsolidate.c:35
static void hashVQ(caryll_Buffer *buf, VQ x)
Definition: unconsolidate.c:27
static void hashVQS(caryll_Buffer *buf, vq_Segment s)
Definition: unconsolidate.c:9
static void mergeHmtx(otfcc_Font *font)
static void expandChain(otfcc_Font *font, otl_Lookup *lookup, table_OTL *table)
static void expandChainingLookups(otfcc_Font *font)
void otfcc_unconsolidateFont(otfcc_Font *font, const otfcc_Options *options)
static void nameGlyphs(otfcc_Font *font, otfcc_GlyphOrder *gord)
static otfcc_GlyphOrder * createGlyphOrder(otfcc_Font *font, const otfcc_Options *options)
static void unconsolidate_chaining(otfcc_Font *font, otl_Lookup *lookup, table_OTL *table)
static void mergeVmtx(otfcc_Font *font)
static void mergeLTSH(otfcc_Font *font)
#define HASH_ITER(hh, head, el, tmp)
Definition: uthash.h:1131
iVQ
Definition: vq.h:60
@ VQ_DELTA
Definition: vq.h:12
@ VQ_STILL
Definition: vq.h:12
void sha1_final(SHA1_CTX *ctx, BYTE hash[])
Definition: sha1.c:105
void sha1_update(SHA1_CTX *ctx, const BYTE data[], size_t len)
Definition: sha1.c:91
void sha1_init(SHA1_CTX *ctx)
Definition: sha1.c:77
#define SHA1_BLOCK_SIZE
Definition: sha1.h:16