mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-04-05 20:55:01 +08:00
Refactor PdfFunctionParser to account for indirect reference tokens
This commit is contained in:
parent
32a562f02a
commit
903218854c
@ -4,11 +4,16 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UglyToad.PdfPig.Functions;
|
||||
using UglyToad.PdfPig.Tests.Tokens;
|
||||
using UglyToad.PdfPig.Tokens;
|
||||
using UglyToad.PdfPig.Util;
|
||||
using Xunit;
|
||||
|
||||
public class PdfFunctionType0Tests
|
||||
{
|
||||
private readonly TestPdfTokenScanner testPdfTokenScanner = new TestPdfTokenScanner();
|
||||
private readonly TestFilterProvider testFilterProvider = new TestFilterProvider();
|
||||
|
||||
private static ArrayToken GetArrayToken(params double[] data)
|
||||
{
|
||||
return new ArrayToken(data.Select(v => new NumericToken((decimal)v)).ToArray());
|
||||
@ -33,7 +38,10 @@
|
||||
|
||||
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 });
|
||||
Assert.Equal(4, result.Length);
|
||||
result = function0.Eval(new double[] { 0.5 });
|
||||
@ -61,7 +69,10 @@
|
||||
|
||||
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 });
|
||||
Assert.Single(result);
|
||||
Assert.Equal(0.0, result[0], 3);
|
||||
@ -100,7 +111,10 @@
|
||||
|
||||
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 });
|
||||
Assert.Single(result);
|
||||
Assert.Equal(0.0, result[0], 3);
|
||||
@ -139,7 +153,10 @@
|
||||
|
||||
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 });
|
||||
Assert.Equal(3, result.Length);
|
||||
Assert.Equal(new double[] { 1, 1, 0 }, result); // yellow
|
||||
@ -178,7 +195,9 @@
|
||||
|
||||
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 });
|
||||
Assert.Equal(3, result.Length);
|
||||
|
@ -3,16 +3,18 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UglyToad.PdfPig.Functions;
|
||||
using UglyToad.PdfPig.Tests.Tokens;
|
||||
using UglyToad.PdfPig.Tokens;
|
||||
using UglyToad.PdfPig.Util;
|
||||
using Xunit;
|
||||
|
||||
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>()
|
||||
{
|
||||
{ NameToken.FunctionType, new NumericToken(4) },
|
||||
{ NameToken.FunctionType, new NumericToken(2) },
|
||||
{ NameToken.Domain, new ArrayToken(domain.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) },
|
||||
});
|
||||
|
||||
return new PdfFunctionType2(dictionaryToken);
|
||||
var func = PdfFunctionParser.Create(dictionaryToken, new TestPdfTokenScanner(), new TestFilterProvider());
|
||||
Assert.Equal(FunctionTypes.Exponential, func.FunctionType);
|
||||
return func as PdfFunctionType2;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -4,12 +4,14 @@
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UglyToad.PdfPig.Functions;
|
||||
using UglyToad.PdfPig.Tests.Tokens;
|
||||
using UglyToad.PdfPig.Tokens;
|
||||
using UglyToad.PdfPig.Util;
|
||||
using Xunit;
|
||||
|
||||
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>()
|
||||
{
|
||||
@ -21,7 +23,10 @@
|
||||
var data = Encoding.ASCII.GetBytes(function); // OtherEncodings.Iso88591.GetBytes(function);
|
||||
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>
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
var appearance = annotationStamp.normalAppearanceStream;
|
||||
// TODO - load color space in annotation appearance
|
||||
// TODO - contains function with indirect reference
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
namespace UglyToad.PdfPig.Functions
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UglyToad.PdfPig.Core;
|
||||
using UglyToad.PdfPig.Tokens;
|
||||
@ -20,25 +19,27 @@
|
||||
/// </summary>
|
||||
public StreamToken FunctionStream { get; }
|
||||
|
||||
private ArrayToken domain;
|
||||
private ArrayToken range;
|
||||
private int numberOfInputValues = -1;
|
||||
private int numberOfOutputValues = -1;
|
||||
|
||||
/// <summary>
|
||||
/// This class represents a function in a PDF document.
|
||||
/// </summary>
|
||||
public PdfFunction(DictionaryToken function)
|
||||
public PdfFunction(DictionaryToken function, ArrayToken domain, ArrayToken range)
|
||||
{
|
||||
FunctionDictionary = function;
|
||||
DomainValues = domain;
|
||||
RangeValues = range;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class represents a function in a PDF document.
|
||||
/// </summary>
|
||||
public PdfFunction(StreamToken function)
|
||||
public PdfFunction(StreamToken function, ArrayToken domain, ArrayToken range)
|
||||
{
|
||||
FunctionStream = function;
|
||||
DomainValues = domain;
|
||||
RangeValues = range;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -119,7 +120,7 @@
|
||||
{
|
||||
if (numberOfInputValues == -1)
|
||||
{
|
||||
ArrayToken array = GetDomainValues();
|
||||
ArrayToken array = DomainValues;
|
||||
numberOfInputValues = array.Length / 2;
|
||||
}
|
||||
return numberOfInputValues;
|
||||
@ -135,7 +136,7 @@
|
||||
/// <returns>The domain range for this component.</returns>
|
||||
public PdfRange GetDomainForInput(int n)
|
||||
{
|
||||
ArrayToken domainValues = GetDomainValues();
|
||||
ArrayToken domainValues = DomainValues;
|
||||
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.
|
||||
/// </summary>
|
||||
/// <returns>the ranges array.</returns>
|
||||
protected virtual ArrayToken RangeValues
|
||||
{
|
||||
get
|
||||
{
|
||||
if (range == null)
|
||||
{
|
||||
GetDictionary().TryGet(NameToken.Range, out range); // Optionnal
|
||||
}
|
||||
return range;
|
||||
}
|
||||
}
|
||||
protected ArrayToken RangeValues { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns all domains for the input values as <see cref="ArrayToken"/>. Required for all function types.
|
||||
/// </summary>
|
||||
/// <returns>the domains array.</returns>
|
||||
private ArrayToken GetDomainValues()
|
||||
{
|
||||
if (domain == null)
|
||||
{
|
||||
if (!GetDictionary().TryGet(NameToken.Domain, out ArrayToken domainToken))
|
||||
{
|
||||
throw new ArgumentException("Could not retrieve Domain.");
|
||||
}
|
||||
domain = domainToken;
|
||||
}
|
||||
return domain;
|
||||
}
|
||||
private ArrayToken DomainValues { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Clip the given input values to the ranges.
|
||||
|
@ -2,7 +2,6 @@
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UglyToad.PdfPig.Core;
|
||||
@ -10,26 +9,6 @@
|
||||
|
||||
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>
|
||||
/// The samples of the function.
|
||||
/// </summary>
|
||||
@ -38,15 +17,27 @@
|
||||
/// <summary>
|
||||
/// Stitching function
|
||||
/// </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>
|
||||
/// Stitching function
|
||||
/// </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
|
||||
@ -59,35 +50,16 @@
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
public ArrayToken Size
|
||||
{
|
||||
get
|
||||
{
|
||||
if (size == null && !GetDictionary().TryGet(NameToken.Size, out size))
|
||||
{
|
||||
throw new ArgumentNullException(NameToken.Size);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
public ArrayToken Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
/// </summary>
|
||||
/// <returns>Number of bits for each output value.</returns>
|
||||
public int BitsPerSample
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!GetDictionary().TryGet<NumericToken>(NameToken.BitsPerSample, out var bps))
|
||||
{
|
||||
throw new ArgumentNullException(NameToken.BitsPerSample);
|
||||
}
|
||||
return bps.Int;
|
||||
}
|
||||
}
|
||||
public int BitsPerSample { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <returns>order of interpolation.</returns>
|
||||
public int Order
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!GetDictionary().TryGet<NumericToken>(NameToken.Order, out var order))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return order.Int;
|
||||
}
|
||||
}
|
||||
public int Order { get; }
|
||||
|
||||
/// <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>
|
||||
/// <returns>the encode array. </returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
private ArrayToken EncodeValues { get; }
|
||||
|
||||
/// <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>
|
||||
/// <returns>the decode array.</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
private ArrayToken DecodeValues { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the encode for the input parameter.
|
||||
|
@ -1,7 +1,6 @@
|
||||
namespace UglyToad.PdfPig.Functions
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UglyToad.PdfPig.Tokens;
|
||||
|
||||
/// <summary>
|
||||
@ -12,80 +11,20 @@
|
||||
/// <summary>
|
||||
/// Exponential interpolation function
|
||||
/// </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 = 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();
|
||||
}
|
||||
C0 = c0;
|
||||
C1 = c1;
|
||||
N = n;
|
||||
}
|
||||
|
||||
internal PdfFunctionType2(StreamToken function) : base(function)
|
||||
internal PdfFunctionType2(StreamToken function, ArrayToken domain, ArrayToken range, ArrayToken c0, ArrayToken c1, double n)
|
||||
: base(function, domain, range)
|
||||
{
|
||||
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();
|
||||
}
|
||||
C0 = c0;
|
||||
C1 = c1;
|
||||
N = n;
|
||||
}
|
||||
|
||||
public override FunctionTypes FunctionType
|
||||
|
@ -12,35 +12,38 @@
|
||||
/// </summary>
|
||||
internal sealed class PdfFunctionType3 : PdfFunction
|
||||
{
|
||||
private ArrayToken functions;
|
||||
private ArrayToken encode;
|
||||
private ArrayToken bounds;
|
||||
private double[] boundsValues;
|
||||
private readonly double[] boundsValues;
|
||||
|
||||
/// <summary>
|
||||
/// Stitching function
|
||||
/// </summary>
|
||||
internal PdfFunctionType3(DictionaryToken function, IReadOnlyList<PdfFunction> functionsArray)
|
||||
: base(function)
|
||||
internal PdfFunctionType3(DictionaryToken function, ArrayToken domain, ArrayToken range, IReadOnlyList<PdfFunction> functionsArray, ArrayToken bounds, ArrayToken encode)
|
||||
: base(function, domain, range)
|
||||
{
|
||||
if (functionsArray == null || functionsArray.Count == 0)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(functionsArray));
|
||||
}
|
||||
this.FunctionsArray = functionsArray;
|
||||
Bounds = bounds;
|
||||
Encode = encode;
|
||||
boundsValues = Bounds.Data.OfType<NumericToken>().Select(t => t.Double).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stitching function
|
||||
/// </summary>
|
||||
internal PdfFunctionType3(StreamToken function, IReadOnlyList<PdfFunction> functionsArray)
|
||||
: base(function)
|
||||
internal PdfFunctionType3(StreamToken function, ArrayToken domain, ArrayToken range, IReadOnlyList<PdfFunction> functionsArray, ArrayToken bounds, ArrayToken encode)
|
||||
: base(function, domain, range)
|
||||
{
|
||||
if (functionsArray == null || functionsArray.Count == 0)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(functionsArray));
|
||||
}
|
||||
this.FunctionsArray = functionsArray;
|
||||
Bounds = bounds;
|
||||
Encode = encode;
|
||||
boundsValues = Bounds.Data.OfType<NumericToken>().Select(t => t.Double).ToArray();
|
||||
}
|
||||
|
||||
public override FunctionTypes FunctionType
|
||||
@ -71,11 +74,6 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
if (boundsValues == null)
|
||||
{
|
||||
boundsValues = Bounds.Data.OfType<NumericToken>().Select(t => t.Double).ToArray();
|
||||
}
|
||||
|
||||
int boundsSize = boundsValues.Length;
|
||||
// create a combined array containing the domain and the bounds values
|
||||
// domain.min, bounds[0], bounds[1], ...., bounds[boundsSize-1], domain.max
|
||||
@ -108,55 +106,22 @@
|
||||
return ClipToRange(functionResult);
|
||||
}
|
||||
|
||||
public IReadOnlyList<PdfFunction> FunctionsArray { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns all functions values as <see cref="ArrayToken"/>.
|
||||
/// Returns all functions values.
|
||||
/// </summary>
|
||||
/// <returns>the functions array. </returns>
|
||||
public ArrayToken Functions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (functions == null && !GetDictionary().TryGet<ArrayToken>(NameToken.Functions, out functions))
|
||||
{
|
||||
throw new ArgumentNullException(NameToken.Functions);
|
||||
}
|
||||
return functions;
|
||||
}
|
||||
}
|
||||
public IReadOnlyList<PdfFunction> FunctionsArray { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns all bounds values as <see cref="ArrayToken"/>.
|
||||
/// </summary>
|
||||
/// <returns>the bounds array.</returns>
|
||||
public ArrayToken Bounds
|
||||
{
|
||||
get
|
||||
{
|
||||
if (bounds == null && !GetDictionary().TryGet<ArrayToken>(NameToken.Bounds, out bounds))
|
||||
{
|
||||
throw new ArgumentNullException(NameToken.Bounds);
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
}
|
||||
public ArrayToken Bounds { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns all encode values as <see cref="ArrayToken"/>.
|
||||
/// </summary>
|
||||
/// <returns>the encode array.</returns>
|
||||
public ArrayToken Encode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (encode == null && !GetDictionary().TryGet<ArrayToken>(NameToken.Encode, out encode))
|
||||
{
|
||||
throw new ArgumentNullException(NameToken.Encode);
|
||||
}
|
||||
return encode;
|
||||
}
|
||||
}
|
||||
public ArrayToken Encode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the encode for the input parameter.
|
||||
|
@ -17,7 +17,8 @@
|
||||
/// <summary>
|
||||
/// PostScript calculator function
|
||||
/// </summary>
|
||||
internal PdfFunctionType4(StreamToken function) : base(function)
|
||||
internal PdfFunctionType4(StreamToken function, ArrayToken domain, ArrayToken range)
|
||||
: base(function, domain, range)
|
||||
{
|
||||
byte[] bytes = FunctionStream.Data.ToArray();
|
||||
string str = OtherEncodings.Iso88591.GetString(bytes);
|
||||
|
@ -30,6 +30,13 @@
|
||||
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;
|
||||
|
||||
switch (functionType)
|
||||
@ -39,43 +46,138 @@
|
||||
{
|
||||
throw new NotImplementedException("PdfFunctionType0 not stream");
|
||||
}
|
||||
return new PdfFunctionType0(functionStream);
|
||||
return CreatePdfFunctionType0(functionStream, domain, range, scanner);
|
||||
|
||||
case 2:
|
||||
return new PdfFunctionType2(functionDictionary);
|
||||
return CreatePdfFunctionType2(functionDictionary, domain, range, scanner);
|
||||
|
||||
case 3:
|
||||
var functions = new List<PdfFunction>();
|
||||
if (functionDictionary.TryGet<ArrayToken>(NameToken.Functions, scanner, out var functionsToken))
|
||||
{
|
||||
foreach (IToken token in functionsToken.Data)
|
||||
{
|
||||
if (DirectObjectFinder.TryGet<StreamToken>(token, scanner, out var strTk))
|
||||
{
|
||||
functions.Add(Create(strTk, scanner, filterProvider));
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet<DictionaryToken>(token, scanner, out var dicTk))
|
||||
{
|
||||
functions.Add(Create(dicTk, scanner, filterProvider));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Could not find function for token '{token}' inside type 3 function.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return new PdfFunctionType3(functionDictionary, functions);
|
||||
return CreatePdfFunctionType3(functionDictionary, domain, range, scanner, filterProvider);
|
||||
|
||||
case 4:
|
||||
if (functionStream == null)
|
||||
{
|
||||
throw new NotImplementedException("PdfFunctionType4 not stream");
|
||||
}
|
||||
return new PdfFunctionType4(functionStream);
|
||||
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>();
|
||||
if (functionDictionary.TryGet<ArrayToken>(NameToken.Functions, scanner, out var functionsToken))
|
||||
{
|
||||
foreach (IToken token in functionsToken.Data)
|
||||
{
|
||||
if (DirectObjectFinder.TryGet<StreamToken>(token, scanner, out var strTk))
|
||||
{
|
||||
functions.Add(Create(strTk, scanner, filterProvider));
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet<DictionaryToken>(token, scanner, out var dicTk))
|
||||
{
|
||||
functions.Add(Create(dicTk, scanner, filterProvider));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Could not find function for token '{token}' inside type 3 function.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentNullException(NameToken.Functions);
|
||||
}
|
||||
|
||||
if (!functionDictionary.TryGet<ArrayToken>(NameToken.Bounds, out var bounds))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user