Ejemplo n.º 1
0
        internal bool Read(Typeface typeface, BinaryReader reader, RestoreTicket ticket)
        {
            //WOFF File
            //WOFFHeader        File header with basic font type and version, along with offsets to metadata and private data blocks.
            //TableDirectory    Directory of font tables, indicating the original size, compressed size and location of each table within the WOFF file.
            //FontTables        The font data tables from the input sfnt font, compressed to reduce bandwidth requirements.
            //ExtendedMetadata  An optional block of extended metadata, represented in XML format and compressed for storage in the WOFF file.
            //PrivateData       An optional block of private data for the font designer, foundry, or vendor to use.
            _header = ReadWOFFHeader(reader);
            if (_header == null)
            {
#if DEBUG
                System.Diagnostics.Debug.WriteLine("can't read ");
#endif
                return(false);
            }

            //
            WoffTableDirectory[] woffTableDirs = ReadTableDirectories(reader);
            if (woffTableDirs == null)
            {
                return(false);
            }
            //
            //try read each compressed table
            if (DecompressHandler == null)
            {
                if (WoffDefaultZlibDecompressFunc.DecompressHandler != null)
                {
                    DecompressHandler = WoffDefaultZlibDecompressFunc.DecompressHandler;
                }
                else
                {
#if DEBUG
                    System.Diagnostics.Debug.WriteLine("no Zlib DecompressHandler ");
#endif
                    return(false);
                }
            }

            TableEntryCollection tableEntryCollection = CreateTableEntryCollection(woffTableDirs);

            using (MemoryStream decompressStream = new MemoryStream())
            {
                if (Extract(reader, woffTableDirs, decompressStream))
                {
                    using (ByteOrderSwappingBinaryReader reader2 = new ByteOrderSwappingBinaryReader(decompressStream))
                    {
                        decompressStream.Position = 0;
                        OpenFontReader openFontReader = new OpenFontReader();
                        return(openFontReader.ReadTableEntryCollection(typeface, ticket, tableEntryCollection, reader2));
                    }
                }
            }
            return(false);
        }
Ejemplo n.º 2
0
        static void TestLoadAndReload(string filename)
        {
            //Trimmable feature tests:
            //[A] read the font file as usual => get full information about the font
            Typeface typeface = null;

            using (FileStream fs = new FileStream(filename, FileMode.Open))
            {
                //read in full mode
                OpenFontReader openFontReader = new OpenFontReader();
                typeface = openFontReader.Read(fs);
            }

            //before
            bool     hasColor1  = typeface.HasColorTable();
            bool     hasSvg1    = typeface.HasSvgTable();
            bool     hasCff1    = typeface.IsCffFont;
            TrimMode glyphMode1 = typeface.GetTrimMode();
            Glyph    g1_1       = typeface.GetGlyph(1);

            //---------------------------------------------------------
            //[B] if you create paths from glyphs, or atlas from glyph
            //   and you don't want any glyph-building-detail (eg. to reduce memory usuage)
            //   but you still want to use the typeface for text-layout
            //   you can trim it down
            RestoreTicket ticket = typeface.TrimDown();//***

            //[C] you can GetGlyph() but this is ANOTHER NEW GLYPH
            //without building instruction( eg. no cff,ttf,svg data,bitmap)

            Glyph g1_2 = typeface.GetGlyph(1);

            //** if you cache the the old version of 'full-info' glyph**
            // the info is still cache on the old glyph and it can be used as 'full-info' glyph
            // TrimDown() DOES NOT go to delete that glyph.

            bool hasColor2 = typeface.HasColorTable();
            bool hasSvg2   = typeface.HasSvgTable();
            bool hasCff2   = typeface.IsCffFont;

            TrimMode glyphMode2 = typeface.GetTrimMode();

            //---------------------------------------------------------

            //[D] can we load glyph detail again?
            //yes=> this need 'ticket' from latest TrimDown()
            //if you don't have it, you can't restore it.

            using (FileStream fs = new FileStream(filename, FileMode.Open))
            {
                typeface.RestoreUp(ticket, fs);
            }
        }
