public int DoIt( )
 {
     Validator v = new Validator();
     m_vp.SetupValidator( v );
     OTFontFileVal.Driver driver = new OTFontFileVal.Driver( this );
     return driver.RunValidation( v, m_sFiles );
 }
Example #2
0
 public bool ValidateNumEntries(Validator validator,
     OTFont fontOwner)
 {
     int numGlyph=this.NumGlyph(fontOwner);
     int numEntry=this.NumEntry(fontOwner);
     if ((numGlyph==Table_loca.ValueInvalid)||
         (numEntry==Table_loca.ValueInvalid)||
         (numEntry!=numGlyph+1))
     {
         if (validator!=null)
         {
             validator.Error(T.T_NULL,
                 E.loca_E_NumEntries, 
                 m_tag, 
                 "number of entries="+numEntry+" number of glyphs="+numGlyph);
         }
         return false;    
     }
     else
     {
         if (validator!=null)
         {
             validator.Pass(P.loca_P_NumEntries, m_tag);
         }
         return true;
     }
 }
Example #3
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;
        }
Example #4
0
        /************************
         * public methods
         */


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

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

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

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


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

            v.Info(I.fpgm_I_NotValidated, m_tag);
            
            return bRet;
        }
 /*
  *        CONSTRUCTORS
  */
 public I_IOGlyphsFile()
 {
     this.m_font=null;
     this.m_tableLoca=null;
     this.m_tableGlyf=null;
     this.m_validator=null;
     this.m_numGlyph=GConsts.IND_UNINITIALIZED;
     this.m_toCloseFileOnClear=false;
 }
Example #7
0
        /************************
         * public methods
         */

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

            v.Info(T.T_NULL, I.CFF_I_Version, m_tag, major + "." + minor);
            v.Info(I.CFF_I_NotValidated, m_tag);
            
            return bRet;
        }
Example #8
0
            public bool Validate(Validator v, string sIdentity, OTTable tableOwner)
            {
                bool bOk = true;

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

                return bOk;
            }
Example #9
0
        /***************
         * constructors
         */


        public OTFileVal(Validator v)
        {
            if (v == null)
            {
                throw new ArgumentNullException();
            }

            m_TableManager = new TableManagerVal(this);
            m_Validator = v;
        }
Example #10
0
        /************************
         * public methods
         */


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

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

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

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

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


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

            if (v.PerformTest(T.cvt_length))
            {
                if ((m_bufTable.GetLength() & 1) != 0)
                {
                    v.Error(T.cvt_length, E.cvt_E_length_odd, m_tag);
                    bRet = false;
                }
                else
                {
                    v.Pass(T.cvt_length, P.cvt_P_length_even, m_tag);
                }
            }
            
            return bRet;
        }
Example #12
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;
            }
        }
Example #13
0
        public Progress( Form1 formParent, 
                         Validator v, 
                         string [] sFilenames, 
                         ReportFileDestination rfd, 
                         bool bOpenReportFiles, 
                         string sReportFixedDir )
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //

            m_Validator = v;
            m_sFiles = sFilenames;
            m_formParent = formParent;
            m_bValidationInProgress = false;
            m_ReportFileDestination = rfd;
            m_bOpenReportFiles = bOpenReportFiles;
            m_sReportFixedDir = sReportFixedDir;
        }
