Example #1
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

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

                // check GPOSLookupIndex array size
                if (m_offsetJstfGPOSModList + (uint)FieldOffsets.GPOSLookupIndex + LookupCount * 2 > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.JSTF_E_Array_pastEOT, table.m_tag, sIdentity + ", GPOSLookupIndex");
                    bRet = false;
                }

                // check that GPOSLookupIndex is in increasing numerical order
                if (LookupCount > 1)
                {
                    for (uint i = 0; i < LookupCount - 1; i++)
                    {
                        if (GetGPOSLookupIndex(i) >= GetGPOSLookupIndex(i + 1))
                        {
                            v.Error(T.T_NULL, E.JSTF_E_Array_order, table.m_tag, sIdentity + ", GPOSLookupIndex");
                            bRet = false;
                            break;
                        }
                    }
                }

                return(bRet);
            }
Example #2
0
        /************************
         * public methods
         */


        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            Table_maxp maxpTable = (Table_maxp)fontOwner.GetTable("maxp");

            if (maxpTable == null)
            {
                v.Error(T.T_NULL, E._TEST_E_TableMissing, m_tag, "Unable to test this table, maxp table is invalid or missing");
                return(false);
            }

            if (v.PerformTest(T.vmtx_TableLength))
            {
                uint CalcTableLength = GetNumOfLongVerMetrics(fontOwner) * 4
                                       + (fontOwner.GetMaxpNumGlyphs() - GetNumOfLongVerMetrics(fontOwner)) * 2;
                if (CalcTableLength == GetLength())
                {
                    v.Pass(T.vmtx_TableLength, P.vmtx_P_TableLength, m_tag);
                }
                else
                {
                    v.Error(T.vmtx_TableLength, E.vmtx_E_TableLength, m_tag);
                    bRet = false;
                }
            }

            return(bRet);
        }
        protected bool CheckDirectoryEntriesNonZero(Validator v)
        {
            Debug.Assert(m_OffsetTable != null);

            bool bRet = false;

            if (m_OffsetTable != null)
            {
                bRet = true;

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

                    if (de.tag == 0)
                    {
                        v.Error(E._DE_E_TagZero, null);
                        bRet = false;
                    }
                    if (de.length == 0)
                    {
                        v.Error(T.T_NULL, E._DE_E_LengthZero, null, de.tag);
                        bRet = false;
                    }
                    if (de.offset == 0)
                    {
                        v.Error(T.T_NULL, E._DE_E_OffsetZero, null, de.tag);
                        bRet = false;
                    }
                }
            }

            return(bRet);
        }
Example #4
0
        /************************
         * public methods
         */


        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            if (v.PerformTest(T.VORG_CFF_Font))
            {
                if (fontOwner.ContainsPostScriptOutlines())
                {
                    v.Pass(T.VORG_CFF_Font, P.VORG_P_CFF_Font, m_tag);
                }
                else
                {
                    v.Error(T.VORG_CFF_Font, E.VORG_E_CFF_Font, m_tag);
                    bRet = false;
                }
            }

            if (v.PerformTest(T.VORG_Version))
            {
                if (majorVersion == 1 && minorVersion == 0)
                {
                    v.Pass(T.VORG_Version, P.VORG_P_Version, m_tag);
                }
                else
                {
                    v.Error(T.VORG_Version, E.VORG_E_Version, m_tag);
                    bRet = false;
                }
            }

            return(bRet);
        }
Example #5
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

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

                // check the JstfPriority array length
                if (m_offsetJstfLangSys + (uint)FieldOffsets.JstfPriorityOffsets + JstfPriorityCount * 2 > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.JSTF_E_Array_pastEOT, table.m_tag, sIdentity + ", JstfPriority array");
                    bRet = false;
                }

                // check each JstfPriority offset
                for (uint i = 0; i < JstfPriorityCount; i++)
                {
                    if (m_offsetJstfLangSys + GetJstfPriorityOffset(i) > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.JSTF_E_Offset_PastEOT, table.m_tag, sIdentity + ", JstfPriority[" + i + "]");
                        bRet = false;
                    }
                }

                // check each JstfPriority table
                for (uint i = 0; i < JstfPriorityCount; i++)
                {
                    JstfPriority_val jp = GetJstfPriorityTable_val(i);
                    bRet &= jp.Validate(v, sIdentity + ", JstfPriority[" + i + "]", table);
                }

                return(bRet);
            }
Example #6
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

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

                // check the Lookup array length
                if (m_offsetJstfMax + (uint)FieldOffsets.LookupOffsets + LookupCount * 2 > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.JSTF_E_Array_pastEOT, table.m_tag, sIdentity + ", Lookup");
                    bRet = false;
                }

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

                // check each Lookup table
                for (uint i = 0; i < LookupCount; i++)
                {
                    LookupTable_val lt = GetLookupTable_val(i);
                    bRet &= lt.Validate(v, sIdentity + ", Lookup[" + i + "]", table);
                }

                return(bRet);
            }
Example #7
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

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

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

                // check that the ExtenderGlyph array is in increasing numerical order
                if (GlyphCount > 1)
                {
                    for (uint i = 0; i < GlyphCount - 1; i++)
                    {
                        if (GetExtenderGlyph(i) >= GetExtenderGlyph(i + 1))
                        {
                            v.Error(T.T_NULL, E.JSTF_E_Array_order, table.m_tag, sIdentity + ", ExtenderGlyph array");
                            bRet = false;
                            break;
                        }
                    }
                }


                return(bRet);
            }
Example #8
0
        /************************
         * public methods
         */


        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            Table_maxp maxpTable = (Table_maxp)fontOwner.GetTable("maxp");
            if (maxpTable == null)
            {
                v.Error(T.T_NULL, E._TEST_E_TableMissing, m_tag, "Unable to test this table, maxp table is invalid or missing");
                return false;
            }
            
            if (v.PerformTest(T.vmtx_TableLength))
            {
                uint CalcTableLength = GetNumOfLongVerMetrics(fontOwner)*4 
                    + (fontOwner.GetMaxpNumGlyphs() - GetNumOfLongVerMetrics(fontOwner))*2;
                if (CalcTableLength == GetLength())
                {
                    v.Pass(T.vmtx_TableLength, P.vmtx_P_TableLength, m_tag);
                }
                else
                {
                    v.Error(T.vmtx_TableLength, E.vmtx_E_TableLength, m_tag);
                    bRet = false;
                }
            }

            return bRet;
        }
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                bRet &= ((val_GDEF)table).ValidateNoOverlap(m_offsetMarkGlyphSetsDefTable, CalcLength(), v, sIdentity, table.GetTag());

                if (MarkSetTableFormat != 1)
                {
                    v.Error(T.T_NULL, E.GDEF_E_MarkSetTableFormat, table.m_tag,
                            sIdentity + ": MarkSetTableFormat=" + MarkSetTableFormat.ToString());
                    bRet = false;
                }

                if (m_offsetMarkGlyphSetsDefTable + CalcLength() > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.GDEF_E_MarkGlyphSetsDefTable_PastEOT, table.m_tag, sIdentity);
                    bRet = false;
                }

                v.Info(T.T_NULL, I.GDEF_I_MarkSetCount, table.m_tag, sIdentity + ": MarkSetCount=" + MarkSetCount);
                // TODO: check Coverage [MarkSetCount] array?

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

                return bRet;
            }
Example #10
0
        /************************
         * public methods
         */


        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            if (v.PerformTest(T.VORG_CFF_Font))
            {
                if (fontOwner.ContainsPostScriptOutlines())
                {
                    v.Pass(T.VORG_CFF_Font, P.VORG_P_CFF_Font, m_tag);
                }
                else
                {
                    v.Error(T.VORG_CFF_Font, E.VORG_E_CFF_Font, m_tag);
                    bRet = false;
                }
            }

            if (v.PerformTest(T.VORG_Version))
            {
                if (majorVersion == 1 && minorVersion == 0)
                {
                    v.Pass(T.VORG_Version, P.VORG_P_Version, m_tag);
                }
                else
                {
                    v.Error(T.VORG_Version, E.VORG_E_Version, m_tag);
                    bRet = false;
                }
            }

            return bRet;
        }
Example #11
0
        bool Validate_indexSubTable_format5(Validator v, indexSubTable5 ist5, indexSubTableArray ista, string sID, OTFontVal fontOwner)
        {
            bool bOk = true;

            Table_EBDT EBDTTable = (Table_EBDT)fontOwner.GetTable("EBDT");

            // header has already been validated


            // validate the image size

            if (ist5.numGlyphs * ist5.imageSize > EBDTTable.GetLength())
            {
                string sDetails = "images extend past end of EBDT table: " + sID + ", imageSize = " + ist5.imageSize
                                  + ", EBDT length = " + EBDTTable.GetLength();
                v.Error(T.EBLC_indexSubTables, E.EBLC_E_indexSubTables, m_tag, sDetails);
                bOk = false;
            }


            // validate the bigGlyphMetrics

            val_EBDT.bigGlyphMetrics_val bgm = val_EBDT.bigGlyphMetrics_val.CreateFromBigGlyphMetrics(ist5.bigMetrics);
            bgm.Validate(v, sID, this);


            // validate numGlyphs

            uint nGlyphsInRange = (uint)ista.lastGlyphIndex - ista.firstGlyphIndex + 1;

            if (ist5.numGlyphs > nGlyphsInRange)
            {
                string sDetails = "numGlyphs is invalid: " + sID +
                                  ", numGlyphs = " + ist5.numGlyphs +
                                  ", indexSubTableArray.firstGlyphIndex = " + ista.firstGlyphIndex +
                                  ", indexSubTableArray.lastGlyphIndex = " + ista.lastGlyphIndex;
                v.Error(T.EBLC_indexSubTables, E.EBLC_E_indexSubTables, m_tag, sDetails);
                bOk = false;
            }


            // validate glyphCodeArray

            for (ushort i = 0; i < ist5.numGlyphs; i++)
            {
                ushort idGlyph = ist5.GetGlyphCode(i);
                if (idGlyph < ista.firstGlyphIndex || idGlyph > ista.lastGlyphIndex)
                {
                    string sDetails = "invalid glyph id: " + sID +
                                      ", glyphCodeArray[" + i + "] = " + idGlyph +
                                      ", indexSubTableArray.firstGlyphIndex = " + ista.firstGlyphIndex +
                                      ", indexSubTableArray.lastGlyphIndex = " + ista.lastGlyphIndex;
                    v.Error(T.EBLC_indexSubTables, E.EBLC_E_indexSubTables, m_tag, sDetails);
                    bOk = false;
                }
            }

            return(bOk);
        }
Example #12
0
        bool Validate_indexSubHeader(Validator v, indexSubHeader iSH, string sID, OTFontVal fontOwner)
        {
            bool bOk = true;

            Table_EBDT EBDTTable = (Table_EBDT)fontOwner.GetTable("EBDT");

            if (iSH.indexFormat < 1 || iSH.indexFormat > 5)
            {
                string sDetails = "invalid indexFormat: " + sID + ", indexFormat = " + iSH.indexFormat;
                v.Error(T.EBLC_indexSubTables, E.EBLC_E_indexSubTables, m_tag, sDetails);
                bOk = false;
            }

            if ((iSH.imageFormat < 1 || iSH.imageFormat > 9 || iSH.imageFormat == 3) &&
                !(version.GetUint() == 0x00030000 &&
                  (iSH.imageFormat == 17 || iSH.imageFormat == 18 || iSH.imageFormat == 19)
                  ))
            {
                string sDetails = "invalid imageFormat: " + sID + ", imageFormat = " + iSH.imageFormat;
                v.Error(T.EBLC_indexSubTables, E.EBLC_E_indexSubTables, m_tag, sDetails);
                bOk = false;
            }

            bool bInconsistentFormats = false;

            if (iSH.indexFormat == 1 || iSH.indexFormat == 3 || iSH.indexFormat == 4)
            {
                if (iSH.imageFormat == 5)
                {
                    bInconsistentFormats = true;
                }
            }
            else
            {
                if (iSH.imageFormat != 5)
                {
                    bInconsistentFormats = true;
                }
            }
            if (bInconsistentFormats)
            {
                string sDetails = "inconsistent formats: " + sID + ", indexFormat = " + iSH.indexFormat + ", imageFormat = " + iSH.imageFormat;
                v.Error(T.EBLC_indexSubTables, E.EBLC_E_indexSubTables, m_tag, sDetails);
                bOk = false;
            }

            if (EBDTTable != null)
            {
                if (iSH.imageDataOffset > EBDTTable.GetLength())
                {
                    string sDetails = "invalid imageDataOffset: " + sID + ", imageDataOffset = " + iSH.imageDataOffset;
                    v.Error(T.EBLC_indexSubTables, E.EBLC_E_indexSubTables, m_tag, sDetails);
                    bOk = false;
                }
            }

            return(bOk);
        }
Example #13
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                bRet &= ((val_BASE)table).ValidateNoOverlap(m_offsetBaseScriptListTable, CalcLength(), v, sIdentity, table.GetTag());

                bool bOrderOk = true;

                if (BaseScriptCount > 1)
                {
                    for (uint i = 0; i < BaseScriptCount - 1; i++)
                    {
                        BaseScriptRecord ThisBsr = GetBaseScriptRecord(i);
                        BaseScriptRecord NextBsr = GetBaseScriptRecord(i + 1);
                        if (ThisBsr.BaseScriptTag >= NextBsr.BaseScriptTag)
                        {
                            v.Error(T.T_NULL, E.BASE_E_BaseScriptList_Order, table.m_tag, sIdentity);
                            bOrderOk = false;
                            bRet     = false;
                            break;
                        }
                    }
                }
                if (bOrderOk)
                {
                    v.Pass(T.T_NULL, P.BASE_P_BaseScriptList_Order, table.m_tag, sIdentity);
                }

                bool bOffsetsOk = true;

                for (uint i = 0; i < BaseScriptCount; i++)
                {
                    BaseScriptRecord bsr = GetBaseScriptRecord(i);
                    if (bsr.BaseScriptOffset + m_offsetBaseScriptListTable > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.BASE_E_BaseScriptList_Offset, table.m_tag, sIdentity + ", index = " + i);
                        bOffsetsOk = false;
                        bRet       = false;
                    }
                }
                if (bOffsetsOk)
                {
                    v.Pass(T.T_NULL, P.BASE_P_BaseScriptList_Offset, table.m_tag, sIdentity);
                }

                for (uint i = 0; i < BaseScriptCount; i++)
                {
                    BaseScriptRecord    bsr = GetBaseScriptRecord(i);
                    BaseScriptTable_val bst = GetBaseScriptTable_val(bsr);
                    bst.Validate(v, sIdentity + ", BaseScriptRecord[" + i + "](" + bsr.BaseScriptTag + ")", table);
                }


                return(bRet);
            }
Example #14
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                bRet &= ((val_GDEF)table).ValidateNoOverlap(m_offsetLigCaretListTable, CalcLength(), v, sIdentity, table.GetTag());

                if (CoverageOffset == 0)
                {
                    v.Error(T.T_NULL, E.GDEF_E_LigCaretListTable_CoverageOffset_0, table.m_tag, sIdentity);
                    bRet = false;
                }
                else if (CoverageOffset > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.GDEF_E_LigCaretListTable_CoverageOffset_invalid, table.m_tag, sIdentity);
                    bRet = false;
                }
                else
                {
                    v.Pass(T.T_NULL, P.GDEF_P_LigCaretListTable_CoverageOffset, table.m_tag, sIdentity);
                    CoverageTable_val ct = GetCoverageTable_val();
                    ct.Validate(v, sIdentity + ", Coverage", table);
                }



                if (m_offsetLigCaretListTable + (uint)FieldOffsets.LigGlyphOffsets + LigGlyphCount * 2 > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.GDEF_E_LigCaretListTable_LigGlyphArray_PastEOT, table.m_tag, sIdentity);
                    bRet = false;
                }

                bool bOffsetsOk = true;

                for (uint i = 0; i < LigGlyphCount; i++)
                {
                    if (m_offsetLigCaretListTable + GetLigGlyphOffset(i) > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GDEF_E_LigCaretListTable_LigGlyphOffset, table.m_tag, sIdentity + ", index = " + i);
                        bOffsetsOk = false;
                        bRet       = false;
                    }
                    else
                    {
                        LigGlyphTable_val lgt = GetLigGlyphTable_val(i);
                        lgt.Validate(v, sIdentity + ", LigGlyph[" + i + "]", table);
                    }
                }
                if (bOffsetsOk)
                {
                    v.Pass(T.T_NULL, P.GDEF_P_LigCaretListTable_LigGlyphArray, table.m_tag, sIdentity);
                }


                return(bRet);
            }
Example #15
0
        bool Validate_indexSubTable_format4(Validator v, indexSubTable4 ist4, indexSubTableArray ista, string sID, OTFontVal fontOwner)
        {
            bool bOk = true;

            Table_EBDT EBDTTable = (Table_EBDT)fontOwner.GetTable("EBDT");

            // header has already been validated


            // validate numGlyphs

            uint nGlyphsInRange = (uint)ista.lastGlyphIndex - ista.firstGlyphIndex + 1;

            if (ist4.numGlyphs > nGlyphsInRange)
            {
                string sDetails = "numGlyphs is invalid: " + sID +
                                  ", numGlyphs = " + ist4.numGlyphs +
                                  ", indexSubTableArray.firstGlyphIndex = " + ista.firstGlyphIndex +
                                  ", indexSubTableArray.lastGlyphIndex = " + ista.lastGlyphIndex;
                v.Error(T.EBLC_indexSubTables, E.EBLC_E_indexSubTables, m_tag, sDetails);
                bOk = false;
            }


            // validate code offset pairs
            uint nEBDTLength = EBDTTable.GetLength();

            for (ushort idGlyph = 0; idGlyph < ist4.numGlyphs; idGlyph++)
            {
                indexSubTable4.codeOffsetPair cop = ist4.GetCodeOffsetPair(idGlyph);

                // glyph code
                if (cop.glyphCode < ista.firstGlyphIndex || cop.glyphCode > ista.lastGlyphIndex)
                {
                    string sDetails = "glyph code is invalid: " + sID +
                                      ", codeOffsetPair[" + idGlyph + "]" +
                                      ", indexSubTableArray.firstGlyphIndex = " + ista.firstGlyphIndex +
                                      ", indexSubTableArray.lastGlyphIndex = " + ista.lastGlyphIndex;
                    v.Error(T.EBLC_indexSubTables, E.EBLC_E_indexSubTables, m_tag, sDetails);
                    bOk = false;
                }

                // offset
                if (cop.offset > nEBDTLength)
                {
                    string sDetails = "invalid offset: " + sID +
                                      ", codeOffsetPair[" + idGlyph + "].offset = " + cop.offset +
                                      ", EBDT length = " + nEBDTLength;
                    v.Error(T.EBLC_indexSubTables, E.EBLC_E_indexSubTables, m_tag, sDetails);
                    bOk = false;
                }
            }

            return(bOk);
        }
        protected bool CheckTagNames(Validator v)
        {
            Debug.Assert(m_OffsetTable != null);

            bool bRet = false;

            if (m_OffsetTable != null)
            {
                bRet = true;

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

                    if (!de.tag.IsValid())
                    {
                        v.Error(T.T_NULL, E._DE_E_TagName, null, (string)de.tag);
                        bRet = false;
                    }
                }

                if (bRet == true)
                {
                    v.Pass(P._DE_P_TagName, null);
                }
            }

            return(bRet);
        }
