示例#1
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;
        }
示例#2
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);
        }
示例#3
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);
            }
示例#4
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);
            }
示例#5
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 CheckTableAlignment(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.offset & 0x03) != 0)
                    {
                        v.Warning(T.T_NULL, W._DE_W_TableAlignment, null, (string)de.tag);
                        //bRet = false;
                    }
                }

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

            return(bRet);
        }
示例#7
0
        private bool ValidateGlyfPartiallyUnreferenced(Validator validator,
                                                       OTFont fontOwner)
        {
            int numEntry = this.NumEntry(fontOwner);

            if (numEntry == Table_loca.ValueInvalid)
            {
                validator.Warning(T.T_NULL, W.loca_W_GlyfPartiallyUnreferenced, this.m_tag);
                return(false);
            }
            int offsLast;

            if (!this.GetGlyfOffset(numEntry - 1, out offsLast, validator, fontOwner))
            {
                validator.Warning(T.T_NULL, W.loca_W_GlyfPartiallyUnreferenced, this.m_tag);
                return(false);
            }
            int lengthGlyf = this.LengthGlyf(fontOwner);

            if (lengthGlyf == Table_loca.ValueInvalid)
            {
                validator.Warning(T.T_NULL, W.loca_W_GlyfPartiallyUnreferenced, this.m_tag);
                return(false);
            }
            if (lengthGlyf != offsLast)
            {
                validator.Warning(T.T_NULL, W.loca_W_GlyfPartiallyUnreferenced, this.m_tag);
                return(false);
            }
            validator.Pass(P.loca_P_GlyfPartiallyUnreferenced, this.m_tag);
            return(true);
        }
示例#8
0
            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;
            }
示例#9
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);
            }
        }
示例#10
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;
        }
示例#11
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;
     }
 }
示例#12
0
        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);
        }
示例#13
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);
            }
示例#14
0
        bool Validate_indexSubTable(Validator v, indexSubTable ist, indexSubTableArray ista, string sID, OTFontVal fontOwner)
        {
            bool bOk = true;

            if (!Validate_indexSubHeader(v, ist.header, sID, fontOwner))
            {
                bOk = false;
            }

            switch (ist.header.indexFormat)
            {
            case 1:
                if (!Validate_indexSubTable_format1(v, (indexSubTable1)ist, ista, sID, fontOwner))
                {
                    bOk = false;
                }
                break;

            case 2:
                if (!Validate_indexSubTable_format2(v, (indexSubTable2)ist, ista, sID, fontOwner))
                {
                    bOk = false;
                }
                break;

            case 3:
                if (!Validate_indexSubTable_format3(v, (indexSubTable3)ist, ista, sID, fontOwner))
                {
                    bOk = false;
                }
                break;

            case 4:
                if (!Validate_indexSubTable_format4(v, (indexSubTable4)ist, ista, sID, fontOwner))
                {
                    bOk = false;
                }
                break;

            case 5:
                if (!Validate_indexSubTable_format5(v, (indexSubTable5)ist, ista, sID, fontOwner))
                {
                    bOk = false;
                }
                break;

            default:
                Debug.Assert(false, "illegal index format", "format = " + ist.header.indexFormat);
                break;
            }

            if (bOk)
            {
                v.Pass(T.EBLC_indexSubTables, P.EBLC_P_indexSubTables, m_tag, sID);
            }

            return(bOk);
        }
示例#15
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;
        }
示例#16
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);
        }
示例#17
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);
            }
示例#18
0
        protected bool CheckForRecommendedTables(Validator v)
        {
            bool bRet = true;

            bool bMissing = false;

            if (!IsPostScript())
            {
                if (GetDirectoryEntry("gasp") == null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "gasp");
                    bMissing = true;
                }

                Table_hmtx hmtxTable = (Table_hmtx)GetTable("hmtx");
                if (hmtxTable != null)
                {
                    if (!hmtxTable.IsMonospace(this) && !ContainsSymbolsOnly())
                    {
                        if (GetDirectoryEntry("kern") == null)
                        {
                            v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "kern");
                            bMissing = true;
                        }

                        if (GetDirectoryEntry("hdmx") == null)
                        {
                            v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "hdmx");
                            bMissing = true;
                        }
                    }
                }

                if (GetDirectoryEntry("VDMX") == null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "VDMX");
                    bMissing = true;
                }
            }

            if (GetDirectoryEntry("DSIG") == null && !GetFile().IsCollection())
            {
                v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "DSIG");
                bMissing = true;
            }

            if (!bMissing)
            {
                v.Pass(P._FONT_P_MissingRecommendedTable, null);
            }

            return(bRet);
        }
示例#19
0
        private bool ValidateGlyfEntryLengthAlignment(Validator validator,
                                                      OTFont fontOwner)
        {
            int cntWarn  = 0;
            int numEntry = this.NumEntry(fontOwner);

            if (numEntry == Table_loca.ValueInvalid)
            {
                if (validator != null)
                {
                    validator.Warning(T.T_NULL, W.loca_W_GlyfEntryLengthAlignment,
                                      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)))
                {
                    cntWarn++;
                    continue;
                }
                if (((offsGlyfNext - offsGlyfCur) % 4) != 0)
                {
                    cntWarn++;
                }
            }
            if (validator != null)
            {
                if (cntWarn == 0)
                {
                    validator.Pass(P.loca_P_GlyfEntryLengthAlignment, m_tag);
                }
                else
                {
                    validator.Warning(T.T_NULL, W.loca_W_GlyfEntryLengthAlignment,
                                      m_tag,
                                      "Number of glyphs with the warning = " + cntWarn);
                }
            }
            return(cntWarn == 0);
        }
示例#20
0
        private bool ValidateGlyfEntryEmpty(Validator validator,
                                            OTFont fontOwner)
        {
            int cntInfo  = 0;
            int numEntry = this.NumEntry(fontOwner);

            if (numEntry == Table_loca.ValueInvalid)
            {
                if (validator != null)
                {
                    validator.Warning(T.T_NULL, W._TEST_W_OtherErrorsInTable,
                                      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)))
                {
                    cntInfo++;
                    continue;
                }
                if (offsGlyfNext == offsGlyfCur)
                {
                    cntInfo++;
                }
            }
            if (validator != null)
            {
                if (cntInfo == 0)
                {
                    validator.Pass(P.loca_P_GlyfEntryEmpty, m_tag);
                }
                else
                {
                    validator.Info(T.T_NULL, I.loca_I_GlyfEntryEmpty,
                                   m_tag,
                                   "Number of glyphs that are empty = " + cntInfo);
                }
            }
            return(cntInfo == 0);
        }
示例#21
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);
        }
示例#22
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);
            }
示例#23
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;
        }
示例#24
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);
        }
示例#25
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;
            }
        }
示例#26
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);
            }
示例#27
0
        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);
        }
示例#28
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);
            }
        }
示例#29
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);
            }
示例#30
0
        protected bool CheckForNoUnnecessaryTables(Validator v)
        {
            bool bRet = true;

            bool bFoundUnnecessary = false;

            Table_hmtx hmtxTable = (Table_hmtx)GetTable("hmtx");
            if (hmtxTable != null)
            {
                if (hmtxTable.IsMonospace(this))
                {
                    if (GetDirectoryEntry("hdmx") != null)
                    {
                        v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "hdmx table not needed for monospaced font");
                        bFoundUnnecessary = true;
                    }

                    if (GetDirectoryEntry("LTSH") != null)
                    {
                        v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "LTSH table not needed for monospaced font");
                        bFoundUnnecessary = true;
                    }

                    if (GetDirectoryEntry("kern") != null)
                    {
                        v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "kern table not needed for monospaced font");
                        bFoundUnnecessary = true;
                    }
                }

                if (GetDirectoryEntry("CFF ") == null && GetDirectoryEntry("VORG") != null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "VORG table not needed, it may optionally be present for fonts with Postscript outlines");
                    bFoundUnnecessary = true;
                }

                if (GetDirectoryEntry("PCLT") != null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "PCLT table not needed, Microsoft no longer recommends including this table");
                    bFoundUnnecessary = true;
                }
            }

            if (GetDirectoryEntry("CFF ") != null)
            {
                string [] UnnecessaryTables = {"glyf", "fpgm", "cvt ", "loca", "prep"};

                for (int i=0; i<UnnecessaryTables.Length; i++)
                {
                    if (GetDirectoryEntry(UnnecessaryTables[i]) != null)
                    {
                        v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, UnnecessaryTables[i] + " not needed since the font contains a 'CFF ' table");
                        bFoundUnnecessary = true;
                    }
                }
            }

            if (GetDirectoryEntry("glyf") != null)
            {
                if (GetDirectoryEntry("CFF ") != null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "CFF not needed since the font contains a 'CFF ' table");
                    bFoundUnnecessary = true;
                }
            }

            if (ContainsLatinOnly())
            {
                if (GetDirectoryEntry("vhea") != null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "vhea not needed since the font only contains Latin characters");
                    bFoundUnnecessary = true;
                }

                if (GetDirectoryEntry("vmtx") != null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "vmtx not needed since the font only contains Latin characters");
                    bFoundUnnecessary = true;
                }
            }

            if (!bFoundUnnecessary)
            {
                v.Pass(P._FONT_P_UnnecessaryTable, null);
            }

            return bRet;
        }
示例#31
0
        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;
        }
示例#32
0
        protected bool CheckForRequiredTables(Validator v)
        {
            bool bRet = true;

            string [] RequiredTables =
                {"cmap", "head", "hhea", "hmtx", "maxp", "name", "OS/2", "post"};

            for (int i=0; i<RequiredTables.Length; i++)
            {
                if (GetDirectoryEntry(RequiredTables[i]) == null)
                {
                    v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, RequiredTables[i]);
                    bRet = false;
                }
            }

            if (GetDirectoryEntry("glyf") == null && GetDirectoryEntry("CFF ") == null && GetDirectoryEntry("EBDT") == null && GetDirectoryEntry("CBDT") == null)
            {
                v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "Font must contain either a 'glyf', 'CFF ', 'EBDT' or 'CBDT' table");
                bRet = false;
            }

            if (GetDirectoryEntry("glyf") != null)
            {
                string [] RequiredGlyphTables = {"loca"};

                for (int i=0; i<RequiredGlyphTables.Length; i++)
                {
                    if (GetDirectoryEntry(RequiredGlyphTables[i]) == null)
                    {
                        v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, RequiredGlyphTables[i] + " is required since the font contains a glyf table");
                        bRet = false;
                    }
                }
            }

            if (GetDirectoryEntry("EBDT") != null)
            {
                if (GetDirectoryEntry("EBLC") == null)
                {
                    v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBLC is required since the font contains an EBDT table");
                    bRet = false;
                }
            }

            if (GetDirectoryEntry("EBLC") != null)
            {
                if (GetDirectoryEntry("EBDT") == null)
                {
                    v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBDT is required since the font contains an EBLC table");
                    bRet = false;
                }
            }

            if (GetDirectoryEntry("EBSC") != null)
            {
                if (GetDirectoryEntry("EBDT") == null)
                {
                    v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBDT is required since the font contains an EBSC table");
                    bRet = false;
                }
                if (GetDirectoryEntry("EBLC") == null)
                {
                    v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBLC is required since the font contains an EBSC table");
                    bRet = false;
                }
            }

            if (bRet)
            {
                v.Pass(P._FONT_P_MissingRequiredTable, null);
            }

            return bRet;
        }
