mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-15 19:54:52 +08:00
#6 use the same base class for both type 1 and cff private dictionaries to enable comparisons and rationalise api
This commit is contained in:
245
src/UglyToad.PdfPig/Fonts/AdobeStylePrivateDictionary.cs
Normal file
245
src/UglyToad.PdfPig/Fonts/AdobeStylePrivateDictionary.cs
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
namespace UglyToad.PdfPig.Fonts
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Util.JetBrains.Annotations;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Holds common properties between Type 1 and Compact Font Format private dictionaries.
|
||||||
|
/// </summary>
|
||||||
|
internal abstract class AdobeStylePrivateDictionary
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Default value of <see cref="BlueScale"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly decimal DefaultBlueScale = 0.039625m;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default value of <see cref="ExpansionFactor"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly decimal DefaultExpansionFactor = 0.06m;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default value of <see cref="BlueFuzz"/>.
|
||||||
|
/// </summary>
|
||||||
|
public const int DefaultBlueFuzz = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default value of <see cref="BlueShift"/>.
|
||||||
|
/// </summary>
|
||||||
|
public const int DefaultBlueShift = 7;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default value of <see cref="LanguageGroup"/>.
|
||||||
|
/// </summary>
|
||||||
|
public const int DefaultLanguageGroup = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required. An array containing an even number of integers.
|
||||||
|
/// The first pair is the baseline overshoot position and the baseline.
|
||||||
|
/// All following pairs describe top-zones.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public IReadOnlyList<int> BlueValues { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: Pairs of integers similar to <see cref="BlueValues"/>.
|
||||||
|
/// These only describe bottom zones.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public IReadOnlyList<int> OtherBlues { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: Integer pairs similar to <see cref="BlueValues"/> however these
|
||||||
|
/// are used to enforce consistency across a font family when there are small differences (<1px) in
|
||||||
|
/// font alignment.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public IReadOnlyList<int> FamilyBlues { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: Integer pairs similar to <see cref="OtherBlues"/> however these
|
||||||
|
/// are used to enforce consistency across a font family with small differences
|
||||||
|
/// in alignment similarly to <see cref="FamilyBlues"/>.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public IReadOnlyList<int> FamilyOtherBlues { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: The point size at which overshoot suppression stops.
|
||||||
|
/// The value is a related to the number of pixels tall that one character space unit will be
|
||||||
|
/// before overshoot suppression is switched off. Overshoot suppression enforces features to snap
|
||||||
|
/// to alignment zones when the point size is below that affected by this value.
|
||||||
|
/// Default: 0.039625
|
||||||
|
/// </summary>
|
||||||
|
/// <example>
|
||||||
|
/// A blue scale of 0.039625 switches overshoot suppression off at 10 points
|
||||||
|
/// on a 300 dpi device using the formula (for 300 dpi):
|
||||||
|
/// BlueScale = (pointsize - 0.49)/240
|
||||||
|
/// For example, if you wish overshoot suppression to turn off at 11
|
||||||
|
/// points on a 300-dpi device, you should set BlueScale to
|
||||||
|
/// (11 − 0.49) ÷ 240 or 0.04379
|
||||||
|
/// </example>
|
||||||
|
public decimal BlueScale { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: The character space distance beyond the flat position of alignment zones
|
||||||
|
/// at which overshoot enforcement occurs.
|
||||||
|
/// Default: 7
|
||||||
|
/// </summary>
|
||||||
|
public int BlueShift { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: The number of character space units to extend an alignment zone
|
||||||
|
/// on a horizontal stem.
|
||||||
|
/// If the top or bottom of a horizontal stem is within BlueFuzz units outside a top-zone
|
||||||
|
/// then the stem top/bottom is treated as if it were within the zone.
|
||||||
|
/// Default: 1
|
||||||
|
/// </summary>
|
||||||
|
public int BlueFuzz { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: The dominant width of horizontal stems vertically in character space units.
|
||||||
|
/// </summary>
|
||||||
|
public decimal? StandardHorizontalWidth { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: The dominant width of vertical stems horizontally in character space units.
|
||||||
|
/// </summary>
|
||||||
|
public decimal? StandardVerticalWidth { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: Up to 12 numbers with the most common widths for horizontal stems vertically in character space units.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public IReadOnlyList<decimal> StemSnapHorizontalWidths { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: Up to 12 numbers with the most common widths for vertical stems horizontally in character space units.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public IReadOnlyList<decimal> StemSnapVerticalWidths { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: At small sizes at low resolutions this controls whether bold characters should appear thicker using
|
||||||
|
/// special techniques.
|
||||||
|
/// </summary>
|
||||||
|
public bool ForceBold { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: Language group 0 includes Latin, Greek and Cyrillic as well as similar alphabets.
|
||||||
|
/// Language group 1 includes Chinese, Japanese Kanji and Korean Hangul as well as similar alphabets.
|
||||||
|
/// Default: 0
|
||||||
|
/// </summary>
|
||||||
|
public int LanguageGroup { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional: The limit for changing the size of a character bounding box for
|
||||||
|
/// <see cref="LanguageGroup"/> 1 counters during font processing.
|
||||||
|
/// </summary>
|
||||||
|
public decimal ExpansionFactor { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="AdobeStylePrivateDictionary"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The builder used to gather property values.</param>
|
||||||
|
protected AdobeStylePrivateDictionary([NotNull] BaseBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueValues = builder.BlueValues ?? Array.Empty<int>();
|
||||||
|
OtherBlues = builder.OtherBlues ?? Array.Empty<int>();
|
||||||
|
FamilyBlues = builder.FamilyBlues ?? Array.Empty<int>();
|
||||||
|
FamilyOtherBlues = builder.FamilyOtherBlues ?? Array.Empty<int>();
|
||||||
|
BlueScale = builder.BlueScale ?? DefaultBlueScale;
|
||||||
|
BlueFuzz = builder.BlueFuzz ?? DefaultBlueFuzz;
|
||||||
|
BlueShift = builder.BlueShift ?? DefaultBlueShift;
|
||||||
|
StandardHorizontalWidth = builder.StandardHorizontalWidth;
|
||||||
|
StandardVerticalWidth = builder.StandardVerticalWidth;
|
||||||
|
StemSnapHorizontalWidths = builder.StemSnapHorizontalWidths ?? Array.Empty<decimal>();
|
||||||
|
StemSnapVerticalWidths = builder.StemSnapVerticalWidths ?? Array.Empty<decimal>();
|
||||||
|
ForceBold = builder.ForceBold ?? false;
|
||||||
|
LanguageGroup = builder.LanguageGroup ?? DefaultLanguageGroup;
|
||||||
|
ExpansionFactor = builder.ExpansionFactor ?? DefaultExpansionFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A mutable builder which can set any property of the private dictionary and performs no validation.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class BaseBuilder
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.BlueValues"/>.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyList<int> BlueValues { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.OtherBlues"/>.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyList<int> OtherBlues { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.FamilyBlues"/>.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyList<int> FamilyBlues { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.FamilyOtherBlues"/>.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyList<int> FamilyOtherBlues { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.BlueScale"/>.
|
||||||
|
/// </summary>
|
||||||
|
public decimal? BlueScale { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.BlueShift"/>.
|
||||||
|
/// </summary>
|
||||||
|
public int? BlueShift { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.BlueFuzz"/>.
|
||||||
|
/// </summary>
|
||||||
|
public int? BlueFuzz { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.StandardVerticalWidth"/>.
|
||||||
|
/// </summary>
|
||||||
|
public decimal? StandardHorizontalWidth { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.StandardVerticalWidth"/>.
|
||||||
|
/// </summary>
|
||||||
|
public decimal? StandardVerticalWidth { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.StemSnapHorizontalWidths"/>.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyList<decimal> StemSnapHorizontalWidths { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.StemSnapVerticalWidths"/>.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyList<decimal> StemSnapVerticalWidths { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.ForceBold"/>.
|
||||||
|
/// </summary>
|
||||||
|
public bool? ForceBold { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.LanguageGroup"/>.
|
||||||
|
/// </summary>
|
||||||
|
public int? LanguageGroup { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="AdobeStylePrivateDictionary.ExpansionFactor"/>.
|
||||||
|
/// </summary>
|
||||||
|
public decimal? ExpansionFactor { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
var topDictionary = topLevelDictionaryReader.Read(individualData, stringIndex);
|
var topDictionary = topLevelDictionaryReader.Read(individualData, stringIndex);
|
||||||
|
|
||||||
var privateDictionary = new CompactFontFormatPrivateDictionary();
|
var privateDictionary = CompactFontFormatPrivateDictionary.GetDefault();
|
||||||
|
|
||||||
if (topDictionary.PrivateDictionarySizeAndOffset.Item2 >= 0)
|
if (topDictionary.PrivateDictionarySizeAndOffset.Item2 >= 0)
|
||||||
{
|
{
|
||||||
@@ -49,9 +49,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var localSubroutines = CompactFontFormatIndex.None;
|
var localSubroutines = CompactFontFormatIndex.None;
|
||||||
if (privateDictionary.LocalSubroutineLocalOffset.HasValue)
|
if (privateDictionary.LocalSubroutineOffset.HasValue)
|
||||||
{
|
{
|
||||||
data.Seek(privateDictionary.LocalSubroutineLocalOffset.Value);
|
data.Seek(privateDictionary.LocalSubroutineOffset.Value);
|
||||||
|
|
||||||
localSubroutines = indexReader.ReadDictionaryData(data);
|
localSubroutines = indexReader.ReadDictionaryData(data);
|
||||||
}
|
}
|
||||||
|
@@ -5,13 +5,13 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Geometry;
|
using Geometry;
|
||||||
|
|
||||||
internal abstract class CompactFontFormatDictionaryReader<T>
|
internal abstract class CompactFontFormatDictionaryReader<TResult, TBuilder>
|
||||||
{
|
{
|
||||||
private readonly List<Operand> operands = new List<Operand>();
|
private readonly List<Operand> operands = new List<Operand>();
|
||||||
|
|
||||||
public abstract T Read(CompactFontFormatData data, IReadOnlyList<string> stringIndex);
|
public abstract TResult Read(CompactFontFormatData data, IReadOnlyList<string> stringIndex);
|
||||||
|
|
||||||
protected T ReadDictionary(T dictionary, CompactFontFormatData data, IReadOnlyList<string> stringIndex)
|
protected TBuilder ReadDictionary(TBuilder builder, CompactFontFormatData data, IReadOnlyList<string> stringIndex)
|
||||||
{
|
{
|
||||||
while (data.CanRead())
|
while (data.CanRead())
|
||||||
{
|
{
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
{
|
{
|
||||||
var key = byte0 == 12 ? new OperandKey(byte0, data.ReadByte()) : new OperandKey(byte0);
|
var key = byte0 == 12 ? new OperandKey(byte0, data.ReadByte()) : new OperandKey(byte0);
|
||||||
|
|
||||||
ApplyOperation(dictionary, operands, key, stringIndex);
|
ApplyOperation(builder, operands, key, stringIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dictionary;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static decimal ReadRealNumber(CompactFontFormatData data)
|
private static decimal ReadRealNumber(CompactFontFormatData data)
|
||||||
@@ -162,7 +162,7 @@
|
|||||||
return decimal.Parse(sb.ToString());
|
return decimal.Parse(sb.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void ApplyOperation(T dictionary, List<Operand> operands, OperandKey operandKey, IReadOnlyList<string> stringIndex);
|
protected abstract void ApplyOperation(TBuilder builder, List<Operand> operands, OperandKey operandKey, IReadOnlyList<string> stringIndex);
|
||||||
|
|
||||||
protected static string GetString(List<Operand> operands, IReadOnlyList<string> stringIndex)
|
protected static string GetString(List<Operand> operands, IReadOnlyList<string> stringIndex)
|
||||||
{
|
{
|
||||||
@@ -232,6 +232,28 @@
|
|||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static int[] ReadDeltaToIntArray(List<Operand> operands)
|
||||||
|
{
|
||||||
|
var results = new int[operands.Count];
|
||||||
|
|
||||||
|
if (operands.Count == 0)
|
||||||
|
{
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
results[0] = (int)operands[0].Decimal;
|
||||||
|
|
||||||
|
for (var i = 1; i < operands.Count; i++)
|
||||||
|
{
|
||||||
|
var previous = results[i - 1];
|
||||||
|
var current = operands[i].Decimal;
|
||||||
|
|
||||||
|
results[i] = (int)(previous + current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
protected static decimal[] ReadDeltaToArray(List<Operand> operands)
|
protected static decimal[] ReadDeltaToArray(List<Operand> operands)
|
||||||
{
|
{
|
||||||
var results = new decimal[operands.Count];
|
var results = new decimal[operands.Count];
|
||||||
|
@@ -1,47 +1,65 @@
|
|||||||
namespace UglyToad.PdfPig.Fonts.CompactFontFormat.Dictionaries
|
namespace UglyToad.PdfPig.Fonts.CompactFontFormat.Dictionaries
|
||||||
{
|
{
|
||||||
internal class CompactFontFormatPrivateDictionary
|
internal class CompactFontFormatPrivateDictionary : AdobeStylePrivateDictionary
|
||||||
{
|
{
|
||||||
public decimal[] BlueValues { get; set; }
|
/// <summary>
|
||||||
|
/// Compatibility entry.
|
||||||
|
/// </summary>
|
||||||
|
public decimal InitialRandomSeed { get; }
|
||||||
|
|
||||||
public decimal[] OtherBlues { get; set; }
|
/// <summary>
|
||||||
|
/// The offset in bytes for the local subroutine index in this font. The value is relative to this private dictionary.
|
||||||
public decimal[] FamilyBlues { get; set; }
|
/// </summary>
|
||||||
|
public int? LocalSubroutineOffset { get; }
|
||||||
public decimal[] FamilyOtherBlues { get; set; }
|
|
||||||
|
|
||||||
public decimal BlueScale { get; set; } = 0.039625m;
|
|
||||||
|
|
||||||
public decimal BlueShift { get; set; } = 7;
|
|
||||||
|
|
||||||
public decimal BlueFuzz { get; set; } = 1;
|
|
||||||
|
|
||||||
public decimal StandardHorizontalWidth { get; set; }
|
|
||||||
|
|
||||||
public decimal StandardVerticalWidth { get; set; }
|
|
||||||
|
|
||||||
public decimal[] StemSnapHorizontal { get; set; }
|
|
||||||
|
|
||||||
public decimal[] StemStapVertical { get; set; }
|
|
||||||
|
|
||||||
public bool ForceBold { get; set; }
|
|
||||||
|
|
||||||
public decimal LanguageGroup { get; set; }
|
|
||||||
|
|
||||||
public decimal ExpansionFactor { get; set; }
|
|
||||||
|
|
||||||
public decimal InitialRandomSeed { get; set; }
|
|
||||||
|
|
||||||
public int? LocalSubroutineLocalOffset { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If a glyph's width equals the default width X it can be omitted from the charstring.
|
/// If a glyph's width equals the default width X it can be omitted from the charstring.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal DefaultWidthX { get; set; }
|
public decimal DefaultWidthX { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If not equal to <see cref="DefaultWidthX"/>, Glyph width is computed by adding the charstring width to the nominal width X value.
|
/// If not equal to <see cref="DefaultWidthX"/>, Glyph width is computed by adding the charstring width to the nominal width X value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal NominalWidthX { get; set; }
|
public decimal NominalWidthX { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="T:UglyToad.PdfPig.Fonts.CompactFontFormat.Dictionaries.CompactFontFormatPrivateDictionary" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The builder used to gather property values.</param>
|
||||||
|
public CompactFontFormatPrivateDictionary(Builder builder) : base(builder)
|
||||||
|
{
|
||||||
|
InitialRandomSeed = builder.InitialRandomSeed;
|
||||||
|
LocalSubroutineOffset = builder.LocalSubroutineOffset;
|
||||||
|
DefaultWidthX = builder.DefaultWidthX;
|
||||||
|
NominalWidthX = builder.NominalWidthX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CompactFontFormatPrivateDictionary GetDefault()
|
||||||
|
{
|
||||||
|
return new Builder().Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Builder : BaseBuilder
|
||||||
|
{
|
||||||
|
public decimal InitialRandomSeed { get; set; }
|
||||||
|
|
||||||
|
public int? LocalSubroutineOffset { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If a glyph's width equals the default width X it can be omitted from the charstring.
|
||||||
|
/// </summary>
|
||||||
|
public decimal DefaultWidthX { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If not equal to <see cref="DefaultWidthX"/>, Glyph width is computed by adding the charstring width to the nominal width X value.
|
||||||
|
/// </summary>
|
||||||
|
public decimal NominalWidthX { get; set; }
|
||||||
|
|
||||||
|
public CompactFontFormatPrivateDictionary Build()
|
||||||
|
{
|
||||||
|
return new CompactFontFormatPrivateDictionary(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -3,32 +3,32 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
internal class CompactFontFormatPrivateDictionaryReader : CompactFontFormatDictionaryReader<CompactFontFormatPrivateDictionary>
|
internal class CompactFontFormatPrivateDictionaryReader : CompactFontFormatDictionaryReader<CompactFontFormatPrivateDictionary, CompactFontFormatPrivateDictionary.Builder>
|
||||||
{
|
{
|
||||||
public override CompactFontFormatPrivateDictionary Read(CompactFontFormatData data, IReadOnlyList<string> stringIndex)
|
public override CompactFontFormatPrivateDictionary Read(CompactFontFormatData data, IReadOnlyList<string> stringIndex)
|
||||||
{
|
{
|
||||||
var dictionary = new CompactFontFormatPrivateDictionary();
|
var builder = new CompactFontFormatPrivateDictionary.Builder();
|
||||||
|
|
||||||
ReadDictionary(dictionary, data, stringIndex);
|
ReadDictionary(builder, data, stringIndex);
|
||||||
|
|
||||||
return dictionary;
|
return builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ApplyOperation(CompactFontFormatPrivateDictionary dictionary, List<Operand> operands, OperandKey operandKey, IReadOnlyList<string> stringIndex)
|
protected override void ApplyOperation(CompactFontFormatPrivateDictionary.Builder dictionary, List<Operand> operands, OperandKey operandKey, IReadOnlyList<string> stringIndex)
|
||||||
{
|
{
|
||||||
switch (operandKey.Byte0)
|
switch (operandKey.Byte0)
|
||||||
{
|
{
|
||||||
case 6:
|
case 6:
|
||||||
dictionary.BlueValues = ReadDeltaToArray(operands);
|
dictionary.BlueValues = ReadDeltaToIntArray(operands);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
dictionary.OtherBlues = ReadDeltaToArray(operands);
|
dictionary.OtherBlues = ReadDeltaToIntArray(operands);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
dictionary.FamilyBlues = ReadDeltaToArray(operands);
|
dictionary.FamilyBlues = ReadDeltaToIntArray(operands);
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
dictionary.FamilyOtherBlues = ReadDeltaToArray(operands);
|
dictionary.FamilyOtherBlues = ReadDeltaToIntArray(operands);
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
dictionary.StandardHorizontalWidth = operands[0].Decimal;
|
dictionary.StandardHorizontalWidth = operands[0].Decimal;
|
||||||
@@ -49,22 +49,22 @@
|
|||||||
dictionary.BlueScale = operands[0].Decimal;
|
dictionary.BlueScale = operands[0].Decimal;
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
dictionary.BlueShift = operands[0].Decimal;
|
dictionary.BlueShift = operands[0].Int;
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
dictionary.BlueFuzz = operands[0].Decimal;
|
dictionary.BlueFuzz = operands[0].Int;
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
dictionary.StemSnapHorizontal = ReadDeltaToArray(operands);
|
dictionary.StemSnapHorizontalWidths = ReadDeltaToArray(operands);
|
||||||
break;
|
break;
|
||||||
case 13:
|
case 13:
|
||||||
dictionary.StemStapVertical = ReadDeltaToArray(operands);
|
dictionary.StemSnapVerticalWidths = ReadDeltaToArray(operands);
|
||||||
break;
|
break;
|
||||||
case 14:
|
case 14:
|
||||||
dictionary.ForceBold = operands[0].Decimal == 1;
|
dictionary.ForceBold = operands[0].Decimal == 1;
|
||||||
break;
|
break;
|
||||||
case 17:
|
case 17:
|
||||||
dictionary.LanguageGroup = operands[0].Decimal;
|
dictionary.LanguageGroup = operands[0].Int;
|
||||||
break;
|
break;
|
||||||
case 18:
|
case 18:
|
||||||
dictionary.ExpansionFactor = operands[0].Decimal;
|
dictionary.ExpansionFactor = operands[0].Decimal;
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 19:
|
case 19:
|
||||||
dictionary.LocalSubroutineLocalOffset = GetIntOrDefault(operands, -1);
|
dictionary.LocalSubroutineOffset = GetIntOrDefault(operands, -1);
|
||||||
break;
|
break;
|
||||||
case 20:
|
case 20:
|
||||||
dictionary.DefaultWidthX = operands[0].Decimal;
|
dictionary.DefaultWidthX = operands[0].Decimal;
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Core;
|
using Core;
|
||||||
|
|
||||||
internal class CompactFontFormatTopLevelDictionaryReader : CompactFontFormatDictionaryReader<CompactFontFormatTopLevelDictionary>
|
internal class CompactFontFormatTopLevelDictionaryReader : CompactFontFormatDictionaryReader<CompactFontFormatTopLevelDictionary, CompactFontFormatTopLevelDictionary>
|
||||||
{
|
{
|
||||||
public override CompactFontFormatTopLevelDictionary Read(CompactFontFormatData data, IReadOnlyList<string> stringIndex)
|
public override CompactFontFormatTopLevelDictionary Read(CompactFontFormatData data, IReadOnlyList<string> stringIndex)
|
||||||
{
|
{
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Parser;
|
using Parser;
|
||||||
|
using Util.JetBrains.Annotations;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Private dictionary for a Type 1 font contains hints that apply across all characters in the font. These hints
|
/// The Private dictionary for a Type 1 font contains hints that apply across all characters in the font. These hints
|
||||||
@@ -12,132 +13,13 @@
|
|||||||
/// Note that subroutines are also defined in the private dictionary however for the purposes of this API they are
|
/// Note that subroutines are also defined in the private dictionary however for the purposes of this API they are
|
||||||
/// stored on the parent <see cref="Type1FontProgram"/>.
|
/// stored on the parent <see cref="Type1FontProgram"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class Type1PrivateDictionary
|
internal class Type1PrivateDictionary : AdobeStylePrivateDictionary
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Default value of <see cref="BlueScale"/>.
|
|
||||||
/// </summary>
|
|
||||||
public static readonly decimal DefaultBlueScale = 0.039625m;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value of <see cref="ExpansionFactor"/>.
|
|
||||||
/// </summary>
|
|
||||||
public static readonly decimal DefaultExpansionFactor = 0.06m;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value of <see cref="BlueFuzz"/>.
|
|
||||||
/// </summary>
|
|
||||||
public const int DefaultBlueFuzz = 1;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value of <see cref="BlueShift"/>.
|
|
||||||
/// </summary>
|
|
||||||
public const int DefaultBlueShift = 7;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value of <see cref="LanguageGroup"/>.
|
|
||||||
/// </summary>
|
|
||||||
public const int DefaultLanguageGroup = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Optional: Uniquely identifies this font.
|
/// Optional: Uniquely identifies this font.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? UniqueId { get; set; }
|
public int? UniqueId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required. An array containing an even number of integers.
|
|
||||||
/// The first pair is the baseline overshoot position and the baseline.
|
|
||||||
/// All following pairs describe top-zones.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<int> BlueValues { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: Pairs of integers similar to <see cref="BlueValues"/>.
|
|
||||||
/// These only describe bottom zones.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<int> OtherBlues { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: Integer pairs similar to <see cref="BlueValues"/> however these
|
|
||||||
/// are used to enforce consistency across a font family when there are small differences (<1px) in
|
|
||||||
/// font alignment.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<int> FamilyBlues { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: Integer pairs similar to <see cref="OtherBlues"/> however these
|
|
||||||
/// are used to enforce consistency across a font family with small differences
|
|
||||||
/// in alignment similarly to <see cref="FamilyBlues"/>.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<int> FamilyOtherBlues { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: The point size at which overshoot suppression stops.
|
|
||||||
/// The value is a related to the number of pixels tall that one character space unit will be
|
|
||||||
/// before overshoot suppression is switched off. Overshoot suppression enforces features to snap
|
|
||||||
/// to alignment zones when the point size is below that affected by this value.
|
|
||||||
/// Default: 0.039625
|
|
||||||
/// </summary>
|
|
||||||
/// <example>
|
|
||||||
/// A blue scale of 0.039625 switches overshoot suppression off at 10 points
|
|
||||||
/// on a 300 dpi device using the formula (for 300 dpi):
|
|
||||||
/// BlueScale = (pointsize - 0.49)/240
|
|
||||||
/// For example, if you wish overshoot suppression to turn off at 11
|
|
||||||
/// points on a 300-dpi device, you should set BlueScale to
|
|
||||||
/// (11 − 0.49) ÷ 240 or 0.04379
|
|
||||||
/// </example>
|
|
||||||
public decimal BlueScale { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: The character space distance beyond the flat position of alignment zones
|
|
||||||
/// at which overshoot enforcement occurs.
|
|
||||||
/// Default: 7
|
|
||||||
/// </summary>
|
|
||||||
public int BlueShift { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: The number of character space units to extend an alignment zone
|
|
||||||
/// on a horizontal stem.
|
|
||||||
/// If the top or bottom of a horizontal stem is within BlueFuzz units outside a top-zone
|
|
||||||
/// then the stem top/bottom is treated as if it were within the zone.
|
|
||||||
/// Default: 1
|
|
||||||
/// </summary>
|
|
||||||
public int BlueFuzz { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: The dominant width of horizontal stems vertically in character space units.
|
|
||||||
/// </summary>
|
|
||||||
public decimal? StandardHorizontalWidth { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: The dominant width of vertical stems horizontally in character space units.
|
|
||||||
/// </summary>
|
|
||||||
public decimal? StandardVerticalWidth { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: Up to 12 numbers with the most common widths for horizontal stems vertically in character space units.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<decimal> StemSnapHorizontalWidths { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: Up to 12 numbers with the most common widths for vertical stems horizontally in character space units.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<decimal> StemSnapVerticalWidths { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: At small sizes at low resolutions this controls whether bold characters should appear thicker using
|
|
||||||
/// special techniques.
|
|
||||||
/// </summary>
|
|
||||||
public bool ForceBold { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: Language group 0 includes Latin, Greek and Cyrillic as well as similar alphabets.
|
|
||||||
/// Language group 1 includes Chinese, Japanese Kanji and Korean Hangul as well as similar alphabets.
|
|
||||||
/// If language group is 1 then <see cref="RoundStemUp"/> should also be set.
|
|
||||||
/// Default: 0
|
|
||||||
/// </summary>
|
|
||||||
public int LanguageGroup { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Optional: Indicates the number of random bytes used for charstring encryption/decryption.
|
/// Optional: Indicates the number of random bytes used for charstring encryption/decryption.
|
||||||
/// Default: 4
|
/// Default: 4
|
||||||
@@ -145,16 +27,10 @@
|
|||||||
public int LenIv { get; }
|
public int LenIv { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Optional: Preserved for backwards compatibility. Must be set if the <see cref="LanguageGroup"/> is 1.
|
/// Optional: Preserved for backwards compatibility. Must be set if the <see cref="AdobeStylePrivateDictionary.LanguageGroup"/> is 1.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? RoundStemUp { get; }
|
public bool? RoundStemUp { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional: The limit for changing the size of a character bounding box for
|
|
||||||
/// <see cref="LanguageGroup"/> 1 counters during font processing.
|
|
||||||
/// </summary>
|
|
||||||
public decimal ExpansionFactor { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required: Backwards compatibility.
|
/// Required: Backwards compatibility.
|
||||||
/// Default: 5839
|
/// Default: 5839
|
||||||
@@ -165,13 +41,15 @@
|
|||||||
/// Required: Backwards compatibility.
|
/// Required: Backwards compatibility.
|
||||||
/// Default: {16 16}
|
/// Default: {16 16}
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
public MinFeature MinFeature { get; } = new MinFeature(16, 16);
|
public MinFeature MinFeature { get; } = new MinFeature(16, 16);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="Type1PrivateDictionary"/>.
|
/// Creates a new <see cref="T:UglyToad.PdfPig.Fonts.Type1.Type1PrivateDictionary" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder">The builder used to gather property values.</param>
|
/// <param name="builder">The builder used to gather property values.</param>
|
||||||
public Type1PrivateDictionary(Builder builder)
|
public Type1PrivateDictionary([NotNull] Builder builder) : base(builder)
|
||||||
{
|
{
|
||||||
if (builder == null)
|
if (builder == null)
|
||||||
{
|
{
|
||||||
@@ -179,28 +57,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
UniqueId = builder.UniqueId;
|
UniqueId = builder.UniqueId;
|
||||||
BlueValues = builder.BlueValues ?? Array.Empty<int>();
|
|
||||||
OtherBlues = builder.OtherBlues ?? Array.Empty<int>();
|
|
||||||
FamilyBlues = builder.FamilyBlues ?? Array.Empty<int>();
|
|
||||||
FamilyOtherBlues = builder.FamilyOtherBlues ?? Array.Empty<int>();
|
|
||||||
BlueScale = builder.BlueScale ?? DefaultBlueScale;
|
|
||||||
BlueFuzz = builder.BlueFuzz ?? DefaultBlueFuzz;
|
|
||||||
BlueShift = builder.BlueShift ?? DefaultBlueShift;
|
|
||||||
StandardHorizontalWidth = builder.StandardHorizontalWidth;
|
|
||||||
StandardVerticalWidth = builder.StandardVerticalWidth;
|
|
||||||
StemSnapHorizontalWidths = builder.StemSnapHorizontalWidths ?? Array.Empty<decimal>();
|
|
||||||
StemSnapVerticalWidths = builder.StemSnapVerticalWidths ?? Array.Empty<decimal>();
|
|
||||||
ForceBold = builder.ForceBold ?? false;
|
|
||||||
LanguageGroup = builder.LanguageGroup ?? DefaultLanguageGroup;
|
|
||||||
RoundStemUp = builder.RoundStemUp;
|
RoundStemUp = builder.RoundStemUp;
|
||||||
LenIv = builder.LenIv;
|
LenIv = builder.LenIv;
|
||||||
ExpansionFactor = builder.ExpansionFactor ?? DefaultExpansionFactor;
|
|
||||||
|
if (builder.Password.HasValue)
|
||||||
|
{
|
||||||
|
Password = builder.Password.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A mutable builder which can set any property of the private dictionary and performs no validation.
|
/// A mutable builder which can set any property of the private dictionary and performs no validation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Builder
|
public class Builder : BaseBuilder
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Temporary storage for the Rd procedure tokens.
|
/// Temporary storage for the Rd procedure tokens.
|
||||||
@@ -231,72 +100,7 @@
|
|||||||
/// <see cref="Type1PrivateDictionary.UniqueId"/>.
|
/// <see cref="Type1PrivateDictionary.UniqueId"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? UniqueId { get; set; }
|
public int? UniqueId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.BlueValues"/>.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<int> BlueValues { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.OtherBlues"/>.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<int> OtherBlues { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.FamilyBlues"/>.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<int> FamilyBlues { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.FamilyOtherBlues"/>.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<int> FamilyOtherBlues { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.BlueScale"/>.
|
|
||||||
/// </summary>
|
|
||||||
public decimal? BlueScale { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.BlueShift"/>.
|
|
||||||
/// </summary>
|
|
||||||
public int? BlueShift { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.BlueFuzz"/>.
|
|
||||||
/// </summary>
|
|
||||||
public int? BlueFuzz { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.StandardVerticalWidth"/>.
|
|
||||||
/// </summary>
|
|
||||||
public decimal? StandardHorizontalWidth { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.StandardVerticalWidth"/>.
|
|
||||||
/// </summary>
|
|
||||||
public decimal? StandardVerticalWidth { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.StemSnapHorizontalWidths"/>.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<decimal> StemSnapHorizontalWidths { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.StemSnapVerticalWidths"/>.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<decimal> StemSnapVerticalWidths { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.ForceBold"/>.
|
|
||||||
/// </summary>
|
|
||||||
public bool? ForceBold { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.LanguageGroup"/>.
|
|
||||||
/// </summary>
|
|
||||||
public int? LanguageGroup { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="Type1PrivateDictionary.Password"/>.
|
/// <see cref="Type1PrivateDictionary.Password"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -317,16 +121,12 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? RoundStemUp { get; set; }
|
public bool? RoundStemUp { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Type1PrivateDictionary.ExpansionFactor"/>.
|
|
||||||
/// </summary>
|
|
||||||
public decimal? ExpansionFactor { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generate a <see cref="Type1PrivateDictionary"/> from the values in this builder.
|
/// Generate a <see cref="Type1PrivateDictionary"/> from the values in this builder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The generated <see cref="Type1PrivateDictionary"/>.</returns>
|
/// <returns>The generated <see cref="Type1PrivateDictionary"/>.</returns>
|
||||||
public Type1PrivateDictionary Build()
|
[NotNull]
|
||||||
|
public Type1PrivateDictionary Build()
|
||||||
{
|
{
|
||||||
return new Type1PrivateDictionary(this);
|
return new Type1PrivateDictionary(this);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user