Example #17
0
        bool Validate_indexSubTable_format2(Validator v, indexSubTable2 ist2, indexSubTableArray ista, string sID, OTFontVal fontOwner)
        {
            bool bOk = true;

            Table_EBDT EBDTTable = (Table_EBDT)fontOwner.GetTable("EBDT");

            // header has already been validated


            // validate the image size

            uint nGlyphsInRange = (uint)ista.lastGlyphIndex - ista.firstGlyphIndex + 1;

            if (nGlyphsInRange * ist2.imageSize > EBDTTable.GetLength())
            {
                string sDetails = "images extend past end of EBDT table: " + sID + ", imageSize = " + ist2.imageSize
                                  + ", EBDT length = " + EBDTTable.GetLength();
                v.Error(T.EBLC_indexSubTables, E.EBLC_E_indexSubTables, m_tag, sDetails);
                bOk = false;
            }

            // validate the bigGlyphMetrics
            val_EBDT.bigGlyphMetrics_val bgm = val_EBDT.bigGlyphMetrics_val.CreateFromBigGlyphMetrics(ist2.bigMetrics);
            bgm.Validate(v, sID, this);

            return(bOk);
        }
Example #18
0
        bool Validate_indexSubTable_format3(Validator v, indexSubTable3 ist3, indexSubTableArray ista, string sID, OTFontVal fontOwner)
        {
            bool bOk = true;

            Table_EBDT EBDTTable = (Table_EBDT)fontOwner.GetTable("EBDT");

            // header has already been validated


            // validate the array of offsets

            int  nArrSize    = ista.lastGlyphIndex - ista.firstGlyphIndex + 1;
            uint nEBDTLength = EBDTTable.GetLength();

            for (ushort i = 0; i < nArrSize; i++)
            {
                uint offsetImage = ist3.GetOffset(i) + ist3.header.imageDataOffset;
                if (offsetImage > nEBDTLength)
                {
                    string sDetails = "invalid offset: " + sID + ", offset[" + i + "] = " + offsetImage +
                                      ", EBDT length = " + nEBDTLength;
                    v.Error(T.EBLC_indexSubTables, E.EBLC_E_indexSubTables, m_tag, sDetails);
                    bOk = false;
                }
            }

            return(bOk);
        }
Example #19
0
        public bool ValidateNumEntries(Validator validator,
                                       OTFont fontOwner)
        {
            int numGlyph = this.NumGlyph(fontOwner);
            int numEntry = this.NumEntry(fontOwner);

            if ((numGlyph == Table_loca.ValueInvalid) ||
                (numEntry == Table_loca.ValueInvalid) ||
                (numEntry != numGlyph + 1))
            {
                if (validator != null)
                {
                    validator.Error(T.T_NULL,
                                    E.loca_E_NumEntries,
                                    m_tag,
                                    "number of entries=" + numEntry + " number of glyphs=" + numGlyph);
                }
                return(false);
            }
            else
            {
                if (validator != null)
                {
                    validator.Pass(P.loca_P_NumEntries, m_tag);
                }
                return(true);
            }
        }
Example #20
0
 public bool ValidateNumEntries(Validator validator,
     OTFont fontOwner)
 {
     int numGlyph=this.NumGlyph(fontOwner);
     int numEntry=this.NumEntry(fontOwner);
     if ((numGlyph==Table_loca.ValueInvalid)||
         (numEntry==Table_loca.ValueInvalid)||
         (numEntry!=numGlyph+1))
     {
         if (validator!=null)
         {
             validator.Error(T.T_NULL,
                 E.loca_E_NumEntries, 
                 m_tag, 
                 "number of entries="+numEntry+" number of glyphs="+numGlyph);
         }
         return false;    
     }
     else
     {
         if (validator!=null)
         {
             validator.Pass(P.loca_P_NumEntries, m_tag);
         }
         return true;
     }
 }
        protected bool CheckNoDuplicateTags(Validator v)
        {
            Debug.Assert(m_OffsetTable != null);

            bool bRet = false;

            if (m_OffsetTable != null)
            {
                bRet = true;

                for (int i = 0; i < m_OffsetTable.DirectoryEntries.Count; i++)
                {
                    DirectoryEntry de1 = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i];

                    // compare this directory entry with every one that follows it
                    for (int j = i + 1; j < m_OffsetTable.DirectoryEntries.Count; j++)
                    {
                        DirectoryEntry de2 = (DirectoryEntry)m_OffsetTable.DirectoryEntries[j];

                        if (de1.tag == de2.tag)
                        {
                            v.Error(T.T_NULL, E._DE_E_DuplicateTag, null, de1.tag);
                        }
                    }
                }
            }

            return(bRet);
        }
Example #22
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                bRet &= ((val_BASE)table).ValidateNoOverlap(m_offsetBaseTagListTable, CalcLength(), v, sIdentity, table.GetTag());

                bool bTagsValid = true;

                for (uint i = 0; i < BaseTagCount; i++)
                {
                    OTTag BaselineTag = GetBaselineTag(i);
                    if (!BaselineTag.IsValid())
                    {
                        v.Error(T.T_NULL, E.BASE_E_BaseTagList_TagValid, table.m_tag, sIdentity + ", tag = 0x" + ((uint)BaselineTag).ToString("x8"));
                        bTagsValid = false;
                        bRet       = false;
                    }
                }
                if (bTagsValid)
                {
                    v.Pass(T.T_NULL, P.BASE_P_BaseTagList_TagValid, table.m_tag, sIdentity);
                }

                bool bOrderOk = true;

                if (BaseTagCount > 1)
                {
                    for (uint i = 0; i < BaseTagCount - 1; i++)
                    {
                        OTTag ThisTag = GetBaselineTag(i);
                        OTTag NextTag = GetBaselineTag(i + 1);
                        if (ThisTag >= NextTag)
                        {
                            v.Error(T.T_NULL, E.BASE_E_BaseTagList_TagOrder, table.m_tag, sIdentity);
                            bOrderOk = false;
                            bRet     = false;
                            break;
                        }
                    }
                }
                if (bOrderOk)
                {
                    v.Pass(T.T_NULL, P.BASE_P_BaseTagList_TagOrder, table.m_tag, sIdentity);
                }

                return(bRet);
            }
Example #23
0
        private bool ValidateOffsetsIncreasing(Validator validator,
                                               OTFont fontOwner)
        {
            int cntErr   = 0;
            int numEntry = this.NumEntry(fontOwner);

            if (numEntry == Table_loca.ValueInvalid)
            {
                if (validator != null)
                {
                    validator.Error(T.T_NULL, E.loca_E_OffsetsIncreasing,
                                    m_tag,
                                    "Unable to determine the number of entries in the 'loca' table");
                }
                return(false);
            }

            int offsGlyfCur, offsGlyfNext;

            for (int iEntry = 0; iEntry < numEntry - 1; iEntry++)
            {
                if ((!this.GetGlyfOffset(iEntry, out offsGlyfCur, validator, fontOwner)) ||
                    (!this.GetGlyfOffset(iEntry + 1, out offsGlyfNext, validator, fontOwner)))
                {
                    cntErr++;
                    continue;
                }
                if (offsGlyfNext < offsGlyfCur)
                {
                    cntErr++;
                }
            }
            if (validator != null)
            {
                if (cntErr == 0)
                {
                    validator.Pass(P.loca_P_OffsetsIncreasing, m_tag);
                }
                else
                {
                    validator.Error(T.T_NULL, E.loca_E_OffsetsIncreasing, m_tag,
                                    "Number of glyphs with the error = " + cntErr);
                }
            }
            return(cntErr == 0);
        }
Example #24
0
        /************************
         * public methods
         */


        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            if (v.PerformTest(T.vhea_version))
            {
                if (version.GetUint() == 0x00010000 || version.GetUint() == 0x00011000)
                {
                    v.Pass(T.vhea_version, P.vhea_P_version, m_tag, "0x" + version.GetUint().ToString("x8"));
                }
                else
                {
                    v.Error(T.vhea_version, E.vhea_E_version, m_tag, "0x" + version.GetUint().ToString("x8"));
                    bRet = false;
                }
            }

            if (v.PerformTest(T.vhea_ReservedFields))
            {
                if (reserved1 == 0 && reserved2 == 0 && reserved3 == 0 && reserved4 == 0)
                {
                    v.Pass(T.vhea_ReservedFields, P.vhea_P_ReservedFields, m_tag);
                }
                else
                {
                    v.Error(T.vhea_ReservedFields, E.vhea_E_ReservedFields, m_tag);
                    bRet = false;
                }
            }

            if (v.PerformTest(T.vhea_metricDataFormat))
            {
                if (metricDataFormat == 0)
                {
                    v.Pass(T.vhea_metricDataFormat, P.vhea_P_metricDataFormat, m_tag);
                }
                else
                {
                    v.Error(T.vhea_metricDataFormat, E.vhea_E_metricDataFormat, m_tag, metricDataFormat.ToString());
                    bRet = false;
                }
            }

            return bRet;
        }
Example #25
0
        /************************
         * public methods
         */


        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            if (v.PerformTest(T.vhea_version))
            {
                if (version.GetUint() == 0x00010000 || version.GetUint() == 0x00011000)
                {
                    v.Pass(T.vhea_version, P.vhea_P_version, m_tag, "0x" + version.GetUint().ToString("x8"));
                }
                else
                {
                    v.Error(T.vhea_version, E.vhea_E_version, m_tag, "0x" + version.GetUint().ToString("x8"));
                    bRet = false;
                }
            }

            if (v.PerformTest(T.vhea_ReservedFields))
            {
                if (reserved1 == 0 && reserved2 == 0 && reserved3 == 0 && reserved4 == 0)
                {
                    v.Pass(T.vhea_ReservedFields, P.vhea_P_ReservedFields, m_tag);
                }
                else
                {
                    v.Error(T.vhea_ReservedFields, E.vhea_E_ReservedFields, m_tag);
                    bRet = false;
                }
            }

            if (v.PerformTest(T.vhea_metricDataFormat))
            {
                if (metricDataFormat == 0)
                {
                    v.Pass(T.vhea_metricDataFormat, P.vhea_P_metricDataFormat, m_tag);
                }
                else
                {
                    v.Error(T.vhea_metricDataFormat, E.vhea_E_metricDataFormat, m_tag, metricDataFormat.ToString());
                    bRet = false;
                }
            }

            return(bRet);
        }
        protected bool CheckTablesInFileAndNotOverlapping(Validator v)
        {
            Debug.Assert(m_OffsetTable != null);

            bool bRet = false;

            if (m_OffsetTable != null)
            {
                bRet = true;

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

                    // make sure the offset plus length is within the file
                    if (de.offset + de.length > GetFile().GetFileLength())
                    {
                        v.Error(T.T_NULL, E._DE_E_TableEndPastEOF, de.tag, de.tag);
                        bRet = false;
                    }

                    // make sure the table doesn't overlap any other tables
                    for (int j = 0; j < m_OffsetTable.DirectoryEntries.Count; j++)
                    {
                        if (i != j)    // don't compare the table to itself!
                        {
                            DirectoryEntry de2 = (DirectoryEntry)m_OffsetTable.DirectoryEntries[j];
                            if (
                                // make sure the table doesn't start inside a second table
                                (de.offset > de2.offset && de.offset < de2.offset + de2.length) ||
                                // make sure the table doesn't end inside a second table
                                (de.offset + de.length > de2.offset && de.offset + de.length < de2.offset + de2.length)
                                )
                            {
                                string sDetails = de.tag + " overlaps " + de2.tag;
                                v.Error(T.T_NULL, E._DE_E_OverlappingTable, de.tag, sDetails);
                            }
                        }
                    }
                }
            }

            return(bRet);
        }
Example #27
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                bRet &= ((val_BASE)table).ValidateNoOverlap(m_offsetAxisTable, CalcLength(), v, sIdentity, table.GetTag());


                if (BaseTagListOffset == 0)
                {
                    v.Pass(T.T_NULL, P.BASE_P_AxisTable_BaseTagListOffset_null, table.m_tag, sIdentity);
                }
                else if (BaseTagListOffset + m_offsetAxisTable > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.BASE_E_AxisTable_BaseTagListOffset, table.m_tag, sIdentity);
                    bRet = false;
                }
                else
                {
                    v.Pass(T.T_NULL, P.BASE_P_AxisTable_BaseTagListOffset_valid, table.m_tag, sIdentity);
                    BaseTagListTable_val btlt = GetBaseTagListTable_val();
                    btlt.Validate(v, sIdentity, table);
                }


                if (BaseScriptListOffset == 0)
                {
                    v.Error(T.T_NULL, E.BASE_E_AxisTable_BaseScriptListOffset_null, table.m_tag, sIdentity);
                    bRet = false;
                }
                else if (BaseScriptListOffset + m_offsetAxisTable > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.BASE_E_AxisTable_BaseScriptListOffset, table.m_tag, sIdentity);
                    bRet = false;
                }
                else
                {
                    v.Pass(T.T_NULL, P.BASE_P_AxisTable_BaseScriptListOffset_valid, table.m_tag, sIdentity);
                    BaseScriptListTable_val bslt = GetBaseScriptListTable_val();
                    bslt.Validate(v, sIdentity, table);
                }

                return(bRet);
            }
Example #28
0
        public bool ValidateNoOverlap(uint offset, uint length, Validator v, string sIdentity, OTTag tag)
        {
            bool bValid = m_DataOverlapDetector.CheckForNoOverlap(offset, length);

            if (!bValid)
            {
                v.Error(T.T_NULL, E._Table_E_DataOverlap, tag, sIdentity + ", offset = " + offset + ", length = " + length);
            }

            return(bValid);
        }
Example #29
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                bRet &= ((val_GDEF)table).ValidateNoOverlap(m_offsetLigGlyphTable, CalcLength(), v, sIdentity, table.GetTag());

                if (m_offsetLigGlyphTable + (uint)FieldOffsets.CaretValueOffsets + CaretCount * 2 > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.GDEF_E_LigGlyphTable_CaretValueArray_PastEOT, table.m_tag, sIdentity);
                    bRet = false;
                }

                bool bOffsetsOk = true;

                for (uint i = 0; i < CaretCount; i++)
                {
                    if (m_offsetLigGlyphTable + GetCaretValueOffset(i) > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.GDEF_E_LigGlyphTable_CaretValueOffset, table.m_tag, sIdentity);
                        bOffsetsOk = false;
                        bRet       = false;
                    }
                }
                if (bOffsetsOk)
                {
                    v.Pass(T.T_NULL, P.GDEF_P_LigGlyphTable_CaretValueArray, table.m_tag, sIdentity);
                }

                for (uint i = 0; i < CaretCount; i++)
                {
                    CaretValueTable cvt = GetCaretValueTable(i);
                    if (cvt.CaretValueFormat < 1 || cvt.CaretValueFormat > 3)
                    {
                        v.Error(T.T_NULL, E.GDEF_E_CaretValueTable_Format, table.m_tag, sIdentity + ", CaretValue[" + i + "], format = " + cvt.CaretValueFormat);
                        bRet = false;
                    }
                }

                return(bRet);
            }
Example #30
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                bRet &= ((val_BASE)table).ValidateNoOverlap(m_offsetBaseValuesTable, CalcLength(), v, sIdentity, table.GetTag());

                // check BaseCoord offsets
                bool bOffsetsOk = true;

                for (uint i = 0; i < BaseCoordCount; i++)
                {
                    ushort bco = GetBaseCoordOffset(i);
                    if (bco == 0)
                    {
                        v.Error(T.T_NULL, E.BASE_E_BaseValuesTable_BCO_0, table.m_tag, sIdentity + ", BaseCoordOffset index = " + i);
                        bOffsetsOk = false;
                        bRet       = false;
                    }
                    else if (bco + m_offsetBaseValuesTable > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.BASE_E_BaseValuesTable_BCO_invalid, table.m_tag, sIdentity + ", BaseCoordOffset index = " + i);
                        bOffsetsOk = false;
                        bRet       = false;
                    }
                }
                if (bOffsetsOk)
                {
                    v.Pass(T.T_NULL, P.BASE_P_BaseValuesTable_BCO, table.m_tag, sIdentity);
                }

                // check the BaseCoord tables
                for (uint i = 0; i < BaseCoordCount; i++)
                {
                    BaseCoordTable_val bct = GetBaseCoordTable_val(i);
                    bct.Validate(v, sIdentity, table);
                }

                return(bRet);
            }
Example #31
0
            public bool Validate(Validator v, string sIdentity, OTTable table)
            {
                bool bRet = true;

                bRet &= ((val_BASE)table).ValidateNoOverlap(m_offsetBaseCoordTable, CalcLength(), v, sIdentity, table.GetTag());

                if (BaseCoordFormat == 1 || BaseCoordFormat == 2 || BaseCoordFormat == 3)
                {
                    v.Pass(T.T_NULL, P.BASE_P_BaseCoordTable_format, table.m_tag, sIdentity);
                }
                else
                {
                    v.Error(T.T_NULL, E.BASE_E_BaseCoordTable_format, table.m_tag, sIdentity + ", format = " + BaseCoordFormat);
                }

                return(bRet);
            }
Example #32
0
        /************************
         * public methods
         */


        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            if (v.PerformTest(T.cvt_length))
            {
                if ((m_bufTable.GetLength() & 1) != 0)
                {
                    v.Error(T.cvt_length, E.cvt_E_length_odd, m_tag);
                    bRet = false;
                }
                else
                {
                    v.Pass(T.cvt_length, P.cvt_P_length_even, m_tag);
                }
            }
            
            return bRet;
        }
Example #33
0
        /************************
         * public methods
         */


        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            if (v.PerformTest(T.cvt_length))
            {
                if ((m_bufTable.GetLength() & 1) != 0)
                {
                    v.Error(T.cvt_length, E.cvt_E_length_odd, m_tag);
                    bRet = false;
                }
                else
                {
                    v.Pass(T.cvt_length, P.cvt_P_length_even, m_tag);
                }
            }

            return(bRet);
        }
