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; }
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); }
/************************ * 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); }
// 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; }
/************************ * 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); }
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); }
public uint GetGlyphInfoOffset(uint iGlyph, OTFont fontOwner) { if (iGlyph >= fontOwner.GetMaxpNumGlyphs()) { throw new ArgumentOutOfRangeException("iGlyph"); } return(m_bufTable.GetUint((uint)FieldOffsets.offsets + iGlyph * 4)); }
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); }
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; }
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)); }
/************************ * 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); }
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); }
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); }
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; }
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; }
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); } }
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; }
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); }
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; }
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); }
/************************ * 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; }
/************************ * 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); }
/************************ * 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); }
/* * 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); }
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)); }
/* * 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; } }
// 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; }
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); }
/* * 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); }
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); }
public void BuildCache(OTFont fontOwner) { m_cache = new glyf_cache(this, fontOwner); }
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; }
/* * 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; }
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; }
/************************ * 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; }
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; }
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; }
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; }
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; }
// 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); } } }
/// <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); }
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; }
/// <summary>Notify observer of FontParsed event</summary> public void OnFontParsedEvent(OTFont f) { m_OnValidateEvent(EventTypes.FontParsed, f); }
/************************ * 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; }
/* * 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; }
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); }