public void Read(TTF.TTFReader r) { r.ReadInt(out this.major); r.ReadInt(out this.minor); r.ReadInt(out this.hdrSize); r.ReadInt(out this.offSize); }
public void Read(TTF.TTFReader r) { r.ReadInt(out this.count); r.ReadInt(out this.offSize); this.offset = new List <uint>(); for (int i = 0; i < this.count + 1; ++i) { this.offset.Add(CFFFile.ReadOffset(r, this.offSize) - 1); } this.data = r.ReadBytes((int)this.offset[this.offset.Count - 1]); }
public static uint ReadOffset(TTF.TTFReader r, int offSize) { if (offSize == 1) { return((uint)(r.ReadUInt8() << 0)); } else if (offSize == 2) { return((uint)((r.ReadUInt8() << 8) | (r.ReadUInt8() << 0))); } else if (offSize == 3) { return((uint)((r.ReadUInt8() << 16) | (r.ReadUInt8() << 8) | (r.ReadUInt8() << 0))); } else { return((uint)((r.ReadUInt8() << 24) | (r.ReadUInt8() << 16) | (r.ReadUInt8() << 8) | (r.ReadUInt8() << 0))); } }
public uint ReadOffset(TTF.TTFReader r) { byte c = ReadOffSize(r); if (c == 1) { return((uint)(r.ReadUInt8() << 0)); } else if (c == 2) { return((uint)((r.ReadUInt8() << 8) | (r.ReadUInt8() << 0))); } else if (c == 3) { return((uint)((r.ReadUInt8() << 16) | (r.ReadUInt8() << 8) | (r.ReadUInt8() << 0))); } else { return((uint)((r.ReadUInt8() << 24) | (r.ReadUInt8() << 16) | (r.ReadUInt8() << 8) | (r.ReadUInt8() << 0))); } }
public void Read(TTF.TTFReader r) { long basePos = r.GetPosition(); this.header = new Header(); this.header.Read(r); this.nameIndex = new INDEX(); this.nameIndex.Read(r); string name = System.Text.ASCIIEncoding.ASCII.GetString(this.nameIndex.data); this.topDictIndex = new INDEX(); this.topDictIndex.Read(r); string topDict = System.Text.ASCIIEncoding.ASCII.GetString(this.topDictIndex.data); this.SetTopDICTDefaults(); // Kinda weird using the byte reader inside a read, but // it turns out to be convenient. TTF.TTFReaderBytes trbDict = new TTF.TTFReaderBytes(this.topDictIndex.data); List <Operand> dP = new List <Operand>(); // DICT Params (aka: operands) while (trbDict.GetPosition() < this.topDictIndex.data.Length) { Operand val = Operand.Read(trbDict); if (val.type == Operand.Type.Error) { // TODO: Error } else if (val.type == Operand.Type.Int || val.type == Operand.Type.Real) { dP.Add(val); continue; } // If it made it down to here, the type value is an operator switch (val.intVal) { case 0: // Version Operand.LoadParsed(dP, out this.versionSID); break; case 1: // Notice Operand.LoadParsed(dP, out this.noticeSID); break; case 2: // FullName Operand.LoadParsed(dP, out this.fullNameSID); break; case 3: // FamilyName Operand.LoadParsed(dP, out this.familyNameSID); break; case 4: // Weight Operand.LoadParsed(dP, out this.weightSID); break; case 5: // FontBBox Operand.LoadParsed(dP, this.fontBBox); break; case (12 << 8) | 0: // Copyright Operand.LoadParsed(dP, out this.copyrightSID); break; case (12 << 8) | 1: // isFixedPitch Operand.LoadParsed(dP, out this.isFixedPitch); //Bool break; case (12 << 8) | 2: // italicAngle Operand.LoadParsed(dP, out this.italicAngle); break; case (12 << 8) | 3: // UnderlinePosition Operand.LoadParsed(dP, out this.underlinePosition); break; case (12 << 8) | 4: // UnderlineThickness Operand.LoadParsed(dP, out this.underlineThickness); break; case (12 << 8) | 5: // PaintType Operand.LoadParsed(dP, out this.paintType); break; case (12 << 8) | 6: // CharstringType Operand.LoadParsed(dP, out this.charstringType); break; case (12 << 8) | 7: // FontMatrix Operand.LoadParsed(dP, this.fontMatrix); break; case (12 << 8) | 8: // StrokeWidth Operand.LoadParsed(dP, out this.strokeWidth); break; case (12 << 8) | 20: // SyntheticBase Operand.LoadParsed(dP, out this.syntheticBase); break; case (12 << 8) | 21: // PosScript Operand.LoadParsed(dP, out this.postScriptSID); break; case (12 << 8) | 22: // BaseFontName Operand.LoadParsed(dP, out this.baseFontNameSID); break; case (12 << 8) | 23: // BaseFontBlend { this.baseFontBlend = Operand.ToIntList(dP); Operand.ConvertDeltasToAbsolute(this.baseFontBlend); dP.Clear(); } break; case (12 << 8) | 30: { this.CID_ROS_1SID = dP[0].GetInt(); this.CID_ROS_2SID = dP[1].GetInt(); this.CID_ROS_3 = dP[2].GetInt(); dP.Clear(); } break; case (12 << 8) | 31: Operand.LoadParsed(dP, out this.CID_FontVersion); break; case (12 << 8) | 32: Operand.LoadParsed(dP, out this.CID_FontRevision); break; case (12 << 8) | 33: Operand.LoadParsed(dP, out this.CID_FontType); break; case (12 << 8) | 34: Operand.LoadParsed(dP, out this.CID_Count); break; case (12 << 8) | 35: Operand.LoadParsed(dP, out this.CID_UIDBase); break; case (12 << 8) | 36: Operand.LoadParsed(dP, out this.CID_FDArray); break; case 13: Operand.LoadParsed(dP, out this.uniqueID); break; case 14: this.XUID = Operand.ToIntList(dP); dP.Clear(); break; case 15: Operand.LoadParsed(dP, out this.charset); break; case 16: Operand.LoadParsed(dP, out this.encodingOffset); break; case 17: Operand.LoadParsed(dP, out this.charStrings); break; case 18: this.privateSize = dP[0].GetInt(); this.privateOffset = dP[1].GetInt(); dP.Clear(); break; } } // End of parsing Top DICT loop this.stringIndex = new INDEX(); this.stringIndex.Read(r); this.strings.Clear(); for (int i = 0; i < this.stringIndex.offset.Count - 1; ++i) { string s = System.Text.ASCIIEncoding.ASCII.GetString( this.stringIndex.data, (int)this.stringIndex.offset[i], (int)(this.stringIndex.offset[i + 1] - this.stringIndex.offset[i])); this.strings.Add(s); } this.globalSubrsIndex = new INDEX(); this.globalSubrsIndex.Read(r); this.globalSubroutines = new Dictionary <int, byte[]>(); int subIdx = 0; if (this.globalSubrsIndex.count > 0) { for (int i = 0; i < this.globalSubrsIndex.count; ++i) { int baseIdx = this.globalSubrsIndex.data[i]; int sz = this.globalSubrsIndex.data[i + 1] - baseIdx; // We're just adding to a dictionary in order for now - it could be simpler with a list, // but it's a placeholder since I haven't really looked into how subroutines work in the // charstring programs and subroutines are entirely unimplemented. // (wleu 12/27/2020) byte[] programBytes = new byte[sz]; System.Buffer.BlockCopy(this.charStringsIndex.data, baseIdx, programBytes, 0, sz); this.globalSubroutines.Add(subIdx, programBytes); ++subIdx; } } //// Encodings //const int EncodingSupplement = (1 << 8); //byte encodingFormat = r.ReadUInt8(); //Format0 f0; //Format1 f1; //if (encodingFormat == 0) //{ // f0 = new Format0(); // f0.format = 0; // f0.nCodes = r.ReadUInt8(); // f0.code = r.ReadBytes(f0.nCodes); // //} //else if (encodingFormat == 1) //{ // f1 = new Format1(); // f1.format = 1; // f1.nRanges = r.ReadUInt8(); // // f1.range1s = new List<Range1>(); // for (int i = 0; i < f1.nRanges; ++i) // { // Range1 r1 = new Range1(); // r1.first = r.ReadUInt8(); // r1.nLeft = r.ReadUInt8(); // f1.range1s.Add(r1); // } //} // Load privates if (this.privateOffset != 0) { this.SetPrivateDICTDefaults(); dP.Clear(); r.SetPosition(basePos + this.privateOffset); long privateEndPos = basePos + this.privateOffset + this.privateSize; while (r.GetPosition() < privateEndPos) { Operand val = Operand.Read(r); if (val.type == Operand.Type.Error) { // TODO: Error } else if (val.type == Operand.Type.Int || val.type == Operand.Type.Real) { dP.Add(val); continue; } switch (val.intVal) { case 6: // BlueValues this.blueValues = Operand.ToIntList(dP); Operand.ConvertDeltasToAbsolute(this.blueValues); dP.Clear(); break; case 7: // OtherBlues this.otherBlues = Operand.ToIntList(dP); Operand.ConvertDeltasToAbsolute(this.otherBlues); dP.Clear(); break; case 8: // FamilyBlues this.familyBlues = Operand.ToIntList(dP); Operand.ConvertDeltasToAbsolute(this.familyBlues); dP.Clear(); break; case 9: // FamilyOtherBlues this.familyOtherBlues = Operand.ToIntList(dP); Operand.ConvertDeltasToAbsolute(this.familyOtherBlues); dP.Clear(); break; case 10: // StdHW Operand.LoadParsed(dP, out this.stdHW); break; case 11: // StdVW Operand.LoadParsed(dP, out this.stdVW); break; case (12 << 8) | 9: // BlueScale Operand.LoadParsed(dP, out this.blueScale); break; case (12 << 8) | 10: // BlueShift Operand.LoadParsed(dP, out this.blueShift); break; case (12 << 8) | 11: // BlueFuzz Operand.LoadParsed(dP, out this.blueFuzz); break; case (12 << 8) | 12: // StemSnapH this.stemSnapH = Operand.ToIntList(dP); Operand.ConvertDeltasToAbsolute(this.stemSnapH); dP.Clear(); break; case (12 << 8) | 13: // StemSnapV this.stemSnapV = Operand.ToIntList(dP); Operand.ConvertDeltasToAbsolute(this.stemSnapV); dP.Clear(); break; case (12 << 8) | 14: // ForceBold Operand.LoadParsed(dP, out this.forceBold); break; case (12 << 8) | 17: // LanguageGroup Operand.LoadParsed(dP, out this.languageGroup); break; case (12 << 8) | 18: // ExpansionFactor Operand.LoadParsed(dP, out this.expansionFactor); break; case (12 << 8) | 19: // initialRandomSeed Operand.LoadParsed(dP, out this.initialRandomSeed); break; case 19: // Subrs Operand.LoadParsed(dP, out this.subrs); break; case 20: // defaultWidthX Operand.LoadParsed(dP, out this.defaultWidthX); break; case 21: // nominalWidthX Operand.LoadParsed(dP, out this.nominalWidthX); break; } } } // Charsets //r.SetPosition(basePos + this.charStrings); //byte charsetFormat = r.ReadUInt8(); // //CharsetFormat0 cf0; //CharsetFormat1 cf1; //CharsetFormat2 cf2; // //if(charsetFormat == 0) //{ // cf0 = new CharsetFormat0(); // cf0.format = 0; // cf0.glyph = new List<int>(); // for(int i = 0; i < 3; ++i) // { // cf0.glyph.Add(ReadDictValueInt(r)); // } //} //else if(charsetFormat == 1) //{ // cf1 = new CharsetFormat1(); // cf1.format = 1; //} //else if(charsetFormat == 2) //{ // cf2 = new CharsetFormat2(); // cf2.format = 2; //} this.loadedCharstrings = new List <Type2Charstring>(); r.SetPosition(basePos + this.charStrings); this.charStringsIndex.Read(r); for (int i = 0; i < this.charStringsIndex.offset.Count - 1; ++i) { int offset = (int)this.charStringsIndex.offset[i]; int size = (int)(this.charStringsIndex.offset[i + 1] - this.charStringsIndex.offset[i]); byte [] rb = new byte[size]; System.Buffer.BlockCopy(this.charStringsIndex.data, offset, rb, 0, size); Type2Charstring t2c = new Type2Charstring(rb); loadedCharstrings.Add(t2c); } // TODO: //FSSelect (CID Fonts only) // TODO: // Local Subr INDEX // TODO: Make sure the localsubr and globalsubr are correctly being // referenced }
static public byte ReadOffSize(TTF.TTFReader r) { return(r.ReadUInt8()); }
// duplicate of TTFReader.ReadUInt16() static public ushort ReadCard16(TTF.TTFReader r) { return((ushort)(r.ReadUInt8() << 8 | r.ReadUInt8())); }
static public byte ReadCard8(TTF.TTFReader r) { return(r.ReadUInt8()); }
/// <summary> /// Read an operand value from a Charstring Type 2 byte array.. /// </summary> /// <param name="r">The reader, with the read position at the Charstring Operand to read.</param> /// <returns>The loaded operand.</returns> /// /// <remarks>This is for Charstring data. For other similar formats such as CFFs or CFF2s, make sure /// the correct Read*() function is used.</remarks> public static Operand ReadType2Op(TTF.TTFReader r) { byte b0 = r.ReadUInt8(); if (b0 <= 11) { return(new Operand(b0, Type.Operator)); } if (b0 == 12) { byte b1 = r.ReadUInt8(); return(new Operand((b0 << 8) | b1, Type.Operator)); } if (b0 <= 18) { return(new Operand(b0, Type.Operator)); } // hintmask and cntrmask if (b0 <= 20) { return(new Operand(b0, Type.Operator)); } if (b0 <= 27) { return(new Operand(b0, Type.Operator)); } if (b0 == 28) { byte b1 = r.ReadUInt8(); byte b2 = r.ReadUInt8(); // This is a two's complement signed number, so we can't just // shift and OR them as an int, but also have to be weary of // the sign bit and two's complement conversion if it's negative. short merged = (short)(b1 << 8 | b2); return(new Operand(merged)); } if (b0 <= 31) { return(new Operand(b0, Type.Operator)); } if (b0 <= 246) { return(new Operand(b0 - 139, Type.Int)); } if (b0 <= 250) { int b1 = r.ReadUInt8(); return(new Operand((b0 - 247) * 256 + b1 + 108)); } if (b0 <= 254) { int b1 = r.ReadUInt8(); return(new Operand(-(b0 - 251) * 256 - b1 - 108)); } if (b0 == 255) { // Doc says this is 16-bit signed integer with 16 bits of fraction. // So this might actually be a fixed point float. int b1 = r.ReadUInt8(); int b2 = r.ReadUInt8(); int b3 = r.ReadUInt8(); int b4 = r.ReadUInt8(); return(new Operand((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4 << 0))); } // This really isn't possible, all 255 value of the byte should be covered. return(Error()); }
/// <summary> /// Read an operand value from a CFF file. /// </summary> /// <param name="r">The reader, with the read position at the Operand to read.</param> /// <returns>The loaded Operand value.</returns> /// <remarks>This is for CFF (DICT) values. For other similar formats such as CFF2s or Charstrings, make sure /// the correct Read*() function is used.</remarks> public static Operand Read(TTF.TTFReader r) { // The results are all signed, so might as well // work on an int level from the beginning. // Personal note - this compressed number representation is // pure insanity. // (12/24/2020) byte b0 = r.ReadUInt8(); if (b0 <= 21) { if (b0 == 12) { return(new Operand((b0 << 8) | r.ReadUInt8(), Type.Operator)); } else { return(new Operand(b0, Type.Operator)); } } else if (b0 == 30) { // AUGHHHHHHHHHH! Who thinks of this!? The code isn't going to // even try to be clever or optimized, we're just "getting by" // with these floating point values... string str = ""; bool cont = true; while (cont) { const int upperBitMask = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7); const int lowerBitMask = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3); int c = r.ReadUInt8(); int upperBit = (c & upperBitMask) >> 4; int lowerBit = c & lowerBitMask; foreach (int i in new int[] { upperBit, lowerBit }) { switch (i) { case 0: str += '0'; break; case 1: str += '1'; break; case 2: str += '2'; break; case 3: str += '3'; break; case 4: str += '4'; break; case 5: str += '5'; break; case 6: str += '6'; break; case 7: str += '7'; break; case 8: str += '8'; break; case 9: str += '9'; break; case 10: str += '.'; break; // a case 11: str += 'E'; break; // b case 12: str += "E-"; break; // c case 13: break; // d (reserved) case 14: str += '-'; break; // e case 15: // f cont = false; break; } } } float f; float.TryParse(str, out f); return(new Operand(f)); } if (b0 == 28) { int b1 = r.ReadUInt8(); int b2 = r.ReadUInt8(); return(new Operand(b1 << 8 | b2)); } else if (b0 == 29) { int b1 = r.ReadUInt8(); int b2 = r.ReadUInt8(); int b3 = r.ReadUInt8(); int b4 = r.ReadUInt8(); return(new Operand((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4 << 0))); } else if (b0 >= 32 && b0 <= 246) { return(new Operand(b0 - 139)); } else if (b0 >= 247 && b0 <= 250) { int b1 = r.ReadUInt8(); return(new Operand((b0 - 247) * 256 + b1 + 108)); } else if (b0 >= 251 && b0 <= 254) { int b1 = r.ReadUInt8(); return(new Operand(-(b0 - 251) * 256 - b1 - 108)); } return(Error()); }