示例#1
0
        /// <summary>
        /// Deserializes this structure from binary data.
        /// </summary>
        /// <param name="reader">The <see cref="BinaryReader"/> to read the data from.</param>
        /// <param name="font">Tiny Font containing this appendix.</param>
        /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="font"/> is null.</exception>
        public override void ReadFrom(BinaryReader reader, TinyFont font)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            if (font == null)
            {
                throw new ArgumentNullException("font");
            }

            _mask     = reader.ReadUInt16();
            _reserved = reader.ReadUInt16();

            _fontPlanes.Clear();

            ushort positionMask = _mask;

            while (positionMask != 0)
            {
                if ((positionMask & 1) != 0)
                {
                    FontPlane plane = new FontPlane();
                    plane.ReadFrom(reader, font);

                    _fontPlanes.Add(plane);
                }

                positionMask >>= 1;
            }
        }
        /// <summary>
        /// Ensures this structure contains valid data.
        /// </summary>
        /// <param name="font">The <see cref="TinyFont"/> containing this appendix.</param>
        public override void Update(TinyFont font)
        {
            UpdateAssert(_setsData.Count <= ushort.MaxValue, "Too many metadata sets.");
            UpdateAssert(_setsData.Count == _setsOffsets.ItemsCount, "Metadata set offset count mismatch.");

            SortedDictionary <MetadataSetOffset, byte[]> sortedSets = new SortedDictionary <MetadataSetOffset, byte[]>();

            for (int i = 0; i < _setsOffsets.ItemsCount; i++)
            {
                sortedSets.Add(_setsOffsets[i], _setsData[i]);
            }

            _setsOffsets.Clear();
            _setsOffsets.AddRange(sortedSets.Keys);

            _setsData.Clear();
            _setsData.AddRange(sortedSets.Values);

            int offset = 0;

            for (int i = 0; i < _setsData.Count; i++)
            {
                UpdateAssert(offset <= ushort.MaxValue, "Too large metadata set.");

                _setsOffsets[i].Offset = (ushort)offset;
                offset += _setsData[i].Length;
            }

            _setsOffsets.Sentinel.Id     = 0xFF;
            _setsOffsets.Sentinel.Offset = offset;
        }
        private void FillOpenType(TinyFont font)
        {
            HashSet <ushort> userGlyphs = new HashSet <ushort>();

            foreach (CharacterImportInfo info in EnumerateAllImports())
            {
                if (info.Mapping.Glyph.HasValue)
                {
                    userGlyphs.Add(info.Mapping.Glyph.Value);
                }
            }

            Dictionary <ushort, BuilderState> allGeneratedGlyphs = new Dictionary <ushort, BuilderState>();

            foreach (FeatureImportInfo feature in _features.Where(f => f.Type == FeatureImportType.Substitution))
            {
                foreach (ushort generatedGlyph in _compiler.GetGeneratedGlyphIds(feature.BuilderState.GlyphTypeface, feature.Script, feature.Language, feature.Feature))
                {
                    allGeneratedGlyphs[generatedGlyph] = feature.BuilderState;
                }
            }

            GlyphClassesAppendix classes      = font.GetOrAddNewAppendix <GlyphClassesAppendix>();
            SubstitutionAppendix substitution = font.GetOrAddNewAppendix <SubstitutionAppendix>();
            PositioningAppendix  positioning  = font.GetOrAddNewAppendix <PositioningAppendix>();

            Dictionary <ushort, BuilderState> glyphsToAdd = new Dictionary <ushort, BuilderState>();

            foreach (FeatureImportInfo feature in _features.Where(f => f.Type == FeatureImportType.Substitution))
            {
                foreach (ushort generatedGlyph in _compiler.CompileFeature(feature.BuilderState.GlyphTypeface, feature.Script, feature.Language, feature.Feature, substitution, classes, allGeneratedGlyphs.Keys.Concat(userGlyphs)))
                {
                    glyphsToAdd[generatedGlyph] = feature.BuilderState;
                }
            }

            foreach (KeyValuePair <ushort, BuilderState> toAddPair in glyphsToAdd)
            {
                if (!userGlyphs.Contains(toAddPair.Key))
                {
                    int character;

                    if (toAddPair.Value.GlyphToCharacterMap.TryGetValue(toAddPair.Key, out character))
                    {
                        _characterImportList[character] = new CharacterImportInfo(toAddPair.Value, new CharacterGlyphPair(character, toAddPair.Key));
                    }
                    else if (toAddPair.Key < toAddPair.Value.GlyphTypeface.GlyphCount)
                    {
                        _glyphImportList.Add(new CharacterImportInfo(toAddPair.Value, new CharacterGlyphPair(null, toAddPair.Key)));
                    }

                    userGlyphs.Add(toAddPair.Key);
                }
            }

            foreach (FeatureImportInfo feature in _features.Where(f => f.Type == FeatureImportType.Positioning))
            {
                _compiler.CompileFeature(feature.BuilderState.GlyphTypeface, feature.Script, feature.Language, feature.Feature, positioning, classes, allGeneratedGlyphs.Keys.Concat(userGlyphs), feature.BuilderState.EmSize);
            }
        }
        /// <summary>
        /// Deserializes this structure from binary data.
        /// </summary>
        /// <param name="reader">The <see cref="BinaryReader"/> to read the data from.</param>
        /// <param name="font">The <see cref="TinyFont"/> containing this appendix.</param>
        /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception>
        public override void ReadFrom(BinaryReader reader, TinyFont font)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            while (true)
            {
                MetadataSetOffset offset = new MetadataSetOffset();
                offset.ReadFrom(reader);

                if (offset.Id == 0xFF)
                {
                    _setsOffsets.Sentinel = offset;
                    break;
                }

                _setsOffsets.Add(offset);
            }

            for (int i = 0; i < _setsOffsets.ItemsCount; i++)
            {
                byte[] data = reader.ReadBytes(_setsOffsets[i + 1].Offset - _setsOffsets[i].Offset);
                Sets.Add(data);
            }
        }