Example #14
0
            public bool Validate(Validator v, OTTable table, ushort numGlyphs,
                                 String sIdentity)
            {
                bool bRet = true;

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

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

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

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

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

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

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


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

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

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

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

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

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

                bool bBitsOk = true;

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

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

            }

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

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

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

                bool bBitsOk = true;

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

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

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

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


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


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

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

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

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

                // bit 2 indicates instructions may depend on point size

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

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

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

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

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

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

                // bit 12 indicates a converted font

                // bit 13 indicates optimized for cleartype

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

                bool bInRange = false;

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

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

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

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

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

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

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

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

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

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

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

                // subfamily (style) string

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

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

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

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

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

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

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

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


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

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

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

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

            bool bScriptTableOk = true;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                            break;

                        }
                    }
                }

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

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

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

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

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

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


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

            if (v.PerformTest(T.GDEF_Version))
            {
                if (Version.GetUint() == 0x00010000)
                {
                    v.Pass(T.GDEF_Version, P.GDEF_P_Version, m_tag);
                }
                else
                {
                    v.Error(T.GDEF_Version, E.GDEF_E_Version, m_tag, "0x" + Version.GetUint().ToString("x8"));
                }
            }

            if (v.PerformTest(T.GDEF_HeaderOffsets))
            {
                bool bOffsetsOk = true;

                if (GlyphClassDefOffset != 0)
                {
                    if (GlyphClassDefOffset > m_bufTable.GetLength())
                    {
                        v.Error(T.GDEF_HeaderOffsets, E.GDEF_E_HeaderOffset, m_tag, "GlyphClassDef");
                        bOffsetsOk = false;
                        bRet       = false;
                    }
                }

                if (AttachListOffset != 0)
                {
                    if (AttachListOffset > m_bufTable.GetLength())
                    {
                        v.Error(T.GDEF_HeaderOffsets, E.GDEF_E_HeaderOffset, m_tag, "AttachList");
                        bOffsetsOk = false;
                        bRet       = false;
                    }
                }

                if (LigCaretListOffset != 0)
                {
                    if (LigCaretListOffset > m_bufTable.GetLength())
                    {
                        v.Error(T.GDEF_HeaderOffsets, E.GDEF_E_HeaderOffset, m_tag, "LigCaretList");
                        bOffsetsOk = false;
                        bRet       = false;
                    }
                }

                if (MarkAttachClassDefOffset != 0)
                {
                    if (MarkAttachClassDefOffset > m_bufTable.GetLength())
                    {
                        v.Error(T.GDEF_HeaderOffsets, E.GDEF_E_HeaderOffset, m_tag, "MarkAttachClassDef");
                        bOffsetsOk = false;
                        bRet       = false;
                    }
                }


                if (bOffsetsOk == true)
                {
                    v.Pass(T.GDEF_HeaderOffsets, P.GDEF_P_HeaderOffsets, m_tag);
                }
            }

            if (v.PerformTest(T.GDEF_Subtables))
            {
                if (GlyphClassDefOffset != 0)
                {
                    ClassDefTable_val cdt = GetGlyphClassDefTable_val();
                    cdt.Validate(v, "GlyphClassDef", this);
                }

                if (AttachListOffset != 0)
                {
                    AttachListTable_val alt = GetAttachListTable_val();
                    alt.Validate(v, "AttachList", this);
                }

                if (LigCaretListOffset != 0)
                {
                    LigCaretListTable_val lclt = GetLigCaretListTable_val();
                    lclt.Validate(v, "LigCaretList", this);
                }

                if (MarkAttachClassDefOffset != 0)
                {
                    ClassDefTable_val macdt = GetMarkAttachClassDefTable_val();
                    macdt.Validate(v, "MarkAttachClassDef", this);
                }
            }

            return(bRet);
        }
Example #23
0
            public bool Validate(Validator v, OTTable table, ushort numGlyphs,
                                 String sIdentity)
            {
                bool bRet = true;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                return bRet;
            }
Example #24
0
            public bool Validate(Validator v, OTTable table, ushort numGlyphs,
                                 String sIdentity)
            {
                bool bRet = true;

                // check the length

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

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


                return bRet;
            }
Example #25
0
            public bool Validate( Validator v, 
                                  OTTable table, 
                                  ushort numGlyphs,
                                  String sIdentity )
            {

                bool bRet = true;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                            etePrev = ete;
                        }
                    }

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

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

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

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

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

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

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

                            etePrev = ete;
                        }
                    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return bRet;
        }
Example #28
0
            public bool Validate(Validator v, OTTable table, ushort numGlyphs,
                                 String sIdentity)
            {
                bool bRet = true;

                
                // check the mapping

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


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

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

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

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

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

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


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


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


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

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

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

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

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

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

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

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

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

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

                RasterInterf.DevMetricsData dmd = null;

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

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

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

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

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

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

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

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

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

                                            bDataOk = false;

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

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

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

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

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

            return bRet;
        }