/// <summary> /// Repopulates the mappings from the given character set. /// </summary> /// <param name="characterSet">The character set to be read from.</param> /// <param name="codes">A list of all numerical encodings in the font, sorted by index.</param> public void ReadFrom(CharacterSet characterSet, IList <int> codes) { ushort code; ushort index; this.unknown = 0; this.mappings.Clear(); IList <Character> chars = characterSet.Characters; this.type = characterSet.MapType; switch (this.MapType) { // Type 0: Codes and indices are assigned in ascending order case CharacterMapType.Range: this.startCode = (ushort)chars[0].Code; this.endCode = (ushort)chars[chars.Count - 1].Code; for (int i = 0; i < chars.Count; i++) { code = (ushort)chars[i].Code; index = (ushort)codes.IndexOf(code); this.mappings.Add(code, index); } break; // Type 1: Codes are assigned in ascending order to the specified indices case CharacterMapType.List: this.startCode = (ushort)chars[0].Code; this.endCode = (ushort)chars[chars.Count - 1].Code; code = this.startCode; for (int i = 0; i < chars.Count; i++, code++) { for (; chars[i].Code > code; code++) { this.mappings.Add(code, Blank); } index = (ushort)codes.IndexOf(code); this.mappings.Add(code, index); } break; // Type 2: Codes and indices are assigned individually case CharacterMapType.Map: this.startCode = 0x0000; this.endCode = 0xFFFF; for (int i = 0; i < chars.Count; i++) { code = (ushort)chars[i].Code; index = (ushort)codes.IndexOf(code); this.mappings.Add(code, index); } break; } }
private void Load(CharacterMapChunk map, CharacterWidthChunk widths, CharacterGlyphChunk glyphs) { this.characters = new List <Character>(map.Mappings.Count); this.type = map.MapType; foreach (int code in map.Mappings.Keys) { int index = map.Mappings[code]; if (index != Blank) { Character c = new Character(code, glyphs.Glyphs[index], widths.XOffsets[index], widths.Widths[index], widths.NextOffsets[index]); this.characters.Add(c); } } }
/// <summary> /// Initializes a new instance of the CharacterSet class with the given map type and an empty character list. /// </summary> /// <param name="type">The character map type, which determines how the mappings are encoded in the saved file.</param> public CharacterSet(CharacterMapType type) { this.characters = new List <Character>(); this.type = type; }
/// <summary> /// Initializes a new instance of the CharacterSet class with the given characters and map type. /// </summary> /// <param name="characters">The initial characters in the set.</param> /// <param name="type">The character map type, which determines how the mappings are encoded in the saved file.</param> public CharacterSet(IList <Character> characters, CharacterMapType type) { this.characters = new List <Character>(characters); this.type = type; }
/// <summary> /// Reads the chunk from the given stream. /// </summary> /// <param name="stream">The stream from which to read the chunk.</param> public override void ReadFrom(Stream stream) { // Read header BinaryReader reader = new BinaryReader(stream); int signature = reader.ReadInt32(); if (signature != Signature) { throw new FormatException("Chunk is not CMAP format."); } reader.ReadInt32(); // chunk size; ignore this.startCode = reader.ReadUInt16(); this.endCode = reader.ReadUInt16(); this.type = (CharacterMapType)reader.ReadUInt16(); this.unknown = reader.ReadUInt16(); this.nextOffset = reader.ReadInt32(); // Read body this.mappings.Clear(); switch (this.type) { /* Type 0: Assign codes and indices in ascending order * Format: BBBB (B = baseIndex) * Codes = startCode ... endCode * Indices = baseIndex ... (baseIndex + (endCode - startCode)) */ case CharacterMapType.Range: for (ushort code = this.startCode, index = reader.ReadUInt16(); code <= this.endCode; code++, index++) { this.mappings.Add(code, index); } break; /* Type 1: Assign codes in ascending order to specified indices * Format: AAAABBBBCCCCDDDD (A = index1, B = index2, C = index3, etc. * Set an index to FFFF to exclude it) * Codes = startCode ... endCode * Indices = index1, index2, index3, ..., indexN */ case CharacterMapType.List: for (ushort code = this.startCode; code <= this.endCode; code++) { ushort index = reader.ReadUInt16(); this.mappings.Add(code, index); } break; /* Type 2: Assign specified codes to specified indices * Format: NNNNAAAABBBBCCCCDDDD (N = number of mappings, A = code1, * B = index1, C = code2, D = index2, etc.) * startCode = 0000, endCode = FFFF * Format * Codes = code1, code2 ... endCode * Indices = index1, index2, index3, ..., indexN */ case CharacterMapType.Map: ushort count = reader.ReadUInt16(); for (int i = 0; i < count; i++) { ushort code = reader.ReadUInt16(); ushort index = reader.ReadUInt16(); this.mappings.Add(code, index); } break; } while (reader.BaseStream.Position < RoundUp(reader.BaseStream.Position)) { reader.ReadUInt16(); } }