示例#33
0
        private bool CheckUnicodeRanges(Validator v, OTFont fontOwner)
        {
            bool bRet = true;
            bool bOk = true;

            if (version == 0)
            {
                if (ulUnicodeRange1 != 0)
                {
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[0] was undefined. All bits must be 0.");
                    bOk = false;
                }
                if (ulUnicodeRange2 != 0)
                {
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[1] was undefined. All bits must be 0.");
                    bOk = false;
                }
                if (ulUnicodeRange3 != 0)
                {
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[2] was undefined. All bits must be 0.");
                    bOk = false;
                }
                if (ulUnicodeRange4 != 0)
                {
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[3] was undefined. All bits must be 0.");
                    bOk = false;
                }

                if (bOk)
                {
                    v.Pass(P.OS_2_P_UnicodeRanges, m_tag);
                }
                else
                {
                    bRet = false;
                }

                return bRet;
            }

            // count the number of entries in each unicode range in the cmap subtable

            UnicodeRanges ur = new UnicodeRanges();
            for (uint c = 0; c < 0xffff; c++)
            {
                // check if c is mapped to a glyph
                uint iGlyph = fontOwner.FastMapUnicodeToGlyphID((char)c);
                if (iGlyph != 0)
                {
                    UnicodeRanges.Range r = ur.GetRange(c);
                    if (r != null)
                    {
                        r.count++;
                    }
                }
            }

            uint nCharsInRange;

            // bit 0
            uint BASIC_LATIN_LOW                     = 0x0020;
            nCharsInRange = ur.GetRange(BASIC_LATIN_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000001, nCharsInRange, "Basic Latin");

            // bit 1
            uint LATIN_1_SUPPLEMENT_LOW                = 0x00A0;
            nCharsInRange = ur.GetRange(LATIN_1_SUPPLEMENT_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000002, nCharsInRange, "Latin-1 Supplement");

            // bit 2
            uint LATIN_EXTENDED_A_LOW                = 0x0100;
            nCharsInRange = ur.GetRange(LATIN_EXTENDED_A_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000004, nCharsInRange, "Latin Extended-A");

            // bit 3
            uint LATIN_EXTENDED_B_LOW                = 0x0180;
            nCharsInRange = ur.GetRange(LATIN_EXTENDED_B_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000008, nCharsInRange, "Latin Extended-B");

            // bit 4
            uint IPA_EXTENSIONS_LOW                    = 0x0250;
            uint Phonetic_Extensions                   = 0x1D00;
            uint Phonetic_Extensions_Supplement        = 0x1D80;
            nCharsInRange = ur.GetRange(IPA_EXTENSIONS_LOW).count
                + ur.GetRange(Phonetic_Extensions).count
                + ur.GetRange(Phonetic_Extensions_Supplement).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000010, nCharsInRange, "IPA Extensions");

            // bit 5
            uint SPACING_MODIFIER_LETTERS_LOW        = 0x02B0;
            uint Modifier_Tone_Letters               = 0xA700;
            nCharsInRange = ur.GetRange(SPACING_MODIFIER_LETTERS_LOW).count
                + ur.GetRange(Modifier_Tone_Letters).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000020, nCharsInRange, "Spacing Modifier Letters");

            // bit 6
            uint COMBINING_DIACRITICAL_MARKS_LOW     = 0x0300;
            uint Combining_Diacritical_Marks_Supplement = 0x1DC0;
            nCharsInRange = ur.GetRange(COMBINING_DIACRITICAL_MARKS_LOW).count
                + ur.GetRange(Combining_Diacritical_Marks_Supplement).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000040, nCharsInRange, "Combining Diacritical Marks");

            // bit 7
            uint GREEK_LOW                             = 0x0370;
            nCharsInRange = ur.GetRange(GREEK_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000080, nCharsInRange, "Greek");

            // v1: Greek Symbols and Coptic
            // v2/v3: Reserved for Unicode SubRanges
            // v4: Coptic                                  2C80-2CFF
            if (version > 1 && version < 4)
            {
                // bit 8 reserved
                if ((ulUnicodeRange1 & 0x00000100) != 0)
                {
                    bOk = false;
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #8");
                }
            }
            // TODO: v4

            // bit 9
            uint CYRILLIC_LOW                        = 0x0400;
            uint CYRILLIC_SUPPLEMENTARY_LOW         = 0x0500;
            uint Cyrillic_Extended_A                = 0x2DE0;
            uint Cyrillic_Extended_B                = 0xA640;
            nCharsInRange = ur.GetRange(CYRILLIC_LOW).count
                          + ur.GetRange(CYRILLIC_SUPPLEMENTARY_LOW).count
                + ur.GetRange(Cyrillic_Extended_A).count
                + ur.GetRange(Cyrillic_Extended_B).count;
            bOk &= VerifyUnicodeRanges(v, ulUnicodeRange1, 0x00000200, nCharsInRange, "Cyrillic, Cyrillic Supplementary");

            // bit 10
            uint ARMENIAN_LOW                        = 0x0530;
            nCharsInRange = ur.GetRange(ARMENIAN_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000400, nCharsInRange, "Armenian");

            // bit 11
            uint HEBREW_LOW                            = 0x0590;
            nCharsInRange = ur.GetRange(HEBREW_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000800, nCharsInRange, "Hebrew");

            // v1: Hebrew Extended (A and B blocks combined)
            // v2/v3: Reserved for Unicode SubRanges
            // v4: Vai                                     A500-A63F
            if (version > 1 && version < 4)
            {
                // bit 12 reserved
                if ((ulUnicodeRange1 & 0x00001000) != 0)
                {
                    bOk = false;
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #12");
                }
            }
            // TODO: v4

            // bit 13
            uint ARABIC_LOW                            = 0x0600;
            uint Arabic_Supplement                     = 0x0750;
            nCharsInRange = ur.GetRange(ARABIC_LOW).count
                + ur.GetRange(Arabic_Supplement).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00002000, nCharsInRange, "Arabic");

            // v1: Arabic Extended
            // v2/v3: Reserved for Unicode SubRanges
            // v4: NKo                                     07C0-07FF
            if (version > 1 && version < 4)
            {
                // bit 14 reserved
                if ((ulUnicodeRange1 & 0x00004000) != 0)
                {
                    bOk = false;
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #14");
                }
            }
            // TODO: v4

            // bit 15
            uint DEVANAGARI_LOW                        = 0x0900;
            nCharsInRange = ur.GetRange(DEVANAGARI_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00008000, nCharsInRange, "Devanagari");

            // bit 16
            uint BENGALI_LOW                         = 0x0980;
            nCharsInRange = ur.GetRange(BENGALI_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00010000, nCharsInRange, "Bengali");

            // bit 17
            uint GURMUKHI_LOW                        = 0x0A00;
            nCharsInRange = ur.GetRange(GURMUKHI_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00020000, nCharsInRange, "Gurmukhi");

            // bit 18
            uint GUJARATI_LOW                        = 0x0A80;
            nCharsInRange = ur.GetRange(GUJARATI_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00040000, nCharsInRange, "Gujarati");

            // bit 19
            uint ORIYA_LOW                            = 0x0B00;
            nCharsInRange = ur.GetRange(ORIYA_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00080000, nCharsInRange, "Oriya");

            // bit 20
            uint TAMIL_LOW                            = 0x0B80;
            nCharsInRange = ur.GetRange(TAMIL_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00100000, nCharsInRange, "Tamil");

            // bit 21
            uint TELUGU_LOW                            = 0x0C00;
            nCharsInRange = ur.GetRange(TELUGU_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00200000, nCharsInRange, "Telugu");

            // bit 22
            uint KANNADA_LOW                         = 0x0C80;
            nCharsInRange = ur.GetRange(KANNADA_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00400000, nCharsInRange, "Kannada");

            // bit 23
            uint MALAYALAM_LOW                        = 0x0D00;
            nCharsInRange = ur.GetRange(MALAYALAM_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00800000, nCharsInRange, "Malayalam");

            // bit 24
            uint THAI_LOW                            = 0x0E00;
            nCharsInRange = ur.GetRange(THAI_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x01000000, nCharsInRange, "Thai");

            // bit 25
            uint LAO_LOW                             = 0x0E80;
            nCharsInRange = ur.GetRange(LAO_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x02000000, nCharsInRange, "Lao");

            // v3: Georgian
            // v4: Georgian                                10A0-10FF
            //     Georgian Supplement                     2D00-2D2F
            // TODO: v4
            // bit 26
            uint GEORGIAN_LOW                        = 0x10A0;
            uint Georgian_Supplement                 = 0x2D00;
            nCharsInRange = ur.GetRange(GEORGIAN_LOW).count
                + ur.GetRange(Georgian_Supplement).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x04000000, nCharsInRange, "Georgian");

            // v1: Georgian Extended
            // v2/v3: Reserved for Unicode SubRanges
            // v4: Balinese                                1B00-1B7F
            if (version > 1 && version < 4)
            {
                // bit 27 reserved
                if ((ulUnicodeRange1 & 0x08000000) != 0)
                {
                    bOk = false;
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #27");
                }
            }
            // TODO: v4

            // bit 28
            uint HANGUL_JAMO_LOW                     = 0x1100;
            nCharsInRange = ur.GetRange(HANGUL_JAMO_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x10000000, nCharsInRange, "Hangul Jamo");

            // bit 29
            uint LATIN_EXTENDED_ADDITIONAL_LOW        = 0x1E00;
            uint Latin_Extended_C                     = 0x2C60;
            uint Latin_Extended_D                     = 0xA720;
            nCharsInRange = ur.GetRange(LATIN_EXTENDED_ADDITIONAL_LOW).count
                + ur.GetRange(Latin_Extended_C).count
                + ur.GetRange(Latin_Extended_D).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x20000000, nCharsInRange, "Latin Extended Additional");

            // bit 30
            uint GREEK_EXTENDED_LOW                    = 0x1F00;
            nCharsInRange = ur.GetRange(GREEK_EXTENDED_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x40000000, nCharsInRange, "Greek Extended");

            // bit 31
            uint GENERAL_PUNCTUATION_LOW             = 0x2000;
            uint Supplemental_Punctuation            = 0x2E00;
            nCharsInRange = ur.GetRange(GENERAL_PUNCTUATION_LOW).count
                + ur.GetRange(Supplemental_Punctuation).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x80000000, nCharsInRange, "General Punctuation");

            // bit 32
            uint SUPER_SUB_SCRIPTS_LOW                = 0x2070;
            nCharsInRange = ur.GetRange(SUPER_SUB_SCRIPTS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000001, nCharsInRange, "Superscripts and Subscripts");

            // bit 33
            uint CURRENCY_SYMBOLS_LOW                = 0x20A0;
            nCharsInRange = ur.GetRange(CURRENCY_SYMBOLS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000002, nCharsInRange, "Currency Symbols");

            // bit 34
            uint SYMBOL_COMBINING_MARKS_LOW            = 0x20D0;
            nCharsInRange = ur.GetRange(SYMBOL_COMBINING_MARKS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000004, nCharsInRange, "Combining Diacritical marks for symbols");

            // bit 35
            uint LETTERLIKE_SYMBOLS_LOW                = 0x2100;
            nCharsInRange = ur.GetRange(LETTERLIKE_SYMBOLS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000008, nCharsInRange, "Letterlike Symbols");

            // bit 36
            uint NUMBER_FORMS_LOW                    = 0x2150;
            nCharsInRange = ur.GetRange(NUMBER_FORMS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000010, nCharsInRange, "Number Forms");

            // bit 37
            uint ARROWS_LOW                            = 0x2190;
            uint SUPPLEMENTAL_ARROWS_A_LOW            = 0x27F0;
            uint SUPPLEMENTAL_ARROWS_B_LOW            = 0x2900;
            uint Miscellaneous_Symbols_and_Arrows     = 0x2B00;
            nCharsInRange = ur.GetRange(ARROWS_LOW).count
                          + ur.GetRange(SUPPLEMENTAL_ARROWS_A_LOW).count
                          + ur.GetRange(SUPPLEMENTAL_ARROWS_B_LOW).count
                + ur.GetRange(Miscellaneous_Symbols_and_Arrows).count;
            bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x00000020, nCharsInRange, "Arrows, Supplementary Arrows A, Supplementary Arrows B");

            // bit 38
            uint MATH_OPERATORS_LOW                    = 0x2200;
            uint SUPPLEMENTAL_MATH_OPERATORS_LOW    = 0x2A00;
            uint MISC_MATH_SYMBOLS_A_LOW            = 0x27C0;
            uint MISC_MATH_SYMBOLS_B_LOW            = 0x2980;
            nCharsInRange = ur.GetRange(MATH_OPERATORS_LOW).count
                          + ur.GetRange(SUPPLEMENTAL_MATH_OPERATORS_LOW).count
                          + ur.GetRange(MISC_MATH_SYMBOLS_A_LOW).count
                          + ur.GetRange(MISC_MATH_SYMBOLS_B_LOW).count;
            bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x00000040, nCharsInRange, "Mathematical Operators, Supplemental Mathematical Operators, Mathematical Symbols A, Mathematical Symbols B");

            // bit 39
            uint MISC_TECHNICAL_LOW                    = 0x2300;
            nCharsInRange = ur.GetRange(MISC_TECHNICAL_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000080, nCharsInRange, "Miscellaneous Technical");

            // bit 40
            uint CONTROL_PICTURES_LOW                = 0x2400;
            nCharsInRange = ur.GetRange(CONTROL_PICTURES_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000100, nCharsInRange, "Control Pictures");

            // bit 41
            uint OCR_LOW                             = 0x2440;
            nCharsInRange = ur.GetRange(OCR_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000200, nCharsInRange, "Optical Character Recognition");

            // bit 42
            uint ENCLOSED_ALPHANUMERICS_LOW            = 0x2460;
            nCharsInRange = ur.GetRange(ENCLOSED_ALPHANUMERICS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000400, nCharsInRange, "Enclosed Alphanumerics");

            // bit 43
            uint BOX_DRAWING_LOW                     = 0x2500;
            nCharsInRange = ur.GetRange(BOX_DRAWING_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000800, nCharsInRange, "Box Drawing");

            // bit 44
            uint BLOCK_ELEMENTS_LOW                    = 0x2580;
            nCharsInRange = ur.GetRange(BLOCK_ELEMENTS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00001000, nCharsInRange, "Block Elements");

            // bit 45
            uint GEOMETRIC_SHAPES_LOW                = 0x25A0;
            nCharsInRange = ur.GetRange(GEOMETRIC_SHAPES_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00002000, nCharsInRange, "Geometric Shapes");

            // bit 46
            uint MISC_SYMBOLS_LOW                    = 0x2600;
            nCharsInRange = ur.GetRange(MISC_SYMBOLS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00004000, nCharsInRange, "Miscellaneous Symbols");

            // bit 47
            uint DINGBATS_LOW                        = 0x2700;
            nCharsInRange = ur.GetRange(DINGBATS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00008000, nCharsInRange, "Dingbats");

            // bit 48
            uint CJK_SYMBOLS_PUNCTUATION_LOW         = 0x3000;
            nCharsInRange = ur.GetRange(CJK_SYMBOLS_PUNCTUATION_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00010000, nCharsInRange, "CJK Symbols and Punctuation");

            // bit 49
            uint HIRAGANA_LOW                        = 0x3040;
            nCharsInRange = ur.GetRange(HIRAGANA_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00020000, nCharsInRange, "Hiragana");

            // bit 50
            uint KATAKANA_LOW                        = 0x30A0;
            uint Katakana_Phonetic_Extensions        = 0x31F0;
            nCharsInRange = ur.GetRange(KATAKANA_LOW).count
                + ur.GetRange(Katakana_Phonetic_Extensions).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00040000, nCharsInRange, "Katakana");

            // bit 51
            uint BOPOMOFO_LOW                        = 0x3100;
            uint BOPOMOFO_EXTENDED_LOW                = 0x31A0;
            nCharsInRange = ur.GetRange(BOPOMOFO_LOW).count
                          + ur.GetRange(BOPOMOFO_EXTENDED_LOW).count;
            bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x00080000, nCharsInRange, "Bopomofo, Bopomofo Extended");

            // bit 52
            uint HANGUL_COMPAT_JAMO_LOW                = 0x3130;
            nCharsInRange = ur.GetRange(HANGUL_COMPAT_JAMO_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00100000, nCharsInRange, "Hangul Compatibility Jamo");

            // v2: CJK Miscellaneous
            // v3: Reserved for Unicode SubRanges
            // v4: Phags-pa                                A840-A87F
            // bit 53 !!! OT Spec 1.3 says bit 53 is CJK Misc !!!
            //        !!! Since there's no unicode range name !!!
            //        !!! that maps nicely to CJK Misc,       !!!
            //        !!! I naturally just ignore it.         !!!
            /*
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00200000, nCharsInRange, "CJK Miscellaneous");
            */
            // TODO: v4

            // bit 54
            uint ENCLOSED_CJK_LETTERS_MONTHS_LOW     = 0x3200;
            nCharsInRange = ur.GetRange(ENCLOSED_CJK_LETTERS_MONTHS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00400000, nCharsInRange, "Enclosed CJK Letters and Months");

            // bit 55
            uint CJK_COMPATIBILITY_LOW                = 0x3300;
            nCharsInRange = ur.GetRange(CJK_COMPATIBILITY_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00800000, nCharsInRange, "CJK Compatibility");

            // bit 56
            uint HANGUL_LOW                            = 0xAC00;
            nCharsInRange = ur.GetRange(HANGUL_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x01000000, nCharsInRange, "Hangul");

            // v1: Reserved for Unicode SubRanges
            // v2: Surrogates
            // v3: Non-Plane 0 *
            // v4: Non-Plane 0 *                           D800-DFFF
            // bit 57 surrogates
            if (version > 1)
            {
                bool bSurrogatesCmapPresent = false;
                Table_cmap cmapTable = (Table_cmap)fontOwner.GetTable("cmap");
                if (cmapTable != null)
                {
                    Table_cmap.EncodingTableEntry eteUniSurrogates = cmapTable.GetEncodingTableEntry(3,10);
                    if (eteUniSurrogates != null)
                        bSurrogatesCmapPresent = true;
                }

                if ((ulUnicodeRange2 & 0x02000000) == 0)
                {
                    if (bSurrogatesCmapPresent)
                    {
                        v.Error(T.T_NULL, E.OS_2_E_SurrogatesBitClear, m_tag);
                        bOk = false;
                    }
                }
                else
                {
                    if (!bSurrogatesCmapPresent)
                    {
                        v.Error(T.T_NULL, E.OS_2_E_SurrogatesBitSet, m_tag);
                        bOk = false;
                    }
                }
            }

            // v1/v2/v3: Reserved for Unicode SubRanges
            // v4: Phoenician                              10900-1091F
            if (version < 4)
            {
                // bit 58 reserved
                if ((ulUnicodeRange2 & 0x04000000) != 0)
                {
                    bOk = false;
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #58");
                }
            }
            // TODO: v4

            // bit 59
            uint CJK_UNIFIED_IDEOGRAPHS_LOW            = 0x4E00;
            uint CJK_RADICALS_SUPPLEMENT_LOW        = 0x2E80;
            uint KANGXI_RADICALS_LOW                = 0x2F00;
            uint IDEOGRAPHIC_DESCRIPTION_CHARS_LOW    = 0x2FF0;
            uint CJK_UNIFIED_IDEOGRAPHS_EXT_A_LOW   = 0x3400;
            uint CJK_UNIFIED_IDEOGRAPHS_EXT_B_LOW   = 0x20000;
            uint KANBUN_LOW                         = 0x3190;
            nCharsInRange = ur.GetRange(CJK_UNIFIED_IDEOGRAPHS_LOW).count
                          + ur.GetRange(CJK_RADICALS_SUPPLEMENT_LOW).count
                          + ur.GetRange(KANGXI_RADICALS_LOW).count
                          + ur.GetRange(IDEOGRAPHIC_DESCRIPTION_CHARS_LOW).count
                          + ur.GetRange(CJK_UNIFIED_IDEOGRAPHS_EXT_A_LOW).count
                          + ur.GetRange(CJK_UNIFIED_IDEOGRAPHS_EXT_B_LOW).count
                          + ur.GetRange(KANBUN_LOW).count;
            bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x08000000, nCharsInRange, "CJK Unified Ideographs, CJK Radicals Supplement, Kangxi Radicals, Ideographic Description Chars, CJK Unified Ideographs Extended A, CJK Unified Ideographs Extended B, Kanbun");

            // bit 60
            uint PRIVATE_USE_AREA_LOW                = 0xE000;
            if (!fontOwner.ContainsMsSymbolEncodedCmap())
            {
                nCharsInRange = ur.GetRange(PRIVATE_USE_AREA_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x10000000, nCharsInRange, "Private Use Area");
            }

            // bit 61
            uint CJK_Strokes                         = 0x31C0;
            uint CJK_COMPATIBILITY_IDEOGRAPHS_LOW    = 0xF900;
            uint CJK_COMPATIBILITY_IDEO_SUPP_LOW    = 0x2F800;
            nCharsInRange = ur.GetRange(CJK_Strokes).count
                + ur.GetRange(CJK_COMPATIBILITY_IDEOGRAPHS_LOW).count
                          + ur.GetRange(CJK_COMPATIBILITY_IDEO_SUPP_LOW).count;
            bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x20000000, nCharsInRange, "CJK Compatibility Ideographs, CJK Compatibility Ideographs Supplement");

            // bit 62
            uint ALPHABETIC_PRESENTATION_FORMS_LOW    = 0xFB00;
            nCharsInRange = ur.GetRange(ALPHABETIC_PRESENTATION_FORMS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x40000000, nCharsInRange, "Alphabetic Presentation Forms");

            // bit 63
            uint ARABIC_PRESENTATION_FORMS_A_LOW     = 0xFB50;
            nCharsInRange = ur.GetRange(ARABIC_PRESENTATION_FORMS_A_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x80000000, nCharsInRange, "Arabic Presentation Forms-A");

            // bit 64
            uint COMBINING_HALF_MARKS_LOW            = 0xFE20;
            nCharsInRange = ur.GetRange(COMBINING_HALF_MARKS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000001, nCharsInRange, "Combining Half Marks");

            // bit 65
            uint Vertical_Forms                      = 0xFE10;
            uint CJK_COMPATIBILITY_FORMS_LOW         = 0xFE30;
            nCharsInRange = ur.GetRange(Vertical_Forms).count
                + ur.GetRange(CJK_COMPATIBILITY_FORMS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000002, nCharsInRange, "CJK Compatibility Forms");

            // bit 66
            uint SMALL_FORM_VARIANTS_LOW             = 0xFE50;
            nCharsInRange = ur.GetRange(SMALL_FORM_VARIANTS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000004, nCharsInRange, "Small Form Variants");

            // bit 67
            uint ARABIC_PRESENTATION_FORMS_B_LOW     = 0xFE70;
            nCharsInRange = ur.GetRange(ARABIC_PRESENTATION_FORMS_B_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000008, nCharsInRange, "Arabic Presentation Forms-B");

            // bit 68
            uint HALFWIDTH_FULLWIDTH_FORMS_LOW        = 0xFF00;
            nCharsInRange = ur.GetRange(HALFWIDTH_FULLWIDTH_FORMS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000010, nCharsInRange, "Halfwidth and Fullwidth Forms");

            // bit 69
            uint SPECIALS_LOW                        = 0xFFF0;
            nCharsInRange = ur.GetRange(SPECIALS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000020, nCharsInRange, "Specials");

            // v1: 70-127 Reserved for Unicode SubRanges
            if (version < 2)
            {
                for (int bitpos = 6; bitpos < 32; bitpos++)
                {
                    if ((ulUnicodeRange3 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (64+bitpos)); }
                }

                for (int bitpos = 0; bitpos < 32; bitpos++)
                {
                    if ((ulUnicodeRange4 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (96+bitpos)); }
                }
            }
            else
            {
                // bit 70
                uint TIBETAN_LOW                        = 0x0F00;
                nCharsInRange = ur.GetRange(TIBETAN_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000040, nCharsInRange, "Tibetan");

                // bit 71
                uint SYRIAC_LOW                            = 0x0700;
                nCharsInRange = ur.GetRange(SYRIAC_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000080, nCharsInRange, "Syriac");

                // bit 72
                uint THAANA_LOW                            = 0x0780;
                nCharsInRange = ur.GetRange(THAANA_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000100, nCharsInRange, "Thaana");

                // bit 73
                uint SINHALA_LOW                        = 0x0D80;
                nCharsInRange = ur.GetRange(SINHALA_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000200, nCharsInRange, "Sinhala");

                // bit 74
                uint MYANMAR_LOW                        = 0x1000;
                nCharsInRange = ur.GetRange(MYANMAR_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000400, nCharsInRange, "Myanmar");

                // bit 75
                uint ETHIOPIC_LOW                        = 0x1200;
                uint Ethiopic_Supplement                 = 0x1380;
                uint Ethiopic_Extended                   = 0x2D80;
                nCharsInRange = ur.GetRange(ETHIOPIC_LOW).count
                    + ur.GetRange(Ethiopic_Supplement).count
                    + ur.GetRange(Ethiopic_Extended).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000800, nCharsInRange, "Ethiopic");

                // bit 76
                uint CHEROKEE_LOW                        = 0x13A0;
                nCharsInRange = ur.GetRange(CHEROKEE_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00001000, nCharsInRange, "Cherokee");

                // bit 77
                uint UNIFIED_CANADIAN_AB_SYL_LOW        = 0x1400;
                nCharsInRange = ur.GetRange(UNIFIED_CANADIAN_AB_SYL_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00002000, nCharsInRange, "Unified Canadian Syllabics");

                // bit 78
                uint OGHAM_LOW                            = 0x1680;
                nCharsInRange = ur.GetRange(OGHAM_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00004000, nCharsInRange, "Ogham");

                // bit 79
                uint RUNIC_LOW                            = 0x16A0;
                nCharsInRange = ur.GetRange(RUNIC_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00008000, nCharsInRange, "Runic");

                // bit 80
                uint KHMER_LOW                            = 0x1780;
                uint Khmer_Symbols                        = 0x19E0;
                nCharsInRange = ur.GetRange(KHMER_LOW).count
                    + ur.GetRange(Khmer_Symbols).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00010000, nCharsInRange, "Khmer");

                // bit 81
                uint MONGOLIAN_LOW                        = 0x1800;
                nCharsInRange = ur.GetRange(MONGOLIAN_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00020000, nCharsInRange, "Mongolian");

                // bit 82
                uint BRAILLE_PATTERNS_LOW                = 0x2800;
                nCharsInRange = ur.GetRange(BRAILLE_PATTERNS_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00040000, nCharsInRange, "Braille");

                // bit 83
                uint YI_LOW                                = 0xA000;
                uint YI_RADICALS_LOW                    = 0xA490;
                nCharsInRange = ur.GetRange(YI_LOW).count
                              + ur.GetRange(YI_RADICALS_LOW).count;
                bOk &= VerifyUnicodeRanges(v, ulUnicodeRange3, 0x00080000, nCharsInRange, "Yi, Yi Radicals");

                // v2: 84-127 Reserved for Unicode SubRanges
                if (version < 3)
                {
                    for (int bitpos = 20; bitpos < 32; bitpos++)
                    {
                        if ((ulUnicodeRange3 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (64+bitpos)); }
                    }

                    for (int bitpos = 0; bitpos < 32; bitpos++)
                    {
                        if ((ulUnicodeRange4 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (96+bitpos)); }
                    }
                }
                else
                {
                    // bit 84
                    uint TAGALOG_LOW                    = 0x1700;
                    uint HANUNOO_LOW                    = 0x1720;
                    uint BUHID_LOW                      = 0x1740;
                    uint TAGBANWA_LOW                   = 0x1760;
                    nCharsInRange = ur.GetRange(TAGALOG_LOW).count
                                  + ur.GetRange(HANUNOO_LOW).count
                                  + ur.GetRange(BUHID_LOW).count
                                  + ur.GetRange(TAGBANWA_LOW).count;
                    bOk &= VerifyUnicodeRanges(v, ulUnicodeRange3, 0x00100000, nCharsInRange, "Tagalog, Hanunoo, Buhid, Tagbanwa");

                    // bit 85
                    uint OLD_ITALIC_LOW                 = 0x10300;
                    nCharsInRange = ur.GetRange(OLD_ITALIC_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00200000, nCharsInRange, "Old Italic");

                    // bit 86
                    uint GOTHIC_LOW                     = 0x10330;
                    nCharsInRange = ur.GetRange(GOTHIC_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00400000, nCharsInRange, "Gothic");

                    // bit 87
                    uint DESERET_LOW                    = 0x10400;
                    nCharsInRange = ur.GetRange(DESERET_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00800000, nCharsInRange, "Deseret");

                    // bit 88
                    uint BYZANTINE_MUSICAL_SYMBOLS_LOW  = 0x1D000;
                    uint MUSICAL_SYMBOLS_LOW            = 0x1D100;
                    uint Ancient_Greek_Musical_Notation = 0x1D200;
                    nCharsInRange = ur.GetRange(BYZANTINE_MUSICAL_SYMBOLS_LOW).count
                                  + ur.GetRange(MUSICAL_SYMBOLS_LOW).count
                        + ur.GetRange(Ancient_Greek_Musical_Notation).count;
                    bOk &= VerifyUnicodeRanges(v, ulUnicodeRange3, 0x01000000, nCharsInRange, "Byzantine Musical Symbols, Musical Symbols");

                    // bit 89
                    uint MATHEMATICAL_ALPHANUMERIC_LOW  = 0x1D400;
                    nCharsInRange = ur.GetRange(MATHEMATICAL_ALPHANUMERIC_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x02000000, nCharsInRange, "Mathematical Alphanumeric Symbols");

                    // bit 90
                    uint PRIVATE_USE_15_LOW             = 0xFFF80;
                    uint PRIVATE_USE_16_LOW             = 0x10FF80;
                    nCharsInRange = ur.GetRange(PRIVATE_USE_15_LOW).count
                                  + ur.GetRange(PRIVATE_USE_16_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x04000000, nCharsInRange, "Private Use (Plane 15), Private Use (Plane 16)");

                    // bit 91
                    uint Variation_Selectors             = 0xFE00;
                    uint VARIATION_SELECTORS_SUPP         = 0xE0100;
                    nCharsInRange = ur.GetRange(Variation_Selectors).count
                        + ur.GetRange(VARIATION_SELECTORS_SUPP).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x08000000, nCharsInRange, "Variation Selectors");

                    // bit 92
                    uint TAGS_LOW                       = 0xE0000;
                    nCharsInRange = ur.GetRange(TAGS_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x10000000, nCharsInRange, "Tags");

                    // v3: 93-127 Reserved for Unicode SubRanges
                    if (version < 4)
                    {
                        for (int bitpos = 29; bitpos < 32; bitpos++)
                        {
                            if ((ulUnicodeRange3 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (64+bitpos)); }
                        }

                        for (int bitpos = 0; bitpos < 32; bitpos++)
                        {
                            if ((ulUnicodeRange4 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (96+bitpos)); }
                        }
                    }
                    else
                    {
                    // v4 addition

                    /*
                      93      Limbu                                   1900-194F
                      94      Tai Le                                  1950-197F
                      95      New Tai Lue                             1980-19DF
                      96      Buginese                                1A00-1A1F
                      97      Glagolitic                              2C00-2C5F
                      98      Tifinagh                                2D30-2D7F
                      99      Yijing Hexagram Symbols                 4DC0-4DFF
                      100     Syloti Nagri                            A800-A82F
                      101     Linear B Syllabary                      10000-1007F
                      Linear B Ideograms                      10080-100FF
                      Aegean Numbers                          10100-1013F
                      102     Ancient Greek Numbers                   10140-1018F
                      103     Ugaritic                                10380-1039F
                      104     Old Persian                             103A0-103DF
                      105     Shavian                                 10450-1047F
                      106     Osmanya                                 10480-104AF
                      107     Cypriot Syllabary                       10800-1083F
                      108     Kharoshthi                              10A00-10A5F
                      109     Tai Xuan Jing Symbols                   1D300-1D35F
                      110     Cuneiform                               12000-123FF
                      Cuneiform Numbers and Punctuation       12400-1247F
                      111     Counting Rod Numerals                   1D360-1D37F
                      112     Sundanese                               1B80-1BBF
                      113     Lepcha                                  1C00-1C4F
                      114     Ol Chiki                                1C50-1C7F
                      115     Saurashtra                              A880-A8DF
                      116     Kayah Li                                A900-A92F
                      117     Rejang                                  A930-A95F
                      118     Cham                                    AA00-AA5F
                      119     Ancient Symbols                         10190-101CF
                      120     Phaistos Disc                           101D0-101FF
                      121     Carian                                  102A0-102DF
                      Lycian                                  10280-1029F
                      Lydian                                  10920-1093F
                      122     Domino Tiles                            1F030-1F09F
                      Mahjong Tiles                           1F000-1F02F
                      123-127 Reserved for process-internal usage
                     */

                        // TODO: v4 addition
                    }
                }
            }

            if (bOk)
            {
                v.Pass(P.OS_2_P_UnicodeRanges, m_tag);
            }
            else
            {
                bRet = false;
            }

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

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


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

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

                return bRet;
            }
