Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3584 sourcerer 1
/*
2
 * Copyright 2009 Vincent Sanders 
3
 *
4
 * This file is part of libnsfb, http://www.netsurf-browser.org/
5
 * Licenced under the MIT License,
6
 *                http://www.opensource.org/licenses/mit-license.php
7
 */
8
 
9
#include 
10
#include 
11
#include 
12
 
13
#include "libnsfb.h"
14
#include "libnsfb_plot.h"
15
#include "libnsfb_plot_util.h"
16
 
17
#include "nsfb.h"
18
#include "plot.h"
19
 
20
static inline uint8_t *
21
get_xy_loc(nsfb_t *nsfb, int x, int y)
22
{
23
        return (uint8_t *)(nsfb->ptr + (y * nsfb->linelen) + (x * 3));
24
}
25
 
26
#if __BYTE_ORDER == __BIG_ENDIAN
27
static inline nsfb_colour_t pixel_to_colour(uint8_t pixel)
28
{
29
        return (pixel >> 8) & ~0xFF000000U;
30
}
31
 
32
/* convert a colour value to a 32bpp pixel value ready for screen output */
33
static inline uint32_t colour_to_pixel(nsfb_colour_t c)
34
{
35
        return (c << 8);
36
}
37
#else /* __BYTE_ORDER == __BIG_ENDIAN */
38
static inline nsfb_colour_t pixel_to_colour(uint32_t pixel)
39
{
40
        return ((pixel & 0xFF) << 16) |
41
                ((pixel & 0xFF00)) |
42
                ((pixel & 0xFF0000) >> 16);
43
}
44
 
45
/* convert a colour value to a 32bpp pixel value ready for screen output */
46
static inline uint32_t colour_to_pixel(nsfb_colour_t c)
47
{
48
        return ((c & 0xff0000) >> 16) | (c & 0xff00) | ((c & 0xff) << 16);
49
}
50
#endif
51
 
52
#define SIGN(x)  ((x<0) ?  -1  :  ((x>0) ? 1 : 0))
53
 
54
static bool
55
line(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen)
56
{
57
        int w;
58
        uint32_t ent;
59
        uint32_t *pvideo;
60
        int x, y, i;
61
        int dx, dy, sdy;
62
        int dxabs, dyabs;
63
 
64
        ent = colour_to_pixel(pen->stroke_colour);
65
 
66
        for (;linec > 0; linec--) {
67
 
68
                if (line->y0 == line->y1) {
69
                        /* horizontal line special cased */
70
 
71
                        if (!nsfb_plot_clip_ctx(nsfb, line)) {
72
                                /* line outside clipping */
73
                                line++;
74
                                continue;
75
                        }
76
 
77
                        pvideo = get_xy_loc(nsfb, line->x0, line->y0);
78
 
79
                        w = line->x1 - line->x0;
80
                        while (w-- > 0)
81
                                *(pvideo + w) = ent;
82
 
83
                } else {
84
                        /* standard bresenham line */
85
 
86
                        if (!nsfb_plot_clip_line_ctx(nsfb, line)) {
87
                                /* line outside clipping */
88
                                line++;
89
                                continue;
90
                        }
91
 
92
                        /* the horizontal distance of the line */
93
                        dx = line->x1 - line->x0;
94
                        dxabs = abs (dx);
95
 
96
                        /* the vertical distance of the line */
97
                        dy = line->y1 - line->y0;
98
                        dyabs = abs (dy);
99
 
100
                        sdy = dx ? SIGN(dy) * SIGN(dx) : SIGN(dy);
101
 
102
                        if (dx >= 0)
103
                                pvideo = get_xy_loc(nsfb, line->x0, line->y0);
104
                        else
105
                                pvideo = get_xy_loc(nsfb, line->x1, line->y1);
106
 
107
                        x = dyabs >> 1;
108
                        y = dxabs >> 1;
109
 
110
                        if (dxabs >= dyabs) {
111
                                /* the line is more horizontal than vertical */
112
                                for (i = 0; i < dxabs; i++) {
113
                                        *pvideo = ent;
114
 
115
                                        pvideo++;
116
                                        y += dyabs;
117
                                        if (y >= dxabs) {
118
                                                y -= dxabs;
119
                                                pvideo += sdy * (nsfb->linelen>>2);
120
                                        }
121
                                }
122
                        } else {
123
                                /* the line is more vertical than horizontal */
124
                                for (i = 0; i < dyabs; i++) {
125
                                        *pvideo = ent;
126
                                        pvideo += sdy * (nsfb->linelen >> 2);
127
 
128
                                        x += dxabs;
129
                                        if (x >= dyabs) {
130
                                                x -= dyabs;
131
                                                pvideo++;
132
                                        }
133
                                }
134
                        }
135
 
136
                }
137
                line++;
138
        }
139
        return true;
140
}
141
 