Ejemplo n.º 3
0
        internal bool Read(Typeface typeface, RestoreTicket ticket, Stream stream, int streamStartOffset = 0, ReadFlags readFlags = ReadFlags.Full)
        {
            //bool little = BitConverter.IsLittleEndian;

            if (streamStartOffset > 0)
            {
                //eg. for ttc
                stream.Seek(streamStartOffset, SeekOrigin.Begin);
            }
            using (var input = new ByteOrderSwappingBinaryReader(stream))
            {
                ushort majorVersion = input.ReadUInt16();
                ushort minorVersion = input.ReadUInt16();

                if (KnownFontFiles.IsTtcf(majorVersion, minorVersion))
                {
                    //this font stream is 'The Font Collection'
                    //To read content of ttc=> one must specific the offset
                    //so use read preview first=> you will know that what are inside the ttc.
                    return(false);
                }
                else if (KnownFontFiles.IsWoff(majorVersion, minorVersion))
                {
                    //check if we enable woff or not
                    WebFont.WoffReader woffReader = new WebFont.WoffReader();
                    input.BaseStream.Position = 0;
                    return(woffReader.Read(typeface, input, ticket));
                }
                else if (KnownFontFiles.IsWoff2(majorVersion, minorVersion))
                {
                    //check if we enable woff2 or not
                    WebFont.Woff2Reader woffReader = new WebFont.Woff2Reader();
                    input.BaseStream.Position = 0;
                    return(woffReader.Read(typeface, input, ticket));
                }
                //-----------------------------------------------------------------


                ushort tableCount    = input.ReadUInt16();
                ushort searchRange   = input.ReadUInt16();
                ushort entrySelector = input.ReadUInt16();
                ushort rangeShift    = input.ReadUInt16();
                //------------------------------------------------------------------
                var tables = new TableEntryCollection();
                for (int i = 0; i < tableCount; i++)
                {
                    tables.AddEntry(new UnreadTableEntry(ReadTableHeader(input)));
                }
                //------------------------------------------------------------------

                return(ReadTableEntryCollection(typeface, ticket, tables, input));
            }
        }
Ejemplo n.º 4
0
        //-------
        //test incorrect restore
        void TestIncorrectRestore(string file1, string file2)
        {
            Typeface typeface = null;

            using (FileStream fs = new FileStream(file1, FileMode.Open))
            {
                //read in full mode
                OpenFontReader openFontReader = new OpenFontReader();
                typeface = openFontReader.Read(fs);
            }

            RestoreTicket ticket = typeface.TrimDown();

            //test restore with incorrect file
            using (FileStream fs = new FileStream(file2, FileMode.Open))
            {
                typeface.RestoreUp(ticket, fs);
            }
        }
Ejemplo n.º 5
0
        internal RestoreTicket TrimDownAndRemoveGlyphBuildingDetail()
        {
            switch (_typefaceTrimMode)
            {
            default: throw new NotSupportedException();

            case TrimMode.EssentailLayoutInfo: return(null);   //same mode

            case TrimMode.Restored:
            case TrimMode.No:
            {
                RestoreTicket ticket = new RestoreTicket();
                ticket.TypefaceName = Name;
                ticket.Headers      = _tblHeaders;    //a copy

                //FROM:GlyphLoadingMode.Full => TO: GlyphLoadingMode.EssentailLayoutInfo

                ticket.HasTtf = _hasTtfOutline;

                //cache glyph name before unload
                if (_cff1FontSet != null)
                {
                    ticket.HasCff = true;
                    UpdateCff1FontSetNamesCache();        //***
                    _cff1FontSet = null;
                }

                //1.Ttf and Otf => clone each glyphs in NO building
                Glyph[] newClones = new Glyph[_glyphs.Length];
                for (int i = 0; i < newClones.Length; ++i)
                {
                    newClones[i] = Glyph.Clone_NO_BuildingInstructions(_glyphs[i]);
                }
                _glyphs = newClones;

                //and since glyph has no building instructions in this mode
                //so  ...

                ticket.ControlValues = ControlValues != null;
                ControlValues        = null;

                ticket.PrepProgramBuffer = PrepProgramBuffer != null;
                PrepProgramBuffer        = null;

                ticket.FpgmProgramBuffer = FpgmProgramBuffer != null;
                FpgmProgramBuffer        = null;

                ticket.CPALTable = CPALTable != null;
                CPALTable        = null;

                ticket.COLRTable = COLRTable != null;
                COLRTable        = null;

                ticket.GaspTable = GaspTable != null;
                GaspTable        = null;

                //
                //3. Svg=> remove SvgTable
                if (_svgTable != null)
                {
                    ticket.HasSvg = true;
                    _svgTable.UnloadSvgData();
                    _svgTable = null;
                }

                //4. Bitmap Font => remove embeded bitmap data
                if (_bitmapFontGlyphSource != null)
                {
                    ticket.HasBitmapSource = true;
                    _bitmapFontGlyphSource.UnloadCBDT();
                }


                _typefaceTrimMode = TrimMode.EssentailLayoutInfo;

                return(ticket);
            }
            }
        }
