Beispiel #1
0
 public bool ValidateNumEntries(Validator validator,
     OTFont fontOwner)
 {
     int numGlyph=this.NumGlyph(fontOwner);
     int numEntry=this.NumEntry(fontOwner);
     if ((numGlyph==Table_loca.ValueInvalid)||
         (numEntry==Table_loca.ValueInvalid)||
         (numEntry!=numGlyph+1))
     {
         if (validator!=null)
         {
             validator.Error(T.T_NULL,
                 E.loca_E_NumEntries, 
                 m_tag, 
                 "number of entries="+numEntry+" number of glyphs="+numGlyph);
         }
         return false;    
     }
     else
     {
         if (validator!=null)
         {
             validator.Pass(P.loca_P_NumEntries, m_tag);
         }
         return true;
     }
 }
        /************************
         * public methods
         */
        
        
        public OTTable GetTable(OTFont fontOwner, DirectoryEntry de)
        {
            // first try getting it from the table cache
            OTTable table = GetTableFromCache(de);

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

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

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

            return table;
        }
Beispiel #3
0
        public header GetGlyphHeader(uint iGlyph, OTFont fontOwner)
        {
            if (iGlyph >= fontOwner.GetMaxpNumGlyphs())
            {
                throw new ArgumentOutOfRangeException("iGlyph");
            }

            header h = null;

            Table_loca locaTable = (Table_loca)fontOwner.GetTable("loca");

            if (locaTable != null)
            {
                int offsGlyph, length;
                if (locaTable.GetEntryGlyf((int)iGlyph,
                                           out offsGlyph, out length, fontOwner))
                {
                    if (length != 0)
                    {
                        h = new header((uint)offsGlyph, m_bufTable);
                    }
                }
            }

            return(h);
        }
Beispiel #4
0
        /************************
         * public static methods
         */


        /// <summary>Return a new OTFont by reading a single font from an
        /// OTFile starting at a given file position.
        /// <p/>
        /// The type of the font is set by determining whether there is
        /// a 'glyf' table or a 'CFF ' table.
        /// </summary>
        public static OTFont ReadFont(OTFile file, uint FontFileNumber, uint filepos)
        {
            OTFont f = null;

            OffsetTable ot = ReadOffsetTable(file, filepos);

            if (ot != null)
            {
                if (ot.numTables == ot.DirectoryEntries.Count)
                {
                    OutlineType olt = OutlineType.OUTLINE_INVALID;
                    for (int i = 0; i < ot.DirectoryEntries.Count; i++)
                    {
                        DirectoryEntry temp   = (DirectoryEntry)ot.DirectoryEntries[i];
                        string         sTable = (string)temp.tag;
                        if (sTable == "CFF ")
                        {
                            olt = OutlineType.OUTLINE_POSTSCRIPT;
                            break;
                        }
                        else if (sTable == "glyf")
                        {
                            olt = OutlineType.OUTLINE_TRUETYPE;
                            break;
                        }
                    }

                    f = new OTFont(file, FontFileNumber, ot, olt);
                }
            }
            return(f);
        }
Beispiel #5
0
        // writing a font file
        /// <summary>Write single font or collection to disk.</summary>
        public static bool WriteFile(string sFilename, OTFont[] fonts)
        {
            bool bRet = true;

            if (fonts.Length == 0)
            {
                // illegal - need at least one font
                throw new ApplicationException("zero length font array");
            }
            else
            {
                // open the font file for writing
                FileStream fs = new FileStream(sFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.None);

                // write it
                if (fonts.Length == 1)
                {
                    bRet = WriteSfntFile(fs, fonts[0]);
                }
                else
                {
                    bRet = WriteTTCFile(fs, fonts);
                }

                // close the font file
                fs.Close();
                fs = null;
            }

            return bRet;
        }
Beispiel #6
0
        /************************
         * public methods
         */


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

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

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

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

            return(table);
        }
