Пример #1
0
        /************************
         * public methods
         */


        public OTTable GetTable(OTFont fontOwner, DirectoryEntry de)
        {
            // first try getting it from the table cache
            OTTable table = GetTableFromCache(de);

            if (table == null)
            {
                if (de.length != 0 &&
                    de.offset != 0 &&
                    de.offset < m_file.GetFileLength() &&
                    de.offset + de.length <= m_file.GetFileLength())
                {
                    // read the table from the file
                    MBOBuffer buf = m_file.ReadPaddedBuffer(de.offset, de.length);

                    if (buf != null)
                    {
                        // put the buffer into a table object
                        table = CreateTableObject(de.tag, buf);

                        // add the table to the cache
                        CachedTables.Add(table);
                    }
                }
            }

            return(table);
        }
Пример #2
0
        /*****************
         * public methods
         */


        ///
        /// <summary>Calculate the check sum for the font as the
        /// sum of the checksums of the offset table, directory entries, and
        /// each table.
        /// </summary>
        public uint CalcChecksum()
        {
            uint sum = 0;

            sum += m_OffsetTable.CalcOffsetTableChecksum();
            sum += m_OffsetTable.CalcDirectoryEntriesChecksum();

            if (m_OffsetTable != null)
            {
                for (int i = 0; i < m_OffsetTable.DirectoryEntries.Count; i++)
                {
                    DirectoryEntry de = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i];

                    OTTable table = GetTable(de);

                    uint calcChecksum = 0;
                    if (table != null)
                    {
                        calcChecksum = table.CalcChecksum();
                    }
                    sum += calcChecksum;
                }
            }

            return(sum);
        }
Пример #3
0
        protected OTTable GetTable(DirectoryEntry de)
        {
            OTTable table = null;

            if (m_File != null)
            {
                // get the table from OTFile's table manager
                table = m_File.GetTableManager().GetTable(this, de);
            }
            else
            {
                // get the table from the list in memory
                for (int i = 0; i < MemBasedTables.Count; i++)
                {
                    OTTable t = (OTTable)MemBasedTables[i];
                    if (de.tag == t.m_tag)
                    {
                        table = t;
                        break;
                    }
                }
            }

            return(table);
        }
Пример #4
0
            public bool Validate(Validator v, string sIdentity, OTTable tableOwner)
            {
                bool bOk = true;

                // ???
                // ??? are there any values that are invalid ???
                // ???

                return bOk;
            }
Пример #5
0
        /// <summary>Return the ith table in the directory entries,
        /// or null if there is no such entry.
        /// </summary>
        public OTTable GetTable(ushort i)
        {
            OTTable table = null;

            DirectoryEntry de = GetDirectoryEntry(i);

            if (de != null)
            {
                table = GetTable(de);
            }

            return(table);
        }
Пример #6
0
        /// <summary>Rmove a table to an non-file based table. Throws
        /// exception if table is not in font.
        /// </summary>
        public void RemoveTable(OTTag tag)
        {
            if (m_File != null)
            {
                throw new ApplicationException("attempted to remove a table from a file-based OTFont object");
            }

            if (GetDirectoryEntry(tag) == null)
            {
                throw new ArgumentException("the specified table doesn't doesn't exist in the font");
            }


            // remove the directory entry

            for (int i = 0; i < m_OffsetTable.DirectoryEntries.Count; i++)
            {
                DirectoryEntry de = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i];
                if (tag == de.tag)
                {
                    m_OffsetTable.DirectoryEntries.RemoveAt(i);
                    m_OffsetTable.numTables--;
                    break;
                }
            }


            // remove the table from the list of tables in memory

            for (int i = 0; i < MemBasedTables.Count; i++)
            {
                OTTable t = (OTTable)MemBasedTables[i];
                if (tag == t.m_tag)
                {
                    MemBasedTables.RemoveAt(i);
                    break;
                }
            }

            string sTable = (string)tag;

            if (sTable == "CFF ")
            {
                m_OutlineType = OutlineType.OUTLINE_INVALID;
            }
            else if (sTable == "glyf")
            {
                m_OutlineType = OutlineType.OUTLINE_INVALID;
            }
        }
Пример #7
0
        /// <summary>Return the first table with tag == <c>tag</c>
        /// or null if there is no such table.
        /// </summary>
        public OTTable GetTable(OTTag tag)
        {
            OTTable table = null;

            // find the directory entry in this font that matches the tag
            DirectoryEntry de = GetDirectoryEntry(tag);

            if (de != null)
            {
                table = GetTable(de);
            }

            return(table);
        }
Пример #8
0
        /************************
         * protected methods
         */

        protected OTTable GetTableFromCache(DirectoryEntry de)
        {
            OTTable ot = null;

            for (int i = 0; i < CachedTables.Count; i++)
            {
                OTTable temp = (OTTable)CachedTables[i];
                if (temp.MatchFileOffsetLength(de.offset, de.length))
                {
                    ot = temp;
                    break;
                }
            }

            return(ot);
        }
Пример #9
0
        public uint GetNumPadBytesAfterTable(OTTable t)
        {
            long TableFilePos = t.GetBuffer().GetFilePos();

            if (TableFilePos == -1)
            {
                // the table's file position is initialized to -1 if the table was not read from a file
                throw new ApplicationException("invalid file position");
            }

            uint TableLength = t.GetBuffer().GetLength();
            long PadFilePos  = TableFilePos + TableLength;

            long NextTablePos = m_fs.Length;

            // possible DSIG in TTC after all the tables
            if (IsCollection() && m_ttch.DsigTag != null && (string)m_ttch.DsigTag == "DSIG" && m_ttch.DsigOffset > 0 && m_ttch.DsigOffset < NextTablePos && (string)t.m_tag != "DSIG")
            {
                NextTablePos = m_ttch.DsigOffset;
            }

            for (uint iFont = 0; iFont < m_nFonts; iFont++)
            {
                if (IsCollection())
                {
                    uint offset = (uint)m_ttch.DirectoryOffsets[(int)iFont];
                    if (offset >= PadFilePos && offset < NextTablePos)
                    {
                        NextTablePos = offset;
                    }
                }

                OTFont f = GetFont(iFont);
                for (ushort iTable = 0; iTable < f.GetNumTables(); iTable++)
                {
                    DirectoryEntry de = f.GetDirectoryEntry(iTable);
                    if (de.offset >= PadFilePos && de.offset < NextTablePos)
                    {
                        NextTablePos = de.offset;
                    }
                }
            }

            return((uint)(NextTablePos - PadFilePos));
        }
Пример #10
0
        /// <summary>Add a new table to an non-file based table. Table cannot
        /// already exist in the font.
        /// </summary>
        public void AddTable(OTTable t)
        {
            if (m_File != null)
            {
                throw new ApplicationException("attempted to add a table to a file-based OTFont object");
            }

            if (GetDirectoryEntry(t.m_tag) != null)
            {
                throw new ArgumentException("the specified table already exists in the font");
            }

            // build a new directory entry
            DirectoryEntry de = new DirectoryEntry();

            de.tag      = new OTTag(t.m_tag.GetBytes());
            de.checkSum = t.CalcChecksum();
            de.offset   = 0; // this value won't get fixed up until the font is written
            de.length   = t.GetLength();

            // add the directory entry

            m_OffsetTable.DirectoryEntries.Add(de);
            m_OffsetTable.numTables++;


            // add the table to the list of tables in memory

            MemBasedTables.Add(t);


            // special handling for certain tables

            string sTable = (string)t.m_tag;

            if (sTable == "CFF ")
            {
                m_OutlineType = OutlineType.OUTLINE_POSTSCRIPT;
            }
            else if (sTable == "glyf")
            {
                m_OutlineType = OutlineType.OUTLINE_TRUETYPE;
            }
        }
Пример #11
0
                    public bool Validate(Validator v, string sIdentity, OTTable table)
                    {
                        bool bRet = true;

                        // check for data overlap
                        bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetLigature, CalcLength(), v, sIdentity, table.GetTag());

                        // check the component array length
                        if (m_offsetLigature + (uint)FieldOffsets.ComponentGlyphIDs + (CompCount-1)*2 > m_bufTable.GetLength())
                        {
                            v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", Component array");
                            bRet = false;
                        }

                        return bRet;
                    }
Пример #12
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                sIdentity += "(ExtensionSubst)";

                // check for data overlap
                bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetExtensionSubst, CalcLength(), v, sIdentity, table.GetTag());

                // check the SubstFormat
                if (SubstFormat != 1)
                {
                    v.Error(T.T_NULL, E.GSUB_E_SubtableFormat, table.m_tag, sIdentity + ", SubstFormat = " + SubstFormat);
                    bRet = false;
                }

                // check the ExtensionLookupType
                if (ExtensionLookupType >= 7)
                {
                    v.Error(T.T_NULL, E.GSUB_E_ExtensionLookupType, table.m_tag, sIdentity + ", ExtensionLookupType = " + ExtensionLookupType);
                    bRet = false;
                }

                // check the ExtensionOffset
                if (m_offsetExtensionSubst + ExtensionOffset > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", ExtensionOffset");
                    bRet = false;
                }

                if (bRet)
                {
                    v.Pass(T.T_NULL, P.GSUB_P_ExtensionSubst, table.m_tag, sIdentity);
                }

                // validate the subtable
                SubTable st = null;
                switch (ExtensionLookupType)
                {
                    case 1: st = new val_GSUB.SingleSubst_val      (m_offsetExtensionSubst + ExtensionOffset, m_bufTable); break;
                    case 2: st = new val_GSUB.MultipleSubst_val    (m_offsetExtensionSubst + ExtensionOffset, m_bufTable); break;
                    case 3: st = new val_GSUB.AlternateSubst_val   (m_offsetExtensionSubst + ExtensionOffset, m_bufTable); break;
                    case 4: st = new val_GSUB.LigatureSubst_val    (m_offsetExtensionSubst + ExtensionOffset, m_bufTable); break;
                    case 5: st = new val_GSUB.ContextSubst_val     (m_offsetExtensionSubst + ExtensionOffset, m_bufTable); break;
                    case 6: st = new val_GSUB.ChainContextSubst_val(m_offsetExtensionSubst + ExtensionOffset, m_bufTable); break;

                }
                if (st != null)
                {
                    I_OTLValidate iv = (I_OTLValidate)st;
                    iv.Validate(v, sIdentity, table);
                }

                return bRet;
            }