Example #34
0
        /*
         *        METHODS PRIVATE: GLYF ACCESS
         */

        private bool GetGlyfOffset(int indexGlyph, out int offsGlyf,
                                   Validator validator, OTFont fontOwner)
        {
            offsGlyf = Table_loca.ValueInvalid;
            int numEntry = this.NumEntry(fontOwner);

            if (numEntry == Table_loca.ValueInvalid)
            {
                return(false);
            }
            if ((indexGlyph < 0) || (indexGlyph >= numEntry))
            {
                //Debug.Assert(false, "Table_loca: GetGlyfOffset");
                return(false);
            }

            int sizeEntry = this.SizeEntry(fontOwner);

            if (sizeEntry == Table_loca.ValueInvalid)
            {
                return(false);
            }
            int pozLoca = sizeEntry * indexGlyph;

            if (pozLoca + sizeEntry > this.GetLength())
            {
                if (validator != null)
                {
                    validator.Error(E._GEN_E_OffsetExceedsTableLength, "loca");
                }
                return(false);
            }
            if (sizeEntry == 2)
            {
                offsGlyf = 2 * m_bufTable.GetUshort((uint)pozLoca);
            }
            else
            {
                offsGlyf = (int)(m_bufTable.GetUint((uint)pozLoca));
            }
            return(true);
        }
Example #35
0
        /*
         *        VALIDATION FUNCTIONS
         */

        
        public bool ValidateFormat(Validator validator, 
            OTFont fontOwner)
        {
            int format=this.Format(fontOwner);
            if ((format!=0)&&(format!=1))
            {
                if (validator!=null)
                {
                    validator.Error(E.loca_E_Format, m_tag);
                }
                return false;
            }
            else
            {
                if (validator!=null)
                {
                    validator.Pass(P.loca_P_Format, m_tag);
                }
                return true;
            }
        }
        protected bool CheckTagsAscending(Validator v)
        {
            Debug.Assert(m_OffsetTable != null);

            bool bRet = false;

            if (m_OffsetTable != null)
            {
                bRet = true;

                for (int i = 0; i < m_OffsetTable.DirectoryEntries.Count; i++)
                {
                    DirectoryEntry de1 = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i];

                    // compare this directory entry with every one that follows it
                    for (int j = i + 1; j < m_OffsetTable.DirectoryEntries.Count; j++)
                    {
                        DirectoryEntry de2 = (DirectoryEntry)m_OffsetTable.DirectoryEntries[j];

                        if ((uint)de1.tag > (uint)de2.tag)
                        {
                            v.Error(E._DE_E_TagsAscending, null);
                            bRet = false;
                            break;
                        }
                    }
                    if (bRet == false)
                    {
                        break;
                    }
                }

                if (bRet == true)
                {
                    v.Pass(P._DE_P_TagsAscending, null);
                }
            }

            return(bRet);
        }
Example #37
0
        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            if (v.PerformTest(T.cmap_Version))
            {
                if (TableVersionNumber == 0)
                {
                    v.Pass(T.cmap_Version, P.cmap_P_version, m_tag);
                }
                else
                {
                    v.Error(T.cmap_Version, E.cmap_E_version, m_tag,
                            TableVersionNumber.ToString());
                    bRet = false;
                }
            }

            // Check that the number of encoding records seems to 
            // agree with the numTables field, and that each offset
            // is greater than 0 and less than the length of the cmap 
            // table.

            bool bOffsetsOk = true;
            if (v.PerformTest(T.cmap_SubtableOffset))
            {
                
                for (uint i=0; i<NumberOfEncodingTables; i++)
                {
                    EncodingTableEntry ete = GetEncodingTableEntry(i);
                    if (ete != null)
                    {
                        if (ete.offset == 0)
                        {
                            v.Error(T.cmap_SubtableOffset, 
                                    E.cmap_E_SubtableOffset_zero, m_tag, 
                                    "encoding table entry index = " + 
                                    i.ToString() + ", platformID = " + 
                                    ete.platformID + ", encodingID = " +
                                    ete.encodingID);
                            bRet = false;
                            bOffsetsOk = false;
                        }

                        if (ete.offset > m_bufTable.GetLength())
                        {
                            v.Error(T.cmap_SubtableOffset,
                                    E.cmap_E_SubtableOffset_eot, m_tag, 
                                    "encoding table entry index = " +
                                    i.ToString() + ", platformID = " +
                                    ete.platformID +
                                    ", encodingID = " + ete.encodingID);
                            bRet = false;
                            bOffsetsOk = false;
                        }
                    }
                    else
                    {
                        v.Warning(T.cmap_SubtableOffset, 
                                  W._TEST_W_OtherErrorsInTable, m_tag, 
                                  "cmap table appears to be corrupt. " + 
                                  " No further tests will be performed.");
                        return bRet; 
                    }
                }
                
                if (bOffsetsOk)
                {
                    v.Pass(T.cmap_SubtableOffset, P.cmap_P_SubtableOffset,
                           m_tag);
                }
            }

            // Check that each subtable can be retrieved from the font
            // and that its offset + length lies within the cmap.

            bool bLengthsOk = true;
            if (v.PerformTest(T.cmap_SubtableLength))
            {
                
                for (uint i=0; i<NumberOfEncodingTables; i++)
                {
                    EncodingTableEntry ete = GetEncodingTableEntry(i);
                    Subtable st = GetSubtable(ete);

                    if (st != null)
                    {
                        if (st.length == 0)
                        {
                            v.Error(T.cmap_SubtableLength,
                                    E.cmap_E_SubtableLength_zero, m_tag, 
                                    i.ToString());
                            bRet = false;
                            bLengthsOk = false;
                        }

                        if (ete.offset + st.length > m_bufTable.GetLength())
                        {
                            v.Error(T.cmap_SubtableLength,
                                    E.cmap_E_SubtableLength_eot, m_tag, 
                                    i.ToString());
                            bRet = false;
                            bLengthsOk = false;
                        }
                    }
                    else
                    {
                        string sDetails = "PlatID = " + ete.platformID +
                            ", EncID = " + ete.encodingID;
                        v.Warning(T.cmap_SubtableLength, 
                                  W._TEST_W_OtherErrorsInTable, m_tag,
                                  "unable to validate the length of subtable - "
                                  + sDetails);
                        bLengthsOk = false;
                    }
                }
                
                if (bLengthsOk)
                {
                    v.Pass(T.cmap_SubtableLength, P.cmap_P_SubtableLength,
                           m_tag);
                }
            }

            // Assuming previous tests ok, check that sort order is by
            // 1. increasing platformID
            // 2. increasing encodingID
            // 3. increasing language

            if (v.PerformTest(T.cmap_SubtableSortOrder))
            {
                if (bOffsetsOk && bLengthsOk)
                {
                    bool bOrderOk = true;

                    if (NumberOfEncodingTables > 1)
                    {
                        EncodingTableEntry etePrev = GetEncodingTableEntry(0);

                        for (uint i=1; i<NumberOfEncodingTables; i++)
                        {
                            EncodingTableEntry ete = GetEncodingTableEntry(i);

                            if (etePrev.platformID == ete.platformID)
                            {
                                if (etePrev.encodingID == ete.encodingID)
                                {
                                    Subtable stPrev = GetSubtable(etePrev);
                                    Subtable st = GetSubtable(ete);

                                    if (stPrev.language > st.language)
                                    {
                                        bOrderOk = false;
                                    }
                                }
                                else if (etePrev.encodingID > ete.encodingID)
                                {
                                    bOrderOk = false;
                                }
                            }
                            else if (etePrev.platformID > ete.platformID)
                            {
                                bOrderOk = false;
                            }

                            etePrev = ete;
                        }
                    }

                    if (bOrderOk)
                    {
                        v.Pass(T.cmap_SubtableSortOrder,
                               P.cmap_P_SubtableSortOrder, m_tag);
                    }
                    else
                    {
                        v.Error(T.cmap_SubtableSortOrder,
                                E.cmap_E_SubtableSortOrder, m_tag);
                        bRet = false;
                    }
                }
                else
                {
                    v.Warning(T.cmap_SubtableSortOrder,
                              W._TEST_W_OtherErrorsInTable, m_tag,
                              "unable to validate sort order");
                }
            }

            // Check that no encoding record has the same 
            //      (platformID,encodingID,language)
            // as the previous one.

            if (v.PerformTest(T.cmap_DuplicateSubtables))
            {
                if (bOffsetsOk && bLengthsOk)
                {
                    bool bNoDuplicates = true;

                    if (NumberOfEncodingTables > 1)
                    {
                        EncodingTableEntry etePrev = GetEncodingTableEntry(0);

                        for (uint i=1; i<NumberOfEncodingTables; i++)
                        {
                            EncodingTableEntry ete = GetEncodingTableEntry(i);

                            if (etePrev.platformID == ete.platformID)
                            {
                                if (etePrev.encodingID == ete.encodingID)
                                {
                                    Subtable stPrev = GetSubtable(etePrev);
                                    Subtable st = GetSubtable(ete);

                                    if (stPrev.language == st.language)
                                    {
                                        bNoDuplicates = false;
                                    }
                                }
                            }

                            etePrev = ete;
                        }
                    }

                    if (bNoDuplicates)
                    {
                        v.Pass(T.cmap_DuplicateSubtables,
                               P.cmap_P_DuplicateSubtables, m_tag);
                    }
                    else
                    {
                        v.Error(T.cmap_DuplicateSubtables,
                                E.cmap_E_DuplicateSubtables, m_tag);
                        bRet = false;
                    }
                }
                else
                {
                    string unable = "unable to validate that there are " + 
                        "no duplicate subtables";
                    v.Warning(T.cmap_DuplicateSubtables,
                              W._TEST_W_OtherErrorsInTable, m_tag,
                              unable );
                }
            }

            // Check that no subtable overlaps and subtable following it,
            // in other words, check for the beginning of one subtable 
            // falling within the bounds of a subtable that follows it.

            if (v.PerformTest(T.cmap_SubtableOverlap))
            {
                if (bOffsetsOk && bLengthsOk)
                {
                    bool bNoOverlap = true;

                    if (NumberOfEncodingTables > 1)
                    {
                        for (uint i=0; i<NumberOfEncodingTables; i++)
                        {
                            EncodingTableEntry ete1 = GetEncodingTableEntry(i);
                            Subtable st1 = GetSubtable(ete1);

                            for (uint j=i+1; j<NumberOfEncodingTables; j++)
                            {
                                EncodingTableEntry ete2 = 
                                    GetEncodingTableEntry(j);
                                Subtable st2 = GetSubtable(ete2);

                                if ( (ete1.offset > ete2.offset && 
                                      ete1.offset < ete2.offset + st2.length) ||
                                    (ete2.offset > ete1.offset &&
                                     ete2.offset < ete1.offset + st1.length) )
                                {
                                    v.Error(T.cmap_SubtableOverlap, 
                                            E.cmap_E_SubtableOverlap, m_tag,
                                            i.ToString() + " " + j.ToString());
                                    bRet = false;
                                    bNoOverlap = true;
                                }
                            }
                        }
                    }

                    if (bNoOverlap)
                    {
                        v.Pass(T.cmap_SubtableOverlap, 
                               P.cmap_P_SubtableOverlap, m_tag);
                    }
                }
                else
                {
                    v.Warning(T.cmap_SubtableOverlap, 
                              W._TEST_W_OtherErrorsInTable, m_tag,
                              "unable to validate that no subtables overlap");
                }
            }

            // Check that all subtable formats (First USHORT in the subtable)
            // is an even number between 0 and 14, inclusive.

            if (v.PerformTest(T.cmap_ValidFormat))
            {
                bool bAllFormatsValid = true;
                for (uint i=0; i<NumberOfEncodingTables; i++)
                {
                    EncodingTableEntry ete = GetEncodingTableEntry(i);
                    if (ete.offset < m_bufTable.GetLength()-1)
                    {
                        // the format of the subtable is the first uint16
                        ushort format = m_bufTable.GetUshort(ete.offset);

                        if (format > HIGHEST_FORMAT || ((format&1)==1))
                        {
                            string sDetails = "PlatID = " + ete.platformID +
                                ", EncID = " + ete.encodingID + ", Fmt = " + 
                                format;
                            v.Error(T.cmap_ValidFormat, 
                                    E.cmap_E_SubtableValidFormat, m_tag, 
                                    sDetails);
                            bRet = false;
                            bAllFormatsValid = false;
                        }
                    }
                    else
                    {
                        string sDetails = "PlatID = " + ete.platformID + 
                            ", EncID = " + ete.encodingID;
                        string unable = 
                            "unable to validate format number for subtable - ";
                        v.Warning(T.cmap_ValidFormat, 
                                  W._TEST_W_OtherErrorsInTable, m_tag, 
                                  unable + sDetails);
                        bAllFormatsValid = false;
                    }
                }

                if (bAllFormatsValid)
                {
                    v.Pass(T.cmap_ValidFormat, 
                           P.cmap_P_SubtableValidFormat, m_tag);
                }
            }

            // Assuming maxp is present, get the number of glyphs from maxp, 
            // and for each subtable, run its validate routine.

            if (v.PerformTest(T.cmap_SubtableInternalFormat))
            {
                if (fontOwner.GetTable("maxp") == null)
                {
                    string cant = 
                        "can't check subtable internal formats - " + 
                        "maxp table inaccessible";
                    v.Warning(T.cmap_SubtableInternalFormat, 
                              W._TEST_W_ErrorInAnotherTable, m_tag,
                              cant );
                }
                else
                {
                    for (uint i=0; i<NumberOfEncodingTables; i++)
                    {
                        bool bInternalFormatOk = true;
                        EncodingTableEntry ete = GetEncodingTableEntry(i);
                        Subtable st = GetSubtable(ete);
                        if (st != null)
                        {
                            ushort numGlyphs = fontOwner.GetMaxpNumGlyphs();
                            string sIdentity = "PlatID = " + ete.platformID +
                                ", EncID = " + ete.encodingID + ", Fmt = " + 
                                st.format;
                            
                            ISubtableValidate valSubtable =
                                (ISubtableValidate)st;
                            bInternalFormatOk = valSubtable.Validate(v, this,
                                                                     numGlyphs,
                                                                     sIdentity);
                            bRet &= bInternalFormatOk;
                            if (bInternalFormatOk)
                            {
                                v.Pass(T.cmap_SubtableInternalFormat,
                                       P.cmap_P_InternalFormat, m_tag, 
                                       sIdentity);
                            }
                        }
                        else
                        {
                            string sDetails = "PlatID = " + ete.platformID +
                                ", EncID = " + ete.encodingID;
                            v.Warning(T.cmap_SubtableInternalFormat,
                                      W._TEST_W_OtherErrorsInTable, m_tag, 
                                      "unable to validate internal format " +
                                      "for subtable - "
                                      + sDetails);
                        }
                    }
                }
            }

            // Pass if there is at least one subtable with platformID == 1 and
            // one subtable with platformID == 3.
            // Warn if either is missing.

            if (v.PerformTest(T.cmap_AppleMSSupport))
            {
                bool bFoundApple = false;
                bool bFoundMS    = false;

                for (uint i=0; i<NumberOfEncodingTables; i++)
                {
                    EncodingTableEntry ete = GetEncodingTableEntry(i);
                    if (ete.platformID == 1)
                    {
                        bFoundApple = true;
                    }
                    else if (ete.platformID == 3)
                    {
                        bFoundMS = true;
                    }
                }

                if (bFoundApple && bFoundMS)
                {
                    v.Pass(T.cmap_AppleMSSupport, P.cmap_P_AppleMSSupport,
                           m_tag);
                }
                else if (!bFoundApple)
                {
                    v.Warning(T.cmap_AppleMSSupport, W.cmap_W_AppleMSSupport_A,
                              m_tag);
                }
                else if (!bFoundMS)
                {
                    v.Warning(T.cmap_AppleMSSupport, W.cmap_W_AppleMSSupport_M,
                              m_tag);
                }
            }

            // Find encoding table with platformID==1, encodingID==0 
            // i.e., Macintosh. Make sure that the Apple Logo, code point 240,
            // is mapped to glyphID 0, a legal requirement for Microsoft fonts
            // developed for use on Apple platforms.

            if (v.PerformTest(T.cmap_AppleLogo))
            {
                EncodingTableEntry ete = GetEncodingTableEntry(1,0);
                if (ete != null)
                {
                    Subtable st = GetSubtable(ete);
                    if (st != null)
                    {
                        byte[] charbuf = new byte[2];
                        charbuf[0] = 240;
                        charbuf[1] = 0;
                        uint glyph = st.MapCharToGlyph(charbuf, 0);
                        if (glyph == 0)
                        {
                            v.Pass(T.cmap_AppleLogo, P.cmap_P_AppleLogo, m_tag);
                        }
                        else
                        {
                            v.Warning(T.cmap_AppleLogo, W.cmap_W_AppleLogo,
                                      m_tag);
                        }
                    }
                    else
                    {
                        string sDetails = "PlatID = " + ete.platformID +
                            ", EncID = " + ete.encodingID;
                        string unable = 
                            "unable to validate apple logo for subtable - ";
                        v.Warning(T.cmap_AppleLogo, 
                                  W._TEST_W_OtherErrorsInTable, m_tag,
                                  unable + sDetails);
                    }
                }
                else
                {
                    v.Warning(T.cmap_AppleLogo, W.cmap_W_AppleLogo_NoMap, 
                              m_tag);
                }
            }

            // Euro symbol.
            // Unless there is a Microsoft Symbol encoding cmap (3,0):
            // * Make sure that any apple cmap(1,0) contains a glyph U+00db
            // * Make sure that any Microsoft Unicode cmap (3,1) contains
            //   a glyph U+20AC.

            if (v.PerformTest(T.cmap_EuroGlyph))
            {
                EncodingTableEntry eteSym = GetEncodingTableEntry(3,0);
                if (eteSym == null)
                {
                    EncodingTableEntry eteMac = GetEncodingTableEntry(1,0);
                    if (eteMac != null)
                    {
                        Subtable st = GetSubtable(eteMac);
                        if (st != null)
                        {
                            byte[] charbuf = new byte[2];
                            charbuf[0] = 0xdb;
                            charbuf[1] = 0;
                            uint glyph = st.MapCharToGlyph(charbuf, 0);
                            if (glyph != 0)
                            {
                                v.Pass(T.cmap_EuroGlyph,
                                       P.cmap_P_EuroGlyph_Mac, m_tag);
                            }
                            else
                            {
                                v.Warning(T.cmap_EuroGlyph,
                                          W.cmap_W_EuroGlyph_Mac, m_tag);
                            }
                        }
                        else
                        {
                            string sDetails = "PlatID = " + eteMac.platformID +
                                ", EncID = " + eteMac.encodingID;
                            string unable = 
                                "unable to validate if euro glyph " + 
                                "is present for subtable - ";
                            v.Warning(T.cmap_EuroGlyph,
                                      W._TEST_W_OtherErrorsInTable, m_tag,
                                      unable + sDetails);
                        }
                    }

                    EncodingTableEntry eteUni = GetEncodingTableEntry(3,1);
                    if (eteUni != null)
                    {
                        Subtable st = GetSubtable(eteUni);
                        if (st != null)
                        {
                            byte[] charbuf = new byte[2];
                            charbuf[0] = 0xac;
                            charbuf[1] = 0x20;
                            uint glyph = st.MapCharToGlyph(charbuf, 0);
                            if (glyph != 0)
                            {
                                v.Pass(T.cmap_EuroGlyph,
                                       P.cmap_P_EuroGlyph_Uni, m_tag);
                            }
                            else
                            {
                                v.Warning(T.cmap_EuroGlyph,
                                          W.cmap_W_EuroGlyph_Uni, m_tag);
                            }
                        }
                        else
                        {
                            string sDetails = "PlatID = " + eteMac.platformID +
                                ", EncID = " + eteMac.encodingID;
                            string unable = "unable to validate if euro glyph" +
                                " is present for subtable - ";
                            v.Warning(T.cmap_EuroGlyph,
                                      W._TEST_W_OtherErrorsInTable, m_tag, 
                                      unable + sDetails);
                        }
                    }
                }
            }

            // Make sure that no glyphs, other than "fi" and "fl" ligatures,
            // are mapped from the "private use area", that is, 
            // 0xE000 - 0xF8FF. The above ligatures may only be a the 
            // prescribed places. 
            //
            // Checks that 0xf001 and 0xfb01 map to the same place, and
            // Checks that 0xf002 and 0xfb02 map to the same place.
            //
            // Only warn if a problem.

            if (v.PerformTest(T.cmap_PrivateUse))
            {
                EncodingTableEntry eteUni = GetEncodingTableEntry(3,1);
                if (eteUni != null)
                {
                    Subtable st = GetSubtable(eteUni);
                    if (st != null)
                    {
                        bool bFoundGlyph = false;
                        bool bFoundLigChar = false;
                        byte[] charbuf = new byte[2];

                        for (char c='\xe000'; c<'\xf8ff'; c++)
                        {
                            uint glyph = fontOwner.FastMapUnicodeToGlyphID(c);
                            if (glyph != 0)
                            {
                                if (c == '\xf001')
                                {
                                    // check to see if this is the 'fi' ligature
                                    uint glyph2 = fontOwner.
                                        FastMapUnicodeToGlyphID('\xfb01');
                                    if (glyph == glyph2)
                                    {
                                        bFoundLigChar = true;
                                    }
                                    else
                                    {
                                        bFoundGlyph = true;
                                        break;
                                    }
                                }
                                else if (c == '\xf002')
                                {
                                    // check to see if this is the 'fl' ligature
                                    uint glyph2 = fontOwner.
                                        FastMapUnicodeToGlyphID('\xfb02');
                                    if (glyph == glyph2)
                                    {
                                        bFoundLigChar = true;
                                    }
                                    else
                                    {
                                        bFoundGlyph = true;
                                        break;
                                    }
                                }
                                else
                                {
                                    bFoundGlyph = true;
                                    break;
                                }
                            }
                        }
                        if (bFoundGlyph)
                        {
                            v.Warning(T.cmap_PrivateUse, 
                                      W.cmap_W_UnicodePrivateUse, m_tag);
                        }
                        else if (bFoundLigChar)
                        {
                            v.Pass(T.cmap_PrivateUse, 
                                   P.cmap_P_UnicodePrivateUse_lig, m_tag);
                        }
                        else
                        {
                            v.Pass(T.cmap_PrivateUse, 
                                   P.cmap_P_UnicodePrivateUse, m_tag);
                        }
                    }
                    else
                    {
                        string sDetails = "PlatID = " + eteUni.platformID + 
                            ", EncID = " + eteUni.encodingID;
                        v.Warning(T.cmap_PrivateUse,
                                  W._TEST_W_OtherErrorsInTable, m_tag, 
                                  "unable to validate Private Use Area " + 
                                  "for subtable - "
                                  + sDetails);
                    }
                }
            }

            // Check that subtable language field is zero if not mac platform

            if (v.PerformTest(T.cmap_NonMacSubtableLanguage))
            {
                bool bOk = true;
                for (uint i=0; i<NumberOfEncodingTables; i++)
                {
                    EncodingTableEntry ete = GetEncodingTableEntry(i);
                    Subtable st = GetSubtable(ete);
                    if (st != null)
                    {
                        if (ete.platformID != 1) // not mac
                        {
                            if (st.language != 0)
                            {
                                string sDetails = "PlatID = " +
                                    ete.platformID + ", EncID = " +
                                    ete.encodingID +
                                    ", Language = " + st.language;
                                v.Error(T.cmap_SubtableLanguage, 
                                        E.cmap_E_NonMacSubtableLanguage,
                                        m_tag, sDetails);
                                bOk = false;
                            }
                        }
                    }
                }
                if (bOk)
                {
                    v.Pass(T.cmap_SubtableLanguage,
                           P.cmap_P_NonMacSubtableLanguage, m_tag);
                }
            }

            return bRet;
        }