示例#5
0
 /// <summary>
 /// Gets size of this appendix.
 /// </summary>
 /// <param name="font">Tiny Font containing this appendix.</param>
 /// <returns>Size in bytes.</returns>
 public override int GetSize(TinyFont font)
 {
     return(sizeof(ushort) + sizeof(ushort) +
            _coverages.Count * Coverage.SizeOf +
            _coverageGlyphCount * sizeof(int));
     //sizeof(ushort) * (_coverageGlyphCount % 2);
 }
示例#6
0
        /// <summary>
        /// Deserializes this structure from binary data.
        /// </summary>
        /// <param name="reader">The <see cref="BinaryReader"/> to read the data from.</param>
        /// <param name="font">Tiny Font containing this appendix.</param>
        /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception>
        public override void ReadFrom(BinaryReader reader, TinyFont font)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            _coverageCount      = reader.ReadUInt16();
            _coverageGlyphCount = reader.ReadUInt16();

            _coverages.Clear();
            _coverages.Capacity = _coverageCount;

            for (int i = 0; i < _coverageCount; i++)
            {
                Coverage coverage = new Coverage();
                coverage.ReadFrom(reader);

                _coverages.Add(coverage);
            }

            _coverageGlyphs.Clear();
            _coverageGlyphs.Capacity = _coverageGlyphCount;

            for (int i = 0; i < _coverageGlyphCount; i++)
            {
                CoverageGlyphs.Add(reader.ReadInt32());
            }

            //if (_coverageGlyphCount % 2 == 1)
            //    reader.ReadUInt16();
        }
示例#7
0
 /// <summary>
 /// Gets total size in bytes of this appendix.
 /// </summary>
 /// <param name="font"></param>
 /// <returns></returns>
 public override int GetSize(TinyFont font)
 {
     return(sizeof(ushort) + sizeof(ushort) +
            _featureOffsets.Count * FeatureOffset.SizeOf +
            _features.Sum(f => f.GetSize()) +
            (_parametersHeap == null ?  0 : _parametersHeap.Length));
 }
 /// <summary>
 /// Serializes this structure into binary data.
 /// </summary>
 /// <param name="writer">The <see cref="BinaryWriter"/> to write the data to.</param>
 /// <param name="font">The <see cref="TinyFont"/> containing this appendix.</param>
 public override void WriteTo(BinaryWriter writer, TinyFont font)
 {
     if (_data != null)
     {
         writer.Write(_data);
     }
 }
示例#9
0
        /// <summary>
        /// Serializes this structure into binary data.
        /// </summary>
        /// <param name="writer">The <see cref="BinaryWriter"/> to write the data to.</param>
        /// <param name="font">Tiny Font containing this appendix.</param>
        /// <exception cref="ArgumentNullException"><paramref name="writer"/> is null.</exception>
        public override void WriteTo(BinaryWriter writer, TinyFont font)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            writer.Write(_featureCount);
            writer.Write(_heapSize);

            foreach (FeatureOffset featureOffset in _featureOffsets)
            {
                featureOffset.WriteTo(writer);
            }

            foreach (Feature feature in _features)
            {
                feature.WriteTo(writer);
            }

            if (_parametersHeap != null)
            {
                writer.Write(_parametersHeap);
            }
        }