Пример #13
0
        /// <summary>Add a new table to an non-file based table. Table cannot
        /// already exist in the font.
        /// </summary>
        public void AddTable(OTTable t)
        {
            if (m_File != null)
            {
                throw new ApplicationException("attempted to add a table to a file-based OTFont object");
            }

            if (GetDirectoryEntry(t.m_tag) != null)
            {
                throw new ArgumentException("the specified table already exists in the font");
            }

            // build a new directory entry
            DirectoryEntry de = new DirectoryEntry();
            de.tag = new OTTag(t.m_tag.GetBytes());
            de.checkSum = t.CalcChecksum();
            de.offset = 0;  // this value won't get fixed up until the font is written
            de.length = t.GetLength();

            // add the directory entry

            m_OffsetTable.DirectoryEntries.Add(de);    
            m_OffsetTable.numTables++;
            

            // add the table to the list of tables in memory

            MemBasedTables.Add(t);


            // special handling for certain tables

            string sTable = (string)t.m_tag;
            if (sTable == "CFF ")
            {
                m_OutlineType = OutlineType.OUTLINE_POSTSCRIPT;
            }
            else if (sTable == "glyf")
            {
                m_OutlineType = OutlineType.OUTLINE_TRUETYPE;
            }
        }
Пример #14
0
        public bool Validate(Validator v, string sIdentity, OTTable table)
        {
            bool bRet = true;

            bool bScriptTableOk = true;

            // check the DefaultLangSys offset
            if (DefaultLangSysOffset != 0)
            {
                if (m_offsetScriptTable + DefaultLangSysOffset > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E._OTL_ScriptTable_E_DefaultLangSysOffset, table.m_tag, sIdentity);
                    bScriptTableOk = false;
                    bRet = false;
                }
                else
                {
                    // check the DefaultLangSys table
                    LangSysTable_val lst = GetDefaultLangSysTable_val();
                    bRet &= lst.Validate(v, sIdentity + ", DefaultLangSysTable", table);
                }
            }

            // check the LansgSysRecord array length
            if (m_offsetScriptTable + (uint)FieldOffsets.LangSysRecord + LangSysCount * 6 > m_bufTable.GetLength())
            {
                v.Error(T.T_NULL, E._OTL_ScriptTable_E_LangSysRecordArray_pastEOT, table.m_tag, sIdentity);
                bScriptTableOk = false;
                bRet = false;
            }

            // check that the LangSysRecord array is sorted alphabetically
            if (LangSysCount > 1)
            {
                for (uint i=0; i<LangSysCount-1; i++)
                {
                    LangSysRecord ThisLsr = GetLangSysRecord(i);
                    LangSysRecord NextLsr = GetLangSysRecord(i+1);
                    if (ThisLsr.LangSysTag >= NextLsr.LangSysTag)
                    {
                        v.Error(T.T_NULL, E._OTL_ScriptTable_E_LangSysRecordArray_order, table.m_tag, sIdentity);
                        bScriptTableOk = false;
                        bRet = false;
                    }
                }
            }

            // check each LangSysRecord
            for (uint i=0; i<LangSysCount; i++)
            {
                LangSysRecord lsr = GetLangSysRecord(i);
                
                // check the tag
                if (!lsr.LangSysTag.IsValid())
                {
                    v.Error(T.T_NULL, E._OTL_ScriptTable_E_LangSysRecord_tag, table.m_tag, sIdentity + ", LangSysRecord[" + i + "]");
                    bScriptTableOk = false;
                    bRet = false;
                }

                // check the offset
                if (m_offsetScriptTable + lsr.LangSysOffset > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E._OTL_ScriptTable_E_LangSysRecord_offset, table.m_tag, sIdentity + ", LangSysRecord[" + i + "]");
                    bScriptTableOk = false;
                    bRet = false;
                }

                // validate the langsys table
                LangSysTable_val lst = GetLangSysTable_val(lsr);
                bRet &= lst.Validate(v, sIdentity + ", LangSysRecord[" + i + "], LangSysTable", table);
            }

            if (bScriptTableOk)
            {
                v.Pass(T.T_NULL, P._OTL_ScriptTable_P_valid, table.m_tag, sIdentity);
            }

            return bRet;
        }
Пример #15
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                // check that ClassRangeRecord array doesn't extend past end of table
                if (m_offsetClassDefFormat2 + (uint)FieldOffsets.ClassRangeRecordArray + ClassRangeCount*6 > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E._OTL_ClassDefinitionTable_E_RangeRecordArrayPastEOT, table.m_tag, sIdentity);
                    bRet = false;
                }

                // check that ClassRangeRecord array is in sorted order
                if (ClassRangeCount > 1)
                {
                    for (uint i=0; i<ClassRangeCount-1; i++)
                    {
                        ClassRangeRecord ThisCrr = GetClassRangeRecord(i);
                        ClassRangeRecord NextCrr = GetClassRangeRecord(i+1);
                        if (ThisCrr.Start >= NextCrr.Start)
                        {
                            v.Error(T.T_NULL, E._OTL_ClassDefinitionTable_E_RangeRecordArray_order, table.m_tag, sIdentity);
                            bRet = false;
                            
                            // temporary debug code
                            /*
                            v.DebugMsg("ClassRangeCount = " + ClassRangeCount, tag);
                            for (uint j=0; j<ClassRangeCount; j++)
                            {
                                ClassRangeRecord crr = GetClassRangeRecord(j);
                                v.DebugMsg("ClassRangeRecord[" + j + "].Start = " + crr.Start, tag);
                            }
                            */

                            break;

                        }
                    }
                }

                return bRet;
            }
