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 2008 Vincent Sanders 
3
 *
4
 * Framebuffer interface
5
 *
6
 * This file is part of NetSurf, http://www.netsurf-browser.org/
7
 *
8
 * NetSurf is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; version 2 of the License.
11
 *
12
 * NetSurf is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program.  If not, see .
19
 */
20
 
21
#include 
22
#include 
23
#include 
24
#include 
25
 
26
#include 
27
#include 
28
#include 
29
#include 
30
 
31
#include "utils/log.h"
32
#include "desktop/browser.h"
33
#include "image/bitmap.h"
34
 
35
#include "framebuffer/gui.h"
36
#include "framebuffer/fbtk.h"
37
#include "framebuffer/framebuffer.h"
38
#include "framebuffer/font.h"
39
 
40
 
41
/* netsurf framebuffer library handle */
42
static nsfb_t *nsfb;
43
 
44
 
45
static bool
46
framebuffer_plot_disc(int x, int y, int radius, const plot_style_t *style)
47
{
48
    nsfb_bbox_t ellipse;
49
    ellipse.x0 = x - radius;
50
    ellipse.y0 = y - radius;
51
    ellipse.x1 = x + radius;
52
    ellipse.y1 = y + radius;
53
 
54
    if (style->fill_type != PLOT_OP_TYPE_NONE) {
55
        nsfb_plot_ellipse_fill(nsfb, &ellipse, style->fill_colour);
56
    }
57
 
58
    if (style->stroke_type != PLOT_OP_TYPE_NONE) {
59
        nsfb_plot_ellipse(nsfb, &ellipse, style->stroke_colour);
60
    }
61
    return true;
62
}
63
 
64
static bool
65
framebuffer_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
66
{
67
    return nsfb_plot_arc(nsfb, x, y, radius, angle1, angle2, style->fill_colour);
68
}
69
 
70
static bool
71
framebuffer_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
72
{
73
    return nsfb_plot_polygon(nsfb, p, n, style->fill_colour);
74
}
75
 
76
 
77
#ifdef FB_USE_FREETYPE
78
static bool
79
framebuffer_plot_text(int x, int y, const char *text, size_t length,
80
		const plot_font_style_t *fstyle)
81
{
82
        uint32_t ucs4;
83
        size_t nxtchr = 0;
84
        FT_Glyph glyph;
85
        FT_BitmapGlyph bglyph;
86
        nsfb_bbox_t loc;
87
 
88
        while (nxtchr < length) {
89
                ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
90
                nxtchr = utf8_next(text, length, nxtchr);
91
 
92
                glyph = fb_getglyph(fstyle, ucs4);
93
                if (glyph == NULL)
94
                        continue;
95
 
96
                if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
97
                        bglyph = (FT_BitmapGlyph)glyph;
98
 
99
                        loc.x0 = x + bglyph->left;
100
                        loc.y0 = y - bglyph->top;
101
                        loc.x1 = loc.x0 + bglyph->bitmap.width;
102
                        loc.y1 = loc.y0 + bglyph->bitmap.rows;
103
 
104
                        /* now, draw to our target surface */
105
                        if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
106
                            nsfb_plot_glyph1(nsfb,
107
                                             &loc,
108
                                             bglyph->bitmap.buffer,
109
                                             bglyph->bitmap.pitch,
110
                                             fstyle->foreground);
111
                        } else {
112
                            nsfb_plot_glyph8(nsfb,
113
                                             &loc,
114
                                             bglyph->bitmap.buffer,
115
                                             bglyph->bitmap.pitch,
116
                                             fstyle->foreground);
117
                        }
118
                }
119
                x += glyph->advance.x >> 16;
120
 
121
        }
122
        return true;
123
 
124
}
125
#else
126
static bool framebuffer_plot_text(int x, int y, const char *text, size_t length,
127
		const plot_font_style_t *fstyle)
128
{
129
    const struct fb_font_desc* fb_font = fb_get_font(fstyle);
130
    const uint32_t *chrp;
131
    char *buffer = NULL;
132
    int chr;
133
    int blen;
134
    nsfb_bbox_t loc;
135
 
136
    utf8_to_font_encoding(fb_font, text, length, &buffer);
137
    if (buffer == NULL)
138
        return true;
139
 
140
        /* y is given as the baseline, at 3/4 from top.
141
         * we need it to the top */
142
        y -= ((fb_font->height * 3) / 4);
143
 
144
        /* the coord is the bottom-left of the pixels offset by 1 to make
145
         *   it work since fb coords are the top-left of pixels
146
         */
147
        y += 1;
148
 
149
    blen = strlen(buffer);
150
 
151
    for (chr = 0; chr < blen; chr++) {
152
        loc.x0 = x;
153
        loc.y0 = y;
154
        loc.x1 = loc.x0 + fb_font->width;
155
        loc.y1 = loc.y0 + fb_font->height;
156
 
157
        chrp = fb_font->data + ((unsigned char)buffer[chr] * fb_font->height);
158
        nsfb_plot_glyph1(nsfb, &loc, (uint8_t *)chrp, 32, fstyle->foreground);
159
 
160
        x += fb_font->width;
161
 
162
    }
163
 
164
    free(buffer);
165
    return true;
166
}
167
#endif
168
 
