/// <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> /// 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; } } }
private CharacterInfo GetCharacterInfo(char c, FontPlane plane, int planeNumber) { int rangeIndex = plane.CharacterRanges.BinarySearch(c, CharacterRangeComparer.Instance); if (rangeIndex >= 0) { return(new CharacterInfo(this, rangeIndex, c, plane, planeNumber)); } return(null); }
/// <summary> /// Returns information for character specified by its code. /// </summary> /// <param name="c">Character code.</param> /// <returns>Character information.</returns> public CharacterInfo GetCharacterInfo(int c) { int planeNumber = c >> 16; FontPlane plane = FontPlanes[planeNumber]; if (plane != null) { return(GetCharacterInfo((char)c, plane, planeNumber)); } return(null); }
/// <summary> /// Sets Font Plane data for specified plane <paramref name="number"/>. /// If plane does not exists yet, it will be appended otherwise existing updated. /// It also update bit mask. /// </summary> /// <param name="number">Plane number.</param> /// <param name="plane">Font Plane data.</param> public void SetPlane(int number, FontPlane plane) { int index = IndexOfPlane(number); if (index >= 0) { _fontPlanes[index] = plane; } else { _fontPlanes.Insert(~index, plane); } _mask |= (ushort)(1 << (number - 1)); }
/// <summary> /// Enumerates thru all characters saved in Tiny Font accross all font planes sorted by font plane in ascending order. /// </summary> /// <returns>Character information.</returns> public IEnumerable <CharacterInfo> EnumerateAllCharacterInfos() { for (int planeNumber = 0; planeNumber <= LastPlane; planeNumber++) { FontPlane plane = FontPlanes[planeNumber]; if (plane != null) { for (int r = 0; r < plane.CharacterRanges.ItemsCount; r++) { CharacterRangeDescription range = plane.CharacterRanges[r]; for (char c = range.FirstCharacter; c <= range.LastCharacter; c++) { yield return(new CharacterInfo(this, r, c, plane, planeNumber)); } } } } }
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; } }
/// <summary> /// Creates new empty instance of Tiny Font. /// </summary> public TinyFont() { _baseFontPlane = new FontPlane(); _fontPlanes = new FontPlanesCollection(this); _appendices = new List <FontAppendix>(); }