Пример #16
0
        /// <summary>Write a TTC (TT Collection) to a disk file.</summary>
        public static bool WriteTTCFile(FileStream fs, OTFont[] fonts)
        {
            bool bRet = true;


            // build the TTC header

            OTTag TTCtag         = (OTTag)"ttcf";
            uint  version        = 0x00020000;
            uint  DirectoryCount = (uint)fonts.Length;

            uint [] TableDirectory = new uint[fonts.Length];
            uint    ulDsigTag      = 0;
            uint    ulDsigLength   = 0;
            uint    ulDsigOffset   = 0;

            uint TTCHeaderLen = 12 + DirectoryCount * 4 + 12; // length of version 2.0 header


            // build an array of offset tables
            OffsetTable[] otArr = new OffsetTable[fonts.Length];
            for (int iFont = 0; iFont < fonts.Length; iFont++)
            {
                otArr[iFont] = new OffsetTable(new OTFixed(1, 0), fonts[iFont].GetNumTables());
            }

            // build an array of head tables that will contain the updated modified field and font checksum
            Table_head[] arrHeadTables = new Table_head[fonts.Length];
            for (int i = 0; i < fonts.Length; i++)
            {
                // get the cache
                Table_head            headTable = (Table_head)fonts[i].GetTable("head");
                Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache();

                // set the 'modified' field to the current date
                DateTime dt = DateTime.Now;
                headCache.modified = headTable.DateTimeToSecondsSince1904(dt);

                // generate a new table and add it to the array
                Table_head newHead = (Table_head)headCache.GenerateTable();
                arrHeadTables[i] = newHead;
            }



            // build a list of directory entries for each font

            long FilePos = TTCHeaderLen;

            for (int iFont = 0; iFont < fonts.Length; iFont++)
            {
                ushort numTables = fonts[iFont].GetNumTables();
                TableDirectory[iFont] = (uint)FilePos;
                FilePos += 12 + numTables * 16;

                uint PrevFilePos = 0;
                for (ushort i = 0; i < numTables; i++)
                {
                    OTTable table = fonts[iFont].GetTable(i);
                    OTTag   tag   = table.m_tag;

                    if ((string)tag == "head")
                    {
                        table = arrHeadTables[iFont];
                    }

                    // check if this table is a duplicate of a table in a previous font

                    PrevFilePos = 0;
                    if (iFont > 0)
                    {
                        for (int iPrevFont = 0; iPrevFont < iFont; iPrevFont++)
                        {
                            for (int iTable = 0; iTable < fonts[iPrevFont].GetNumTables(); iTable++)
                            {
                                OTTable PrevTable = fonts[iPrevFont].GetTable(table.m_tag);
                                if (PrevTable != null)
                                {
                                    if (MBOBuffer.BinaryEqual(table.m_bufTable, PrevTable.m_bufTable))
                                    {
                                        // get the file position for the previous table
                                        for (int iDe = 0; iDe < otArr[iPrevFont].DirectoryEntries.Count; iDe++)
                                        {
                                            DirectoryEntry dePrev = (DirectoryEntry)otArr[iPrevFont].DirectoryEntries[iDe];
                                            if (dePrev.tag == table.m_tag)
                                            {
                                                PrevFilePos = dePrev.offset;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }


                    // build a new directory entry

                    DirectoryEntry de = new DirectoryEntry();
                    de.tag      = new OTTag(tag.GetBytes());
                    de.checkSum = table.CalcChecksum();
                    de.length   = table.GetLength();
                    if (PrevFilePos != 0)
                    {
                        de.offset = (uint)PrevFilePos;
                    }
                    else
                    {
                        de.offset = (uint)FilePos;
                        FilePos  += table.GetBuffer().GetPaddedLength();
                    }

                    otArr[iFont].DirectoryEntries.Add(de);
                }


                // sort the directory entries

                if (numTables > 1)
                {
                    for (int i = 0; i < numTables - 1; i++)
                    {
                        for (int j = i + 1; j < numTables; j++)
                        {
                            if (((DirectoryEntry)otArr[iFont].DirectoryEntries[i]).tag > ((DirectoryEntry)otArr[iFont].DirectoryEntries[j]).tag)
                            {
                                DirectoryEntry temp = (DirectoryEntry)otArr[iFont].DirectoryEntries[i];
                                otArr[iFont].DirectoryEntries[i] = (DirectoryEntry)otArr[iFont].DirectoryEntries[j];
                                otArr[iFont].DirectoryEntries[j] = temp;
                            }
                        }
                    }
                }
            }


            // update each font's checksum in the head table

            for (int iFont = 0; iFont < fonts.Length; iFont++)
            {
                ushort numTables = fonts[iFont].GetNumTables();

                // calculate the checksum
                uint sum = 0;
                sum += otArr[iFont].CalcOffsetTableChecksum();
                sum += otArr[iFont].CalcDirectoryEntriesChecksum();
                for (ushort i = 0; i < numTables; i++)
                {
                    DirectoryEntry de    = (DirectoryEntry)otArr[iFont].DirectoryEntries[i];
                    OTTable        table = fonts[iFont].GetTable(de.tag);
                    if ((string)de.tag == "head")
                    {
                        table = arrHeadTables[iFont];
                    }
                    sum += table.CalcChecksum();
                }

                // get the cache
                Table_head            headTable = arrHeadTables[iFont];
                Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache();

                // set the checkSumAdujustment field
                headCache.checkSumAdjustment = 0xb1b0afba - sum;

                // generate a new table and replace the head table in the array of head tables
                Table_head newHead = (Table_head)headCache.GenerateTable();
                arrHeadTables[iFont] = newHead;
            }



            // write the TTC header

            WriteUint32MBO(fs, (uint)TTCtag);
            WriteUint32MBO(fs, version);
            WriteUint32MBO(fs, DirectoryCount);
            for (int i = 0; i < fonts.Length; i++)
            {
                WriteUint32MBO(fs, TableDirectory[i]);
            }
            WriteUint32MBO(fs, ulDsigTag);
            WriteUint32MBO(fs, ulDsigLength);
            WriteUint32MBO(fs, ulDsigOffset);


            // write out each font

            for (int iFont = 0; iFont < fonts.Length; iFont++)
            {
                ushort numTables = fonts[iFont].GetNumTables();

                // write the offset table

                fs.Write(otArr[iFont].m_buf.GetBuffer(), 0, (int)otArr[iFont].m_buf.GetLength());


                // write the directory entries

                for (int i = 0; i < numTables; i++)
                {
                    DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i];
                    fs.Write(de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength());
                }


                // write out each table unless a shared version has been written

                for (ushort i = 0; i < numTables; i++)
                {
                    DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i];
                    if (fs.Position == de.offset)
                    {
                        OTTable table = fonts[iFont].GetTable(de.tag);
                        if ((string)table.m_tag == "head")
                        {
                            table = arrHeadTables[iFont];
                        }
                        fs.Write(table.m_bufTable.GetBuffer(), 0, (int)table.GetBuffer().GetPaddedLength());
                    }
                }
            }


            return(bRet);
        }
Пример #17
0
        /// <summary>Write a single OTF to a disk file, with tables in
        /// proper order, checksums set, etc.
        /// </summary>
        public static bool WriteSfntFile(FileStream fs, OTFont font)
        {
            bool bRet = true;


            OTFixed     sfntVersion = new OTFixed(1, 0);
            ushort      numTables   = font.GetNumTables();
            OffsetTable ot          = new OffsetTable(sfntVersion, numTables);


            // order tables in fastfont order

            string [] arrOrderedNames = null;
            string [] ttNames         =
            {
                "head", "hhea", "maxp", "OS/2", "hmtx", "LTSH", "VDMX", "hdmx", "cmap", "fpgm",
                "prep", "cvt ", "loca", "glyf", "kern", "name", "post", "gasp", "PCLT"
            };
            string [] psNames =
            {
                "head", "hhea", "maxp", "OS/2", "name", "cmap", "post", "CFF "
            };

            if (font.ContainsTrueTypeOutlines())
            {
                arrOrderedNames = ttNames;
            }
            else if (font.ContainsPostScriptOutlines())
            {
                arrOrderedNames = psNames;
            }

            OTTable[] OrderedTables = new OTTable[numTables];
            for (ushort i = 0; i < numTables; i++)
            {
                OrderedTables[i] = font.GetTable(i);
            }

            if (arrOrderedNames != null)
            {
                ushort curpos = 0;
                for (int iName = 0; iName < arrOrderedNames.Length; iName++)
                {
                    for (ushort i = curpos; i < numTables; i++)
                    {
                        if (arrOrderedNames[iName] == (string)OrderedTables[i].m_tag)
                        {
                            OTTable temp = OrderedTables[curpos];
                            OrderedTables[curpos] = OrderedTables[i];
                            OrderedTables[i]      = temp;
                            curpos++;
                            break;
                        }
                    }
                }
            }


            // update the modified date in the head table

            for (int i = 0; i < OrderedTables.Length; i++)
            {
                if ((string)OrderedTables[i].m_tag == "head")
                {
                    // get the cache
                    Table_head            headTable = (Table_head)OrderedTables[i];
                    Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache();

                    // set the 'modified' field to the current date and time
                    DateTime dt = DateTime.Now;
                    headCache.modified = headTable.DateTimeToSecondsSince1904(dt);

                    // generate a new table and replace the head table in the list of ordered tables
                    Table_head newHead = (Table_head)headCache.GenerateTable();
                    OrderedTables[i] = newHead;

                    break;
                }
            }


            // build a list of directory entries

            long TableFilePos = 12 + numTables * 16;

            for (ushort i = 0; i < numTables; i++)
            {
                OTTable table = OrderedTables[i];
                OTTag   tag   = table.m_tag;

                // build a new directory entry
                DirectoryEntry de = new DirectoryEntry();
                de.tag      = new OTTag(tag.GetBytes());
                de.checkSum = table.CalcChecksum();
                de.offset   = (uint)TableFilePos;
                de.length   = table.GetLength();

                ot.DirectoryEntries.Add(de);

                TableFilePos += table.GetBuffer().GetPaddedLength();
            }


            // sort the directory entries

            if (numTables > 1)
            {
                for (int i = 0; i < numTables - 1; i++)
                {
                    for (int j = i + 1; j < numTables; j++)
                    {
                        if (((DirectoryEntry)(ot.DirectoryEntries[i])).tag > ((DirectoryEntry)(ot.DirectoryEntries[j])).tag)
                        {
                            DirectoryEntry temp = (DirectoryEntry)ot.DirectoryEntries[i];
                            ot.DirectoryEntries[i] = (DirectoryEntry)ot.DirectoryEntries[j];
                            ot.DirectoryEntries[j] = temp;
                        }
                    }
                }
            }


            // update the font checksum in the head table

            for (int i = 0; i < OrderedTables.Length; i++)
            {
                if ((string)OrderedTables[i].m_tag == "head")
                {
                    // calculate the checksum
                    uint sum = 0;
                    sum += ot.CalcOffsetTableChecksum();
                    sum += ot.CalcDirectoryEntriesChecksum();
                    for (int j = 0; j < OrderedTables.Length; j++)
                    {
                        sum += OrderedTables[j].CalcChecksum();
                    }

                    // get the cache
                    Table_head            headTable = (Table_head)OrderedTables[i];
                    Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache();

                    // set the checkSumAdujustment field
                    headCache.checkSumAdjustment = 0xb1b0afba - sum;

                    // generate a new table and replace the head table in the list of ordered tables
                    Table_head newHead = (Table_head)headCache.GenerateTable();
                    OrderedTables[i] = newHead;

                    break;
                }
            }


            // write the offset table

            fs.Write(ot.m_buf.GetBuffer(), 0, (int)ot.m_buf.GetLength());


            // write the directory entries

            for (int i = 0; i < numTables; i++)
            {
                DirectoryEntry de = (DirectoryEntry)ot.DirectoryEntries[i];
                fs.Write(de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength());
            }


            // write the tables

            for (ushort i = 0; i < numTables; i++)
            {
                OTTable table = OrderedTables[i];

                fs.Write(table.m_bufTable.GetBuffer(), 0, (int)table.GetBuffer().GetPaddedLength());
            }


            return(bRet);
        }
Пример #18
0
                    public bool Validate(Validator v, string sIdentity, OTTable table)
                    {
                        bool bRet = true;

                        // check for data overlap
                        bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetSubClassSet, CalcLength(), v, sIdentity, table.GetTag());

                        // check the SubClassRule array length
                        if (m_offsetSubClassSet + (uint)FieldOffsets.SubClassRuleOffsets + SubClassRuleCount*2 > m_bufTable.GetLength())
                        {
                            v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", SubClassRule array");
                            bRet = false;
                        }

                        // check each SubClassRule offset
                        for (uint i=0; i<SubClassRuleCount; i++)
                        {
                            if (m_offsetSubClassSet + GetSubClassRuleOffset(i) > m_bufTable.GetLength())
                            {
                                v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", SubClassRule[" + i + "]");
                                bRet = false;
                            }
                        }

                        // check each SubClassRule table
                        for (uint i=0; i<SubClassRuleCount; i++)
                        {
                            SubClassRule_val scr = GetSubClassRuleTable_val(i);
                            bRet &= scr.Validate(v, sIdentity + ", SubClassRule[" + i + "]", table);
                        }

                        return bRet;
                    }
Пример #19
0
                public bool Validate(Validator v, string sIdentity, OTTable table)
                {
                    bool bRet = true;

                    // check for data overlap
                    bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetContextSubst, CalcLength(), v, sIdentity, table.GetTag());

                    // check the coverage offset
                    if (m_offsetContextSubst + CoverageOffset > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", Coverage offset");
                        bRet = false;
                    }

                    // check the coverage table
                    CoverageTable_val ct = GetCoverageTable_val();
                    bRet &= ct.Validate(v, sIdentity + ", Coverage", table);

                    // check the ClassDef offset
                    if (m_offsetContextSubst + ClassDefOffset > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", ClassDef offset");
                        bRet = false;
                    }

                    // check the ClassDef table
                    ClassDefTable_val cdt = GetClassDefTable_val();
                    bRet &= cdt.Validate(v, sIdentity + ", ClassDef", table);

                    // check the SubClassSet array length
                    if (m_offsetContextSubst + (uint)FieldOffsets.SubClassSetOffsets + SubClassSetCount*2 > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", SubClassSet array");
                        bRet = false;
                    }

                    // check each SubClassSet offset
                    for (uint i=0; i<SubClassSetCount; i++)
                    {
                        if (m_offsetContextSubst + GetSubClassSetOffset(i) > m_bufTable.GetLength())
                        {
                            v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", SubClassSet[" + i + "]");
                            bRet = false;
                        }
                    }

                    // check each SubClassSet table
                    for (uint i=0; i<SubClassSetCount; i++)
                    {
                        if (GetSubClassSetOffset(i) != 0)
                        {
                            SubClassSet_val scs = GetSubClassSetTable_val(i);
                            if (scs != null)
                            {
                                bRet &= scs.Validate(v, sIdentity + ", SubClassSet[" + i + "]", table);
                            }
                        }
                    }

                    return bRet;
                }