Beispiel #7
0
        public uint GetNumLeftSideBearingEntries(OTFont fontOwner)
        {
            uint nhm       = GetNumberOfHMetrics(fontOwner);
            uint numGlyphs = fontOwner.GetMaxpNumGlyphs();

            return(numGlyphs - nhm);
        }
        /// <summary>Read and parse font, either a single font or a single
        /// font from a collection, using the <c>OTFont</c> class.
        /// </summary>
        public OTFont GetFont(uint i)
        {
            OTFont f = null;

            Debug.Assert(i < m_nFonts);
            Debug.Assert(m_FontFileType != FontFileType.INVALID);
            if (i > 0)
            {
                Debug.Assert(m_FontFileType == FontFileType.COLLECTION);
            }

            if (i < m_nFonts)
            {
                if (m_FontFileType == FontFileType.SINGLE)
                {
                    f = OTFont.ReadFont(this, 0, 0);
                }
                else if (m_FontFileType == FontFileType.COLLECTION)
                {
                    Debug.Assert(m_ttch != null);
                    if (m_ttch != null)
                    {
                        uint nDirOffset = (uint)m_ttch.DirectoryOffsets[(int)i];

                        f = OTFont.ReadFont(this, i, nDirOffset);
                    }
                }
            }

            return(f);
        }
Beispiel #9
0
 public uint GetGlyphInfoOffset(uint iGlyph, OTFont fontOwner)
 {
     if (iGlyph >= fontOwner.GetMaxpNumGlyphs())
     {
         throw new ArgumentOutOfRangeException("iGlyph");
     }
     return(m_bufTable.GetUint((uint)FieldOffsets.offsets + iGlyph * 4));
 }
Beispiel #10
0
 protected int SizeEntry(OTFont fontOwner)
 {
     this.Format(fontOwner);
     if ((this.m_format != 0) && (this.m_format != 1))
     {
         return(Table_loca.ValueInvalid);
     }
     return((this.m_format == 0)?2:4);
 }
Beispiel #11
0
 protected int SizeEntry(OTFont fontOwner)
 {
     this.Format(fontOwner);
     if ((this.m_format!=0)&&(this.m_format!=1))
     {
         return Table_loca.ValueInvalid;
     }
     return (this.m_format==0)?2:4;
 }
 /*
  *        CONSTRUCTORS
  */
 public I_IOGlyphsFile()
 {
     this.m_font=null;
     this.m_tableLoca=null;
     this.m_tableGlyf=null;
     this.m_validator=null;
     this.m_numGlyph=GConsts.IND_UNINITIALIZED;
     this.m_toCloseFileOnClear=false;
 }
Beispiel #13
0
        public short GetLeftSideBearing(uint i, OTFont fontOwner)
        {
            if (i >= GetNumLeftSideBearingEntries(fontOwner))
            {
                throw new ArgumentOutOfRangeException("i");
            }

            uint nhm = GetNumberOfHMetrics(fontOwner);

            return(m_bufTable.GetShort(nhm * 4 + i * 2));
        }
Beispiel #14
0
        /************************
         * protected methods
         */

        protected ushort GetNumberOfHMetrics(OTFont fontOwner)
        {
            Table_hhea hheaTable = (Table_hhea)fontOwner.GetTable("hhea");

            if (hheaTable != null)
            {
                m_nNumberOfHMetrics = hheaTable.numberOfHMetrics;
            }

            //Debug.Assert(numberOfHMetrics != 0);
            return(m_nNumberOfHMetrics);
        }
Beispiel #15
0
 protected int NumGlyph(OTFont fontOwner)
 {
     if (this.m_numGlyph == Table_loca.ValueInvalid)
     {
         Table_maxp tableMaxp = (Table_maxp)fontOwner.GetTable("maxp");
         if (tableMaxp != null)
         {
             this.m_numGlyph = tableMaxp.NumGlyphs;
         }
     }
     return(this.m_numGlyph);
 }
