public bool SetComponents(WoffReader reader) { uint startOffset = reader.Offset; bool weHaveInstructions = false; ushort flags = MORE_COMPONENTS; while ((flags & MORE_COMPONENTS) > 0) { flags = reader.ReadUInt16(); weHaveInstructions |= (flags & WE_HAVE_INSTRUCTIONS) != 0; ushort argSize = WoffBuffer.SizeOfUShort; // 2-bytes glyph index if ((flags & ARG_1_AND_2_ARE_WORDS) > 0) { argSize += WoffBuffer.SizeOfUShort * 2; // 4-bytes } else { argSize += WoffBuffer.SizeOfUShort; // 2-bytes } if ((flags & WE_HAVE_A_SCALE) > 0) { argSize += WoffBuffer.SizeOfUShort; // 2-bytes } else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) > 0) { argSize += WoffBuffer.SizeOfUShort * 2; // 4-bytes } else if ((flags & WE_HAVE_A_TWO_BY_TWO) > 0) { argSize += WoffBuffer.SizeOfUShort * 4; // 8-bytes } if (!reader.Skip(argSize)) { return(false); } } uint endOffset = reader.Offset; _hasInstructions = weHaveInstructions; _componentLength = (ushort)(endOffset - startOffset); _components = reader.ReadByte(_componentLength, startOffset); Debug.Assert(reader.Offset == endOffset); return(reader.Offset == endOffset); }
private bool TransformHmtx() { var glyfTable = _woffFont.Tables[_glyfIndex] as WoffTableGlyf; Debug.Assert(glyfTable != null); if (glyfTable == null) { return(false); } if (_hheaIndex == -1 || _hmtxIndex == -1) { return(false); } var glyphs = glyfTable.Glyphs; var glyphAdvances = glyfTable.GlyphsAdvances; var woffDirs = _woffFont.Directories; var hheaDir = woffDirs[_hheaIndex]; // Get numberOfHMetrics, https://www.microsoft.com/typography/otspec/hhea.htm var hheaReader = new WoffReader(hheaDir.OrigTable); // Skip 34 to reach 'hhea' numberOfHMetrics if (hheaReader.Skip(34) == false) { return(false); } ushort numOfHMetrics = hheaReader.ReadUInt16(); var reader = new WoffReader(_woffDir.CompTable); var flags = reader.ReadByte(); // By the specs: When hmtx transform is indicated by the table directory, // the Flags (bits 0 or 1 or both) must be set. if ((flags & 0x01) != 1 && (flags & 0x02) != 1) { Trace.TraceError("Hmtx Compression Error: When hmtx transform is indicated by the table directory, " + "the Flags (bits 0 or 1 or both) must be set."); return(false); } // By the specs: Bits 2-7 are reserved and must be zero. if ((flags & 0xFC) != 0) { Trace.TraceError("Hmtx Compression Error: Bits 2-7 are reserved and must be zero."); } int numOfGlyphs = glyphs.Length; Debug.Assert(glyphAdvances.Length == numOfGlyphs); // The number of glyphs numGlyphs can be 0, if there is no 'glyf' but cannot then xform 'hmtx'. Debug.Assert(numOfHMetrics <= numOfGlyphs); if (numOfHMetrics > numOfGlyphs) { return(false); } // https://www.microsoft.com/typography/otspec/hmtx.htm // "...only one entry need be in the array, but that entry is required." if (numOfHMetrics < 1) { return(false); } bool hasProportionalLsbs = (flags & 0x01) == 0; bool hasMonospaceLsbs = (flags & 0x02) == 0; IList <ushort> advanceWidths = new List <ushort>(); IList <short> lsbs = new List <short>(); for (ushort glyphIndex = 0; glyphIndex < numOfHMetrics; glyphIndex++) { advanceWidths.Add(reader.ReadUInt16()); } for (ushort glyphIndex = 0; glyphIndex < numOfHMetrics; glyphIndex++) { if (hasProportionalLsbs) { lsbs.Add(reader.ReadInt16()); } else { lsbs.Add(glyphAdvances[glyphIndex]); } } for (ushort glyphIndex = numOfHMetrics; glyphIndex < numOfGlyphs; glyphIndex++) { if (hasMonospaceLsbs) { lsbs.Add(reader.ReadInt16()); } else { lsbs.Add(glyphAdvances[glyphIndex]); } } return(SerializeHmtx(advanceWidths, lsbs, numOfHMetrics, numOfGlyphs)); }