Пример #20
0
                        public bool Validate(Validator v, string sIdentity, OTTable table)
                        {
                            bool bRet = true;
                            
                            // check for data overlap
                            bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetSubRule, CalcLength(), v, sIdentity, table.GetTag());

                            // check the Input array length
                            if (m_offsetSubRule + (uint)FieldOffsets.InputGlyphIds + (GlyphCount-1)*2 > m_bufTable.GetLength())
                            {
                                v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", Input array");
                                bRet = false;
                            }

                            // check the SubstLookupRecord array length
                            uint offset = m_offsetSubRule + (uint)FieldOffsets.InputGlyphIds + (uint)(GlyphCount-1)*2;
                            if (offset + SubstCount*4 > m_bufTable.GetLength())
                            {
                                v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", SubstLookupRecord array");
                                bRet = false;
                            }

                            // check each SubstLookupRecord
                            for (uint i=0; i<SubstCount; i++)
                            {
                                SubstLookupRecord slr = GetSubstLookupRecord(i);
                                if (slr.SequenceIndex > GlyphCount)
                                {
                                    string sValues = ", slr.SequenceIndex = " + slr.SequenceIndex + ", slr.LookupListIndex = " + slr.LookupListIndex + ", GlyphCount = " + GlyphCount;
                                    v.Error(T.T_NULL, E.GSUB_E_SubstLookupRecord_SequenceIndex, table.m_tag, sIdentity + ", SubstLookupRecord[" + i + "]" + sValues);
                                    bRet = false;
                                }
                            }


                            return bRet;
                        }
Пример #21
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                sIdentity += "(ContextSubst, fmt " + SubstFormat + ")";


                if (SubstFormat == 1)
                {
                    ContextSubstFormat1_val f1 = GetContextSubstFormat1_val();
                    bRet &= f1.Validate(v, sIdentity, table);
                }
                else if (SubstFormat == 2)
                {
                    ContextSubstFormat2_val f2 = GetContextSubstFormat2_val();
                    bRet &= f2.Validate(v, sIdentity, table);
                }
                else if (SubstFormat == 3)
                {
                    ContextSubstFormat3_val f3 = GetContextSubstFormat3_val();
                    bRet &= f3.Validate(v, sIdentity, table);
                }
                else
                {
                    v.Error(T.T_NULL, E.GSUB_E_SubtableFormat, table.m_tag, sIdentity);
                    bRet = false;
                }

                if (bRet)
                {
                    v.Pass(T.T_NULL, P.GSUB_P_ContextSubst, table.m_tag, sIdentity);
                }

                return bRet;
            }
Пример #22
0
        public bool Validate(Validator v, string sIdentity, OTTable table)
        {
            bool bRet = true;

            if (ClassFormat == 1)
            {
                ClassDefFormat1_val cdf1 = GetClassDefFormat1_val();
                bRet &= cdf1.Validate(v, sIdentity + "(Fmt1)", table);
            }
            else if (ClassFormat == 2)
            {
                ClassDefFormat2_val cdf2 = GetClassDefFormat2_val();
                bRet &= cdf2.Validate(v, sIdentity + "(Fmt2)", table);
            }
            else
            {
                v.Error(T.T_NULL, E._OTL_ClassDefinitionTable_E_Format, table.m_tag, sIdentity + ", format = " + ClassFormat.ToString());
                bRet = false;
            }

            // way too many ClassDefTables to justify this pass message
            //if (bRet)
            //{
            //    v.Pass("_OTL_ClassDefinitionTable_P_valid", table.m_tag, sIdentity);
            //}

            return bRet;
        }
Пример #23
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                if (m_offsetClassDefFormat1 + (uint)FieldOffsets.ClassValueArray + GlyphCount*2 > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E._OTL_ClassDefinitionTable_E_GlyphArrayPastEOT, table.m_tag, sIdentity);
                    bRet = false;
                }

                return bRet;
            }
Пример #24
0
        public bool Validate(Validator v, string sIdentity, OTTable table)
        {
            bool bRet = true;
            bool bScriptListOk = true;

            // check that ScriptRecord array doesn't extend past end of table

            if (m_offsetScriptListTable + (uint)FieldOffsets.ScriptRecords + 6*ScriptCount > m_bufTable.GetLength())
            {
                v.Error(T.T_NULL, E._OTL_ScriptListTable_E_ScriptRecordArray_pastEOT, table.m_tag, sIdentity);
                bScriptListOk = false;
                bRet = false;
            }

            // check that ScriptRecord array is in alphabetical order
            if (ScriptCount > 1)
            {
                for (uint i=0; i<ScriptCount-1; i++)
                {
                    ScriptRecord srCurr = GetScriptRecord(i);
                    ScriptRecord srNext = GetScriptRecord(i+1);
                    if (srCurr.ScriptTag >= srNext.ScriptTag)
                    {
                        v.Error(T.T_NULL, E._OTL_ScriptListTable_E_ScriptRecordArray_order, table.m_tag, sIdentity);
                        bScriptListOk = false;
                        bRet = false;
                    }
                }
            }

            // check each ScriptRecord
            for (uint i=0; i<ScriptCount; i++)
            {
                // check the tag
                ScriptRecord sr = GetScriptRecord(i);
                if (!sr.ScriptTag.IsValid())
                {
                    v.Error(T.T_NULL, E._OTL_ScriptListTable_E_ScriptRecord_tag, table.m_tag, sIdentity + ", ScriptRecord[" + i + "]");
                    bScriptListOk = false;
                    bRet = false;
                }

                // check the offset
                if (m_offsetScriptListTable + sr.ScriptTableOffset > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E._OTL_ScriptListTable_E_ScriptRecord_offset, table.m_tag, sIdentity + ", ScriptRecord[" + i + "]");
                    bScriptListOk = false;
                    bRet = false;
                }

                // validate the ScriptTable
                ScriptTable_val st = GetScriptTable_val(sr);
                bRet &= st.Validate(v, sIdentity + ", ScriptRecord[" + i + "](" + sr.ScriptTag + "), ScriptTable", table);
            }

            if (bScriptListOk)
            {
                v.Pass(T.T_NULL, P._OTL_ScriptListTable_P_valid, table.m_tag, sIdentity);
            }

            return bRet;
        }