Beispiel #16
0
        private int m_numGlyph;               // from maxp

        /*
         *        METHODS: ACCESS
         */
        protected int LengthGlyf(OTFont fontOwner)
        {
            if (this.m_lengthGlyf == Table_loca.ValueInvalid)
            {
                DirectoryEntry deGlyf = fontOwner.GetDirectoryEntry("glyf");
                if (deGlyf != null)
                {
                    this.m_lengthGlyf = (int)deGlyf.length;
                }
            }
            return(this.m_lengthGlyf);
        }
Beispiel #17
0
 private int        m_numGlyph;            // from maxp
 /*
  *        METHODS: ACCESS
  */
 protected int LengthGlyf(OTFont fontOwner)
 {
     if (this.m_lengthGlyf==Table_loca.ValueInvalid)
     {
         DirectoryEntry deGlyf=fontOwner.GetDirectoryEntry("glyf");
         if (deGlyf != null)
         {
             this.m_lengthGlyf=(int)deGlyf.length;
         }
     }
     return this.m_lengthGlyf;
 }
Beispiel #18
0
 protected int NumGlyph(OTFont fontOwner)
 {
     if (this.m_numGlyph==Table_loca.ValueInvalid)
     {
         Table_maxp tableMaxp = (Table_maxp)fontOwner.GetTable("maxp");
         if (tableMaxp != null)
         {
             this.m_numGlyph = tableMaxp.NumGlyphs;
         }
     }
     return this.m_numGlyph;
 }
Beispiel #19
0
 public int NumEntry(OTFont fontOwner) 
 {
     int sizeEntry=this.SizeEntry(fontOwner);
     if (sizeEntry==Table_loca.ValueInvalid)
     {
         return Table_loca.ValueInvalid;
     }
     else
     {
         return (int)(this.m_bufTable.GetLength()/sizeEntry);
     }
 }
Beispiel #20
0
 protected int Format(OTFont fontOwner)
 {
     // sets format without validating it
     if (this.m_format==Table_loca.ValueInvalid)
     {
         Table_head headTable = (Table_head)fontOwner.GetTable("head");
         if (headTable!=null)
         {
             this.m_format=headTable.indexToLocFormat;
         }
     }
     return this.m_format;
 }
Beispiel #21
0
 protected int Format(OTFont fontOwner)
 {
     // sets format without validating it
     if (this.m_format == Table_loca.ValueInvalid)
     {
         Table_head headTable = (Table_head)fontOwner.GetTable("head");
         if (headTable != null)
         {
             this.m_format = headTable.indexToLocFormat;
         }
     }
     return(this.m_format);
 }
Beispiel #22
0
        public int NumEntry(OTFont fontOwner)
        {
            int sizeEntry = this.SizeEntry(fontOwner);

            if (sizeEntry == Table_loca.ValueInvalid)
            {
                return(Table_loca.ValueInvalid);
            }
            else
            {
                return((int)(this.m_bufTable.GetLength() / sizeEntry));
            }
        }
        public longHorMetric GetHMetric(uint i, OTFont fontOwner)
        {
            if (i >= GetNumberOfHMetrics(fontOwner))
            {
                throw new ArgumentOutOfRangeException("i");
            }

            longHorMetric hm = new longHorMetric();
            hm.advanceWidth = m_bufTable.GetUshort(i*4);
            hm.lsb          = m_bufTable.GetShort(i*4+2);

            return hm;
        }
Beispiel #24
0
        public longHorMetric GetHMetric(uint i, OTFont fontOwner)
        {
            if (i >= GetNumberOfHMetrics(fontOwner))
            {
                throw new ArgumentOutOfRangeException("i");
            }

            longHorMetric hm = new longHorMetric();

            hm.advanceWidth = m_bufTable.GetUshort(i * 4);
            hm.lsb          = m_bufTable.GetShort(i * 4 + 2);

            return(hm);
        }