示例#35
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;
        }
示例#36
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;
        }
示例#37
0
        protected bool CheckForNoUnnecessaryTables(Validator v)
        {
            bool bRet = true;

            bool bFoundUnnecessary = false;

            Table_hmtx hmtxTable = (Table_hmtx)GetTable("hmtx");

            if (hmtxTable != null)
            {
                if (hmtxTable.IsMonospace(this))
                {
                    if (GetDirectoryEntry("hdmx") != null)
                    {
                        v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "hdmx table not needed for monospaced font");
                        bFoundUnnecessary = true;
                    }

                    if (GetDirectoryEntry("LTSH") != null)
                    {
                        v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "LTSH table not needed for monospaced font");
                        bFoundUnnecessary = true;
                    }

                    if (GetDirectoryEntry("kern") != null)
                    {
                        v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "kern table not needed for monospaced font");
                        bFoundUnnecessary = true;
                    }
                }

                if (GetDirectoryEntry("CFF ") == null && GetDirectoryEntry("VORG") != null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "VORG table not needed, it may optionally be present for fonts with Postscript outlines");
                    bFoundUnnecessary = true;
                }

                if (GetDirectoryEntry("PCLT") != null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "PCLT table not needed, Microsoft no longer recommends including this table");
                    bFoundUnnecessary = true;
                }
            }

            if (GetDirectoryEntry("CFF ") != null)
            {
                string [] UnnecessaryTables = { "glyf", "fpgm", "cvt ", "loca", "prep" };

                for (int i = 0; i < UnnecessaryTables.Length; i++)
                {
                    if (GetDirectoryEntry(UnnecessaryTables[i]) != null)
                    {
                        v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, UnnecessaryTables[i] + " not needed since the font contains a 'CFF ' table");
                        bFoundUnnecessary = true;
                    }
                }
            }

            if (GetDirectoryEntry("glyf") != null)
            {
                if (GetDirectoryEntry("CFF ") != null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "CFF not needed since the font contains a 'CFF ' table");
                    bFoundUnnecessary = true;
                }
            }

            if (ContainsLatinOnly())
            {
                if (GetDirectoryEntry("vhea") != null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "vhea not needed since the font only contains Latin characters");
                    bFoundUnnecessary = true;
                }

                if (GetDirectoryEntry("vmtx") != null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "vmtx not needed since the font only contains Latin characters");
                    bFoundUnnecessary = true;
                }
            }


            if (!bFoundUnnecessary)
            {
                v.Pass(P._FONT_P_UnnecessaryTable, null);
            }

            return(bRet);
        }
