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)  

read.c
Go to the documentation of this file.
1 #include "../glyf.h"
2 
3 #include "support/util.h"
5 
7  if (*cp >= contours->items[*cc].length) {
8  *cp = 0;
9  *cc += 1;
10  }
11  return &contours->items[*cc].items[(*cp)++];
12 }
13 
15  const otfcc_Options *options) {
17  glyf_ContourList *contours = &g->contours;
18 
19  shapeid_t pointsInGlyph = 0;
20  for (shapeid_t j = 0; j < numberOfContours; j++) {
21  shapeid_t lastPointInCurrentContour = read_16u(start + 2 * j);
23  glyf_iContour.init(&contour);
24  glyf_iContour.fill(&contour, lastPointInCurrentContour - pointsInGlyph + 1);
25  glyf_iContourList.push(contours, contour);
26  pointsInGlyph = lastPointInCurrentContour + 1;
27  }
28  uint16_t instructionLength = read_16u(start + 2 * numberOfContours);
29  uint8_t *instructions = NULL;
30  if (instructionLength > 0) {
31  NEW(instructions, instructionLength);
32  memcpy(instructions, start + 2 * numberOfContours + 2, sizeof(uint8_t) * instructionLength);
33  }
34  g->instructionsLength = instructionLength;
35  g->instructions = instructions;
36 
37  // read flags
38  // There are repeating entries in the flags list, we will fill out the
39  // result
41  NEW(flags, pointsInGlyph);
42  font_file_pointer flagStart = start + 2 * numberOfContours + 2 + instructionLength;
43  shapeid_t flagsReadSofar = 0;
44  shapeid_t flagBytesReadSofar = 0;
45 
46  shapeid_t currentContour = 0;
47  shapeid_t currentContourPointIndex = 0;
48  while (flagsReadSofar < pointsInGlyph) {
49  uint8_t flag = flagStart[flagBytesReadSofar];
50  flags[flagsReadSofar] = flag;
51  flagBytesReadSofar += 1;
52  flagsReadSofar += 1;
53  next_point(contours, &currentContour, &currentContourPointIndex)->onCurve =
55  if (flag & GLYF_FLAG_REPEAT) { // repeating flag
56  uint8_t repeat = flagStart[flagBytesReadSofar];
57  flagBytesReadSofar += 1;
58  for (uint8_t j = 0; j < repeat; j++) {
59  flags[flagsReadSofar + j] = flag;
60  next_point(contours, &currentContour, &currentContourPointIndex)->onCurve =
62  }
63  flagsReadSofar += repeat;
64  }
65  }
66 
67  // read X coordinates
68  font_file_pointer coordinatesStart = flagStart + flagBytesReadSofar;
69  uint32_t coordinatesOffset = 0;
70  shapeid_t coordinatesRead = 0;
71  currentContour = 0;
72  currentContourPointIndex = 0;
73  while (coordinatesRead < pointsInGlyph) {
74  uint8_t flag = flags[coordinatesRead];
75  int16_t x;
76  if (flag & GLYF_FLAG_X_SHORT) {
77  x = (flag & GLYF_FLAG_POSITIVE_X ? 1 : -1) *
78  read_8u(coordinatesStart + coordinatesOffset);
79  coordinatesOffset += 1;
80  } else {
81  if (flag & GLYF_FLAG_SAME_X) {
82  x = 0;
83  } else {
84  x = read_16s(coordinatesStart + coordinatesOffset);
85  coordinatesOffset += 2;
86  }
87  }
88  iVQ.replace(&(next_point(contours, &currentContour, &currentContourPointIndex)->x),
89  iVQ.createStill(x));
90  coordinatesRead += 1;
91  }
92  // read Y, identical to X
93  coordinatesRead = 0;
94  currentContour = 0;
95  currentContourPointIndex = 0;
96  while (coordinatesRead < pointsInGlyph) {
97  uint8_t flag = flags[coordinatesRead];
98  int16_t y;
99  if (flag & GLYF_FLAG_Y_SHORT) {
100  y = (flag & GLYF_FLAG_POSITIVE_Y ? 1 : -1) *
101  read_8u(coordinatesStart + coordinatesOffset);
102  coordinatesOffset += 1;
103  } else {
104  if (flag & GLYF_FLAG_SAME_Y) {
105  y = 0;
106  } else {
107  y = read_16s(coordinatesStart + coordinatesOffset);
108  coordinatesOffset += 2;
109  }
110  }
111  iVQ.replace(&(next_point(contours, &currentContour, &currentContourPointIndex)->y),
112  iVQ.createStill(y));
113  coordinatesRead += 1;
114  }
115  FREE(flags);
116 
117  // turn deltas to absolute coordiantes
118  VQ cx = iVQ.neutral(), cy = iVQ.neutral();
119  for (shapeid_t j = 0; j < numberOfContours; j++) {
120  for (shapeid_t k = 0; k < contours->items[j].length; k++) {
121  glyf_Point *z = &contours->items[j].items[k];
122  iVQ.inplacePlus(&cx, z->x);
123  iVQ.inplacePlus(&cy, z->y);
124  iVQ.copyReplace(&z->x, cx);
125  iVQ.copyReplace(&z->y, cy);
126  }
127  glyf_iContour.shrinkToFit(&contours->items[j]);
128  }
129  glyf_iContourList.shrinkToFit(contours);
130  iVQ.dispose(&cx), iVQ.dispose(&cy);
131  return g;
132 }
133 
135  const otfcc_Options *options) {
137 
138  // pass 1, read references quantity
139  uint16_t flags = 0;
140  uint32_t offset = 0;
141  bool glyphHasInstruction = false;
142  do {
143  flags = read_16u(start + offset);
145 
147  ref.glyph = Handle.fromIndex(index);
148 
149  offset += 4; // flags & index
150  if (flags & ARGS_ARE_XY_VALUES) {
151  ref.isAnchored = REF_XY;
153  ref.x = iVQ.createStill(read_16s(start + offset));
154  ref.y = iVQ.createStill(read_16s(start + offset + 2));
155  offset += 4;
156  } else {
157  ref.x = iVQ.createStill(read_8s(start + offset));
158  ref.y = iVQ.createStill(read_8s(start + offset + 1));
159  offset += 2;
160  }
161  } else {
162  ref.isAnchored = REF_ANCHOR_ANCHOR;
164  ref.outer = read_16u(start + offset);
165  ref.inner = read_16u(start + offset + 2);
166  offset += 4;
167  } else {
168  ref.outer = read_8u(start + offset);
169  ref.inner = read_8u(start + offset + 1);
170  offset += 2;
171  }
172  }
173  if (flags & WE_HAVE_A_SCALE) {
175  offset += 2;
176  } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
179  offset += 4;
180  } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
185  offset += 8;
186  }
187  ref.roundToGrid = flags & ROUND_XY_TO_GRID;
188  ref.useMyMetrics = flags & USE_MY_METRICS;
191  logWarning("glyf: SCALED_COMPONENT_OFFSET is not supported.")
192  }
193  if (flags & WE_HAVE_INSTRUCTIONS) { glyphHasInstruction = true; }
194  glyf_iReferenceList.push(&g->references, ref);
195  } while (flags & MORE_COMPONENTS);
196 
197  if (glyphHasInstruction) {
198  uint16_t instructionLength = read_16u(start + offset);
199  font_file_pointer instructions = NULL;
200  if (instructionLength > 0) {
201  NEW(instructions, instructionLength);
202  memcpy(instructions, start + offset + 2, sizeof(uint8_t) * instructionLength);
203  }
204  g->instructionsLength = instructionLength;
205  g->instructions = instructions;
206  } else {
207  g->instructionsLength = 0;
208  g->instructions = NULL;
209  }
210 
211  return g;
212 }
213 
215  const otfcc_Options *options) {
217  int16_t numberOfContours = read_16u(start);
218  glyf_Glyph *g;
219  if (numberOfContours > 0) {
220  g = otfcc_read_simple_glyph(start + 10, numberOfContours, options);
221  } else {
223  }
224  g->stat.xMin = read_16s(start + 2);
225  g->stat.yMin = read_16s(start + 4);
226  g->stat.xMax = read_16s(start + 6);
227  g->stat.yMax = read_16s(start + 8);
228  return g;
229 }
230 
231 // common states of tuple polymorphizer
232 
233 typedef struct {
239  bool allowIUP;
242 
243 // GVAR header
244 #pragma pack(1)
245 struct GVARHeader {
254 };
255 
259 };
263  struct TupleVariationHeader tvhs[];
264 };
265 #pragma pack()
266 
267 #define GVAR_OFFSETS_ARE_LONG 1
268 #define EMBEDDED_PEAK_TUPLE 0x8000
269 #define INTERMEDIATE_REGION 0x4000
270 #define PRIVATE_POINT_NUMBERS 0x2000
271 #define TUPLE_INDEX_MASK 0xFFF
272 
273 static INLINE struct TupleVariationHeader *nextTVH(struct TupleVariationHeader *currentHeader,
274  const TuplePolymorphizerCtx *ctx) {
275  uint32_t bump = 2 * sizeof(uint16_t);
276  uint16_t tupleIndex = be16(currentHeader->tupleIndex);
277  if (tupleIndex & EMBEDDED_PEAK_TUPLE) bump += ctx->dimensions * sizeof(f2dot14);
278  if (tupleIndex & INTERMEDIATE_REGION) bump += 2 * ctx->dimensions * sizeof(f2dot14);
279  return (struct TupleVariationHeader *)((font_file_pointer)currentHeader + bump);
280 }
281 
282 #define POINT_COUNT_IS_WORD 0x80
283 #define POINT_COUNT_LONG_MASK 0x7FFF
284 #define POINT_RUN_COUNT_MASK 0x7F
285 #define POINTS_ARE_WORDS 0x80
286 
288  shapeid_t *pc, shapeid_t totalPoints) {
289  uint16_t nPoints = 0;
290  uint8_t firstByte = *data;
291  if (firstByte & POINT_COUNT_IS_WORD) {
292  nPoints = (data[0] << 8 | data[1]) & POINT_COUNT_LONG_MASK;
293  data += 2;
294  } else {
295  nPoints = firstByte;
296  data++;
297  }
298  if (nPoints > 0) {
299  struct {
301  bool wide;
302  } run = {0, false};
303  shapeid_t filled = 0;
304  shapeid_t jPoint = 0;
305  NEW_CLEAN_N(*pointIndeces, nPoints);
306  while (filled < nPoints) {
307  if (run.length == 0) {
308  uint8_t runHeader = *data++;
309  run.wide = !!(runHeader & POINTS_ARE_WORDS);
310  run.length = (runHeader & POINT_RUN_COUNT_MASK) + 1;
311  }
312  int16_t pointNumber = jPoint;
313  if (run.wide) {
314  pointNumber += *((uint16_t *)data);
315  data += 2;
316  } else {
317  pointNumber += *data++;
318  }
319  (*pointIndeces)[filled] = pointNumber;
320  filled++;
321  jPoint = pointNumber;
322  --run.length;
323  }
324  *pc = nPoints;
325  } else {
326  NEW_CLEAN_N(*pointIndeces, totalPoints);
327  for (shapeid_t j = 0; j < totalPoints; j++) {
328  (*pointIndeces)[j] = j;
329  }
330  *pc = totalPoints;
331  }
332 
333  return data;
334 }
335 
336 #define DELTAS_ARE_ZERO 0x80
337 #define DELTAS_ARE_WORDS 0x40
338 #define DELTA_RUN_COUNT_MASK 0x3F
339 
341  pos_t *deltas) {
342  struct {
344  bool wide;
345  bool zero;
346  } run = {0, false, false};
347  shapeid_t filled = 0;
348  while (filled < nPoints) {
349  int16_t delta = 0;
350  if (run.length == 0) {
351  uint8_t runHeader = *data++;
352  run.zero = runHeader & DELTAS_ARE_ZERO;
353  run.wide = runHeader & DELTAS_ARE_WORDS;
354  run.length = (runHeader & DELTA_RUN_COUNT_MASK) + 1;
355  }
356  if (!run.zero) {
357  if (run.wide) {
358  delta = (int16_t)be16(*(uint16_t *)data);
359  data += 2;
360  } else {
361  delta = (int8_t)*data;
362  data++;
363  }
364  }
365  deltas[filled] = (pos_t)delta;
366  filled++;
367  --run.length;
368  }
369  return data;
370 }
371 
372 typedef VQ *(*CoordPartGetter)(glyf_Point *z);
373 
374 static VQ *getX(glyf_Point *z) {
375  return &z->x;
376 }
377 static VQ *getY(glyf_Point *z) {
378  return &z->y;
379 }
380 
381 static INLINE void fillTheGaps(shapeid_t jMin, shapeid_t jMax, vq_Segment *nudges,
382  glyf_Point **glyphRefs, CoordPartGetter getter) {
383  for (shapeid_t j = jMin; j < jMax; j++) {
384  if (nudges[j].val.delta.touched) continue;
385  // get next knot
386  shapeid_t jNext = j;
387  while (!nudges[jNext].val.delta.touched) {
388  if (jNext == jMax - 1) {
389  jNext = jMin;
390  } else {
391  jNext += 1;
392  }
393  if (jNext == j) break;
394  }
395  // get pre knot
396  shapeid_t jPrev = j;
397  while (!nudges[jPrev].val.delta.touched) {
398  if (jPrev == jMin) {
399  jPrev = jMax - 1;
400  } else {
401  jPrev -= 1;
402  }
403  if (jPrev == j) break;
404  }
405  if (nudges[jNext].val.delta.touched && nudges[jPrev].val.delta.touched) {
406  f16dot16 untouchJ = otfcc_to_fixed(getter(glyphRefs[j])->kernel);
407  f16dot16 untouchPrev = otfcc_to_fixed(getter(glyphRefs[jPrev])->kernel);
408  f16dot16 untouchNext = otfcc_to_fixed(getter(glyphRefs[jNext])->kernel);
409  f16dot16 deltaPrev = otfcc_to_fixed(nudges[jPrev].val.delta.quantity);
410  f16dot16 deltaNext = otfcc_to_fixed(nudges[jNext].val.delta.quantity);
411 
412  f16dot16 uMin = untouchPrev;
413  f16dot16 uMax = untouchNext;
414  f16dot16 dMin = deltaPrev;
415  f16dot16 dMax = deltaNext;
416  if (untouchPrev > untouchNext) {
417  uMin = untouchNext;
418  uMax = untouchPrev;
419  dMin = deltaNext;
420  dMax = deltaPrev;
421  }
422  if (untouchJ <= uMin) {
423  nudges[j].val.delta.quantity = otfcc_from_fixed(dMin);
424  } else if (untouchJ >= uMax) {
425  nudges[j].val.delta.quantity = otfcc_from_fixed(dMax);
426  } else {
427  nudges[j].val.delta.quantity =
428  otfcc_from_fixed(otfcc_f1616_muldiv(dMax - dMin, untouchJ - uMin, uMax - uMin));
429  }
430  }
431  }
432 }
433 
434 static void applyCoords(const shapeid_t totalPoints, glyf_Glyph *glyph,
435  glyf_Point **glyphRefs, // target
436  const shapeid_t nTouchedPoints, const pos_t *tupleDelta,
437  const shapeid_t *points,
438  const vq_Region *r, // data
439  CoordPartGetter getter) {
440  vq_Segment *nudges;
441  NEW_CLEAN_N(nudges, totalPoints);
442  for (shapeid_t j = 0; j < totalPoints; j++) {
443  nudges[j].type = VQ_DELTA;
444  nudges[j].val.delta.touched = false;
445  nudges[j].val.delta.quantity = 0;
446  nudges[j].val.delta.region = r;
447  }
448  for (shapeid_t j = 0; j < nTouchedPoints; j++) {
449  if (points[j] >= totalPoints) continue;
450  nudges[points[j]].val.delta.touched = true;
451  nudges[points[j]].val.delta.quantity += tupleDelta[j];
452  }
453  // fill the gaps
454  shapeid_t jFirst = 0;
455  foreach (glyf_Contour *c, glyph->contours) {
456  fillTheGaps(jFirst, jFirst + c->length, nudges, glyphRefs, getX);
457  jFirst += c->length;
458  }
459  for (shapeid_t j = 0; j < totalPoints; j++) {
460  if (!nudges[j].val.delta.quantity && nudges[j].val.delta.touched) continue;
461  VQ *coordinatePart = getter(glyphRefs[j]);
462  vq_iSegList.push(&(coordinatePart->shift), nudges[j]);
463  }
464  FREE(nudges);
465 }
466 
467 static INLINE void applyPolymorphism(const shapeid_t totalPoints, glyf_GlyphPtr glyph, // target
468  const shapeid_t nTouchedPoints, const shapeid_t *points,
469  const pos_t *deltaX, const pos_t *deltaY,
470  const vq_Region *r // delta data
471 ) {
472  glyf_Point **glyphRefs;
473  NEW_CLEAN_N(glyphRefs, totalPoints);
474  {
475  shapeid_t j = 0;
476  foreach (glyf_Contour *c, glyph->contours) {
477  foreach (glyf_Point *g, *c) { glyphRefs[j++] = g; }
478  }
479  foreach (glyf_ComponentReference *r, glyph->references) {
480  // in glyf_ComponentReference, we also have a X and a Y entry
481  // so a trick of conversion
482  glyphRefs[j++] = (glyf_Point *)&(r->x);
483  }
484  }
485  applyCoords(totalPoints, glyph, glyphRefs, nTouchedPoints, deltaX, points, r, getX);
486  applyCoords(totalPoints, glyph, glyphRefs, nTouchedPoints, deltaY, points, r, getY);
487  // Horizontal phantom point
488  if (totalPoints + 1 < nTouchedPoints) {
489  iVQ.addDelta(&(glyph->horizontalOrigin), true, r, deltaX[totalPoints]);
490  iVQ.addDelta(&(glyph->advanceWidth), true, r,
491  deltaX[totalPoints + 1] - deltaX[totalPoints]);
492  }
493  // Vertical phantom point
494  if (totalPoints + 3 < nTouchedPoints) {
495  iVQ.addDelta(&(glyph->verticalOrigin), true, r, deltaY[totalPoints + 2]);
496  iVQ.addDelta(&(glyph->advanceHeight), true, r,
497  deltaY[totalPoints + 2] - deltaY[totalPoints + 3]);
498  }
499 
500  FREE(glyphRefs);
501 }
502 
504  f2dot14 *end) {
506  for (uint16_t d = 0; d < dimensions; d++) {
507  pos_t peakVal = otfcc_from_f2dot14(be16(peak[d]));
508  vq_AxisSpan span = {peakVal <= 0 ? -1 : 0, peakVal, peakVal >= 0 ? 1 : 0};
509  if (start && end) {
510  span.start = otfcc_from_f2dot14(be16(start[d]));
511  span.end = otfcc_from_f2dot14(be16(end[d]));
512  }
513  r->spans[d] = span;
514  }
515  return r;
516 }
517 
519  const TuplePolymorphizerCtx *ctx,
520  struct GlyphVariationData *gvd, const otfcc_Options *options) {
521 
522  shapeid_t totalPoints = 0;
523  foreach (glyf_Contour *c, glyph->contours) { totalPoints += c->length; }
524  totalPoints += glyph->references.length;
525  shapeid_t totalDeltaEntries = totalPoints + ctx->nPhantomPoints;
526 
527  uint16_t nTuples = be16(gvd->tupleVariationCount) & 0xFFF;
528  struct TupleVariationHeader *tvh = gvd->tvhs;
529 
530  bool hasSharedPointNumbers = be16(gvd->tupleVariationCount) & 0x8000;
531  shapeid_t sharedPointCount = 0;
532  shapeid_t *sharedPointIndeces = NULL;
534  if (hasSharedPointNumbers) {
535  data = parsePointNumbers(data, &sharedPointIndeces, &sharedPointCount, totalDeltaEntries);
536  }
537 
538  size_t tsdStart = 0;
539 
540  for (uint16_t j = 0; j < nTuples; j++) {
541 
542  // Tuple options
544  bool hasEmbeddedPeak = be16(tvh->tupleIndex) & EMBEDDED_PEAK_TUPLE;
545  bool hasIntermediate = be16(tvh->tupleIndex) & INTERMEDIATE_REGION;
546 
547  // Peak tuple
548  f2dot14 *peak = NULL;
549  if (hasEmbeddedPeak) {
550  peak = (f2dot14 *)(((font_file_pointer)tvh) + 4);
551  } else {
552  peak = ctx->sharedTuples + ctx->dimensions * tupleIndex;
553  }
554 
555  // Intermediate tuple -- if present
556  f2dot14 *start = NULL;
557  f2dot14 *end = NULL;
558  if (hasIntermediate) {
559  start = (f2dot14 *)(((font_file_pointer)tvh) + 4 +
560  2 * (hasEmbeddedPeak ? 1 : 0) * ctx->dimensions);
561  end = (f2dot14 *)(((font_file_pointer)tvh) + 4 +
562  2 * (hasEmbeddedPeak ? 2 : 1) * ctx->dimensions);
563  }
564 
565  const vq_Region *r = table_iFvar.registerRegion(
566  ctx->fvar, createRegionFromTuples(ctx->dimensions, peak, start, end));
567 
568  // Pointer of tuple serialized data
569  font_file_pointer tsd = data + tsdStart;
570  // Point number term
571  shapeid_t nPoints = sharedPointCount;
572  shapeid_t *pointIndeces = sharedPointIndeces;
573 
574  if (be16(tvh->tupleIndex) & PRIVATE_POINT_NUMBERS) {
575  shapeid_t privatePointCount = 0;
576  shapeid_t *privatePointNumbers = NULL;
577  tsd =
578  parsePointNumbers(tsd, &privatePointNumbers, &privatePointCount, totalDeltaEntries);
579  nPoints = privatePointCount;
580  pointIndeces = privatePointNumbers;
581  }
582  if (pointIndeces) {
583  // Delta term
584  pos_t *deltaX = 0;
585  pos_t *deltaY = 0;
586  NEW_CLEAN_N(deltaX, nPoints);
587  NEW_CLEAN_N(deltaY, nPoints);
588 
589  tsd = readPackedDelta(tsd, nPoints, deltaX);
590  tsd = readPackedDelta(tsd, nPoints, deltaY);
591 
592  // Do polymorphize
593  applyPolymorphism(totalPoints, glyph, nPoints, pointIndeces, deltaX, deltaY, r);
594  FREE(deltaX);
595  FREE(deltaY);
596  }
597  // Cleanup
598  if (be16(tvh->tupleIndex) & PRIVATE_POINT_NUMBERS) { FREE(pointIndeces); }
599  tsdStart += be16(tvh->variationDataSize);
600 
601  tvh = nextTVH(tvh, ctx);
602  }
603  FREE(sharedPointIndeces);
604 }
605 
606 // NOTE: for polymorphize, we would
607 // TODO: polymorphize advanceWidth, verticalOrigin and advanceHeight
608 static INLINE void polymorphize(const otfcc_Packet packet, const otfcc_Options *options,
609  table_glyf *glyf, const GlyfIOContext *ctx) {
610  if (!ctx->fvar || !ctx->fvar->axes.length) return;
611  FOR_TABLE(OTFCC_CHR('g','v','a','r'), table) {
613  if (table.length < sizeof(struct GVARHeader)) return;
614  struct GVARHeader *header = (struct GVARHeader *)data;
615  if (be16(header->axisCount) != ctx->fvar->axes.length) {
616  logWarning("Axes number in GVAR and FVAR are inequal");
617  return;
618  };
619  for (glyphid_t j = 0; j < glyf->length; j++) {
620  TuplePolymorphizerCtx tpctx = {.fvar = ctx->fvar,
621  .dimensions = ctx->fvar->axes.length,
622  .nPhantomPoints = ctx->nPhantomPoints,
623  .sharedTupleCount = be16(header->sharedTupleCount),
624  .sharedTuples =
625  (f2dot14 *)(data + be32(header->sharedTuplesOffset)),
626  .coordDimensions = 2,
627  .allowIUP = glyf->items[j]->contours.length > 0};
628  uint32_t glyphVariationDataOffset = 0;
629  if (be16(header->flags) & GVAR_OFFSETS_ARE_LONG) {
630  glyphVariationDataOffset =
631  be32(((uint32_t *)(data + sizeof(struct GVARHeader)))[j]);
632  } else {
633  glyphVariationDataOffset =
634  2 * be16(((uint16_t *)(data + sizeof(struct GVARHeader)))[j]);
635  }
636  struct GlyphVariationData *gvd =
637  (struct GlyphVariationData *)(data + be32(header->glyphVariationDataArrayOffset) +
638  glyphVariationDataOffset);
639  polymorphizeGlyph(j, glyf->items[j], &tpctx, gvd, options);
640  }
641  }
642 }
643 
645  const GlyfIOContext *ctx) {
646  uint32_t *offsets = NULL;
647  table_glyf *glyf = NULL;
648 
649  NEW_CLEAN_N(offsets, (ctx->numGlyphs + 1));
650  if (!offsets) goto ABSENT;
651  bool foundLoca = false;
652 
653  // read loca
654  FOR_TABLE(OTFCC_CHR('l','o','c','a'), table) {
656  uint32_t length = table.length;
657  if (length < 2 * ctx->numGlyphs + 2) goto LOCA_CORRUPTED;
658  for (uint32_t j = 0; j < ctx->numGlyphs + 1; j++) {
659  if (ctx->locaIsLong) {
660  offsets[j] = read_32u(data + j * 4);
661  } else {
662  offsets[j] = read_16u(data + j * 2) * 2;
663  }
664  if (j > 0 && offsets[j] < offsets[j - 1]) goto LOCA_CORRUPTED;
665  }
666  foundLoca = true;
667  break;
668  LOCA_CORRUPTED:
669  logWarning("table 'loca' corrupted.\n");
670  if (offsets) { FREE(offsets), offsets = NULL; }
671  continue;
672  }
673  if (!foundLoca) goto ABSENT;
674 
675  // read glyf
676  FOR_TABLE(OTFCC_CHR('g','l','y','f'), table) {
678  uint32_t length = table.length;
679  if (length < offsets[ctx->numGlyphs]) goto GLYF_CORRUPTED;
680 
681  glyf = table_iGlyf.create();
682 
683  for (glyphid_t j = 0; j < ctx->numGlyphs; j++) {
684  if (offsets[j] < offsets[j + 1]) { // non-space glyph
685  table_iGlyf.push(glyf, otfcc_read_glyph(data, offsets[j], options));
686  } else { // space glyph
687  table_iGlyf.push(glyf, otfcc_newGlyf_glyph());
688  }
689  }
690  goto PRESENT;
691  GLYF_CORRUPTED:
692  logWarning("table 'glyf' corrupted.\n");
693  if (glyf) { DELETE(table_iGlyf.free, glyf), glyf = NULL; }
694  }
695  goto ABSENT;
696 
697 PRESENT:
698  if (offsets) { FREE(offsets), offsets = NULL; }
699  // We have glyf table read. Do polymorphize
700  polymorphize(packet, options, glyf, ctx);
701  return glyf;
702 
703 ABSENT:
704  if (offsets) { FREE(offsets), offsets = NULL; }
705  if (glyf) { FREE(glyf), glyf = NULL; }
706  return NULL;
707 }
vq_iSegList
Definition: CPAL.d:17843
cp
Definition: action.c:1035
static uint8_t read_8u(const uint8_t *src)
Definition: bin-io.h:118
static uint32_t read_32u(const uint8_t *src)
Definition: bin-io.h:132
static uint16_t read_16u(const uint8_t *src)
Definition: bin-io.h:121
static int16_t read_16s(const uint8_t *src)
Definition: bin-io.h:153
static uint16_t be16(uint16_t x)
Definition: bin-io.h:163
static int8_t read_8s(const uint8_t *src)
Definition: bin-io.h:150
static uint32_t be32(uint32_t x)
Definition: bin-io.h:166
#define OTFCC_CHR(a, b, c, d)
Definition: caryll-font.c:7
long pc
Definition: disdvi.c:114
int z
Definition: dviconv.c:26
struct rect data
Definition: dvipdfm.c:64
long int flag
Definition: f2c.h:53
glyf_iComponentReference
Definition: glyf.d:18080
glyf_iContour
Definition: glyf.d:18027
table_iGlyf
Definition: glyf.d:18133
glyf_iReferenceList
Definition: glyf.d:18082
glyf_iContourList
Definition: glyf.d:18030
#define c(n)
Definition: gpos-common.c:150
#define d(n)
Definition: gpos-common.c:151
int deltas[13]
Definition: gsftopk.c:1503
#define memcpy(d, s, n)
Definition: gsftopk.c:64
const unsigned char FREE
Definition: image.cpp:34
table_iFvar
Definition: fvar.h:38
@ REF_ANCHOR_ANCHOR
Definition: glyf.h:48
@ REF_XY
Definition: glyf.h:47
#define NULL
Definition: ftobjs.h:61
kerning y
Definition: ttdriver.c:212
#define WE_HAVE_A_SCALE
Definition: ttgload.c:73
#define MORE_COMPONENTS
Definition: ttgload.c:75
#define USE_MY_METRICS
Definition: ttgload.c:79
#define ARGS_ARE_XY_VALUES
Definition: ttgload.c:71
#define ROUND_XY_TO_GRID
Definition: ttgload.c:72
#define SCALED_COMPONENT_OFFSET
Definition: ttgload.c:81
int int double double double char double points
Definition: gdfx.h:18
int int cy
Definition: gdfx.h:13
int cx
Definition: gdfx.h:12
#define NEW
Definition: gdkanji.c:77
signed short int16_t
Definition: stdint.h:76
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 INLINE
Definition: port.h:26
#define WE_HAVE_INSTRUCTIONS
Definition: tt_glyf.c:196
#define WE_HAVE_AN_X_AND_Y_SCALE
Definition: tt_glyf.c:194
#define WE_HAVE_A_TWO_BY_TWO
Definition: tt_glyf.c:195
#define ARG_1_AND_2_ARE_WORDS
Definition: tt_glyf.c:188
#define length(c)
Definition: ctangleboot.c:65
#define logWarning(...)
Definition: aliases.h:14
#define Handle
Definition: aliases.h:45
uint8_t * font_file_pointer
Definition: aliases.h:41
#define FOR_TABLE(name, table)
Definition: aliases.h:33
@ GLYF_FLAG_X_SHORT
Definition: glyf.h:35
@ GLYF_FLAG_REPEAT
Definition: glyf.h:37
@ GLYF_FLAG_POSITIVE_Y
Definition: glyf.h:41
@ GLYF_FLAG_SAME_X
Definition: glyf.h:38
@ GLYF_FLAG_POSITIVE_X
Definition: glyf.h:40
@ GLYF_FLAG_ON_CURVE
Definition: glyf.h:34
@ GLYF_FLAG_SAME_Y
Definition: glyf.h:39
@ GLYF_FLAG_Y_SHORT
Definition: glyf.h:36
glyf_Glyph * otfcc_newGlyf_glyph(void)
Definition: glyf.d:20959
float x
Definition: cordic.py:15
def ref(x)
Definition: pdf-org.py:104
#define DELETE(fn, ptr)
Definition: otfcc-alloc.h:76
#define NEW_CLEAN_N(ptr, n)
Definition: otfcc-alloc.h:72
int k
Definition: otp-parser.c:70
static int delta
Definition: pbmtolj.c:36
struct @173 dimensions[]
#define zero
static int repeat
Definition: pnmtops.c:230
int g
Definition: ppmqvga.c:68
int r
Definition: ppmqvga.c:68
static int offset
Definition: ppmtogif.c:642
double pos_t
Definition: primitives.h:24
uint16_t shapeid_t
Definition: primitives.h:19
f16dot16 otfcc_f1616_muldiv(f16dot16 a, f16dot16 b, f16dot16 c)
Definition: primitives.c:60
uint16_t glyphid_t
Definition: primitives.h:14
int32_t f16dot16
Definition: primitives.h:9
double otfcc_from_f2dot14(const f2dot14 x)
Definition: primitives.c:6
double otfcc_from_fixed(const f16dot16 x)
Definition: primitives.c:14
int16_t f2dot14
Definition: primitives.h:8
f16dot16 otfcc_to_fixed(const double x)
Definition: primitives.c:17
#define flags
static vq_Region * createRegionFromTuples(uint16_t dimensions, f2dot14 *peak, f2dot14 *start, f2dot14 *end)
Definition: read.c:503
static INLINE void polymorphize(const otfcc_Packet packet, const otfcc_Options *options, table_glyf *glyf, const GlyfIOContext *ctx)
Definition: read.c:608
#define POINTS_ARE_WORDS
Definition: read.c:285
static glyf_Glyph * otfcc_read_simple_glyph(font_file_pointer start, shapeid_t numberOfContours, const otfcc_Options *options)
Definition: read.c:14
#define DELTAS_ARE_WORDS
Definition: read.c:337
#define POINT_COUNT_IS_WORD
Definition: read.c:282
#define DELTA_RUN_COUNT_MASK
Definition: read.c:338
static void applyCoords(const shapeid_t totalPoints, glyf_Glyph *glyph, glyf_Point **glyphRefs, const shapeid_t nTouchedPoints, const pos_t *tupleDelta, const shapeid_t *points, const vq_Region *r, CoordPartGetter getter)
Definition: read.c:434
#define INTERMEDIATE_REGION
Definition: read.c:269
static VQ * getY(glyf_Point *z)
Definition: read.c:377
#define PRIVATE_POINT_NUMBERS
Definition: read.c:270
#define POINT_COUNT_LONG_MASK
Definition: read.c:283
static INLINE void fillTheGaps(shapeid_t jMin, shapeid_t jMax, vq_Segment *nudges, glyf_Point **glyphRefs, CoordPartGetter getter)
Definition: read.c:381
static INLINE void polymorphizeGlyph(glyphid_t gid, glyf_GlyphPtr glyph, const TuplePolymorphizerCtx *ctx, struct GlyphVariationData *gvd, const otfcc_Options *options)
Definition: read.c:518
static INLINE font_file_pointer readPackedDelta(font_file_pointer data, shapeid_t nPoints, pos_t *deltas)
Definition: read.c:340
#define POINT_RUN_COUNT_MASK
Definition: read.c:284
table_glyf * otfcc_readGlyf(const otfcc_Packet packet, const otfcc_Options *options, const GlyfIOContext *ctx)
Definition: read.c:644
static INLINE font_file_pointer parsePointNumbers(font_file_pointer data, shapeid_t **pointIndeces, shapeid_t *pc, shapeid_t totalPoints)
Definition: read.c:287
static INLINE struct TupleVariationHeader * nextTVH(struct TupleVariationHeader *currentHeader, const TuplePolymorphizerCtx *ctx)
Definition: read.c:273
static glyf_Point * next_point(glyf_ContourList *contours, shapeid_t *cc, shapeid_t *cp)
Definition: read.c:6
#define EMBEDDED_PEAK_TUPLE
Definition: read.c:268
#define GVAR_OFFSETS_ARE_LONG
Definition: read.c:267
#define TUPLE_INDEX_MASK
Definition: read.c:271
static INLINE void applyPolymorphism(const shapeid_t totalPoints, glyf_GlyphPtr glyph, const shapeid_t nTouchedPoints, const shapeid_t *points, const pos_t *deltaX, const pos_t *deltaY, const vq_Region *r)
Definition: read.c:467
VQ *(* CoordPartGetter)(glyf_Point *z)
Definition: read.c:372
static glyf_Glyph * otfcc_read_composite_glyph(font_file_pointer start, const otfcc_Options *options)
Definition: read.c:134
#define DELTAS_ARE_ZERO
Definition: read.c:336
static glyf_Glyph * otfcc_read_glyph(font_file_pointer data, uint32_t offset, const otfcc_Options *options)
Definition: read.c:214
static VQ * getX(glyf_Point *z)
Definition: read.c:374
#define flag
Definition: round_prec.c:45
#define uint16_t
Definition: stdint.in.h:161
#define int8_t
Definition: stdint.in.h:153
#define int16_t
Definition: stdint.in.h:160
uint16_t majorVersion
Definition: read.c:246
uint32_t sharedTuplesOffset
Definition: read.c:250
uint16_t sharedTupleCount
Definition: read.c:249
uint16_t axisCount
Definition: read.c:248
uint16_t minorVersion
Definition: read.c:247
uint16_t flags
Definition: read.c:252
uint16_t glyphCount
Definition: read.c:251
uint32_t glyphVariationDataArrayOffset
Definition: read.c:253
bool locaIsLong
Definition: glyf.h:10
table_fvar * fvar
Definition: glyf.h:13
glyphid_t numGlyphs
Definition: glyf.h:11
shapeid_t nPhantomPoints
Definition: glyf.h:12
uint16_t dataOffset
Definition: read.c:262
struct TupleVariationHeader tvhs[]
Definition: read.c:263
uint16_t tupleVariationCount
Definition: read.c:261
uint8_t coordDimensions
Definition: read.c:238
table_fvar * fvar
Definition: read.c:234
uint16_t dimensions
Definition: read.c:235
f2dot14 * sharedTuples
Definition: read.c:237
uint16_t sharedTupleCount
Definition: read.c:236
shapeid_t nPhantomPoints
Definition: read.c:240
uint16_t variationDataSize
Definition: read.c:257
uint16_t tupleIndex
Definition: read.c:258
Definition: vq.h:37
vq_SegList shift
Definition: vq.h:39
Definition: pt1.h:140
size_t length
Definition: glyf.d:18029
glyf_Contour * items
Definition: glyf.d:18029
size_t length
Definition: glyf.d:18026
glyf_Point * items
Definition: glyf.d:18026
OWNING glyf_ContourList contours
Definition: glyf.h:101
int8_t onCurve
Definition: glyf.h:14
Definition: pbmfont.h:4
CONTOUR * contours
Definition: pt1.h:180
Definition: mendex.h:20
vf_Axes axes
Definition: fvar.h:28
glyf_GlyphPtr * items
Definition: glyf.d:18132
size_t length
Definition: glyf.d:18132
Definition: table.h:30
Definition: strexpr.c:21
size_t length
Definition: CPAL.d:20195
pos_t start
Definition: region.h:11
pos_t end
Definition: region.h:13
Definition: vq.h:13
bool touched
Definition: vq.h:19
union vq_Segment::@1805 val
struct vq_Segment::@1805::@1806 delta
const vq_Region * region
Definition: vq.h:20
VQSegType type
Definition: vq.h:14
pos_t quantity
Definition: vq.h:18
int j
Definition: t4ht.c:1589
vq_Region * vq_createRegion(shapeid_t dimensions)
Definition: region.c:4
@ start
Definition: preamble.c:52
iVQ
Definition: vq.h:60
@ VQ_DELTA
Definition: vq.h:12
#define end(cp)
Definition: zic.c:71