Ejemplo n.º 6
0
        internal bool ReadTableEntryCollection(Typeface typeface, RestoreTicket ticket, TableEntryCollection tables, BinaryReader input)
        {
            if (ticket != null)
            {
                return(ReadTableEntryCollectionOnRestoreMode(typeface, ticket, tables, input));
            }

            typeface.SetTableEntryCollection(tables.CloneTableHeaders());

            var rd = new EntriesReaderHelper(tables, input);
            //PART 1: basic information
            OS2Table          os2Table          = rd.Read(new OS2Table());
            Meta              meta              = rd.Read(new Meta());
            NameEntry         nameEntry         = rd.Read(new NameEntry());
            Head              head              = rd.Read(new Head());
            MaxProfile        maxProfile        = rd.Read(new MaxProfile());
            HorizontalHeader  horizontalHeader  = rd.Read(new HorizontalHeader());
            HorizontalMetrics horizontalMetrics = rd.Read(new HorizontalMetrics(horizontalHeader.NumberOfHMetrics, maxProfile.GlyphCount));
            VerticalHeader    vhea              = rd.Read(new VerticalHeader());

            if (vhea != null)
            {
                VerticalMetrics vmtx = rd.Read(new VerticalMetrics(vhea.NumOfLongVerMetrics));
            }

            Cmap cmaps = rd.Read(new Cmap());
            VerticalDeviceMetrics vdmx = rd.Read(new VerticalDeviceMetrics());
            Kern kern = rd.Read(new Kern());
            //------------------------------------
            //PART 2: glyphs detail
            //2.1 True type font

            GlyphLocations glyphLocations = rd.Read(new GlyphLocations(maxProfile.GlyphCount, head.WideGlyphLocations));
            Glyf           glyf           = rd.Read(new Glyf(glyphLocations));
            Gasp           gaspTable      = rd.Read(new Gasp());
            COLR           colr           = rd.Read(new COLR());
            CPAL           cpal           = rd.Read(new CPAL());

            //2.2 Cff font
            PostTable postTable = rd.Read(new PostTable());
            CFFTable  cff       = rd.Read(new CFFTable());

            //additional math table (if available)
            MathTable mathtable = rd.Read(new MathTable());
            //------------------------------------

            //PART 3: advanced typography
            GDEF gdef      = rd.Read(new GDEF());
            GSUB gsub      = rd.Read(new GSUB());
            GPOS gpos      = rd.Read(new GPOS());
            BASE baseTable = rd.Read(new BASE());
            JSTF jstf      = rd.Read(new JSTF());

            STAT stat = rd.Read(new STAT());

            if (stat != null)
            {
                //variable font
                FVar fvar = rd.Read(new FVar());
                if (fvar != null)
                {
                    GVar gvar = rd.Read(new GVar());
                    CVar cvar = rd.Read(new CVar());
                    HVar hvar = rd.Read(new HVar());
                    MVar mvar = rd.Read(new MVar());
                    AVar avar = rd.Read(new AVar());
                }
            }

            bool isPostScriptOutline = false;
            bool isBitmapFont        = false;

            typeface.SetBasicTypefaceTables(os2Table, nameEntry, head, horizontalMetrics);
            if (glyf == null)
            {
                //check if this is cff table ?
                if (cff == null)
                {
                    //check  cbdt/cblc ?
                    CBLC cblcTable = rd.Read(new CBLC());
                    if (cblcTable != null)
                    {
                        CBDT cbdtTable = rd.Read(new CBDT());
                        //read cbdt
                        //bitmap font

                        BitmapFontGlyphSource bmpFontGlyphSrc = new BitmapFontGlyphSource(cblcTable);
                        bmpFontGlyphSrc.LoadCBDT(cbdtTable);
                        Glyph[] glyphs = bmpFontGlyphSrc.BuildGlyphList();
                        typeface.SetBitmapGlyphs(glyphs, bmpFontGlyphSrc);
                        isBitmapFont = true;
                    }
                    else
                    {
                        //TODO:
                        EBLC fontBmpTable = rd.Read(new EBLC());
                        throw new NotSupportedException();
                    }
                }
                else
                {
                    isPostScriptOutline = true;
                    typeface.SetCffFontSet(cff.Cff1FontSet);
                }
            }
            else
            {
                typeface.SetTtfGlyphs(glyf.Glyphs);
            }

            //----------------------------
            typeface.CmapTable  = cmaps;
            typeface.KernTable  = kern;
            typeface.MaxProfile = maxProfile;
            typeface.HheaTable  = horizontalHeader;
            //----------------------------
            typeface.GaspTable = gaspTable;

            if (!isPostScriptOutline && !isBitmapFont)
            {
                //for true-type font outline
                FpgmTable fpgmTable = rd.Read(new FpgmTable());
                //control values table
                CvtTable  cvtTable         = rd.Read(new CvtTable());
                PrepTable propProgramTable = rd.Read(new PrepTable());

                typeface.ControlValues     = cvtTable?._controlValues;
                typeface.FpgmProgramBuffer = fpgmTable?._programBuffer;
                typeface.PrepProgramBuffer = propProgramTable?._programBuffer;
            }

            //-------------------------
            typeface.LoadOpenFontLayoutInfo(
                gdef,
                gsub,
                gpos,
                baseTable,
                colr,
                cpal);
            //------------

            typeface.SetSvgTable(rd.Read(new SvgTable()));
            typeface.PostTable = postTable;

            if (mathtable != null)
            {
                MathGlyphLoader.LoadMathGlyph(typeface, mathtable);
            }
#if DEBUG
            //test
            //int found = typeface.GetGlyphIndexByName("Uacute");
            if (typeface.IsCffFont)
            {
                //optional
                typeface.UpdateAllCffGlyphBounds();
            }
#endif
            typeface.UpdateLangs(meta);
            typeface.UpdateFrequentlyUsedValues();
            return(true);
        }