示例#10
0
        /// <summary>
        /// Creates new instance of Tiny Font from binary reader.
        /// </summary>
        /// <param name="reader">Source or serialized data.</param>
        /// <returns>New instance of Tiny Font.</returns>
        public static TinyFont Load(BinaryReader reader)
        {
            TinyFont font = new TinyFont();

            font.ReadFrom(reader);
            return(font);
        }
示例#11
0
 /// <summary>
 /// Ensures this structure contains valid data.
 /// </summary>
 /// <param name="font">The <see cref="TinyFont"/> containing this appendix.</param>
 public override void Update(TinyFont font)
 {
     if (_data != null && _data.Length > MaximumAppendixSize)
     {
         throw new InvalidOperationException();
     }
 }
        /// <summary>
        /// Deserializes this structure from binary data.
        /// </summary>
        /// <param name="reader">The <see cref="BinaryReader"/> to read the data from.</param>
        /// <param name="font">Tiny Font containing this appendix.</param>
        /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception>
        public override void ReadFrom(BinaryReader reader, TinyFont font)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            _offsets.Clear();

            for (int i = 0; i < font.TotalCharactersCount; i++)
            {
                _offsets.Add(reader.ReadUInt16());
            }

            _attachmentListSize = reader.ReadUInt16();

            _lists.Clear();

            foreach (ushort offset in _offsets)
            {
                if (offset > 0)
                {
                    AttachmentList list = new AttachmentList();
                    list.ReadFrom(reader);
                    _lists.Add(list);
                }
            }
        }
示例#13
0
        /// <summary>
        /// Creates new instance of Character Info.
        /// </summary>
        /// <param name="font">Tiny Font containing character.</param>
        /// <param name="rangeIndex">Index to character range containing this character.</param>
        /// <param name="c">Characeter.</param>
        /// <param name="plane">Font plane describing plane to which this character belongs.</param>
        /// <param name="planeNumber">Number of <paramref name="plane"/> containg this character.</param>
        internal CharacterInfo(TinyFont font, int rangeIndex, char c, FontPlane plane, int planeNumber)
        {
            Contract.Assert(plane != null, "Plane for specified character does not exists.");

            _font = font;
            _characterAntialiasingData = plane.CharacterAntialiasingData;
            _characterBitmapData       = plane.CharacterBitmapData;
            _c           = (char)c;
            _planeNumber = planeNumber;

            _rangeIndex = rangeIndex;
            _range      = plane.CharacterRanges[_rangeIndex];

            checked
            {
                _characterIndex = (int)_range.IndexOfFirstCharacter + _c - _range.FirstCharacter;
                _character      = plane.Characters[_characterIndex];

                _offset = (int)(_range.Offset + _character.Offset);

                if (_font.Description.IsExtended)
                {
                    _antialiasOffset = (int)(plane.CharacterRangesAntialiasing[_rangeIndex].Offset + plane.CharactersAntialiasing[_characterIndex].Offset);
                }
                else
                {
                    _antialiasOffset = -1;
                }
            }
        }
示例#14
0
        private void FillVerticalMetrics(TinyFont font)
        {
            GlyphMetadataAppendix metadata = font.GetOrAddNewAppendix <GlyphMetadataAppendix>();

            List <sbyte> marginTop    = new List <sbyte>();
            List <sbyte> marginBottom = new List <sbyte>();

            foreach (CharacterImportInfo info in from import in _characterImportList.Values
                     orderby import.Mapping.Character
                     select import)
            {
                marginTop.Add(Helper.FitIntoInt8(info.EmSideBearing.Top, Trace));
                marginBottom.Add(Helper.FitIntoInt8(info.EmSideBearing.Bottom, Trace));
            }

            foreach (CharacterImportInfo info in _glyphImportList)
            {
                marginTop.Add(Helper.FitIntoInt8(info.EmSideBearing.Top, Trace));
                marginBottom.Add(Helper.FitIntoInt8(info.EmSideBearing.Bottom, Trace));
            }

            GlyphMetadataAppendix.MetadataSetOffset offsetTop = new GlyphMetadataAppendix.MetadataSetOffset();
            offsetTop.Id   = GlyphMetadataAppendix.MarginTopSet;
            offsetTop.Bits = GlyphMetadataAppendix.MetadataSetBitLength.Eight;

            metadata.Sets.Add(marginTop.Select(m => (byte)m).ToArray());
            metadata.SetsOffsets.Add(offsetTop);

            GlyphMetadataAppendix.MetadataSetOffset offsetBottom = new GlyphMetadataAppendix.MetadataSetOffset();
            offsetBottom.Id   = GlyphMetadataAppendix.MarginBottomSet;
            offsetBottom.Bits = GlyphMetadataAppendix.MetadataSetBitLength.Eight;

            metadata.Sets.Add(marginBottom.Select(m => (byte)m).ToArray());
            metadata.SetsOffsets.Add(offsetBottom);
        }
