~ubuntu-branches/ubuntu/trusty/grfcodec/trusty

« back to all changes in this revision

Viewing changes to src/pcxsprit.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Matthijs Kooijman
  • Date: 2010-08-23 14:45:52 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100823144552-4qggmf9izixsw8li
Tags: 1.0.0+debian1-1
* [30caa6a] Repackaged upstream source, to remove a duplicate file (which
  the lenny version of tar --keep-old-files doesn't like.
* [331d12b] Update watch file to upstream's new versioning scheme.
* [28b6b51] Mangle the +debian suffix in the watch file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include "pcxsprit.h"
 
3
#include "ttdpal.h"
 
4
#include "grfcomm.h"
 
5
 
 
6
extern bool _mapAll,_hexspritenums;
 
7
 
 
8
/***********************\
 
9
*                                               *
 
10
* class pcxwrite                *
 
11
*                                               *
 
12
\***********************/
 
13
 
 
14
// to make this a bit more readable, use binary digits instead of hex
 
15
#define b____ 0
 
16
#define b___O 1
 
17
#define b__O_ 2
 
18
#define b__OO 3
 
19
#define b_O__ 4
 
20
#define b_O_O 5
 
21
#define b_OO_ 6
 
22
#define b_OOO 7
 
23
#define bO___ 8
 
24
#define bO__O 9
 
25
#define bO_O_ 10
 
26
#define bO_OO 11
 
27
#define bOO__ 12
 
28
#define bOO_O 13
 
29
#define bOOO_ 14
 
30
#define bOOOO 15
 
31
 
 
32
 
 
33
#define _(o,t) ((b ## t << 4) + b ## o)
 
34
 
 
35
#define DIGITHEIGHT 5
 
36
#define DIGITWIDTH 4
 
37
// DIGITHEIGHT*DIGITWIDTH*16(digits)/8(bitsperbyte) = 40 bytes
 
38
#define DIGITIND(digit,line) (digit/2+8*line)
 
39
#define DIGITSHR(digit) (4*(digit&1))
 
40
static unsigned char digitlines[40] = {
 
41
 
 
42
_( _OO_, __O_ ),_( OOO_, OOO_ ),_( __O_, OOOO),_( _OO_, OOOO),_( _OO_, _OO_ ), _( _OO_, OOO_ ), _( _OOO, OOO_ ), _( OOOO, OOOO ),
 
43
_( O__O, _OO_ ),_( ___O, ___O ),_( _OO_, O___),_( O___, ___O),_( O__O, O__O ), _( O__O, O__O ), _( O___, O__O ), _( O___, O___ ),
 
44
_( O__O, __O_ ),_( _OO_, _OO_ ),_( O_O_, OOO_),_( OOOO, __O_),_( _OO_, _OOO ), _( OOOO, OOO_ ), _( O___, O__O ), _( OOO_, OOO_ ),
 
45
_( O__O, __O_ ),_( O___, ___O ),_( OOOO, ___O),_( O__O, _O__),_( O__O, ___O ), _( O__O, O__O ), _( O___, O__O ), _( O___, O___ ),
 
46
_( _OO_, _OOO ),_( OOOO, OOO_ ),_( __O_, OOO_),_( _OO_, _O__),_( _OO_, _OO_ ), _( O__O, OOO_ ), _( _OOO, OOO_ ), _( OOOO, O___ ),
 
47
 
 
48
};
 
49
#undef _
 
50
 
 
51
 
 
52
pcxwrite::pcxwrite(multifile *mfile)
 
53
{
 
54
        setfile(mfile);
 
55
        spriteno=-1;    // so the first one will be 0
 
56
        lastdigitx = -50;
 
57
}
 
58
 
 
59
void pcxwrite::filedone(int final)
 
60
{
 
61
        int y;
 
62
 
 
63
        if (curfile) {
 
64
                if (final) {
 
65
                        // fill with blank lines to the right height if necessary
 
66
                        for (y=totaly; y<sy; y++) {
 
67
                                startencoding();
 
68
                                encodebytes(background, sx);
 
69
                                endencoding();
 
70
                        }
 
71
 
 
72
                        if (sy != -1)
 
73
                                totaly = sy;
 
74
 
 
75
                }
 
76
 
 
77
                writepal();
 
78
                writeheader();
 
79
                fflush(curfile);
 
80
        }
 
81
}
 
82
 
 
83
void pcxwrite::setcolours(U8 bg, U8 bord, int skip)
 
84
{
 
85
        background = bg;
 
86
        border = bord;
 
87
        borderskip = skip;
 
88
}
 
89
 
 
90
void pcxwrite::startsubimage(int /*x*/, int /*y*/, int sx, int sy)
 
91
{
 
92
#define BORDERSIZE 4
 
93
        int bordersizex = BORDERSIZE;
 
94
        int bordersizey = BORDERSIZE + DIGITHEIGHT + 1;
 
95
 
 
96
        sx += bordersizex;
 
97
        sy += bordersizey;
 
98
 
 
99
        subx += ( (int) (px + bandx) / bandx) * bandx;
 
100
 
 
101
        if (subx + sx >= pcxfile::sx) {
 
102
                newband();
 
103
                lastdigitx = -50;
 
104
        }
 
105
 
 
106
        if (sy > thisbandy) {
 
107
                thisbandy = ( (int) (sy + bandy - 1) / bandy) * bandy;
 
108
                alloclines(thisbandy);
 
109
        }
 
110
 
 
111
        cx = 0;
 
112
        cy = 0;
 
113
 
 
114
        px = sx;// - bordersizex;
 
115
        py = sy;// - bordersizey;
 
116
 
 
117
        dx = 1;
 
118
        dy = 1;
 
119
 
 
120
        if (borderskip) {
 
121
                int i, bx, by;
 
122
                bx = sx - 2;
 
123
                by = sy - 2;
 
124
                for (i=0; i < 2*bx+2*by; i+=borderskip) {
 
125
                        border = i & 8;
 
126
 
 
127
                        if (i < bx)
 
128
                                putpixel(i, 0, border);
 
129
 
 
130
                        else if (i < bx + by)
 
131
                                putpixel(0, i - bx, border);
 
132
 
 
133
                        else if (i < 2*bx + by)
 
134
                                putpixel(i-bx-by, by, border);
 
135
 
 
136
                        else
 
137
                                putpixel(bx, i-2*bx-by, border);
 
138
                }
 
139
        }
 
140
 
 
141
        //  WRONG Y IN NFO FILE !!
 
142
 
 
143
        // show sprite number
 
144
        showspriteno();
 
145
 
 
146
        dx++;
 
147
        dy+=1+DIGITHEIGHT+1;
 
148
}
 
149
 
 
150
void pcxwrite::showspriteno()
 
151
{
 
152
        char spritenum[10];
 
153
        int newlastx;
 
154
        if(_hexspritenums)
 
155
                sprintf(spritenum, "%X", spriteno);
 
156
        else
 
157
                sprintf(spritenum, "%d", spriteno);
 
158
 
 
159
        newlastx = subx+strlen(spritenum)*(DIGITWIDTH+1)+dx;
 
160
        if (newlastx >= pcxfile::sx)
 
161
                return;
 
162
 
 
163
        if (subx+dx < lastdigitx + 2*(DIGITWIDTH+1))
 
164
                return;
 
165
 
 
166
        lastdigitx = newlastx;
 
167
 
 
168
        for (int i=0; spritenum[i]; i++) {
 
169
                int digit = spritenum[i] - '0';
 
170
                if (digit > 9)
 
171
                        digit += '0' - 'A';
 
172
                for (int y=0; y<DIGITHEIGHT; y++) {
 
173
                        int pixels = digitlines[DIGITIND(digit,y)] >> DIGITSHR(digit);
 
174
                        for (int x=DIGITWIDTH-1; x>=0; x--) {
 
175
                                if (pixels & 1)
 
176
                                        putpixel(x + i*(DIGITWIDTH+1),y,border);
 
177
                                pixels >>= 1;
 
178
                        }
 
179
                }
 
180
        }
 
181
}
 
182
 
 
183
void pcxwrite::setline(U8 *band)
 
184
{
 
185
        memset(band, background, sx);
 
186
}
 
187
 
 
188
void pcxwrite::spritedone(int sx, int sy){
 
189
        spritedone();
 
190
 
 
191
        bool maybeGlyph=!_mapAll;
 
192
 
 
193
        for(int cx=0, x=subofsx(cx,0);cx<sx&&maybeGlyph;cx++,x++)
 
194
                for(int cy=0, y=subofsy(cy,0);cy<sy;cy++,y++)
 
195
                        maybeGlyph &= (band[y][x] < 3);
 
196
 
 
197
        if (!maybeGlyph)
 
198
                for(int cx=0, x=subofsx(cx,0);cx<sx;cx++,x++)
 
199
                        for(int cy=0, y=subofsy(cy,0);cy<sy;cy++,y++)
 
200
                                band[y][x] = putcolourmap[band[y][x]];
 
201
}
 
202
 
 
203
void pcxwrite::writeheader()
 
204
{
 
205
        long oldpos = ftell(curfile);
 
206
        fseek(curfile, 0, SEEK_SET);
 
207
 
 
208
        header.window[3] = totaly - 1;
 
209
        header.screen[1] = totaly - 1;
 
210
 
 
211
        #ifdef __BIG_ENDIAN__
 
212
                pcxheader le_header = header;
 
213
                be_swapheader(le_header);
 
214
        #else
 
215
                pcxheader& le_header = header;
 
216
        #endif
 
217
        cfwrite("writing pcx header", &le_header, sizeof(pcxheader), 1, curfile);
 
218
        fseek(curfile, oldpos, SEEK_SET);
 
219
}
 
220
 
 
221
void pcxwrite::writepal()
 
222
{
 
223
        long oldpos = ftell(curfile);
 
224
 
 
225
        fseek(curfile, 0, SEEK_END);
 
226
 
 
227
        fputc(12, curfile);
 
228
        cfwrite("writing palette", palette, 768, 1, curfile);
 
229
 
 
230
        fseek(curfile, oldpos, SEEK_SET);
 
231
}
 
232
 
 
233
void pcxwrite::setpalette(const U8 *palette)
 
234
{
 
235
        pcxwrite::palette = palette;
 
236
}
 
237
 
 
238
/*void pcxwrite::setpalette(FILE *palfile)
 
239
{
 
240
        cfread(palette, 1, 768, palfile);
 
241
}*/
 
242
 
 
243
 
 
244
/***********************\
 
245
*                                               *
 
246
* class pcxread                 *
 
247
*                                               *
 
248
\***********************/
 
249
 
 
250
pcxread::pcxread(singlefile *mfile)
 
251
{
 
252
        setfile(mfile);
 
253
};
 
254
 
 
255
void pcxread::startsubimage(int x, int y, int sx, int sy)
 
256
{
 
257
        subx = x;
 
258
 
 
259
        if (y + sy > pcxread::sy) {
 
260
                printf("\nError: Sprite y extends beyond end of PCX file.\nFile has %d lines, sprite wants %d..%d\n.",
 
261
                        pcxread::sy, y, y + sy - 1);
 
262
                exit(2);
 
263
        }
 
264
 
 
265
        if (sy > bandlines) {   // don't have enough lines in memory, read rest
 
266
                alloclines(sy);
 
267
        }
 
268
 
 
269
        if (y > totaly) {       // doesn't start right at the top -> delete extra lines
 
270
                expirelines(y - totaly);
 
271
                totaly = y;
 
272
        }
 
273
 
 
274
        cx = 0;
 
275
        cy = 0;
 
276
 
 
277
        px = sx;
 
278
        py = sy;
 
279
 
 
280
        dx = 0;
 
281
        dy = 0;
 
282
}
 
283
 
 
284
void pcxread::setline(U8 *band)
 
285
{
 
286
        startdecoding();
 
287
 
 
288
        decodebytes(band, sx);
 
289
}
 
290
 
 
291
extern bool _force;
 
292
extern int _quiet;
 
293
 
 
294
void pcxread::readheader()
 
295
{
 
296
        long oldpos = ftell(curfile);
 
297
        fseek(curfile, 0, SEEK_SET);
 
298
 
 
299
        cfread("reading pcx header", &header, sizeof(pcxheader), 1, curfile);
 
300
        be_swapheader(header);
 
301
 
 
302
        if (header.nplanes == 3) {
 
303
                fprintf(stderr, "Cannot read truecolour PCX files!\n");
 
304
                exit(2);
 
305
        }
 
306
        if ( (header.bpp != 8) || (header.nplanes != 1) ) {
 
307
                fprintf(stderr, "PCX file is not a 256 colour file!\n");
 
308
                exit(2);
 
309
        }
 
310
 
 
311
        fseek(curfile,-768,SEEK_END);
 
312
        U8 palette[768];
 
313
 
 
314
        if (fread(palette,1,768,curfile) != 768 ) {
 
315
                fprintf(stderr, "Could not read palette from PCX file!\n");
 
316
                exit(2);
 
317
        }
 
318
 
 
319
        int i=0;
 
320
        for(;i<NUM_PALS;i++)
 
321
                if(!memcmp(palette,defaultpalettes[i],768)) break;
 
322
 
 
323
        if ( i == NUM_PALS ) {
 
324
                if ( _force ) {
 
325
                        if (!_quiet) fprintf(stderr, "Warning: Encoding despite unrecognized palette.\n");
 
326
                } else {
 
327
                        fprintf(stderr, "Error: Unrecognized palette, aborting.\n"
 
328
                                "Specify -f on the command line to override this check.\n");
 
329
                        exit(2);
 
330
                }
 
331
        }
 
332
 
 
333
        fseek(curfile, oldpos, SEEK_SET);
 
334
 
 
335
        /* header.bpl is number of bytes per scanline.
 
336
         * header.window[2] - header.window[0] + 1 is number of bytes actually used.
 
337
         * The original ZSoft standard defines header.bpl to be always even, so there may be unused bytes.
 
338
         * However, more modern software (e.g. gimp) do not care about that and do not waste any bytes. */
 
339
        sx = header.bpl;
 
340
        sy = header.window[3] - header.window[1] + 1;
 
341
        totaly = 0;
 
342
 
 
343
        thisbandy = 0;
 
344
}
 
345