Ejemplo n.º 7
0
        bool ReadTableEntryCollectionOnRestoreMode(Typeface typeface, RestoreTicket ticket, TableEntryCollection tables, BinaryReader input)
        {
            //RESTORE MODE
            //check header matches

            if (!typeface.IsTrimmed() ||
                !typeface.CompareOriginalHeadersWithNewlyLoadOne(tables.CloneTableHeaders()))
            {
                return(false);
            }


            var rd = new EntriesReaderHelper(tables, input);
            //PART 1: basic information
            //..
            //------------------------------------
            //PART 2: glyphs detail
            //2.1 True type font
            GlyphLocations glyphLocations = ticket.HasTtf ? rd.Read(new GlyphLocations(typeface.MaxProfile.GlyphCount, typeface.Head.WideGlyphLocations)) : null;
            Glyf           glyf           = ticket.HasTtf ? rd.Read(new Glyf(glyphLocations)) : null;

            typeface.GaspTable = ticket.GaspTable ? rd.Read(new Gasp()) : null;

            typeface.SetColorAndPalTable(
                ticket.COLRTable ? rd.Read(new COLR()) : null,
                ticket.CPALTable ? rd.Read(new CPAL()) : null);


            //2.2 Cff font
            CFFTable cff = ticket.HasCff ? rd.Read(new CFFTable()) : null;

            bool isPostScriptOutline = false;
            bool isBitmapFont        = false;

            if (glyf == null)
            {
                //check if this is cff table ?
                if (cff == null)
                {
                    //check  cbdt/cblc ?
                    if (ticket.HasBitmapSource)
                    {
                        //reload only CBDT (embeded bitmap)
                        CBDT cbdt = rd.Read(new CBDT());
                        typeface._bitmapFontGlyphSource.LoadCBDT(cbdt);
                        //just clone existing glyph
                        isBitmapFont = true;
                    }
                    else
                    {
                        //?
                        throw new NotSupportedException();
                    }
                }
                else
                {
                    isPostScriptOutline = true;
                    typeface.SetCffFontSet(cff.Cff1FontSet);
                }
            }
            else
            {
                typeface.SetTtfGlyphs(glyf.Glyphs);
            }

            if (!isPostScriptOutline && !isBitmapFont)
            {
                //for true-type font outline
                FpgmTable fpgmTable = rd.Read(new FpgmTable());
                //control values table
                CvtTable  cvtTable         = rd.Read(new CvtTable());
                PrepTable propProgramTable = rd.Read(new PrepTable());

                typeface.ControlValues     = cvtTable?._controlValues;
                typeface.FpgmProgramBuffer = fpgmTable?._programBuffer;
                typeface.PrepProgramBuffer = propProgramTable?._programBuffer;
            }

            if (ticket.HasSvg)
            {
                typeface.SetSvgTable(rd.Read(new SvgTable()));
            }


#if DEBUG
            //test
            //int found = typeface.GetGlyphIndexByName("Uacute");
            if (typeface.IsCffFont)
            {
                //optional???
                typeface.UpdateAllCffGlyphBounds();
            }
#endif
            typeface._typefaceTrimMode = TrimMode.Restored;
            return(true);
        }