1 /* rule.hpp -- Output rules
2  * by pts@fazekas.hu Fri Mar 15 15:11:38 CET 2002
3  */
4 
5 #ifdef __GNUC__
6 #ifndef __clang__
7 #pragma interface
8 #endif
9 #endif
10 
11 #ifndef RULE_HPP
12 #define RULE_HPP 1
13 
14 #include "config2.h"
15 #include "gensio.hpp"
16 #include "image.hpp"
17 #include "minips.hpp"
18 
19 /** a namespace */
20 class Rule { public:
21   struct Cache {
22     bool WarningOK;
23     BEGIN_STATIC_ENUM(unsigned char,ff_t)
24       FF_default=0, /* only for one-liner */
25       FF_eps=71, /* only for one-liner, temporary */
26       FF_pdf=72, /* only for one-liner, temporary */
27       FF_pdfb=73, /* only for one-liner, temporary */
28       FF_PSL1=110,
29       FF_PSLC=115,
30       FF_PSL2=120,
31       FF_PSL3=130,
32       FF_PDFB10=90,
33       FF_PDFB12=92,
34       FF_PDF10=80,
35       FF_PDF12=82,
36       FF_GIF89a=1,
37       FF_PNM=2,
38       FF_PAM=3,
39       FF_PIP=4, /* Portable Indexed file format by pts */
40       FF_Empty=5,
41       FF_Meta=6,
42       FF_JPEG=7,
43       FF_TIFF=8,
44       FF_PNG=9,
45       FF_XPM=10,
46       FF_BMP=11,
47       FF_XWD=12,
48       FF_X11=13  /* Don't add a comma, gcc-4.8.1. can't compile it that way. */
49     END_STATIC_ENUM()
50     ff_t FileFormat;
51     Image::sf_t SampleFormat;
52     /** Used only in appliers.cpp when _check_rule() changes SampleFormat so
53      * setSampleFormat() called before _work() would set that dummy
54      * SampleFormat.
55      */
56     Image::sf_t origSampleFormat;
57     BEGIN_STATIC_ENUM(unsigned char,te_t)
58       TE_default=0, /* only for one-liner */
59       TE_Binary=1,
60       TE_ASCII=2,
61       TE_Hex=3,
62       TE_A85=4,
63       TE_MSBfirst=5,
64       TE_LSBfirst=6
65     END_STATIC_ENUM()
66     te_t TransferEncoding;
67 
68     BEGIN_STATIC_ENUM(unsigned char,co_t)
69       CO_default=0, /* only for one-liner */
70       CO_None=1,
71       CO_LZW=2,
72       CO_ZIP=3,
73       CO_RLE=4,
74       CO_Fax=5,
75       CO_DCT=6,
76       CO_IJG=7,
77       CO_JAI=8,
78       CO_max=8
79     END_STATIC_ENUM()
80     co_t Compression;
81 
82     BEGIN_STATIC_ENUM(unsigned char,pr_t)
83       PR_None=1,
84       PR_TIFF2=2,
85       PR_PNGNone=10, PR_PNG=10,
86       PR_PNGSub=11,
87       PR_PNGUP=12,
88       PR_PNGAverage=13,
89       PR_PNGPaeth=14,
90       PR_PNGAuto=15,
91       PR_PNGAutoMaybe=25,
92       PR_PNGAutoBadUnsigned=45,
93       PR_PNGAutoBadSigned=55
94     END_STATIC_ENUM()
95     pr_t Predictor;
96 
97     Image::Sampled::rgb_t Transparent;
98 
99     bool isOneBit() const;
100     bool isPDF() const;
101     bool isPDFB() const;
102     bool isPS() const;
103     bool isPSL2() const;
104     bool isPSL3() const;
105     bool hasPredictor() const;
106     bool isIndexed() const;
107     bool isTransparentM() const;
108     bool isGray() const;
109     bool isRGB() const;
110     bool isDCTE() const;
111     bool isBinSB() const;
112     /** /Compression/ZIP not OK with /PSL1, /PSLC, /PSL2, /PDF10, /PDFB10 */
113     bool isZIPOK() const;
114     // bool is8() const;
115 
116     /** @param s is case insensitive, leading `/' is optional.
117      * @return SF_max if not found, or a valid SF_... constant
118      */
119     static Image::sf_t parseSampleFormat(char const*s, slen_t slen);
120     static char const* dumpFileFormat(ff_t FileFormat, co_t Compression=CO_default);
121     static char const* dumpTransferEncoding(te_t TransferEncoding);
122     static char const* dumpSampleFormat(Image::sf_t SampleFormat);
123     static char const* dumpCompression(co_t Compression);
124   };
125 
126   struct CacheHints {
127     BEGIN_STATIC_ENUM(unsigned char,sc_t) /* Fri Aug 16 16:33:47 CEST 2002 */
128       SC_default=0,
129       SC_None=1,
130       SC_OK=2,
131       SC_RotateOK=3
132     END_STATIC_ENUM()
133     sc_t Scale;
134 
135     /* Image dimensions for encoding filters (may be different from real
136      * image dimensions, but _really_ disrecommended).
137      * slen_t important becasuse of separate().
138      */
139     slen_t EncoderColumns, EncoderBPL, EncoderRows;
140     /** Number of color components (channels) per pixel. */
141     unsigned char EncoderColors;
142     slen_t PredictorColumns;
143     unsigned char PredictorBPC, PredictorColors;
144     unsigned ColorTransform;
145     signed Effort;
146     slen_t RecordSize;
147     slendiff_t K;
148     /* JPEG quality for the IJG encoding filter */
149     unsigned char Quality;
150     unsigned TransferCPL;
151     MiniPS::String *Comment, *Title, *Subject, *Author, *Creator, *Producer;
152     MiniPS::String *Created, *Produced;
153     MiniPS::Dict *DCT;
154     /** MiniPS::Real* or integer */
155     MiniPS::VALUE TopMargin, BottomMargin, LeftMargin, RightMargin;
156     /** MiniPS::Real* or integer. Specifies the dimension the image should
157      * be lowered below the baseline for (PostScript or PDF) output with
158      * /Scale/None. Default to 0.
159      */
160     MiniPS::VALUE LowerMargin;
161     /** 72 by default. */
162     MiniPS::VALUE ImageDPI;
163     static char const* dumpScale(sc_t Scale);
164   };
165 
166   struct OutputRule {
167     Cache cache;
168     CacheHints cacheHints;
169     MiniPS::Dict* dict;
170     /* /Hints entry in dict */
171     MiniPS::Dict* dictHints;
172     /* Number of this output rule, as appeared in .job. Imp: name */
173     unsigned c;
isEOLRule::OutputRule174     inline bool isEOL() const { return dictHints==NULLP; }
175     /** In: dict, dictHints, cache and cacheHints is uninitialized. Out: they
176      * get inititalized from param. Errors might occur and error messages
177      * might get printed.
178      */
179     void fromDict(MiniPS::VALUE);
180     /** Calls info->setSampleFormat(), and sets cacheHints.PredictorColumns
181      * and some other fields if they are zero (unspecified in the .job file)
182      */
183     void doSampleFormat(Image::SampledInfo *info, bool separate=false);
184     /** Appends "" when CO_None,
185      * "<</K ... /Columns ...>>/CCITTFaxDecode filter" when CO_Fax
186      * "/...Decode filter" otherwise
187      * Calls appendPredictorSpec() if necessary.
188      * For PDF (not PS!), implies appendTransferSpec().
189      */
190     void appendDecoderSpec(GenBuffer::Writable &out) const;
191     /** Appends "" when PR_None or
192      * appends "<</BitsPerComponent.../Colors.../Columns.../Predictor 2>>" or
193      * appends "<</BitsPerComponent.../Colors.../Columns.../Predictor 10>>"
194      * appends "<</K ...>>"
195      */
196     void appendPredictorSpec(GenBuffer::Writable &out) const;
197     /** Appends "" or "/ASCII85Decode filter" or "/ASCIIHexDecode filter"
198      */
199     void appendTransferSpec(GenBuffer::Writable &out) const;
200     bool hasPredictorSpec() const;
201   };
202 
203   struct Applier {
204     BEGIN_STATIC_ENUM(unsigned,cons_t)
205       DONT_KNOW=0, BAD=1, MAYBE=2, OK=3
206     END_STATIC_ENUM()
207     /** Checks the specified OutputRule for internal consistency, updates
208      * the `or->cache', emits warnings, and returns consistency status
209      * information.
210      *
211      * -- If (this) Applier doesn't know how to handle the OutputRule, returns
212      *    DONT_KNOW immediately.
213      * -- If (this) Applier knows that the OutputRule is internally
214      *    inconsistent or proved to be unsupported (i.e printing JPEG images
215      *    on PostScript Level1 printers), regardless of the image itself, it
216      *    returns BAD immediately and emits a warning about the reason.
217      * -- If (this) Applier knows that the OutputRule may or may not be
218      *    processed, depending on the actual image, then MAYBE is returned.
219      * -- If (this) Applier knows that the OutputRule can be processed on
220      *    any image, then OK is returned.
221      */
222     typedef cons_t(*check_rule_t)(OutputRule* or_);
223 
224     /** Outputs (writes) the PostScript or PDF presentation of the image
225      * specified in param `sf' to the output stream in param `out', using
226      * the Output Rule specified in param `or'.
227      * @return DONT_KNOW if doesn't know how to handle the OutputRule;
228      *         BAD if it is sure that the image cannot be written with the
229      *             specified OutputRule;
230      *         OK if writing was successful
231      */
232     typedef cons_t(*work_t)(GenBuffer::Writable& out, OutputRule*or_, Image::SampledInfo *sf);
233 
234     /** A short, informal description of this Applier. */
235     char const*format;
236     check_rule_t check_rule;
237     /** May be NULLP if `check_rule' never returns OK or MAYBE */
238     work_t work;
239     /** Null or next Applier to probe. Filled by register0(); */
240     Applier *next;
241   };
242 
243   /* Registers a new type of output Applier, i.e a new output file
244    * format/method. The new output format will be put in front of all others,
245    * and will be checked first by apply_best().
246    */
247   static void register0(Applier*);
248   /* Loads the image contained in te file `filename'. */
249 
250   /** Builds the list of available profiles from the Profile element read
251    * from a .job file. To do the task, calls check_rule() of all registered (!)
252    * Appliers. Also calls OutputRule::fromDict for each profile element.
253    * All returned OutputRules have an Applier which returned OK or MAYBE.
254    * @return a dict==NULLP-terminated list of OutputRules
255    */
256   static OutputRule* buildProfile(MiniPS::VALUE Profile, bool quiet=false);
257 
258   /** Applies the Profile specified in param `rule_list' to the image
259    * specified in param `sf', and writes the output to param `out'.
260    */
261   static void applyProfile(GenBuffer::Writable& out, OutputRule*rule_list, Image::SampledInfo *sf);
262 
263   /** Frees memory associated with a profile returned by buildProfile() */
264   static void deleteProfile(OutputRule*);
265 
266   static unsigned printAppliers(GenBuffer::Writable &out);
267 
268 
269   typedef void (*stream_writer_t)(GenBuffer::Writable&out, GenBuffer::Writable&outstream, Image::SampledInfo *sf);
270 
271   /** Writes a PS/PDF file to `out' according to `template_': substitutes
272    * actual image (pixel) data from `sf->getImg()', and substitutes image
273    * metadata from `sf'. `outstream' should be a prepared stream (top of chain
274    * of Encode filters).
275    *   See a .tte file for an example template.
276    */
277   static void writeTTE(
278     GenBuffer::Writable& out,
279     GenBuffer::Writable& outpal,
280     GenBuffer::Writable& outstream,
281     char const*template_,
282     Rule::OutputRule*or_,
283     Image::SampledInfo *sf,
284     stream_writer_t stream_writer,
285     char const*const*strings=(char**)NULLP);
286 
287   /** Doesn't invoke MiniPS::delete0(chunkArray); */
288   static void writeTTM(
289    Filter::VerbatimE &outve,
290    GenBuffer::Writable&outpal,
291    GenBuffer::Writable&outstream,
292    MiniPS::Array *chunkArray,
293    Rule::OutputRule*or_,
294    Image::SampledInfo *sf,
295    stream_writer_t stream_writer,
296    char const*const*strings=(char**)NULLP);
297 
298   /** Used by writeTTT() to find template specification by name */
299   static MiniPS::Dict* Templates;
300   /** @param out must be of type Filter::VerbatimE if the template is a TTM
301    * array.
302    * @param template_key a key in file bts.ttt
303    */
304   static void writeTTT(
305    GenBuffer::Writable&out,
306    GenBuffer::Writable&outpal,
307    GenBuffer::Writable&outstream,
308    char const *template_key,
309    Rule::OutputRule*or_,
310    Image::SampledInfo *sf,
311    stream_writer_t stream_writer,
312    char const*const*strings=(char**)NULLP);
313 
314   static void writeData(GenBuffer::Writable& out, GenBuffer::Writable&outstream, Image::SampledInfo *sf);
315   static void writePalData(GenBuffer::Writable& out, GenBuffer::Writable&outstream, Image::SampledInfo *sf);
316 
317 };
318 
319 #endif
320