示例#38
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;
        }
示例#39
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;
        }
示例#40
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;
        }
示例#41
0
        protected bool CheckForOptimalTableOrder(Validator v)
        {
            bool bRet = true;

            if (!GetFile().IsCollection())  // don't perform this test on .ttc files
            {
                string [] OrderedTables = null;
                string [] TTOrderedTables =
                {
                    "head", "hhea", "maxp", "OS/2", "hmtx", "LTSH", "VDMX",
                    "hdmx", "cmap", "fpgm", "prep", "cvt ", "loca", "glyf",
                    "kern", "name", "post", "gasp", "PCLT" /*"DSIG"*/
                };
                string [] PSOrderedTables =
                {
                    "head", "hhea", "maxp", "OS/2", "name", "cmap", "post", "CFF "
                };

                if (ContainsTrueTypeOutlines())
                {
                    OrderedTables = TTOrderedTables;
                }
                else if (ContainsPostScriptOutlines())
                {
                    OrderedTables = PSOrderedTables;
                }

                if (OrderedTables != null)
                {
                    Debug.Assert(m_OffsetTable != null);

                    bool bOrderOk = true;

                    if (m_OffsetTable != null)
                    {
                        for (int i=0; i<OrderedTables.Length-1; i++)
                        {
                            for (int j=i+1; j<OrderedTables.Length; j++)
                            {
                                DirectoryEntry deBefore = GetDirectoryEntry(OrderedTables[i]);
                                DirectoryEntry deAfter  = GetDirectoryEntry(OrderedTables[j]);
                                if (deBefore != null && deAfter != null)
                                {
                                    if (deBefore.offset > deAfter.offset)
                                    {
                                        string sDetails = "table '" + deAfter.tag + "' precedes table '" + deBefore.tag + "'";
                                        v.Warning(T.T_NULL, W._FONT_W_OptimalOrder, null, sDetails);
                                        bOrderOk = false;
                                        break;
                                    }
                                }
                            }
                            if (!bOrderOk)
                            {
                                break;
                            }
                        }
                    }

                    if (bOrderOk)
                    {
                        v.Pass(P._FONT_P_OptimalOrder, null);
                    }
                }
            }

            return bRet;
        }
示例#42
0
        protected bool CheckForRecommendedTables(Validator v)
        {
            bool bRet = true;

            bool bMissing = false;

            if (!IsPostScript())
            {

                if (GetDirectoryEntry("gasp") == null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "gasp");
                    bMissing = true;
                }

                Table_hmtx hmtxTable = (Table_hmtx)GetTable("hmtx");
                if (hmtxTable != null)
                {
                    if (!hmtxTable.IsMonospace(this) && !ContainsSymbolsOnly())
                    {
                        if (GetDirectoryEntry("kern") == null)
                        {
                            v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "kern");
                            bMissing = true;
                        }

                        if (GetDirectoryEntry("hdmx") == null)
                        {
                            v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "hdmx");
                            bMissing = true;
                        }
                    }
                }

                if (GetDirectoryEntry("VDMX") == null)
                {
                    v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "VDMX");
                    bMissing = true;
                }

            }

            if (GetDirectoryEntry("DSIG") == null)
            {
                v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "DSIG");
                bMissing = true;
            }

            if (!bMissing)
            {
                v.Pass(P._FONT_P_MissingRecommendedTable, null);
            }

            return bRet;
        }
示例#43
0
        protected bool CheckForRequiredTables(Validator v)
        {
            bool bRet = true;

            string [] RequiredTables =
            { "cmap", "head", "hhea", "hmtx", "maxp", "name", "OS/2", "post" };

            for (int i = 0; i < RequiredTables.Length; i++)
            {
                if (GetDirectoryEntry(RequiredTables[i]) == null)
                {
                    v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, RequiredTables[i]);
                    bRet = false;
                }
            }

            if (GetDirectoryEntry("glyf") == null && GetDirectoryEntry("CFF ") == null && GetDirectoryEntry("CFF2") == null && GetDirectoryEntry("EBDT") == null && GetDirectoryEntry("CBDT") == null)
            {
                v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "Font must contain either a 'glyf', 'CFF ', 'CFF2', 'EBDT' or 'CBDT' table");
                bRet = false;
            }

            if (GetDirectoryEntry("glyf") != null)
            {
                string [] RequiredGlyphTables = { "loca" };

                for (int i = 0; i < RequiredGlyphTables.Length; i++)
                {
                    if (GetDirectoryEntry(RequiredGlyphTables[i]) == null)
                    {
                        v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, RequiredGlyphTables[i] + " is required since the font contains a glyf table");
                        bRet = false;
                    }
                }
            }

            if (GetDirectoryEntry("EBDT") != null)
            {
                if (GetDirectoryEntry("EBLC") == null)
                {
                    v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBLC is required since the font contains an EBDT table");
                    bRet = false;
                }
            }

            if (GetDirectoryEntry("EBLC") != null)
            {
                if (GetDirectoryEntry("EBDT") == null)
                {
                    v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBDT is required since the font contains an EBLC table");
                    bRet = false;
                }
            }

            if (GetDirectoryEntry("EBSC") != null)
            {
                if (GetDirectoryEntry("EBDT") == null)
                {
                    v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBDT is required since the font contains an EBSC table");
                    bRet = false;
                }
                if (GetDirectoryEntry("EBLC") == null)
                {
                    v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBLC is required since the font contains an EBSC table");
                    bRet = false;
                }
            }


            if (bRet)
            {
                v.Pass(P._FONT_P_MissingRequiredTable, null);
            }

            return(bRet);
        }
示例#44
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;
        }
示例#45
0
        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;
        }
示例#46
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;
        }
示例#47
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;
        }