示例#15
0
 internal int GetSize(TinyFont font)
 {
     return(FontMetrics.SizeOf +
            FontDescription.SizeOf +
            BitmapDescription.SizeOf +
            _characterRanges.Count * CharacterRangeDescription.SizeOf +
            _characters.Count * CharacterDescription.SizeOf +
            _characterBitmapData.Length +
            (font.Description.IsExtended ? AntialiasingMetrics.SizeOf : 0) +
            _characterRangesAntialiasing.Count * CharacterRangeAntialiasing.SizeOf +
            _charactersAntialiasing.Count * CharacterAntialiasing.SizeOf +
            (_characterAntialiasingData == null ? 0 : _characterAntialiasingData.Length));
 }
        /// <summary>
        /// Serializes this structure into binary data.
        /// </summary>
        /// <param name="writer">The <see cref="BinaryWriter"/> to write the data to.</param>
        /// <param name="font">The <see cref="TinyFont"/> containing this appendix.</param>
        /// <exception cref="ArgumentNullException"><paramref name="writer"/> is null.</exception>
        public override void WriteTo(BinaryWriter writer, TinyFont font)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            foreach (MetadataSetOffset offset in _setsOffsets)
            {
                offset.WriteTo(writer);
            }

            foreach (byte[] data in _setsData)
            {
                writer.Write(data);
            }
        }
示例#17
0
        /// <summary>
        /// Ensures this structure contains valid data.
        /// </summary>
        /// <param name="font">Tiny Font containing this appendix.</param>
        public override void Update(TinyFont font)
        {
            UpdateAssert(_features.ItemsCount <= ushort.MaxValue, "Too many features.");
            UpdateAssert(_features.ItemsCount == _featureOffsets.ItemsCount, "Feature offset count mismatch.");
            UpdateAssert(_parametersHeap == null || _parametersHeap.Length <= ushort.MaxValue, "The parameters heap is too large.");

            _featureCount = (ushort)_features.ItemsCount;
            _heapSize     = (ushort)(_parametersHeap == null ? 0 : _parametersHeap.Length);

            for (int i = 0; i < _features.ItemsCount; i++)
            {
                _features[i].Update();
            }

            _features.Sentinel.StateCount = 0;
            _features.Sentinel.Rules.Clear();
            _features.Sentinel.StateOffsets.Clear();
            _features.Sentinel.StateOffsets.Sentinel = 0;

            SortedDictionary <FeatureOffset, Feature> sortedFeatures = new SortedDictionary <FeatureOffset, Feature>();

            for (int i = 0; i < _featureCount; i++)
            {
                sortedFeatures.Add(_featureOffsets[i], _features[i]);
            }

            _featureOffsets.Clear();
            _featureOffsets.AddRange(sortedFeatures.Keys);

            _features.Clear();
            _features.AddRange(sortedFeatures.Values);

            int offset = 0;

            for (int i = 0; i < _features.Count; i++)
            {
                UpdateAssert(offset <= ushort.MaxValue, "Too large feature.");

                _featureOffsets[i].Offset = (ushort)offset;
                offset += _features[i].GetSize();
            }

            _featureOffsets.Sentinel.Tag = 0xFFFFFFFF;
        }
        /// <summary>
        /// Serializes this structure into binary data.
        /// </summary>
        /// <param name="writer">The <see cref="BinaryWriter"/> to write the data to.</param>
        /// <param name="font">Tiny Font containing this appendix.</param>
        /// <exception cref="ArgumentNullException"><paramref name="writer"/> is null.</exception>
        public override void WriteTo(BinaryWriter writer, TinyFont font)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            foreach (ushort offset in _offsets)
            {
                writer.Write(offset);
            }

            writer.Write(_attachmentListSize);

            foreach (AttachmentList list in _lists)
            {
                list.WriteTo(writer);
            }
        }
        /// <summary>
        /// Ensures this structure contains valid data.
        /// </summary>
        /// <param name="font">Tiny Font containing this appendix.</param>
        public override void Update(TinyFont font)
        {
            UpdateAssert(_lists.Count <= ushort.MaxValue, "Too many attachment points lists.");

            _offsets.Clear();
            int offset = 1;

            foreach (AttachmentList list in _lists)
            {
                list.Update();
                _offsets.Add((ushort)offset);

                offset += (list.GetSize() / sizeof(ushort));

                UpdateAssert(offset <= ushort.MaxValue, "Too many attachment points.");
            }

            _attachmentListSize = (ushort)(offset - 1);
        }