142
 
143
 
144
static bool fill(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t c)
145
{
146
        int w;
147
        uint32_t *pvid;
148
        uint32_t ent;
149
        uint32_t llen;
150
        uint32_t width;
151
        uint32_t height;
152
 
153
        if (!nsfb_plot_clip_ctx(nsfb, rect))
154
                return true; /* fill lies outside current clipping region */
155
 
156
        ent = colour_to_pixel(c);
157
        width = rect->x1 - rect->x0;
158
        height = rect->y1 - rect->y0;
159
        llen = (nsfb->linelen >> 2) - width;
160
 
161
        pvid = get_xy_loc(nsfb, rect->x0, rect->y0);
162
 
163
        while (height-- > 0) {
164
                w = width;
165
                while (w >= 16) {
166
                       *pvid++ = ent; *pvid++ = ent;
167
                       *pvid++ = ent; *pvid++ = ent;
168
                       *pvid++ = ent; *pvid++ = ent;
169
                       *pvid++ = ent; *pvid++ = ent;
170
                       *pvid++ = ent; *pvid++ = ent;
171
                       *pvid++ = ent; *pvid++ = ent;
172
                       *pvid++ = ent; *pvid++ = ent;
173
                       *pvid++ = ent; *pvid++ = ent;
174
                       w-=16;
175
                }
176
                while (w >= 4) {
177
                       *pvid++ = ent; *pvid++ = ent;
178
                       *pvid++ = ent; *pvid++ = ent;
179
                       w-=4;
180
                }
181
                while (w > 0) {
182
                       *pvid++ = ent;
183
                       w--;
184
                }
185
                pvid += llen;
186
        }
187
 
188
        return true;
189
}
190
 
191
 
192
 
193
 
194
static bool point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c)
195
{
196
        uint32_t *pvideo;
197
 
198
        /* check point lies within clipping region */
199
        if ((x < nsfb->clip.x0) ||
200
            (x >= nsfb->clip.x1) ||
201
            (y < nsfb->clip.y0) ||
202
            (y >= nsfb->clip.y1))
203
                return true;
204
 
205
        pvideo = get_xy_loc(nsfb, x, y);
206
 
207
        if ((c & 0xFF000000) != 0) {
208
                if ((c & 0xFF000000) != 0xFF000000) {
209
                        c = nsfb_plot_ablend(c, pixel_to_colour(*pvideo));
210
                }
211
 
212
                *pvideo = colour_to_pixel(c);
213
        }
214
        return true;
215
}
216
 
217
static bool
218
glyph1(nsfb_t *nsfb,
219
       nsfb_bbox_t *loc,
220
       const uint8_t *pixel,
221
       int pitch,
222
       nsfb_colour_t c)