示例#48
0
        private bool CheckUnicodeRanges(Validator v, OTFont fontOwner)
        {
            bool bRet = true;
            bool bOk = true;

            if (version == 0)
            {
                if (ulUnicodeRange1 != 0)
                {
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[0] was undefined. All bits must be 0.");
                    bOk = false;
                }
                if (ulUnicodeRange2 != 0)
                {
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[1] was undefined. All bits must be 0.");
                    bOk = false;
                }
                if (ulUnicodeRange3 != 0)
                {
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[2] was undefined. All bits must be 0.");
                    bOk = false;
                }
                if (ulUnicodeRange4 != 0)
                {
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[3] was undefined. All bits must be 0.");
                    bOk = false;
                }

                if (bOk)
                {
                    v.Pass(P.OS_2_P_UnicodeRanges, m_tag);
                }
                else
                {
                    bRet = false;
                }

                return bRet;
            }

            // count the number of entries in each unicode range in the cmap subtable
            

            UnicodeRanges ur = new UnicodeRanges();
            for (uint c = 0; c < 0xffff; c++)
            {
                // check if c is mapped to a glyph
                uint iGlyph = fontOwner.FastMapUnicodeToGlyphID((char)c);
                if (iGlyph != 0)
                {
                    UnicodeRanges.Range r = ur.GetRange(c);
                    if (r != null)
                    {
                        r.count++;
                    }
                }
            }


            uint nCharsInRange;


            // bit 0
            uint BASIC_LATIN_LOW                     = 0x0020; 
            nCharsInRange = ur.GetRange(BASIC_LATIN_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000001, nCharsInRange, "Basic Latin");

            // bit 1
            uint LATIN_1_SUPPLEMENT_LOW                = 0x00A0; 
            nCharsInRange = ur.GetRange(LATIN_1_SUPPLEMENT_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000002, nCharsInRange, "Latin-1 Supplement");

            // bit 2
            uint LATIN_EXTENDED_A_LOW                = 0x0100; 
            nCharsInRange = ur.GetRange(LATIN_EXTENDED_A_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000004, nCharsInRange, "Latin Extended-A");

            // bit 3
            uint LATIN_EXTENDED_B_LOW                = 0x0180; 
            nCharsInRange = ur.GetRange(LATIN_EXTENDED_B_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000008, nCharsInRange, "Latin Extended-B");

            // bit 4
            uint IPA_EXTENSIONS_LOW                    = 0x0250; 
            nCharsInRange = ur.GetRange(IPA_EXTENSIONS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000010, nCharsInRange, "IPA Extensions");

            // bit 5
            uint SPACING_MODIFIER_LETTERS_LOW        = 0x02B0; 
            nCharsInRange = ur.GetRange(SPACING_MODIFIER_LETTERS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000020, nCharsInRange, "Spacing Modifier Letters");

            // bit 6
            uint COMBINING_DIACRITICAL_MARKS_LOW     = 0x0300; 
            nCharsInRange = ur.GetRange(COMBINING_DIACRITICAL_MARKS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000040, nCharsInRange, "Combining Diacritical Marks");

            // bit 7
            uint GREEK_LOW                             = 0x0370; 
            nCharsInRange = ur.GetRange(GREEK_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000080, nCharsInRange, "Greek");
            
            // bit 8 reserved
            if ((ulUnicodeRange1 & 0x00000100) != 0)
            {
                bOk = false;
                v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #8");
            }

            // bit 9
            uint CYRILLIC_LOW                        = 0x0400; 
            uint CYRILLIC_SUPPLEMENTARY_LOW         = 0x0500;
            nCharsInRange = ur.GetRange(CYRILLIC_LOW).count
                          + ur.GetRange(CYRILLIC_SUPPLEMENTARY_LOW).count;
            bOk &= VerifyUnicodeRanges(v, ulUnicodeRange1, 0x00000200, nCharsInRange, "Cyrillic, Cyrillic Supplementary");
            
            // bit 10
            uint ARMENIAN_LOW                        = 0x0530; 
            nCharsInRange = ur.GetRange(ARMENIAN_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000400, nCharsInRange, "Armenian");
            
            // bit 11
            uint HEBREW_LOW                            = 0x0590; 
            nCharsInRange = ur.GetRange(HEBREW_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000800, nCharsInRange, "Hebrew");
            
            if (version > 1)
            {
                // bit 12 reserved
                if ((ulUnicodeRange1 & 0x00001000) != 0)
                {
                    bOk = false;
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #12");
                }
            }

            // bit 13
            uint ARABIC_LOW                            = 0x0600; 
            nCharsInRange = ur.GetRange(ARABIC_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00002000, nCharsInRange, "Arabic");
            
            if (version > 1)
            {
                // bit 14 reserved
                if ((ulUnicodeRange1 & 0x00004000) != 0)
                {
                    bOk = false;
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #14");
                }
            }

            // bit 15
            uint DEVANAGARI_LOW                        = 0x0900; 
            nCharsInRange = ur.GetRange(DEVANAGARI_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00008000, nCharsInRange, "Devanagari");
            
            // bit 16
            uint BENGALI_LOW                         = 0x0980; 
            nCharsInRange = ur.GetRange(BENGALI_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00010000, nCharsInRange, "Bengali");
            
            // bit 17
            uint GURMUKHI_LOW                        = 0x0A00; 
            nCharsInRange = ur.GetRange(GURMUKHI_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00020000, nCharsInRange, "Gurmukhi");
            
            // bit 18
            uint GUJARATI_LOW                        = 0x0A80; 
            nCharsInRange = ur.GetRange(GUJARATI_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00040000, nCharsInRange, "Gujarati");
            
            // bit 19
            uint ORIYA_LOW                            = 0x0B00; 
            nCharsInRange = ur.GetRange(ORIYA_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00080000, nCharsInRange, "Oriya");
            
            // bit 20
            uint TAMIL_LOW                            = 0x0B80; 
            nCharsInRange = ur.GetRange(TAMIL_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00100000, nCharsInRange, "Tamil");
            
            // bit 21
            uint TELUGU_LOW                            = 0x0C00; 
            nCharsInRange = ur.GetRange(TELUGU_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00200000, nCharsInRange, "Telugu");
            
            // bit 22
            uint KANNADA_LOW                         = 0x0C80; 
            nCharsInRange = ur.GetRange(KANNADA_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00400000, nCharsInRange, "Kannada");
            
            // bit 23
            uint MALAYALAM_LOW                        = 0x0D00; 
            nCharsInRange = ur.GetRange(MALAYALAM_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00800000, nCharsInRange, "Malayalam");
            
            // bit 24
            uint THAI_LOW                            = 0x0E00; 
            nCharsInRange = ur.GetRange(THAI_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x01000000, nCharsInRange, "Thai");
            
            // bit 25
            uint LAO_LOW                             = 0x0E80; 
            nCharsInRange = ur.GetRange(LAO_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x02000000, nCharsInRange, "Lao");
            
            // bit 26
            uint GEORGIAN_LOW                        = 0x10A0; 
            nCharsInRange = ur.GetRange(GEORGIAN_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x04000000, nCharsInRange, "Georgian");
            
            if (version > 1)
            {
                // bit 27 reserved
                if ((ulUnicodeRange1 & 0x08000000) != 0)
                {
                    bOk = false;
                    v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #27");
                }
            }
            
            // bit 28
            uint HANGUL_JAMO_LOW                     = 0x1100; 
            nCharsInRange = ur.GetRange(HANGUL_JAMO_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x10000000, nCharsInRange, "Hangul Jamo");
            
            // bit 29
            uint LATIN_EXTENDED_ADDITIONAL_LOW        = 0x1E00; 
            nCharsInRange = ur.GetRange(LATIN_EXTENDED_ADDITIONAL_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x20000000, nCharsInRange, "Latin Extended Additional");
            
            // bit 30
            uint GREEK_EXTENDED_LOW                    = 0x1F00; 
            nCharsInRange = ur.GetRange(GREEK_EXTENDED_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x40000000, nCharsInRange, "Greek Extended");
            
            // bit 31
            uint GENERAL_PUNCTUATION_LOW             = 0x2000; 
            nCharsInRange = ur.GetRange(GENERAL_PUNCTUATION_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x80000000, nCharsInRange, "General Punctuation");


            // bit 32
            uint SUPER_SUB_SCRIPTS_LOW                = 0x2070; 
            nCharsInRange = ur.GetRange(SUPER_SUB_SCRIPTS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000001, nCharsInRange, "Superscripts and Subscripts");
            
            // bit 33
            uint CURRENCY_SYMBOLS_LOW                = 0x20A0; 
            nCharsInRange = ur.GetRange(CURRENCY_SYMBOLS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000002, nCharsInRange, "Currency Symbols");
            
            // bit 34
            uint SYMBOL_COMBINING_MARKS_LOW            = 0x20D0; 
            nCharsInRange = ur.GetRange(SYMBOL_COMBINING_MARKS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000004, nCharsInRange, "Combining Diacritical marks for symbols");
            
            // bit 35
            uint LETTERLIKE_SYMBOLS_LOW                = 0x2100; 
            nCharsInRange = ur.GetRange(LETTERLIKE_SYMBOLS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000008, nCharsInRange, "Letterlike Symbols");
            
            // bit 36
            uint NUMBER_FORMS_LOW                    = 0x2150; 
            nCharsInRange = ur.GetRange(NUMBER_FORMS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000010, nCharsInRange, "Number Forms");
            
            // bit 37
            uint ARROWS_LOW                            = 0x2190; 
            uint SUPPLEMENTAL_ARROWS_A_LOW            = 0x27F0;
            uint SUPPLEMENTAL_ARROWS_B_LOW            = 0x2900;
            nCharsInRange = ur.GetRange(ARROWS_LOW).count
                          + ur.GetRange(SUPPLEMENTAL_ARROWS_A_LOW).count
                          + ur.GetRange(SUPPLEMENTAL_ARROWS_B_LOW).count; 
            bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x00000020, nCharsInRange, "Arrows, Supplementary Arrows A, Supplementary Arrows B");

            // bit 38
            uint MATH_OPERATORS_LOW                    = 0x2200; 
            uint SUPPLEMENTAL_MATH_OPERATORS_LOW    = 0x2A00;
            uint MISC_MATH_SYMBOLS_A_LOW            = 0x27C0;
            uint MISC_MATH_SYMBOLS_B_LOW            = 0x2980;
            nCharsInRange = ur.GetRange(MATH_OPERATORS_LOW).count
                          + ur.GetRange(SUPPLEMENTAL_MATH_OPERATORS_LOW).count
                          + ur.GetRange(MISC_MATH_SYMBOLS_A_LOW).count
                          + ur.GetRange(MISC_MATH_SYMBOLS_B_LOW).count;
            bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x00000040, nCharsInRange, "Mathematical Operators, Supplemental Mathematical Operators, Mathematical Symbols A, Mathematical Symbols B");
            
            // bit 39
            uint MISC_TECHNICAL_LOW                    = 0x2300; 
            nCharsInRange = ur.GetRange(MISC_TECHNICAL_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000080, nCharsInRange, "Miscellaneous Technical");
            
            // bit 40
            uint CONTROL_PICTURES_LOW                = 0x2400; 
            nCharsInRange = ur.GetRange(CONTROL_PICTURES_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000100, nCharsInRange, "Control Pictures");
            
            // bit 41
            uint OCR_LOW                             = 0x2440; 
            nCharsInRange = ur.GetRange(OCR_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000200, nCharsInRange, "Optical Character Recognition");
            
            // bit 42
            uint ENCLOSED_ALPHANUMERICS_LOW            = 0x2460; 
            nCharsInRange = ur.GetRange(ENCLOSED_ALPHANUMERICS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000400, nCharsInRange, "Enclosed Alphanumerics");
            
            // bit 43
            uint BOX_DRAWING_LOW                     = 0x2500; 
            nCharsInRange = ur.GetRange(BOX_DRAWING_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000800, nCharsInRange, "Box Drawing");
            
            // bit 44
            uint BLOCK_ELEMENTS_LOW                    = 0x2580; 
            nCharsInRange = ur.GetRange(BLOCK_ELEMENTS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00001000, nCharsInRange, "Block Elements");
            
            // bit 45
            uint GEOMETRIC_SHAPES_LOW                = 0x25A0; 
            nCharsInRange = ur.GetRange(GEOMETRIC_SHAPES_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00002000, nCharsInRange, "Geometric Shapes");
            
            // bit 46
            uint MISC_SYMBOLS_LOW                    = 0x2600; 
            nCharsInRange = ur.GetRange(MISC_SYMBOLS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00004000, nCharsInRange, "Miscellaneous Symbols");
            
            // bit 47
            uint DINGBATS_LOW                        = 0x2700; 
            nCharsInRange = ur.GetRange(DINGBATS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00008000, nCharsInRange, "Dingbats");
            
            // bit 48
            uint CJK_SYMBOLS_PUNCTUATION_LOW         = 0x3000; 
            nCharsInRange = ur.GetRange(CJK_SYMBOLS_PUNCTUATION_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00010000, nCharsInRange, "CJK Symbols and Punctuation");
            
            // bit 49
            uint HIRAGANA_LOW                        = 0x3040; 
            nCharsInRange = ur.GetRange(HIRAGANA_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00020000, nCharsInRange, "Hiragana");
            
            // bit 50
            uint KATAKANA_LOW                        = 0x30A0; 
            nCharsInRange = ur.GetRange(KATAKANA_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00040000, nCharsInRange, "Katakana");
            
            // bit 51
            uint BOPOMOFO_LOW                        = 0x3100; 
            uint BOPOMOFO_EXTENDED_LOW                = 0x31A0;
            nCharsInRange = ur.GetRange(BOPOMOFO_LOW).count
                          + ur.GetRange(BOPOMOFO_EXTENDED_LOW).count; 
            bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x00080000, nCharsInRange, "Bopomofo, Bopomofo Extended");
            
            // bit 52
            uint HANGUL_COMPAT_JAMO_LOW                = 0x3130; 
            nCharsInRange = ur.GetRange(HANGUL_COMPAT_JAMO_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00100000, nCharsInRange, "Hangul Compatibility Jamo");
            
            // bit 53 !!! OT Spec 1.3 says bit 53 is CJK Misc !!!
            //        !!! Since there's no unicode range name !!!
            //        !!! that maps nicely to CJK Misc,       !!!
            //        !!! I naturally just ignore it.         !!!
            /*
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00200000, nCharsInRange, "CJK Miscellaneous");
            */
            
            // bit 54
            uint ENCLOSED_CJK_LETTERS_MONTHS_LOW     = 0x3200; 
            nCharsInRange = ur.GetRange(ENCLOSED_CJK_LETTERS_MONTHS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00400000, nCharsInRange, "Enclosed CJK Letters and Months");
            
            // bit 55
            uint CJK_COMPATIBILITY_LOW                = 0x3300; 
            nCharsInRange = ur.GetRange(CJK_COMPATIBILITY_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00800000, nCharsInRange, "CJK Compatibility");
            
            // bit 56
            uint HANGUL_LOW                            = 0xAC00; 
            nCharsInRange = ur.GetRange(HANGUL_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x01000000, nCharsInRange, "Hangul");
            
            // bit 57 surrogates
            if (version > 1)
            {
                bool bSurrogatesCmapPresent = false;
                Table_cmap cmapTable = (Table_cmap)fontOwner.GetTable("cmap");
                if (cmapTable != null)
                {
                    Table_cmap.EncodingTableEntry eteUniSurrogates = cmapTable.GetEncodingTableEntry(3,10);
                    if (eteUniSurrogates != null)
                        bSurrogatesCmapPresent = true;
                }

                if ((ulUnicodeRange2 & 0x02000000) == 0)
                {
                    if (bSurrogatesCmapPresent)
                    {
                        v.Error(T.T_NULL, E.OS_2_E_SurrogatesBitClear, m_tag);
                        bOk = false;
                    }
                }
                else
                {
                    if (!bSurrogatesCmapPresent)
                    {
                        v.Error(T.T_NULL, E.OS_2_E_SurrogatesBitSet, m_tag);
                        bOk = false;
                    }
                }
            }

            // bit 58 reserved
            if ((ulUnicodeRange2 & 0x04000000) != 0)
            {
                bOk = false;
                v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #58");
            }

            // bit 59
            uint CJK_UNIFIED_IDEOGRAPHS_LOW            = 0x4E00; 
            uint CJK_RADICALS_SUPPLEMENT_LOW        = 0x2E80;
            uint KANGXI_RADICALS_LOW                = 0x2F00;
            uint IDEOGRAPHIC_DESCRIPTION_CHARS_LOW    = 0x2FF0;
            uint CJK_UNIFIED_IDEOGRAPHS_EXT_A_LOW   = 0x3400;
            uint CJK_UNIFIED_IDEOGRAPHS_EXT_B_LOW   = 0x20000;
            uint KANBUN_LOW                         = 0x3190;
            nCharsInRange = ur.GetRange(CJK_UNIFIED_IDEOGRAPHS_LOW).count
                          + ur.GetRange(CJK_RADICALS_SUPPLEMENT_LOW).count
                          + ur.GetRange(KANGXI_RADICALS_LOW).count
                          + ur.GetRange(IDEOGRAPHIC_DESCRIPTION_CHARS_LOW).count
                          + ur.GetRange(CJK_UNIFIED_IDEOGRAPHS_EXT_A_LOW).count
                          + ur.GetRange(CJK_UNIFIED_IDEOGRAPHS_EXT_B_LOW).count
                          + ur.GetRange(KANBUN_LOW).count; 
            bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x08000000, nCharsInRange, "CJK Unified Ideographs, CJK Radicals Supplement, Kangxi Radicals, Ideographic Description Chars, CJK Unified Ideographs Extended A, CJK Unified Ideographs Extended B, Kanbun");
            
            // bit 60
            uint PRIVATE_USE_AREA_LOW                = 0xE000; 
            if (!fontOwner.ContainsMsSymbolEncodedCmap())
            {
                nCharsInRange = ur.GetRange(PRIVATE_USE_AREA_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x10000000, nCharsInRange, "Private Use Area");
            }
            
            // bit 61
            uint CJK_COMPATIBILITY_IDEOGRAPHS_LOW    = 0xF900; 
            uint CJK_COMPATIBILITY_IDEO_SUPP_LOW    = 0x2F800;
            nCharsInRange = ur.GetRange(CJK_COMPATIBILITY_IDEOGRAPHS_LOW).count
                          + ur.GetRange(CJK_COMPATIBILITY_IDEO_SUPP_LOW).count; 
            bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x20000000, nCharsInRange, "CJK Compatibility Ideographs, CJK Compatibility Ideographs Supplement");
            
            // bit 62
            uint ALPHABETIC_PRESENTATION_FORMS_LOW    = 0xFB00; 
            nCharsInRange = ur.GetRange(ALPHABETIC_PRESENTATION_FORMS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x40000000, nCharsInRange, "Alphabetic Presentation Forms");
            
            // bit 63
            uint ARABIC_PRESENTATION_FORMS_A_LOW     = 0xFB50; 
            nCharsInRange = ur.GetRange(ARABIC_PRESENTATION_FORMS_A_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x80000000, nCharsInRange, "Arabic Presentation Forms-A");
            

            
            // bit 64
            uint COMBINING_HALF_MARKS_LOW            = 0xFE20; 
            nCharsInRange = ur.GetRange(COMBINING_HALF_MARKS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000001, nCharsInRange, "Combining Half Marks");
            
            // bit 65
            uint CJK_COMPATIBILITY_FORMS_LOW         = 0xFE30; 
            nCharsInRange = ur.GetRange(CJK_COMPATIBILITY_FORMS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000002, nCharsInRange, "CJK Compatibility Forms");
            
            // bit 66
            uint SMALL_FORM_VARIANTS_LOW             = 0xFE50; 
            nCharsInRange = ur.GetRange(SMALL_FORM_VARIANTS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000004, nCharsInRange, "Small Form Variants");
            
            // bit 67
            uint ARABIC_PRESENTATION_FORMS_B_LOW     = 0xFE70; 
            nCharsInRange = ur.GetRange(ARABIC_PRESENTATION_FORMS_B_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000008, nCharsInRange, "Arabic Presentation Forms-B");
            
            // bit 68
            uint HALFWIDTH_FULLWIDTH_FORMS_LOW        = 0xFF00; 
            nCharsInRange = ur.GetRange(HALFWIDTH_FULLWIDTH_FORMS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000010, nCharsInRange, "Halfwidth and Fullwidth Forms");
            
            // bit 69
            uint SPECIALS_LOW                        = 0xFFF0; 
            nCharsInRange = ur.GetRange(SPECIALS_LOW).count;
            bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000020, nCharsInRange, "Specials");

            if (version < 2)
            {
                for (int bitpos = 6; bitpos < 32; bitpos++)
                {
                    if ((ulUnicodeRange3 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (64+bitpos)); }
                }

                for (int bitpos = 0; bitpos < 32; bitpos++)
                {
                    if ((ulUnicodeRange4 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (96+bitpos)); }
                }
            }
            else
            {
                // bit 70
                uint TIBETAN_LOW                        = 0x0F00; 
                nCharsInRange = ur.GetRange(TIBETAN_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000040, nCharsInRange, "Tibetan");
                
                // bit 71
                uint SYRIAC_LOW                            = 0x0700; 
                nCharsInRange = ur.GetRange(SYRIAC_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000080, nCharsInRange, "Syriac");
                
                // bit 72
                uint THAANA_LOW                            = 0x0780; 
                nCharsInRange = ur.GetRange(THAANA_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000100, nCharsInRange, "Thaana");
                
                // bit 73
                uint SINHALA_LOW                        = 0x0D80; 
                nCharsInRange = ur.GetRange(SINHALA_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000200, nCharsInRange, "Sinhala");
                
                // bit 74
                uint MYANMAR_LOW                        = 0x1000; 
                nCharsInRange = ur.GetRange(MYANMAR_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000400, nCharsInRange, "Myanmar");
                
                // bit 75
                uint ETHIOPIC_LOW                        = 0x1200; 
                nCharsInRange = ur.GetRange(ETHIOPIC_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000800, nCharsInRange, "Ethiopic");
                
                // bit 76
                uint CHEROKEE_LOW                        = 0x13A0; 
                nCharsInRange = ur.GetRange(CHEROKEE_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00001000, nCharsInRange, "Cherokee");
                
                // bit 77
                uint UNIFIED_CANADIAN_AB_SYL_LOW        = 0x1400; 
                nCharsInRange = ur.GetRange(UNIFIED_CANADIAN_AB_SYL_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00002000, nCharsInRange, "Unified Canadian Syllabics");
                
                // bit 78
                uint OGHAM_LOW                            = 0x1680; 
                nCharsInRange = ur.GetRange(OGHAM_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00004000, nCharsInRange, "Ogham");
                
                // bit 79
                uint RUNIC_LOW                            = 0x16A0; 
                nCharsInRange = ur.GetRange(RUNIC_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00008000, nCharsInRange, "Runic");
                
                // bit 80
                uint KHMER_LOW                            = 0x1780; 
                nCharsInRange = ur.GetRange(KHMER_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00010000, nCharsInRange, "Khmer");
                
                // bit 81
                uint MONGOLIAN_LOW                        = 0x1800; 
                nCharsInRange = ur.GetRange(MONGOLIAN_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00020000, nCharsInRange, "Mongolian");
                
                // bit 82
                uint BRAILLE_PATTERNS_LOW                = 0x2800; 
                nCharsInRange = ur.GetRange(BRAILLE_PATTERNS_LOW).count;
                bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00040000, nCharsInRange, "Braille");
                
                // bit 83
                uint YI_LOW                                = 0xA000; 
                uint YI_RADICALS_LOW                    = 0xA490;
                nCharsInRange = ur.GetRange(YI_LOW).count 
                              + ur.GetRange(YI_RADICALS_LOW).count;
                bOk &= VerifyUnicodeRanges(v, ulUnicodeRange3, 0x00080000, nCharsInRange, "Yi, Yi Radicals");
                

                if (version < 3)
                {
                    for (int bitpos = 20; bitpos < 32; bitpos++)
                    {
                        if ((ulUnicodeRange3 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (64+bitpos)); }
                    }

                    for (int bitpos = 0; bitpos < 32; bitpos++)
                    {
                        if ((ulUnicodeRange4 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (96+bitpos)); }
                    }
                }
                else
                {
                    // bit 84
                    uint TAGALOG_LOW                    = 0x1700;
                    uint HANUNOO_LOW                    = 0x1720;
                    uint BUHID_LOW                      = 0x1740;
                    uint TAGBANWA_LOW                   = 0x1760;
                    nCharsInRange = ur.GetRange(TAGALOG_LOW).count
                                  + ur.GetRange(HANUNOO_LOW).count
                                  + ur.GetRange(BUHID_LOW).count
                                  + ur.GetRange(TAGBANWA_LOW).count;
                    bOk &= VerifyUnicodeRanges(v, ulUnicodeRange3, 0x00100000, nCharsInRange, "Tagalog, Hanunoo, Buhid, Tagbanwa");

                    // bit 85
                    uint OLD_ITALIC_LOW                 = 0x10300;
                    nCharsInRange = ur.GetRange(OLD_ITALIC_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00200000, nCharsInRange, "Old Italic");

                    // bit 86
                    uint GOTHIC_LOW                     = 0x10330;
                    nCharsInRange = ur.GetRange(GOTHIC_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00400000, nCharsInRange, "Gothic");

                    // bit 87
                    uint DESERET_LOW                    = 0x10400;
                    nCharsInRange = ur.GetRange(DESERET_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00800000, nCharsInRange, "Deseret");

                    // bit 88
                    uint BYZANTINE_MUSICAL_SYMBOLS_LOW  = 0x1D000;
                    uint MUSICAL_SYMBOLS_LOW            = 0x1D100;
                    nCharsInRange = ur.GetRange(BYZANTINE_MUSICAL_SYMBOLS_LOW).count
                                  + ur.GetRange(MUSICAL_SYMBOLS_LOW).count;
                    bOk &= VerifyUnicodeRanges(v, ulUnicodeRange3, 0x01000000, nCharsInRange, "Byzantine Musical Symbols, Musical Symbols");

                    // bit 89
                    uint MATHEMATICAL_ALPHANUMERIC_LOW  = 0x1D400;
                    nCharsInRange = ur.GetRange(MATHEMATICAL_ALPHANUMERIC_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x02000000, nCharsInRange, "Mathematical Alphanumeric Symbols");

                    // bit 90
                    uint PRIVATE_USE_15_LOW             = 0xFFF80;
                    uint PRIVATE_USE_16_LOW             = 0x10FF80;
                    nCharsInRange = ur.GetRange(PRIVATE_USE_15_LOW).count
                                  + ur.GetRange(PRIVATE_USE_16_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x04000000, nCharsInRange, "Private Use (Plane 15), Private Use (Plane 16)");

                    // bit 91
                    uint VARIATION_SELECTORS_LOW         = 0xE0100;
                    nCharsInRange = ur.GetRange(VARIATION_SELECTORS_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x08000000, nCharsInRange, "Variation Selectors");

                    // bit 92
                    uint TAGS_LOW                       = 0xE0000;
                    nCharsInRange = ur.GetRange(TAGS_LOW).count;
                    bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x10000000, nCharsInRange, "Tags");

                    for (int bitpos = 29; bitpos < 32; bitpos++)
                    {
                        if ((ulUnicodeRange3 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (64+bitpos)); }
                    }

                    for (int bitpos = 0; bitpos < 32; bitpos++)
                    {
                        if ((ulUnicodeRange4 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (96+bitpos)); }
                    }
                }
            }

            if (bOk)
            {
                v.Pass(P.OS_2_P_UnicodeRanges, m_tag);
            }
            else
            {
                bRet = false;
            }

            return bRet;
        }