169
 
170
static bool
171
framebuffer_plot_bitmap(int x, int y,
172
                        int width, int height,
173
                        struct bitmap *bitmap, colour bg,
174
                        bitmap_flags_t flags)
175
{
176
	int xf,yf;
177
        nsfb_bbox_t loc;
178
        nsfb_bbox_t clipbox;
179
        bool repeat_x = (flags & BITMAPF_REPEAT_X);
180
        bool repeat_y = (flags & BITMAPF_REPEAT_Y);
181
	int bmwidth;
182
	int bmheight;
183
	unsigned char *bmptr;
184
	nsfb_t *bm = (nsfb_t *)bitmap;
185
 
186
	/* x and y define coordinate of top left of of the initial explicitly
187
	 * placed tile. The width and height are the image scaling and the
188
	 * bounding box defines the extent of the repeat (which may go in all
189
	 * four directions from the initial tile).
190
	 */
191
 
192
	if (!(repeat_x || repeat_y)) {
193
		/* Not repeating at all, so just plot it */
194
                loc.x0 = x;
195
                loc.y0 = y;
196
                loc.x1 = loc.x0 + width;
197
                loc.y1 = loc.y0 + height;
198
 
199
		return nsfb_plot_copy(bm, NULL, nsfb, &loc);
200
	}
201
 
202
        nsfb_plot_get_clip(nsfb, &clipbox);
203
	nsfb_get_geometry(bm, &bmwidth, &bmheight, NULL);
204
	nsfb_get_buffer(bm, &bmptr, NULL);
205
 
206
	/* Optimise tiled plots of 1x1 bitmaps by replacing with a flat fill
207
	 * of the area.  Can only be done when image is fully opaque. */
208
	if ((bmwidth == 1) && (bmheight == 1)) {
209
		if ((*(nsfb_colour_t *)bmptr & 0xff000000) != 0) {
210
			return nsfb_plot_rectangle_fill(nsfb, &clipbox,
211
					*(nsfb_colour_t *)bmptr);
212
		}
213
	}
214
 
215
	/* Optimise tiled plots of bitmaps scaled to 1x1 by replacing with
216
	 * a flat fill of the area.  Can only be done when image is fully
217
	 * opaque. */
218
	if ((width == 1) && (height == 1)) {
219
		if (bitmap_get_opaque(bm)) {
220
			/** TODO: Currently using top left pixel. Maybe centre
221
			 *        pixel or average value would be better. */
222
			return nsfb_plot_rectangle_fill(nsfb, &clipbox,
223
					*(nsfb_colour_t *)bmptr);
224
		}
225
	}
226
 
227
	/* get left most tile position */
228
	if (repeat_x)
229
		for (; x > clipbox.x0; x -= width);
230
 
231
	/* get top most tile position */
232
	if (repeat_y)
233
		for (; y > clipbox.y0; y -= height);
234
 
235
	/* tile down and across to extents */
236
	for (xf = x; xf < clipbox.x1; xf += width) {
237
		for (yf = y; yf < clipbox.y1; yf += height) {
238
 
239
                        loc.x0 = xf;
240
                        loc.y0 = yf;
241
                        loc.x1 = loc.x0 + width;
242
                        loc.y1 = loc.y0 + height;
243
 
244
			nsfb_plot_copy(bm, NULL, nsfb, &loc);
245
 
246
			if (!repeat_y)
247
				break;
248
		}
249
		if (!repeat_x)
250
	   		break;
251
	}
252
	return true;
253
}
254
 
255
static bool
256
framebuffer_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
257
{
258
	nsfb_bbox_t rect;
259
	bool dotted = false;
260
	bool dashed = false;
261
 
262
	rect.x0 = x0;
263
	rect.y0 = y0;
264
	rect.x1 = x1;
265
	rect.y1 = y1;
266
 
267
	if (style->fill_type != PLOT_OP_TYPE_NONE) {
268
		nsfb_plot_rectangle_fill(nsfb, &rect, style->fill_colour);
269
	}
270
 
271
	if (style->stroke_type != PLOT_OP_TYPE_NONE) {
272
		if (style->stroke_type == PLOT_OP_TYPE_DOT)
273
			dotted = true;
274
 
275
		if (style->stroke_type == PLOT_OP_TYPE_DASH)
276
			dashed = true;
277
 
278
		nsfb_plot_rectangle(nsfb, &rect, style->stroke_width, style->stroke_colour, dotted, dashed);
279
	}
280
 
281
	return true;
282
}
283
 