223
{
224
        uint32_t *pvideo;
225
        int xloop, yloop;
226
        int xoff, yoff; /* x and y offset into image */
227
        int x = loc->x0;
228
        int y = loc->y0;
229
        int width = loc->x1 - loc->x0;
230
        int height = loc->y1 - loc->y0;
231
        uint32_t fgcol;
232
        const uint8_t *fntd;
233
        uint8_t row;
234
 
235
        if (!nsfb_plot_clip_ctx(nsfb, loc))
236
                return true;
237
 
238
        if (height > (loc->y1 - loc->y0))
239
                height = (loc->y1 - loc->y0);
240
 
241
        if (width > (loc->x1 - loc->x0))
242
                width = (loc->x1 - loc->x0);
243
 
244
        xoff = loc->x0 - x;
245
        yoff = loc->y0 - y;
246
 
247
        pvideo = get_xy_loc(nsfb, loc->x0, loc->y0);
248
 
249
        fgcol = colour_to_pixel(c);
250
 
251
        for (yloop = yoff; yloop < height; yloop++) {
252
                fntd = pixel + (yloop * (pitch>>3)) + (xoff>>3);
253
                row = (*fntd++) << (xoff & 3);
254
                for (xloop = xoff; xloop < width ; xloop++) {
255
                        if (((xloop % 8) == 0) && (xloop != 0)) {
256
                                row = *fntd++;
257
                        }
258
 
259
                        if ((row & 0x80) != 0) {
260
                                *(pvideo + xloop) = fgcol;
261
                        }
262
                        row = row << 1;
263
 
264
                }
265
 
266
                pvideo += (nsfb->linelen >> 2);
267
        }
268
 
269
        return true;
270
}
271
 
272
static bool
273
glyph8(nsfb_t *nsfb,
274
       nsfb_bbox_t *loc,
275
       const uint8_t *pixel,
276
       int pitch,
277
       nsfb_colour_t c)
278
{
279
        uint32_t *pvideo;
280
        nsfb_colour_t abpixel; /* alphablended pixel */
281
        int xloop, yloop;
282
        int xoff, yoff; /* x and y offset into image */
283
        int x = loc->x0;
284
        int y = loc->y0;
285
        int width = loc->x1 - loc->x0;
286
        int height = loc->y1 - loc->y0;
287
        uint32_t fgcol;
288
 
289
        if (!nsfb_plot_clip_ctx(nsfb, loc))
290
                return true;
291
 
292
        if (height > (loc->y1 - loc->y0))
293
                height = (loc->y1 - loc->y0);
294
 
295
        if (width > (loc->x1 - loc->x0))
296
                width = (loc->x1 - loc->x0);
297
 
298
        xoff = loc->x0 - x;
299
        yoff = loc->y0 - y;
300
 
301
        pvideo = get_xy_loc(nsfb, loc->x0, loc->y0);
302
 
303
        fgcol = c & 0xFFFFFF;
304
 
305
        for (yloop = 0; yloop < height; yloop++) {
306
                for (xloop = 0; xloop < width; xloop++) {
307
                        abpixel = (pixel[((yoff + yloop) * pitch) + xloop + xoff] << 24) | fgcol;
308
                        if ((abpixel & 0xFF000000) != 0) {
309
                                /* pixel is not transparent */
310
                                if ((abpixel & 0xFF000000) != 0xFF000000) {
311
                                        abpixel = nsfb_plot_ablend(abpixel,
312
                                                                   pixel_to_colour(*(pvideo + xloop)));
313
                                }
314
 
315
                                *(pvideo + xloop) = colour_to_pixel(abpixel);
316
                        }
317
                }
318
                pvideo += (nsfb->linelen >> 2);
319
        }
320
 
321
        return true;
322
}
323
 
324
static bool
325
bitmap(nsfb_t *nsfb,
326
       const nsfb_bbox_t *loc,
327
       const nsfb_colour_t *pixel,
328
       int bmp_width,
329
       int bmp_height,
330
       int bmp_stride,
331
       bool alpha)