示例#49
0
        /************************
         * public methods
         */


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

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


            if (v.PerformTest(T.EBLC_version))
            {
                if (version.GetUint() == 0x00020000)
                {
                    v.Pass(T.EBLC_version, P.EBLC_P_version, m_tag);
                }
                else
                {
                    v.Error(T.EBLC_version, E.EBLC_E_version, m_tag, "version = 0x" + version.GetUint().ToString("x8") + ", unable to continue validation");
                    return(false);
                }
            }

            if (v.PerformTest(T.EBLC_numSizes))
            {
                if (numSizes < (m_bufTable.GetLength() / 48))
                {
                    v.Pass(T.EBLC_numSizes, P.EBLC_P_numSizes, m_tag);
                }
                else
                {
                    v.Error(T.EBLC_numSizes, E.EBLC_E_numSizes, m_tag, "0x" + numSizes.ToString("x8"));
                    bNumSizesOkay = false;
                    bRet          = false;
                }
            }

            if (v.PerformTest(T.EBLC_TableDependency))
            {
                if (EBDTTable != null)
                {
                    v.Pass(T.EBLC_TableDependency, P.EBLC_P_TableDependency, m_tag);
                }
                else
                {
                    v.Error(T.EBLC_TableDependency, E.EBLC_E_TableDependency, m_tag);
                    bRet = false;
                }
            }

            if (v.PerformTest(T.EBLC_indexSubTableArrayOffset) && bNumSizesOkay == true)
            {
                bool bOffsetsOk = true;
                bool bIndicesOk = true;

                uint SmallestPossibleOffset = 8 + numSizes * 48; // sizeof header + sizeof bitmapSizeTAbles
                for (uint i = 0; i < numSizes; i++)
                {
                    bitmapSizeTable bst = GetBitmapSizeTable(i);

                    // start must be less than or equal to end
                    if (bst.startGlyphIndex > bst.endGlyphIndex)
                    {
                        string s = "index = " + i + ", start index = " + bst.startGlyphIndex + ", stop index = " + bst.endGlyphIndex;
                        v.Error(T.EBLC_SizeTableIndexOrder, E.EBLC_E_BitmapSizeTableIndexOrder, m_tag, s);
                        bIndicesOk = false;
                        bRet       = false;
                    }

                    if (bst.indexSubTableArrayOffset < SmallestPossibleOffset ||
                        bst.indexSubTableArrayOffset + bst.indexTablesSize > GetLength())
                    {
                        string s = "index = " + i + ", indexSubTableArrayOffset = " + bst.indexSubTableArrayOffset
                                   + ", indexTablesSize = " + bst.indexTablesSize;
                        v.Error(T.EBLC_indexSubTableArrayOffset, E.EBLC_E_indexSubTableArrayOffset, m_tag, s);
                        bOffsetsOk = false;
                        bRet       = false;
                    }
                    else
                    {
                        indexSubTableArray[] ista = GetIndexSubTableArray(bst);

                        for (uint j = 0; j < bst.numberOfIndexSubTables; j++)
                        {
                            // first must be less than or equal to last
                            if (ista[j].firstGlyphIndex > ista[j].lastGlyphIndex)
                            {
                            }

                            // subtable indices must be within size table range
                            if (ista[j].firstGlyphIndex <bst.startGlyphIndex ||
                                                         ista[j].lastGlyphIndex> bst.endGlyphIndex)
                            {
                            }
                        }
                    }
                }

                if (bOffsetsOk)
                {
                    v.Pass(T.EBLC_indexSubTableArrayOffset, P.EBLC_P_indexSubTableArrayOffset, m_tag);
                }

                if (bIndicesOk)
                {
                    v.Pass(T.EBLC_SizeTableIndexOrder, P.EBLC_P_BitmapSizeTableIndexOrder, m_tag);
                }
            }

            if (v.PerformTest(T.EBLC_bitDepth) && bNumSizesOkay == true)
            {
                bool bBitDepthOk = true;

                for (uint i = 0; i < numSizes; i++)
                {
                    bitmapSizeTable bst = GetBitmapSizeTable(i);
                    if (bst.bitDepth != 1 && bst.bitDepth != 2 && bst.bitDepth != 4 && bst.bitDepth != 8)
                    {
                        string s = "index = " + i + ", bitDepth = " + bst.bitDepth;
                        v.Error(T.EBLC_bitDepth, E.EBLC_E_bitDepth, m_tag, s);
                        bBitDepthOk = false;
                        bRet        = false;
                    }
                }

                if (bBitDepthOk)
                {
                    v.Pass(T.EBLC_bitDepth, P.EBLC_P_bitDepth, m_tag);
                }
            }

            if (v.PerformTest(T.EBLC_indexSubTables) && bNumSizesOkay == true)
            {
                for (uint i = 0; i < numSizes; i++)
                {
                    bitmapSizeTable bst   = GetBitmapSizeTable(i);
                    string          sSize = "bitmapsize[" + i + "], ppemX=" + bst.ppemX + ", ppemY=" + bst.ppemY;

                    indexSubTableArray[] ista = GetIndexSubTableArray(bst);

                    for (uint j = 0; j < bst.numberOfIndexSubTables; j++)
                    {
                        indexSubTable ist = bst.GetIndexSubTable(ista[j]);
                        string        sID = sSize + ", indexSubTable[" + j + "](fmt " + ist.header.indexFormat + ")";

                        if (!Validate_indexSubTable(v, ist, ista[j], sID, fontOwner))
                        {
                            bRet = false;
                        }
                    }
                }
            }

            return(bRet);
        }
示例#50
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;
        }