284
static bool
285
framebuffer_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
286
{
287
	nsfb_bbox_t rect;
288
	nsfb_plot_pen_t pen;
289
 
290
	rect.x0 = x0;
291
	rect.y0 = y0;
292
	rect.x1 = x1;
293
	rect.y1 = y1;
294
 
295
	if (style->stroke_type != PLOT_OP_TYPE_NONE) {
296
 
297
		if (style->stroke_type == PLOT_OP_TYPE_DOT) {
298
			pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
299
			pen.stroke_pattern = 0xAAAAAAAA;
300
		} else if (style->stroke_type == PLOT_OP_TYPE_DASH) {
301
			pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
302
			pen.stroke_pattern = 0xF0F0F0F0;
303
		} else {
304
			pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
305
		}
306
 
307
		pen.stroke_colour = style->stroke_colour;
308
		pen.stroke_width = style->stroke_width;
309
		nsfb_plot_line(nsfb, &rect, &pen);
310
	}
311
 
312
	return true;
313
}
314
 
315
 
316
static bool
317
framebuffer_plot_path(const float *p,
318
                      unsigned int n,
319
                      colour fill,
320
                      float width,
321
                      colour c,
322
                      const float transform[6])
323
{
324
	LOG(("path unimplemented"));
325
	return true;
326
}
327
 
328
static bool
329
framebuffer_plot_clip(const struct rect *clip)
330
{
331
	nsfb_bbox_t nsfb_clip;
332
	nsfb_clip.x0 = clip->x0;
333
	nsfb_clip.y0 = clip->y0;
334
	nsfb_clip.x1 = clip->x1;
335
	nsfb_clip.y1 = clip->y1;
336
 
337
	return nsfb_plot_set_clip(nsfb, &nsfb_clip);
338
}
339
 
340
const struct plotter_table fb_plotters = {
341
	.clip = framebuffer_plot_clip,
342
	.arc = framebuffer_plot_arc,
343
	.disc = framebuffer_plot_disc,
344
	.line = framebuffer_plot_line,
345
	.rectangle = framebuffer_plot_rectangle,
346
	.polygon = framebuffer_plot_polygon,
347
	.path = framebuffer_plot_path,
348
	.bitmap = framebuffer_plot_bitmap,
349
	.text = framebuffer_plot_text,
350
        .option_knockout = true,
351
};
352
 
353
 
354
 
355
nsfb_t *
356
framebuffer_initialise(const char *fename, int width, int height, int bpp)
357
{
358
    enum nsfb_type_e fbtype;
359
    enum nsfb_format_e fbfmt;
360
 
361
    /* bpp is a proxy for the framebuffer format */
362
    switch (bpp) {
363
    case 32:
364
	    fbfmt = NSFB_FMT_XRGB8888;
365
	    break;
366
 
367
    case 24:
368
	    fbfmt = NSFB_FMT_RGB888;
369
	    break;
370
 
371
    case 16:
372
	    fbfmt = NSFB_FMT_RGB565;
373
	    break;
374
 
375
    case 8:
376
	    fbfmt = NSFB_FMT_I8;
377
	    break;
378
 
379
    case 4:
380
	    fbfmt = NSFB_FMT_I4;
381
	    break;
382
 
383
    case 1:
384
	    fbfmt = NSFB_FMT_I1;
385
	    break;
386
 
387
    default:
388
        LOG(("Bad bits per pixel (%d)\n", bpp));
389
        return NULL;
390
    }
391
 
392
 
393
 
394
 
395
    fbtype = nsfb_type_from_name(fename);
396
    if (fbtype == NSFB_SURFACE_NONE) {
397
        LOG(("The %s surface is not available from libnsfb\n", fename));
398
        return NULL;
399
    }
400
 
401
    nsfb = nsfb_new(fbtype);
402
    if (nsfb == NULL) {
403
        LOG(("Unable to create %s fb surface\n", fename));
404
        return NULL;
405
    }
406
 
407
    if (nsfb_set_geometry(nsfb, width, height, fbfmt) == -1) {
408
        LOG(("Unable to set surface geometry\n"));
409
        nsfb_free(nsfb);
410
        return NULL;
411
    }
412
 
413
    nsfb_cursor_init(nsfb);
414
 
415
    if (nsfb_init(nsfb) == -1) {
416
        LOG(("Unable to initialise nsfb surface\n"));
417
        nsfb_free(nsfb);
418
        return NULL;
419
    }
420
 
421
    return nsfb;
422
 
423
}
424
 
425
void
426
framebuffer_finalise(void)
427
{
428
    nsfb_free(nsfb);
429
}
430
 
431
bool
432
framebuffer_set_cursor(struct fbtk_bitmap *bm)
433
{
434
    return nsfb_cursor_set(nsfb, (nsfb_colour_t *)bm->pixdata, bm->width, bm->height, bm->width, bm->hot_x, bm->hot_y);
435
}
436
 
437
nsfb_t *framebuffer_set_surface(nsfb_t *new_nsfb)
438
{
439
	nsfb_t *old_nsfb;
440
	old_nsfb = nsfb;
441
	nsfb = new_nsfb;
442
	return old_nsfb;
443
}