Пример #25
0
        public bool Validate(Validator v, string sIdentity, OTTable table)
        {
            bool bRet = true;

            // check StartSize for unreasonable values
            if (StartSize > 16384)
            {
                v.Warning(T.T_NULL, W._OTL_DeviceTable_W_StartSize, table.m_tag, sIdentity + ", StartSize = " + StartSize);
            }

            // check EndSize for unreasonable values
            if (EndSize > 16384)
            {
                v.Warning(T.T_NULL, W._OTL_DeviceTable_W_EndSize, table.m_tag, sIdentity + ", EndSize = " + EndSize);
            }

            // check that StartSize <= EndSize
            if (StartSize > EndSize)
            {
                v.Error(T.T_NULL, E._OTL_DeviceTable_E_sizes, table.m_tag, sIdentity);
                bRet = false;
            }

            // check DeltaFormat is 1, 2, or 3
            if (DeltaFormat < 1 || DeltaFormat > 3)
            {
                v.Error(T.T_NULL, E._OTL_DeviceTable_E_DeltaFormat, table.m_tag, sIdentity + ", DeltaFormat = " + DeltaFormat);
                bRet = false;
            }
            else
            {

                // check that DeltaValue array doesn't extend past the end of the table
                int nSizes = EndSize - StartSize + 1;
                int nValuesPerUint = 16 >> DeltaFormat;
                int nUints = nSizes / nValuesPerUint;
                if (nSizes % nValuesPerUint != 0) nUints++;
                if (m_offsetDeviceTable + (uint)FieldOffsets.DeltaValueArray + nUints > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E._OTL_DeviceTable_E_DeltaValueArray_pastEOT, table.m_tag, sIdentity);
                    bRet = false;
                }
            }

            // way too many device tables to justify this pass message
            //if (bRet)
            //{
            //    v.Pass("_OTL_DeviceTable_P_valid", table.m_tag, sIdentity);
            //}

            return bRet;
        }
Пример #26
0
        public bool Validate(Validator v, string sIdentity, OTTable table)
        {
            bool bRet = true;

            if (LookupOrder != 0)
            {
                v.Error(T.T_NULL, E._OTL_LangSysTable_E_LookupOrder, table.m_tag, sIdentity);
                bRet = false;
            }

            if (m_offsetLangSysTable + (uint)FieldOffsets.FeatureIndexArray + FeatureCount*2 > m_bufTable.GetLength())
            {
                v.Error(T.T_NULL, E._OTL_LangSysTable_E_FeatureIndexArray_pastEOT, table.m_tag, sIdentity);
                bRet = false;
            }

            if (bRet)
            {
                v.Pass(T.T_NULL, P._OTL_LangSysTable_P_valid, table.m_tag, sIdentity);
            }

            return bRet;
        }
Пример #27
0
        public virtual OTTable CreateTableObject(OTTag tag, MBOBuffer buf)
        {
            OTTable table = null;

            string sName = GetUnaliasedTableName(tag);

            switch (sName)
            {
            case "BASE": table = new Table_BASE(tag, buf); break;

            case "CFF ": table = new Table_CFF(tag, buf); break;

            case "cmap": table = new Table_cmap(tag, buf); break;

            case "cvt ": table = new Table_cvt(tag, buf); break;

            case "DSIG": table = new Table_DSIG(tag, buf); break;

            case "EBDT": table = new Table_EBDT(tag, buf); break;

            case "EBLC": table = new Table_EBLC(tag, buf); break;

            case "EBSC": table = new Table_EBSC(tag, buf); break;

            case "fpgm": table = new Table_fpgm(tag, buf); break;

            case "gasp": table = new Table_gasp(tag, buf); break;

            case "GDEF": table = new Table_GDEF(tag, buf); break;

            case "glyf": table = new Table_glyf(tag, buf); break;

            case "GPOS": table = new Table_GPOS(tag, buf); break;

            case "GSUB": table = new Table_GSUB(tag, buf); break;

            case "hdmx": table = new Table_hdmx(tag, buf); break;

            case "head": table = new Table_head(tag, buf); break;

            case "hhea": table = new Table_hhea(tag, buf); break;

            case "hmtx": table = new Table_hmtx(tag, buf); break;

            case "JSTF": table = new Table_JSTF(tag, buf); break;

            case "kern": table = new Table_kern(tag, buf); break;

            case "loca": table = new Table_loca(tag, buf); break;

            case "LTSH": table = new Table_LTSH(tag, buf); break;

            case "maxp": table = new Table_maxp(tag, buf); break;

            case "name": table = new Table_name(tag, buf); break;

            case "OS/2": table = new Table_OS2(tag, buf); break;

            case "PCLT": table = new Table_PCLT(tag, buf); break;

            case "post": table = new Table_post(tag, buf); break;

            case "prep": table = new Table_prep(tag, buf); break;

            case "VDMX": table = new Table_VDMX(tag, buf); break;

            case "vhea": table = new Table_vhea(tag, buf); break;

            case "vmtx": table = new Table_vmtx(tag, buf); break;

            case "VORG": table = new Table_VORG(tag, buf); break;

            //case "Zapf": table = new Table_Zapf(tag, buf); break;
            default: table = new Table__Unknown(tag, buf); break;
            }

            return(table);
        }
Пример #28
0
        public bool Validate(Validator v, string sIdentity, OTTable table)
        {
            bool bRet = true;

            bool bFeatureListOk = true;

            // check the FeatureRecord array length
            if (m_offsetFeatureListTable + (uint)FieldOffsets.FeatureRecordArray + FeatureCount*6 > m_bufTable.GetLength())
            {
                v.Error(T.T_NULL, E._OTL_FeatureListTable_E_FeatureRecordArray_pastEOT, table.m_tag, sIdentity);
                bFeatureListOk = false;
                bRet = false;
            }

            // check that the FeatureRecord array is sorted alphabetically
            if (FeatureCount > 1)
            {
                for (uint i=0; i<FeatureCount-1; i++)
                {
                    FeatureRecord frCurr = GetFeatureRecord(i);
                    FeatureRecord frNext = GetFeatureRecord(i+1);
                    if (frCurr.FeatureTag > frNext.FeatureTag)
                    {
                        v.Error(T.T_NULL, E._OTL_FeatureListTable_E_FeatureRecordArray_order, table.m_tag, sIdentity);
                        bFeatureListOk = false;
                        bRet = false;
                        break;
                    }
                }
            }

            // check each FeatureRecord
            for (uint i=0; i<FeatureCount; i++)
            {
                FeatureRecord fr = GetFeatureRecord(i);
                if (fr != null)
                {
                    // check tag
                    if (!fr.FeatureTag.IsValid())
                    {
                        v.Error(T.T_NULL, E._OTL_FeatureListTable_E_FeatureRecord_tag, table.m_tag, sIdentity + ", FeatureRecord[" + i + "]");
                        bFeatureListOk = false;
                        bRet = false;
                    }
                    else if (!IsKnownFeatureTag(fr.FeatureTag))
                    {
                        v.Warning(T.T_NULL, W._OTL_FeatureListTable_W_FeatureRecord_tag, table.m_tag, sIdentity + ", FeatureRecord[" + i + "], tag = '" + fr.FeatureTag + "'");
                    }

                    // check offset
                    if (m_offsetFeatureListTable + fr.FeatureTableOffset > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E._OTL_FeatureListTable_E_FeatureRecord_offset, table.m_tag, sIdentity + ", FeatureRecord[" + i + "]");
                        bFeatureListOk = false;
                        bRet = false;
                    }
                    else
                    {
                        // validate the feature table
                        FeatureTable_val ft = GetFeatureTable_val(fr);
                        bRet &= ft.Validate(v, sIdentity + ", FeatureRecord[" + i + "]" + "(" + (string)fr.FeatureTag +  ")" + ", FeatureTable", table);
                    }
                }
                else
                {
                    bFeatureListOk = false;
                    bRet = false;
                }
            }


            if (bFeatureListOk)
            {
                v.Pass(T.T_NULL, P._OTL_FeatureListTable_P_valid, table.m_tag, sIdentity);
            }

            return bRet;
        }
Пример #29
0
                public bool Validate(Validator v, string sIdentity, OTTable table)
                {
                    bool bRet = true;

                    // check for data overlap
                    bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetSingleSubst, CalcLength(), v, sIdentity, table.GetTag());

                    // check the coverage offset
                    if (m_offsetSingleSubst + CoverageOffset > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", Coverage offset");
                        bRet = false;
                    }

                    // check the coverage table
                    CoverageTable_val ct = GetCoverageTable_val();
                    bRet &= ct.Validate(v, sIdentity + ", Coverage", table);

                    // check the Substitute array length
                    if (m_offsetSingleSubst + (uint)FieldOffsets.SubstituteGlyphIDs + GlyphCount*2 > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", Substitute array");
                        bRet = false;
                    }

                    return bRet;
                }
Пример #30
0
                public bool Validate(Validator v, string sIdentity, OTTable table)
                {
                    bool bRet = true;

                    // check for data overlap
                    bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetAlternateSet, CalcLength(), v, sIdentity, table.GetTag());

                    // check the alternate array length
                    if (m_offsetAlternateSet + (uint)FieldOffsets.AlternateGlyphIDs + GlyphCount*2 > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", Alternate array");
                        bRet = false;
                    }

                    return bRet;
                }