示例#20
0
        /// <summary>
        /// Ensures this structure contains valid data.
        /// </summary>
        /// <param name="font">Tiny Font containing this appendix.</param>
        public override void Update(TinyFont font)
        {
            UpdateAssert(_coverages.Count <= ushort.MaxValue, "Too many coverages.");
            UpdateAssert(_coverageGlyphs.Count <= ushort.MaxValue, "Too many coverage glyphs.");

            _coverageCount      = (ushort)_coverages.Count;
            _coverageGlyphCount = (ushort)_coverageGlyphs.Count;

            foreach (Coverage coverage in _coverages)
            {
                UpdateAssert(coverage.Offset + coverage.Count <= _coverageGlyphs.Count, "Out of range coverage.");
                _coverageGlyphs.Sort(coverage.Offset, coverage.Count, Comparer <int> .Default);
            }

            foreach (Coverage coverage in _coverages)
            {
                UpdateAssert(Helper.IsSorted(_coverageGlyphs, coverage.Offset, coverage.Count, Comparer <int> .Default), "Incompatible overlapping coverages.");
            }
        }
示例#21
0
        /// <summary>
        /// Assembles new Tiny Font from imports.
        /// </summary>
        /// <returns>Tiny Font.</returns>
        public TinyFont Build()
        {
            TinyFont font = new TinyFont();

            if (_features.Count > 0)
            {
                FillOpenType(font);  // can add new characters/glyphs
            }
            FillMetrics(font.Metrics);

            for (ushort plane = 0; plane <= LastPlane; plane++)
            {
                FillCharacters(font, from import in _characterImportList.Values
                               orderby import.Mapping.Character
                               select import, plane);
            }

            for (int i = 0; i < _glyphImportList.Count; i++)
            {
                _glyphImportList[i].Mapping.Character = i + LastPlaneFirstCharacter;
            }

            if (_glyphImportList.Count > 0)
            {
                FillCharacters(font, _glyphImportList, LastPlane);
            }

#if TERKA_FEATURES
            if (_importGraphemeClusterBoundaries)
            {
                FillGraphemeClusterBoundaries(font);
            }

            if (_importVerticalMetrics)
            {
                FillVerticalMetrics(font);
            }
#endif
            font.Update();

            RemapGlyphsToCharacters(font);
            return(font);
        }
示例#22
0
        /// <summary>
        /// Serializes this structure into binary data.
        /// </summary>
        /// <param name="writer">The <see cref="BinaryWriter"/> to write the data to.</param>
        /// <param name="font">Tiny Font containing this appendix.</param>
        /// <exception cref="ArgumentNullException"><paramref name="writer"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="font"/> is null.</exception>
        public override void WriteTo(BinaryWriter writer, TinyFont font)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            if (font == null)
            {
                throw new ArgumentNullException("font");
            }

            writer.Write(_mask);
            writer.Write(_reserved);

            foreach (FontPlane plane in _fontPlanes)
            {
                plane.WriteTo(writer, font);
            }
        }
示例#23
0
        /// <summary>
        /// Deserializes this structure from binary data.
        /// </summary>
        /// <param name="reader">The <see cref="BinaryReader"/> to read the data from.</param>
        /// <param name="font">Tiny Font containing this appendix.</param>
        /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception>
        public override void ReadFrom(BinaryReader reader, TinyFont font)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            _featureCount = reader.ReadUInt16();
            _heapSize     = reader.ReadUInt16();

            _featureOffsets.Clear();
            _featureOffsets.Capacity = _featureCount;

            for (int i = 0; i < _featureCount; i++)
            {
                FeatureOffset offset = new FeatureOffset();
                offset.ReadFrom(reader);

                _featureOffsets.Add(offset);
            }

            _featureOffsets.Sentinel.ReadFrom(reader);

            _features.Clear();
            _features.Capacity = _featureCount;

            for (int i = 0; i < _featureCount; i++)
            {
                Feature feature = new Feature();
                feature.ReadFrom(reader);

                _features.Add(feature);
            }

            _features.Sentinel.ReadFrom(reader);

            if (_heapSize > 0)
            {
                _parametersHeap = reader.ReadBytes(_heapSize);
            }
        }
