summaryrefslogtreecommitdiff
path: root/dviware/dvi2bitmap/PkFont.h
blob: cac4e0c18af6a70417681e4c97a4d8c054027a1b (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
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
/* This file is part of dvi2bitmap; see README for copyrights and licence */

#ifndef PK_FONT_HEADER_READ
#define PK_FONT_HEADER_READ 1

#include <config.h>

#include <string>
// We only need to include <ostream> here, but <iostream> is on more machines
#include <iostream>
#include <FileByteStream.h>
#include <Byte.h>
#include <DviError.h>
#include <verbosity.h>

/** A PK font */
class PkFont;

class PkError : public DviError {
 public:
    PkError(string s) : DviError(s) { }
};

class PkRasterdata {
 public:
    PkRasterdata(Byte opcode,
		 const Byte *rasterdata, unsigned int len,
		 unsigned int w, unsigned int h);
    /**
     * Returns the bitmap corresponding to the input rasterdata
     *
     * @return the bitmap, as an array of size <code>[0..w-1][0..h-1]</code>
     */
    const Byte *bitmap()
	{ if (bitmap_ == 0) construct_bitmap(); return bitmap_; }
    /**
     * Sets the verbosity of this module.
     * @param level the required verbosity
     * @return the previous verbosity level
     */
    static verbosities verbosity (const verbosities level) {
	enum verbosities oldv = verbosity_;
	verbosity_ = level;
	return oldv;
    }
 private:
    Byte *rasterdata_, *eob_;
    const unsigned int len_, w_, h_;
    Byte dyn_f_;
    bool start_black_;
    Byte *bitmap_;
    bool highnybble_;
    unsigned int repeatcount_;
    unsigned int unpackpk();
    Byte nybble();
    void construct_bitmap ();
    static verbosities verbosity_;
};

class PkGlyph {
 public:
    PkGlyph(unsigned int cc,
	    unsigned int tfmwidth,  unsigned int dm,
	    unsigned int w, unsigned int h,
	    int hoff, int voff,
	    PkRasterdata *rasterdata, PkFont *f);
    PkGlyph(unsigned int cc,
	    unsigned int tfmwidth, unsigned int dx, unsigned int dy,
	    unsigned int w, unsigned int h,
	    int hoff, int voff,
	    PkRasterdata *rasterdata, PkFont *f);
    PkGlyph(int resolution, PkFont *f);
    /**
     * The character code for this glyph
     */
    inline unsigned int characterCode() const { return cc_; }
    /**
     * The character which this glyph represents.
     * @return the (ASCII) printable character which this glyph
     * purports to represent
     */
    inline char characterChar() const
	{ return (cc_ >= ' ' && cc_ < 127 
		  ? static_cast<char>(cc_) : '?'); }

    const Byte *bitmap();
    /**
     * Width of this character.  This is the row-length of the bitmap
     * returned by method <code>bitmap()</code>
     * @return width in device units (ie, pixels)
     */
    inline unsigned int w() const { return w_; }
    /**
     * Height of this character.  This is the number of columns in the bitmap
     * returned by method <code>bitmap()</code>
     * @return height in device units (ie, pixels)
     */
    inline unsigned int h() const { return h_; }
    /**
     * Obtains the horizontal offset of the first
     * pixel of the bitmap from the reference point for this glyph,
     * with positive numbers indicating a rightward offset.  This is
     * the negative of the horizontal offset of the
     * reference point from the bitmap, as discussed in {@link
     * #PkGlyph the constructor}.
     *
     * @return the offset (in pixels, with right being positive)
     */
    inline int hoff() const { return -hoff_; }
    /**
     * Obtains the vertical offset of the first
     * pixel of the bitmap from the reference point for this glyph,
     * with positive numbers indicating a downward offset (which is
     * rather rare, since the reference point is generally near the
     * lower-left corner of the glyph).
     * This is the negative of the vertical offset of the
     * reference point from the bitmap, as discussed in {@link
     * #PkGlyph the constructor}.
     *
     * @return the offset (in pixels, with down being positive)
     */
    inline int voff() const { return -voff_; }
    /**
     * The glyph's width.
     * @return the glyph's width in points
     */
    double tfmWidth() const { return tfmwidth_; }
    /**
     * The glyph's horizontal escapement
     * @return the escapement in pixels
     */
    int hEscapement() const { return dx_; }
    /**
     * The glyph's vertical escapement
     * @return the escapement in pixels
     */
    int vEscapement() const { return dy_; }
    /**
     * Sets the verbosity of this module.
     * @param level the required verbosity
     * @return the previous verbosity level
     */
    static verbosities verbosity (const verbosities level) {
	enum verbosities oldv = verbosity_;
	verbosity_ = level; 
	return oldv;
    }

 private:
    unsigned int cc_, dx_, dy_, w_, h_;
    double tfmwidth_;
    int hoff_, voff_;
    PkFont *font_;
    PkRasterdata *rasterdata_;
    bool longform_;
    const Byte *bitmap_;
    static verbosities verbosity_;
    static const int two20_ = 1048576;	// 2^20
    static const int two16_ = 65536; // 2^16
};

class PkFont {
 public:
    PkFont (double fontmag,
	    unsigned int c,
	    unsigned int s,
	    unsigned int d,
	    string name);
    ~PkFont();
    /**
     * Returns the glyph at a given position in this font.  If the
     * font has not been loaded, it returns a dummy glyph.
     * @return the numbered glyph from the font
     */
    PkGlyph *glyph (unsigned int i) const {
	if (font_loaded_)
	{
	    if (i > nglyphs_)
		throw DviBug ("requested out-of-range glyph");
	    return glyphs_[i];
	}
	else
	    return glyphs_[0];	// dummy glyph
    }
    static verbosities verbosity (const verbosities level);
    // setFontPath: specify path to search for fonts.  If argument is
    // null or zero length, simple enable this.
    static void setFontSearchPath(string fp);
    static void setFontSearchPath(char  *fp);
    static void setFontSearchPath(bool yesno);
    // setFontSearchCommand: set the command to use to search for
    // fonts.  If argument is null or zero length, simply enable this,
    // using the compiled-in default.
    static void setFontSearchCommand(string cmd);
    static void setFontSearchCommand(char* cmd);
    static void setFontSearchCommand(bool yesno);
    static void setFontSearchKpse(bool yesno);
    /**
     * Sets the base font resolution.  This must be consistent with
     * the the Metafont mode set by {@link #setMissingFontMode}, if
     * font-generation is to work.
     * @param res the new font resolution
     * @see #dpiBase
     */
    static void setResolution(int res) { resolution_ = res; }
    /**
     * Sets the Metafont mode to be used when generating fonts.  This
     * must be consistent with any base font resolution set in {@link
     * #setResolution}.
     * @param mode a Metafont mode
     */
    static void setMissingFontMode(string mode) { missingFontMode_ = mode; }
    // Ought I to rationalise setMakeFonts, so that this looks more
    // like the interface of setFontSearchCommand()?  Not really,
    // since it's possible in principle that there could be more than
    // just this command-based way of making fonts.
    static void setFontgen(bool doit);
    static void setFontgenCommand(string command_template);
    string fontgenCommand() const;
    /**
     * Identifies the current font
     * @return the font's name
     */
    string name() const { return name_; }
    /**
     * Locates the current font's bitmap file
     * @return theh path to the PK file which defines this font
     */
    string fontFilename() const { return path_; }
    double magnification(bool includeDviMag=true) const;
    /**
     * Obtains the base font resolution, in dots-per-inch.  This is
     * the base resolution corresponding to the Metafont mode set by
     * {@link #setMissingFontMode}, and the two must be consistent if
     * font-generation is to work.
     * @return the font resolution, in dots-per-inch
     * @see #setResolution
     */
    static int dpiBase() { return resolution_; }
    /**
     * Obtains the resolution of the current font, taking
     * magnification into account
     * @return the font's resolution, in dots-per-inch
     */
    int dpiScaled() const {
	return static_cast<int>(resolution_
				* magnification()
				+ 0.5);
    }
    /**
     * Obtains the font's scale.  This is the factor <em>s/d</em>,
     * where <em>s</em> and <em>d</em> are the font scale and font
     * design size as specified when the font was declared in the DVI
     * file.  Together, they specify that the font is to be used at
     * <em>magnification/1000 . s/d</em> times its design size.  This
     * is distinct from the return value of {@link #magnification},
     * which takes DVI file magnification into account, and which is
     * therefore more useful in general.
     *
     * @return the font scale, s/d
     */
    double scale() const {
	return (double)font_header_.s / (double)font_header_.d;
    }
    /**
     * Has the current font been declared in the document so far, or
     * just in the DVI file postamble.
     * @return true if we have seen a fnt_def declaration for this
     * font, in the DVI file body
     */
    bool seenInDoc(void) const { return seen_in_doc_; }
    void setSeenInDoc(void) { seen_in_doc_ = true; }

    /**
     * Obtains the size of the <code>word_space</code> parameter for this font.
     * This does <em>not</em> include any overall DVI magnification.
     * @return <code>word_space</code> in DVI units
     */
    double wordSpace() const { return word_space_; }
    /**
     * Obtains the size of the <code>back_space</code> parameter for this font.
     * This does <em>not</em> include any overall DVI magnification.
     * @return <code>back_space</code> in DVI units
     */
    double backSpace() const { return back_space_; }
    /**
     * Obtains the size of the <code>quad</code> parameter for this font.
     * This does <em>not</em> include any overall DVI magnification.
     * @return <code>quad</code> in DVI units
     */
    double quad() const { return quad_; }

    // No need to check font_loaded_ in these next three, since these
    // are never called between the font being created and preamble_
    // being filled in.
    /**
     * Obtains the design size of this font, as obtained from the PK
     * file preamble.
     * @return the design size in points
     */
    double designSize() const {	return preamble_.designSize; }
    /**
     * Obtains the number of horizontal pixels per point for this
     * font, as obtained from the PK file preamble.
     * @return the hppp parameter in points
     */
    double hppp() const { return preamble_.hppp; }
    /**
     * Obtains the number of vertical pixels per point for this
     * font, as obtained from the PK file preamble.
     * @return the vppp parameter in points
     */
    double vppp() const { return preamble_.vppp; }
    /**
     * Obtains the font checksum, as obtained from the PK file preamble.
     * @return checksum
     */
    unsigned int checksum() const { return preamble_.cs; }
    /**
     * Check if the font has actually been loaded.  This is false
     * if the font was declared in the DVI file, but its bitmaps were
     * not or cound not be loaded from disk for some reason.
     * @return true if the font was successfully read from disk
     */
    bool loaded() const { return font_loaded_; }

    static string& substitute_font_string (const string fmt,
					   const string mode, 
					   const string fontname,
					   const int dpi,
					   const int basedpi,
					   const double magnification)
	throw (PkError);


 private:
    static const unsigned int nglyphs_ = 256;
    static const unsigned int two20_ = 1048576; // 2^20
    static const unsigned int two16_ = 65536; // 2^16

    string name_;
    string path_;		/* name of (tbd) file containing font */
    FileByteStream *pkf_;
    bool font_loaded_;		/* font loaded successfully */
    struct {
	unsigned int c;		/* font checksum */
	unsigned int s;		/* fixed-point scale factor, in DVI units */
	unsigned int d;		/* `design size', in DVI units */
    } font_header_;		/* this is the information retrieved
				   from the font declaration */
    double dvimag_;		/* Magnification imposed by DVI file (1.0 = no mag) */
    struct {
	unsigned int id, cs;
	double designSize, hppp, vppp;
	string comment;
    } preamble_;
    //double fontscale_;
    // following are in DVI units
    double quad_, word_space_, back_space_;
    PkGlyph *glyphs_[nglyphs_];
    bool find_font (string&);
    void read_font(InputByteStream&);

    /* Search the given path for a font.  Not static, so that it can
       see the current font's parameters. */
    string& search_pkpath (string path,
			   string name, double resolution);

    bool seen_in_doc_;		// true once the font_def command has been
    				// seen in the document, as well as the
    				// postamble
    static verbosities verbosity_;
    static string fontSearchPath_;	// colon-separated list of directories
    static string fontSearchCommandTemplate_; // command to find fonts
    static string fontgenCommandTemplate_; // command to generate fonts
    static void setFontSearchStrategy_(unsigned int, bool);
    static unsigned int fontSearchStrategies_; // ways to find fonts: flags:
    static const unsigned int fontSearchStrategyPath_ = 1;
    static const unsigned int fontSearchStrategyKpse_ = 2;
    static const unsigned int fontSearchStrategyCommand_ = 4;

    static int resolution_;	// base resolution for MF mode
    static bool makeMissingFonts_;	// automatically make fonts
    static string missingFontMode_;
};

#endif // #ifndef PK_FONT_HEADER_READ