Beispiel #25
0
        /************************
         * protected methods
         */

        protected ushort GetNumGlyphs(OTFont fontOwner)
        {
            if (m_numGlyphs == 0)
            {
                Table_maxp maxpTable = (Table_maxp)fontOwner.GetTable("maxp");

                if (maxpTable != null)
                {
                    m_numGlyphs = maxpTable.NumGlyphs;
                }
            }

            Debug.Assert(m_numGlyphs != 0, "m_numGlyphs == 0");
            return(m_numGlyphs);
        }
        /************************
         * accessors
         */

        public vMetric GetVMetric(uint i, OTFont fontOwner)
        {
            vMetric vm = new vMetric();
            m_nLongVerMetrics = (ushort)GetNumOfLongVerMetrics(fontOwner); 
            m_nGlyphsInTheFont = fontOwner.GetMaxpNumGlyphs();
            
            if( i >= m_nGlyphsInTheFont )
            {
                throw new ArgumentOutOfRangeException();
            }

            vm = GetVMetric( i );            

            return vm;
        }
Beispiel #27
0
        /************************
         * protected methods
         */

        protected uint GetNumOfLongVerMetrics(OTFont fontOwner)
        {
            if (m_nLongVerMetrics == 0)
            {
                // get the vhea table (to get access to the numOfLongVerMetrics property)
                Table_vhea vheaTable = (Table_vhea)fontOwner.GetTable("vhea");

                if (vheaTable != null)
                {
                    m_nLongVerMetrics = vheaTable.numOfLongVerMetrics;
                }
            }

            Debug.Assert(m_nLongVerMetrics != 0);
            return(m_nLongVerMetrics);
        }
Beispiel #28
0
        /************************
         * accessors
         */

        public vMetric GetVMetric(uint i, OTFont fontOwner)
        {
            vMetric vm = new vMetric();

            m_nLongVerMetrics  = (ushort)GetNumOfLongVerMetrics(fontOwner);
            m_nGlyphsInTheFont = fontOwner.GetMaxpNumGlyphs();

            if (i >= m_nGlyphsInTheFont)
            {
                throw new ArgumentOutOfRangeException();
            }

            vm = GetVMetric(i);

            return(vm);
        }
Beispiel #29
0
        /*
         *        METHODS PUBLIC: GLYF ACCESS
         */
        public bool GetEntryGlyf(int indexGlyph,
                                 out int offsStart, out int length, OTFont fontOwner)
        {
            offsStart = Table_loca.ValueInvalid;
            length    = Table_loca.ValueInvalid;

            int offsGlyfCur, offsGlyfNext;

            if ((!this.GetGlyfOffset(indexGlyph, out offsGlyfCur, fontOwner)) ||
                (!this.GetGlyfOffset(indexGlyph + 1, out offsGlyfNext, fontOwner)))
            {
                return(false); // the error is already reported
            }

            int lengthGlyf = this.LengthGlyf(fontOwner);

            if (lengthGlyf == Table_loca.ValueInvalid)
            {
                return(false);
            }

            if ((offsGlyfCur < 0) || (offsGlyfCur >= lengthGlyf))
            {
                // Offset Within Glyf Range
                return(false);
            }
            if ((offsGlyfNext < 0) || (offsGlyfNext >= lengthGlyf))
            {
                int numEntry = this.NumEntry(fontOwner);
                if ((indexGlyph != numEntry - 2) || (offsGlyfNext != lengthGlyf))
                {
                    // Offset Within Glyf Range
                    return(false);
                }
            }

            int lengthGlyfCur = offsGlyfNext - offsGlyfCur;

            if (lengthGlyfCur < 0)
            {
                // offsets increasing error
                return(false);
            }
            offsStart = offsGlyfCur;
            length    = lengthGlyfCur;
            return(true);
        }
Beispiel #30
0
        public uint GetNumPadBytesAfterTable(OTTable t)
        {
            long TableFilePos = t.GetBuffer().GetFilePos();

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

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

            long NextTablePos = m_fs.Length;

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

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

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

            return((uint)(NextTablePos - PadFilePos));
        }
