parseGlyph function
dynamic
parseGlyph(
- dynamic glyph,
- dynamic data,
- dynamic start
Implementation
parseGlyph(glyph, data, start) {
var p = new Parser(data, start);
glyph.numberOfContours = p.parseShort();
glyph.xMin = p.parseShort();
glyph.yMin = p.parseShort();
glyph.xMax = p.parseShort();
glyph.yMax = p.parseShort();
var flags;
var flag;
if (glyph.numberOfContours > 0) {
// This glyph is not a composite.
glyph.endPointIndices = [];
var endPointIndices = glyph.endPointIndices;
for (var i = 0; i < glyph.numberOfContours; i += 1) {
endPointIndices.add(p.parseUShort());
}
glyph.instructionLength = p.parseUShort();
glyph.instructions = [];
for (var i = 0; i < glyph.instructionLength; i += 1) {
glyph.instructions.add(p.parseByte());
}
var numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1;
flags = [];
for (var i = 0; i < numberOfCoordinates; i += 1) {
flag = p.parseByte();
flags.add(flag);
// If bit 3 is set, we repeat this flag n times, where n is the next byte.
if ((flag & 8) > 0) {
var repeatCount = p.parseByte();
for (var j = 0; j < repeatCount; j += 1) {
flags.add(flag);
i += 1;
}
}
}
argument(flags.length == numberOfCoordinates, 'Bad flags.');
if (endPointIndices.length > 0) {
var points = [];
var point;
// X/Y coordinates are relative to the previous point, except for the first point which is relative to 0,0.
if (numberOfCoordinates > 0) {
for (var i = 0; i < numberOfCoordinates; i += 1) {
flag = flags[i];
point = {};
point["onCurve"] = (flag & 1) == 1;
point["lastPointOfContour"] = endPointIndices.indexOf(i) >= 0;
points.add(point);
}
var px = 0;
for (var i = 0; i < numberOfCoordinates; i += 1) {
flag = flags[i];
point = points[i];
point["x"] = parseGlyphCoordinate(p, flag, px, 2, 16);
px = point["x"];
}
var py = 0;
for (var i = 0; i < numberOfCoordinates; i += 1) {
flag = flags[i];
point = points[i];
point["y"] = parseGlyphCoordinate(p, flag, py, 4, 32);
py = point["y"];
}
}
glyph.points = points;
} else {
glyph.points = [];
}
} else if (glyph.numberOfContours == 0) {
glyph.points = [];
} else {
glyph.isComposite = true;
glyph.points = [];
glyph.components = [];
var moreComponents = true;
while (moreComponents) {
flags = p.parseUShort();
var component = {
"glyphIndex": p.parseUShort(),
"xScale": 1,
"scale01": 0,
"scale10": 0,
"yScale": 1,
"dx": 0,
"dy": 0
};
if ((flags & 1) > 0) {
// The arguments are words
if ((flags & 2) > 0) {
// values are offset
component["dx"] = p.parseShort();
component["dy"] = p.parseShort();
} else {
// values are matched points
component["matchedPoints"] = [p.parseUShort(), p.parseUShort()];
}
} else {
// The arguments are bytes
if ((flags & 2) > 0) {
// values are offset
component["dx"] = p.parseChar();
component["dy"] = p.parseChar();
} else {
// values are matched points
component["matchedPoints"] = [p.parseByte(), p.parseByte()];
}
}
if ((flags & 8) > 0) {
// We have a scale
component["xScale"] = component["yScale"] = p.parseF2Dot14();
} else if ((flags & 64) > 0) {
// We have an X / Y scale
component["xScale"] = p.parseF2Dot14();
component["yScale"] = p.parseF2Dot14();
} else if ((flags & 128) > 0) {
// We have a 2x2 transformation
component["xScale"] = p.parseF2Dot14();
component["scale01"] = p.parseF2Dot14();
component["scale10"] = p.parseF2Dot14();
component["yScale"] = p.parseF2Dot14();
}
glyph.components.add(component);
moreComponents = !!(flags & 32);
}
if (flags & 0x100) {
// We have instructions
glyph.instructionLength = p.parseUShort();
glyph.instructions = [];
for (var i = 0; i < glyph.instructionLength; i += 1) {
glyph.instructions.add(p.parseByte());
}
}
}
}