Example #38
0
        private bool CheckCodePageBit(int nBit, uint CodePage, string sName, Validator v, OTFont fontOwner)
        {
            bool bRet = true;

            int nTotalChars = 0;
            int nMissingChars = 0;

            // decode the bit number
            bool bBitSet;
            if (nBit < 32)
            {
                bBitSet = ((ulCodePageRange1 & (1<<nBit)) != 0);
            }
            else
            {
                bBitSet = ((ulCodePageRange2 & (1<<(nBit-32))) != 0);
            }


            if (nBit == 31)
            {
                // symbol character set
                Table_cmap cmapTable = (Table_cmap)fontOwner.GetTable("cmap");
                if (cmapTable != null)
                {
                    if (cmapTable.GetEncodingTableEntry(3,0) != null)
                    {
                        if (!bBitSet)
                        {
                            v.Error(T.T_NULL, E.OS_2_E_SymbolBitClear, m_tag);
                            bRet = false;
                        }
                    }
                    else
                    {
                        if (bBitSet)
                        {
                            int nPresentChars = 0;
                            for (ushort c=0xf000; c<= 0xf0ff; c++)
                            {
                                if (fontOwner.FastMapUnicodeToGlyphID((char)c) != 0)
                                {
                                    nPresentChars++;
                                }
                            }
                    
                            if (nPresentChars == 0)
                            {
                                v.Error(T.T_NULL, E.OS_2_E_SymbolBitSet, m_tag);
                                bRet = false;
                            }
                        }
                    }
                }
                else
                {
                    v.Error(T.T_NULL, E._TEST_E_TableMissing, m_tag, "cmap");
                    bRet = false;
                }
            }
            else if (CodePage == 0)
            {
                // reserved field, bit should not be set
                if (bBitSet)
                {
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_CodePage, m_tag, "bit #" + nBit);
                    bRet = false;
                }
            }
            else
            {
                try
                {
                    if (MultiByte.IsCodePageInstalled(CodePage))
                    {
                        ushort [] arrMissingChars = new ushort[10];

                        uint nMaxCharSize = MultiByte.GetCodePageMaxCharSize(CodePage);
                        if (nMaxCharSize == 1)
                        {
                            for (ushort c = 0; c<256; c++)
                            {
                                // check for special case: MultiByteToWideChar maps char 0xca in CP1255 to U05BA, but CP1255 spec says its not defined
                                if (CodePage != 1255 || c != 0xca)
                                {
                                    CheckCodePageGlyph(CodePage, (char)c, ref nTotalChars, ref nMissingChars, arrMissingChars, fontOwner);
                                }
                            }
                        }
                        else if (nMaxCharSize == 2)
                        {
                            bool [] LeadByteMap = new bool[256];
                            for (int i=0; i<256; i++)
                            {
                                LeadByteMap[i] = MultiByte.IsCodePageLeadByte(CodePage, (byte)i);
                            }

                            for (ushort c = 0; c<256; c++)
                            {
                                if (LeadByteMap[c] == false)
                                {
                                    CheckCodePageGlyph(CodePage, (char)c, ref nTotalChars, ref nMissingChars, arrMissingChars, fontOwner);
                                }
                            }

                            for (uint leadbyte = 0; leadbyte<256; leadbyte++)
                            {
                                if (LeadByteMap[leadbyte] == true)
                                {
                                    for (uint secondbyte = 0; secondbyte<256; secondbyte++)
                                    {
                                        char c = (char)((leadbyte << 8) + secondbyte);
                                        CheckCodePageGlyph(CodePage, c, ref nTotalChars, ref nMissingChars, arrMissingChars, fontOwner);
                                    }
                                }
                            }
                        }
                        else
                        {
                            Debug.Assert(false);
                        }

                        if (bBitSet)
                        {
                            if (nMissingChars != 0)
                            {
                                string sDetails = "bit #" + nBit + ", " + sName;
                                int n = 0;
                                if (nMissingChars <=10)
                                {
                                    sDetails += " (missing chars:";
                                    n = nMissingChars;
                                }
                                else
                                {
                                    sDetails += " (" + nMissingChars + " missing, first ten missing chars are:";
                                    n = 10;
                                }
                                for (int i=0; i<n; i++)
                                {
                                    sDetails += " U" + arrMissingChars[i].ToString("X4");
                                }
                                sDetails += ")";
                                v.Warning(T.T_NULL, W.OS_2_W_CodePageRangeBitSet, m_tag, sDetails);
                            }
                        }
                        else
                        {
                            if (nMissingChars == 0)
                            {
                                v.Warning(T.T_NULL, W.OS_2_W_CodePageRangeBitClear, m_tag, "bit #" + nBit + ", " + sName);
                            }
                        }
                    }
                    else
                    {
                        v.ApplicationError(T.T_NULL, E.OS_2_A_CodePageNotInstalled, m_tag, "CodePage " + CodePage + " is not installed on the system");
                    }
                }
                catch (Exception e)
                {
                    v.ApplicationError(T.T_NULL, E.OS_2_A_CodePageNotInstalled, m_tag, "CodePage " + CodePage + " throws an exception:" + e.Message);
                }
            }

            return bRet;
        }
Example #39
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;
            }
Example #40
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;
            }