Пример #31
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                sIdentity += "(ReverseChainSubst)";

                // check for data overlap
                bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetReverseChainSubst, CalcLength(), v, sIdentity, table.GetTag());

                // check the SubstFormat
                if (SubstFormat != 1)
                {
                    v.Error(T.T_NULL, E.GSUB_E_SubtableFormat, table.m_tag, sIdentity + ", SubstFormat = " + SubstFormat);
                    bRet = false;
                }

                // check the coverage offset
                if (m_offsetReverseChainSubst + CoverageOffset > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", Coverage offset");
                    bRet = false;
                }

                // check the coverage table
                CoverageTable_val ct = GetCoverageTable_val();
                bRet &= ct.Validate(v, sIdentity + ", Coverage table", table);

                // check the BacktrackCoverage array length
                uint offset = m_offsetReverseChainSubst + (uint)FieldOffsets.BacktrackCoverageOffsets;
                if (offset + BacktrackGlyphCount*2 > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", BacktrackCoverage array");
                    bRet = false;
                }

                // check each BacktrackCoverage offset
                for (uint i=0; i<BacktrackGlyphCount; i++)
                {
                    if (m_offsetReverseChainSubst + GetBacktrackCoverageOffset(i) > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", BacktrackCoverage[" + i + "]");
                        bRet = false;
                    }
                }

                // check each BacktrackCoverage table
                for (uint i=0; i<BacktrackGlyphCount; i++)
                {
                    CoverageTable_val bct = GetBacktrackCoverageTable_val(i);
                    bRet &= bct.Validate(v, sIdentity + ", BacktrackCoverage[" + i + "]", table);
                }

                // check the LookaheadCoverage array length
                offset = m_offsetReverseChainSubst + (uint)FieldOffsets.BacktrackCoverageOffsets + (uint)BacktrackGlyphCount*2
                    + 2;
                if (offset + LookaheadGlyphCount*2 > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", LookaheadCoverage array");
                    bRet = false;
                }

                // check each LookaheadCoverage offset
                for (uint i=0; i<LookaheadGlyphCount; i++)
                {
                    if (m_offsetReverseChainSubst + GetLookaheadCoverageOffset(i) > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", LookaheadCoverage[" + i + "]");
                        bRet = false;
                    }
                }

                // check each LookaheadCoverage table
                for (uint i=0; i<LookaheadGlyphCount; i++)
                {
                    CoverageTable_val lct = GetLookaheadCoverageTable_val(i);
                    bRet &= lct.Validate(v, sIdentity + ", LookaheadCoverage[" + i + "]", table);
                }


                // check the SubstituteGlyphIDs array length
                offset = m_offsetReverseChainSubst + (uint)FieldOffsets.BacktrackCoverageOffsets + (uint)BacktrackGlyphCount*2
                    + 2 + (uint)LookaheadGlyphCount*2 + 2;
                if (offset + SubstituteGlyphCount*2 > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", Substitue Glyph ID array");
                    bRet = false;
                }


                if (bRet)
                {
                    v.Pass(T.T_NULL, P.GSUB_P_ReverseChainContextSubst, table.m_tag, sIdentity);
                }



                return bRet;
            }
Пример #32
0
            public bool Validate( Validator v, 
                                  OTTable table, 
                                  ushort numGlyphs,
                                  String sIdentity )
            {

                bool bRet = true;

                m_v = v;
                m_table = table;
                m_sIdentity = sIdentity;
                m_numGlyphs = numGlyphs;

                List<VarSelectorRecord> recs = new List<VarSelectorRecord>();

                // Find the offset of the start of the Default and
                // Non-Default UVS tables to make sure that
                // everything the offsets point to is within the table
                // area.
                const uint f14HeaderLength = 10; // USHORT, ULONG, ULONG
                const uint varSelRecLength = 11; // UINT24, ULONG, ULONG
                uint dataStart = f14HeaderLength + 
                    ( NumVarSelectorRecs * varSelRecLength );
                        
                // Fill in recs while we are at it.
                bool bLengthsOk = CheckLengths( dataStart, recs );
                bRet = bLengthsOk;

                if ( !bLengthsOk ) {
                    string unable = "Unable to perform more tests";
                    // Is the 2nd arg correct?
                    v.Warning( T.T_NULL, W._TEST_W_OtherErrorsInTable, 
                               m_table.m_tag, unable + SDetails() );
                    goto Finish;
                } 
                
                // We now know that all the tables are within the data area,
                // that is, from dataStart to the end of the subtable. Now
                // we about overlapping and non-packed tables.
                bool bOverlapsOk = CheckOverlaps( dataStart, recs );
                if ( !bOverlapsOk ) {
                    bRet = false;
                    string unable = "Unable to perform more tests";
                    // Is the 2nd arg correct?
                    v.Warning( T.T_NULL, W._TEST_W_OtherErrorsInTable, 
                               m_table.m_tag, unable + SDetails() );
                    goto Finish;
                }

                // Check that all values in offset tables are legal
                bRet = CheckLegalValues( recs );

                Finish:
                return bRet;
            }
Пример #33
0
            public bool Validate(Validator v, OTTable table, ushort numGlyphs,
                                 String sIdentity)
            {
                bool bRet = true;

                
                // check the mapping

                byte [] charbuf = new byte[2];
                for (uint i = 0; i<=65535; i++)
                {
                    char c = (char)i;
                    charbuf[0] = (byte)c;
                    charbuf[1] = (byte)(c>>8);
                    uint nGlyphID = MapCharToGlyph(charbuf, 0);
                    if (nGlyphID >= numGlyphs)
                    {
                        v.Error(T.T_NULL, E.cmap_E_Mapping, table.m_tag, 
                                sIdentity + ", char = 0x" + 
                                ((uint)c).ToString("X4") + ", glyphID = " +
                                nGlyphID);
                        bRet = false;
                    }
                }


                return bRet;
            }
Пример #34
0
                public bool Validate(Validator v, string sIdentity, OTTable table)
                {
                    bool bRet = true;

                    // check for data overlap
                    bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetChainContextSubst, CalcLength(), v, sIdentity, table.GetTag());

                    // check the BacktrackCoverage array length
                    uint offset = m_offsetChainContextSubst + (uint)FieldOffsets.BacktrackCoverageOffsets;
                    if (offset + BacktrackGlyphCount*2 > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", BacktrackCoverage array");
                        bRet = false;
                    }

                    // check each BacktrackCoverage offset
                    for (uint i=0; i<BacktrackGlyphCount; i++)
                    {
                        if (m_offsetChainContextSubst + GetBacktrackCoverageOffset(i) > m_bufTable.GetLength())
                        {
                            v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", BacktrackCoverage[" + i + "]");
                            bRet = false;
                        }
                    }

                    // check each BacktrackCoverage table
                    for (uint i=0; i<BacktrackGlyphCount; i++)
                    {
                        CoverageTable_val ct = GetBacktrackCoverageTable_val(i);
                        ct.Validate(v, sIdentity + ", BacktrackCoverage[" + i + "]", table);
                    }

                    // check the InputCoverage array length
                    offset = m_offsetChainContextSubst + (uint)FieldOffsets.BacktrackCoverageOffsets 
                        + (uint)BacktrackGlyphCount*2 + 2;
                    if (offset + InputGlyphCount*2 > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", InputCoverage array");
                        bRet = false;
                    }

                    // check each InputCoverage offset
                    for (uint i=0; i<InputGlyphCount; i++)
                    {
                        if (m_offsetChainContextSubst + GetInputCoverageOffset(i) > m_bufTable.GetLength())
                        {
                            v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", InputCoverage[" + i + "]");
                            bRet = false;
                        }
                    }

                    // check each InputCoverage table
                    for (uint i=0; i<InputGlyphCount; i++)
                    {
                        CoverageTable_val ct = GetInputCoverageTable_val(i);
                        ct.Validate(v, sIdentity + ", InputCoverage[" + i + "]", table);
                    }

                    // check the LookaheadCoverage array length
                    offset = m_offsetChainContextSubst + (uint)FieldOffsets.BacktrackCoverageOffsets 
                        + (uint)BacktrackGlyphCount*2 + 2 + (uint)InputGlyphCount*2 + 2;
                    if (offset + LookaheadGlyphCount*2 > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", LookaheadCoverage array");
                        bRet = false;
                    }

                    // check each LookaheadCoverage offset
                    for (uint i=0; i<LookaheadGlyphCount; i++)
                    {
                        if (m_offsetChainContextSubst + GetLookaheadCoverageOffset(i) > m_bufTable.GetLength())
                        {
                            v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", LookaheadCoverage[" + i + "]");
                            bRet = false;
                        }
                    }

                    // check each LookaheadCoverage table
                    for (uint i=0; i<LookaheadGlyphCount; i++)
                    {
                        CoverageTable_val ct = GetLookaheadCoverageTable_val(i);
                        ct.Validate(v, sIdentity + ", LookaheadCoverage[" + i + "]", table);
                    }

                    // check the SubstLookupRecord array length
                    offset = m_offsetChainContextSubst + (uint)FieldOffsets.BacktrackCoverageOffsets 
                        + (uint)BacktrackGlyphCount*2 + 2 + (uint)InputGlyphCount*2 + 2 
                        + (uint)LookaheadGlyphCount*2 + 2;
                    if (offset + SubstCount*4 > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", SubstLookupRecord array");
                        bRet = false;
                    }

                    // check each SubstLookupRecord
                    for (uint i=0; i<SubstCount; i++)
                    {
                        SubstLookupRecord slr = GetSubstLookupRecord(i);
                        if (slr.SequenceIndex > InputGlyphCount)
                        {
                            string sValues = ", slr.SequenceIndex = " + slr.SequenceIndex + ", slr.LookupListIndex = " + slr.LookupListIndex + ", InputGlyphCount = " + InputGlyphCount;
                            v.Error(T.T_NULL, E.GSUB_E_SubstLookupRecord_SequenceIndex, table.m_tag, sIdentity + ", SubstLookupRecord[" + i + "]" + sValues);
                            bRet = false;
                        }
                    }

                    return bRet;
                }