示例#24
0
        /// <summary>
        /// Ensures this structure contains valid data.
        /// </summary>
        /// <param name="font">Tiny Font containing this appendix.</param>
        public override void Update(TinyFont font)
        {
            ushort positionMask = _mask;
            int    removedMask  = 0;

            int i = 0;

            while (positionMask != 0)
            {
                if ((positionMask & 1) != 0)
                {
                    UpdateAssert(i < _fontPlanes.Count, "Too few planes.");
                    UpdateAssert(_fontPlanes[i] != null, "Plane not initialized.");

                    _fontPlanes[i].Update();

                    if (!_fontPlanes[i].HasContent)
                    {
                        removedMask |= 1 << i;

                        _fontPlanes.RemoveAt(i);
                    }
                    else
                    {
                        // we need to keep all metrics in sync, but bitmap ~ offset can be different
                        short planeOffset = _fontPlanes[i].Metrics.Offset;
                        _fontPlanes[i].Metrics        = (FontMetrics)font.Metrics.Clone();
                        _fontPlanes[i].Metrics.Offset = planeOffset;

                        i++;
                    }
                }

                positionMask >>= 1;
            }

            _mask &= (ushort)~removedMask;
        }
示例#25
0
        /// <summary>
        /// Serializes this structure into binary data.
        /// </summary>
        /// <param name="writer">The <see cref="BinaryWriter"/> to write the data to.</param>
        /// <param name="font">Tiny Font containing this appendix.</param>
        /// <exception cref="ArgumentNullException"><paramref name="writer"/> is null.</exception>
        public override void WriteTo(BinaryWriter writer, TinyFont font)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            writer.Write(_coverageCount);
            writer.Write(_coverageGlyphCount);

            for (int i = 0; i < _coverages.Count; i++)
            {
                _coverages[i].WriteTo(writer);
            }

            for (int i = 0; i < _coverageGlyphs.Count; i++)
            {
                writer.Write(_coverageGlyphs[i]);
            }

            //if (_coverageGlyphCount % 2 == 1)
            //    writer.Write((ushort)0);
        }
示例#26
0
        /// <summary>
        /// Serializes this structure into binary data.
        /// </summary>
        /// <param name="writer">The <see cref="BinaryWriter"/> to write the data to.</param>
        /// <param name="font">The <see cref="TinyFont"/> containing this appendix.</param>
        /// <exception cref="ArgumentNullException"><paramref name="writer"/> is null.</exception>
        public void WriteTo(BinaryWriter writer, TinyFont font)
        {
            if (writer == null)
            {
                throw new ArgumentNullException();
            }

            if (font == null)
            {
                throw new ArgumentNullException();
            }

            _metrics.WriteTo(writer);
            _description.WriteTo(writer);
            _characterBitmapDescription.WriteTo(writer);

            WriteBasicTo(writer);

            if (font.Description.IsExtended)
            {
                WriteExtendedTo(writer);
            }
        }
示例#27
0
        /// <summary>
        /// Deserializes this structure from binary data.
        /// </summary>
        /// <param name="reader">The <see cref="BinaryReader"/> to read the data from.</param>
        /// <param name="font">The <see cref="TinyFont"/> containing this appendix.</param>
        /// <exception cref="ArgumentNullException"><paramref name="reader"/> is null.</exception>
        public void ReadFrom(BinaryReader reader, TinyFont font)
        {
            if (reader == null)
            {
                throw new ArgumentNullException();
            }

            if (font == null)
            {
                throw new ArgumentNullException();
            }

            _metrics.ReadFrom(reader);
            _description.ReadFrom(reader);
            _characterBitmapDescription.ReadFrom(reader);

            ReadBasicFrom(reader);

            if (font.Description.IsExtended)
            {
                ReadExtendedFrom(reader);
            }
        }
示例#28
0
        private void FillGraphemeClusterBoundaries(TinyFont font)
        {
            GlyphMetadataAppendix metadata = font.GetOrAddNewAppendix <GlyphMetadataAppendix>();

            byte[] clusterBoundaries = Resources.GraphemeBreakProperty;

            BitArray data = new BitArray(0);

            foreach (CharacterInfo info in font.EnumerateAllCharacterInfos())
            {
                byte property = FindClusterProperty(clusterBoundaries, info.Codepoint);
                data.AppendLsb(property, 4);
            }

            byte[] setData = new byte[(data.Length + 7) / 8];
            data.CopyTo(setData, 0);

            metadata.Sets.Add(setData);
            GlyphMetadataAppendix.MetadataSetOffset offset = new GlyphMetadataAppendix.MetadataSetOffset();
            offset.Id   = GlyphMetadataAppendix.GraphemeSet;
            offset.Bits = GlyphMetadataAppendix.MetadataSetBitLength.Four;

            metadata.SetsOffsets.Add(offset);
        }
