summaryrefslogtreecommitdiff
path: root/graphics/sam2p/rule.hpp
blob: 7dcf3cd4a0b1c334eb79fdbce7db8692802a28d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
/* rule.hpp -- Output rules
 * by pts@fazekas.hu 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