Example #41
0
        /************************
         * public methods
         */
        
        
        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            if (v.PerformTest(T.OS_2_Version))
            {
                if (version == 0 || version == 1 || version == 2)
                {
                    v.Warning(T.OS_2_Version, W.OS_2_W_Version_old, m_tag, version.ToString());
                }
                else if (version == 3)
                {
                    v.Pass(T.OS_2_Version, P.OS_2_P_Version, m_tag, version.ToString());
                }
                else
                {
                    v.Error(T.OS_2_Version, E.OS_2_E_Version, m_tag, version.ToString());
                    bRet = false;
                }
            }

            if (v.PerformTest(T.OS_2_TableLength))
            {
                uint len = GetLength();
                if ((version == 0 && len == 78)
                    || (version == 1 && len == 86)
                    || (version == 2 && len == 96)
                    || (version == 3 && len == 96))
                {
                    v.Pass(T.OS_2_TableLength, P.OS_2_P_TableLength, m_tag);
                }
                else
                {
                    v.Error(T.OS_2_TableLength, E.OS_2_E_TableLength, m_tag);
                    bRet = false;
                }
            }

            if (!bRet)
            {
                v.Warning(T.T_NULL, W._TEST_W_OtherErrorsInTable, m_tag, "OS/2 table appears to be corrupt.  No further tests will be performed.");
                return bRet;
            }

            if (v.PerformTest(T.OS_2_xAvgCharWidth))
            {
                if (fontOwner.GetTable("maxp") == null)
                {
                    v.Warning(T.OS_2_xAvgCharWidth, W._TEST_W_ErrorInAnotherTable, m_tag, "maxp table inaccessible, can't check Avg Char Width");
                }
                else
                {
                    if (fontOwner.ContainsTrueTypeOutlines())
                    {
                        Table_hmtx hmtxTable = (Table_hmtx)fontOwner.GetTable("hmtx");
                        val_loca locaTable = (val_loca)fontOwner.GetTable("loca");
                        val_maxp maxpTable = (val_maxp)fontOwner.GetTable("maxp");
                        if (hmtxTable == null)
                        {
                            v.Error(T.OS_2_xAvgCharWidth, E._TEST_E_TableMissing, m_tag, "hmtx");
                            bRet = false;
                        }
                        else if (locaTable == null)
                        {
                            v.Error(T.OS_2_xAvgCharWidth, E._TEST_E_TableMissing, m_tag, "loca");
                            bRet = false;
                        }
                        else if (maxpTable == null)
                        {
                            v.Error(T.OS_2_xAvgCharWidth, E._TEST_E_TableMissing, m_tag, "maxp");
                            bRet = false;
                        }
                        else
                        {

                            if (   version == 3
                                || fontOwner.ContainsMsSymbolEncodedCmap())
                            {
                                int nTotalWidth = 0;
                                int nTotalGlyphs = 0;
                                for (uint iGlyph=0; iGlyph<fontOwner.GetMaxpNumGlyphs(); iGlyph++)
                                {
                                    Table_hmtx.longHorMetric hm = hmtxTable.GetOrMakeHMetric(iGlyph, fontOwner);
                                    if (hm != null)
                                    {
                                        nTotalWidth += hm.advanceWidth;
                                        // only average non-zero width glyphs
                                        if (hm.advanceWidth > 0)
                                        {
                                            nTotalGlyphs ++;
                                        }
                                    }
                                }

                                short CalcAvgWidth = 0;
                                if (nTotalGlyphs > 0)
                                    CalcAvgWidth = (short)(nTotalWidth / nTotalGlyphs);

                                if (xAvgCharWidth == CalcAvgWidth)
                                {
                                    v.Pass(T.OS_2_xAvgCharWidth, P.OS_2_P_xAvgCharWidth, m_tag);
                                }
                                else
                                {
                                    string s = "actual = " + xAvgCharWidth + ", calc = " + CalcAvgWidth;
                                    v.Error(T.OS_2_xAvgCharWidth, E.OS_2_E_xAvgCharWidth, m_tag, s);
                                    bRet = false;
                                }
                            }
                            else
                            {
                                // do weighed average
                                ushort [] weightLC = { 
                                                       64, 14, 27, 35, 100, 20, 14, 42, 63,  3,  6, 35, 20,
                                                       56, 56, 17,  4,  49, 56, 71, 31, 10,  18, 3, 18, 2
                                                     };
                                ushort weightSpace = 166;

                                try
                                {

                                    uint iSpaceGlyph = fontOwner.FastMapUnicodeToGlyphID(' ');
                                    if (iSpaceGlyph >= fontOwner.GetMaxpNumGlyphs())
                                    {
                                        throw new ApplicationException("error in cmap table");
                                    }
                                    Table_hmtx.longHorMetric hmSpace = hmtxTable.GetOrMakeHMetric(iSpaceGlyph, fontOwner);

                                    if (hmSpace != null)
                                    {

                                        int nTotalWeight = hmSpace.advanceWidth * weightSpace;
                                        int nLowerCase = 0;
                                        for (char c = 'a'; c <= 'z'; c++)
                                        {
                                            uint iGlyph = fontOwner.FastMapUnicodeToGlyphID(c);
                                            if (iGlyph > 0
                                                && iGlyph < fontOwner.GetMaxpNumGlyphs())
                                            {
                                                nLowerCase ++;

                                                Table_hmtx.longHorMetric hm = hmtxTable.GetOrMakeHMetric(iGlyph, fontOwner);
                                                nTotalWeight += hm.advanceWidth * weightLC[c-'a'];
                                            }
                                        }

                                        short CalcAvgWidth = 0;
                                        
                                        if (nLowerCase == 26)
                                        {
                                            CalcAvgWidth = (short)(nTotalWeight / 1000);
                                        }
                                        else
                                        {
                                            int nTotalWidth = 0;
                                            int nTotalGlyphs = 0;
                                            for (uint iGlyph=0; iGlyph<fontOwner.GetMaxpNumGlyphs(); iGlyph++)
                                            {
                                                Table_hmtx.longHorMetric hm = hmtxTable.GetOrMakeHMetric(iGlyph, fontOwner);
                                                nTotalWidth += hm.advanceWidth;
                                                nTotalGlyphs ++;
                                            }

                                            CalcAvgWidth = (short)(nTotalWidth / nTotalGlyphs);
                                        }

                                        if (xAvgCharWidth == CalcAvgWidth)
                                        {
                                            v.Pass(T.OS_2_xAvgCharWidth, P.OS_2_P_xAvgCharWidth, m_tag);
                                        }
                                        else
                                        {
                                            string s = "actual = " + xAvgCharWidth + ", calc = " + CalcAvgWidth;
                                            v.Error(T.OS_2_xAvgCharWidth, E.OS_2_E_xAvgCharWidth, m_tag, s);
                                            bRet = false;
                                        }
                                    }
                                    else
                                    {
                                        v.Warning(T.OS_2_xAvgCharWidth, W.OS_2_W_hmtx_invalid, m_tag, "unable to parse hmtx table");
                                    }
                                }
                                catch (ApplicationException e)
                                {
                                    v.Warning(T.OS_2_xAvgCharWidth, W._TEST_W_ErrorInAnotherTable, m_tag, "xAvgCharWidth cannot be validated due to " + e.Message);
                                }
                            }
                        }

                    }
                    else
                    {
                        // not a TT outline font - should embedded bitmap only font be handled here?
                        v.Info(T.OS_2_xAvgCharWidth, I._TEST_I_NotForCFF, m_tag, "test = OS/2_xAvgCharWidth");
                    }

                }
            }

            if (v.PerformTest(T.OS_2_WeightClass))
            {
                if (usWeightClass >= 100 &&
                    usWeightClass <= 900 &&
                    usWeightClass% 100 == 0)
                {
                    bool bWeightClassOk = true;

                    // compare to the PANOSE weight value
                    if (panose_byte1 == 2 || panose_byte1 == 3 || panose_byte1 == 4) // latin text, hand writing, or decorative
                    {
                        if (panose_byte3 > 1)
                        {
                            // convert PANOSE weight value from a range of [2..11] to a range of [100..900] (reasonably close anyway, given integer math)
                            int nConvertedPANOSE = (panose_byte3-2)*89+100;
                            int nDifference = Math.Abs(usWeightClass - nConvertedPANOSE);
                            if (nDifference < 200)
                            {
                                v.Pass(T.OS_2_WeightClass, P.OS_2_P_WeightClass_PANOSE, m_tag);
                            }
                            else
                            {
                                v.Warning(T.OS_2_WeightClass, W.OS_2_W_WeightClass_PANOSE, m_tag, "usWeightClass = " + usWeightClass + ", PANOSE weight = " + panose_byte3);
                                bWeightClassOk = false;
                            }
                        }
                    }

                    if (bWeightClassOk)
                    {
                        v.Pass(T.OS_2_WeightClass, P.OS_2_P_WeightClass, m_tag, usWeightClass.ToString());
                    }
                }
                else
                {
                    v.Error(T.OS_2_WeightClass, E.OS_2_E_WeightClass, m_tag, usWeightClass.ToString());
                    bRet = false;
                }
            }

            if (v.PerformTest(T.OS_2_WidthClass))
            {
                if (usWidthClass >=1 && usWidthClass <= 9)
                {
                    v.Pass(T.OS_2_WidthClass, P.OS_2_P_WidthClass, m_tag, usWidthClass.ToString());
                }
                else
                {
                    v.Error(T.OS_2_WidthClass, E.OS_2_E_WidthClass, m_tag, usWidthClass.ToString());
                    bRet = false;
                }
            }

            if (v.PerformTest(T.OS_2_fsType))
            {
                bool bPass = true;

                if ((fsType & 0xfcf1) != 0)
                {
                    v.Error(T.OS_2_fsType, E.OS_2_E_fsTypeReserved, m_tag, "0x"+fsType.ToString("x4"));
                    bRet = false;
                    bPass = false;
                }
                else
                {
                    int nExclusiveBits = 0;
                    if ((fsType & 0x0002) !=0) //Restricted License Embedding
                    {
                        nExclusiveBits++;
                    }
                    if ((fsType & 0x0004) != 0) // Preview and Print embedding
                    {
                        nExclusiveBits++;
                    }
                    if ((fsType & 0x0008) != 0) // Editable embedding
                    {
                        nExclusiveBits++;
                    }

                    if (nExclusiveBits > 1)
                    {
                        string sDetails = "0x"+fsType.ToString("x4");
                        if ((fsType & 0x0002) !=0)
                        {
                            sDetails += ", Restricted License Embedding";
                        }
                        if ((fsType & 0x0004) != 0)
                        {
                            sDetails += ", Preview and Print embedding";
                        }
                        if ((fsType & 0x0008) != 0)
                        {
                            sDetails += ", Editable embedding";
                        }

                        v.Error(T.OS_2_fsType, E.OS_2_E_fsTypeExclusiveBits, m_tag, sDetails);
                        bRet = false;
                        bPass = false;
                    }
                }

                if (bPass)
                {
                    string sDetails = "0x"+fsType.ToString("x4");
                    if (fsType == 0)
                    {
                        sDetails += ", Installable Embedding";
                    }
                    if ((fsType & 0x0002) !=0)
                    {
                        sDetails += ", Restricted License Embedding";
                    }
                    if ((fsType & 0x0004) != 0)
                    {
                        sDetails += ", Preview and Print embedding";
                    }
                    if ((fsType & 0x0008) != 0)
                    {
                        sDetails += ", Editable embedding";
                    }
                    if ((fsType & 0x0100) != 0)
                    {
                        sDetails += ", No subsetting";
                    }
                    if ((fsType & 0x0200) != 0)
                    {
                        sDetails += ", Bitmap embedding only";
                    }

                    v.Pass(T.OS_2_fsType, P.OS_2_P_fsType, m_tag, sDetails);
                }
            }

            if (v.PerformTest(T.OS_2_SubscriptSuperscript))
            {
                Table_head headTable = (Table_head)fontOwner.GetTable("head");
                if (headTable != null)
                {
                    ushort unitsPerEm = headTable.unitsPerEm;
                    ushort SmallestScript = (ushort)(unitsPerEm / 10);
                    bool bNoWarnOrErr = true;


                    if (ySubscriptXSize < SmallestScript ||
                        ySubscriptXSize > unitsPerEm )
                    {
                        v.Warning(T.OS_2_SubscriptSuperscript, W.OS_2_W_ySubscriptXSize_unlikely, m_tag, ySubscriptXSize.ToString());
                        bNoWarnOrErr = false;
                    }
                    if (ySubscriptYSize < SmallestScript ||
                        ySubscriptYSize > unitsPerEm )
                    {
                        v.Warning(T.OS_2_SubscriptSuperscript, W.OS_2_W_ySubscriptYSize_unlikely, m_tag, ySubscriptYSize.ToString());
                        bNoWarnOrErr = false;
                    }
                    if (ySubscriptYOffset < 0 )
                    {
                        v.Warning(T.OS_2_SubscriptSuperscript, W.OS_2_W_ySubscriptYOffset_LTZero, m_tag, ySubscriptYOffset.ToString());
                        bNoWarnOrErr = false;
                    }
                    if (ySuperscriptXSize < SmallestScript ||
                        ySuperscriptXSize > unitsPerEm )
                    {
                        v.Warning(T.OS_2_SubscriptSuperscript, W.OS_2_W_ySuperscriptXSize_unlikely, m_tag, ySuperscriptXSize.ToString());
                        bNoWarnOrErr = false;
                    }
                    if (ySuperscriptYSize < SmallestScript ||
                        ySuperscriptYSize > unitsPerEm )
                    {
                        v.Warning(T.OS_2_SubscriptSuperscript, W.OS_2_W_ySuperscriptYSize_unlikely, m_tag, ySuperscriptYSize.ToString());
                        bNoWarnOrErr = false;
                    }
                    if (ySuperscriptYOffset < 0 )
                    {
                        v.Warning(T.OS_2_SubscriptSuperscript, W.OS_2_W_ySuperscriptYOffset_unlikely, m_tag, ySuperscriptYOffset.ToString());
                        bNoWarnOrErr = false;
                    }

                    if (bNoWarnOrErr)
                    {
                        v.Pass(T.OS_2_SubscriptSuperscript, P.OS_2_P_SuperscriptSubscript, m_tag);
                    }
                }
                else
                {
                    v.Error(T.OS_2_SubscriptSuperscript, E._TEST_E_TableMissing, m_tag, "head");
                    bRet = false;
                }
            }

            if (v.PerformTest(T.OS_2_Strikeout))
            {
                Table_head headTable = (Table_head)fontOwner.GetTable("head");
                if (headTable != null)
                {
                    ushort unitsPerEm = headTable.unitsPerEm;
                    bool bNoWarnings = true;

                    if (yStrikeoutSize < 0 || yStrikeoutSize > unitsPerEm / 2 )
                    {
                        v.Warning(T.OS_2_Strikeout, W.OS_2_W_yStrikeoutSize_unlikely, m_tag, yStrikeoutSize.ToString());
                        bNoWarnings = false;
                    }
                    if (yStrikeoutPosition <= 0 )
                    {
                        v.Warning(T.OS_2_Strikeout, W.OS_2_W_yStrikeoutPosition_unlikely, m_tag, yStrikeoutPosition.ToString());
                        bNoWarnings = false;
                    }

                    if (bNoWarnings)
                    {
                        v.Pass(T.OS_2_Strikeout, P.OS_2_P_Strikeout, m_tag);
                    }
                }
                else
                {
                    v.Error(T.OS_2_Strikeout, E._TEST_E_TableMissing, m_tag, "head");
                    bRet = false;
                }
            }

            if (v.PerformTest(T.OS_2_FamilyClass))
            {
                bool bIDsOk = true;
                byte ClassID = (byte)(sFamilyClass >> 8);
                byte SubclassID = (byte)(sFamilyClass);

                if (ClassID == 6 || ClassID == 11 || ClassID == 13 || ClassID == 14 )
                {
                    v.Error(T.OS_2_FamilyClass, E.OS_2_E_sFamilyClass_classID_reserved, m_tag, ClassID.ToString());
                    bIDsOk = false;
                    bRet = false;
                }
                if (ClassID > 14 )
                {
                    v.Error(T.OS_2_FamilyClass, E.OS_2_E_sFamilyClass_ClassID_undefined, m_tag, ClassID.ToString());
                    bIDsOk = false;
                    bRet = false;
                }
                if (SubclassID > 15 )
                {
                    v.Error(T.OS_2_FamilyClass, E.OS_2_E_sFamilyClass_subclassID_undefined, m_tag, ClassID.ToString());
                    bIDsOk = false;
                    bRet = false;
                }
                if (bIDsOk)
                {
                    v.Pass(T.OS_2_FamilyClass, P.OS_2_P_sFamilyClass, m_tag);
                }
            }

            if (v.PerformTest(T.OS_2_Panose))
            {
                bool bPanoseOk = true;

                if (panose_byte1 < 5) // panose kind valid, but not latin symbol
                {
                    if (fontOwner.ContainsSymbolsOnly())
                    {
                        v.Error(T.OS_2_Panose, E.OS_2_E_Panose_FamilyTypeNotSymbol, m_tag, "PANOSE byte 1 = " + panose_byte1.ToString());
                        bPanoseOk = false;
                        bRet = false;
                    }
                }
                else if (panose_byte1 == 5) // panose family kind == latin symbol
                {
                    if (!fontOwner.ContainsSymbolsOnly())
                    {
                        v.Error(T.OS_2_Panose, E.OS_2_E_Panose_FamilyTypeSymbol, m_tag, "PANOSE byte 1 = " + panose_byte1.ToString());
                        bPanoseOk = false;
                        bRet = false;
                    }
                }
                else if ( panose_byte1 > 5 ) // family kind is invalid
                {
                    v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bFamilyType, m_tag, panose_byte1.ToString());
                    bPanoseOk = false;
                    bRet = false;
                }




                if (panose_byte1 == 2) // family kind == latin text
                {
                    if ( panose_byte2 > 15 )
                    {
                        v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bSerifStyle, m_tag, panose_byte2.ToString());
                        bPanoseOk = false;
                        bRet = false;
                    }
                }

                if ( panose_byte3 > 11 ) // byte3 always means weight
                {
                    v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bWeight, m_tag, panose_byte3.ToString());
                    bPanoseOk = false;
                    bRet = false;
                }

                if (panose_byte1 == 5) // panose family kind == latin symbol
                {
                    if (panose_byte3 != 1) // weight must be 1 for symbols
                    {
                        v.Error(T.OS_2_Panose, E.OS_2_E_Panose_SymbolWeight, m_tag, panose_byte3.ToString());
                        bPanoseOk = false;
                        bRet = false;
                    }

                    if (panose_byte5 != 1) // aspect ratio & contrast must be 1 for symbols
                    {
                        v.Error(T.OS_2_Panose, E.OS_2_E_Panose_SymbolAspectRatio, m_tag, panose_byte5.ToString());
                        bPanoseOk = false;
                        bRet = false;
                    }
                }


                if (panose_byte1 == 2) // family kind == latin text
                {
                    // the following tests are only valid when family kind is latin text

                    if ( panose_byte4 > 9 )
                    {
                        v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bProportion, m_tag, panose_byte4.ToString());
                        bPanoseOk = false;
                        bRet = false;
                    }

                    if ( panose_byte5 > 9 )
                    {
                        v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bContrast, m_tag, panose_byte5.ToString());
                        bPanoseOk = false;
                        bRet = false;
                    }

                    if ( panose_byte6 > 10 )
                    {
                        v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bStrokeVariation, m_tag, panose_byte6.ToString());
                        bPanoseOk = false;
                        bRet = false;
                    }

                    if ( panose_byte7 > 11 )
                    {
                        v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bArmStyle, m_tag, panose_byte7.ToString());
                        bPanoseOk = false;
                        bRet = false;
                    }

                    if ( panose_byte8 > 15 )
                    {
                        v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bLetterform, m_tag, panose_byte8.ToString());
                        bPanoseOk = false;
                        bRet = false;
                    }

                    if ( panose_byte9 > 13 )
                    {
                        v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bMidline, m_tag, panose_byte9.ToString());
                        bPanoseOk = false;
                        bRet = false;
                    }

                    if ( panose_byte10 > 7 )
                    {
                        v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bXHeight, m_tag, panose_byte10.ToString());
                        bPanoseOk = false;
                        bRet = false;
                    }
                }

                if (panose_byte1  == 0 && 
                    panose_byte2  == 0 &&
                    panose_byte3  == 0 &&
                    panose_byte4  == 0 &&
                    panose_byte5  == 0 &&
                    panose_byte6  == 0 &&
                    panose_byte7  == 0 &&
                    panose_byte8  == 0 &&
                    panose_byte9  == 0 &&
                    panose_byte10 == 0 )
                {
                    v.Warning(T.OS_2_Panose, W.OS_2_W_Panose_undefined, m_tag);
                    bPanoseOk = false;
                }

                if (bPanoseOk)
                {
                    v.Pass(T.OS_2_Panose, P.OS_2_P_Panose, m_tag);
                }
            }

            if (v.PerformTest(T.OS_2_UnicodeRanges))
            {
                bRet &= CheckUnicodeRanges(v, fontOwner);
            }

            if (v.PerformTest(T.OS_2_fsSelection))
            {
                bool bSelOk = true;

                Table_name nameTable = (Table_name)fontOwner.GetTable("name");
                string sStyle = null;
                string sStyleLower = null;
                if (nameTable != null)
                {
                    sStyle = nameTable.GetStyleString();
                    if (sStyle != null)
                    {
                        sStyleLower = sStyle.ToLower();
                    }
                }

                // reserved bits
                if ( (fsSelection & 0xFF80 ) != 0 )
                {
                    // we need to look for Win 3.1 font pages
                    // Fonts with these
                    const ushort HEBREW_FONT_PAGE = 0xB100;
                    const ushort SIMP_ARABIC_FONT_PAGE = 0xB200;
                    const ushort TRAD_ARABIC_FONT_PAGE = 0xB300;
                    const ushort OEM_ARABIC_FONT_PAGE = 0xB400;
                    const ushort SIMP_FARSI_FONT_PAGE = 0xBA00;
                    const ushort TRAD_FARSI_FONT_PAGE = 0xBB00;
                    const ushort THAI_FONT_PAGE = 0xDE00;

                    String sDetails = "Bit(s) ";
                    bool bFoundFirstBadBit = false;

                    if (version == 0)
                    {
                        switch (fsSelection & 0xFF00)
                        {
                            case HEBREW_FONT_PAGE:
                                sDetails = "Hebrew Windows 3.1 font page";
                                break;
                            case SIMP_ARABIC_FONT_PAGE:
                                sDetails = "Simplified Arabic Windows 3.1 font page";
                                break;
                            case TRAD_ARABIC_FONT_PAGE:
                                sDetails = "Traditional Arabic Windows 3.1 font page";
                                break;
                            case OEM_ARABIC_FONT_PAGE:
                                sDetails = "OEM Arabic Windows 3.1 font page";
                                break;
                            case SIMP_FARSI_FONT_PAGE:
                                sDetails = "Simplified Farsi Windows 3.1 font page";
                                break;
                            case TRAD_FARSI_FONT_PAGE:
                                sDetails = "Traditional Farsi Windows 3.1 font page";
                                break;
                            case THAI_FONT_PAGE:
                                sDetails = "Thai Windows 3.1 font page";
                                break;
                            default:
                                for (int i=0; i<16; i++)
                                {
                                    int nBitValue = 1<<i;
                                    if ((nBitValue & 0xFF80) != 0)
                                    {
                                        if ((fsSelection & nBitValue) != 0)
                                        {
                                            if (bFoundFirstBadBit)
                                            {
                                                sDetails += ", " + i;
                                            }
                                            else
                                            {
                                                sDetails += i.ToString();
                                                bFoundFirstBadBit = true;
                                            }
                                        }
                                    }
                                }
                                break;
                            
                        }
                    }
                    else
                    {
                        for (int i=0; i<16; i++)
                        {
                            int nBitValue = 1<<i;
                            if ((nBitValue & 0xFF80) != 0)
                            {
                                if ((fsSelection & nBitValue) != 0)
                                {
                                    if (bFoundFirstBadBit)
                                    {
                                        sDetails += ", " + i;
                                    }
                                    else
                                    {
                                        sDetails += i.ToString();
                                        bFoundFirstBadBit = true;
                                    }
                                }
                            }
                        }
                    }

                    v.Error(T.OS_2_fsSelection, E.OS_2_E_fsSelection_undefbits, m_tag, sDetails);
                    bSelOk = false;
                    bRet = false;
                }

                // compare to head.macStyle italic and bold bits
                Table_head headTable = (Table_head)fontOwner.GetTable("head");
                if (headTable != null)
                {
                    bool bItalic = ((fsSelection & 0x01) != 0 );
                    bool bBold   = ((fsSelection & 0x20) != 0 );

                    bool bMacBold = ((headTable.macStyle & 0x0001) != 0);
                    bool bMacItal = ((headTable.macStyle & 0x0002) != 0);

                    if (bItalic != bMacItal)
                    {
                        string sDetails = null;
                        if (bItalic) sDetails = "fsSelection italic bit is set, but macstyle italic bit is clear";
                        else sDetails =  "fsSelection italic bit is clear, but macstyle italic bit is set";

                        v.Error(T.OS_2_fsSelection, E.OS_2_E_fsSelection_macStyle_italic, m_tag, sDetails);
                        bSelOk = false;
                        bRet = false;
                    }

                    if (bBold != bMacBold)
                    {
                        string sDetails = null;
                        if (bBold) sDetails = "fsSelection bold bit is set, but macstyle bold bit is clear";
                        else sDetails =  "fsSelection bold bit is clear, but macstyle bold bit is set";

                        v.Error(T.OS_2_fsSelection, E.OS_2_E_fsSelection_macStyle_bold, m_tag, sDetails);
                        bSelOk = false;
                        bRet = false;
                    }
                }

                if ((fsSelection & 0x01) != 0 ) // italic bit
                {
                    // compare to name subfamily
                    if (sStyleLower != null)
                    {
                        if (sStyleLower.IndexOf("italic") == -1 && sStyleLower.IndexOf("oblique") == -1)
                        {
                            v.Error(T.OS_2_fsSelection, E.OS_2_E_fsSelection_subfamily, m_tag, "fsSelection italic bit is set, but subfamily is " + sStyle);
                            bSelOk = false;
                            bRet = false;
                        }
                    }
                }

                if ((fsSelection & 0x20) != 0 ) // bold bit
                {
                    // compare to name subfamily
                    if (sStyleLower != null)
                    {
                        if (sStyleLower.IndexOf("bold") == -1)
                        {
                            v.Error(T.OS_2_fsSelection, E.OS_2_E_fsSelection_subfamily, m_tag, "fsSelection bold bit is set, but subfamily is " + sStyle);
                            bSelOk = false;
                            bRet = false;
                        }
                    }

                    if (usWeightClass <= 500)
                    {
                        v.Warning(T.OS_2_fsSelection, W.OS_2_W_fsSelection_weight, m_tag, "usWeightClass = " + usWeightClass);
                        bSelOk = false;
                    }
                }

                if ((fsSelection & 0x40) != 0 ) // regular bit
                {
                    if ((fsSelection & 0x20) != 0 )
                    {
                        v.Error(T.OS_2_fsSelection, E.OS_2_E_reg_bold, m_tag);
                        bSelOk = false;
                        bRet = false;
                    }
                    if ((fsSelection & 0x01) != 0) 
                    {
                        v.Error(T.OS_2_fsSelection, E.OS_2_E_reg_ital, m_tag);
                        bSelOk = false;
                        bRet = false;
                    }

                    if (sStyleLower != null)
                    {
                        // compare to name subfamily
                        if (sStyleLower.CompareTo("regular") != 0)
                        {
                            v.Error(T.OS_2_fsSelection, E.OS_2_E_fsSelection_subfamily, m_tag, "fsSelection regular bit is set, but subfamily is " + sStyle);
                            bSelOk = false;
                            bRet = false;
                        }
                    }                    
                }

                if (bSelOk)
                {
                    v.Pass(T.OS_2_fsSelection, P.OS_2_P_fsSelection, m_tag);
                }
            }

            if (v.PerformTest(T.OS_2_CharIndexes))
            {
                Table_cmap cmapTable = (Table_cmap)fontOwner.GetTable("cmap");

                if (cmapTable != null)
                {
                    ushort charFirst = 0xffff;
                    ushort charLast  = 0;

                    Table_cmap.EncodingTableEntry eteUni = cmapTable.GetEncodingTableEntry(3,1);
                    if (eteUni == null)
                    {
                        // presumably a symbol font
                        eteUni = cmapTable.GetEncodingTableEntry(3,0);
                    }

                    if (eteUni != null)
                    {
                        Table_cmap.Subtable st = cmapTable.GetSubtable(eteUni);
                        if (st != null)
                        {
                            bool bCmapOk = true;
                            byte[] charbuf = new byte[2];
                            // find the first char
                            for (ushort c=0; c<0xffff; c++)
                            {
                                charbuf[0] = (byte)c;
                                charbuf[1] = (byte)(c>>8);
                                uint glyphID;
                                try
                                {
                                    glyphID = st.MapCharToGlyph(charbuf, 0);
                                }
                                catch
                                {
                                    bCmapOk = false;
                                    break;
                                }
                                if (glyphID != 0)
                                {
                                    charFirst = c;
                                    break;
                                }
                            }
                            // find the last char (start at fffd: fffe and ffff aren't legal characters)
                            if (bCmapOk)
                            {
                                for (ushort c=0xfffd; c>0; c--)
                                {
                                    charbuf[0] = (byte)c;
                                    charbuf[1] = (byte)(c>>8);
                                    uint glyphID;
                                    try
                                    {
                                        glyphID = st.MapCharToGlyph(charbuf, 0);
                                    }
                                    catch
                                    {
                                        bCmapOk = false;
                                        break;
                                    }

                                    if (glyphID != 0)
                                    {
                                        charLast = c;
                                        break;
                                    }
                                }
                            }

                            if (!bCmapOk)
                            {
                                v.Warning(T.OS_2_CharIndexes, W._TEST_W_ErrorInAnotherTable, m_tag, "usFirstCharIndex and usLastCharIndex cannot be validated due to errors in the cmap table");
                            }
                            else if (usFirstCharIndex == charFirst && usLastCharIndex == charLast)
                            {
                                v.Pass(T.OS_2_CharIndexes, P.OS_2_P_CharIndexes, m_tag, "first = 0x" + usFirstCharIndex.ToString("x4") + ", last = 0x" + usLastCharIndex.ToString("x4"));
                            }
                            else
                            {
                                if (usFirstCharIndex != charFirst)
                                {
                                    String sDetails = "actual = 0x" + usFirstCharIndex.ToString("x4") + ", calculated = 0x" + charFirst.ToString("x4");
                                    v.Error(T.OS_2_CharIndexes, E.OS_2_E_usFirstCharIndex, m_tag, sDetails);
                                    bRet = false;
                                }
                        
                                if (usLastCharIndex != charLast)
                                {
                                    String sDetails = "actual = 0x" + usLastCharIndex.ToString("x4") + ", calculated = 0x" + charLast.ToString("x4");
                                    v.Error(T.OS_2_CharIndexes, E.OS_2_E_usLastCharIndex, m_tag, sDetails);
                                    bRet = false;
                                }
                            }
                        }
                        else
                        {
                            v.Warning(T.OS_2_CharIndexes, W._TEST_W_ErrorInAnotherTable, m_tag, "usFirstCharIndex and usLastCharIndex cannot be validated due to errors in the cmap table");
                        }
                    }

                }
                else
                {
                    v.Error(T.OS_2_CharIndexes, E._TEST_E_TableMissing, m_tag, "cmap");
                    bRet = false;
                }
            }

            if (v.PerformTest(T.OS_2_TypoMetrics))
            {
                bool bOk = true;

                if (sTypoAscender <= 0)
                {
                    v.Error(T.OS_2_TypoMetrics, E.OS_2_E_sTypoAscender_notpositive, m_tag, sTypoAscender.ToString());
                    bOk = false;
                    bRet = false;
                }

                if (sTypoDescender > 0)
                {
                    v.Error(T.OS_2_TypoMetrics, E.OS_2_E_sTypoDescender_positive, m_tag, sTypoDescender.ToString());
                    bOk = false;
                    bRet = false;
                }

                Table_head headTable = (Table_head)fontOwner.GetTable("head");
                if (headTable != null)
                {
                    if (sTypoAscender - sTypoDescender > headTable.unitsPerEm)
                    {
                        string sDetails = "sTypoAscender = " + sTypoAscender + ", sTypoDescender = " + sTypoDescender;
                        v.Warning(T.OS_2_TypoMetrics, W.OS_2_W_sTypoAscenderDescender_difference, m_tag, sDetails);
                        bOk = false;
                    }
                }
                else
                {
                    v.Error(T.OS_2_TypoMetrics, E._TEST_E_TableMissing, m_tag, "head");
                    bRet = false;
                }

                if (bOk)
                {
                    string sDetails = "sTypoAscender = " + sTypoAscender + ", sTypoDescender = " + sTypoDescender;
                    v.Pass(T.OS_2_TypoMetrics, P.OS_2_P_sTypoAscenderDescender, m_tag, sDetails);
                }
            }

            if (v.PerformTest(T.OS_2_CodePageRanges))
            {
                if (version >= 1)
                {
                    bRet &= CheckCodePageRanges(v, fontOwner);
                }
            }

            if (v.PerformTest(T.OS_2_sxHeight))
            {
                if (version >= 2)
                {
                    if (sxHeight == 0)
                    {
                        if (fontOwner.FastMapUnicodeToGlyphID((char)0x0078) != 0)
                        {
                            v.Error(T.OS_2_sxHeight, E.OS_2_E_sxHeight, m_tag);
                            bRet = false;
                        }
                        else
                        {
                            v.Pass(T.OS_2_sxHeight, P.OS_2_P_sxHeight_zero, m_tag, sxHeight.ToString());
                        }
                    }
                    else
                    {
                        v.Pass(T.OS_2_sxHeight, P.OS_2_P_sxHeight_nonzero, m_tag, sxHeight.ToString());
                    }
                }
            }

            if (v.PerformTest(T.OS_2_sCapHeight))
            {
                if (version >= 2)
                {
                    if (sCapHeight == 0)
                    {
                        if (fontOwner.FastMapUnicodeToGlyphID((char)0x0048) != 0)
                        {
                            v.Error(T.OS_2_sCapHeight, E.OS_2_E_sCapHeight, m_tag);
                            bRet = false;
                        }
                        else
                        {
                            v.Pass(T.OS_2_sCapHeight, P.OS_2_P_sCapHeight_zero, m_tag, sCapHeight.ToString());
                        }
                    }
                    else
                    {
                        v.Pass(T.OS_2_sCapHeight, P.OS_2_P_sCapHeight_nonzero, m_tag, sCapHeight.ToString());
                    }
                }
            }

            if (v.PerformTest(T.OS_2_usDefaultChar))
            {
                if (version >= 2)
                {
                    if (usDefaultChar == 0)
                    {
                        v.Pass(T.OS_2_usDefaultChar, P.OS_2_P_usDefaultChar_zero, m_tag);
                    }
                    else if (fontOwner.FastMapUnicodeToGlyphID((char)usDefaultChar) != 0)
                    {
                        v.Pass(T.OS_2_usDefaultChar, P.OS_2_P_usDefaultChar_nonzero, m_tag, "0x" + usDefaultChar.ToString("x4"));
                    }
                    else
                    {
                        v.Error(T.OS_2_usDefaultChar, E.OS_2_E_usDefaultChar_notmapped, m_tag, "0x" + usDefaultChar.ToString("x4"));
                        bRet = false;
                    }
                }
            }

            if (v.PerformTest(T.OS_2_usBreakChar))
            {
                if (version >= 2)
                {
                    if (fontOwner.FastMapUnicodeToGlyphID((char)usBreakChar) != 0)
                    {
                        v.Pass(T.OS_2_usBreakChar, P.OS_2_P_usBreakChar_mapped, m_tag);
                    }
                    else
                    {
                        v.Error(T.OS_2_usBreakChar, E.OS_2_E_usBreakChar_notmapped, m_tag, "0x" + usBreakChar.ToString("x4"));
                        bRet = false;
                    }
                }
            }

            if (v.PerformTest(T.OS_2_usMaxContext))
            {
                if (version >= 2)
                {
                    ushort GPOSMaxContext = 0;
                    Table_GPOS GPOSTable = (Table_GPOS)fontOwner.GetTable("GPOS");
                    if (GPOSTable != null)
                    {
                        GPOSMaxContext = GPOSTable.GetMaxContext();
                    }

                    ushort GSUBMaxContext = 0;
                    Table_GSUB GSUBTable = (Table_GSUB)fontOwner.GetTable("GSUB");
                    if (GSUBTable != null)
                    {
                        GSUBMaxContext = GSUBTable.GetMaxContext();
                    }

                    ushort CalcMaxContext = Math.Max(GPOSMaxContext, GSUBMaxContext);

                    if (usMaxContext == CalcMaxContext)
                    {
                        v.Pass(T.OS_2_usMaxContext, P.OS_2_P_usMaxContext, m_tag, usMaxContext.ToString());
                    }
                    else
                    {
                        v.Error(T.OS_2_usMaxContext, E.OS_2_E_usMaxContext, m_tag, "calc = " + CalcMaxContext + ", actual = " + usMaxContext);
                        bRet = false;
                    }
                }
            }

            return bRet;
        }