示例#29
0
        private void FillCharacters(TinyFont font, IEnumerable <CharacterImportInfo> imports, ushort planeNumber)
        {
            Contract.Requires(font != null, "Font cannot be null.");
            Contract.Requires(font.Metrics != null, "Font metrics cannot be null.");

            if (font.Metrics.Height == 0)
            {
                Trace.TraceEvent(TraceEventType.Warning, 0, "TinyFont has a height of zero. No glyphs will be included.");
                return;
            }

            FontPlane plane = planeNumber == 0 ? font.FontPlanes[0] : new FontPlane();

            Contract.Requires(plane != null, "Plane cannot be null.");

            FillDescription(plane.Description);

            uint  numberOfCharacters = 0;
            bool  antialiasing       = font.Description.IsExtended;
            short firstNonBlankLine  = short.MaxValue;
            int   maxCharacterWidth  = font.Metrics.MaximumCharacterWidth;

            BitArray        antialiasingData = new BitArray(0);
            List <BitArray> bitmapData       = new List <BitArray>(font.Metrics.Height);

            for (int i = 0; i < font.Metrics.Height; i++)
            {
                bitmapData.Add(new BitArray(0));
            }

            int lastCharacter = -1;
            CharacterRangeDescription  rangeDescription  = null;
            CharacterRangeAntialiasing rangeAntialiasing = null;

            foreach (CharacterImportInfo import in imports)
            {
                Contract.Assert(import.Mapping.Character.Value >= 0 && import.Mapping.Character.Value <= LastPlaneLastCharacter, "All content must have valid two bytes characters.");
                Contract.Assert(import.Mapping.Character.Value > lastCharacter, "Content must be ordered by characters and cannot overlap.");

                int character = import.Mapping.Character.Value;

                // If character does not belong to this plane, skip it
                if ((character >> 16) != planeNumber)
                {
                    continue;
                }

                if (lastCharacter != (character - 1))
                {
                    if (rangeDescription != null)
                    {
                        rangeDescription.LastCharacter = (char)lastCharacter;
                        plane.CharacterRanges.Add(rangeDescription);

                        if (antialiasing)
                        {
                            plane.CharacterRangesAntialiasing.Add(rangeAntialiasing);
                        }
                    }

                    rangeDescription                       = new CharacterRangeDescription();
                    rangeDescription.Offset                = (uint)bitmapData[0].Length;
                    rangeDescription.FirstCharacter        = (char)character;
                    rangeDescription.IndexOfFirstCharacter = numberOfCharacters;

                    if (antialiasing)
                    {
                        rangeAntialiasing        = new CharacterRangeAntialiasing();
                        rangeAntialiasing.Offset = (uint)(antialiasingData.Length / BitsPerByte);
                    }
                }

                lastCharacter     = character;
                maxCharacterWidth = Math.Max(maxCharacterWidth, import.InkBox.Width);
                ++numberOfCharacters;

                CharacterDescription characterDescription = new CharacterDescription();
                characterDescription.LeftMargin  = Helper.FitIntoInt8(import.EmSideBearing.Left, Trace);
                characterDescription.RightMargin = Helper.FitIntoInt8(import.EmSideBearing.Right, Trace);
                characterDescription.Offset      = checked ((ushort)(bitmapData[0].Length - rangeDescription.Offset));
                plane.Characters.Add(characterDescription);

                if (import.BitmapData != null)
                {
                    AppendBitmap(bitmapData, import);

                    short glyphFirstNonBlankLine = Helper.FitIntoInt16(import.InkBox.Y, Trace);
                    if (firstNonBlankLine > glyphFirstNonBlankLine)
                    {
                        firstNonBlankLine = glyphFirstNonBlankLine;
                    }
                }

                if (antialiasing)
                {
                    CharacterAntialiasing characterAntialiasing = new CharacterAntialiasing();
                    characterAntialiasing.Offset = import.AntialiasData == null ? CharacterAntialiasing.NoData : checked ((ushort)(antialiasingData.Length / BitsPerByte - rangeAntialiasing.Offset));
                    plane.CharactersAntialiasing.Add(characterAntialiasing);

                    if (import.AntialiasData != null)
                    {
                        AppendAntialiasing(antialiasingData, import);

                        int bitPadding = antialiasingData.Length % BitsPerByte;
                        if (bitPadding > 0)
                        {
                            antialiasingData.Length += BitsPerByte - bitPadding;
                        }
                    }
                }
            }

            if (numberOfCharacters > 0)
            {
                if (rangeDescription != null)
                {
                    rangeDescription.LastCharacter = (char)lastCharacter;
                    plane.CharacterRanges.Add(rangeDescription);

                    if (antialiasing)
                    {
                        plane.CharacterRangesAntialiasing.Add(rangeAntialiasing);
                    }
                }

                plane.Metrics.Offset               = firstNonBlankLine;
                plane.CharacterBitmap.Width        = (uint)bitmapData[0].Length;
                plane.CharacterBitmap.Height       = (uint)(bitmapData.Count - firstNonBlankLine);
                plane.CharacterBitmap.BitsPerPixel = 1;
                plane.CharacterBitmapData          = ToBitmapData(bitmapData, firstNonBlankLine);

                if (antialiasing)
                {
                    plane.CharacterAntialiasingData         = ToAntialiasingData(antialiasingData);
                    plane.CharacterAntialiasingMetrics.Size = (uint)plane.CharacterAntialiasingData.Length;
                }

                font.Metrics.MaximumCharacterWidth = Helper.FitIntoInt16(maxCharacterWidth, Trace);

                font.FontPlanes[planeNumber] = plane;
            }
        }
