mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-18 09:57:56 +08:00
Refactor PdfFunctionParser to account for indirect reference tokens
This commit is contained in:
@@ -4,11 +4,16 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UglyToad.PdfPig.Functions;
|
using UglyToad.PdfPig.Functions;
|
||||||
|
using UglyToad.PdfPig.Tests.Tokens;
|
||||||
using UglyToad.PdfPig.Tokens;
|
using UglyToad.PdfPig.Tokens;
|
||||||
|
using UglyToad.PdfPig.Util;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
public class PdfFunctionType0Tests
|
public class PdfFunctionType0Tests
|
||||||
{
|
{
|
||||||
|
private readonly TestPdfTokenScanner testPdfTokenScanner = new TestPdfTokenScanner();
|
||||||
|
private readonly TestFilterProvider testFilterProvider = new TestFilterProvider();
|
||||||
|
|
||||||
private static ArrayToken GetArrayToken(params double[] data)
|
private static ArrayToken GetArrayToken(params double[] data)
|
||||||
{
|
{
|
||||||
return new ArrayToken(data.Select(v => new NumericToken((decimal)v)).ToArray());
|
return new ArrayToken(data.Select(v => new NumericToken((decimal)v)).ToArray());
|
||||||
@@ -33,7 +38,10 @@
|
|||||||
|
|
||||||
StreamToken function = new StreamToken(dictionaryToken, data);
|
StreamToken function = new StreamToken(dictionaryToken, data);
|
||||||
|
|
||||||
var function0 = new PdfFunctionType0(function);
|
var func = PdfFunctionParser.Create(function, testPdfTokenScanner, testFilterProvider);
|
||||||
|
Assert.Equal(FunctionTypes.Sampled, func.FunctionType);
|
||||||
|
var function0 = func as PdfFunctionType0;
|
||||||
|
|
||||||
var result = function0.Eval(new double[] { 0 });
|
var result = function0.Eval(new double[] { 0 });
|
||||||
Assert.Equal(4, result.Length);
|
Assert.Equal(4, result.Length);
|
||||||
result = function0.Eval(new double[] { 0.5 });
|
result = function0.Eval(new double[] { 0.5 });
|
||||||
@@ -61,7 +69,10 @@
|
|||||||
|
|
||||||
StreamToken function = new StreamToken(dictionaryToken, data);
|
StreamToken function = new StreamToken(dictionaryToken, data);
|
||||||
|
|
||||||
var function0 = new PdfFunctionType0(function);
|
var func = PdfFunctionParser.Create(function, testPdfTokenScanner, testFilterProvider);
|
||||||
|
Assert.Equal(FunctionTypes.Sampled, func.FunctionType);
|
||||||
|
var function0 = func as PdfFunctionType0;
|
||||||
|
|
||||||
var result = function0.Eval(new double[] { 0.00 });
|
var result = function0.Eval(new double[] { 0.00 });
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
Assert.Equal(0.0, result[0], 3);
|
Assert.Equal(0.0, result[0], 3);
|
||||||
@@ -100,7 +111,10 @@
|
|||||||
|
|
||||||
StreamToken function = new StreamToken(dictionaryToken, data);
|
StreamToken function = new StreamToken(dictionaryToken, data);
|
||||||
|
|
||||||
var function0 = new PdfFunctionType0(function);
|
var func = PdfFunctionParser.Create(function, testPdfTokenScanner, testFilterProvider);
|
||||||
|
Assert.Equal(FunctionTypes.Sampled, func.FunctionType);
|
||||||
|
var function0 = func as PdfFunctionType0;
|
||||||
|
|
||||||
var result = function0.Eval(new double[] { 0.00 });
|
var result = function0.Eval(new double[] { 0.00 });
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
Assert.Equal(0.0, result[0], 3);
|
Assert.Equal(0.0, result[0], 3);
|
||||||
@@ -139,7 +153,10 @@
|
|||||||
|
|
||||||
StreamToken function = new StreamToken(dictionaryToken, data);
|
StreamToken function = new StreamToken(dictionaryToken, data);
|
||||||
|
|
||||||
var function0 = new PdfFunctionType0(function);
|
var func = PdfFunctionParser.Create(function, testPdfTokenScanner, testFilterProvider);
|
||||||
|
Assert.Equal(FunctionTypes.Sampled, func.FunctionType);
|
||||||
|
var function0 = func as PdfFunctionType0;
|
||||||
|
|
||||||
var result = function0.Eval(new double[] { 0, 0 });
|
var result = function0.Eval(new double[] { 0, 0 });
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(new double[] { 1, 1, 0 }, result); // yellow
|
Assert.Equal(new double[] { 1, 1, 0 }, result); // yellow
|
||||||
@@ -178,7 +195,9 @@
|
|||||||
|
|
||||||
StreamToken function = new StreamToken(dictionaryToken, data);
|
StreamToken function = new StreamToken(dictionaryToken, data);
|
||||||
|
|
||||||
var function0 = new PdfFunctionType0(function);
|
var func = PdfFunctionParser.Create(function, testPdfTokenScanner, testFilterProvider);
|
||||||
|
Assert.Equal(FunctionTypes.Sampled, func.FunctionType);
|
||||||
|
var function0 = func as PdfFunctionType0;
|
||||||
|
|
||||||
var result = function0.Eval(new double[] { 0 });
|
var result = function0.Eval(new double[] { 0 });
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
|
@@ -3,16 +3,18 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UglyToad.PdfPig.Functions;
|
using UglyToad.PdfPig.Functions;
|
||||||
|
using UglyToad.PdfPig.Tests.Tokens;
|
||||||
using UglyToad.PdfPig.Tokens;
|
using UglyToad.PdfPig.Tokens;
|
||||||
|
using UglyToad.PdfPig.Util;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
public class PdfFunctionType2Tests
|
public class PdfFunctionType2Tests
|
||||||
{
|
{
|
||||||
private PdfFunctionType2 CreateFunction(double[] domain, double[] range, double[] c0, double[] c1, double n)
|
private static PdfFunctionType2 CreateFunction(double[] domain, double[] range, double[] c0, double[] c1, double n)
|
||||||
{
|
{
|
||||||
DictionaryToken dictionaryToken = new DictionaryToken(new Dictionary<NameToken, IToken>()
|
DictionaryToken dictionaryToken = new DictionaryToken(new Dictionary<NameToken, IToken>()
|
||||||
{
|
{
|
||||||
{ NameToken.FunctionType, new NumericToken(4) },
|
{ NameToken.FunctionType, new NumericToken(2) },
|
||||||
{ NameToken.Domain, new ArrayToken(domain.Select(v => new NumericToken((decimal)v)).ToArray()) },
|
{ NameToken.Domain, new ArrayToken(domain.Select(v => new NumericToken((decimal)v)).ToArray()) },
|
||||||
{ NameToken.Range, new ArrayToken(range.Select(v => new NumericToken((decimal)v)).ToArray()) },
|
{ NameToken.Range, new ArrayToken(range.Select(v => new NumericToken((decimal)v)).ToArray()) },
|
||||||
|
|
||||||
@@ -21,7 +23,9 @@
|
|||||||
{ NameToken.N, new NumericToken((decimal)n) },
|
{ NameToken.N, new NumericToken((decimal)n) },
|
||||||
});
|
});
|
||||||
|
|
||||||
return new PdfFunctionType2(dictionaryToken);
|
var func = PdfFunctionParser.Create(dictionaryToken, new TestPdfTokenScanner(), new TestFilterProvider());
|
||||||
|
Assert.Equal(FunctionTypes.Exponential, func.FunctionType);
|
||||||
|
return func as PdfFunctionType2;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@@ -4,12 +4,14 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UglyToad.PdfPig.Functions;
|
using UglyToad.PdfPig.Functions;
|
||||||
|
using UglyToad.PdfPig.Tests.Tokens;
|
||||||
using UglyToad.PdfPig.Tokens;
|
using UglyToad.PdfPig.Tokens;
|
||||||
|
using UglyToad.PdfPig.Util;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
public class PdfFunctionType4Tests
|
public class PdfFunctionType4Tests
|
||||||
{
|
{
|
||||||
private PdfFunctionType4 CreateFunction(string function, double[] domain, double[] range)
|
private static PdfFunctionType4 CreateFunction(string function, double[] domain, double[] range)
|
||||||
{
|
{
|
||||||
DictionaryToken dictionaryToken = new DictionaryToken(new Dictionary<NameToken, IToken>()
|
DictionaryToken dictionaryToken = new DictionaryToken(new Dictionary<NameToken, IToken>()
|
||||||
{
|
{
|
||||||
@@ -21,7 +23,10 @@
|
|||||||
var data = Encoding.ASCII.GetBytes(function); // OtherEncodings.Iso88591.GetBytes(function);
|
var data = Encoding.ASCII.GetBytes(function); // OtherEncodings.Iso88591.GetBytes(function);
|
||||||
StreamToken stream = new StreamToken(dictionaryToken, data);
|
StreamToken stream = new StreamToken(dictionaryToken, data);
|
||||||
|
|
||||||
return new PdfFunctionType4(stream);
|
var func = PdfFunctionParser.Create(stream, new TestPdfTokenScanner(), new TestFilterProvider());
|
||||||
|
Assert.Equal(FunctionTypes.PostScript, func.FunctionType);
|
||||||
|
|
||||||
|
return func as PdfFunctionType4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
var appearance = annotationStamp.normalAppearanceStream;
|
var appearance = annotationStamp.normalAppearanceStream;
|
||||||
// TODO - load color space in annotation appearance
|
// TODO - load color space in annotation appearance
|
||||||
|
// TODO - contains function with indirect reference
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
namespace UglyToad.PdfPig.Functions
|
namespace UglyToad.PdfPig.Functions
|
||||||
{
|
{
|
||||||
using System;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UglyToad.PdfPig.Core;
|
using UglyToad.PdfPig.Core;
|
||||||
using UglyToad.PdfPig.Tokens;
|
using UglyToad.PdfPig.Tokens;
|
||||||
@@ -20,25 +19,27 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public StreamToken FunctionStream { get; }
|
public StreamToken FunctionStream { get; }
|
||||||
|
|
||||||
private ArrayToken domain;
|
|
||||||
private ArrayToken range;
|
|
||||||
private int numberOfInputValues = -1;
|
private int numberOfInputValues = -1;
|
||||||
private int numberOfOutputValues = -1;
|
private int numberOfOutputValues = -1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class represents a function in a PDF document.
|
/// This class represents a function in a PDF document.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PdfFunction(DictionaryToken function)
|
public PdfFunction(DictionaryToken function, ArrayToken domain, ArrayToken range)
|
||||||
{
|
{
|
||||||
FunctionDictionary = function;
|
FunctionDictionary = function;
|
||||||
|
DomainValues = domain;
|
||||||
|
RangeValues = range;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class represents a function in a PDF document.
|
/// This class represents a function in a PDF document.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PdfFunction(StreamToken function)
|
public PdfFunction(StreamToken function, ArrayToken domain, ArrayToken range)
|
||||||
{
|
{
|
||||||
FunctionStream = function;
|
FunctionStream = function;
|
||||||
|
DomainValues = domain;
|
||||||
|
RangeValues = range;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -119,7 +120,7 @@
|
|||||||
{
|
{
|
||||||
if (numberOfInputValues == -1)
|
if (numberOfInputValues == -1)
|
||||||
{
|
{
|
||||||
ArrayToken array = GetDomainValues();
|
ArrayToken array = DomainValues;
|
||||||
numberOfInputValues = array.Length / 2;
|
numberOfInputValues = array.Length / 2;
|
||||||
}
|
}
|
||||||
return numberOfInputValues;
|
return numberOfInputValues;
|
||||||
@@ -135,7 +136,7 @@
|
|||||||
/// <returns>The domain range for this component.</returns>
|
/// <returns>The domain range for this component.</returns>
|
||||||
public PdfRange GetDomainForInput(int n)
|
public PdfRange GetDomainForInput(int n)
|
||||||
{
|
{
|
||||||
ArrayToken domainValues = GetDomainValues();
|
ArrayToken domainValues = DomainValues;
|
||||||
return new PdfRange(domainValues.Data.OfType<NumericToken>().Select(t => t.Double), n);
|
return new PdfRange(domainValues.Data.OfType<NumericToken>().Select(t => t.Double), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,34 +154,13 @@
|
|||||||
/// Returns all ranges for the output values as <see cref="ArrayToken"/>. Required for type 0 and type 4 functions.
|
/// Returns all ranges for the output values as <see cref="ArrayToken"/>. Required for type 0 and type 4 functions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>the ranges array.</returns>
|
/// <returns>the ranges array.</returns>
|
||||||
protected virtual ArrayToken RangeValues
|
protected ArrayToken RangeValues { get; }
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (range == null)
|
|
||||||
{
|
|
||||||
GetDictionary().TryGet(NameToken.Range, out range); // Optionnal
|
|
||||||
}
|
|
||||||
return range;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns all domains for the input values as <see cref="ArrayToken"/>. Required for all function types.
|
/// Returns all domains for the input values as <see cref="ArrayToken"/>. Required for all function types.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>the domains array.</returns>
|
/// <returns>the domains array.</returns>
|
||||||
private ArrayToken GetDomainValues()
|
private ArrayToken DomainValues { get; }
|
||||||
{
|
|
||||||
if (domain == null)
|
|
||||||
{
|
|
||||||
if (!GetDictionary().TryGet(NameToken.Domain, out ArrayToken domainToken))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Could not retrieve Domain.");
|
|
||||||
}
|
|
||||||
domain = domainToken;
|
|
||||||
}
|
|
||||||
return domain;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clip the given input values to the ranges.
|
/// Clip the given input values to the ranges.
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UglyToad.PdfPig.Core;
|
using UglyToad.PdfPig.Core;
|
||||||
@@ -10,26 +9,6 @@
|
|||||||
|
|
||||||
internal sealed class PdfFunctionType0 : PdfFunction
|
internal sealed class PdfFunctionType0 : PdfFunction
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// An array of 2 x m numbers specifying the linear mapping of input values
|
|
||||||
/// into the domain of the function's sample table. Default value: [ 0 (Size0
|
|
||||||
/// - 1) 0 (Size1 - 1) ...].
|
|
||||||
/// </summary>
|
|
||||||
private ArrayToken encode;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An array of 2 x n numbers specifying the linear mapping of sample values
|
|
||||||
/// into the range appropriate for the function's output values. Default
|
|
||||||
/// value: same as the value of Range.
|
|
||||||
/// </summary>
|
|
||||||
private ArrayToken decode;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An array of m positive integers specifying the number of samples in each
|
|
||||||
/// input dimension of the sample table.
|
|
||||||
/// </summary>
|
|
||||||
private ArrayToken size;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The samples of the function.
|
/// The samples of the function.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -38,15 +17,27 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stitching function
|
/// Stitching function
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal PdfFunctionType0(DictionaryToken function) : base(function)
|
internal PdfFunctionType0(DictionaryToken function, ArrayToken domain, ArrayToken range, ArrayToken size, int bitsPerSample, int order, ArrayToken encode, ArrayToken decode)
|
||||||
|
: base(function, domain, range)
|
||||||
{
|
{
|
||||||
|
Size = size;
|
||||||
|
BitsPerSample = bitsPerSample;
|
||||||
|
Order = order;
|
||||||
|
EncodeValues = encode;
|
||||||
|
DecodeValues = decode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stitching function
|
/// Stitching function
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal PdfFunctionType0(StreamToken function) : base(function)
|
internal PdfFunctionType0(StreamToken function, ArrayToken domain, ArrayToken range, ArrayToken size, int bitsPerSample, int order, ArrayToken encode, ArrayToken decode)
|
||||||
|
: base(function, domain, range)
|
||||||
{
|
{
|
||||||
|
Size = size;
|
||||||
|
BitsPerSample = bitsPerSample;
|
||||||
|
Order = order;
|
||||||
|
EncodeValues = encode;
|
||||||
|
DecodeValues = decode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override FunctionTypes FunctionType
|
public override FunctionTypes FunctionType
|
||||||
@@ -59,35 +50,16 @@
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The "Size" entry, which is the number of samples in each input dimension of the sample table.
|
/// The "Size" entry, which is the number of samples in each input dimension of the sample table.
|
||||||
|
/// <para>An array of m positive integers specifying the number of samples in each input dimension of the sample table.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ArrayToken Size
|
public ArrayToken Size { get; }
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (size == null && !GetDictionary().TryGet(NameToken.Size, out size))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(NameToken.Size);
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the number of bits that the output value will take up.
|
/// Get the number of bits that the output value will take up.
|
||||||
/// <para>Valid values are 1,2,4,8,12,16,24,32.</para>
|
/// <para>Valid values are 1,2,4,8,12,16,24,32.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Number of bits for each output value.</returns>
|
/// <returns>Number of bits for each output value.</returns>
|
||||||
public int BitsPerSample
|
public int BitsPerSample { get; }
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (!GetDictionary().TryGet<NumericToken>(NameToken.BitsPerSample, out var bps))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(NameToken.BitsPerSample);
|
|
||||||
}
|
|
||||||
return bps.Int;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the order of interpolation between samples. Valid values are 1 and 3,
|
/// Get the order of interpolation between samples. Valid values are 1 and 3,
|
||||||
@@ -95,69 +67,21 @@
|
|||||||
/// is 1. See p.170 in PDF spec 1.7.
|
/// is 1. See p.170 in PDF spec 1.7.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>order of interpolation.</returns>
|
/// <returns>order of interpolation.</returns>
|
||||||
public int Order
|
public int Order { get; }
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (!GetDictionary().TryGet<NumericToken>(NameToken.Order, out var order))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return order.Int;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns all encode values as <see cref="ArrayToken"/>.
|
/// An array of 2 x m numbers specifying the linear mapping of input values
|
||||||
|
/// into the domain of the function's sample table. Default value: [ 0 (Size0
|
||||||
|
/// - 1) 0 (Size1 - 1) ...].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>the encode array. </returns>
|
private ArrayToken EncodeValues { get; }
|
||||||
private ArrayToken EncodeValues
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (encode == null)
|
|
||||||
{
|
|
||||||
GetDictionary().TryGet<ArrayToken>(NameToken.Encode, out encode);
|
|
||||||
|
|
||||||
// the default value is [0 (size[0]-1) 0 (size[1]-1) ...]
|
|
||||||
if (encode == null)
|
|
||||||
{
|
|
||||||
var values = new List<NumericToken>();
|
|
||||||
ArrayToken sizeValues = Size;
|
|
||||||
int sizeValuesSize = sizeValues.Length;
|
|
||||||
for (int i = 0; i < sizeValuesSize; i++)
|
|
||||||
{
|
|
||||||
values.Add(new NumericToken(0));
|
|
||||||
values.Add(new NumericToken((sizeValues[i] as NumericToken).Int - 1L));
|
|
||||||
}
|
|
||||||
encode = new ArrayToken(values);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return encode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns all decode values as <see cref="ArrayToken"/>.
|
/// An array of 2 x n numbers specifying the linear mapping of sample values
|
||||||
|
/// into the range appropriate for the function's output values. Default
|
||||||
|
/// value: same as the value of Range.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>the decode array.</returns>
|
private ArrayToken DecodeValues { get; }
|
||||||
private ArrayToken DecodeValues
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (decode == null)
|
|
||||||
{
|
|
||||||
GetDictionary().TryGet<ArrayToken>(NameToken.Decode, out decode);
|
|
||||||
|
|
||||||
// if decode is null, the default values are the range values
|
|
||||||
if (decode == null)
|
|
||||||
{
|
|
||||||
decode = RangeValues;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return decode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the encode for the input parameter.
|
/// Get the encode for the input parameter.
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
namespace UglyToad.PdfPig.Functions
|
namespace UglyToad.PdfPig.Functions
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using UglyToad.PdfPig.Tokens;
|
using UglyToad.PdfPig.Tokens;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -12,80 +11,20 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Exponential interpolation function
|
/// Exponential interpolation function
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal PdfFunctionType2(DictionaryToken function) : base(function)
|
internal PdfFunctionType2(DictionaryToken function, ArrayToken domain, ArrayToken range, ArrayToken c0, ArrayToken c1, double n)
|
||||||
|
: base(function, domain, range)
|
||||||
{
|
{
|
||||||
if (GetDictionary().TryGet(NameToken.C0, out ArrayToken array0))
|
C0 = c0;
|
||||||
{
|
C1 = c1;
|
||||||
C0 = array0;
|
N = n;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
C0 = new ArrayToken(new List<IToken>());
|
|
||||||
}
|
|
||||||
if (C0.Length == 0)
|
|
||||||
{
|
|
||||||
C0 = new ArrayToken(new List<NumericToken>() { new NumericToken(0) });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetDictionary().TryGet(NameToken.C1, out ArrayToken array1))
|
internal PdfFunctionType2(StreamToken function, ArrayToken domain, ArrayToken range, ArrayToken c0, ArrayToken c1, double n)
|
||||||
|
: base(function, domain, range)
|
||||||
{
|
{
|
||||||
C1 = array1;
|
C0 = c0;
|
||||||
}
|
C1 = c1;
|
||||||
else
|
N = n;
|
||||||
{
|
|
||||||
C1 = new ArrayToken(new List<IToken>());
|
|
||||||
}
|
|
||||||
if (C0.Length == 0)
|
|
||||||
{
|
|
||||||
C1 = new ArrayToken(new List<NumericToken>() { new NumericToken(1) });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetDictionary().TryGet(NameToken.N, out NumericToken exp))
|
|
||||||
{
|
|
||||||
N = exp.Double;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal PdfFunctionType2(StreamToken function) : base(function)
|
|
||||||
{
|
|
||||||
if (GetDictionary().TryGet(NameToken.C0, out ArrayToken array0))
|
|
||||||
{
|
|
||||||
C0 = array0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
C0 = new ArrayToken(new List<IToken>());
|
|
||||||
}
|
|
||||||
if (C0.Length == 0)
|
|
||||||
{
|
|
||||||
C0 = new ArrayToken(new List<NumericToken>() { new NumericToken(0) });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetDictionary().TryGet(NameToken.C1, out ArrayToken array1))
|
|
||||||
{
|
|
||||||
C1 = array1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
C1 = new ArrayToken(new List<IToken>());
|
|
||||||
}
|
|
||||||
if (C0.Length == 0)
|
|
||||||
{
|
|
||||||
C1 = new ArrayToken(new List<NumericToken>() { new NumericToken(1) });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetDictionary().TryGet(NameToken.N, out NumericToken exp))
|
|
||||||
{
|
|
||||||
N = exp.Double;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override FunctionTypes FunctionType
|
public override FunctionTypes FunctionType
|
||||||
|
@@ -12,35 +12,38 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal sealed class PdfFunctionType3 : PdfFunction
|
internal sealed class PdfFunctionType3 : PdfFunction
|
||||||
{
|
{
|
||||||
private ArrayToken functions;
|
private readonly double[] boundsValues;
|
||||||
private ArrayToken encode;
|
|
||||||
private ArrayToken bounds;
|
|
||||||
private double[] boundsValues;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stitching function
|
/// Stitching function
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal PdfFunctionType3(DictionaryToken function, IReadOnlyList<PdfFunction> functionsArray)
|
internal PdfFunctionType3(DictionaryToken function, ArrayToken domain, ArrayToken range, IReadOnlyList<PdfFunction> functionsArray, ArrayToken bounds, ArrayToken encode)
|
||||||
: base(function)
|
: base(function, domain, range)
|
||||||
{
|
{
|
||||||
if (functionsArray == null || functionsArray.Count == 0)
|
if (functionsArray == null || functionsArray.Count == 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(functionsArray));
|
throw new ArgumentNullException(nameof(functionsArray));
|
||||||
}
|
}
|
||||||
this.FunctionsArray = functionsArray;
|
this.FunctionsArray = functionsArray;
|
||||||
|
Bounds = bounds;
|
||||||
|
Encode = encode;
|
||||||
|
boundsValues = Bounds.Data.OfType<NumericToken>().Select(t => t.Double).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stitching function
|
/// Stitching function
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal PdfFunctionType3(StreamToken function, IReadOnlyList<PdfFunction> functionsArray)
|
internal PdfFunctionType3(StreamToken function, ArrayToken domain, ArrayToken range, IReadOnlyList<PdfFunction> functionsArray, ArrayToken bounds, ArrayToken encode)
|
||||||
: base(function)
|
: base(function, domain, range)
|
||||||
{
|
{
|
||||||
if (functionsArray == null || functionsArray.Count == 0)
|
if (functionsArray == null || functionsArray.Count == 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(functionsArray));
|
throw new ArgumentNullException(nameof(functionsArray));
|
||||||
}
|
}
|
||||||
this.FunctionsArray = functionsArray;
|
this.FunctionsArray = functionsArray;
|
||||||
|
Bounds = bounds;
|
||||||
|
Encode = encode;
|
||||||
|
boundsValues = Bounds.Data.OfType<NumericToken>().Select(t => t.Double).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override FunctionTypes FunctionType
|
public override FunctionTypes FunctionType
|
||||||
@@ -71,11 +74,6 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (boundsValues == null)
|
|
||||||
{
|
|
||||||
boundsValues = Bounds.Data.OfType<NumericToken>().Select(t => t.Double).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
int boundsSize = boundsValues.Length;
|
int boundsSize = boundsValues.Length;
|
||||||
// create a combined array containing the domain and the bounds values
|
// create a combined array containing the domain and the bounds values
|
||||||
// domain.min, bounds[0], bounds[1], ...., bounds[boundsSize-1], domain.max
|
// domain.min, bounds[0], bounds[1], ...., bounds[boundsSize-1], domain.max
|
||||||
@@ -108,55 +106,22 @@
|
|||||||
return ClipToRange(functionResult);
|
return ClipToRange(functionResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IReadOnlyList<PdfFunction> FunctionsArray { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns all functions values as <see cref="ArrayToken"/>.
|
/// Returns all functions values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>the functions array. </returns>
|
public IReadOnlyList<PdfFunction> FunctionsArray { get; }
|
||||||
public ArrayToken Functions
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (functions == null && !GetDictionary().TryGet<ArrayToken>(NameToken.Functions, out functions))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(NameToken.Functions);
|
|
||||||
}
|
|
||||||
return functions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns all bounds values as <see cref="ArrayToken"/>.
|
/// Returns all bounds values as <see cref="ArrayToken"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>the bounds array.</returns>
|
/// <returns>the bounds array.</returns>
|
||||||
public ArrayToken Bounds
|
public ArrayToken Bounds { get; }
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (bounds == null && !GetDictionary().TryGet<ArrayToken>(NameToken.Bounds, out bounds))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(NameToken.Bounds);
|
|
||||||
}
|
|
||||||
return bounds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns all encode values as <see cref="ArrayToken"/>.
|
/// Returns all encode values as <see cref="ArrayToken"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>the encode array.</returns>
|
/// <returns>the encode array.</returns>
|
||||||
public ArrayToken Encode
|
public ArrayToken Encode { get; }
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (encode == null && !GetDictionary().TryGet<ArrayToken>(NameToken.Encode, out encode))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(NameToken.Encode);
|
|
||||||
}
|
|
||||||
return encode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the encode for the input parameter.
|
/// Get the encode for the input parameter.
|
||||||
|
@@ -17,7 +17,8 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// PostScript calculator function
|
/// PostScript calculator function
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal PdfFunctionType4(StreamToken function) : base(function)
|
internal PdfFunctionType4(StreamToken function, ArrayToken domain, ArrayToken range)
|
||||||
|
: base(function, domain, range)
|
||||||
{
|
{
|
||||||
byte[] bytes = FunctionStream.Data.ToArray();
|
byte[] bytes = FunctionStream.Data.ToArray();
|
||||||
string str = OtherEncodings.Iso88591.GetString(bytes);
|
string str = OtherEncodings.Iso88591.GetString(bytes);
|
||||||
|
@@ -30,6 +30,13 @@
|
|||||||
throw new ArgumentException(nameof(function));
|
throw new ArgumentException(nameof(function));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!functionDictionary.TryGet(NameToken.Domain, scanner, out ArrayToken domain))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(NameToken.Domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
functionDictionary.TryGet(NameToken.Range, scanner, out ArrayToken range);
|
||||||
|
|
||||||
int functionType = (functionDictionary.Data[NameToken.FunctionType] as NumericToken).Int;
|
int functionType = (functionDictionary.Data[NameToken.FunctionType] as NumericToken).Int;
|
||||||
|
|
||||||
switch (functionType)
|
switch (functionType)
|
||||||
@@ -39,12 +46,93 @@
|
|||||||
{
|
{
|
||||||
throw new NotImplementedException("PdfFunctionType0 not stream");
|
throw new NotImplementedException("PdfFunctionType0 not stream");
|
||||||
}
|
}
|
||||||
return new PdfFunctionType0(functionStream);
|
return CreatePdfFunctionType0(functionStream, domain, range, scanner);
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
return new PdfFunctionType2(functionDictionary);
|
return CreatePdfFunctionType2(functionDictionary, domain, range, scanner);
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
|
return CreatePdfFunctionType3(functionDictionary, domain, range, scanner, filterProvider);
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if (functionStream == null)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("PdfFunctionType4 not stream");
|
||||||
|
}
|
||||||
|
return CreatePdfFunctionType4(functionStream, domain, range, scanner);
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IOException("Error: Unknown function type " + functionType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PdfFunctionType0 CreatePdfFunctionType0(StreamToken functionStream, ArrayToken domain, ArrayToken range, IPdfTokenScanner scanner)
|
||||||
|
{
|
||||||
|
if (range == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Could not retrieve Range in type 0 function.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!functionStream.StreamDictionary.TryGet<ArrayToken>(NameToken.Size, scanner, out var size))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(NameToken.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!functionStream.StreamDictionary.TryGet<NumericToken>(NameToken.BitsPerSample, scanner, out var bps))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(NameToken.BitsPerSample);
|
||||||
|
}
|
||||||
|
|
||||||
|
int order = 1; // Default value
|
||||||
|
if (functionStream.StreamDictionary.TryGet<NumericToken>(NameToken.Order, scanner, out var orderToken))
|
||||||
|
{
|
||||||
|
order = orderToken.Int;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!functionStream.StreamDictionary.TryGet<ArrayToken>(NameToken.Encode, scanner, out var encode) || encode == null)
|
||||||
|
{
|
||||||
|
// The default value is [0 (size[0]-1) 0 (size[1]-1) ...]
|
||||||
|
var values = new List<NumericToken>();
|
||||||
|
int sizeValuesSize = size.Length;
|
||||||
|
for (int i = 0; i < sizeValuesSize; i++)
|
||||||
|
{
|
||||||
|
values.Add(new NumericToken(0));
|
||||||
|
values.Add(new NumericToken((size[i] as NumericToken).Int - 1L));
|
||||||
|
}
|
||||||
|
encode = new ArrayToken(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!functionStream.StreamDictionary.TryGet<ArrayToken>(NameToken.Decode, scanner, out var decode) || decode == null)
|
||||||
|
{
|
||||||
|
// if decode is null, the default values are the range values
|
||||||
|
decode = range;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PdfFunctionType0(functionStream, domain, range, size, bps.Int, order, encode, decode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PdfFunctionType2 CreatePdfFunctionType2(DictionaryToken functionDictionary, ArrayToken domain, ArrayToken range, IPdfTokenScanner scanner)
|
||||||
|
{
|
||||||
|
if (!functionDictionary.TryGet(NameToken.C0, scanner, out ArrayToken array0) || array0.Length == 0)
|
||||||
|
{
|
||||||
|
array0 = new ArrayToken(new List<NumericToken>() { new NumericToken(0) }); // Default value: [0.0].
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!functionDictionary.TryGet(NameToken.C1, scanner, out ArrayToken array1) || array1.Length == 0)
|
||||||
|
{
|
||||||
|
array1 = new ArrayToken(new List<NumericToken>() { new NumericToken(1) }); // Default value: [1.0].
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!functionDictionary.TryGet(NameToken.N, scanner, out NumericToken exp))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(NameToken.N);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PdfFunctionType2(functionDictionary, domain, range, array0, array1, exp.Double);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PdfFunctionType3 CreatePdfFunctionType3(DictionaryToken functionDictionary, ArrayToken domain, ArrayToken range, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider)
|
||||||
|
{
|
||||||
var functions = new List<PdfFunction>();
|
var functions = new List<PdfFunction>();
|
||||||
if (functionDictionary.TryGet<ArrayToken>(NameToken.Functions, scanner, out var functionsToken))
|
if (functionDictionary.TryGet<ArrayToken>(NameToken.Functions, scanner, out var functionsToken))
|
||||||
{
|
{
|
||||||
@@ -64,18 +152,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new PdfFunctionType3(functionDictionary, functions);
|
else
|
||||||
|
|
||||||
case 4:
|
|
||||||
if (functionStream == null)
|
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("PdfFunctionType4 not stream");
|
throw new ArgumentNullException(NameToken.Functions);
|
||||||
}
|
}
|
||||||
return new PdfFunctionType4(functionStream);
|
|
||||||
|
|
||||||
default:
|
if (!functionDictionary.TryGet<ArrayToken>(NameToken.Bounds, out var bounds))
|
||||||
throw new IOException("Error: Unknown function type " + functionType);
|
{
|
||||||
}
|
throw new ArgumentNullException(NameToken.Bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!functionDictionary.TryGet<ArrayToken>(NameToken.Encode, out var encode))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(NameToken.Encode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PdfFunctionType3(functionDictionary, domain, range, functions, bounds, encode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PdfFunctionType4 CreatePdfFunctionType4(StreamToken functionStream, ArrayToken domain, ArrayToken range, IPdfTokenScanner scanner)
|
||||||
|
{
|
||||||
|
if (range == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Could not retrieve Range in type 4 function.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PdfFunctionType4(functionStream, domain, range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user