Beispiel #31
0
        /*
         *        VALIDATION FUNCTIONS
         */

        
        public bool ValidateFormat(Validator validator, 
            OTFont fontOwner)
        {
            int format=this.Format(fontOwner);
            if ((format!=0)&&(format!=1))
            {
                if (validator!=null)
                {
                    validator.Error(E.loca_E_Format, m_tag);
                }
                return false;
            }
            else
            {
                if (validator!=null)
                {
                    validator.Pass(P.loca_P_Format, m_tag);
                }
                return true;
            }
        }
Beispiel #32
0
            // constructor

            public glyf_cache(Table_glyf OwnerTable, OTFont OwnerFont)
            {
                m_arrGlyphs = new ArrayList();


                // get each glyph from the glyf table

                for (uint iGlyph = 0; iGlyph < OwnerFont.GetMaxpNumGlyphs(); iGlyph++)
                {
                    header h = OwnerTable.GetGlyphHeader(iGlyph, OwnerFont);
                    if (h == null)
                    {
                        m_arrGlyphs.Add(null);
                    }
                    else
                    {
                        glyph_base gb = GetGlyphLogicalData(h);
                        m_arrGlyphs.Add(gb);
                    }
                }
            }
        public longHorMetric GetOrMakeHMetric(uint i, OTFont fontOwner)
        {
            longHorMetric hm = null;
            m_nGlyphsInTheFont = fontOwner.GetMaxpNumGlyphs();            
            m_nNumberOfHMetrics = GetNumberOfHMetrics(fontOwner);
            uint nlsb = GetNumLeftSideBearingEntries(fontOwner);
            uint CalcTableLength = (uint)m_nNumberOfHMetrics*4 + nlsb*2;

            if( i >= m_nGlyphsInTheFont )
            {
                throw new ArgumentOutOfRangeException();
            }            

            // only try to parse out the data if the table length is correct
            if (CalcTableLength == GetLength())
            {
                hm = GetOrMakeHMetric( i );                
            }

            return hm;
        }
Beispiel #34
0
        public longHorMetric GetOrMakeHMetric(uint i, OTFont fontOwner)
        {
            longHorMetric hm = null;

            m_nGlyphsInTheFont  = fontOwner.GetMaxpNumGlyphs();
            m_nNumberOfHMetrics = GetNumberOfHMetrics(fontOwner);
            uint nlsb            = GetNumLeftSideBearingEntries(fontOwner);
            uint CalcTableLength = (uint)m_nNumberOfHMetrics * 4 + nlsb * 2;

            if (i >= m_nGlyphsInTheFont)
            {
                throw new ArgumentOutOfRangeException();
            }

            // only try to parse out the data if the table length is correct
            if (CalcTableLength == GetLength())
            {
                hm = GetOrMakeHMetric(i);
            }

            return(hm);
        }
Beispiel #35
0
        /*
         *        METHODS PROTECTED: GLYF ACCESS
         */

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

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

            int sizeEntry = this.SizeEntry(fontOwner);

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

            if (pozLoca + sizeEntry > this.GetLength())
            {
                //Offset Exceeds Table Length
                return(false);
            }
            if (sizeEntry == 2)
            {
                offsGlyf = 2 * m_bufTable.GetUshort((uint)pozLoca);
            }
            else
            {
                offsGlyf = (int)(m_bufTable.GetUint((uint)pozLoca));
            }
            return(true);
        }