Example #42
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;
        }
Example #43
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;
            }
Example #44
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;
            }
Example #45
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;
        }
Example #46
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;
            }
Example #47
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;
        }
Example #48
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;
        }
Example #49
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;
        }
Example #50
0
        /************************
         * public methods
         */


        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;


            if (v.PerformTest(T.head_TableLength))
            {
                if (m_bufTable.GetLength() == 54)
                {
                    v.Pass(T.head_TableLength, P.head_P_TableLength, m_tag);
                }
                else
                {
                    v.Error(T.head_TableLength, E.head_E_TableLength, m_tag, m_bufTable.GetLength().ToString());
                    bRet = false;
                }
            }

            if (v.PerformTest(T.head_TableVersion))
            {
                if (TableVersionNumber.GetUint() == 0x00010000)
                {
                    v.Pass(T.head_TableVersion, P.head_P_TableVersion, m_tag);
                }
                else
                {
                    v.Error(T.head_TableVersion, E.head_E_TableVersion, m_tag, "0x"+TableVersionNumber.GetUint().ToString("x8"));
                    bRet = false;
                }
            }

            if (v.PerformTest(T.head_fontRevision))
            {
                string sVersion = fontOwner.GetFontVersion();
                if (sVersion != null)
                {
                    if (sVersion.Length >= 11
                        && sVersion.StartsWith("Version ")
                        && Char.IsDigit(sVersion, 8))
                    {
                        string sVersionNum = sVersion.Substring(8);
                        bool bFoundDecPt = false;
                        int nLastDigitPos = 0;
                        for (int i=0; i<sVersionNum.Length; i++)
                        {
                            if (Char.IsDigit(sVersionNum, i))
                            {
                                nLastDigitPos = i;
                            }
                            else if (sVersionNum[i] == '.')
                            {
                                if (!bFoundDecPt)
                                {
                                    bFoundDecPt = true;
                                }
                                else
                                {
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                        double fVersion = Double.Parse(sVersionNum.Substring(0, nLastDigitPos+1));
                        double fRevision = fontRevision.GetDouble();

                        if (Math.Round(fVersion, 3) == Math.Round(fRevision, 3))
                        {
                            v.Pass(T.head_fontRevision, P.head_P_fontRevision, m_tag, fRevision.ToString("f3"));
                        }
                        else
                        {
                            string s = "revision: " + fRevision.ToString("f3") + ", version: " + sVersionNum;
                            v.Warning(T.head_fontRevision, W.head_W_fontRevision, m_tag, s);
                        }
                    }
                }
            }
            
            if (v.PerformTest(T.head_ChecksumAdjustment))
            {
                if (checkSumAdjustment == 0xb1b0afba - fontOwner.CalcChecksum())
                {
                    v.Pass(T.head_ChecksumAdjustment, P.head_P_FontChecksum, m_tag, "0x"+checkSumAdjustment.ToString("x8"));
                }
                else
                {
                    v.Error(T.head_ChecksumAdjustment, E.head_E_FontChecksum, m_tag, "0x"+checkSumAdjustment.ToString("x8"));
                    bRet = false;
                }
            }
            
            if (v.PerformTest(T.head_MagicNumber))
            {
                if (magicNumber == 0x5f0f3cf5)
                {
                    v.Pass(T.head_MagicNumber, P.head_P_MagicNumber, m_tag);
                }
                else
                {
                    v.Error(T.head_MagicNumber, E.head_E_MagicNumber, m_tag, "0x"+magicNumber.ToString("x8"));
                    bRet = false;
                }
            }
            
            if (v.PerformTest(T.head_FlagTests))
            {
                ushort val = flags;
                // bit 0 indicates baseline for font at y=0
                
                // bit 1 indicates left sidebearing point at x=0

                // bit 2 indicates instructions may depend on point size

                // bit 3 indicates forcing ppem to integer values instead of fractional values

                // bit 4 indicates non-linear scaling - if set allows presence of LTSH and/or hdmx tables
                Table_hdmx hdmxTable = (Table_hdmx)fontOwner.GetTable("hdmx");
                Table_LTSH LTSHTable = (Table_LTSH)fontOwner.GetTable("LTSH");
                if ((val & 0x0010) == 0)
                {
                    if (hdmxTable == null)
                    {
                        v.Pass(T.head_FlagTests, P.head_P_flags_bit4_0_hdmx, m_tag);
                    }
                    else
                    {
                        v.Error(T.head_FlagTests, E.head_E_flags_bit4_0_hdmx, m_tag);
                    }

                    if (LTSHTable == null)
                    {
                        v.Pass(T.head_FlagTests, P.head_P_flags_bit4_0_LTSH, m_tag);
                    }
                    else
                    {
                        v.Error(T.head_FlagTests, E.head_E_flags_bit4_0_LTSH, m_tag);
                    }
                }
                else
                {
                    if (hdmxTable != null)
                    {
                        v.Pass(T.head_FlagTests, P.head_P_flags_bit4_1_hdmx, m_tag);
                    }
                    else
                    {
                        v.Warning(T.head_FlagTests, W.head_W_flags_bit4_1_hdmx, m_tag);
                    }

                    if (LTSHTable != null)
                    {
                        v.Pass(T.head_FlagTests, P.head_P_flags_bit4_1_LTSH, m_tag);
                    }
                    else
                    {
                        v.Warning(T.head_FlagTests, W.head_W_flags_bit4_1_LTSH, m_tag);
                    }
                }

                // bits 5 - 10 are used by apple and ignored by windows

                // bit 11 indicates font data is 'lossless' as a result of having been compressed/decompressed

                // bit 12 indicates a converted font

                // bit 13 indicates optimized for cleartype

                // bit 14 reserved
                if ((val & 0x4000) == 0)
                {
                    v.Pass(T.head_FlagTests, P.head_P_flags_bit14, m_tag);
                }
                else
                {
                    v.Error(T.head_FlagTests, E.head_E_flags_bit14, m_tag, val.ToString());
                    bRet = false;
                }
                    
                // bit 15 reserved
                if ((val & 0x8000) == 0)
                {
                    v.Pass(T.head_FlagTests, P.head_P_flags_bit15, m_tag);
                }
                else
                {
                    v.Error(T.head_FlagTests, E.head_E_flags_bit15, m_tag, val.ToString());
                    bRet = false;
                }
            }
            
            if (v.PerformTest(T.head_UnitsPerEmValues))
            {
                ushort val = unitsPerEm;

                bool bInRange = false;

                if (val < 16) // opentype spec says min value is 16
                {
                    v.Error(T.head_UnitsPerEmValues, E.head_E_unitsPerEm_LT16, m_tag, val.ToString());
                    bRet = false;
                }
                else if (val < 64) // apple spec says min value is 64
                {
                    v.Warning(T.head_UnitsPerEmValues, W.head_W_unitsPerEM_LT64, m_tag, val.ToString());
                }
                else if (val > 16384)
                {
                    v.Error(T.head_UnitsPerEmValues, E.head_E_unitsPerEM_GT16384, m_tag, val.ToString());
                    bRet = false;
                }
                else
                {
                    bInRange = true;
                }

                // apple spec says unitsPerEm must be power of two
                // but don't check if it's a CFF font
                if (!fontOwner.ContainsPostScriptOutlines())
                {
                    bool bPowerOfTwo = false;
                    for (int i=0; i<16; i++)
                    {
                        ushort nPow2 = (ushort)(1<<i);
                        if (val == nPow2)
                        {
                            bPowerOfTwo = true;
                            break;
                        }
                    }
                    if (bPowerOfTwo)
                    {
                        if (bInRange)
                        {
                            v.Pass(T.head_UnitsPerEmValues, P.head_P_unitsPerEm, m_tag, val.ToString());
                        }
                    }
                    else
                    {
                        v.Warning(T.head_UnitsPerEmValues, W.head_W_unitsPerEm_Pow2, m_tag, val.ToString());
                    }
                }
            }
            
            if (v.PerformTest(T.head_Dates))
            {
                DateTime dtBeforeTrueType = new DateTime(1985, 1, 1);

                if ((created >> 32) == 0)
                {
                    DateTime dtCreated = this.GetCreatedDateTime();
                    if (created == 0)
                    {
                        v.Warning(T.head_Dates, W.head_W_created_0, m_tag);
                    }
                    else if (dtCreated < dtBeforeTrueType || dtCreated > DateTime.Now)
                    {
                        string sDetails = "created = " + created + " (" + dtCreated.ToString("f", null) + ")";
                        v.Warning(T.head_Dates, W.head_W_created_unlikely, m_tag, sDetails);
                    }
                    else
                    {
                        v.Pass(T.head_Dates, P.head_P_created_0, m_tag);
                    }
                }
                else
                {
                    string sDetails = "created = 0x" + created.ToString("x16");
                    v.Error(T.head_Dates, E.head_E_created_invalid, m_tag, sDetails);
                    bRet = false;
                }

                if ((modified >> 32) == 0)
                {
                    DateTime dtModified = this.GetModifiedDateTime();
                    if (modified == 0)
                    {
                        v.Warning(T.head_Dates, W.head_W_modified_0, m_tag);
                    }
                    else if (dtModified < dtBeforeTrueType || dtModified > DateTime.Now)
                    {
                        string sDetails = "modified = " + modified + " (" + dtModified.ToString("f", null) + ")";
                        v.Warning(T.head_Dates, W.head_W_modified_unlikely, m_tag, sDetails);
                    }
                    else
                    {
                        v.Pass(T.head_Dates, P.head_P_modified_0, m_tag);
                    }
                }
                else
                {
                    string sDetails = "modified = 0x" + modified.ToString("x16");
                    v.Error(T.head_Dates, E.head_E_modified_invalid, m_tag, sDetails);
                    bRet = false;
                }
            }
            
            if (v.PerformTest(T.head_MinMaxValues))
            {
                if (fontOwner.ContainsTrueTypeOutlines())
                {
                    if (xMin > xMax)
                    {
                        v.Error(T.head_MinMaxValues, E.head_E_xMin_GT_xMax, m_tag);
                        bRet = false;
                    }

                    if (yMin > yMax)
                    {
                        v.Error(T.head_MinMaxValues, E.head_E_yMin_GT_yMax, m_tag);
                        bRet = false;
                    }

                    short xMinExpected = 32767;
                    short xMaxExpected = -32768;
                    short yMinExpected = 32767;
                    short yMaxExpected = -32768;

                    Table_glyf glyfTable = (Table_glyf)fontOwner.GetTable("glyf");
                    if (glyfTable != null)
                    {
                        Table_maxp maxp = (Table_maxp)fontOwner.GetTable("maxp");
                        if (maxp != null)
                        {
                            for (uint i=0; i<fontOwner.GetMaxpNumGlyphs(); i++)
                            {
                                Table_glyf.header h = glyfTable.GetGlyphHeader(i, fontOwner);
                                if (h != null)
                                {
                                    if (xMinExpected > h.xMin) xMinExpected = h.xMin;
                                    if (xMaxExpected < h.xMax) xMaxExpected = h.xMax;
                                    if (yMinExpected > h.yMin) yMinExpected = h.yMin;
                                    if (yMaxExpected < h.yMax) yMaxExpected = h.yMax;
                                }
                            }

                            if (xMin == xMinExpected)
                            {
                                String s = "xMin = " + xMin;
                                v.Pass(T.head_MinMaxValues, P.head_P_xMin_glyf, m_tag, s);
                            }
                            else
                            {
                                string s = "actual: " + xMin + ", expected: " + xMinExpected;
                                v.Error(T.head_MinMaxValues, E.head_E_xMin_glyf, m_tag, s);
                                bRet = false;
                            }

                            if (yMin == yMinExpected)
                            {
                                String s = "yMin = " + yMin;
                                v.Pass(T.head_MinMaxValues, P.head_P_yMin_glyf, m_tag, s);
                            }
                            else
                            {
                                string s = "actual: " + yMin + ", expected: " + yMinExpected;
                                v.Error(T.head_MinMaxValues, E.head_E_yMin_glyf, m_tag, s);
                                bRet = false;
                            }

                            if (xMax == xMaxExpected)
                            {
                                String s = "xMax = " + xMax;
                                v.Pass(T.head_MinMaxValues, P.head_P_xMax_glyf, m_tag, s);
                            }
                            else
                            {
                                string s = "actual: " + xMax + ", expected: " + xMaxExpected;
                                v.Error(T.head_MinMaxValues, E.head_E_xMax_glyf, m_tag, s);
                                bRet = false;
                            }

                            if (yMax == yMaxExpected)
                            {
                                String s = "yMax = " + yMax;
                                v.Pass(T.head_MinMaxValues, P.head_P_yMax_glyf, m_tag, s);
                            }
                            else
                            {
                                string s = "actual: " + yMax + ", expected: " + yMaxExpected;
                                v.Error(T.head_MinMaxValues, E.head_E_yMax_glyf, m_tag, s);
                                bRet = false;
                            }
                        }
                        else
                        {
                            v.Error(T.head_MinMaxValues, E._TEST_E_TableMissing, m_tag, "maxp");
                        }
                    }
                    else
                    {
                        v.Error(T.head_MinMaxValues, E._TEST_E_TableMissing, m_tag, "glyf");
                    }
                }
                else
                {
                    v.Info(T.head_MinMaxValues, I._TEST_I_NotForCFF, m_tag, "test = head_MinMaxValues");
                }
            }
            
            if (v.PerformTest(T.head_MacStyleBits))
            {
                bool bMacBold = ((macStyle & 0x0001) != 0);
                bool bMacItal = ((macStyle & 0x0002) != 0);

                // subfamily (style) string

                Table_name nameTable = (Table_name)fontOwner.GetTable("name");
                string sStyle = null;
                string sStyleLower = null;
                if (nameTable != null)
                {
                    sStyle = nameTable.GetStyleString();
                    if (sStyle != null)
                    {
                        sStyleLower = sStyle.ToLower();
                    }
                }
                if (sStyleLower != null)
                {
                    if (bMacBold && sStyleLower.IndexOf("bold") == -1)
                    {
                        v.Error(T.head_MacStyleBits, E.head_E_macStyleBold_subfamily, m_tag, "macStyle bold bit is set, but subfamily is " + sStyle);
                        bRet = false;
                    }
                    else if (!bMacBold && sStyleLower.IndexOf("bold") != -1)
                    {
                        v.Error(T.head_MacStyleBits, E.head_E_macStyleBold_subfamily, m_tag, "macStyle bold bit is clear, but subfamily is " + sStyle);
                        bRet = false;
                    }
                    else
                    {
                        v.Pass(T.head_MacStyleBits, P.head_P_macStyleBold_subfamily, m_tag);
                    }

                    if (bMacItal && sStyleLower.IndexOf("italic") == -1 && sStyleLower.IndexOf("oblique") == -1)
                    {
                        v.Error(T.head_MacStyleBits, E.head_E_macStyleItal_subfamily, m_tag, "macStyle italic bit is set, but subfamily is " + sStyle);
                        bRet = false;
                    }
                    else if (!bMacItal && (sStyleLower.IndexOf("italic") != -1 || sStyleLower.IndexOf("oblique") != -1))
                    {
                        v.Error(T.head_MacStyleBits, E.head_E_macStyleItal_subfamily, m_tag, "macStyle italic bit is clear, but subfamily is " + sStyle);
                        bRet = false;
                    }
                    else
                    {
                        v.Pass(T.head_MacStyleBits, P.head_P_macStyleItal_subfamily, m_tag);
                    }
                }

                Table_OS2 OS2Table = (Table_OS2)fontOwner.GetTable("OS/2");
                if (OS2Table != null)
                {
                    // fsSelection

                    bool bOS2Bold = ((OS2Table.fsSelection & 0x0020) != 0);
                    bool bOS2Ital = ((OS2Table.fsSelection & 0x0001) != 0);

                    if (bMacBold == bOS2Bold)
                    {
                        v.Pass(T.head_MacStyleBits, P.head_P_macStyleBold_OS2, m_tag);
                    }
                    else if (bMacBold)
                    {
                        v.Error(T.head_MacStyleBits, E.head_E_macStyleBold1_OS2, m_tag);
                        bRet = false;
                    }
                    else
                    {
                        v.Error(T.head_MacStyleBits, E.head_E_macStyleBold0_OS2, m_tag);
                        bRet = false;
                    }

                    if (bMacItal == bOS2Ital)
                    {
                        v.Pass(T.head_MacStyleBits, P.head_P_macStyleItal_OS2, m_tag);
                    }
                    else if (bMacItal)
                    {
                        v.Error(T.head_MacStyleBits, E.head_E_macStyleItal1_OS2, m_tag);
                        bRet = false;
                    }
                    else
                    {
                        v.Error(T.head_MacStyleBits, E.head_E_macStyleItal0_OS2, m_tag);
                        bRet = false;
                    }
                }

                Table_post postTable = (Table_post)fontOwner.GetTable("post");

                if (postTable != null)
                {
                    bool bPostItal = (postTable.italicAngle.GetUint() != 0);


                    if (bMacItal == bPostItal)
                    {
                        v.Pass(T.head_MacStyleBits, P.head_P_macStyleItal_post, m_tag);
                    }
                    else if (bMacItal)
                    {
                        v.Error(T.head_MacStyleBits, E.head_E_macStyleItal1_post, m_tag);
                        bRet = false;
                    }
                    else
                    {
                        v.Error(T.head_MacStyleBits, E.head_E_macStyleItal0_post, m_tag);
                        bRet = false;
                    }
                }
            }
            
            if (v.PerformTest(T.head_LowestRecSize))
            {
                if (lowestRecPPEM == 0)
                {
                    v.Error(T.head_LowestRecSize, E.head_E_lowestRecPPEM_zero, m_tag);
                    bRet = false;
                }
                else if (lowestRecPPEM >= 1 && lowestRecPPEM <= 6)
                {
                    v.Warning(T.head_LowestRecSize, W.head_W_lowestRecPPEM_small, m_tag, "lowestRecPPEM = " + lowestRecPPEM.ToString());
                }
                else if (lowestRecPPEM >= 36)
                {
                    v.Warning(T.head_LowestRecSize, W.head_W_lowestRecPPEM_large, m_tag, "lowestRecPPEM = " + lowestRecPPEM.ToString());
                }
                else
                {
                    v.Pass(T.head_LowestRecSize, P.head_P_lowestRecPPEM, m_tag);
                }
            }
            
            if (v.PerformTest(T.head_FontDirectionHint))
            {
                if (fontDirectionHint >= -2 && fontDirectionHint <= 2)
                {
                    v.Pass(T.head_FontDirectionHint, P.head_P_fontDirectionHint, m_tag, fontDirectionHint.ToString());
                }
                else
                {
                    v.Error(T.head_FontDirectionHint, E.head_E_fontDirectionHint, m_tag, fontDirectionHint.ToString());
                    bRet = false;
                }
            }
            
            if (v.PerformTest(T.head_IndexToLocFormat))
            {
                if (fontOwner.ContainsPostScriptOutlines())
                {
                    v.Pass(T.head_IndexToLocFormat, P.head_P_indexToLocFormat_ignore, m_tag, "indexToLocFormat = " + indexToLocFormat);
                }
                else
                {
                    if (indexToLocFormat == 0 || indexToLocFormat == 1)
                    {
                        v.Pass(T.head_IndexToLocFormat, P.head_P_indexToLocFormat_range, m_tag, indexToLocFormat.ToString());
                    }
                    else
                    {
                        v.Error(T.head_IndexToLocFormat, E.head_E_indexToLocFormat_range, m_tag, indexToLocFormat.ToString());
                        bRet = false;
                    }

                    if (indexToLocFormat == 0 || indexToLocFormat == 1)
                    {
                        Table_loca locaTable = (Table_loca)fontOwner.GetTable("loca");
                        if (locaTable != null)
                        {
                            Table_maxp maxpTable = (Table_maxp)fontOwner.GetTable("maxp");
                            if (maxpTable != null)
                            {
                                uint locaTableElementSize = 0;
                                if (indexToLocFormat == 0)
                                    locaTableElementSize = 2;
                                else if (indexToLocFormat == 1)
                                    locaTableElementSize = 4;

                                uint CalcLocaLength = (uint)(maxpTable.NumGlyphs + 1) * locaTableElementSize;
                                if (CalcLocaLength == locaTable.GetLength())
                                {
                                    v.Pass(T.head_IndexToLocFormat, P.head_P_indexToLocFormat_match, m_tag, indexToLocFormat.ToString());
                                }
                                else
                                {
                                    v.Error(T.head_IndexToLocFormat, E.head_E_indexToLocFormat_match, m_tag, indexToLocFormat.ToString());
                                    bRet = false;
                                }
                            }
                            else
                            {
                                v.Error(T.head_IndexToLocFormat, E._TEST_E_TableMissing, m_tag, "maxp");
                            }
                        }
                        else
                        {
                            v.Error(T.head_IndexToLocFormat, E._TEST_E_TableMissing, m_tag, "loca");
                        }
                    }
                }
            }
            
            if (v.PerformTest(T.head_GlyphDataFormat))
            {
                if (glyphDataFormat == 0)
                {
                    v.Pass(T.head_GlyphDataFormat, P.head_P_glyphDataFormat, m_tag);
                }
                else
                {
                    v.Error(T.head_GlyphDataFormat, E.head_E_glyphDataFormat, m_tag);
                    bRet = false;
                }
            }

            return bRet;
        }
Example #51
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;
            }
Example #52
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;
        }
