blob: 7aaee93659dc80c4a0e98fad159d48e1c5d5bd4c [file] [log] [blame]
//========================================================================
//
// Function.h
//
// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
// Copyright (C) 2009, 2010, 2018, 2019 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
// Copyright (C) 2011 Andrea Canciani <ranma42@gmail.com>
// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
// Copyright (C) 2012 Adam Reichold <adamreichold@myopera.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================
#ifndef FUNCTION_H
#define FUNCTION_H
#include "Object.h"
#include <set>
class Dict;
class Stream;
struct PSObject;
class PSStack;
//------------------------------------------------------------------------
// Function
//------------------------------------------------------------------------
#define funcMaxInputs 32
#define funcMaxOutputs 32
#define sampledFuncMaxInputs 16
class Function {
public:
Function();
virtual ~Function();
Function(const Function &) = delete;
Function& operator=(const Function &other) = delete;
// Construct a function. Returns NULL if unsuccessful.
static Function *parse(Object *funcObj);
// Initialize the entries common to all function types.
bool init(Dict *dict);
virtual Function *copy() const = 0;
// Return the function type:
// -1 : identity
// 0 : sampled
// 2 : exponential
// 3 : stitching
// 4 : PostScript
virtual int getType() const = 0;
// Return size of input and output tuples.
int getInputSize() const { return m; }
int getOutputSize() const { return n; }
double getDomainMin(int i) const { return domain[i][0]; }
double getDomainMax(int i) const { return domain[i][1]; }
double getRangeMin(int i) const { return range[i][0]; }
double getRangeMax(int i) const { return range[i][1]; }
bool getHasRange() const { return hasRange; }
virtual bool hasDifferentResultSet(const Function *func) const { return false; }
// Transform an input tuple into an output tuple.
virtual void transform(const double *in, double *out) const = 0;
virtual bool isOk() const = 0;
protected:
static Function *parse(Object *funcObj, std::set<int> *usedParents);
Function(const Function *func);
int m, n; // size of input and output tuples
double // min and max values for function domain
domain[funcMaxInputs][2];
double // min and max values for function range
range[funcMaxOutputs][2];
bool hasRange; // set if range is defined
};
//------------------------------------------------------------------------
// IdentityFunction
//------------------------------------------------------------------------
class IdentityFunction: public Function {
public:
IdentityFunction();
~IdentityFunction();
Function *copy() const override { return new IdentityFunction(); }
int getType() const override { return -1; }
void transform(const double *in, double *out) const override;
bool isOk() const override { return true; }
private:
};
//------------------------------------------------------------------------
// SampledFunction
//------------------------------------------------------------------------
class SampledFunction: public Function {
public:
SampledFunction(Object *funcObj, Dict *dict);
~SampledFunction();
Function *copy() const override { return new SampledFunction(this); }
int getType() const override { return 0; }
void transform(const double *in, double *out) const override;
bool isOk() const override { return ok; }
bool hasDifferentResultSet(const Function *func) const override;
int getSampleSize(int i) const { return sampleSize[i]; }
double getEncodeMin(int i) const { return encode[i][0]; }
double getEncodeMax(int i) const { return encode[i][1]; }
double getDecodeMin(int i) const { return decode[i][0]; }
double getDecodeMax(int i) const { return decode[i][1]; }
const double *getSamples() const { return samples; }
int getSampleNumber() const { return nSamples; }
private:
SampledFunction(const SampledFunction *func);
int // number of samples for each domain element
sampleSize[funcMaxInputs];
double // min and max values for domain encoder
encode[funcMaxInputs][2];
double // min and max values for range decoder
decode[funcMaxOutputs][2];
double // input multipliers
inputMul[funcMaxInputs];
int *idxOffset;
double *samples; // the samples
int nSamples; // size of the samples array
double *sBuf; // buffer for the transform function
mutable double cacheIn[funcMaxInputs];
mutable double cacheOut[funcMaxOutputs];
bool ok;
};
//------------------------------------------------------------------------
// ExponentialFunction
//------------------------------------------------------------------------
class ExponentialFunction: public Function {
public:
ExponentialFunction(Object *funcObj, Dict *dict);
~ExponentialFunction();
Function *copy() const override { return new ExponentialFunction(this); }
int getType() const override { return 2; }
void transform(const double *in, double *out) const override;
bool isOk() const override { return ok; }
const double *getC0() const { return c0; }
const double *getC1() const { return c1; }
double getE() const { return e; }
private:
ExponentialFunction(const ExponentialFunction *func);
double c0[funcMaxOutputs];
double c1[funcMaxOutputs];
double e;
bool isLinear;
bool ok;
};
//------------------------------------------------------------------------
// StitchingFunction
//------------------------------------------------------------------------
class StitchingFunction: public Function {
public:
StitchingFunction(Object *funcObj, Dict *dict, std::set<int> *usedParents);
~StitchingFunction();
Function *copy() const override { return new StitchingFunction(this); }
int getType() const override { return 3; }
void transform(const double *in, double *out) const override;
bool isOk() const override { return ok; }
int getNumFuncs() const { return k; }
const Function *getFunc(int i) const { return funcs[i]; }
const double *getBounds() const { return bounds; }
const double *getEncode() const { return encode; }
const double *getScale() const { return scale; }
private:
StitchingFunction(const StitchingFunction *func);
int k;
Function **funcs;
double *bounds;
double *encode;
double *scale;
bool ok;
};
//------------------------------------------------------------------------
// PostScriptFunction
//------------------------------------------------------------------------
class PostScriptFunction: public Function {
public:
PostScriptFunction(Object *funcObj, Dict *dict);
~PostScriptFunction();
Function *copy() const override { return new PostScriptFunction(this); }
int getType() const override { return 4; }
void transform(const double *in, double *out) const override;
bool isOk() const override { return ok; }
const GooString *getCodeString() const { return codeString; }
private:
PostScriptFunction(const PostScriptFunction *func);
bool parseCode(Stream *str, int *codePtr);
GooString getToken(Stream *str);
void resizeCode(int newSize);
void exec(PSStack *stack, int codePtr) const;
GooString *codeString;
PSObject *code;
int codeSize;
mutable double cacheIn[funcMaxInputs];
mutable double cacheOut[funcMaxOutputs];
bool ok;
};
#endif