Refactor PdfFunctionParser to account for indirect reference tokens

This commit is contained in:
BobLd 2023-05-21 11:11:21 +01:00
parent 32a562f02a
commit 903218854c
10 changed files with 227 additions and 287 deletions

View File

@ -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);

View File

@ -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]

View File

@ -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>

View File

@ -20,6 +20,7 @@
var appearance = annotationStamp.normalAppearanceStream;
// TODO - load color space in annotation appearance
// TODO - contains function with indirect reference
}
}

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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);
}
}
}