Example #53
0
        bool VerifyUnicodeRanges( Validator  v,
            uint        ulUnicodeRange,
            uint        ulUnicodeRangeBit,
            uint        nCharsInRange,
            string      sRangeNames)
        {
            bool bRet = true;
            if(nCharsInRange != 0)
            {
                if((ulUnicodeRange & ulUnicodeRangeBit) == 0)
                {
                    v.Info(T.T_NULL, I.OS_2_I_RangeBitNotSet, m_tag, nCharsInRange + " characters are present in the ranges: " + sRangeNames);
                }
            }
            else
            {
                if((ulUnicodeRange & ulUnicodeRangeBit) != 0)
                {
                    v.Error(T.T_NULL, E.OS_2_E_RangeBitSet, m_tag, "No characters are present in the ranges: " + sRangeNames);
                    bRet = false;
                }
            }

            return bRet;
        }
Example #54
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;
        }
Example #55
0
        /************************
         * public methods
         */


        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            if (v.PerformTest(T.PCLT_TableLength))
            {
                if (GetLength() == 54)
                {
                    v.Pass(T.PCLT_TableLength, P.PCLT_P_TableLength, m_tag);
                }
                else
                {
                    v.Error(T.PCLT_TableLength, E.PCLT_E_TableLength, m_tag, GetLength().ToString());
                    bRet = false;
                }
            }

            if (v.PerformTest(T.PCLT_Version))
            {
                if (Version.GetUint() == 0x00010000)
                {
                    v.Pass(T.PCLT_Version, P.PCLT_P_Version, m_tag);
                }
                else
                {
                    v.Error(T.PCLT_Version, E.PCLT_E_Version, m_tag, "0x"+Version.GetUint().ToString("x8"));
                    bRet = false;
                }
            }

            if (v.PerformTest(T.PCLT_Pitch))
            {
                Table_hmtx hmtxTable = (Table_hmtx)fontOwner.GetTable("hmtx");
                Table_maxp maxpTable = (Table_maxp)fontOwner.GetTable("maxp");
                if (hmtxTable == null)
                {
                    v.Error(T.PCLT_Pitch, E._TEST_E_TableMissing, m_tag, "hmtx");
                    bRet = false;
                }
                else if (maxpTable == null)
                {
                    v.Error(T.PCLT_Pitch, E._TEST_E_TableMissing, m_tag, "maxp");
                    bRet = false;
                }
                else
                {
                    uint iSpaceGlyph = fontOwner.FastMapUnicodeToGlyphID(' ');

                    if (iSpaceGlyph < fontOwner.GetMaxpNumGlyphs())
                    {
                        Table_hmtx.longHorMetric hmSpace = hmtxTable.GetOrMakeHMetric(iSpaceGlyph, fontOwner);
                        if (hmSpace != null)
                        {
                            if (Pitch == hmSpace.advanceWidth)
                            {
                                v.Pass(T.PCLT_Pitch, P.PCLT_P_Pitch, m_tag);
                            }
                            else
                            {
                                string s = "actual = " + Pitch + ", expected = " + hmSpace.advanceWidth;
                                v.Error(T.PCLT_Pitch, E.PCLT_E_Pitch, m_tag, s);
                                bRet = false;
                            }
                        }
                    }
                    else
                    {
                        // JJF Figure out what to do
                        v.Warning(T.PCLT_Pitch, W._TEST_W_ErrorInAnotherTable, m_tag, "can't validate Pitch field, error getting the space glyph");
                        bRet = false;
                    }
                }
            }

            if (v.PerformTest(T.PCLT_Style))
            {
                ushort Posture   = (ushort)(Style      & 0x0003);
                ushort Width     = (ushort)((Style>>2) & 0x0007);
                ushort Structure = (ushort)((Style>>5) & 0x001f);
                ushort Reserved  = (ushort)(Style>>10);

                bool bBitsOk = true;

                if (Posture == 3)
                {
                    v.Error(T.PCLT_Style, E.PCLT_E_Style_Posture, m_tag, "0x"+Style.ToString("x4"));
                    bBitsOk = false;
                    bRet = false;
                }
                if (Width == 5)
                {
                    v.Error(T.PCLT_Style, E.PCLT_E_Style_Width, m_tag, "0x"+Style.ToString("x4"));
                    bBitsOk = false;
                    bRet = false;
                }
                if (Structure > 17)
                {
                    v.Error(T.PCLT_Style, E.PCLT_E_Style_Structure, m_tag, "0x"+Style.ToString("x4"));
                    bBitsOk = false;
                    bRet = false;
                }
                if (Reserved != 0)
                {
                    v.Error(T.PCLT_Style, E.PCLT_E_Style_Reserved, m_tag, "0x"+Style.ToString("x4"));
                    bBitsOk = false;
                    bRet = false;
                }

                if (bBitsOk)
                {
                    v.Pass(T.PCLT_Style, P.PCLT_P_Style, m_tag);
                }

            }

            if (v.PerformTest(T.PCLT_StrokeWeight))
            {
                if (StrokeWeight >= -7 && StrokeWeight <= 7)
                {
                    v.Pass(T.PCLT_StrokeWeight, P.PCLT_P_StrokeWeight, m_tag, StrokeWeight.ToString());
                }
                else
                {
                    v.Error(T.PCLT_StrokeWeight, E.PCLT_E_StrokeWeight, m_tag, StrokeWeight.ToString());
                    bRet = false;
                }
            }

            if (v.PerformTest(T.PCLT_WidthType))
            {
                if (WidthType >= -5 && WidthType <= 5)
                {
                    v.Pass(T.PCLT_WidthType, P.PCLT_P_WidthType, m_tag, WidthType.ToString());
                }
                else
                {
                    v.Error(T.PCLT_WidthType, E.PCLT_E_WidthType, m_tag, WidthType.ToString());
                    bRet = false;
                }
            }

            if (v.PerformTest(T.PCLT_SerifStyle))
            {
                uint bot6 = (uint)SerifStyle & 0x3f;
                uint top2 = (uint)SerifStyle>>6;

                bool bBitsOk = true;

                if (bot6 > 12)
                {
                    v.Error(T.PCLT_SerifStyle, E.PCLT_E_Bottom6, m_tag, "0x"+SerifStyle.ToString("x2"));
                    bBitsOk = false;
                    bRet = false;
                }                
                if (top2 == 0 || top2 == 3)
                {
                    v.Error(T.PCLT_SerifStyle, E.PCLT_E_Top2, m_tag);
                    bBitsOk = false;
                    bRet = false;
                }

                if (bBitsOk)
                {
                    v.Pass(T.PCLT_SerifStyle, P.PCLT_P_SerifStyle, m_tag);
                }
            }

            if (v.PerformTest(T.PCLT_Reserved))
            {
                if (Reserved == 0)
                {
                    v.Pass(T.PCLT_Reserved, P.PCLT_P_Reserved, m_tag);
                }
                else
                {
                    v.Error(T.PCLT_Reserved, E.PCLT_E_Reserved, m_tag, Reserved.ToString());
                    bRet = false;
                }
            }

            return bRet;
        }