Пример #35
0
        public bool Validate(Validator v, string sIdentity, OTTable table)
        {
            bool bRet = true;

            // check that FeatureParams is null
            if (FeatureParams != 0)
            {
                v.Error(T.T_NULL, E._OTL_FeatureTable_E_FeatureParams_nonnull, table.m_tag, sIdentity);
                bRet = false;
            }

            // check LookupListIndex array length
            if (m_offsetFeatureTable + (uint)FieldOffsets.LookupListIndexArray + LookupCount * 2 > m_bufTable.GetLength())
            {
                v.Error(T.T_NULL, E._OTL_FeatureTable_E_LookupListIndexArray_pastEOT, table.m_tag, sIdentity);
                bRet = false;
            }

            if (bRet)
            {
                v.Pass(T.T_NULL, P._OTL_FeatureTable_P_valid, table.m_tag, sIdentity);
            }

            return bRet;
        }
Пример #36
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;


                sIdentity += "(LigatureSubst, fmt " + SubstFormat + ")";

                if (SubstFormat == 1)
                {
                    // check for data overlap
                    bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetLigatureSubst, CalcLength(), v, sIdentity, table.GetTag());

                    // check the coverage offset
                    if (m_offsetLigatureSubst + CoverageOffset > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", Coverage offset");
                        bRet = false;
                    }

                    // check the coverage table
                    CoverageTable_val ct = GetCoverageTable_val();
                    bRet &= ct.Validate(v, sIdentity + ", Coverage", table);

                    // check the LigatureSet array length
                    if (m_offsetLigatureSubst + (uint)FieldOffsets.LigatureSetOffsets + LigSetCount*2 > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", LigatureSet array");
                        bRet = false;
                    }

                    // check each LigatureSet offset
                    for (uint i=0; i<LigSetCount; i++)
                    {
                        if (m_offsetLigatureSubst + GetLigatureSetOffset(i) > m_bufTable.GetLength())
                        {
                            v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", LigatureSet[" + i + "]");
                            bRet = false;
                        }
                    }

                    // check each LigatureSet table
                    for (uint i=0; i<LigSetCount; i++)
                    {
                        LigatureSet_val ls = GetLigatureSetTable_val(i);
                        bRet &= ls.Validate(v, sIdentity + ", LigatureSet[" + i + "]", table);
                    }
                }
                else
                {
                    v.Error(T.T_NULL, E.GSUB_E_SubtableFormat, table.m_tag, sIdentity);
                    bRet = false;
                }

                if (bRet)
                {
                    v.Pass(T.T_NULL, P.GSUB_P_LigatureSubst, table.m_tag, sIdentity);
                }

                return bRet;
            }
Пример #37
0
            public bool Validate(Validator v, OTTable table, ushort numGlyphs,
                                 String sIdentity)
            {
                bool bRet = true;

                // warn if not encoding id 10
                if (m_ete.encodingID != 10)
                {
                    v.Warning(T.T_NULL, W.cmap_W_f12_EncID, table.m_tag, 
                              sIdentity);
                }

                // check that groups are sorted by ascending startCharCodes
                if (nGroups > 1)
                {
                    for (uint i=0; i<nGroups-1; i++)
                    {
                        Group gCurr = GetGroup(i);
                        Group gNext = GetGroup(i+1);

                        if (gCurr.startCharCode >= gNext.startCharCode)
                        {
                            v.Error(T.T_NULL, E.cmap_E_f12_SortOrder, 
                                    table.m_tag, sIdentity);
                            bRet = false;
                            break;
                        }
                    }
                }

                // check each start code is less than or equal to the end code
                for (uint i=0; i<nGroups; i++)
                {
                    Group g = GetGroup(i);
                    if (g.startCharCode > g.endCharCode)
                    {
                        String sDetails = ", group[" + i +
                            "], startCharCode = 0x" +
                            g.startCharCode.ToString("X8") + 
                            ", endCharCode = 0x" + g.endCharCode.ToString("X8");
                        v.Error(T.T_NULL, E.cmap_E_f12_StartCode_GT_EndCode, 
                                table.m_tag, sIdentity + sDetails);
                        bRet = false;
                    }
                }

                // check the mapping
                for (uint i=0; i<nGroups; i++)
                {
                    Group g = GetGroup(i);
                    uint c = g.endCharCode;
                    uint nGlyphID = g.startGlyphID + (c - g.startCharCode);
                    if (nGlyphID >= numGlyphs)
                    {
                        v.Error(T.T_NULL, E.cmap_E_Mapping, table.m_tag, 
                                sIdentity + ", char = 0x" + 
                                ((uint)c).ToString("X4") + ", glyphID = " + 
                                nGlyphID);
                        bRet = false;
                    }
                }

                
                // if encoding id 10, then check that the greatest character
                // is not greater than 0x10ffff
                if (m_ete.encodingID == 10)
                {
                    if (nGroups > 0)
                    {
                        Group lastgroup = GetGroup(nGroups-1);
                        if (lastgroup.endCharCode > 0x10ffff)
                        {
                            v.Error(T.T_NULL, E.cmap_E_f12_EndCode_GT_10FFFF, 
                                    table.m_tag, sIdentity + 
                                    ", last endCharCode = 0x" + 
                                    lastgroup.endCharCode.ToString("X8"));
                            bRet = false;
                        }
                    }
                }

                return bRet;
            }
Пример #38
0
        public bool Validate(Validator v, string sIdentity, OTTable table)
        {
            bool bRet = true;
            bool bLookupListOk = true;

            // check that the Lookup array doesn't extend past end of table
            if (m_offsetLookupListTable + (uint)FieldOffsets.LookupArray + LookupCount * 2 > m_bufTable.GetLength())
            {
                v.Error(T.T_NULL, E._OTL_LookupListTable_E_LookupArray_pastEOT, table.m_tag, sIdentity);
                bLookupListOk = false;
                bRet = false;
            }

            // check that each offset is within the table
            for (uint i=0; i<LookupCount; i++)
            {
                if (m_offsetLookupListTable + GetLookupOffset(i) > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E._OTL_LookupListTable_E_Lookup_offset, table.m_tag, sIdentity + ", Lookup[" + i + "]");
                    bLookupListOk = false;
                    bRet = false;
                }
            }

            // validate each lookup table
            for (uint i=0; i<LookupCount; i++)
            {
                LookupTable_val lt = GetLookupTable_val(i);
                if (lt != null)
                {
                    bRet &= lt.Validate(v, sIdentity + ", Lookup[" + i + "]", table);
                }
                else
                {
                    bLookupListOk = false;
                    bRet = false;
                }
            }

            if (bLookupListOk)
            {
                v.Pass(T.T_NULL, P._OTL_LookupListTable_P_valid, table.m_tag, sIdentity);
            }

            return bRet;
        }
Пример #39
0
            public bool Validate(Validator v, OTTable table, ushort numGlyphs,
                                 String sIdentity)
            {
                bool bRet = true;

                // check the length

                if (length != 262)
                {
                    v.Error(T.T_NULL, E.cmap_E_f0_length, table.m_tag, 
                            sIdentity);
                    bRet = false;
                }

                // check the mapping
                for (char c = (char)0; c<256; c++)
                {
                    ushort nGlyphID = GetGlyphID(c);
                    if (nGlyphID >= numGlyphs)
                    {
                        v.Error(T.T_NULL, E.cmap_E_Mapping, table.m_tag,
                                sIdentity + ", char = 0x" +
                                ((uint)c).ToString("X4") + ", glyphID = " + 
                                nGlyphID);
                        bRet = false;
                    }
                }


                return bRet;
            }
Пример #40
0
        public bool Validate(Validator v, string sIdentity, OTTable table)
        {
            bool bRet = true;

            // check the LookupType
            if (((string)table.m_tag == "GPOS") && LookupType > 9 
                || ((string)table.m_tag == "GSUB" && LookupType > 8))
            {
                v.Error(T.T_NULL, E._OTL_LookupTable_E_LookupType, table.m_tag, sIdentity + ", LookupType = " + LookupType);
                bRet = false;
            }

            // check LookupFlag reserved bits are clear
            if ((LookupFlag & 0x00f0) != 0)
            {
                v.Error(T.T_NULL, E._OTL_LookupTable_E_LookupFlag_reserved, table.m_tag, sIdentity);
                bRet = false;
            }

            // check Subtable offset array doesn't extend past end of table
            if (m_offsetLookupTable + (uint)FieldOffsets.SubTableOffsetArray + SubTableCount*2 > m_bufTable.GetLength())
            {
                v.Error(T.T_NULL, E._OTL_LookupTable_E_SubtableArray_pastEOT, table.m_tag, sIdentity);
                bRet = false;
            }

            // check Subtable offsets don't point past end of table
            for (uint i=0; i<SubTableCount; i++)
            {
                // verify that the subtable offset is accessible, if not error was already reported
                if (m_offsetLookupTable + (uint)FieldOffsets.SubTableOffsetArray + i*2 + 2 <= m_bufTable.GetLength())
                {
                    if (m_offsetLookupTable + GetSubTableOffset(i) > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E._OTL_LookupTable_E_SubtableArray_offset, table.m_tag, sIdentity + ", SubTable[" + i + "]");
                        bRet = false;
                    }
                }
            }

            // way too many lookup tables to justify this pass message
            //if (bRet)
            //{
            //    v.Pass("_OTL_LookupTable_P_valid", table.m_tag, sIdentity);
            //}


            // validate each subtable
            for (uint i=0; i<SubTableCount; i++)
            {
                // verify that the subtable offset is accessible, if not error was already reported
                if (m_offsetLookupTable + (uint)FieldOffsets.SubTableOffsetArray + i*2 + 2 <= m_bufTable.GetLength())
                {
                    // verify subtable offset is valid
                    if (m_offsetLookupTable + GetSubTableOffset(i) <= m_bufTable.GetLength())
                    {
                        SubTable st = GetSubTable(i);
                        if (st != null)
                        {
                            I_OTLValidate iv = (I_OTLValidate)st;
                            bRet &= iv.Validate(v, sIdentity + ", SubTable[" + i + "]", table);
                        }
                        else
                        {
                            v.Warning(T.T_NULL, W._TEST_W_OtherErrorsInTable, table.m_tag, "unable to validate subtable: " + sIdentity + ", SubTable[" + i + "]");
                        }
                    }
                    else
                    {
                        v.Warning(T.T_NULL, W._TEST_W_OtherErrorsInTable, table.m_tag, "unable to validate subtable: " + sIdentity + ", SubTable[" + i + "]");
                    }
                }
            }


            return bRet;
        }