Beispiel #36
0
        public bool IsMonospace(OTFont fontOwner)
        {
            bool bHmtxMono        = true;
            uint numberOfHMetrics = GetNumberOfHMetrics(fontOwner);

            if (numberOfHMetrics > 2)
            {
                // find the first non-zero width after the null glyph
                ushort nFirstWidth    = 0;
                uint   nFirstWidthPos = 1;
                for (uint i = nFirstWidthPos; i < numberOfHMetrics; i++)
                {
                    nFirstWidth = GetHMetric(i, fontOwner).advanceWidth;
                    if (nFirstWidth != 0)
                    {
                        nFirstWidthPos = i;
                        break;
                    }
                }

                if (nFirstWidth != 0)
                {
                    for (uint i = (uint)nFirstWidthPos + 1; i < numberOfHMetrics; i++)
                    {
                        ushort nWidth = GetHMetric(i, fontOwner).advanceWidth;
                        if (nWidth != 0 && nWidth != nFirstWidth)
                        {
                            bHmtxMono = false;
                            break;
                        }
                    }
                }
            }

            return(bHmtxMono);
        }
Beispiel #37
0
 public void BuildCache(OTFont fontOwner)
 {
     m_cache = new glyf_cache(this, fontOwner);
 }
Beispiel #38
0
        public header GetGlyphHeader(uint iGlyph, OTFont fontOwner)
        {
            if (iGlyph >= fontOwner.GetMaxpNumGlyphs())
            {
                throw new ArgumentOutOfRangeException("iGlyph");
            }

            header h = null;

            Table_loca locaTable = (Table_loca)fontOwner.GetTable("loca");
            if (locaTable != null)
            {
                int offsGlyph, length;
                if (locaTable.GetEntryGlyf((int)iGlyph, 
                    out offsGlyph, out length, fontOwner))
                {
                    if (length!=0)
                    {
                        h = new header((uint)offsGlyph, m_bufTable);
                    }
                }
            }

            return h;
        }
Beispiel #39
0
        /*
         *        METHODS PROTECTED: GLYF ACCESS
         */

        protected bool GetGlyfOffset(int indexGlyph, out int offsGlyf, OTFont fontOwner)
        {
            offsGlyf=Table_loca.ValueInvalid;
            int numEntry=this.NumEntry(fontOwner);
            if (numEntry==Table_loca.ValueInvalid)
                return false;
            if ((indexGlyph<0)||(indexGlyph>=numEntry))
            {
                //Debug.Assert(false, "Table_loca: GetGlyfOffset");
                return false;
            }

            int sizeEntry=this.SizeEntry(fontOwner);
            if (sizeEntry==Table_loca.ValueInvalid)
                return false;
            int pozLoca=sizeEntry*indexGlyph;
            if (pozLoca+sizeEntry>this.GetLength())
            {
                //Offset Exceeds Table Length
                return false;
            }
            if (sizeEntry==2)
            {
                offsGlyf = 2*m_bufTable.GetUshort((uint)pozLoca);
            }
            else
            {
                offsGlyf = (int)(m_bufTable.GetUint((uint)pozLoca));
            }
            return true;
        }
Beispiel #40
0
 public void BuildCache(OTFont fontOwner)
 {
     m_cache = new glyf_cache(this, fontOwner);
 }
        public bool IsMonospace(OTFont fontOwner)
        {
            bool bHmtxMono = true;
            uint numberOfHMetrics = GetNumberOfHMetrics(fontOwner);
            if (numberOfHMetrics > 2)
            {
                // find the first non-zero width after the null glyph
                ushort nFirstWidth = 0;
                uint nFirstWidthPos = 1;
                for (uint i=nFirstWidthPos; i<numberOfHMetrics; i++)
                {
                    nFirstWidth = GetHMetric(i, fontOwner).advanceWidth;
                    if (nFirstWidth != 0)
                    {
                        nFirstWidthPos = i;
                        break;
                    }
                }

                if (nFirstWidth != 0)
                {
                    for (uint i=(uint)nFirstWidthPos+1; i<numberOfHMetrics; i++)
                    {
                        ushort nWidth = GetHMetric(i, fontOwner).advanceWidth;
                        if (nWidth != 0 && nWidth != nFirstWidth)
                        {
                            bHmtxMono = false;
                            break;
                        }
                    }
                }
            }

            return bHmtxMono;
        }