Example #56
0
        /************************
         * public methods
         */


        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            ushort numGlyphs = GetNumGlyphs(fontOwner);


            if (v.PerformTest(T.hdmx_Version))
            {
                if (TableVersionNumber == 0)
                {
                    v.Pass(T.hdmx_Version, P.hdmx_P_Version, m_tag);
                }
                else
                {
                    v.Error(T.hdmx_Version, E.hdmx_E_Version, m_tag, TableVersionNumber.ToString());
                    bRet = false;
                }
            }

            bool bNumDeviceRecordsOk = true;
            if (v.PerformTest(T.hdmx_NumDeviceRecords))
            {
                if (NumberDeviceRecords >= 0)
                {
                    v.Pass(T.hdmx_NumDeviceRecords, P.hdmx_P_NumDeviceRecords, m_tag, NumberDeviceRecords.ToString());
                }
                else
                {
                    v.Error(T.hdmx_NumDeviceRecords, E.hdmx_E_NumDeviceRecords_neg, m_tag, NumberDeviceRecords.ToString());
                    bNumDeviceRecordsOk = false;
                    bRet = false;
                }
            }

            bool bSizeOk = true;
            if (v.PerformTest(T.hdmx_SizeofDeviceRecord))
            {

                if ((SizeofDeviceRecord & 3) != 0)
                {
                    v.Error(T.hdmx_SizeofDeviceRecord, E.hdmx_E_SizeofDeviceRecord_alignment, m_tag, SizeofDeviceRecord.ToString());
                    bSizeOk = false;
                    bRet = false;
                }

                uint CalculatedSizeofDeviceRecord = CalculateSizeofDeviceRecord(numGlyphs);

                if (SizeofDeviceRecord != CalculatedSizeofDeviceRecord)
                {
                    string s = "actual = " + SizeofDeviceRecord + ", calc = " + CalculatedSizeofDeviceRecord;
                    v.Error(T.hdmx_SizeofDeviceRecord, E.hdmx_E_SizeofDeviceRecord_numGlyphs, m_tag, s);
                    bSizeOk = false;
                    bRet = false;
                }

                if (bSizeOk)
                {
                    v.Pass(T.hdmx_SizeofDeviceRecord, P.hdmx_P_SizeofDeviceRecord, m_tag, SizeofDeviceRecord.ToString());
                }
            }

            bool bLengthOk = true;
            if (v.PerformTest(T.hdmx_TableLength))
            {
                if (bNumDeviceRecordsOk)
                {
                    uint CalculatedTableLength = 8 + (uint)NumberDeviceRecords * CalculateSizeofDeviceRecord(numGlyphs);
                    if (GetLength() == CalculatedTableLength)
                    {
                        v.Pass(T.hdmx_TableLength, P.hdmx_P_TableLength, m_tag);
                    }
                    else
                    {
                        string s = "actual: " + GetLength() + ", calc: " + CalculatedTableLength;
                        v.Error(T.hdmx_TableLength, E.hdmx_E_TableLength, m_tag, s);
                        bLengthOk = false;
                        bRet = false;
                    }
                }
                else
                {
                    v.Warning(T.hdmx_TableLength, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate table length");
                }
            }

            if (v.PerformTest(T.hdmx_DeviceRecordPadBytesZero))
            {
                if (bSizeOk && bLengthOk & bNumDeviceRecordsOk)
                {
                    uint unpaddedLength = (uint)numGlyphs + 2;
                    if ((unpaddedLength & 3) == 0)
                    {
                        v.Pass(T.hdmx_DeviceRecordPadBytesZero, P.hdmx_P_DeviceRecordPadBytes_none, m_tag);
                    }
                    else
                    {
                        bool bPadOk = true;
                        if (NumberDeviceRecords > 1)
                        {
                            for (uint i=0; i<NumberDeviceRecords; i++)
                            {
                                DeviceRecord dr = GetDeviceRecord(i, numGlyphs);
                                for (uint j=0; j<dr.GetNumPadBytes(); j++)
                                {
                                    if (dr.GetPadByte(j) != 0)
                                    {
                                        bPadOk = false;
                                        break;
                                    }
                                }
                            }
                        }
                        if (bPadOk)
                        {
                            v.Pass(T.hdmx_DeviceRecordPadBytesZero, P.hdmx_P_DeviceRecordPadBytes_zero, m_tag);
                        }
                        else
                        {
                            v.Error(T.hdmx_DeviceRecordPadBytesZero, E.hdmx_E_DeviceRecordPadBytes_nonzero, m_tag);
                            bRet = false;
                        }
                    }
                }
                else
                {
                    v.Warning(T.hdmx_DeviceRecordPadBytesZero, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate that device record padding bytes are zero");
                }
            }

            if (v.PerformTest(T.hdmx_SortedOrder))
            {
                if (bSizeOk && bLengthOk && bNumDeviceRecordsOk)
                {
                    bool bSortOk = true;
                    if (NumberDeviceRecords > 1)
                    {
                        DeviceRecord drCurr = GetDeviceRecord(0, numGlyphs);
                        DeviceRecord drNext = null;
                        for (uint i=1; i<NumberDeviceRecords; i++)
                        {
                            drNext = GetDeviceRecord(i, numGlyphs);
                            if (drCurr.PixelSize >= drNext.PixelSize)
                            {
                                bSortOk = false;
                                break;
                            }
                            drCurr = drNext;
                        }
                    }
                    if (bSortOk)
                    {
                        v.Pass(T.hdmx_SortedOrder, P.hdmx_P_SortedOrder, m_tag);
                    }
                    else
                    {
                        v.Error(T.hdmx_SortedOrder, E.hdmx_E_SortedOrder, m_tag);
                        bRet = false;
                    }
                }
                else
                {
                    v.Warning(T.hdmx_SortedOrder, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate that device records are in sorted order");
                }
            }

            if (v.PerformTest(T.hdmx_DuplicateDeviceRecords))
            {
                if (bSizeOk && bLengthOk && bNumDeviceRecordsOk)
                {
                    bool bNoDup = true;
                    if (NumberDeviceRecords > 1)
                    {
                        for (uint i=0; i<NumberDeviceRecords-1; i++)
                        {
                            DeviceRecord dr1 = GetDeviceRecord(i, numGlyphs);
                            for (uint j=i+1; j<NumberDeviceRecords; j++)
                            {
                                DeviceRecord dr2 = GetDeviceRecord(j, numGlyphs);
                                if (dr1.PixelSize == dr2.PixelSize)
                                {
                                    bNoDup = false;
                                    break;
                                }
                            }
                        }
                    }
                    if (bNoDup)
                    {
                        v.Pass(T.hdmx_DuplicateDeviceRecords, P.hdmx_P_DuplicateDeviceRecords, m_tag);
                    }
                    else
                    {
                        v.Error(T.hdmx_DuplicateDeviceRecords, E.hdmx_E_DuplicateDeviceRecords, m_tag);
                        bRet = false;
                    }
                }
                else
                {
                    v.Warning(T.hdmx_DuplicateDeviceRecords, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate that there are no duplicate device records");
                }
            }

            if (v.PerformTest(T.hdmx_Widths))
            {
                if (bSizeOk && bLengthOk && bNumDeviceRecordsOk)
                {
                    bool bWidthsOk = true;
                    RasterInterf.DevMetricsData dmd = null;
                    try
                    {
                        Version ver = fontOwner.GetFile().GetRasterizer().FTVersion;

                        if ( ver.CompareTo(new Version(2,6,1)) < 0 )
                            v.Warning(T.hdmx_Widths, W.hdmx_W_Need_Newer_FreeType, m_tag,
                                      "Using FreeType Version " + ver + " may not get correct results for HDMX");

                        dmd = fontOwner.GetCalculatedDevMetrics();
                    }
                    catch (Exception e)
                    {
                        v.ApplicationError(T.hdmx_Widths, E._Table_E_Exception, m_tag, e.Message);
                        bRet = false;
                    }

                    if (dmd != null)
                    {
                        for (uint i=0; i<NumberDeviceRecords; i++)
                        {
                            DeviceRecord dr = GetDeviceRecord(i, numGlyphs);

                            for (uint iGlyph=0; iGlyph<numGlyphs; iGlyph++)
                            {

                                if (dr.GetWidth(iGlyph) != dmd.hdmxData.Records[i].Widths[iGlyph])
                                {

                                    String sDetails = "rec " + i + ", PixelSize " + dr.PixelSize + ", glyph# " + iGlyph 
                                        + ", width = " + dr.GetWidth(iGlyph) + ", calc = " + dmd.hdmxData.Records[i].Widths[iGlyph];
                                    v.Error(T.hdmx_Widths, E.hdmx_E_Widths, m_tag, sDetails);
                                    bWidthsOk = false;
                                    bRet = false;
                                }
                            }

                        }

                        if (bWidthsOk)
                        {
                            v.Pass(T.hdmx_Widths, P.hdmx_P_Widths, m_tag);
                        }
                    }
                    else
                    {
                        // if user didn't cancel, then check for error message
                        if (!v.CancelFlag)
                        {
                            String sDetails = null;
                            try
                            {
                                sDetails = fontOwner.GetDevMetricsDataError();
                            }
                            catch (Exception e)
                            {
                                v.ApplicationError(T.hdmx_Widths, E._Table_E_Exception, m_tag, e.Message);
                            }
                            Debug.Assert(sDetails != null);
                            v.Error(T.hdmx_Widths, E.hdmx_E_Rasterizer, m_tag, sDetails);
                            bRet = false;
                        }                    
                    }

                }
                else
                {
                    v.Warning(T.hdmx_Widths, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate that the widths are correct");
                }
            }

            return bRet;
        }
Example #57
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;
        }
Example #58
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;
        }
Example #59
0
        /************************
         * public methods
         */


        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

            if (v.PerformTest(T.VDMX_Version))
            {
                if (version == 0 || version == 1)
                {
                    v.Pass(T.VDMX_Version, P.VDMX_P_Version, m_tag, version.ToString());
                }
                else
                {
                    v.Error(T.VDMX_Version, E.VDMX_E_Version, m_tag, version.ToString());
                    bRet = false;
                }
            }

            if (v.PerformTest(T.VDMX_Offsets))
            {
                bool bOffsetsOk = true;
                
                ushort minPossibleOffset = (ushort)((ushort)FieldOffsets.ratRange + numRatios * 4 + numRatios*2);
                ushort maxPossibleOffset = (ushort)GetLength();

                for (uint i=0; i<numRatios; i++)
                {
                    ushort offset = GetVdmxGroupOffset(i);
                    if (offset < minPossibleOffset || offset > maxPossibleOffset)
                    {
                        v.Error(T.VDMX_Offsets, E.VDMX_E_InvalidOffset, m_tag, "#" + i + " offset = " + offset);
                        bOffsetsOk = false;
                        bRet = false;
                    }
                }

                if (bOffsetsOk)
                {
                    v.Pass(T.VDMX_Offsets, P.VDMX_P_Offsets, m_tag);
                }
            }

            if (v.PerformTest(T.VDMX_GroupsInTable))
            {
                bool bGroupsOk = true;

                for (uint i=0; i<numRatios; i++)
                {
                    Vdmx vdmx = GetVdmxGroup(i);
                    uint EndOffset = (uint)GetVdmxGroupOffset(i) + 4 + (uint)vdmx.recs*6;

                    if (EndOffset > GetLength())
                    {
                        v.Error(T.VDMX_GroupsInTable, E.VDMX_E_GroupsInTable, m_tag, "group# " + i);
                        bGroupsOk = false;
                        bRet = false;
                    }
                }

                if (bGroupsOk)
                {
                    v.Pass(T.VDMX_GroupsInTable, P.VDMX_P_GroupsInTable, m_tag);
                }
            }

            if (v.PerformTest(T.VDMX_CompareToCalcData))
            {
                bool bDataOk = true;
                bool needtol = false;

                RasterInterf.DevMetricsData dmd = null;

                try
                {
                    Version ver = fontOwner.GetFile().GetRasterizer().FTVersion;

                    if ( ver.CompareTo(new Version(2,6,1)) < 0 )
                        v.Warning(T.VDMX_CompareToCalcData, W.VDMX_W_Need_Newer_FreeType, m_tag,
                                  "Using FreeType Version " + ver + " may not get correct results for VDMX");

                    dmd = fontOwner.GetCalculatedDevMetrics();
                }
                catch (InvalidOperationException e)
                {
                    // JJF Figure out what to do. Changed to warning
                    v.Warning(T.VDMX_CompareToCalcData, W._TEST_W_ErrorInAnotherTable, m_tag, e.Message);
                }
                catch(Exception e)
                {
                    v.ApplicationError(T.VDMX_CompareToCalcData, E._Table_E_Exception, m_tag, e.Message);
                    bRet = false;
                }

                if (dmd != null)
                {
                    for (uint iRatio=0; iRatio<numRatios; iRatio++)
                    {
                        Ratios ratio = GetRatioRange(iRatio);
                        Vdmx group = GetVdmxGroup(iRatio);

                        for (uint iEntry=0; iEntry<group.recs; iEntry++)
                        {
                            Vdmx.vTable vTableEntry = group.GetEntry(iEntry);

                            if (vTableEntry.yPelHeight <= 255)
                            {
                                if (vTableEntry.yPelHeight == dmd.vdmxData.groups[iRatio].entry[vTableEntry.yPelHeight - group.startsz].yPelHeight)
                                {
                                    
                                    if (vTableEntry.yMin != dmd.vdmxData.groups[iRatio].entry[iEntry].yMin
                                        || vTableEntry.yMax != dmd.vdmxData.groups[iRatio].entry[iEntry].yMax){

                                        int dif = dmd.vdmxData.groups[iRatio].entry[iEntry].yMax - dmd.vdmxData.groups[iRatio].entry[iEntry].yMin;

                                        if (!TestTolerance(dmd.vdmxData.groups[iRatio].entry[iEntry].yMin, vTableEntry.yMin, dif) ||
                                         !TestTolerance(dmd.vdmxData.groups[iRatio].entry[iEntry].yMax, vTableEntry.yMax, dif))
                                        {

                                            String sDetails = "group[" + iRatio + "], entry[" + iEntry + "], yPelHeight = " + vTableEntry.yPelHeight +
                                                ", yMin,yMax = " + vTableEntry.yMin + "," + vTableEntry.yMax +
                                                ", calculated yMin,yMax = " + dmd.vdmxData.groups[iRatio].entry[iEntry].yMin + "," +
                                                dmd.vdmxData.groups[iRatio].entry[iEntry].yMax;
                                            v.Error(T.VDMX_CompareToCalcData, E.VDMX_E_CalcData, m_tag, sDetails);

                                            bDataOk = false;

                                        }
                                        else
                                        {
                                            needtol = true;
                                        }
                                    }
                                    /*
                                    else
                                    {
                                        String s = "group[" + iRatio + "], yPelHeight = " + vTableEntry.yPelHeight + ", entry OK";
                                        v.DebugMsg(s, m_tag);
                                    }
                                    */
                                }
                                else
                                {
                                    Debug.Assert(false);
                                }
                            }
                            else
                            {
                                String sDetails = "group[" + iRatio + "], entry[" + iEntry + "], yPelHeight = " + vTableEntry.yPelHeight;
                                v.Error(T.VDMX_CompareToCalcData, E.VDMX_E_yPelHeight_illegal, m_tag, sDetails);
                                bDataOk = false;
                            }
                        }
                    }

                    if (bDataOk)
                    {
                        if (needtol)
                        {
                            String sDetails = "The differences were smaller than the tolerance, so they may well be valid if the VDMX was hand-tuned";
                            v.Warning(T.VDMX_CompareToCalcData, W.VDMX_W_CalcData, m_tag, sDetails);
                        }
                        else
                        {
                            v.Pass(T.VDMX_CompareToCalcData, P.VDMX_P_CalcData, m_tag);
                        }
                    }
                    else
                    {
                        //v.Error(T.VDMX_CompareToCalcData, E.VDMX_E_CalcData, m_tag);
                        bRet = false;
                    }
                }
                else
                {
                    // Rasterization could not occur for various reasons.
                    string s = "Unable to get calculated device metrics.";
                    v.Error(T.VDMX_CompareToCalcData, E.VDMX_E_CalcData, m_tag, s);
                    bDataOk = false;
                    bRet = false;
                }
            }

            return bRet;
        }
Example #60
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;
        }