예제 #1
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;
        }
예제 #2
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;
        }
예제 #3
0
        /************************
         * public methods
         */
        
        
        public bool Validate(Validator v, OTFontVal fontOwner)
        {
            bool bRet = true;

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

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

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

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

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

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

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

                                try
                                {

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

                                    if (hmSpace != null)
                                    {

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

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

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

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

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

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

                }
            }

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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




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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return bRet;
        }
예제 #4
0
        private bool CheckNames(Validator v,
                                OTFontVal fontOwner,
                                PostNames pn,
                                uint iGlyph,
                                uint index)
        {
            bool   bNamesOk = true;
            string sName    = GetNameString(index - 258);

            System.Globalization.NumberStyles hexStyle =
                System.Globalization.NumberStyles.HexNumber;
            if (Is_uniXXXX(sName))
            {
                char c = (char)Int16.Parse(sName.Substring(3, 4), hexStyle);
                if (fontOwner.FastMapUnicodeToGlyphID(c) != iGlyph)
                {
                    char   cMapped = fontOwner.MapGlyphIDToUnicode(iGlyph, (char)0);
                    string s       = "glyph = " + iGlyph +
                                     ", char = U+" +
                                     ((uint)cMapped).ToString("X4")
                                     + ", name = " + sName;
                    v.Info(T.post_v2_names,
                           I.post_I_names_uni_unexpected,
                           m_tag, s);
                    bNamesOk = false;
                }
            }
            else if (Is_uXXXXX(sName))
            {
                uint c = (uint)Int32.Parse(sName.Substring(1), hexStyle);
                if (c < 0xffff)
                {
                    if (fontOwner.FastMapUnicodeToGlyphID((char)c) != iGlyph)
                    {
                        char cMapped = fontOwner.MapGlyphIDToUnicode(iGlyph,
                                                                     (char)0);
                        string s = "glyph = " + iGlyph + ", char = U+" +
                                   ((uint)cMapped).ToString("X4") + ", name = " + sName;
                        v.Info(T.post_v2_names, I.post_I_names_uni_unexpected,
                               m_tag, s);
                        bNamesOk = false;
                    }
                }
                else
                {
                    if (fontOwner.FastMapUnicode32ToGlyphID(c) != iGlyph)
                    {
                        uint cMapped =
                            fontOwner.MapGlyphIDToUnicode32(iGlyph, 0);
                        string s = "glyph = " + iGlyph + ", char = U+" +
                                   ((uint)cMapped).ToString("X5") + ", name = " + sName;
                        v.Info(T.post_v2_names, I.post_I_names_uni_unexpected,
                               m_tag, s);
                        bNamesOk = false;
                    }
                }
            }
            else
            {
                // check the Adobe Glyph Names

                char c = (char)fontOwner.MapGlyphIDToUnicode(iGlyph, (char)0);
                if (c != 0xffff)
                {
                    string sAdobeName = pn.GetAdobeGlyphName(c);
                    if (sAdobeName == null)
                    {
                        string s = "glyph = " + iGlyph + ", char = U+" +
                                   ((uint)c).ToString("X4") + ", name = " + sName;
                        v.Info(T.post_v2_names, I.post_I_names_noAdobe, m_tag, s);
                        bNamesOk = false;
                    }
                    else if (sName != sAdobeName)
                    {
                        string s = "glyph = " + iGlyph + ", char = U+" +
                                   ((uint)c).ToString("X4") + ", name = " + sName;
                        v.Info(T.post_v2_names, I.post_I_names_nomatch, m_tag, s);
                        bNamesOk = false;
                    }
                }
            }
            return(bNamesOk);
        }
예제 #5
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);
        }
예제 #6
0
 private bool CheckNames( Validator v,
                          OTFontVal fontOwner,
                          PostNames pn,
                          uint iGlyph,
                          uint index )
 {
     bool bNamesOk = true;
     string sName = GetNameString(index-258);
     System.Globalization.NumberStyles hexStyle = 
         System.Globalization.NumberStyles.HexNumber;
     if (Is_uniXXXX(sName))
     {
         char c = (char)Int16.Parse(sName.Substring(3, 4), hexStyle );
         if (fontOwner.FastMapUnicodeToGlyphID(c) != iGlyph)
         {
             char cMapped = fontOwner.MapGlyphIDToUnicode(iGlyph,(char)0);
             string s = "glyph = " + iGlyph +
                 ", char = U+" + 
                 ((uint)cMapped).ToString("X4")
                 + ", name = " + sName;
             v.Info(T.post_v2_names, 
                    I.post_I_names_uni_unexpected, 
                    m_tag, s);
             bNamesOk = false;
         }
     }
     else if (Is_uXXXXX(sName))
     {
         uint c = (uint)Int32.Parse(sName.Substring(1), hexStyle );
         if (c < 0xffff)
         {
             if (fontOwner.FastMapUnicodeToGlyphID((char)c) != iGlyph)
             {
                 char cMapped = fontOwner.MapGlyphIDToUnicode(iGlyph, 
                                                              (char)0);
                 string s = "glyph = " + iGlyph + ", char = U+" +
                     ((uint)cMapped).ToString("X4") + ", name = " + sName;
                 v.Info(T.post_v2_names, I.post_I_names_uni_unexpected, 
                        m_tag, s);
                 bNamesOk = false;
             }
         }
         else
         {
             if (fontOwner.FastMapUnicode32ToGlyphID(c) != iGlyph)
             {
                 uint cMapped = 
                     fontOwner.MapGlyphIDToUnicode32(iGlyph, 0);
                 string s = "glyph = " + iGlyph + ", char = U+" + 
                     ((uint)cMapped).ToString("X5") + ", name = " + sName;
                 v.Info(T.post_v2_names, I.post_I_names_uni_unexpected, 
                        m_tag, s);
                 bNamesOk = false;
             }
         }
     }
     else
     {
         // check the Adobe Glyph Names
         
         char c = (char)fontOwner.MapGlyphIDToUnicode(iGlyph, (char)0);
         if (c != 0xffff)
         {
             string sAdobeName = pn.GetAdobeGlyphName(c);
             if (sAdobeName == null)
             {
                 string s = "glyph = " + iGlyph + ", char = U+" + 
                     ((uint)c).ToString("X4") + ", name = " + sName;
                 v.Info(T.post_v2_names, I.post_I_names_noAdobe, m_tag,s);
                 bNamesOk = false;
             }
             else if (sName != sAdobeName)
             {
                 string s = "glyph = " + iGlyph + ", char = U+" + 
                     ((uint)c).ToString("X4") + ", name = " + sName;
                 v.Info(T.post_v2_names, I.post_I_names_nomatch, m_tag,s);
                 bNamesOk = false;
             }
         }
     }
     return bNamesOk;
 }