Пример #41
0
            public bool Validate(Validator v, OTTable table, ushort numGlyphs,
                                 String sIdentity)
            {
                bool bRet = true;

                // check that segCountX2 is even
                if ((segCountX2 & 1) == 1)
                {
                    v.Error(T.T_NULL, E.cmap_E_f4_segCountX2, table.m_tag, 
                            sIdentity + ", segCountX2 = " + segCountX2);
                    bRet = false;
                }

                // check searchRange
                ushort segCount = (ushort)(segCountX2 / 2);
                ushort CalculatedSearchRange  = 
                    (ushort)(2 * util.MaxPower2LE(segCount));
                if (searchRange != CalculatedSearchRange)
                {
                    v.Error(T.T_NULL, E.cmap_E_f4_searchRange, table.m_tag, 
                            sIdentity + ", searchRange = " + searchRange +
                            ", calc = " + CalculatedSearchRange);
                    bRet = false;
                }

                // check entrySelector
                ushort CalculatedEntrySelector = 
                    util.Log2((ushort)(CalculatedSearchRange/2));
                if (entrySelector != CalculatedEntrySelector)
                {
                    v.Error(T.T_NULL, E.cmap_E_f4_entrySelector, table.m_tag, 
                            sIdentity + ", entrySelector = " + entrySelector +
                            ", calc = " + CalculatedEntrySelector);
                    bRet = false;
                }

                // check rangeShift
                ushort CalculatedRangeShift    = 
                    (ushort)(2 * segCount - CalculatedSearchRange);
                if (rangeShift != CalculatedRangeShift)
                {
                    v.Error(T.T_NULL, E.cmap_E_f4_rangeShift, table.m_tag,
                            sIdentity + ", rangeShift = " + rangeShift + 
                            ", calc = " + CalculatedRangeShift);
                    bRet = false;
                }

                // check that final endCode value is 0xffff
                if (GetEndCode((uint)segCount-1) != 0xffff)
                {
                    v.Error(T.T_NULL, E.cmap_E_f4_FinalEndCode, table.m_tag, 
                            sIdentity + ", endCode[" + (segCount-1) + "] = " +
                            GetEndCode((uint)segCount-1));
                    bRet = false;
                }

                // check that end character codes are in ascending order
                if (segCount > 1)
                {
                    for (uint i=0; i<segCount-1; i++)
                    {
                        if (GetEndCode(i) >= GetEndCode(i+1))
                        {
                            v.Error(T.T_NULL, E.cmap_E_f4_EndCodeOrder, 
                                    table.m_tag, sIdentity);
                            bRet = false;
                            break;
                        }
                    }
                }

                // check that the reservedPad is zero
                if (   m_ete.offset + (uint)FieldOffsets.endCode + segCountX2 
                       < m_bufTable.GetLength()
                       && reservedPad != 0)
                {
                    v.Error(T.T_NULL, E.cmap_E_f4_reservedPad, table.m_tag,
                            sIdentity);
                    bRet = false;
                }

                // check that each start character code is not greater than 
                // the corresponding end character code
                for (uint i=0; i<segCount; i++)
                {
                    if (GetStartCode(i) > GetEndCode(i))
                    {
                        String sDetails = ", startCode[" + i + "] = " +
                            GetStartCode(i) + " , endCode[" + i + "] = " +
                            GetEndCode(i);
                        v.Error(T.T_NULL, E.cmap_E_f4_StartCode_GT_EndCode, 
                                table.m_tag, sIdentity + sDetails);
                        bRet = false;
                    }
                }

                // check that each delta value (where idRangeOffset == 0) 
                // added to the start code is not negative
                for (uint i=0; i<segCount; i++)
                {
                    if (GetIdRangeOffset(i) == 0)
                    {
                        if (GetIdDelta(i) + GetStartCode(i) < 0)
                        {
                            String sDetails = ", idDelta[" + i + "] = " +
                                GetIdDelta(i) + ", startCode[" + i + "] = " + 
                                GetStartCode(i);
                            v.Error(T.T_NULL, E.cmap_E_f4_idDeltaNeg,
                                    table.m_tag, sIdentity + sDetails);
                            bRet = false;
                        }
                    }
                }

                // check range offsets
                for (uint i=0; i<segCount; i++)
                {
                    ushort idRangeOffset = GetIdRangeOffset(i);
                    ushort endCode = GetEndCode(i);
                    ushort startCode = GetStartCode(i);
                    if (idRangeOffset != 0)
                    {
                        uint AddressOfIdRangeOffset =
                            (uint)FieldOffsets.endCode + segCountX2*3u + 2 + 
                            i*2;
                        uint obscureIndex = (uint)
                            (idRangeOffset + (endCode - startCode)*2 + 
                             AddressOfIdRangeOffset);
                        if (obscureIndex > length)
                        {
                            v.Error(T.T_NULL, E.cmap_E_f4_idRangeOffset,
                                    table.m_tag, sIdentity + 
                                    ", idRangeOffset[" + i + "] = " + 
                                    idRangeOffset);
                            bRet = false;
                        }
                    }
                }

                // check that glyph ids are less than numGlyphs
                for (uint i=0; i<segCount; i++)
                {
                    int nGlyphMappingErrors = 0;
                    // Report the first 10 errors and 
                    // a count of errors after that.
                    int nMaxMappingErrors = 10; 
                    ushort idRangeOffset = GetIdRangeOffset(i);
                    ushort endCode = GetEndCode(i);
                    ushort startCode = GetStartCode(i);
                    short idDelta = GetIdDelta(i);
                    ushort nGlyph;

                    for (uint j=startCode; j<= endCode; j++)
                    {
                        ushort c = (ushort)j;
                        nGlyph = 0;
                        if (idRangeOffset == 0)
                        {
                            nGlyph = (ushort)(c + idDelta);
                        }
                        else
                        {
                            uint AddressOfIdRangeOffset = (uint)
                                FieldOffsets.endCode + segCountX2*3u + 2 + i*2;
                            uint obscureIndex = (uint)
                                (idRangeOffset + (c-startCode)*2 + 
                                 AddressOfIdRangeOffset);
                            // throw out invalid indexes for this test 
                            // (they should have already been reported)
                            if (obscureIndex < length && 
                                (m_ete.offset + obscureIndex < 
                                 m_bufTable.GetLength()))
                            {
                                nGlyph = 
                                    m_bufTable.GetUshort(m_ete.offset + 
                                                         obscureIndex);
                            }
                            if (nGlyph !=0 )
                            {
                                nGlyph = (ushort)(nGlyph + idDelta);
                            }
                        }

                        if (nGlyph > numGlyphs)
                        {
                            // it is possible that an entire segment is bad.
                            // That causes a hang like behavior and a 
                            // bloated error file
                            // that cannot be opened because it is so huge. 
                            if (nGlyphMappingErrors < nMaxMappingErrors)
                            {
                                v.Error(T.T_NULL, E.cmap_E_Mapping, 
                                        table.m_tag, 
                                        sIdentity + ", char = 0x" +
                                        c.ToString("X4") + ", glyphID = " + 
                                        nGlyph);
                            }
                            nGlyphMappingErrors++;
                        }
                    }

                    if (nGlyphMappingErrors >= nMaxMappingErrors)
                    {
                        string sDetails = sIdentity + ", segment = " + i + 
                            " has " + nGlyphMappingErrors + 
                            " glyphs mapped out of range";    
                        v.Error(T.T_NULL, E.cmap_E_Mapping, table.m_tag, 
                                sDetails);
                        bRet = false;
                    }
                }

                return bRet;
            }
Пример #42
0
        public bool Validate(Validator v, string sIdentity, OTTable table)
        {
            bool bRet = true;

            if (CoverageFormat == 1)
            {
                if (m_offsetCoverageTable + (uint)FieldOffsets1.GlyphArray + F1GlyphCount*2 > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E._OTL_CoverageTable_E_GlyphArrayPastEOT, table.m_tag, sIdentity);
                    bRet = false;
                }
            }
            else if (CoverageFormat == 2)
            {
                if (m_offsetCoverageTable + (uint)FieldOffsets2.RangeRecordArray + F2RangeCount*6 > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E._OTL_CoverageTable_E_RangeRecordArrayPastEOT, table.m_tag, sIdentity);
                    bRet = false;
                }
            }
            else
            {
                v.Error(T.T_NULL, E._OTL_CoverageTable_E_Format, table.m_tag, sIdentity + ", format = " + CoverageFormat.ToString());
                bRet = false;
            }

            // way too many coverage tables to justify this pass message
            //if (bRet)
            //{
            //    v.Pass("_OTL_CoverageTable_P_valid", table.m_tag, sIdentity);
            //}

            return bRet;
        }