示例#51
0
        /************************
         * public methods
         */


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

            if (v.PerformTest(T.BASE_Version))
            {
                if (Version.GetUint() == 0x00010000 || Version.GetUint() == 0x00010001)
                {
                    v.Pass(T.BASE_Version, P.BASE_P_Version, m_tag);
                }
                else
                {
                    v.Error(T.BASE_Version, E.BASE_E_Version, m_tag, "0x" + Version.GetUint().ToString("x8"));
                    bRet = false;
                }
            }

            if (v.PerformTest(T.BASE_HeaderOffsets))
            {
                if (HorizAxisOffset == 0)
                {
                    v.Pass(T.BASE_HeaderOffsets, P.BASE_P_HorizAxisOffset_null, m_tag);
                }
                else if (HorizAxisOffset < GetLength())
                {
                    v.Pass(T.BASE_HeaderOffsets, P.BASE_P_HorizAxisOffset_valid, m_tag);
                }
                else
                {
                    v.Error(T.BASE_HeaderOffsets, E.BASE_E_HorizAxisOffset_OutsideTable, m_tag);
                    bRet = false;
                }

                if (VertAxisOffset == 0)
                {
                    v.Pass(T.BASE_HeaderOffsets, P.BASE_P_VertAxisOffset_null, m_tag);
                }
                else if (VertAxisOffset < GetLength())
                {
                    v.Pass(T.BASE_HeaderOffsets, P.BASE_P_VertAxisOffset_valid, m_tag);
                }
                else
                {
                    v.Error(T.BASE_HeaderOffsets, E.BASE_E_VertAxisOffset_OutsideTable, m_tag);
                    bRet = false;
                }
            }

            if (v.PerformTest(T.BASE_HorizAxisTable))
            {
                AxisTable_val at = GetHorizAxisTable_val();
                if (at != null)
                {
                    at.Validate(v, "H Axis", this);
                }
            }

            if (v.PerformTest(T.BASE_VertAxisTable))
            {
                AxisTable_val at = GetVertAxisTable_val();
                if (at != null)
                {
                    at.Validate(v, "V Axis", this);
                }
            }
            // TODO: BASE Item Variation Store

            return(bRet);
        }
示例#52
0
        protected bool CheckTableAlignment(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.offset & 0x03) != 0)
                    {
                        v.Warning(T.T_NULL, W._DE_W_TableAlignment, null, (string)de.tag);
                        //bRet = false;
                    }
                }

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

            }

            return bRet;
        }
示例#53
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;
        }
