diff --git a/src/UglyToad.PdfPig/Writer/DataCompresser.cs b/src/UglyToad.PdfPig/Writer/DataCompresser.cs new file mode 100644 index 00000000..7ebd2fb6 --- /dev/null +++ b/src/UglyToad.PdfPig/Writer/DataCompresser.cs @@ -0,0 +1,38 @@ +namespace UglyToad.PdfPig.Writer +{ + using System.Collections.Generic; + using System.IO; + using System.Linq; + using Filters; + using Logging; + using Tokens; + + internal static class DataCompresser + { + public static byte[] CompressBytes(IReadOnlyList bytes) => CompressBytes(bytes.ToArray()); + public static byte[] CompressBytes(byte[] bytes) + { + using (var memoryStream = new MemoryStream(bytes)) + { + var parameters = new DictionaryToken(new Dictionary()); + var flater = new FlateFilter(new DecodeParameterResolver(new NoOpLog()), new PngPredictor(), new NoOpLog()); + var result = flater.Encode(memoryStream, parameters, 0); + return result; + } + } + + public static StreamToken CompressToStream(IReadOnlyList bytes) => CompressToStream(bytes.ToArray()); + public static StreamToken CompressToStream(byte[] bytes) + { + var compressed = CompressBytes(bytes); + var stream = new StreamToken(new DictionaryToken(new Dictionary + { + { NameToken.Length, new NumericToken(compressed.Length) }, + { NameToken.Length1, new NumericToken(bytes.Length) }, + { NameToken.Filter, new ArrayToken(new []{ NameToken.FlateDecode }) } + }), compressed); + + return stream; + } + } +} diff --git a/src/UglyToad.PdfPig/Writer/Fonts/TrueTypeWritingFont.cs b/src/UglyToad.PdfPig/Writer/Fonts/TrueTypeWritingFont.cs index 78782af5..e1ee2cb1 100644 --- a/src/UglyToad.PdfPig/Writer/Fonts/TrueTypeWritingFont.cs +++ b/src/UglyToad.PdfPig/Writer/Fonts/TrueTypeWritingFont.cs @@ -5,9 +5,7 @@ using System.IO; using System.Linq; using Core; - using Filters; using Geometry; - using Logging; using Tokens; using PdfPig.Fonts; using PdfPig.Fonts.Exceptions; @@ -52,17 +50,10 @@ public ObjectToken WriteFont(NameToken fontKeyName, Stream outputStream, BuilderContext context) { - var b = TrueTypeSubsetter.Subset(fontFileBytes.ToArray(), new TrueTypeSubsetEncoding(characterMapping.Keys.ToList())); + var newEncoding = new TrueTypeSubsetEncoding(characterMapping.Keys.ToList()); + var subsetBytes = TrueTypeSubsetter.Subset(fontFileBytes.ToArray(), newEncoding); - // A symbolic font (one which contains characters not in the standard latin set) - - // should contain a MacRoman (1, 0) or Windows Symbolic (3,0) cmap subtable which maps character codes to glyph id. - var bytes = CompressBytes(b); - var embeddedFile = new StreamToken(new DictionaryToken(new Dictionary - { - { NameToken.Length, new NumericToken(bytes.Length) }, - { NameToken.Length1, new NumericToken(b.Length) }, - { NameToken.Filter, new ArrayToken(new []{ NameToken.FlateDecode }) } - }), bytes); + var embeddedFile = DataCompresser.CompressToStream(subsetBytes); var fileRef = context.WriteObject(outputStream, embeddedFile); @@ -82,8 +73,8 @@ { NameToken.Flags, new NumericToken((int)FontDescriptorFlags.Symbolic) }, { NameToken.FontBbox, GetBoundingBox(bbox, scaling) }, { NameToken.ItalicAngle, new NumericToken(postscript.ItalicAngle) }, - { NameToken.Ascent, new NumericToken(hhead.Ascent * scaling) }, - { NameToken.Descent, new NumericToken(hhead.Descent * scaling) }, + { NameToken.Ascent, new NumericToken(Math.Round(hhead.Ascent * scaling, 2)) }, + { NameToken.Descent, new NumericToken(Math.Round(hhead.Descent * scaling, 2)) }, { NameToken.CapHeight, new NumericToken(90) }, { NameToken.StemV, new NumericToken(90) }, { NameToken.FontFile2, new IndirectReferenceToken(fileRef.Number) } @@ -121,13 +112,8 @@ var descriptor = context.WriteObject(outputStream, new DictionaryToken(descriptorDictionary)); var toUnicodeCMap = ToUnicodeCMapBuilder.ConvertToCMapStream(characterMapping); - var compressedToUnicodeCMap = CompressBytes(toUnicodeCMap); - var toUnicode = context.WriteObject(outputStream, new StreamToken(new DictionaryToken(new Dictionary() - { - {NameToken.Length, new NumericToken(compressedToUnicodeCMap.Length)}, - {NameToken.Length1, new NumericToken(toUnicodeCMap.Count)}, - {NameToken.Filter, new ArrayToken(new[] {NameToken.FlateDecode})} - }), compressedToUnicodeCMap)); + var toUnicodeStream = DataCompresser.CompressToStream(toUnicodeCMap); + var toUnicode = context.WriteObject(outputStream, toUnicodeStream); var dictionary = new Dictionary { @@ -174,25 +160,14 @@ } } - private static byte[] CompressBytes(IReadOnlyList bytes) - { - using (var memoryStream = new MemoryStream(bytes.ToArray())) - { - var parameters = new DictionaryToken(new Dictionary()); - var flater = new FlateFilter(new DecodeParameterResolver(new NoOpLog()), new PngPredictor(), new NoOpLog()); - var result = flater.Encode(memoryStream, parameters, 0); - return result; - } - } - private static ArrayToken GetBoundingBox(PdfRectangle boundingBox, decimal scaling) { return new ArrayToken(new[] { - new NumericToken((decimal)boundingBox.Left * scaling), - new NumericToken((decimal)boundingBox.Bottom * scaling), - new NumericToken((decimal)boundingBox.Right * scaling), - new NumericToken((decimal)boundingBox.Top * scaling) + new NumericToken(Math.Round((decimal)boundingBox.Left * scaling, 2)), + new NumericToken(Math.Round((decimal)boundingBox.Bottom * scaling, 2)), + new NumericToken(Math.Round((decimal)boundingBox.Right * scaling, 2)), + new NumericToken(Math.Round((decimal)boundingBox.Top * scaling, 2)) }); } } diff --git a/src/UglyToad.PdfPig/Writer/PdfDocumentBuilder.cs b/src/UglyToad.PdfPig/Writer/PdfDocumentBuilder.cs index e8d93d77..75e4838a 100644 --- a/src/UglyToad.PdfPig/Writer/PdfDocumentBuilder.cs +++ b/src/UglyToad.PdfPig/Writer/PdfDocumentBuilder.cs @@ -295,13 +295,8 @@ var bytes = memoryStream.ToArray(); - var streamDictionary = new Dictionary - { - { NameToken.Length, new NumericToken(bytes.Length) } - }; - - var stream = new StreamToken(new DictionaryToken(streamDictionary), bytes); - + var stream = DataCompresser.CompressToStream(bytes); + return stream; } } diff --git a/src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs b/src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs index 3ada37d1..1cd7370b 100644 --- a/src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs +++ b/src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs @@ -228,10 +228,22 @@ operations.Add(BeginText.Value); operations.Add(new SetFontAndSize(font.Name, fontSize)); operations.Add(new MoveToNextLineWithOffset((decimal)position.X, (decimal)position.Y)); + var bytesPerShow = new List(); foreach (var letter in text) { + if (char.IsWhiteSpace(letter)) + { + operations.Add(new ShowText(bytesPerShow.ToArray())); + bytesPerShow.Clear(); + } + var b = fontProgram.GetValueForCharacter(letter); - operations.Add(new ShowText(new [] { b })); + bytesPerShow.Add(b); + } + + if (bytesPerShow.Count > 0) + { + operations.Add(new ShowText(bytesPerShow.ToArray())); } operations.Add(EndText.Value); @@ -294,7 +306,7 @@ private static decimal RgbToDecimal(byte value) { var res = Math.Max(0, value / (decimal)byte.MaxValue); - res = Math.Min(1, res); + res = Math.Round(Math.Min(1, res), 4); return res; }