示例#30
0
        private void RemapGlyphsToCharacters(TinyFont font)
        {
            Dictionary <ushort, int> mapping = new Dictionary <ushort, int>();

            foreach (CharacterImportInfo info in _glyphImportList)
            {
                if (info.Mapping.Glyph.HasValue)
                {
                    mapping[info.Mapping.Glyph.Value] = info.Mapping.Character.Value;
                }
            }

            foreach (CharacterImportInfo info in _characterImportList.Values)
            {
                if (info.Mapping.Glyph.HasValue)
                {
                    mapping[info.Mapping.Glyph.Value] = info.Mapping.Character.Value;
                }
            }

            byte   plane;
            ushort planeLess;

            foreach (StateMachineAppendix substition in font.Appendices.OfType <StateMachineAppendix>())
            {
                foreach (StateMachineAppendix.Feature feature in substition.Features)
                {
                    foreach (StateMachineAppendix.Rule rule in feature.Rules)
                    {
                        if (rule.Condition == StateMachineAppendix.RuleCondition.Glyph)
                        {
                            RemapGlyph(mapping, rule.ConditionParameter, out plane, out planeLess);
                            rule.ConditionPlane     = plane;
                            rule.ConditionParameter = planeLess;
                        }

                        switch (rule.Action)
                        {
                        case StateMachineAppendix.RuleAction.GlyphOverwrite:
                        case StateMachineAppendix.RuleAction.GlyphRewrite_2_1:
                        case StateMachineAppendix.RuleAction.GlyphRewrite_3_1:
                        case StateMachineAppendix.RuleAction.GlyphInsertion:
                        {
                            RemapGlyph(mapping, rule.ActionParameter, out plane, out planeLess);
                            rule.ActionPlane     = plane;
                            rule.ActionParameter = planeLess;
                        }
                        break;

                        case StateMachineAppendix.RuleAction.GlyphRewrite_N_M:
                            int offset     = rule.ActionParameter + sizeof(ushort);
                            int glyphCount = BitConverter.ToUInt16(substition.ParametersHeap, offset);
                            offset += sizeof(ushort);

                            for (int i = 0; i < glyphCount; i++, offset += sizeof(int))
                            {
                                int glyph = BitConverter.ToInt32(substition.ParametersHeap, offset);
                                glyph = RemapGlyph(mapping, (ushort)glyph, out plane, out planeLess);

                                BitConverter.GetBytes(glyph).CopyTo(substition.ParametersHeap, offset);
                            }
                            break;
                        }
                    }
                }
            }

            foreach (GlyphClassesAppendix coverage in font.Appendices.OfType <GlyphClassesAppendix>())
            {
                for (int i = 0; i < coverage.CoverageGlyphs.Count; i++)
                {
                    coverage.CoverageGlyphs[i] = RemapGlyph(mapping, (ushort)coverage.CoverageGlyphs[i], out plane, out planeLess);
                }
            }
        }