示例#54
0
        private bool CheckCodePageRanges(Validator v, OTFont fontOwner)
        {
            bool bRet = true;

            bRet &= CheckCodePageBit(0, 1252, "Latin 1",    v, fontOwner);
            bRet &= CheckCodePageBit(1, 1250, "Latin 2",    v, fontOwner);
            bRet &= CheckCodePageBit(2, 1251, "Cyrillic",   v, fontOwner);
            bRet &= CheckCodePageBit(3, 1253, "Greek",      v, fontOwner);
            bRet &= CheckCodePageBit(4, 1254, "Turkish",    v, fontOwner);
            bRet &= CheckCodePageBit(5, 1255, "Hebrew",     v, fontOwner);
            bRet &= CheckCodePageBit(6, 1256, "Arabic",     v, fontOwner);
            bRet &= CheckCodePageBit(7, 1257, "Baltic",     v, fontOwner);
            bRet &= CheckCodePageBit(8, 1258, "Vietnamese", v, fontOwner);

            // bits 9-15 are reserved
            bRet &= CheckCodePageBit( 9, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(10, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(11, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(12, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(13, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(14, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(15, 0, null, v, fontOwner);


            bRet &= CheckCodePageBit(16,  874, "Thai",                v, fontOwner);
            bRet &= CheckCodePageBit(17,  932, "Japanese Shift-JIS",  v, fontOwner);
            bRet &= CheckCodePageBit(18,  936, "Chinese simplified",  v, fontOwner);
            bRet &= CheckCodePageBit(19,  949, "Korean Wansung",      v, fontOwner);
            bRet &= CheckCodePageBit(20,  950, "Chinese traditional", v, fontOwner);
            bRet &= CheckCodePageBit(21, 1361, "Korean Johab",        v, fontOwner);

            // bits 22-28 are reserved
            bRet &= CheckCodePageBit(22, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(23, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(24, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(25, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(26, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(27, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(28, 0, null, v, fontOwner);


            bRet &= CheckCodePageBit(29, 10000, "Mac character set", v, fontOwner);
            //bRet &= CheckCodePageBit(30, ???? , "OEM character set", v, fontOwner); // no code page specified
            bRet &= CheckCodePageBit(31, 0, "Symbol character set", v, fontOwner);


            // bits 32-47 are reserved
            bRet &= CheckCodePageBit(32, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(33, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(34, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(35, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(36, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(37, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(38, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(39, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(40, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(41, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(42, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(43, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(44, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(45, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(46, 0, null, v, fontOwner);
            bRet &= CheckCodePageBit(47, 0, null, v, fontOwner);


            bRet &= CheckCodePageBit(48, 869, "IBM Greek",              v, fontOwner);
            bRet &= CheckCodePageBit(49, 866, "MS-DOS Russian",         v, fontOwner);
            bRet &= CheckCodePageBit(50, 865, "MS-DOS Nordic",          v, fontOwner);
            bRet &= CheckCodePageBit(51, 864, "Arabic",                 v, fontOwner);
            bRet &= CheckCodePageBit(52, 863, "MS-DOS Canadian French", v, fontOwner);
            bRet &= CheckCodePageBit(53, 862, "Hebrew",                 v, fontOwner);
            bRet &= CheckCodePageBit(54, 861, "MS-DOS Icelandic",       v, fontOwner);
            bRet &= CheckCodePageBit(55, 860, "MS-DOS Portuguese",      v, fontOwner);
            bRet &= CheckCodePageBit(56, 857, "IBM Turkish",            v, fontOwner);
            bRet &= CheckCodePageBit(57, 855, "IBM Cyrillic",           v, fontOwner);
            bRet &= CheckCodePageBit(58, 852, "Latin 2",                v, fontOwner);
            bRet &= CheckCodePageBit(59, 775, "MS-DOS Baltic",          v, fontOwner);
            bRet &= CheckCodePageBit(60, 737, "Greek",                  v, fontOwner);
            bRet &= CheckCodePageBit(61, 708, "Arabic; ASMO 708",       v, fontOwner);
            bRet &= CheckCodePageBit(62, 850, "WE/Latin 1",             v, fontOwner);
            bRet &= CheckCodePageBit(63, 437, "US",                     v, fontOwner);

            if (bRet == true)
            {
                v.Pass(P.OS_2_P_CodePageRanges, m_tag);
            }

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

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

                // check the BaseValuesOffset
                if (BaseValuesOffset == 0)
                {
                    v.Pass(T.T_NULL, P.BASE_P_BaseValuesOffset_null, table.m_tag, sIdentity);
                }
                else if (BaseValuesOffset + m_offsetBaseScriptTable > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.BASE_E_BaseValuesOffset, table.m_tag, sIdentity);
                }
                else
                {
                    v.Pass(T.T_NULL, P.BASE_P_BaseValuesOffset, table.m_tag, sIdentity);
                }

                // check the DefaultMinMaxOffset
                if (DefaultMinMaxOffset == 0)
                {
                    v.Pass(T.T_NULL, P.BASE_P_DefaultMinMaxOffset_null, table.m_tag, sIdentity);
                }
                else if (DefaultMinMaxOffset + m_offsetBaseScriptTable > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.BASE_E_DefaultMinMaxOffset, table.m_tag, sIdentity);
                }
                else
                {
                    v.Pass(T.T_NULL, P.BASE_P_DefaultMinMaxOffset, table.m_tag, sIdentity);
                }

                // check the BaseLangSysRecord order
                bool bOrderOk = true;

                if (BaseLangSysCount > 1)
                {
                    for (uint i = 0; i < BaseLangSysCount - 1; i++)
                    {
                        BaseLangSysRecord ThisBlsr = GetBaseLangSysRecord(i);
                        BaseLangSysRecord NextBlsr = GetBaseLangSysRecord(i + 1);
                        if (ThisBlsr.BaseLangSysTag >= NextBlsr.BaseLangSysTag)
                        {
                            v.Error(T.T_NULL, E.BASE_E_BaseLangSysRecord_order, table.m_tag, sIdentity);
                            bOrderOk = false;
                            bRet     = false;
                        }
                    }
                }
                if (bOrderOk)
                {
                    v.Pass(T.T_NULL, P.BASE_P_BaseLangSysRecord_order, table.m_tag, sIdentity);
                }

                // check the BaseLangSysRecord MinMaxOffsets
                bool bOffsetsOk = true;

                for (uint i = 0; i < BaseLangSysCount; i++)
                {
                    BaseLangSysRecord bslr = GetBaseLangSysRecord(i);
                    if (bslr.MinMaxOffset == 0)
                    {
                        v.Error(T.T_NULL, E.BASE_E_BaseLangSysRecord_offset0, table.m_tag, sIdentity + ", BaseLangSysRecord index = " + i);
                        bOffsetsOk = false;
                        bRet       = false;
                    }
                    else if (bslr.MinMaxOffset + m_offsetBaseScriptTable > m_bufTable.GetLength())
                    {
                        v.Error(T.T_NULL, E.BASE_E_BaseLangSysRecord_offset, table.m_tag, sIdentity + ", BaseLangSysRecord index = " + i);
                        bOffsetsOk = false;
                        bRet       = false;
                    }
                }
                if (bOffsetsOk)
                {
                    v.Pass(T.T_NULL, P.BASE_P_BaseLangSysRecord_offsets, table.m_tag, sIdentity);
                }

                // check the BaseValuesTable
                if (BaseValuesOffset != 0)
                {
                    BaseValuesTable_val bvt = GetBaseValuesTable_val();
                    bvt.Validate(v, sIdentity, table);
                }

                // check the Default MinMaxTable
                if (DefaultMinMaxOffset != 0)
                {
                    MinMaxTable_val mmt = GetDefaultMinMaxTable_val();
                    mmt.Validate(v, sIdentity + ", default MinMax", table);
                }

                // check the BaseLangSysRecord MinMaxTables
                for (uint i = 0; i < BaseLangSysCount; i++)
                {
                    BaseLangSysRecord blsr = GetBaseLangSysRecord(i);
                    MinMaxTable_val   mmt  = GetMinMaxTable_val(blsr);
                    mmt.Validate(v, sIdentity + ", BaseLangSysRecord[" + i + "]", table);
                }

                return(bRet);
            }
示例#56
0
        /*****************
         * public methods
         */


        public bool Validate()
        {
            bool bRet = true;
            int  canrast;

            Validator v = GetFile().GetValidator();

            if (v.PerformTest(T._OFFSET_sfntVersion))
            {
                uint sfnt = m_OffsetTable.sfntVersion.GetUint();
                if (!OTFile.IsValidSfntVersion(sfnt))
                {
                    v.Error(T._OFFSET_sfntVersion, E._OFFSET_E_InvalidSFNT, null, "0x" + sfnt.ToString("x8"));
                    bRet = false;
                }
            }

            if (v.PerformTest(T._OFFSET_numTables))
            {
                if (m_OffsetTable.numTables == 0)
                {
                    v.Error(T._OFFSET_numTables, E._OFFSET_E_numTables, null);
                    bRet = false;
                }
                else
                {
                    v.Pass(T._OFFSET_numTables, P._OFFSET_P_numTables, null, m_OffsetTable.numTables.ToString());
                }
            }

            if (v.PerformTest(T._OFFSET_BinarySearchFields))
            {
                ushort numTables               = m_OffsetTable.numTables;
                ushort CalculatedSearchRange   = (ushort)(util.MaxPower2LE(numTables) * 16);
                ushort CalculatedEntrySelector = util.Log2(util.MaxPower2LE(numTables));
                ushort CalculatedRangeShift    = (ushort)(numTables * 16 - CalculatedSearchRange);

                bool bBinaryFieldsOk = true;

                if (m_OffsetTable.searchRange != CalculatedSearchRange)
                {
                    v.Error(T._OFFSET_BinarySearchFields, E._OFFSET_E_searchRange, null, m_OffsetTable.searchRange.ToString());
                    bBinaryFieldsOk = false;
                    bRet            = false;
                }
                if (m_OffsetTable.entrySelector != CalculatedEntrySelector)
                {
                    v.Error(T._OFFSET_BinarySearchFields, E._OFFSET_E_entrySelector, null, m_OffsetTable.entrySelector.ToString());
                    bBinaryFieldsOk = false;
                    bRet            = false;
                }
                if (m_OffsetTable.rangeShift != CalculatedRangeShift)
                {
                    v.Error(T._OFFSET_BinarySearchFields, E._OFFSET_E_rangeShift, null, m_OffsetTable.rangeShift.ToString());
                    bBinaryFieldsOk = false;
                    bRet            = false;
                }

                if (bBinaryFieldsOk)
                {
                    v.Pass(T._OFFSET_BinarySearchFields, P._OFFSET_P_BinarySearchTables, null);
                }
            }

            bRet &= CheckDirectoryEntriesNonZero(v);

            bRet &= CheckTablesInFileAndNotOverlapping(v);

            bRet &= CheckNoDuplicateTags(v);

            if (v.PerformTest(T._DE_TagsAscendingOrder))
            {
                bRet &= CheckTagsAscending(v);
            }

            if (v.PerformTest(T._DE_TagNames))
            {
                bRet &= CheckTagNames(v);
            }

            if (v.PerformTest(T._DE_TableAlignment))
            {
                bRet &= CheckTableAlignment(v);
            }

            if (v.PerformTest(T._FONT_RequiredTables))
            {
                bRet &= CheckForRequiredTables(v);
            }

            if (v.PerformTest(T._FONT_RecommendedTables))
            {
                bRet &= CheckForRecommendedTables(v);
            }

            if (v.PerformTest(T._FONT_UnnecessaryTables))
            {
                bRet &= CheckForNoUnnecessaryTables(v);
            }

            if (v.PerformTest(T._FONT_OptimalTableOrder))
            {
                bRet &= CheckForOptimalTableOrder(v);
            }


            // Validate each table

            if (m_OffsetTable != null)
            {
                for (int i = 0; i < m_OffsetTable.DirectoryEntries.Count; i++)
                {
                    // check to see if user canceled validation
                    if (v.CancelFlag)
                    {
                        break;
                    }

                    // get the table
                    DirectoryEntry de    = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i];
                    OTTable        table = GetFile().GetTableManager().GetTable(this, de);

                    // Will it really happen?
                    if (GetFile().GetTableManager().GetUnaliasedTableName(de.tag) == "DSIG" && GetFile().IsCollection())
                    {
                        continue;
                    }

                    if (GetFile().GetTableManager().GetUnaliasedTableName(de.tag) == "glyf" &&
                        Is_TTC_LaterIdenticalTable("glyf"))
                    {
                        v.Info(T.T_NULL, I.glyf_I_IDENTICAL_GLYF_TABLES_IN_TTC, de.tag, "glyf");
                        continue;
                    }

                    if (GetFile().GetTableManager().GetUnaliasedTableName(de.tag) == "EBDT" &&
                        Is_TTC_LaterIdenticalTable("EBDT"))
                    {
                        v.Info(T.T_NULL, I.glyf_I_IDENTICAL_GLYF_TABLES_IN_TTC, de.tag, "EBDT");
                        continue;
                    }

                    // Call the function that validates a single table
                    bRet &= this.GetFile().ValidateTable(table, v, de, this);
                }
            }

            canrast = TestFontRasterization();
            ushort numGlyphs = GetMaxpNumGlyphs();

            // rasterization test - BW

            v.OnRastTestValidationEvent_BW(true);
            if (v.PeformRastTest_BW() && Is_TTC_LaterIdenticalTable("glyf"))
            {
                v.Info(T.T_NULL, I.glyf_I_IDENTICAL_GLYF_TABLES_IN_TTC, null, "B/W Rasterization");
            }
            else
            if (v.PeformRastTest_BW())
            {
                if (canrast > 0)
                {
                    try
                    {
                        // fetch the rasterizer object and initialize it with this font
                        RasterInterf ri = GetFile().GetRasterizer();
                        ri.RasterNewSfnt(GetFile().GetFileStream(), GetFontIndexInFile());


                        // call the rasterizer
                        RasterInterf.UpdateProgressDelegate upg  = new RasterInterf.UpdateProgressDelegate(v.OnTableProgress);
                        RasterInterf.RastTestErrorDelegate  rted = new RasterInterf.RastTestErrorDelegate(v.OnRastTestError);
                        int               x          = v.GetRastTestXRes();
                        int               y          = v.GetRastTestYRes();
                        int []            pointsizes = v.GetRastTestPointSizes();
                        RastTestTransform rtt        = v.GetRastTestTransform();
                        bRet &= ri.RastTest(
                            x, y, pointsizes,
                            rtt.stretchX, rtt.stretchY, rtt.rotation, rtt.skew, rtt.matrix,
                            true, false, false, 0,
                            rted, upg, numGlyphs);
                        if (ri.GetRastErrorCount() == 0)
                        {
                            v.Pass(T.T_NULL, P._rast_P_rasterization, null);
                        }
                    }
                    catch (Exception e)
                    {
                        v.ApplicationError(T.T_NULL, E._rast_A_ExceptionUnhandled, null, e.Message + e.StackTrace);
                    }
                }
                else if (canrast == 0)
                {
                    v.Info(T.T_NULL, I._rast_I_rasterization, null, GetDevMetricsDataError());
                }
                else
                {
                    v.Error(T.T_NULL, E._rast_E_rasterization, null, GetDevMetricsDataError());
                    bRet = false;
                }
            }
            else
            {
                v.Info(I._TEST_I_RastTestNotSelected, null);
            }
            v.OnRastTestValidationEvent_BW(false);


            // rasterization test - Grayscale

            v.OnRastTestValidationEvent_Grayscale(true);
            if (v.PeformRastTest_Grayscale() && Is_TTC_LaterIdenticalTable("glyf"))
            {
                v.Info(T.T_NULL, I.glyf_I_IDENTICAL_GLYF_TABLES_IN_TTC, null, "Grayscale Rasterization");
            }
            else
            if (v.PeformRastTest_Grayscale())
            {
                if (canrast > 0)
                {
                    try
                    {
                        // fetch the rasterizer object and initialize it with this font
                        RasterInterf ri = GetFile().GetRasterizer();
                        ri.RasterNewSfnt(GetFile().GetFileStream(), GetFontIndexInFile());


                        // call the rasterizer
                        RasterInterf.UpdateProgressDelegate upg  = new RasterInterf.UpdateProgressDelegate(v.OnTableProgress);
                        RasterInterf.RastTestErrorDelegate  rted = new RasterInterf.RastTestErrorDelegate(v.OnRastTestError);
                        int               x          = v.GetRastTestXRes();
                        int               y          = v.GetRastTestYRes();
                        int []            pointsizes = v.GetRastTestPointSizes();
                        RastTestTransform rtt        = v.GetRastTestTransform();
                        bRet &= ri.RastTest(
                            x, y, pointsizes,
                            rtt.stretchX, rtt.stretchY, rtt.rotation, rtt.skew, rtt.matrix,
                            false, true, false, 0,
                            rted, upg, numGlyphs);
                        if (ri.GetRastErrorCount() == 0)
                        {
                            v.Pass(T.T_NULL, P._rast_P_rasterization, null);
                        }
                    }
                    catch (Exception e)
                    {
                        v.ApplicationError(T.T_NULL, E._rast_A_ExceptionUnhandled, null, e.Message + e.StackTrace);
                    }
                }
                else if (canrast == 0)
                {
                    v.Info(T.T_NULL, I._rast_I_rasterization, null, GetDevMetricsDataError());
                }
                else
                {
                    v.Error(T.T_NULL, E._rast_E_rasterization, null, GetDevMetricsDataError());
                    bRet = false;
                }
            }
            else
            {
                v.Info(I._TEST_I_RastTestNotSelected, null);
            }
            v.OnRastTestValidationEvent_Grayscale(false);



            // rasterization test - Cleartype

            v.OnRastTestValidationEvent_Cleartype(true);
            if (v.PeformRastTest_Cleartype() && Is_TTC_LaterIdenticalTable("glyf"))
            {
                v.Info(T.T_NULL, I.glyf_I_IDENTICAL_GLYF_TABLES_IN_TTC, null, "Cleartype Rasterization");
            }
            else
            if (v.PeformRastTest_Cleartype())
            {
                if (canrast > 0)
                {
                    try
                    {
                        uint CTFlags = v.GetCleartypeFlags();

                        // fetch the rasterizer object and initialize it with this font
                        RasterInterf ri = GetFile().GetRasterizer();
                        ri.RasterNewSfnt(GetFile().GetFileStream(), GetFontIndexInFile());


                        // call the rasterizer
                        RasterInterf.UpdateProgressDelegate upg  = new RasterInterf.UpdateProgressDelegate(v.OnTableProgress);
                        RasterInterf.RastTestErrorDelegate  rted = new RasterInterf.RastTestErrorDelegate(v.OnRastTestError);
                        int               x          = v.GetRastTestXRes();
                        int               y          = v.GetRastTestYRes();
                        int []            pointsizes = v.GetRastTestPointSizes();
                        RastTestTransform rtt        = v.GetRastTestTransform();
                        bRet &= ri.RastTest(
                            x, y, pointsizes,
                            rtt.stretchX, rtt.stretchY, rtt.rotation, rtt.skew, rtt.matrix,
                            false, false, true, CTFlags,
                            rted, upg, numGlyphs);
                        if (ri.GetRastErrorCount() == 0)
                        {
                            v.Pass(T.T_NULL, P._rast_P_rasterization, null);
                        }
                    }
                    catch (Exception e)
                    {
                        v.ApplicationError(T.T_NULL, E._rast_A_ExceptionUnhandled, null, e.Message + e.StackTrace);
                    }
                }
                else if (canrast == 0)
                {
                    v.Info(T.T_NULL, I._rast_I_rasterization, null, GetDevMetricsDataError());
                }
                else
                {
                    v.Error(T.T_NULL, E._rast_E_rasterization, null, GetDevMetricsDataError());
                    bRet = false;
                }
            }
            else
            {
                v.Info(I._TEST_I_RastTestNotSelected, null);
            }
            v.OnRastTestValidationEvent_Cleartype(false);

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

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

                // check the MinCoordOffset
                if (MinCoordOffset == 0)
                {
                    v.Pass(T.T_NULL, P.BASE_P_MinMaxTable_MinCO_0, table.m_tag, sIdentity);
                }
                else if (MinCoordOffset + m_offsetMinMaxTable > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.BASE_E_MinMaxTable_MinCO, table.m_tag, sIdentity);
                    bRet = false;
                }
                else
                {
                    v.Pass(T.T_NULL, P.BASE_P_MinMaxTable_MinCO, table.m_tag, sIdentity);
                }

                // check the MaxCoordOffset
                if (MaxCoordOffset == 0)
                {
                    v.Pass(T.T_NULL, P.BASE_P_MinMaxTable_MaxCO_0, table.m_tag, sIdentity);
                }
                else if (MaxCoordOffset + m_offsetMinMaxTable > m_bufTable.GetLength())
                {
                    v.Error(T.T_NULL, E.BASE_E_MinMaxTable_MaxCO, table.m_tag, sIdentity);
                    bRet = false;
                }
                else
                {
                    v.Pass(T.T_NULL, P.BASE_P_MinMaxTable_MaxCO, table.m_tag, sIdentity);
                }

                // check the FeatMinMaxRecords
                bool bFeatMinMaxRecordsOk = true;

                for (uint i = 0; i < FeatMinMaxCount; i++)
                {
                    FeatMinMaxRecord fmmr = GetFeatMinMaxRecord(i);

                    if (fmmr != null)
                    {
                        if (fmmr.MinCoordOffset + m_offsetMinMaxTable > m_bufTable.GetLength())
                        {
                            v.Error(T.T_NULL, E.BASE_E_FeatMinMaxRecords_MinCO_offset, table.m_tag, sIdentity + ", FeatMinMaxRecord[" + i + "]");
                            bFeatMinMaxRecordsOk = false;
                            bRet = false;
                        }

                        if (fmmr.MaxCoordOffset + m_offsetMinMaxTable > m_bufTable.GetLength())
                        {
                            v.Error(T.T_NULL, E.BASE_E_FeatMinMaxRecords_MaxCO_offset, table.m_tag, sIdentity + ", FeatMinMaxRecord[" + i + "]");
                            bFeatMinMaxRecordsOk = false;
                            bRet = false;
                        }
                    }
                    else
                    {
                        bFeatMinMaxRecordsOk = false;
                    }
                }
                if (bFeatMinMaxRecordsOk)
                {
                    v.Pass(T.T_NULL, P.BASE_P_FeatMinMaxRecords_offsets, table.m_tag, sIdentity);
                }

                // check the BaseCoord Tables
                BaseCoordTable_val bct = null;

                bct = GetMinCoordTable_val();
                if (bct != null)
                {
                    bct.Validate(v, sIdentity, table);
                }

                bct = GetMaxCoordTable_val();
                if (bct != null)
                {
                    bct.Validate(v, sIdentity, table);
                }
                for (uint i = 0; i < FeatMinMaxCount; i++)
                {
                    FeatMinMaxRecord fmmr = GetFeatMinMaxRecord(i);

                    bct = GetFeatMinCoordTable_val(fmmr);
                    if (bct != null)
                    {
                        bct.Validate(v, sIdentity, table);
                    }

                    bct = GetFeatMaxCoordTable_val(fmmr);
                    if (bct != null)
                    {
                        bct.Validate(v, sIdentity, table);
                    }
                }

                return(bRet);
            }
示例#58
0
        /************************
         * public methods
         */


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

            if (v.PerformTest(T.gasp_Version))
            {
                if (version == 0 || version == 1)
                {
                    v.Pass(T.gasp_Version, P.gasp_P_Version, m_tag, "version = " + version.ToString());
                }
                else
                {
                    v.Error(T.gasp_Version, E.gasp_E_Version, m_tag, "version = " + version.ToString() + ", unable to continue validation");
                    return false;
                }
            }

            if (v.PerformTest(T.gasp_rangeGaspBehavior))
            {
                bool bFlagsOk = true;
                string first_error = null;
                for (uint i=0; i<numRanges; i++)
                {
                    GaspRange gr = GetGaspRange(i);
                    if (gr != null)
                    {
                        if (   (version == 0 && gr.rangeGaspBehavior > 0x3)
                            || (version == 1 && gr.rangeGaspBehavior > 0xf))
                        {
                            bFlagsOk = false;
                            first_error = "version=" + version + ", range #" + i + ", rangeGaspBehavior=0x"
                                + gr.rangeGaspBehavior.ToString("X4");
                            break;
                        }
                    }
                }
                if (bFlagsOk)
                {
                    v.Pass(T.gasp_rangeGaspBehavior, P.gasp_P_rangeGaspBehavior, m_tag);
                }
                else
                {
                    v.Error(T.gasp_rangeGaspBehavior, E.gasp_E_rangeGaspBehavior, m_tag, first_error);
                    bRet = false;
                }
            }

            if (v.PerformTest(T.gasp_SortOrder))
            {
                bool bSortOk = true;
                if (numRanges > 1)
                {
                    GaspRange grCurr = GetGaspRange(0);
                    GaspRange grNext = null;
                    for (uint i=1; i<numRanges; i++)
                    {
                        grNext = GetGaspRange(i);
                        if (grCurr.rangeMaxPPEM >= grNext.rangeMaxPPEM)
                        {
                            bSortOk = false;
                            break;
                        }
                        grCurr = grNext;
                    }
                }
                if (bSortOk)
                {
                    v.Pass(T.gasp_SortOrder, P.gasp_P_SortOrder, m_tag);
                }
                else
                {
                    v.Error(T.gasp_SortOrder, E.gasp_E_SortOrder, m_tag);
                    bRet = false;
                }
            }

            if (v.PerformTest(T.gasp_Sentinel))
            {
                GaspRange gr = GetGaspRange((uint)numRanges-1);
                if (gr.rangeMaxPPEM == 0xFFFF)
                {
                    v.Pass(T.gasp_Sentinel, P.gasp_P_Sentinel, m_tag);
                }
                else
                {
                    v.Error(T.gasp_Sentinel, E.gasp_E_Sentinel, m_tag);
                    bRet = false;
                }
            }

            if (v.PerformTest(T.gasp_AdjRangeIdenticalFlags))
            {
                bool bNoAdjIdent = true;

                if (numRanges > 1)
                {
                    for (uint i=0; i<numRanges-1; i++)
                    {
                        GaspRange grCurr = GetGaspRange(i);
                        GaspRange grNext = GetGaspRange(i+1);
                        if (grCurr.rangeGaspBehavior == grNext.rangeGaspBehavior)
                        {
                            string sDetails = "rangeGaspBehavior[" + i + "] = " + grCurr.rangeGaspBehavior + ", rangeGaspBehavior[" + (i+1) + "] = " + grNext.rangeGaspBehavior;
                            v.Warning(T.gasp_AdjRangeIdenticalFlags, W.gasp_W_AdjRangeIdenticalFlags, m_tag, sDetails);
                            bNoAdjIdent = false;
                        }
                    }
                }

                if (bNoAdjIdent)
                {
                    v.Pass(T.gasp_AdjRangeIdenticalFlags, P.gasp_P_AdjRangeIdenticalFlags, m_tag);
                }
            }

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