#21 enable document creation using standard 14 font to test output

This commit is contained in:
Eliot Jones
2018-12-02 16:14:55 +00:00
parent d4813ba3a9
commit d6a896dcb0
63 changed files with 646 additions and 62 deletions

View File

@@ -2,7 +2,9 @@
{ {
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using Content; using Content;
using PdfPig.Fonts;
using PdfPig.Geometry; using PdfPig.Geometry;
using PdfPig.Util; using PdfPig.Util;
using PdfPig.Writer; using PdfPig.Writer;
@@ -59,6 +61,27 @@
return result; return result;
} }
[Fact]
public void CanWriteSinglePageStandard14FontHelloWorld()
{
var builder = new PdfDocumentBuilder();
var page = builder.AddPage(PageSize.A4);
var font = builder.AddStandard14Font(Standard14Font.Helvetica);
page.AddText("Hello World!", 12, new PdfPoint(25, 520), font);
var b = builder.Build();
using (var document = PdfDocument.Open(b))
{
var page1 = document.GetPage(1);
Assert.Equal(new[] {"Hello", "World!"}, page1.GetWords().Select(x => x.Text));
}
}
[Fact] [Fact]
public void CanWriteSinglePageHelloWorld() public void CanWriteSinglePageHelloWorld()
{ {

View File

@@ -36,23 +36,24 @@
private static readonly HashSet<string> Standard14Names = new HashSet<string>(); private static readonly HashSet<string> Standard14Names = new HashSet<string>();
private static readonly Dictionary<string, string> Standard14Mapping = new Dictionary<string, string>(34); private static readonly Dictionary<string, string> Standard14Mapping = new Dictionary<string, string>(34);
private static readonly Dictionary<string, FontMetrics> Standard14AfmMap = new Dictionary<string, FontMetrics>(34); private static readonly Dictionary<string, FontMetrics> Standard14AfmMap = new Dictionary<string, FontMetrics>(34);
private static readonly Dictionary<Standard14Font, FontMetrics> Standard14AfmTypeMap = new Dictionary<Standard14Font, FontMetrics>(14);
static Standard14() static Standard14()
{ {
AddAdobeFontMetrics("Courier-Bold"); AddAdobeFontMetrics("Courier-Bold", Standard14Font.CourierBold);
AddAdobeFontMetrics("Courier-BoldOblique"); AddAdobeFontMetrics("Courier-BoldOblique", Standard14Font.CourierBoldOblique);
AddAdobeFontMetrics("Courier"); AddAdobeFontMetrics("Courier", Standard14Font.Courier);
AddAdobeFontMetrics("Courier-Oblique"); AddAdobeFontMetrics("Courier-Oblique", Standard14Font.CourierOblique);
AddAdobeFontMetrics("Helvetica"); AddAdobeFontMetrics("Helvetica", Standard14Font.Helvetica);
AddAdobeFontMetrics("Helvetica-Bold"); AddAdobeFontMetrics("Helvetica-Bold", Standard14Font.HelveticaBold);
AddAdobeFontMetrics("Helvetica-BoldOblique"); AddAdobeFontMetrics("Helvetica-BoldOblique", Standard14Font.HelveticaBoldOblique);
AddAdobeFontMetrics("Helvetica-Oblique"); AddAdobeFontMetrics("Helvetica-Oblique", Standard14Font.HelveticaOblique);
AddAdobeFontMetrics("Symbol"); AddAdobeFontMetrics("Symbol", Standard14Font.Symbol);
AddAdobeFontMetrics("Times-Bold"); AddAdobeFontMetrics("Times-Bold", Standard14Font.TimesBold);
AddAdobeFontMetrics("Times-BoldItalic"); AddAdobeFontMetrics("Times-BoldItalic", Standard14Font.TimesBoldItalic);
AddAdobeFontMetrics("Times-Italic"); AddAdobeFontMetrics("Times-Italic", Standard14Font.TimesItalic);
AddAdobeFontMetrics("Times-Roman"); AddAdobeFontMetrics("Times-Roman", Standard14Font.TimesRoman);
AddAdobeFontMetrics("ZapfDingbats"); AddAdobeFontMetrics("ZapfDingbats", Standard14Font.ZapfDingbats);
// alternative names from Adobe Supplement to the ISO 32000 // alternative names from Adobe Supplement to the ISO 32000
AddAdobeFontMetrics("CourierCourierNew", "Courier"); AddAdobeFontMetrics("CourierCourierNew", "Courier");
@@ -79,12 +80,12 @@
AddAdobeFontMetrics("Times,BoldItalic", "Times-BoldItalic"); AddAdobeFontMetrics("Times,BoldItalic", "Times-BoldItalic");
} }
private static void AddAdobeFontMetrics(string fontName) private static void AddAdobeFontMetrics(string fontName, Standard14Font? type = null)
{ {
AddAdobeFontMetrics(fontName, fontName); AddAdobeFontMetrics(fontName, fontName, type);
} }
private static void AddAdobeFontMetrics(string fontName, string afmName) private static void AddAdobeFontMetrics(string fontName, string afmName, Standard14Font? type = null)
{ {
Standard14Names.Add(fontName); Standard14Names.Add(fontName);
Standard14Mapping.Add(fontName, afmName); Standard14Mapping.Add(fontName, afmName);
@@ -109,6 +110,10 @@
} }
Standard14AfmMap[fontName] = Parser.Parse(bytes, true); Standard14AfmMap[fontName] = Parser.Parse(bytes, true);
if (type.HasValue)
{
Standard14AfmTypeMap[type.Value] = Standard14AfmMap[fontName];
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -128,6 +133,11 @@
return metrics; return metrics;
} }
public static FontMetrics GetAdobeFontMetrics(Standard14Font fontType)
{
return Standard14AfmTypeMap[fontType];
}
/// <summary> /// <summary>
/// Determines if a font with this name is a standard 14 font. /// Determines if a font with this name is a standard 14 font.
/// </summary> /// </summary>
@@ -157,4 +167,22 @@
return mappedName; return mappedName;
} }
} }
internal enum Standard14Font
{
TimesRoman = 0,
TimesBold = 1,
TimesItalic=2,
TimesBoldItalic = 3,
Helvetica = 4,
HelveticaBold = 5,
HelveticaOblique = 6,
HelveticaBoldOblique = 7,
Courier = 8,
CourierBold = 9,
CourierOblique = 10,
CourierBoldOblique = 11,
Symbol = 12,
ZapfDingbats = 13
}
} }

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.ClippingPaths namespace UglyToad.PdfPig.Graphics.Operations.ClippingPaths
{ {
using System.IO;
using Content; using Content;
internal class ModifyClippingByEvenOddIntersect : IGraphicsStateOperation internal class ModifyClippingByEvenOddIntersect : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.ClippingPaths namespace UglyToad.PdfPig.Graphics.Operations.ClippingPaths
{ {
using System.IO;
using Content; using Content;
internal class ModifyClippingByNonZeroWindingIntersect : IGraphicsStateOperation internal class ModifyClippingByNonZeroWindingIntersect : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class CloseAndStrokePath : IGraphicsStateOperation internal class CloseAndStrokePath : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class CloseFillPathEvenOddRuleAndStroke : IGraphicsStateOperation internal class CloseFillPathEvenOddRuleAndStroke : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class CloseFillPathNonZeroWindingAndStroke : IGraphicsStateOperation internal class CloseFillPathNonZeroWindingAndStroke : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class EndPath : IGraphicsStateOperation internal class EndPath : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class FillPathEvenOddRule : IGraphicsStateOperation internal class FillPathEvenOddRule : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class FillPathEvenOddRuleAndStroke : IGraphicsStateOperation internal class FillPathEvenOddRuleAndStroke : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class FillPathNonZeroWinding : IGraphicsStateOperation internal class FillPathNonZeroWinding : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class FillPathNonZeroWindingAndStroke : IGraphicsStateOperation internal class FillPathNonZeroWindingAndStroke : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class FillPathNonZeroWindingCompatibility : IGraphicsStateOperation internal class FillPathNonZeroWindingCompatibility : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.General namespace UglyToad.PdfPig.Graphics.Operations.General
{ {
using System.IO;
using Content; using Content;
internal class SetColorRenderingIntent : IGraphicsStateOperation internal class SetColorRenderingIntent : IGraphicsStateOperation
@@ -12,5 +13,10 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
} }
} }

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.General namespace UglyToad.PdfPig.Graphics.Operations.General
{ {
using System.IO;
using Content; using Content;
internal class SetFlatnessTolerance : IGraphicsStateOperation internal class SetFlatnessTolerance : IGraphicsStateOperation
@@ -20,6 +21,11 @@
operationContext.GetCurrentState().Flatness = Tolerance; operationContext.GetCurrentState().Flatness = Tolerance;
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Tolerance} {Symbol}"; return $"{Tolerance} {Symbol}";

View File

@@ -1,6 +1,7 @@
namespace UglyToad.PdfPig.Graphics.Operations.General namespace UglyToad.PdfPig.Graphics.Operations.General
{ {
using System; using System;
using System.IO;
using Content; using Content;
using Core; using Core;
@@ -28,6 +29,11 @@
operationContext.GetCurrentState().CapStyle = Cap; operationContext.GetCurrentState().CapStyle = Cap;
} }
public void Write(Stream stream)
{
throw new NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{(int) Cap} {Symbol}"; return $"{(int) Cap} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.General namespace UglyToad.PdfPig.Graphics.Operations.General
{ {
using System.IO;
using Content; using Content;
using Core; using Core;
@@ -21,6 +22,11 @@
operationContext.GetCurrentState().LineDashPattern = Pattern; operationContext.GetCurrentState().LineDashPattern = Pattern;
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Pattern.Array} {Pattern.Phase} {Symbol}"; return $"{Pattern.Array} {Pattern.Phase} {Symbol}";

View File

@@ -1,6 +1,7 @@
namespace UglyToad.PdfPig.Graphics.Operations.General namespace UglyToad.PdfPig.Graphics.Operations.General
{ {
using System; using System;
using System.IO;
using Content; using Content;
using Core; using Core;
@@ -28,6 +29,11 @@
operationContext.GetCurrentState().JoinStyle = Join; operationContext.GetCurrentState().JoinStyle = Join;
} }
public void Write(Stream stream)
{
throw new NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{(int)Join} {Symbol}"; return $"{(int)Join} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.General namespace UglyToad.PdfPig.Graphics.Operations.General
{ {
using System.IO;
using Content; using Content;
internal class SetLineWidth : IGraphicsStateOperation internal class SetLineWidth : IGraphicsStateOperation
@@ -22,6 +23,11 @@
currentState.LineWidth = Width; currentState.LineWidth = Width;
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Width} {Symbol}"; return $"{Width} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.General namespace UglyToad.PdfPig.Graphics.Operations.General
{ {
using System.IO;
using Content; using Content;
internal class SetMiterLimit : IGraphicsStateOperation internal class SetMiterLimit : IGraphicsStateOperation
@@ -22,6 +23,11 @@
currentState.MiterLimit = Limit; currentState.MiterLimit = Limit;
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Limit} {Symbol}"; return $"{Limit} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal interface IGraphicsStateOperation internal interface IGraphicsStateOperation
@@ -7,5 +8,7 @@
string Operator { get; } string Operator { get; }
void Run(IOperationContext operationContext, IResourceStore resourceStore); void Run(IOperationContext operationContext, IResourceStore resourceStore);
void Write(Stream stream);
} }
} }

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
using Tokens; using Tokens;
@@ -23,6 +24,11 @@
operationContext.ApplyXObject(xobject); operationContext.ApplyXObject(xobject);
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Name} {Symbol}"; return $"{Name} {Symbol}";

View File

@@ -0,0 +1,32 @@
namespace UglyToad.PdfPig.Graphics.Operations
{
using System.IO;
using Util;
internal static class OperationWriteHelper
{
private static readonly byte WhiteSpace = OtherEncodings.StringAsLatin1Bytes(" ")[0];
private static readonly byte NewLine = OtherEncodings.StringAsLatin1Bytes("\n")[0];
public static void WriteText(this Stream stream, string text)
{
var bytes = OtherEncodings.StringAsLatin1Bytes(text);
stream.Write(bytes, 0, bytes.Length);
}
public static void WriteWhiteSpace(this Stream stream)
{
stream.WriteByte(WhiteSpace);
}
public static void WriteNewLine(this Stream stream)
{
stream.WriteByte(NewLine);
}
public static void WriteDecimal(this Stream stream, decimal value)
{
stream.WriteText(value.ToString("G"));
}
}
}

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
{ {
using System.IO;
using Content; using Content;
using Geometry; using Geometry;
@@ -26,6 +27,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{ControlPoint1.X} {ControlPoint1.Y} {ControlPoint2.X} {ControlPoint2.Y} {End.X} {End.Y} {Symbol}"; return $"{ControlPoint1.X} {ControlPoint1.Y} {ControlPoint2.X} {ControlPoint2.Y} {End.X} {End.Y} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
{ {
using System.IO;
using Content; using Content;
using Geometry; using Geometry;
@@ -23,6 +24,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{ControlPoint1.X} {ControlPoint1.Y} {End.X} {End.Y} {Symbol}"; return $"{ControlPoint1.X} {ControlPoint1.Y} {End.X} {End.Y} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
{ {
using System.IO;
using Content; using Content;
using Geometry; using Geometry;
@@ -27,6 +28,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{LowerLeft.X} {LowerLeft.Y} {Width} {Height} {Symbol}"; return $"{LowerLeft.X} {LowerLeft.Y} {Width} {Height} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
{ {
using System.IO;
using Content; using Content;
using Geometry; using Geometry;
@@ -23,6 +24,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{ControlPoint2.X} {ControlPoint2.Y} {End.X} {End.Y} {Symbol}"; return $"{ControlPoint2.X} {ControlPoint2.Y} {End.X} {End.Y} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
{ {
using System.IO;
using Content; using Content;
using Geometry; using Geometry;
@@ -20,6 +21,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{End.X} {End.Y} {Symbol}"; return $"{End.X} {End.Y} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
{ {
using System.IO;
using Content; using Content;
using Geometry; using Geometry;
@@ -20,6 +21,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Point.X} {Point.Y} {Symbol}"; return $"{Point.X} {Point.Y} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
{ {
using System.IO;
using Content; using Content;
internal class CloseSubpath : IGraphicsStateOperation internal class CloseSubpath : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class SetNonStrokeColorDeviceCmyk : IGraphicsStateOperation internal class SetNonStrokeColorDeviceCmyk : IGraphicsStateOperation
@@ -28,6 +29,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{C} {M} {Y} {K} {Symbol}"; return $"{C} {M} {Y} {K} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class SetNonStrokeColorDeviceGray : IGraphicsStateOperation internal class SetNonStrokeColorDeviceGray : IGraphicsStateOperation
@@ -19,6 +20,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Gray} {Symbol}"; return $"{Gray} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class SetNonStrokeColorDeviceRgb : IGraphicsStateOperation internal class SetNonStrokeColorDeviceRgb : IGraphicsStateOperation
@@ -25,6 +26,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{R} {G} {B} {Symbol}"; return $"{R} {G} {B} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class SetStrokeColorDeviceCmyk : IGraphicsStateOperation internal class SetStrokeColorDeviceCmyk : IGraphicsStateOperation
@@ -28,6 +29,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{C} {M} {Y} {K} {Symbol}"; return $"{C} {M} {Y} {K} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class SetStrokeColorDeviceGray : IGraphicsStateOperation internal class SetStrokeColorDeviceGray : IGraphicsStateOperation
@@ -19,6 +20,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Gray} {Symbol}"; return $"{Gray} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class SetStrokeColorDeviceRgb : IGraphicsStateOperation internal class SetStrokeColorDeviceRgb : IGraphicsStateOperation
@@ -25,6 +26,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{R} {G} {B} {Symbol}"; return $"{R} {G} {B} {Symbol}";

View File

@@ -1,6 +1,7 @@
namespace UglyToad.PdfPig.Graphics.Operations.SpecialGraphicsState namespace UglyToad.PdfPig.Graphics.Operations.SpecialGraphicsState
{ {
using System; using System;
using System.IO;
using Content; using Content;
using PdfPig.Core; using PdfPig.Core;
@@ -37,6 +38,24 @@
operationContext.GetCurrentState().CurrentTransformationMatrix = newCtm; operationContext.GetCurrentState().CurrentTransformationMatrix = newCtm;
} }
public void Write(Stream stream)
{
stream.WriteDecimal(Value[0]);
stream.WriteWhiteSpace();
stream.WriteDecimal(Value[1]);
stream.WriteWhiteSpace();
stream.WriteDecimal(Value[2]);
stream.WriteWhiteSpace();
stream.WriteDecimal(Value[3]);
stream.WriteWhiteSpace();
stream.WriteDecimal(Value[4]);
stream.WriteWhiteSpace();
stream.WriteDecimal(Value[5]);
stream.WriteWhiteSpace();
stream.WriteText(Symbol);
stream.WriteNewLine();
}
public override string ToString() public override string ToString()
{ {
return $"{Value[0]} {Value[1]} {Value[2]} {Value[3]} {Value[4]} {Value[5]} {Symbol}"; return $"{Value[0]} {Value[1]} {Value[2]} {Value[3]} {Value[4]} {Value[5]} {Symbol}";

View File

@@ -1,6 +1,7 @@
namespace UglyToad.PdfPig.Graphics.Operations.SpecialGraphicsState namespace UglyToad.PdfPig.Graphics.Operations.SpecialGraphicsState
{ {
using System; using System;
using System.IO;
using Content; using Content;
internal class Pop : IGraphicsStateOperation internal class Pop : IGraphicsStateOperation
@@ -27,6 +28,11 @@
} }
} }
public void Write(Stream stream)
{
throw new NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.SpecialGraphicsState namespace UglyToad.PdfPig.Graphics.Operations.SpecialGraphicsState
{ {
using System.IO;
using Content; using Content;
internal class Push : IGraphicsStateOperation internal class Push : IGraphicsStateOperation
@@ -22,5 +23,10 @@
{ {
context.PushState(); context.PushState();
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
} }
} }

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations namespace UglyToad.PdfPig.Graphics.Operations
{ {
using System.IO;
using Content; using Content;
internal class StrokePath : IGraphicsStateOperation internal class StrokePath : IGraphicsStateOperation
@@ -18,6 +19,11 @@
{ {
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextObjects namespace UglyToad.PdfPig.Graphics.Operations.TextObjects
{ {
using System.IO;
using Content; using Content;
using PdfPig.Core; using PdfPig.Core;
@@ -20,6 +21,12 @@
operationContext.TextMatrices.TextLineMatrix = TransformationMatrix.Identity; operationContext.TextMatrices.TextLineMatrix = TransformationMatrix.Identity;
} }
public void Write(Stream stream)
{
stream.WriteText(Symbol);
stream.WriteNewLine();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextObjects namespace UglyToad.PdfPig.Graphics.Operations.TextObjects
{ {
using System.IO;
using Content; using Content;
using PdfPig.Core; using PdfPig.Core;
@@ -20,6 +21,12 @@
operationContext.TextMatrices.TextLineMatrix = TransformationMatrix.Identity; operationContext.TextMatrices.TextLineMatrix = TransformationMatrix.Identity;
} }
public void Write(Stream stream)
{
stream.WriteText(Symbol);
stream.WriteNewLine();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextPositioning namespace UglyToad.PdfPig.Graphics.Operations.TextPositioning
{ {
using System.IO;
using Content; using Content;
/// <summary> /// <summary>
@@ -27,6 +28,11 @@
tdOperation.Run(operationContext, resourceStore); tdOperation.Run(operationContext, resourceStore);
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return Symbol; return Symbol;

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextPositioning namespace UglyToad.PdfPig.Graphics.Operations.TextPositioning
{ {
using System.IO;
using Content; using Content;
using PdfPig.Core; using PdfPig.Core;
@@ -40,6 +41,16 @@
operationContext.TextMatrices.TextMatrix = transformed; operationContext.TextMatrices.TextMatrix = transformed;
} }
public void Write(Stream stream)
{
stream.WriteDecimal(Tx);
stream.WriteWhiteSpace();
stream.WriteDecimal(Ty);
stream.WriteWhiteSpace();
stream.WriteText(Symbol);
stream.WriteNewLine();
}
public override string ToString() public override string ToString()
{ {
return $"{Tx} {Ty} {Symbol}"; return $"{Tx} {Ty} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextPositioning namespace UglyToad.PdfPig.Graphics.Operations.TextPositioning
{ {
using System.IO;
using Content; using Content;
using TextState; using TextState;
@@ -30,6 +31,11 @@
tdOperation.Run(operationContext, resourceStore); tdOperation.Run(operationContext, resourceStore);
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Tx} {Ty} {Symbol}"; return $"{Tx} {Ty} {Symbol}";

View File

@@ -1,6 +1,7 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextPositioning namespace UglyToad.PdfPig.Graphics.Operations.TextPositioning
{ {
using System; using System;
using System.IO;
using Content; using Content;
using PdfPig.Core; using PdfPig.Core;
@@ -30,6 +31,11 @@
operationContext.TextMatrices.TextLineMatrix = newMatrix; operationContext.TextMatrices.TextLineMatrix = newMatrix;
} }
public void Write(Stream stream)
{
throw new NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Value[0]} {Value[1]} {Value[2]} {Value[3]} {Value[4]} {Value[5]} {Symbol}"; return $"{Value[0]} {Value[1]} {Value[2]} {Value[3]} {Value[4]} {Value[5]} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextShowing namespace UglyToad.PdfPig.Graphics.Operations.TextShowing
{ {
using System.IO;
using Content; using Content;
using TextPositioning; using TextPositioning;
using Util.JetBrains.Annotations; using Util.JetBrains.Annotations;
@@ -36,6 +37,11 @@
showText.Run(operationContext, resourceStore); showText.Run(operationContext, resourceStore);
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Text} {Symbol}"; return $"{Text} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextShowing namespace UglyToad.PdfPig.Graphics.Operations.TextShowing
{ {
using System.IO;
using Content; using Content;
using TextPositioning; using TextPositioning;
using TextState; using TextState;
@@ -48,6 +49,11 @@
showText.Run(operationContext, resourceStore); showText.Run(operationContext, resourceStore);
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{WordSpacing} {CharacterSpacing} {Text} {Symbol}"; return $"{WordSpacing} {CharacterSpacing} {Text} {Symbol}";

View File

@@ -1,5 +1,7 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextShowing namespace UglyToad.PdfPig.Graphics.Operations.TextShowing
{ {
using System;
using System.IO;
using Content; using Content;
using IO; using IO;
using Util; using Util;
@@ -50,6 +52,19 @@
operationContext.ShowText(input); operationContext.ShowText(input);
} }
public void Write(Stream stream)
{
if (Text == null && Bytes != null)
{
throw new NotImplementedException("Support for writing hex not done yet.");
}
stream.WriteText($"({Text})");
stream.WriteWhiteSpace();
stream.WriteText(Symbol);
stream.WriteNewLine();
}
public override string ToString() public override string ToString()
{ {
return $"{Text} {Symbol}"; return $"{Text} {Symbol}";

View File

@@ -2,6 +2,7 @@
{ {
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Content; using Content;
using Tokens; using Tokens;
@@ -36,5 +37,10 @@
{ {
operationContext.ShowPositionedText(Array); operationContext.ShowPositionedText(Array);
} }
public void Write(Stream stream)
{
throw new NotImplementedException();
}
} }
} }

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextState namespace UglyToad.PdfPig.Graphics.Operations.TextState
{ {
using System.IO;
using Content; using Content;
internal class SetCharacterSpacing : IGraphicsStateOperation internal class SetCharacterSpacing : IGraphicsStateOperation
@@ -22,6 +23,11 @@
currentState.FontState.CharacterSpacing = Spacing; currentState.FontState.CharacterSpacing = Spacing;
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Spacing} {Symbol}"; return $"{Spacing} {Symbol}";

View File

@@ -1,6 +1,7 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextState namespace UglyToad.PdfPig.Graphics.Operations.TextState
{ {
using System; using System;
using System.IO;
using Content; using Content;
using Tokens; using Tokens;
using Util.JetBrains.Annotations; using Util.JetBrains.Annotations;
@@ -37,6 +38,16 @@
currentState.FontState.FontName = Font; currentState.FontState.FontName = Font;
} }
public void Write(Stream stream)
{
stream.WriteText(Font.ToString());
stream.WriteWhiteSpace();
stream.WriteDecimal(Size);
stream.WriteWhiteSpace();
stream.WriteText(Symbol);
stream.WriteNewLine();
}
public override string ToString() public override string ToString()
{ {
return $"{Font} {Size} {Symbol}"; return $"{Font} {Size} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextState namespace UglyToad.PdfPig.Graphics.Operations.TextState
{ {
using System.IO;
using Content; using Content;
internal class SetHorizontalScaling : IGraphicsStateOperation internal class SetHorizontalScaling : IGraphicsStateOperation
@@ -22,6 +23,11 @@
currentState.FontState.HorizontalScaling = Scale; currentState.FontState.HorizontalScaling = Scale;
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Scale} {Symbol}"; return $"{Scale} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextState namespace UglyToad.PdfPig.Graphics.Operations.TextState
{ {
using System.IO;
using Content; using Content;
internal class SetTextLeading : IGraphicsStateOperation internal class SetTextLeading : IGraphicsStateOperation
@@ -22,6 +23,11 @@
currentState.FontState.Leading = Leading; currentState.FontState.Leading = Leading;
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Leading} {Symbol}"; return $"{Leading} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextState namespace UglyToad.PdfPig.Graphics.Operations.TextState
{ {
using System.IO;
using Content; using Content;
using Core; using Core;
@@ -23,6 +24,11 @@
currentState.FontState.RenderingMode = Mode; currentState.FontState.RenderingMode = Mode;
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Mode} {Symbol}"; return $"{Mode} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextState namespace UglyToad.PdfPig.Graphics.Operations.TextState
{ {
using System.IO;
using Content; using Content;
internal class SetTextRise : IGraphicsStateOperation internal class SetTextRise : IGraphicsStateOperation
@@ -22,6 +23,11 @@
currentState.FontState.Rise = Rise; currentState.FontState.Rise = Rise;
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Rise} {Symbol}"; return $"{Rise} {Symbol}";

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Graphics.Operations.TextState namespace UglyToad.PdfPig.Graphics.Operations.TextState
{ {
using System.IO;
using Content; using Content;
internal class SetWordSpacing : IGraphicsStateOperation internal class SetWordSpacing : IGraphicsStateOperation
@@ -22,6 +23,11 @@
currentState.FontState.WordSpacing = Spacing; currentState.FontState.WordSpacing = Spacing;
} }
public void Write(Stream stream)
{
throw new System.NotImplementedException();
}
public override string ToString() public override string ToString()
{ {
return $"{Spacing} {Symbol}"; return $"{Spacing} {Symbol}";

View File

@@ -0,0 +1,15 @@
namespace UglyToad.PdfPig.Writer
{
using System.Collections.Generic;
using Geometry;
using Tokens;
internal interface IWritingFont
{
bool HasWidths { get; }
bool TryGetBoundingBox(char character, out PdfRectangle boundingBox);
IReadOnlyDictionary<IToken, IToken> GetDictionary(NameToken fontKeyName);
}
}

View File

@@ -5,12 +5,15 @@
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Content; using Content;
using Fonts;
using Fonts.TrueType; using Fonts.TrueType;
using Fonts.TrueType.Parser; using Fonts.TrueType.Parser;
using Geometry; using Geometry;
using Graphics.Operations;
using IO; using IO;
using Tokens; using Tokens;
using Util; using Util;
using Util.JetBrains.Annotations;
internal class PdfDocumentBuilder internal class PdfDocumentBuilder
{ {
@@ -21,7 +24,7 @@
private readonly Dictionary<Guid, FontStored> fonts = new Dictionary<Guid, FontStored>(); private readonly Dictionary<Guid, FontStored> fonts = new Dictionary<Guid, FontStored>();
public IReadOnlyDictionary<int, PdfPageBuilder> Pages => pages; public IReadOnlyDictionary<int, PdfPageBuilder> Pages => pages;
public IReadOnlyDictionary<Guid, TrueTypeFontProgram> Fonts => fonts.ToDictionary(x => x.Key, x => x.Value.FontProgram); public IReadOnlyDictionary<Guid, IWritingFont> Fonts => fonts.ToDictionary(x => x.Key, x => x.Value.FontProgram);
public AddedFont AddTrueTypeFont(IReadOnlyList<byte> fontFileBytes) public AddedFont AddTrueTypeFont(IReadOnlyList<byte> fontFileBytes)
{ {
@@ -31,7 +34,7 @@
var id = Guid.NewGuid(); var id = Guid.NewGuid();
var i = fonts.Count; var i = fonts.Count;
var added = new AddedFont(id, NameToken.Create($"F{i}")); var added = new AddedFont(id, NameToken.Create($"F{i}"));
fonts[id] = new FontStored(added, font); fonts[id] = new FontStored(added, new TrueTypeWritingFont(font));
return added; return added;
} }
@@ -41,6 +44,16 @@
} }
} }
public AddedFont AddStandard14Font(Standard14Font type)
{
var id = Guid.NewGuid();
var name = NameToken.Create($"F{fonts.Count}");
var added = new AddedFont(id, name);
fonts[id] = new FontStored(added, new Standard14WritingFont(Standard14.GetAdobeFontMetrics(type)));
return added;
}
public PdfPageBuilder AddPage(PageSize size, bool isPortrait = true) public PdfPageBuilder AddPage(PageSize size, bool isPortrait = true)
{ {
if (!size.TryGetPdfRectangle(out var rectangle)) if (!size.TryGetPdfRectangle(out var rectangle))
@@ -97,22 +110,12 @@
// Body // Body
foreach (var font in fonts) foreach (var font in fonts)
{ {
var widths = new ArrayToken(new[] { new NumericToken(0), new NumericToken(255) }); var fontDictionary = font.Value.FontProgram.GetDictionary(font.Value.FontKey.Name);
var widthsObj = WriteObject(widths, memory, objectLocations, ref number);
// TODO // TODO
// var descriptorRef = new IndirectReference(number++, 0); // var descriptorRef = new IndirectReference(number++, 0);
var dictionary = new DictionaryToken(new Dictionary<IToken, IToken> var dictionary = new DictionaryToken(fontDictionary);
{
{ NameToken.Type, NameToken.Font },
{ NameToken.Subtype, NameToken.TrueType },
{ NameToken.FirstChar, new NumericToken(0) },
{ NameToken.LastChar, new NumericToken(255) },
{ NameToken.Encoding, NameToken.WinAnsiEncoding },
{ NameToken.Widths, widthsObj },
//{ NameToken.FontDesc, new IndirectReferenceToken(descriptorRef) }
});
var fontObj = WriteObject(dictionary, memory, objectLocations, ref number); var fontObj = WriteObject(dictionary, memory, objectLocations, ref number);
fontsWritten.Add(font.Key, fontObj); fontsWritten.Add(font.Key, fontObj);
@@ -133,22 +136,37 @@
resources.Add(NameToken.Font, new IndirectReferenceToken(fontsDictionaryRef.Number)); resources.Add(NameToken.Font, new IndirectReferenceToken(fontsDictionaryRef.Number));
} }
var page = new DictionaryToken(new Dictionary<IToken, IToken> var pageReferences = new List<IndirectReferenceToken>();
foreach (var page in pages)
{ {
{ NameToken.Type, NameToken.Page }, var pageDictionary = new Dictionary<IToken, IToken>
{ {
NameToken.Resources, {NameToken.Type, NameToken.Page},
new DictionaryToken(resources) {
}, NameToken.Resources,
{ NameToken.MediaBox, RectangleToArray(pages[1].PageSize) } new DictionaryToken(resources)
}); },
{NameToken.MediaBox, RectangleToArray(page.Value.PageSize)}
};
var pageRef = WriteObject(page, memory, objectLocations, ref number); if (page.Value.Operations.Count > 0)
{
var contentStream = WriteContentStream(page.Value.Operations);
var contentStreamObj = WriteObject(contentStream, memory, objectLocations, ref number);
pageDictionary[NameToken.Contents] = new IndirectReferenceToken(contentStreamObj.Number);
}
var pageRef = WriteObject(new DictionaryToken(pageDictionary), memory, objectLocations, ref number);
pageReferences.Add(new IndirectReferenceToken(pageRef.Number));
}
var pagesDictionary = new DictionaryToken(new Dictionary<IToken, IToken> var pagesDictionary = new DictionaryToken(new Dictionary<IToken, IToken>
{ {
{ NameToken.Type, NameToken.Pages }, { NameToken.Type, NameToken.Pages },
{ NameToken.Kids, new ArrayToken(new [] { new IndirectReferenceToken(pageRef.Number) }) }, { NameToken.Kids, new ArrayToken(pageReferences) },
{ NameToken.Count, new NumericToken(1) } { NameToken.Count, new NumericToken(1) }
}); });
@@ -168,6 +186,28 @@
} }
} }
private static StreamToken WriteContentStream(IReadOnlyList<IGraphicsStateOperation> content)
{
using (var memoryStream = new MemoryStream())
{
foreach (var operation in content)
{
operation.Write(memoryStream);
}
var bytes = memoryStream.ToArray();
var streamDictionary = new Dictionary<IToken, IToken>
{
{ NameToken.Length, new NumericToken(bytes.Length) }
};
var stream = new StreamToken(new DictionaryToken(streamDictionary), bytes);
return stream;
}
}
private static ArrayToken RectangleToArray(PdfRectangle rectangle) private static ArrayToken RectangleToArray(PdfRectangle rectangle)
{ {
return new ArrayToken(new[] return new ArrayToken(new[]
@@ -201,14 +241,16 @@
internal class FontStored internal class FontStored
{ {
[NotNull]
public AddedFont FontKey { get; } public AddedFont FontKey { get; }
public TrueTypeFontProgram FontProgram { get; } [NotNull]
public IWritingFont FontProgram { get; }
public FontStored(AddedFont fontKey, TrueTypeFontProgram fontProgram) public FontStored(AddedFont fontKey, IWritingFont fontProgram)
{ {
FontKey = fontKey; FontKey = fontKey ?? throw new ArgumentNullException(nameof(fontKey));
FontProgram = fontProgram; FontProgram = fontProgram ?? throw new ArgumentNullException(nameof(fontProgram));
} }
} }
@@ -225,5 +267,4 @@
} }
} }
} }
} }

View File

@@ -8,6 +8,7 @@
using Graphics.Operations; using Graphics.Operations;
using Graphics.Operations.SpecialGraphicsState; using Graphics.Operations.SpecialGraphicsState;
using Graphics.Operations.TextObjects; using Graphics.Operations.TextObjects;
using Graphics.Operations.TextPositioning;
using Graphics.Operations.TextShowing; using Graphics.Operations.TextShowing;
using Graphics.Operations.TextState; using Graphics.Operations.TextState;
@@ -59,24 +60,18 @@
try try
{ {
var ctm = TransformationMatrix.FromValues(position.X, 0, position.Y, 0, 0, 0); var realWidth = widthRect.Width;
var realWidth = ctm.Transform(widthRect).Width;
if (realWidth + position.X > PageSize.Width) if (realWidth + position.X > PageSize.Width)
{ {
throw new InvalidOperationException("Text would exceed the bounds."); throw new InvalidOperationException("Text would exceed the bounds.");
} }
operations.Add(new ModifyCurrentTransformationMatrix(new[]
{
position.X, 0, position.Y, 0, 0, 0
}));
var beginText = BeginText.Value; var beginText = BeginText.Value;
operations.Add(beginText); operations.Add(beginText);
operations.Add(new SetFontAndSize(font.Name, fontSize)); operations.Add(new SetFontAndSize(font.Name, fontSize));
operations.Add(new MoveToNextLineWithOffset(position.X, position.Y));
operations.Add(new ShowText(text)); operations.Add(new ShowText(text));
operations.Add(EndText.Value); operations.Add(EndText.Value);
@@ -90,7 +85,7 @@
return this; return this;
} }
private static decimal CalculateGlyphSpaceTextWidth(string text, TrueTypeFontProgram font) private static decimal CalculateGlyphSpaceTextWidth(string text, IWritingFont font)
{ {
var width = 0m; var width = 0m;
for (var i = 0; i < text.Length; i++) for (var i = 0; i < text.Length; i++)

View File

@@ -0,0 +1,47 @@
namespace UglyToad.PdfPig.Writer
{
using System.Collections.Generic;
using Fonts;
using Fonts.Encodings;
using Geometry;
using Tokens;
internal class Standard14WritingFont : IWritingFont
{
private readonly FontMetrics metrics;
public bool HasWidths { get; } = false;
public Standard14WritingFont(FontMetrics metrics)
{
this.metrics = metrics;
}
public bool TryGetBoundingBox(char character, out PdfRectangle boundingBox)
{
var encoding = StandardEncoding.Instance;
boundingBox = default(PdfRectangle);
if (!metrics.CharacterMetrics.TryGetValue(encoding.GetName(character), out var characterMetric))
{
return false;
}
boundingBox = new PdfRectangle(characterMetric.BoundingBox.Left, characterMetric.BoundingBox.Bottom,
characterMetric.BoundingBox.Left + characterMetric.WidthX, characterMetric.BoundingBox.Top);
return true;
}
public IReadOnlyDictionary<IToken, IToken> GetDictionary(NameToken fontKeyName)
{
return new Dictionary<IToken, IToken>
{
{ NameToken.Type, NameToken.Font },
{ NameToken.Subtype, NameToken.Type1 },
{ NameToken.BaseFont, NameToken.Create(metrics.FontName) },
{ NameToken.Encoding, NameToken.MacRomanEncoding },
{ NameToken.Name, fontKeyName }
};
}
}
}

View File

@@ -36,6 +36,9 @@
private static readonly byte[] StartXref = OtherEncodings.StringAsLatin1Bytes("startxref"); private static readonly byte[] StartXref = OtherEncodings.StringAsLatin1Bytes("startxref");
private static readonly byte[] StreamStart = OtherEncodings.StringAsLatin1Bytes("stream");
private static readonly byte[] StreamEnd = OtherEncodings.StringAsLatin1Bytes("endstream");
private static readonly byte StringStart = GetByte("("); private static readonly byte StringStart = GetByte("(");
private static readonly byte StringEnd = GetByte(")"); private static readonly byte StringEnd = GetByte(")");
@@ -81,8 +84,9 @@
case ObjectToken objectToken: case ObjectToken objectToken:
WriteObject(objectToken, outputStream); WriteObject(objectToken, outputStream);
break; break;
case StreamToken _: case StreamToken streamToken:
throw new NotImplementedException(); WriteStream(streamToken, outputStream);
break;
case StringToken stringToken: case StringToken stringToken:
WriteString(stringToken, outputStream); WriteString(stringToken, outputStream);
break; break;
@@ -268,6 +272,17 @@
WriteLineBreak(outputStream); WriteLineBreak(outputStream);
} }
private static void WriteStream(StreamToken streamToken, Stream outputStream)
{
WriteDictionary(streamToken.StreamDictionary, outputStream);
WriteLineBreak(outputStream);
outputStream.Write(StreamStart, 0, StreamStart.Length);
WriteLineBreak(outputStream);
outputStream.Write(streamToken.Data.ToArray(), 0, streamToken.Data.Count);
WriteLineBreak(outputStream);
outputStream.Write(StreamEnd, 0, StreamEnd.Length);
}
private static void WriteString(StringToken stringToken, Stream outputStream) private static void WriteString(StringToken stringToken, Stream outputStream)
{ {
outputStream.WriteByte(StringStart); outputStream.WriteByte(StringStart);

View File

@@ -0,0 +1,33 @@
namespace UglyToad.PdfPig.Writer
{
using System.Collections.Generic;
using Fonts.TrueType;
using Geometry;
using Tokens;
internal class TrueTypeWritingFont : IWritingFont
{
private readonly TrueTypeFontProgram font;
public TrueTypeWritingFont(TrueTypeFontProgram font)
{
this.font = font;
}
public bool HasWidths { get; } = true;
public bool TryGetBoundingBox(char character, out PdfRectangle boundingBox)
{
return font.TryGetBoundingBox(character, out boundingBox);
}
public IReadOnlyDictionary<IToken, IToken> GetDictionary(NameToken fontKeyName)
{
return new Dictionary<IToken, IToken>
{
{ NameToken.Type, NameToken.Font },
{ NameToken.Subtype, NameToken.TrueType }
};
}
}
}