move annotations to experimental access, support changing color state for document creation and update readme

This commit is contained in:
Eliot Jones
2018-12-30 14:12:04 +00:00
parent 55a0e6b646
commit 4d5518a599
14 changed files with 125 additions and 184 deletions

View File

@@ -15,7 +15,6 @@
public class Page
{
private readonly DictionaryToken dictionary;
private readonly AnnotationProvider annotationProvider;
/// <summary>
/// The page number (starting at 1).
@@ -68,7 +67,6 @@
}
this.dictionary = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
this.annotationProvider = annotationProvider ?? throw new ArgumentNullException(nameof(annotationProvider));
Number = number;
MediaBox = mediaBox;
@@ -80,7 +78,7 @@
Height = mediaBox.Bounds.Height;
Size = mediaBox.Bounds.GetPageSize();
ExperimentalAccess = new Experimental(this);
ExperimentalAccess = new Experimental(this, annotationProvider);
}
private static string GetText(PageContent content)
@@ -109,21 +107,18 @@
return (wordExtractor ?? DefaultWordExtractor.Instance).GetWords(Letters);
}
internal IEnumerable<Annotation> GetAnnotations()
{
return annotationProvider.GetAnnotations();
}
/// <summary>
/// Provides access to useful members which will change in future releases.
/// </summary>
public class Experimental
{
private readonly Page page;
private readonly AnnotationProvider annotationProvider;
internal Experimental(Page page)
internal Experimental(Page page, AnnotationProvider annotationProvider)
{
this.page = page;
this.annotationProvider = annotationProvider;
}
/// <summary>
@@ -135,6 +130,15 @@
{
return page.Content.GetImages();
}
/// <summary>
/// Get the annotation objects from the page.
/// </summary>
/// <returns>The lazily evaluated set of annotations on this page.</returns>
public IEnumerable<Annotation> GetAnnotations()
{
return annotationProvider.GetAnnotations();
}
}
}
}

View File