332
{
333
        uint32_t *pvideo;
334
        nsfb_colour_t abpixel = 0; /* alphablended pixel */
335
        int xloop, yloop;
336
        int xoff, yoff; /* x and y offset into image */
337
        int x = loc->x0;
338
        int y = loc->y0;
339
        int width = loc->x1 - loc->x0;
340
        int height = loc->y1 - loc->y0;
341
        nsfb_bbox_t clipped; /* clipped display */
342
 
343
        /* TODO here we should scale the image from bmp_width to width, for
344
         * now simply crop.
345
         */
346
        if (width > bmp_width)
347
                width = bmp_width;
348
 
349
        if (height > bmp_height)
350
                height = bmp_height;
351
 
352
        /* The part of the scaled image actually displayed is cropped to the
353
         * current context.
354
         */
355
        clipped.x0 = x;
356
        clipped.y0 = y;
357
        clipped.x1 = x + width;
358
        clipped.y1 = y + height;
359
 
360
        if (!nsfb_plot_clip_ctx(nsfb, &clipped)) {
361
                return true;
362
        }
363
 
364
        if (height > (clipped.y1 - clipped.y0))
365
                height = (clipped.y1 - clipped.y0);
366
 
367
        if (width > (clipped.x1 - clipped.x0))
368
                width = (clipped.x1 - clipped.x0);
369
 
370
        xoff = clipped.x0 - x;
371
        yoff = (clipped.y0 - y) * bmp_width;
372
        height = height * bmp_stride + yoff;
373
 
374
        /* plot the image */
375
        pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0);
376
 
377
        if (alpha) {
378
                for (yloop = yoff; yloop < height; yloop += bmp_stride) {
379
                        for (xloop = 0; xloop < width; xloop++) {
380
                                abpixel = pixel[yloop + xloop + xoff];
381
                                if ((abpixel & 0xFF000000) != 0) {
382
                                        if ((abpixel & 0xFF000000) != 0xFF000000) {
383
                                                abpixel = nsfb_plot_ablend(abpixel,
384
                                                                           pixel_to_colour(*(pvideo + xloop)));
385
                                        }
386
 
387
                                        *(pvideo + xloop) = colour_to_pixel(abpixel);
388
                                }
389
                        }
390
                        pvideo += (nsfb->linelen >> 2);
391
                }
392
        } else {
393
                for (yloop = yoff; yloop < height; yloop += bmp_stride) {
394
                        for (xloop = 0; xloop < width; xloop++) {
395
                                abpixel = pixel[yloop + xloop + xoff];
396
                                *(pvideo + xloop) = colour_to_pixel(abpixel);
397
                        }
398
                        pvideo += (nsfb->linelen >> 2);
399
                }
400
        }
401
        return true;
402
}
403
 
404
static bool readrect(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer)
405
{
406
        uint32_t *pvideo;
407
        int xloop, yloop;
408
        int width;
409
 
410
        if (!nsfb_plot_clip_ctx(nsfb, rect)) {
411
                return true;
412
        }
413
 
414
        width = rect->x1 - rect->x0;
415
 
416
        pvideo = get_xy_loc(nsfb, rect->x0, rect->y0);
417
 
418
        for (yloop = rect->y0; yloop < rect->y1; yloop += 1) {
419
                for (xloop = 0; xloop < width; xloop++) {
420
                        *buffer = pixel_to_colour(*(pvideo + xloop));
421
                        buffer++;
422
                }
423
                pvideo += (nsfb->linelen >> 2);
424
        }
425
        return true;
426
}
427
 
428
const nsfb_plotter_fns_t _nsfb_24bpp_plotters = {
429
        .line = line,
430
        .fill = fill,
431
        .point = point,
432
        .bitmap = bitmap,
433
        .glyph8 = glyph8,
434
        .glyph1 = glyph1,
435
        .readrect = readrect,
436
};
437
 
438
/*
439
 * Local Variables:
440
 * c-basic-offset:8
441
 * End:
442
 */