/// <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;
            }
        }
Exemple #2
0
        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);
                }
            }
        }
Exemple #3
0
 /// <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;
 }
Exemple #4
0
 /// <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();
            }
        }