@@ -1,160 +0,0 @@
namespace UglyToad.PdfPig.Cos
{
using System.Collections.Generic;
using System.IO;
using System.Text;
/// <summary>
/// The "PDFDocEncoding" encoding. Note that this is *not* a Type 1 font encoding, it is used only within PDF "text strings".
/// </summary>
internal static class PdfDocEncoding
{
private const char ReplacementCharacter = '\uFFFD';
private static readonly int[] CodeToUni;
private static readonly IReadOnlyDictionary<char, int> UnicodeToCode;
static PdfDocEncoding()
{
var temporaryMap = new Dictionary<char, int>(256);
CodeToUni = new int[256];
// initialize with basically ISO-8859-1
for (int i = 0; i < 256; i++)
{
// skip entries not in Unicode column
if (i > 0x17 && i < 0x20)
{
continue;
}
if (i > 0x7E && i < 0xA1)
{
continue;
}
if (i == 0xAD)
{
continue;
}
Set(i, (char)i, temporaryMap);
}
// then do all deviations (based on the table in ISO 32000-1:2008)
// block 1
Set(0x18, '\u02D8', temporaryMap); // BREVE
Set(0x19, '\u02C7', temporaryMap); // CARON
Set(0x1A, '\u02C6', temporaryMap); // MODIFIER LETTER CIRCUMFLEX ACCENT
Set(0x1B, '\u02D9', temporaryMap); // DOT ABOVE
Set(0x1C, '\u02DD', temporaryMap); // DOUBLE ACUTE ACCENT
Set(0x1D, '\u02DB', temporaryMap); // OGONEK
Set(0x1E, '\u02DA', temporaryMap); // RING ABOVE
Set(0x1F, '\u02DC', temporaryMap); // SMALL TILDE
// block 2
Set(0x7F, ReplacementCharacter, temporaryMap); // undefined
Set(0x80, '\u2022', temporaryMap); // BULLET
Set(0x81, '\u2020', temporaryMap); // DAGGER
Set(0x82, '\u2021', temporaryMap); // DOUBLE DAGGER
Set(0x83, '\u2026', temporaryMap); // HORIZONTAL ELLIPSIS
Set(0x84, '\u2014', temporaryMap); // EM DASH
Set(0x85, '\u2013', temporaryMap); // EN DASH
Set(0x86, '\u0192', temporaryMap); // LATIN SMALL LETTER SCRIPT F
Set(0x87, '\u2044', temporaryMap); // FRACTION SLASH (solidus)
Set(0x88, '\u2039', temporaryMap); // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
Set(0x89, '\u203A', temporaryMap); // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
Set(0x8A, '\u2212', temporaryMap); // MINUS SIGN
Set(0x8B, '\u2030', temporaryMap); // PER MILLE SIGN
Set(0x8C, '\u201E', temporaryMap); // DOUBLE LOW-9 QUOTATION MARK (quotedblbase)
Set(0x8D, '\u201C', temporaryMap); // LEFT DOUBLE QUOTATION MARK (quotedblleft)
Set(0x8E, '\u201D', temporaryMap); // RIGHT DOUBLE QUOTATION MARK (quotedblright)
Set(0x8F, '\u2018', temporaryMap); // LEFT SINGLE QUOTATION MARK (quoteleft)
Set(0x90, '\u2019', temporaryMap); // RIGHT SINGLE QUOTATION MARK (quoteright)
Set(0x91, '\u201A', temporaryMap); // SINGLE LOW-9 QUOTATION MARK (quotesinglbase)
Set(0x92, '\u2122', temporaryMap); // TRADE MARK SIGN
Set(0x93, '\uFB01', temporaryMap); // LATIN SMALL LIGATURE FI
Set(0x94, '\uFB02', temporaryMap); // LATIN SMALL LIGATURE FL
Set(0x95, '\u0141', temporaryMap); // LATIN CAPITAL LETTER L WITH STROKE
Set(0x96, '\u0152', temporaryMap); // LATIN CAPITAL LIGATURE OE
Set(0x97, '\u0160', temporaryMap); // LATIN CAPITAL LETTER S WITH CARON
Set(0x98, '\u0178', temporaryMap); // LATIN CAPITAL LETTER Y WITH DIAERESIS
Set(0x99, '\u017D', temporaryMap); // LATIN CAPITAL LETTER Z WITH CARON
Set(0x9A, '\u0131', temporaryMap); // LATIN SMALL LETTER DOTLESS I
Set(0x9B, '\u0142', temporaryMap); // LATIN SMALL LETTER L WITH STROKE
Set(0x9C, '\u0153', temporaryMap); // LATIN SMALL LIGATURE OE
Set(0x9D, '\u0161', temporaryMap); // LATIN SMALL LETTER S WITH CARON
Set(0x9E, '\u017E', temporaryMap); // LATIN SMALL LETTER Z WITH CARON
Set(0x9F, ReplacementCharacter, temporaryMap); // undefined
Set(0xA0, '\u20AC', temporaryMap); // EURO SIGN
// end of deviations
UnicodeToCode = temporaryMap;
}
private static void Set(int code, char unicode, Dictionary<char, int> unicodeToCode)
{
CodeToUni[code] = unicode;
unicodeToCode[unicode] = code;
}
/**
* Returns the string representation of the given PDFDocEncoded bytes.
*/
public static string ToString(byte[] bytes)
{
if (bytes == null)
{
return null;
}
StringBuilder sb = new StringBuilder();
foreach (var b in bytes)
{
if ((b & 0xff) >= CodeToUni.Length)
{
sb.Append('?');
}
else
{
sb.Append((char)CodeToUni[b & 0xff]);
}
}
return sb.ToString();
}
/// <summary>
/// Returns the given string encoded with PDFDocEncoding.
/// </summary>
public static byte[] GetBytes(string text)
{
using (var memoryStream = new MemoryStream())
using (var write = new StreamWriter(memoryStream))
{
foreach (var c in text)
{
if (!UnicodeToCode.TryGetValue(c, out int value))
{
write.Write(0);
}
else
{
write.Write(value);
}
}
return memoryStream.ToArray();
}
}
/// <summary>
/// Returns true if the given character is available in PDFDocEncoding.
/// </summary>
/// <param name="character">UTF-16 character</param>
public static bool ContainsChar(char character)
{
return UnicodeToCode.ContainsKey(character);
}
}
}

View File

@@ -28,7 +28,14 @@
public void Write(Stream stream)
{
throw new System.NotImplementedException();
stream.WriteDecimal(R);
stream.WriteWhiteSpace();
stream.WriteDecimal(G);
stream.WriteWhiteSpace();
stream.WriteDecimal(B);
stream.WriteWhiteSpace();
stream.WriteText(Symbol);
stream.WriteNewLine();
}
public override string ToString()

