示例#1
0
 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);
 }
示例#2
0
        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]);
        }
示例#3
0
 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)));
     }
 }
示例#4
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)));
            }
        }
示例#5
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
        }
示例#6
0
 static public byte ReadOffSize(TTF.TTFReader r)
 {
     return(r.ReadUInt8());
 }
示例#7
0
 // duplicate of TTFReader.ReadUInt16()
 static public ushort ReadCard16(TTF.TTFReader r)
 {
     return((ushort)(r.ReadUInt8() << 8 | r.ReadUInt8()));
 }
示例#8
0
 static public byte ReadCard8(TTF.TTFReader r)
 {
     return(r.ReadUInt8());
 }
示例#9
0
        /// <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());
        }
示例#10
0
        /// <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());
        }