Beispiel #42
0
        /************************
         * public static methods
         */
        
        
        /// <summary>Return a new OTFont by reading a single font from an 
        /// OTFile starting at a given file position. 
        /// <p/>
        /// The type of the font is set by determining whether there is
        /// a 'glyf' table or a 'CFF ' table.
        /// </summary>
        public static OTFont ReadFont(OTFile file, uint FontFileNumber, uint filepos)
        {
            OTFont f = null;

            OffsetTable ot = ReadOffsetTable(file, filepos);

            if (ot != null)
            {
                if (ot.numTables == ot.DirectoryEntries.Count)
                {
                    OutlineType olt = OutlineType.OUTLINE_INVALID;
                    for (int i = 0; i<ot.DirectoryEntries.Count; i++)
                    {
                        DirectoryEntry temp = (DirectoryEntry)ot.DirectoryEntries[i];
                        string sTable = (string)temp.tag;
                        if (sTable == "CFF ")
                        {
                            olt = OutlineType.OUTLINE_POSTSCRIPT;
                            break;
                        }
                        else if (sTable == "glyf")
                        {
                            olt = OutlineType.OUTLINE_TRUETYPE;
                            break;
                        }
                    }

                    f = new OTFont(file, FontFileNumber, ot, olt);
                }
            }
            return f;
        }
        /************************
         * protected methods
         */

        protected ushort GetNumberOfHMetrics(OTFont fontOwner)
        {

            Table_hhea hheaTable = (Table_hhea)fontOwner.GetTable("hhea");
            if (hheaTable != null)
            {
                m_nNumberOfHMetrics = hheaTable.numberOfHMetrics;
            }

            //Debug.Assert(numberOfHMetrics != 0);
            return m_nNumberOfHMetrics;
        }
Beispiel #44
0
        private void CheckCodePageGlyph(uint CodePage, char c, ref int nTotalChars, ref int nMissingChars, ushort [] arrMissingChars, OTFont fontOwner)
        {
            int unicode = MultiByte.MultiByteCharToUnicodeChar(CodePage, c);
            if (unicode != -1)
            {
                if (    !Char.IsControl((char)unicode) && 
                    (unicode < 0xe000 || unicode > 0xf8ff) // outside private use area
                    )
                {
                    nTotalChars++;
                    if (fontOwner.FastMapUnicodeToGlyphID((char)unicode) == 0)
                    {
                        nMissingChars++;

                        if (nMissingChars <= 10)
                        {
                            arrMissingChars[nMissingChars-1] = (ushort)unicode;
                        }
                    }
                }
            }
        }
        /************************
         * protected methods
         */

        protected uint GetNumOfLongVerMetrics(OTFont fontOwner)
        {
            if (m_nLongVerMetrics == 0)
            {
                // get the vhea table (to get access to the numOfLongVerMetrics property)
                Table_vhea vheaTable = (Table_vhea)fontOwner.GetTable("vhea");

                if (vheaTable != null)
                {
                    m_nLongVerMetrics = vheaTable.numOfLongVerMetrics;
                }
            }

            Debug.Assert(m_nLongVerMetrics != 0);
            return m_nLongVerMetrics;
        }
Beispiel #46
0
        private bool CheckCodePageBit(int nBit, uint CodePage, string sName, Validator v, OTFont fontOwner)
        {
            bool bRet = true;

            int nTotalChars = 0;
            int nMissingChars = 0;

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


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

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

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

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

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

            return bRet;
        }
Beispiel #47
0
        private bool CheckCodePageRanges(Validator v, OTFont fontOwner)
        {
            bool bRet = true;

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

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


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

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


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


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


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

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

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

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

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

                return bRet;
            }

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

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


            uint nCharsInRange;


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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return bRet;
        }