View File

@@ -28,7 +28,14 @@
public void Write(Stream stream)
{
throw new System.NotImplementedException();
stream.WriteDecimal(R);
stream.WriteWhiteSpace();
stream.WriteDecimal(G);
stream.WriteWhiteSpace();
stream.WriteDecimal(B);
stream.WriteWhiteSpace();
stream.WriteText(Symbol);
stream.WriteNewLine();
}
public override string ToString()

View File

@@ -4,7 +4,6 @@ namespace UglyToad.PdfPig.Graphics
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Cos;
using Exceptions;
using Operations;
using Operations.TextShowing;

View File

@@ -2,7 +2,6 @@
{
using System;
using System.Collections.Generic;
using Cos;
using CrossReference;
using Exceptions;
using IO;

View File

@@ -2,7 +2,6 @@
{
using System.Collections.Generic;
using System.Linq;
using Cos;
using CrossReference;
using Exceptions;
using Parts.CrossReference;

View File

@@ -1,7 +1,6 @@
namespace UglyToad.PdfPig.Parser.Parts.CrossReference
{
using System.Collections.Generic;
using Cos;
using Exceptions;
using Filters;
using PdfPig.CrossReference;

View File

@@ -8,6 +8,7 @@
using Graphics.Operations;
using Graphics.Operations.General;
using Graphics.Operations.PathConstruction;
using Graphics.Operations.SpecialGraphicsState;
using Graphics.Operations.TextObjects;
using Graphics.Operations.TextPositioning;
using Graphics.Operations.TextShowing;
@@ -84,6 +85,51 @@
}
}
/// <summary>
/// Sets the stroke color for any following operations to the RGB value. Use <see cref="ResetColor"/> to reset.
/// </summary>
/// <param name="r">Red - 0 to 255</param>
/// <param name="g">Green - 0 to 255</param>
/// <param name="b">Blue - 0 to 255</param>
public void SetStrokeColor(byte r, byte g, byte b)
{
operations.Add(Push.Value);
operations.Add(new SetStrokeColorDeviceRgb(RgbToDecimal(r), RgbToDecimal(g), RgbToDecimal(b)));
}
/// <summary>
/// Sets the stroke color with the exact decimal value between 0 and 1 for any following operations to the RGB value. Use <see cref="ResetColor"/> to reset.
/// </summary>
/// <param name="r">Red - 0 to 1</param>
/// <param name="g">Green - 0 to 1</param>
/// <param name="b">Blue - 0 to 1</param>
internal void SetStrokeColorExact(decimal r, decimal g, decimal b)
{
operations.Add(Push.Value);
operations.Add(new SetStrokeColorDeviceRgb(CheckRgbDecimal(r, nameof(r)),
CheckRgbDecimal(g, nameof(g)), CheckRgbDecimal(b, nameof(b))));
}
/// <summary>
/// Sets the fill and text color for any following operations to the RGB value. Use <see cref="ResetColor"/> to reset.
/// </summary>
/// <param name="r">Red - 0 to 255</param>
/// <param name="g">Green - 0 to 255</param>
/// <param name="b">Blue - 0 to 255</param>
public void SetTextAndFillColor(byte r, byte g, byte b)
{
operations.Add(Push.Value);
operations.Add(new SetNonStrokeColorDeviceRgb(RgbToDecimal(r), RgbToDecimal(g), RgbToDecimal(b)));
}
/// <summary>
/// Restores the stroke, text and fill color to default (black).
/// </summary>
public void ResetColor()
{
operations.Add(Pop.Value);
}
/// <summary>
/// Calculates the size and position of each letter in a given string in the provided font without changing the state of the page.
/// </summary>
@@ -221,5 +267,28 @@
return letters;
}
private static decimal RgbToDecimal(byte value)
{
var res = Math.Max(0, value / (decimal)byte.MaxValue);
res = Math.Min(1, res);
return res;
}
private static decimal CheckRgbDecimal(decimal value, string argument)
{
if (value < 0)
{
throw new ArgumentOutOfRangeException(argument, $"Provided decimal for RGB color was less than zero: {value}.");
}
if (value > 1)
{
throw new ArgumentOutOfRangeException(argument, $"Provided decimal for RGB color was greater than one: {value}.");
}
return value;
}
}
}