/* rule.hpp -- Output rules
* by
[email protected] Fri Mar 15 15:11:38 CET 2002
*/
#ifdef __GNUC__
#ifndef __clang__
#pragma interface
#endif
#endif
#ifndef RULE_HPP
#define RULE_HPP 1
#include "config2.h"
#include "gensio.hpp"
#include "image.hpp"
#include "minips.hpp"
/** a namespace */
class Rule { public:
struct Cache {
bool WarningOK;
BEGIN_STATIC_ENUM(unsigned char,ff_t)
FF_default=0, /* only for one-liner */
FF_eps=71, /* only for one-liner, temporary */
FF_pdf=72, /* only for one-liner, temporary */
FF_pdfb=73, /* only for one-liner, temporary */
FF_PSL1=110,
FF_PSLC=115,
FF_PSL2=120,
FF_PSL3=130,
FF_PDFB10=90,
FF_PDFB12=92,
FF_PDF10=80,
FF_PDF12=82,
FF_GIF89a=1,
FF_PNM=2,
FF_PAM=3,
FF_PIP=4, /* Portable Indexed file format by pts */
FF_Empty=5,
FF_Meta=6,
FF_JPEG=7,
FF_TIFF=8,
FF_PNG=9,
FF_XPM=10,
FF_BMP=11,
FF_XWD=12,
FF_X11=13 /* Don't add a comma, gcc-4.8.1. can't compile it that way. */
END_STATIC_ENUM()
ff_t FileFormat;
Image::sf_t SampleFormat;
/** Used only in appliers.cpp when _check_rule() changes SampleFormat so
* setSampleFormat() called before _work() would set that dummy
* SampleFormat.
*/
Image::sf_t origSampleFormat;
BEGIN_STATIC_ENUM(unsigned char,te_t)
TE_default=0, /* only for one-liner */
TE_Binary=1,
TE_ASCII=2,
TE_Hex=3,
TE_A85=4,
TE_MSBfirst=5,
TE_LSBfirst=6
END_STATIC_ENUM()
te_t TransferEncoding;
BEGIN_STATIC_ENUM(unsigned char,co_t)
CO_default=0, /* only for one-liner */
CO_None=1,
CO_LZW=2,
CO_ZIP=3,
CO_RLE=4,
CO_Fax=5,
CO_DCT=6,
CO_IJG=7,
CO_JAI=8,
CO_max=8
END_STATIC_ENUM()
co_t Compression;
BEGIN_STATIC_ENUM(unsigned char,pr_t)
PR_None=1,
PR_TIFF2=2,
PR_PNGNone=10, PR_PNG=10,
PR_PNGSub=11,
PR_PNGUP=12,
PR_PNGAverage=13,
PR_PNGPaeth=14,
PR_PNGAuto=15,
PR_PNGAutoMaybe=25,
PR_PNGAutoBadUnsigned=45,
PR_PNGAutoBadSigned=55
END_STATIC_ENUM()
pr_t Predictor;
Image::Sampled::rgb_t Transparent;
bool isOneBit() const;
bool isPDF() const;
bool isPDFB() const;
bool isPS() const;
bool isPSL2() const;
bool isPSL3() const;
bool hasPredictor() const;
bool isIndexed() const;
bool isTransparentM() const;
bool isGray() const;
bool isRGB() const;
bool isDCTE() const;
bool isBinSB() const;
/** /Compression/ZIP not OK with /PSL1, /PSLC, /PSL2, /PDF10, /PDFB10 */
bool isZIPOK() const;
// bool is8() const;
/** @param s is case insensitive, leading `/' is optional.
* @return SF_max if not found, or a valid SF_... constant
*/
static Image::sf_t parseSampleFormat(char const*s, slen_t slen);
static char const* dumpFileFormat(ff_t FileFormat, co_t Compression=CO_default);
static char const* dumpTransferEncoding(te_t TransferEncoding);
static char const* dumpSampleFormat(Image::sf_t SampleFormat);
static char const* dumpCompression(co_t Compression);
};
struct CacheHints {
BEGIN_STATIC_ENUM(unsigned char,sc_t) /* Fri Aug 16 16:33:47 CEST 2002 */
SC_default=0,
SC_None=1,
SC_OK=2,
SC_RotateOK=3
END_STATIC_ENUM()
sc_t Scale;
/* Image dimensions for encoding filters (may be different from real
* image dimensions, but _really_ disrecommended).
* slen_t important becasuse of separate().
*/
slen_t EncoderColumns, EncoderBPL, EncoderRows;
/** Number of color components (channels) per pixel. */
unsigned char EncoderColors;
slen_t PredictorColumns;
unsigned char PredictorBPC, PredictorColors;
unsigned ColorTransform;
signed Effort;
slen_t RecordSize;
slendiff_t K;
/* JPEG quality for the IJG encoding filter */
unsigned char Quality;
unsigned TransferCPL;
MiniPS::String *Comment, *Title, *Subject, *Author, *Creator, *Producer;
MiniPS::String *Created, *Produced;
MiniPS::Dict *DCT;
/** MiniPS::Real* or integer */
MiniPS::VALUE TopMargin, BottomMargin, LeftMargin, RightMargin;
/** MiniPS::Real* or integer. Specifies the dimension the image should
* be lowered below the baseline for (PostScript or PDF) output with
* /Scale/None. Default to 0.
*/
MiniPS::VALUE LowerMargin;
/** 72 by default. */
MiniPS::VALUE ImageDPI;
static char const* dumpScale(sc_t Scale);
};
struct OutputRule {
Cache cache;
CacheHints cacheHints;
MiniPS::Dict* dict;
/* /Hints entry in dict */
MiniPS::Dict* dictHints;
/* Number of this output rule, as appeared in .job. Imp: name */
unsigned c;
inline bool isEOL() const { return dictHints==NULLP; }
/** In: dict, dictHints, cache and cacheHints is uninitialized. Out: they
* get inititalized from param. Errors might occur and error messages
* might get printed.
*/
void fromDict(MiniPS::VALUE);
/** Calls info->setSampleFormat(), and sets cacheHints.PredictorColumns
* and some other fields if they are zero (unspecified in the .job file)
*/
void doSampleFormat(Image::SampledInfo *info, bool separate=false);
/** Appends "" when CO_None,
* "<</K ... /Columns ...>>/CCITTFaxDecode filter" when CO_Fax
* "/...Decode filter" otherwise
* Calls appendPredictorSpec() if necessary.
* For PDF (not PS!), implies appendTransferSpec().
*/
void appendDecoderSpec(GenBuffer::Writable &out) const;
/** Appends "" when PR_None or
* appends "<</BitsPerComponent.../Colors.../Columns.../Predictor 2>>" or
* appends "<</BitsPerComponent.../Colors.../Columns.../Predictor 10>>"
* appends "<</K ...>>"
*/
void appendPredictorSpec(GenBuffer::Writable &out) const;
/** Appends "" or "/ASCII85Decode filter" or "/ASCIIHexDecode filter"
*/
void appendTransferSpec(GenBuffer::Writable &out) const;
bool hasPredictorSpec() const;
};
struct Applier {
BEGIN_STATIC_ENUM(unsigned,cons_t)
DONT_KNOW=0, BAD=1, MAYBE=2, OK=3
END_STATIC_ENUM()
/** Checks the specified OutputRule for internal consistency, updates
* the `or->cache', emits warnings, and returns consistency status
* information.
*
* -- If (this) Applier doesn't know how to handle the OutputRule, returns
* DONT_KNOW immediately.
* -- If (this) Applier knows that the OutputRule is internally
* inconsistent or proved to be unsupported (i.e printing JPEG images
* on PostScript Level1 printers), regardless of the image itself, it
* returns BAD immediately and emits a warning about the reason.
* -- If (this) Applier knows that the OutputRule may or may not be
* processed, depending on the actual image, then MAYBE is returned.
* -- If (this) Applier knows that the OutputRule can be processed on
* any image, then OK is returned.
*/
typedef cons_t(*check_rule_t)(OutputRule* or_);
/** Outputs (writes) the PostScript or PDF presentation of the image
* specified in param `sf' to the output stream in param `out', using
* the Output Rule specified in param `or'.
* @return DONT_KNOW if doesn't know how to handle the OutputRule;
* BAD if it is sure that the image cannot be written with the
* specified OutputRule;
* OK if writing was successful
*/
typedef cons_t(*work_t)(GenBuffer::Writable& out, OutputRule*or_, Image::SampledInfo *sf);
/** A short, informal description of this Applier. */
char const*format;
check_rule_t check_rule;
/** May be NULLP if `check_rule' never returns OK or MAYBE */
work_t work;
/** Null or next Applier to probe. Filled by register0(); */
Applier *next;
};
/* Registers a new type of output Applier, i.e a new output file
* format/method. The new output format will be put in front of all others,
* and will be checked first by apply_best().
*/
static void register0(Applier*);
/* Loads the image contained in te file `filename'. */
/** Builds the list of available profiles from the Profile element read
* from a .job file. To do the task, calls check_rule() of all registered (!)
* Appliers. Also calls OutputRule::fromDict for each profile element.
* All returned OutputRules have an Applier which returned OK or MAYBE.
* @return a dict==NULLP-terminated list of OutputRules
*/
static OutputRule* buildProfile(MiniPS::VALUE Profile, bool quiet=false);
/** Applies the Profile specified in param `rule_list' to the image
* specified in param `sf', and writes the output to param `out'.
*/
static void applyProfile(GenBuffer::Writable& out, OutputRule*rule_list, Image::SampledInfo *sf);
/** Frees memory associated with a profile returned by buildProfile() */
static void deleteProfile(OutputRule*);
static unsigned printAppliers(GenBuffer::Writable &out);
typedef void (*stream_writer_t)(GenBuffer::Writable&out, GenBuffer::Writable&outstream, Image::SampledInfo *sf);
/** Writes a PS/PDF file to `out' according to `template_': substitutes
* actual image (pixel) data from `sf->getImg()', and substitutes image
* metadata from `sf'. `outstream' should be a prepared stream (top of chain
* of Encode filters).
* See a .tte file for an example template.
*/
static void writeTTE(
GenBuffer::Writable& out,
GenBuffer::Writable& outpal,
GenBuffer::Writable& outstream,
char const*template_,
Rule::OutputRule*or_,
Image::SampledInfo *sf,
stream_writer_t stream_writer,
char const*const*strings=(char**)NULLP);
/** Doesn't invoke MiniPS::delete0(chunkArray); */
static void writeTTM(
Filter::VerbatimE &outve,
GenBuffer::Writable&outpal,
GenBuffer::Writable&outstream,
MiniPS::Array *chunkArray,
Rule::OutputRule*or_,
Image::SampledInfo *sf,
stream_writer_t stream_writer,
char const*const*strings=(char**)NULLP);
/** Used by writeTTT() to find template specification by name */
static MiniPS::Dict* Templates;
/** @param out must be of type Filter::VerbatimE if the template is a TTM
* array.
* @param template_key a key in file bts.ttt
*/
static void writeTTT(
GenBuffer::Writable&out,
GenBuffer::Writable&outpal,
GenBuffer::Writable&outstream,
char const *template_key,
Rule::OutputRule*or_,
Image::SampledInfo *sf,
stream_writer_t stream_writer,
char const*const*strings=(char**)NULLP);
static void writeData(GenBuffer::Writable& out, GenBuffer::Writable&outstream, Image::SampledInfo *sf);
static void writePalData(GenBuffer::Writable& out, GenBuffer::Writable&outstream, Image::SampledInfo *sf);
};
#endif