Beispiel #49
0
            // constructor

            public glyf_cache(Table_glyf OwnerTable, OTFont OwnerFont)
            {
                m_arrGlyphs = new ArrayList();


                // get each glyph from the glyf table

                for (uint iGlyph=0; iGlyph<OwnerFont.GetMaxpNumGlyphs(); iGlyph++)
                {
                    header h = OwnerTable.GetGlyphHeader(iGlyph, OwnerFont);
                    if (h == null)
                    {
                        m_arrGlyphs.Add(null);
                    }
                    else
                    {
                        glyph_base gb = GetGlyphLogicalData(h);
                        m_arrGlyphs.Add(gb);
                    }
                }

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


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


            // order tables in fastfont order

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

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

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

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


            // update the modified date in the head table

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

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

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

                    break;
                }
            }


            // build a list of directory entries

            long TableFilePos = 12 + numTables * 16;

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

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

                ot.DirectoryEntries.Add(de);

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


            // sort the directory entries

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


            // update the font checksum in the head table

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

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

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

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

                    break;
                }
            }


            // write the offset table

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


            // write the directory entries

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


            // write the tables

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

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


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

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

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

                return bRet;
            }

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

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

            uint nCharsInRange;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                        // TODO: v4 addition
                    }
                }
            }

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

            return bRet;
        }
Beispiel #52
0
 /// <summary>Notify observer of FontParsed event</summary>
 public void OnFontParsedEvent(OTFont f)
 {
     m_OnValidateEvent(EventTypes.FontParsed, f);
 }
Beispiel #53
0
        /************************
         * protected methods
         */

        protected ushort GetNumGlyphs(OTFont fontOwner)
        {
            if (m_numGlyphs == 0)
            {
                Table_maxp maxpTable = (Table_maxp)fontOwner.GetTable("maxp");

                if (maxpTable != null)
                {
                    m_numGlyphs = maxpTable.NumGlyphs;
                }
            }

            Debug.Assert(m_numGlyphs != 0, "m_numGlyphs == 0");
            return m_numGlyphs;
        }
Beispiel #54
0
        /*
         *        METHODS PUBLIC: GLYF ACCESS
         */        
        public bool GetEntryGlyf(int indexGlyph, 
            out int offsStart, out int length, OTFont fontOwner)
        {
            offsStart=Table_loca.ValueInvalid;
            length=Table_loca.ValueInvalid;

            int offsGlyfCur, offsGlyfNext; 
            if  ((!this.GetGlyfOffset(indexGlyph,out offsGlyfCur, fontOwner))||
                (!this.GetGlyfOffset(indexGlyph+1,out offsGlyfNext, fontOwner)))
            {
                return false; // the error is already reported
            }

            int lengthGlyf=this.LengthGlyf(fontOwner);
            if (lengthGlyf==Table_loca.ValueInvalid)
            {
                return false;
            }

            if ((offsGlyfCur<0)||(offsGlyfCur>=lengthGlyf))
            {
                // Offset Within Glyf Range
                return false;
            }
            if ((offsGlyfNext<0)||(offsGlyfNext>=lengthGlyf))
            {
                int numEntry=this.NumEntry(fontOwner);
                if ((indexGlyph!=numEntry-2)||(offsGlyfNext!=lengthGlyf))
                {
                    // Offset Within Glyf Range
                    return false;
                }
            } 

            int lengthGlyfCur=offsGlyfNext-offsGlyfCur;
            if (lengthGlyfCur<0)
            {
                // offsets increasing error
                return false;
            }
            offsStart=offsGlyfCur;
            length=lengthGlyfCur;
            return true;
        }
Beispiel #55
0
        public GlyphInfo GetGlyphInfo(uint iGlyph, OTFont fontOwner)
        {
            uint offset = GetGlyphInfoOffset(iGlyph, fontOwner);

            return(new GlyphInfo(offset, m_bufTable));
        }
        public short GetLeftSideBearing(uint i, OTFont fontOwner)
        {
            if (i >= GetNumLeftSideBearingEntries(fontOwner))
            {
                throw new ArgumentOutOfRangeException("i");
            }

            uint nhm = GetNumberOfHMetrics(fontOwner);

            return m_bufTable.GetShort(nhm*4 + i*2);
        }