From 131b6c4a00575c9e996a9ae60c90a9647fb5ef75 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 20 Jan 2010 17:18:28 +0000 Subject: move plot functions to their own sub directory fix 8 and 16bpp plotters when used with cursor svn path=/trunk/libnsfb/; revision=9850 --- src/16bpp_plotters.c | 424 -------------------------------- src/1bpp_plotters.c | 266 --------------------- src/24bpp_plotters.c | 469 ------------------------------------ src/32bpp_plotters.c | 442 ---------------------------------- src/8bpp_plotters.c | 401 ------------------------------- src/Makefile | 4 +- src/frontend_linux.c | 68 +++++- src/plot.c | 169 ------------- src/plot/16bpp.c | 448 ++++++++++++++++++++++++++++++++++ src/plot/1bpp.c | 266 +++++++++++++++++++++ src/plot/24bpp.c | 442 ++++++++++++++++++++++++++++++++++ src/plot/32bpp.c | 442 ++++++++++++++++++++++++++++++++++ src/plot/8bpp.c | 425 +++++++++++++++++++++++++++++++++ src/plot/Makefile | 4 + src/plot/api.c | 169 +++++++++++++ src/plot/generic.c | 663 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/plot/util.c | 199 ++++++++++++++++ src/plot_util.c | 199 ---------------- src/plotters.c | 663 --------------------------------------------------- 19 files changed, 3127 insertions(+), 3036 deletions(-) delete mode 100644 src/16bpp_plotters.c delete mode 100644 src/1bpp_plotters.c delete mode 100644 src/24bpp_plotters.c delete mode 100644 src/32bpp_plotters.c delete mode 100644 src/8bpp_plotters.c delete mode 100644 src/plot.c create mode 100644 src/plot/16bpp.c create mode 100644 src/plot/1bpp.c create mode 100644 src/plot/24bpp.c create mode 100644 src/plot/32bpp.c create mode 100644 src/plot/8bpp.c create mode 100644 src/plot/Makefile create mode 100644 src/plot/api.c create mode 100644 src/plot/generic.c create mode 100644 src/plot/util.c delete mode 100644 src/plot_util.c delete mode 100644 src/plotters.c (limited to 'src') diff --git a/src/16bpp_plotters.c b/src/16bpp_plotters.c deleted file mode 100644 index b9ff186..0000000 --- a/src/16bpp_plotters.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright 2009 Vincent Sanders - * - * This file is part of libnsfb, http://www.netsurf-browser.org/ - * Licenced under the MIT License, - * http://www.opensource.org/licenses/mit-license.php - */ - -#include -#include -#include - -#include "libnsfb.h" -#include "libnsfb_plot.h" -#include "libnsfb_plot_util.h" - -#include "nsfb.h" -#include "plot.h" - -static inline uint16_t *get_xy_loc(nsfb_t *nsfb, int x, int y) -{ - return (void *)(nsfb->ptr + (y * nsfb->linelen) + (x << 1)); -} - -static inline nsfb_colour_t pixel_to_colour(uint16_t pixel) -{ - return ((pixel & 0x1F) << 19) | - ((pixel & 0x7E0) << 5) | - ((pixel & 0xF800) >> 8); -} - -/* convert a colour value to a 16bpp pixel value ready for screen output */ -static inline uint16_t colour_to_pixel(nsfb_colour_t c) -{ - return ((c & 0xF8) << 8) | ((c & 0xFC00 ) >> 5) | ((c & 0xF80000) >> 19); -} - -#define SIGN(x) ((x<0) ? -1 : ((x>0) ? 1 : 0)) - - -static bool -line(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen) -{ - int w; - uint16_t ent; - uint16_t *pvideo; - int x, y, i; - int dx, dy, sdy; - int dxabs, dyabs; - - ent = colour_to_pixel(pen->stroke_colour); - - for (;linec > 0; linec--) { - - if (line->y0 == line->y1) { - /* horizontal line special cased */ - - if (!nsfb_plot_clip_ctx(nsfb, line)) { - /* line outside clipping */ - line++; - continue; - } - - pvideo = get_xy_loc(nsfb, line->x0, line->y0); - - w = line->x1 - line->x0; - while (w-- > 0) - *(pvideo + w) = ent; - - } else { - /* standard bresenham line */ - if (!nsfb_plot_clip_line_ctx(nsfb, line)) { - /* line outside clipping */ - line++; - continue; - } - - /* the horizontal distance of the line */ - dx = line->x1 - line->x0; - dxabs = abs (dx); - - /* the vertical distance of the line */ - dy = line->y1 - line->y0; - dyabs = abs (dy); - - sdy = dx ? SIGN(dy) * SIGN(dx) : SIGN(dy); - - if (dx >= 0) - pvideo = get_xy_loc(nsfb, line->x0, line->y0); - else - pvideo = get_xy_loc(nsfb, line->x1, line->y1); - - x = dyabs >> 1; - y = dxabs >> 1; - - if (dxabs >= dyabs) { - /* the line is more horizontal than vertical */ - for (i = 0; i < dxabs; i++) { - *pvideo = ent; - - pvideo++; - y += dyabs; - if (y >= dxabs) { - y -= dxabs; - pvideo += sdy * (nsfb->linelen>>1); - } - } - } else { - /* the line is more vertical than horizontal */ - for (i = 0; i < dyabs; i++) { - *pvideo = ent; - pvideo += sdy * (nsfb->linelen >> 1); - - x += dxabs; - if (x >= dyabs) { - x -= dyabs; - pvideo++; - } - } - } - - } - line++; - } - return true; -} - - - -static bool fill(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t c) -{ - int w; - uint16_t *pvid16; - uint16_t ent16; - uint32_t *pvid32; - uint32_t ent32; - uint32_t llen; - uint32_t width; - uint32_t height; - - if (!nsfb_plot_clip_ctx(nsfb, rect)) - return true; /* fill lies outside current clipping region */ - - ent16 = colour_to_pixel(c); - width = rect->x1 - rect->x0; - height = rect->y1 - rect->y0; - - pvid16 = get_xy_loc(nsfb, rect->x0, rect->y0); - - if (((rect->x0 & 1) == 0) && ((width & 1) == 0)) { - /* aligned to 32bit value and width is even */ - width = width >> 1; - llen = (nsfb->linelen >> 2) - width; - ent32 = ent16 | (ent16 << 16); - pvid32 = (uint32_t *)pvid16; - - while (height-- > 0) { - w = width; - while (w >= 16) { - *pvid32++ = ent32; *pvid32++ = ent32; - *pvid32++ = ent32; *pvid32++ = ent32; - *pvid32++ = ent32; *pvid32++ = ent32; - *pvid32++ = ent32; *pvid32++ = ent32; - *pvid32++ = ent32; *pvid32++ = ent32; - *pvid32++ = ent32; *pvid32++ = ent32; - *pvid32++ = ent32; *pvid32++ = ent32; - *pvid32++ = ent32; *pvid32++ = ent32; - w-=16; - } - while (w >= 4) { - *pvid32++ = ent32; *pvid32++ = ent32; - *pvid32++ = ent32; *pvid32++ = ent32; - w-=4; - } - while (w > 0) { - *pvid32++ = ent32; - w--; - } - // for (w = width; w > 0; w--) *pvid32++ = ent32; - pvid32 += llen; - } - - } else { - llen = (nsfb->linelen >> 1) - width; - - - while (height-- > 0) { - for (w = width; w > 0; w--) *pvid16++ = ent16; - pvid16 += llen; - } - } - return true; -} - - -static bool point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c) -{ - uint16_t *pvideo; - - /* check point lies within clipping region */ - if ((x < nsfb->clip.x0) || - (x >= nsfb->clip.x1) || - (y < nsfb->clip.y0) || - (y >= nsfb->clip.y1)) - return true; - - pvideo = get_xy_loc(nsfb, x, y); - - if ((c & 0xFF000000) != 0) { - if ((c & 0xFF000000) != 0xFF000000) { - c = nsfb_plot_ablend(c, pixel_to_colour(*pvideo)); - } - - *pvideo = colour_to_pixel(c); - } - return true; -} - -static bool -glyph1(nsfb_t *nsfb, - nsfb_bbox_t *loc, - const uint8_t *pixel, - int pitch, - nsfb_colour_t c) -{ - uint16_t *pvideo; - int xloop, yloop; - int xoff, yoff; /* x and y offset into image */ - int x = loc->x0; - int y = loc->y0; - int width = loc->x1 - loc->x0; - int height = loc->y1 - loc->y0; - uint16_t fgcol; - const uint8_t *fntd; - uint8_t row; - - if (!nsfb_plot_clip_ctx(nsfb, loc)) - return true; - - if (height > (loc->y1 - loc->y0)) - height = (loc->y1 - loc->y0); - - if (width > (loc->x1 - loc->x0)) - width = (loc->x1 - loc->x0); - - xoff = loc->x0 - x; - yoff = loc->y0 - y; - - pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); - - fgcol = colour_to_pixel(c); - - for (yloop = yoff; yloop < height; yloop++) { - fntd = pixel + (yloop * (pitch>>3)) + (xoff>>3); - row = (*fntd++) << (xoff & 3); - for (xloop = xoff; xloop < width ; xloop++) { - if (((xloop % 8) == 0) && (xloop != 0)) { - row = *fntd++; - } - - if ((row & 0x80) != 0) { - *(pvideo + xloop) = fgcol; - } - row = row << 1; - - } - - pvideo += (nsfb->linelen >> 1); - } - - return true; -} - -static bool -glyph8(nsfb_t *nsfb, - nsfb_bbox_t *loc, - const uint8_t *pixel, - int pitch, - nsfb_colour_t c) -{ - uint16_t *pvideo; - nsfb_colour_t abpixel; /* alphablended pixel */ - int xloop, yloop; - int xoff, yoff; /* x and y offset into image */ - int x = loc->x0; - int y = loc->y0; - int width = loc->x1 - loc->x0; - int height = loc->y1 - loc->y0; - uint16_t fgcol; - - if (!nsfb_plot_clip_ctx(nsfb, loc)) - return true; - - if (height > (loc->y1 - loc->y0)) - height = (loc->y1 - loc->y0); - - if (width > (loc->x1 - loc->x0)) - width = (loc->x1 - loc->x0); - - xoff = loc->x0 - x; - yoff = loc->y0 - y; - - pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); - - fgcol = c & 0xFFFFFF; - - for (yloop = 0; yloop < height; yloop++) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = (pixel[((yoff + yloop) * pitch) + xloop + xoff] << 24) | fgcol; - if ((abpixel & 0xFF000000) != 0) { - /* pixel is not transparent */ - if ((abpixel & 0xFF000000) != 0xFF000000) { - abpixel = nsfb_plot_ablend(abpixel, - pixel_to_colour(*(pvideo + xloop))); - } - - *(pvideo + xloop) = colour_to_pixel(abpixel); - } - } - pvideo += (nsfb->linelen >> 1); - } - - return true; -} - -static bool -bitmap(nsfb_t *nsfb, - const nsfb_bbox_t *loc, - const nsfb_colour_t *pixel, - int bmp_width, - int bmp_height, - int bmp_stride, - bool alpha) -{ - uint16_t *pvideo; - nsfb_colour_t abpixel; /* alphablended pixel */ - int xloop, yloop; - int xoff, yoff; /* x and y offset into image */ - int x = loc->x0; - int y = loc->y0; - int width = loc->x1 - loc->x0; - int height = loc->y1 - loc->y0; - nsfb_bbox_t clipped; /* clipped display */ - - - /* TODO here we should scale the image from bitmap->width to width, for - * now simply crop. - */ - if (width > bmp_width) - width = bmp_width; - - if (height > bmp_height) - height = bmp_height; - - /* The part of the scaled image actually displayed is cropped to the - * current context. - */ - clipped.x0 = x; - clipped.y0 = y; - clipped.x1 = x + width; - clipped.y1 = y + height; - - if (!nsfb_plot_clip_ctx(nsfb, &clipped)) - return true; - - if (height > (clipped.y1 - clipped.y0)) - height = (clipped.y1 - clipped.y0); - - if (width > (clipped.x1 - clipped.x0)) - width = (clipped.x1 - clipped.x0); - - - xoff = clipped.x0 - x; - yoff = (clipped.y0 - y) * bmp_width; - height = height * bmp_width + yoff; - - /* plot the image */ - pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0); - - if (alpha) { - for (yloop = yoff; yloop < height; yloop += bmp_stride) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = pixel[yloop + xloop + xoff]; - if ((abpixel & 0xFF000000) != 0) { - if ((abpixel & 0xFF000000) != 0xFF000000) { - abpixel = nsfb_plot_ablend(abpixel, - pixel_to_colour(*(pvideo + xloop))); - } - - *(pvideo + xloop) = colour_to_pixel(abpixel); - } - } - pvideo += (nsfb->linelen >> 1); - } - } else { - for (yloop = yoff; yloop < height; yloop += bmp_stride) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = pixel[yloop + xloop + xoff]; - *(pvideo + xloop) = colour_to_pixel(abpixel); - } - pvideo += (nsfb->linelen >> 1); - } - } - - return true; -} - - - - -const nsfb_plotter_fns_t _nsfb_16bpp_plotters = { - .line = line, - .fill = fill, - .point = point, - .bitmap = bitmap, - .glyph8 = glyph8, - .glyph1 = glyph1, -}; - -/* - * Local Variables: - * c-basic-offset:8 - * End: - */ diff --git a/src/1bpp_plotters.c b/src/1bpp_plotters.c deleted file mode 100644 index bd511e7..0000000 --- a/src/1bpp_plotters.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright 2008 Vincent Sanders - * - * This file is part of NetSurf, http://www.netsurf-browser.org/ - * - * NetSurf is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * NetSurf is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include - -#include "utils/log.h" -#include "utils/utf8.h" -#include "desktop/plotters.h" - -#include "framebuffer/fb_gui.h" -#include "framebuffer/fb_plotters.h" -#include "framebuffer/fb_bitmap.h" -#include "framebuffer/fb_font.h" - -extern struct fb_info_s *fbinfo; - - -static bool fb_1bpp_rectangle(int x0, int y0, int width, int height, - int line_width, colour c, bool dotted, bool dashed) -{ - LOG(("%s(%d, %d, %d, %d, %d, 0x%lx, %d, %d)\n", __func__, - x0,y0,width,height,line_width,c,dotted,dashed)); - return true; -} - -static bool fb_1bpp_line(int x0, int y0, int x1, int y1, int width, - colour c, bool dotted, bool dashed) -{ - LOG(("%s(%d, %d, %d, %d, %d, 0x%lx, %d, %d)\n", __func__, - x0,y0,x1,y1,width,c,dotted,dashed)); - - return true; -} - -static bool fb_1bpp_polygon(const int *p, unsigned int n, colour fill) -{ - LOG(("%s(%p, %d, 0x%lx)\n", __func__, p,n,fill)); - return true; -} - - -static bool fb_1bpp_fill(int x0, int y0, int x1, int y1, colour c) -{ - int x; - int y; - int pent; - - LOG(("%s(%d, %d, %d, %d, 0x%lx)\n", __func__, - x0,y0,x1,y1,c)); - - if (c != 0) - pent = 0xff; - else - pent = 0; - - fb_plotters_clip_rect_ctx(&x0, &y0, &x1, &y1); - - x = x1 - x0; - for (y = y0; y < y1; y++) { - memset(fb_plotters_get_xy_loc(x0, y, fbinfo), pent, x); - } - return true; -} - -static bool fb_1bpp_clg(colour c) -{ - LOG(("%s(%lx)\n", __func__, c)); - fb_1bpp_fill(fb_plot_ctx.x0, - fb_plot_ctx.y0, - fb_plot_ctx.x1, - fb_plot_ctx.y1, - c); - return true; -} - - -static bool fb_1bpp_text(int x, int y, const struct css_style *style, - const char *text, size_t length, colour bg, colour c) -{ - const struct fb_font_desc* fb_font = fb_get_font(style); - u8_t *video_char_start; - const u8_t *font_data; - int yloop; - unsigned char row; - int chr; - - LOG(("%s(%d, %d, %p, %.*s , %d, 0x%lx, 0x%lx)\n", __func__, - x,y,style,length,text,length,bg,c)); - - for (chr=0; chr < length; chr++) { - video_char_start = fb_plotters_get_xy_loc(x + (chr * (fb_font->width)), y, fbinfo); - - /* move our font-data to the correct position */ - font_data = fb_font->data + (text[chr] * fb_font->height); - - for (yloop = 0; yloop < fb_font->height; yloop++) { - row = font_data[yloop]; - *video_char_start = row; - video_char_start += fbinfo->line_len; - } - } - return true; - - - /* copied from css/css.h - need to open the correct font here - * font properties * - css_font_family font_family; - struct { - css_font_size_type size; - union { - struct css_length length; - float absolute; - float percent; - } value; - } font_size; - css_font_style font_style; - css_font_variant font_variant; - css_font_weight font_weight; - */ - return true; -} - -static bool fb_1bpp_disc(int x, int y, int radius, colour c, bool filled) -{ - LOG(("%s(%d, %d, %d, 0x%lx, %d)\n", __func__, - x, y, radius, c, filled)); - return true; -} - -static bool fb_1bpp_arc(int x, int y, int radius, int angle1, int angle2, - colour c) -{ - LOG(("x %d, y %d, radius %d, angle1 %d, angle2 %d, c 0x%lx", - x, y, radius, angle1, angle2, c)); - return true; -} - -static inline colour ablend(colour pixel) -{ - return pixel; -} - - -static bool fb_1bpp_bitmap(int x, int y, int width, int height, - struct bitmap *bitmap, colour bg, - struct content *content) -{ - u8_t *video_char_start; - colour *pixel = (colour *)bitmap->pixdata; - colour abpixel; /* alphablended pixel */ - int xloop,yloop; - - video_char_start = fb_plotters_get_xy_loc(x, y, fbinfo); - - for (yloop = 0; yloop < height; yloop++) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = pixel[(yloop * bitmap->width) + xloop]; - if ((abpixel & 0xFF000000) != 0) { - if ((abpixel & 0xFF000000) != 0xFF) - abpixel = ablend(abpixel); - if (abpixel == 0) - video_char_start[xloop] |= (1 << (xloop % 8)); - else - video_char_start[xloop] &= ~(1 << (xloop % 8)); - - } - } - video_char_start += fbinfo->line_len; - } - - return true; -} - -static bool fb_1bpp_bitmap_tile(int x, int y, int width, int height, - struct bitmap *bitmap, colour bg, - bool repeat_x, bool repeat_y, - struct content *content) -{ - unsigned long xf,yf,wf,hf; - - if (!(repeat_x || repeat_y)) { - /* Not repeating at all, so just pass it on */ - return fb_1bpp_bitmap(x,y,width,height,bitmap,bg,content); - } - - for (xf = 0; xf < width; xf += bitmap->width) { - for(yf = 0;yf < height; yf += bitmap->height) { - if(width > xf+bitmap->width) - { - wf = width-(xf+bitmap->width); - } - else - { - wf=bitmap->width; - } - - if(height > yf+bitmap->height) - { - hf = height-(yf+bitmap->height); - } - else - { - hf=bitmap->height; - } - - fb_1bpp_bitmap(x+xf, y+yf, wf, hf, bitmap, bg, content); - - } - } - - return true; -} - -static bool fb_1bpp_flush(void) -{ - LOG(("%s()\n", __func__)); - return true; -} - -static bool fb_1bpp_path(const float *p, unsigned int n, colour fill, float width, - colour c, const float transform[6]) -{ - LOG(("%s(%f, %d, 0x%lx, %f, 0x%lx, %f)\n", __func__, - *p, n, fill, width, c, *transform)); - return true; -} - -const struct plotter_table framebuffer_1bpp_plot = { - .clg = fb_1bpp_clg, - .rectangle = fb_1bpp_rectangle, - .line = fb_1bpp_line, - .polygon = fb_1bpp_polygon, - .fill = fb_1bpp_fill, - .clip = fb_clip, - .text = fb_1bpp_text, - .disc = fb_1bpp_disc, - .arc = fb_1bpp_arc, - .bitmap = fb_1bpp_bitmap, - .bitmap_tile = fb_1bpp_bitmap_tile, - .flush = fb_1bpp_flush, - .path = fb_1bpp_path -}; - -/* - * Local Variables: - * c-basic-offset:8 - * End: - */ diff --git a/src/24bpp_plotters.c b/src/24bpp_plotters.c deleted file mode 100644 index 777b896..0000000 --- a/src/24bpp_plotters.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright 2008 Vincent Sanders - * - * This file is part of NetSurf, http://www.netsurf-browser.org/ - * - * NetSurf is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * NetSurf is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include - -#include "utils/log.h" -#include "utils/utf8.h" -#include "desktop/plotters.h" - -#include "framebuffer/fb_gui.h" -#include "framebuffer/fb_plotters.h" -#include "framebuffer/fb_bitmap.h" -#include "framebuffer/fb_font.h" - -static inline uint8_t * -fb_8bpp_get_xy_loc(int x, int y) -{ - return (uint8_t *)(framebuffer->ptr + - (y * framebuffer->linelen) + - (x)); -} - - -static bool fb_8bpp_line(int x0, int y0, int x1, int y1, int width, - colour c, bool dotted, bool dashed) -{ - LOG(("%d, %d, %d, %d, %d, 0x%lx, %d, %d", - x0, y0, x1, y1, width, (unsigned long)c, dotted, dashed)); - - return true; -} - -static bool fb_8bpp_rectangle(int x0, int y0, int width, int height, - int line_width, colour c, bool dotted, bool dashed) -{ - fb_8bpp_line(x0, y0, x0 + width, y0, line_width, c, dotted, dashed); - fb_8bpp_line(x0, y0 + height, x0 + width, y0 + height, line_width, c, dotted, dashed); - fb_8bpp_line(x0, y0, x0, y0 + height, line_width, c, dotted, dashed); - fb_8bpp_line(x0 + width, y0, x0 + width, y0 + height, line_width, c, dotted, dashed); - return true; -} - -static bool fb_8bpp_polygon(const int *p, unsigned int n, colour fill) -{ - /*LOG(("%p, %d, 0x%lx", p,n,fill));*/ - return fb_plotters_polygon(p, n, fill, fb_8bpp_line); -} - -static colour calc_colour(uint8_t c) -{ - return framebuffer->palette[c]; -} - - -static int -find_closest_palette_entry(colour c) -{ - colour palent; - int col; - - int dr, dg, db; /* delta red, green blue values */ - - int cur_distance; - int best_distance = INT_MAX; - int best_col = 0; - - for (col = 0; col < 256; col++) { - palent = framebuffer->palette[col]; - - dr = (c & 0xFF) - (palent & 0xFF); - dg = ((c >> 8) & 0xFF) - ((palent >> 8) & 0xFF); - db = ((c >> 16) & 0xFF) - ((palent >> 16) & 0xFF); - cur_distance = ((dr * dr) + (dg * dg) + (db *db)); - if (cur_distance < best_distance) { - best_distance = cur_distance; - best_col = col; - } - } - - return best_col; -} - -static inline uint8_t fb_colour_to_pixel(colour c) -{ - return find_closest_palette_entry(c); -} - -static inline colour fb_8bpp_to_colour(uint8_t pixel) -{ - return framebuffer->palette[pixel]; -} - -static bool fb_8bpp_fill(int x0, int y0, int x1, int y1, colour c) -{ - int y; - uint8_t ent; - uint8_t *pvideo; - - if (!fb_plotters_clip_rect_ctx(&x0, &y0, &x1, &y1)) - return true; /* fill lies outside current clipping region */ - - pvideo = fb_8bpp_get_xy_loc(x0, y0); - - ent = find_closest_palette_entry(c); - - for (y = y0; y < y1; y++) { - memset(pvideo, ent, x1 - x0); - pvideo += framebuffer->linelen; - } - - return true; -} - -static bool fb_8bpp_clg(colour c) -{ - LOG(("colour %lx", (unsigned long)c)); - fb_8bpp_fill(fb_plot_ctx.x0, - fb_plot_ctx.y0, - fb_plot_ctx.x1, - fb_plot_ctx.y1, - c); - return true; -} - -#ifdef FB_USE_FREETYPE - -static bool -fb_8bpp_draw_ft_monobitmap(FT_Bitmap *bp, int x, int y, colour c) -{ - return false; -} - -static bool -fb_8bpp_draw_ft_bitmap(FT_Bitmap *bp, int x, int y, colour c) -{ - uint8_t *pvideo; - uint8_t *pixel = (uint8_t *)bp->buffer; - colour abpixel; /* alphablended pixel */ - int xloop, yloop; - int x0,y0,x1,y1; - int xoff, yoff; /* x and y offset into image */ - int height = bp->rows; - int width = bp->width; - uint32_t fgcol; - - /* The part of the scaled image actually displayed is cropped to the - * current context. - */ - x0 = x; - y0 = y; - x1 = x + width; - y1 = y + height; - - if (!fb_plotters_clip_rect_ctx(&x0, &y0, &x1, &y1)) - return true; - - if (height > (y1 - y0)) - height = (y1 - y0); - - if (width > (x1 - x0)) - width = (x1 - x0); - - xoff = x0 - x; - yoff = y0 - y; - - /* plot the image */ - pvideo = fb_8bpp_get_xy_loc(x0, y0); - - fgcol = c & 0xFFFFFF; - - for (yloop = 0; yloop < height; yloop++) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = (pixel[((yoff + yloop) * bp->pitch) + xloop + xoff] << 24) | fgcol; - if ((abpixel & 0xFF000000) != 0) { - if ((abpixel & 0xFF000000) != 0xFF000000) { - abpixel = fb_plotters_ablend(abpixel, - fb_8bpp_to_colour(*(pvideo + xloop))); - } - - *(pvideo + xloop) = fb_colour_to_pixel(abpixel); - - } - } - pvideo += framebuffer->linelen; - } - - return true; -} - -static bool fb_8bpp_text(int x, int y, const struct css_style *style, - const char *text, size_t length, colour bg, colour c) -{ - uint32_t ucs4; - size_t nxtchr = 0; - FT_Glyph glyph; - FT_BitmapGlyph bglyph; - - while (nxtchr < length) { - ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr); - nxtchr = utf8_next(text, length, nxtchr); - - glyph = fb_getglyph(style, ucs4); - if (glyph == NULL) - continue; - if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { - bglyph = (FT_BitmapGlyph)glyph; - - /* now, draw to our target surface */ - if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { - fb_8bpp_draw_ft_monobitmap(&bglyph->bitmap, - x + bglyph->left, - y - bglyph->top, - c); - } else { - fb_8bpp_draw_ft_bitmap(&bglyph->bitmap, - x + bglyph->left, - y - bglyph->top, - c); - } - } - x += glyph->advance.x >> 16; - - } - return true; - -} -#else -static bool fb_8bpp_text(int x, int y, const struct css_style *style, - const char *text, size_t length, colour bg, colour c) -{ - const struct fb_font_desc* fb_font = fb_get_font(style); - const uint32_t *font_data; - uint32_t row; - - int xloop, yloop; - size_t chr; - - uint8_t *pvideo; - uint8_t fgcol; - - unsigned char *buffer = NULL; - int x0,y0,x1,y1; - int xoff, yoff; /* x and y offset into image */ - int height = fb_font->height; - - /* aquire thge text in local font encoding */ - utf8_to_font_encoding(fb_font, text, length, (char **)&buffer); - if (!buffer) - return true; - length = strlen((char *)buffer); - - - /* y is given to the fonts baseline we need it to the fonts top */ - y-=((fb_font->height * 75)/100); - - y+=1; /* the coord is the bottom-left of the pixels offset by 1 to make - * it work since fb coords are the top-left of pixels - */ - - /* The part of the text displayed is cropped to the current context. */ - x0 = x; - y0 = y; - x1 = x + (fb_font->width * length); - y1 = y + fb_font->height; - - if (!fb_plotters_clip_rect_ctx(&x0, &y0, &x1, &y1)) - return true; /* text lies outside current clipping region */ - - /* find width and height to plot */ - if (height > (y1 - y0)) - height = (y1 - y0); - - xoff = x0 - x; - yoff = y0 - y; - - fgcol = find_closest_palette_entry(c); - - /*LOG(("x %d, y %d, style %p, txt %.*s , len %d, bg 0x%lx, fg 0x%lx", - x,y,style,length,text,length,bg,c));*/ - - for (chr = 0; chr < length; chr++, x += fb_font->width) { - if ((x + fb_font->width) > x1) - break; - - if (x < x0) - continue; - - pvideo = fb_8bpp_get_xy_loc(x, y0); - - /* move our font-data to the correct position */ - font_data = fb_font->data + (buffer[chr] * fb_font->height); - - for (yloop = 0; yloop < height; yloop++) { - row = font_data[yoff + yloop]; - for (xloop = fb_font->width; xloop > 0 ; xloop--) { - if ((row & 1) != 0) - *(pvideo + xloop) = fgcol; - row = row >> 1; - } - pvideo += framebuffer->linelen; - } - } - - free(buffer); - return true; -} -#endif - -static bool fb_8bpp_disc(int x, int y, int radius, colour c, bool filled) -{ - LOG(("x %d, y %d, rad %d, c 0x%lx, fill %d", x, y, radius, (unsigned long)c, filled)); - return true; -} - -static bool fb_8bpp_arc(int x, int y, int radius, int angle1, int angle2, - colour c) -{ - LOG(("x %d, y %d, radius %d, angle1 %d, angle2 %d, c 0x%lx", - x, y, radius, angle1, angle2, (unsigned long)c)); - return true; -} - - - -static bool fb_8bpp_bitmap(int x, int y, int width, int height, - struct bitmap *bitmap, colour bg, - struct content *content) -{ - uint8_t *pvideo; - colour *pixel = (colour *)bitmap->pixdata; - colour abpixel; /* alphablended pixel */ - int xloop, yloop; - int x0,y0,x1,y1; - int xoff, yoff; /* x and y offset into image */ - - /* LOG(("x %d, y %d, width %d, height %d, bitmap %p, content %p", - x,y,width,height,bitmap,content));*/ - - /* TODO here we should scale the image from bitmap->width to width, for - * now simply crop. - */ - if (width > bitmap->width) - width = bitmap->width; - - if (height > bitmap->height) - height = bitmap->height; - - /* The part of the scaled image actually displayed is cropped to the - * current context. - */ - x0 = x; - y0 = y; - x1 = x + width; - y1 = y + height; - - if (!fb_plotters_clip_rect_ctx(&x0, &y0, &x1, &y1)) - return true; - - if (height > (y1 - y0)) - height = (y1 - y0); - - if (width > (x1 - x0)) - width = (x1 - x0); - - xoff = x0 - x; - yoff = (y0 - y) * bitmap->width; - height = height * bitmap->width + yoff; - - /* plot the image */ - pvideo = fb_8bpp_get_xy_loc(x0, y0); - - if (bitmap->opaque) { - for (yloop = yoff; yloop < height; yloop += bitmap->width) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = pixel[yloop + xloop + xoff]; - *(pvideo + xloop) = fb_colour_to_pixel(abpixel); - } - pvideo += framebuffer->linelen; - } - } else { - for (yloop = yoff; yloop < height; yloop += bitmap->width) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = pixel[yloop + xloop + xoff]; - if ((abpixel & 0xFF000000) != 0) { - if ((abpixel & 0xFF000000) != 0xFF000000) { - abpixel = fb_plotters_ablend(abpixel, - fb_8bpp_to_colour(*(pvideo + xloop))); - } - - *(pvideo + xloop) = fb_colour_to_pixel(abpixel); - } - } - pvideo += framebuffer->linelen; - } - } - - return true; -} - -static bool fb_8bpp_bitmap_tile(int x, int y, int width, int height, - struct bitmap *bitmap, colour bg, - bool repeat_x, bool repeat_y, - struct content *content) -{ - return fb_plotters_bitmap_tile(x, y, width, height, - bitmap, bg, repeat_x, repeat_y, - content, fb_8bpp_bitmap); -} - -static bool fb_8bpp_flush(void) -{ - LOG(("%s()\n", __func__)); - return true; -} - -static bool fb_8bpp_path(const float *p, - unsigned int n, - colour fill, - float width, - colour c, - const float transform[6]) -{ - LOG(("%f, %d, 0x%lx, %f, 0x%lx, %f", - *p, n, (unsigned long)fill, width, (unsigned long)c, *transform)); - - return true; -} - -const struct plotter_table framebuffer_8bpp_plot = { - .clg = fb_8bpp_clg, - .rectangle = fb_8bpp_rectangle, - .line = fb_8bpp_line, - .polygon = fb_8bpp_polygon, - .fill = fb_8bpp_fill, - .clip = fb_clip, - .text = fb_8bpp_text, - .disc = fb_8bpp_disc, - .arc = fb_8bpp_arc, - .bitmap = fb_8bpp_bitmap, - .bitmap_tile = fb_8bpp_bitmap_tile, - .flush = fb_8bpp_flush, - .path = fb_8bpp_path, - .option_knockout = true, -}; - - -/* - * Local Variables: - * c-basic-offset:8 - * End: - */ diff --git a/src/32bpp_plotters.c b/src/32bpp_plotters.c deleted file mode 100644 index 243cdb4..0000000 --- a/src/32bpp_plotters.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright 2009 Vincent Sanders - * - * This file is part of libnsfb, http://www.netsurf-browser.org/ - * Licenced under the MIT License, - * http://www.opensource.org/licenses/mit-license.php - */ - -#include -#include -#include - -#include "libnsfb.h" -#include "libnsfb_plot.h" -#include "libnsfb_plot_util.h" - -#include "nsfb.h" -#include "plot.h" - -static inline uint32_t * -get_xy_loc(nsfb_t *nsfb, int x, int y) -{ - return (uint32_t *)(nsfb->ptr + (y * nsfb->linelen) + (x << 2)); -} - -#if __BYTE_ORDER == __BIG_ENDIAN -static inline nsfb_colour_t pixel_to_colour(uint32_t pixel) -{ - return (pixel >> 8) & ~0xFF000000U; -} - -/* convert a colour value to a 32bpp pixel value ready for screen output */ -static inline uint32_t colour_to_pixel(nsfb_colour_t c) -{ - return (c << 8); -} -#else /* __BYTE_ORDER == __BIG_ENDIAN */ -static inline nsfb_colour_t pixel_to_colour(uint32_t pixel) -{ - return ((pixel & 0xFF) << 16) | - ((pixel & 0xFF00)) | - ((pixel & 0xFF0000) >> 16); -} - -/* convert a colour value to a 32bpp pixel value ready for screen output */ -static inline uint32_t colour_to_pixel(nsfb_colour_t c) -{ - return ((c & 0xff0000) >> 16) | (c & 0xff00) | ((c & 0xff) << 16); -} -#endif - -#define SIGN(x) ((x<0) ? -1 : ((x>0) ? 1 : 0)) - -static bool -line(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen) -{ - int w; - uint32_t ent; - uint32_t *pvideo; - int x, y, i; - int dx, dy, sdy; - int dxabs, dyabs; - - ent = colour_to_pixel(pen->stroke_colour); - - for (;linec > 0; linec--) { - - if (line->y0 == line->y1) { - /* horizontal line special cased */ - - if (!nsfb_plot_clip_ctx(nsfb, line)) { - /* line outside clipping */ - line++; - continue; - } - - pvideo = get_xy_loc(nsfb, line->x0, line->y0); - - w = line->x1 - line->x0; - while (w-- > 0) - *(pvideo + w) = ent; - - } else { - /* standard bresenham line */ - - if (!nsfb_plot_clip_line_ctx(nsfb, line)) { - /* line outside clipping */ - line++; - continue; - } - - /* the horizontal distance of the line */ - dx = line->x1 - line->x0; - dxabs = abs (dx); - - /* the vertical distance of the line */ - dy = line->y1 - line->y0; - dyabs = abs (dy); - - sdy = dx ? SIGN(dy) * SIGN(dx) : SIGN(dy); - - if (dx >= 0) - pvideo = get_xy_loc(nsfb, line->x0, line->y0); - else - pvideo = get_xy_loc(nsfb, line->x1, line->y1); - - x = dyabs >> 1; - y = dxabs >> 1; - - if (dxabs >= dyabs) { - /* the line is more horizontal than vertical */ - for (i = 0; i < dxabs; i++) { - *pvideo = ent; - - pvideo++; - y += dyabs; - if (y >= dxabs) { - y -= dxabs; - pvideo += sdy * (nsfb->linelen>>2); - } - } - } else { - /* the line is more vertical than horizontal */ - for (i = 0; i < dyabs; i++) { - *pvideo = ent; - pvideo += sdy * (nsfb->linelen >> 2); - - x += dxabs; - if (x >= dyabs) { - x -= dyabs; - pvideo++; - } - } - } - - } - line++; - } - return true; -} - - - -static bool fill(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t c) -{ - int w; - uint32_t *pvid; - uint32_t ent; - uint32_t llen; - uint32_t width; - uint32_t height; - - if (!nsfb_plot_clip_ctx(nsfb, rect)) - return true; /* fill lies outside current clipping region */ - - ent = colour_to_pixel(c); - width = rect->x1 - rect->x0; - height = rect->y1 - rect->y0; - llen = (nsfb->linelen >> 2) - width; - - pvid = get_xy_loc(nsfb, rect->x0, rect->y0); - - while (height-- > 0) { - w = width; - while (w >= 16) { - *pvid++ = ent; *pvid++ = ent; - *pvid++ = ent; *pvid++ = ent; - *pvid++ = ent; *pvid++ = ent; - *pvid++ = ent; *pvid++ = ent; - *pvid++ = ent; *pvid++ = ent; - *pvid++ = ent; *pvid++ = ent; - *pvid++ = ent; *pvid++ = ent; - *pvid++ = ent; *pvid++ = ent; - w-=16; - } - while (w >= 4) { - *pvid++ = ent; *pvid++ = ent; - *pvid++ = ent; *pvid++ = ent; - w-=4; - } - while (w > 0) { - *pvid++ = ent; - w--; - } - pvid += llen; - } - - return true; -} - - - - -static bool point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c) -{ - uint32_t *pvideo; - - /* check point lies within clipping region */ - if ((x < nsfb->clip.x0) || - (x >= nsfb->clip.x1) || - (y < nsfb->clip.y0) || - (y >= nsfb->clip.y1)) - return true; - - pvideo = get_xy_loc(nsfb, x, y); - - if ((c & 0xFF000000) != 0) { - if ((c & 0xFF000000) != 0xFF000000) { - c = nsfb_plot_ablend(c, pixel_to_colour(*pvideo)); - } - - *pvideo = colour_to_pixel(c); - } - return true; -} - -static bool -glyph1(nsfb_t *nsfb, - nsfb_bbox_t *loc, - const uint8_t *pixel, - int pitch, - nsfb_colour_t c) -{ - uint32_t *pvideo; - int xloop, yloop; - int xoff, yoff; /* x and y offset into image */ - int x = loc->x0; - int y = loc->y0; - int width = loc->x1 - loc->x0; - int height = loc->y1 - loc->y0; - uint32_t fgcol; - const uint8_t *fntd; - uint8_t row; - - if (!nsfb_plot_clip_ctx(nsfb, loc)) - return true; - - if (height > (loc->y1 - loc->y0)) - height = (loc->y1 - loc->y0); - - if (width > (loc->x1 - loc->x0)) - width = (loc->x1 - loc->x0); - - xoff = loc->x0 - x; - yoff = loc->y0 - y; - - pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); - - fgcol = colour_to_pixel(c); - - for (yloop = yoff; yloop < height; yloop++) { - fntd = pixel + (yloop * (pitch>>3)) + (xoff>>3); - row = (*fntd++) << (xoff & 3); - for (xloop = xoff; xloop < width ; xloop++) { - if (((xloop % 8) == 0) && (xloop != 0)) { - row = *fntd++; - } - - if ((row & 0x80) != 0) { - *(pvideo + xloop) = fgcol; - } - row = row << 1; - - } - - pvideo += (nsfb->linelen >> 2); - } - - return true; -} - -static bool -glyph8(nsfb_t *nsfb, - nsfb_bbox_t *loc, - const uint8_t *pixel, - int pitch, - nsfb_colour_t c) -{ - uint32_t *pvideo; - nsfb_colour_t abpixel; /* alphablended pixel */ - int xloop, yloop; - int xoff, yoff; /* x and y offset into image */ - int x = loc->x0; - int y = loc->y0; - int width = loc->x1 - loc->x0; - int height = loc->y1 - loc->y0; - uint32_t fgcol; - - if (!nsfb_plot_clip_ctx(nsfb, loc)) - return true; - - if (height > (loc->y1 - loc->y0)) - height = (loc->y1 - loc->y0); - - if (width > (loc->x1 - loc->x0)) - width = (loc->x1 - loc->x0); - - xoff = loc->x0 - x; - yoff = loc->y0 - y; - - pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); - - fgcol = c & 0xFFFFFF; - - for (yloop = 0; yloop < height; yloop++) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = (pixel[((yoff + yloop) * pitch) + xloop + xoff] << 24) | fgcol; - if ((abpixel & 0xFF000000) != 0) { - /* pixel is not transparent */ - if ((abpixel & 0xFF000000) != 0xFF000000) { - abpixel = nsfb_plot_ablend(abpixel, - pixel_to_colour(*(pvideo + xloop))); - } - - *(pvideo + xloop) = colour_to_pixel(abpixel); - } - } - pvideo += (nsfb->linelen >> 2); - } - - return true; -} - -static bool -bitmap(nsfb_t *nsfb, - const nsfb_bbox_t *loc, - const nsfb_colour_t *pixel, - int bmp_width, - int bmp_height, - int bmp_stride, - bool alpha) -{ - uint32_t *pvideo; - nsfb_colour_t abpixel = 0; /* alphablended pixel */ - int xloop, yloop; - int xoff, yoff; /* x and y offset into image */ - int x = loc->x0; - int y = loc->y0; - int width = loc->x1 - loc->x0; - int height = loc->y1 - loc->y0; - nsfb_bbox_t clipped; /* clipped display */ - - /* TODO here we should scale the image from bmp_width to width, for - * now simply crop. - */ - if (width > bmp_width) - width = bmp_width; - - if (height > bmp_height) - height = bmp_height; - - /* The part of the scaled image actually displayed is cropped to the - * current context. - */ - clipped.x0 = x; - clipped.y0 = y; - clipped.x1 = x + width; - clipped.y1 = y + height; - - if (!nsfb_plot_clip_ctx(nsfb, &clipped)) { - return true; - } - - if (height > (clipped.y1 - clipped.y0)) - height = (clipped.y1 - clipped.y0); - - if (width > (clipped.x1 - clipped.x0)) - width = (clipped.x1 - clipped.x0); - - xoff = clipped.x0 - x; - yoff = (clipped.y0 - y) * bmp_width; - height = height * bmp_stride + yoff; - - /* plot the image */ - pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0); - - if (alpha) { - for (yloop = yoff; yloop < height; yloop += bmp_stride) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = pixel[yloop + xloop + xoff]; - if ((abpixel & 0xFF000000) != 0) { - if ((abpixel & 0xFF000000) != 0xFF000000) { - abpixel = nsfb_plot_ablend(abpixel, - pixel_to_colour(*(pvideo + xloop))); - } - - *(pvideo + xloop) = colour_to_pixel(abpixel); - } - } - pvideo += (nsfb->linelen >> 2); - } - } else { - for (yloop = yoff; yloop < height; yloop += bmp_stride) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = pixel[yloop + xloop + xoff]; - *(pvideo + xloop) = colour_to_pixel(abpixel); - } - pvideo += (nsfb->linelen >> 2); - } - } - return true; -} - -static bool readrect(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer) -{ - uint32_t *pvideo; - int xloop, yloop; - int width; - - if (!nsfb_plot_clip_ctx(nsfb, rect)) { - return true; - } - - width = rect->x1 - rect->x0; - - pvideo = get_xy_loc(nsfb, rect->x0, rect->y0); - - for (yloop = rect->y0; yloop < rect->y1; yloop += 1) { - for (xloop = 0; xloop < width; xloop++) { - *buffer = pixel_to_colour(*(pvideo + xloop)); - buffer++; - } - pvideo += (nsfb->linelen >> 2); - } - return true; -} - -const nsfb_plotter_fns_t _nsfb_32bpp_plotters = { - .line = line, - .fill = fill, - .point = point, - .bitmap = bitmap, - .glyph8 = glyph8, - .glyph1 = glyph1, - .readrect = readrect, -}; - -/* - * Local Variables: - * c-basic-offset:8 - * End: - */ diff --git a/src/8bpp_plotters.c b/src/8bpp_plotters.c deleted file mode 100644 index b29d241..0000000 --- a/src/8bpp_plotters.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright 2009 Vincent Sanders - * - * This file is part of libnsfb, http://www.netsurf-browser.org/ - * Licenced under the MIT License, - * http://www.opensource.org/licenses/mit-license.php - */ - -#include -#include -#include -#include -#include - -#include "libnsfb.h" -#include "libnsfb_plot.h" -#include "libnsfb_plot_util.h" - -#include "nsfb.h" -#include "plot.h" - -static inline uint8_t *get_xy_loc(nsfb_t *nsfb, int x, int y) -{ - return (uint8_t *)(nsfb->ptr + (y * nsfb->linelen) + (x)); -} - - -static inline nsfb_colour_t pixel_to_colour(nsfb_t *nsfb, uint8_t pixel) -{ - return nsfb->palette[pixel]; -} - -static uint8_t -colour_to_pixel(nsfb_t *nsfb, nsfb_colour_t c) -{ - nsfb_colour_t palent; - int col; - - int dr, dg, db; /* delta red, green blue values */ - - int cur_distance; - int best_distance = INT_MAX; - uint8_t best_col = 0; - - for (col = 0; col < 256; col++) { - palent = nsfb->palette[col]; - - dr = (c & 0xFF) - (palent & 0xFF); - dg = ((c >> 8) & 0xFF) - ((palent >> 8) & 0xFF); - db = ((c >> 16) & 0xFF) - ((palent >> 16) & 0xFF); - cur_distance = ((dr * dr) + (dg * dg) + (db *db)); - if (cur_distance < best_distance) { - best_distance = cur_distance; - best_col = col; - } - } - - return best_col; -} - -#define SIGN(x) ((x<0) ? -1 : ((x>0) ? 1 : 0)) - -static bool -line(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen) -{ - int w; - uint8_t ent; - uint8_t *pvideo; - int x, y, i; - int dx, dy, sdy; - int dxabs, dyabs; - - ent = colour_to_pixel(nsfb, pen->stroke_colour); - - for (;linec > 0; linec--) { - - if (line->y0 == line->y1) { - /* horizontal line special cased */ - - if (!nsfb_plot_clip_ctx(nsfb, line)) { - /* line outside clipping */ - line++; - continue; - } - - pvideo = get_xy_loc(nsfb, line->x0, line->y0); - - w = line->x1 - line->x0; - while (w-- > 0) - *(pvideo + w) = ent; - - } else { - /* standard bresenham line */ - - if (!nsfb_plot_clip_line_ctx(nsfb, line)) { - /* line outside clipping */ - line++; - continue; - } - - /* the horizontal distance of the line */ - dx = line->x1 - line->x0; - dxabs = abs (dx); - - /* the vertical distance of the line */ - dy = line->y1 - line->y0; - dyabs = abs (dy); - - sdy = dx ? SIGN(dy) * SIGN(dx) : SIGN(dy); - - if (dx >= 0) - pvideo = get_xy_loc(nsfb, line->x0, line->y0); - else - pvideo = get_xy_loc(nsfb, line->x1, line->y1); - - x = dyabs >> 1; - y = dxabs >> 1; - - if (dxabs >= dyabs) { - /* the line is more horizontal than vertical */ - for (i = 0; i < dxabs; i++) { - *pvideo = ent; - - pvideo++; - y += dyabs; - if (y >= dxabs) { - y -= dxabs; - pvideo += sdy * nsfb->linelen; - } - } - } else { - /* the line is more vertical than horizontal */ - for (i = 0; i < dyabs; i++) { - *pvideo = ent; - pvideo += sdy * nsfb->linelen; - - x += dxabs; - if (x >= dyabs) { - x -= dyabs; - pvideo++; - } - } - } - - } - line++; - } - - return true; -} - -static bool fill(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t c) -{ - int y; - uint8_t ent; - uint8_t *pvideo; - - if (!nsfb_plot_clip_ctx(nsfb, rect)) - return true; /* fill lies outside current clipping region */ - - pvideo = get_xy_loc(nsfb, rect->x0, rect->y0); - - ent = colour_to_pixel(nsfb, c); - - for (y = rect->y0; y < rect->y1; y++) { - memset(pvideo, ent, rect->x1 - rect->x0); - pvideo += nsfb->linelen; - } - - return true; -} - -static bool point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c) -{ - uint8_t *pvideo; - - /* check point lies within clipping region */ - if ((x < nsfb->clip.x0) || - (x >= nsfb->clip.x1) || - (y < nsfb->clip.y0) || - (y >= nsfb->clip.y1)) - return true; - - pvideo = get_xy_loc(nsfb, x, y); - - if ((c & 0xFF000000) != 0) { - if ((c & 0xFF000000) != 0xFF000000) { - c = nsfb_plot_ablend(c, pixel_to_colour(nsfb, *pvideo)); - } - - *pvideo = colour_to_pixel(nsfb, c); - } - return true; -} - -static bool -glyph1(nsfb_t *nsfb, - nsfb_bbox_t *loc, - const uint8_t *pixel, - int pitch, - nsfb_colour_t c) -{ - uint8_t *pvideo; - int xloop, yloop; - int xoff, yoff; /* x and y offset into image */ - int x = loc->x0; - int y = loc->y0; - int width = loc->x1 - loc->x0; - int height = loc->y1 - loc->y0; - uint8_t fgcol; - const uint8_t *fntd; - uint8_t row; - - if (!nsfb_plot_clip_ctx(nsfb, loc)) - return true; - - if (height > (loc->y1 - loc->y0)) - height = (loc->y1 - loc->y0); - - if (width > (loc->x1 - loc->x0)) - width = (loc->x1 - loc->x0); - - xoff = loc->x0 - x; - yoff = loc->y0 - y; - - pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); - - fgcol = colour_to_pixel(nsfb, c); - - for (yloop = yoff; yloop < height; yloop++) { - fntd = pixel + (yloop * (pitch>>3)) + (xoff>>3); - row = (*fntd++) << (xoff & 3); - for (xloop = xoff; xloop < width ; xloop++) { - if (((xloop % 8) == 0) && (xloop != 0)) { - row = *fntd++; - } - - if ((row & 0x80) != 0) { - *(pvideo + xloop) = fgcol; - } - row = row << 1; - - } - - pvideo += nsfb->linelen; - } - - return true; -} - -static bool -glyph8(nsfb_t *nsfb, - nsfb_bbox_t *loc, - const uint8_t *pixel, - int pitch, - nsfb_colour_t c) -{ - uint8_t *pvideo; - nsfb_colour_t abpixel; /* alphablended pixel */ - int xloop, yloop; - int xoff, yoff; /* x and y offset into image */ - int x = loc->x0; - int y = loc->y0; - int width = loc->x1 - loc->x0; - int height = loc->y1 - loc->y0; - uint8_t fgcol; - - if (!nsfb_plot_clip_ctx(nsfb, loc)) - return true; - - if (height > (loc->y1 - loc->y0)) - height = (loc->y1 - loc->y0); - - if (width > (loc->x1 - loc->x0)) - width = (loc->x1 - loc->x0); - - xoff = loc->x0 - x; - yoff = loc->y0 - y; - - pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); - - fgcol = c & 0xFFFFFF; - - for (yloop = 0; yloop < height; yloop++) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = (pixel[((yoff + yloop) * pitch) + xloop + xoff] << 24) | fgcol; - if ((abpixel & 0xFF000000) != 0) { - /* pixel is not transparent */ - if ((abpixel & 0xFF000000) != 0xFF000000) { - abpixel = nsfb_plot_ablend(abpixel, - pixel_to_colour(nsfb, *(pvideo + xloop))); - } - - *(pvideo + xloop) = colour_to_pixel(nsfb, abpixel); - } - } - pvideo += nsfb->linelen; - } - - return true; -} - -static bool -bitmap(nsfb_t *nsfb, - const nsfb_bbox_t *loc, - const nsfb_colour_t *pixel, - int bmp_width, - int bmp_height, - int bmp_stride, - bool alpha) -{ - uint8_t *pvideo; - nsfb_colour_t abpixel = 0; /* alphablended pixel */ - int xloop, yloop; - int xoff, yoff; /* x and y offset into image */ - int x = loc->x0; - int y = loc->y0; - int width = loc->x1 - loc->x0; - int height = loc->y1 - loc->y0; - nsfb_bbox_t clipped; /* clipped display */ - - /* TODO here we should scale the image from bmp_width to width, for - * now simply crop. - */ - if (width > bmp_width) - width = bmp_width; - - if (height > bmp_height) - height = bmp_height; - - /* The part of the scaled image actually displayed is cropped to the - * current context. - */ - clipped.x0 = x; - clipped.y0 = y; - clipped.x1 = x + width; - clipped.y1 = y + height; - - if (!nsfb_plot_clip_ctx(nsfb, &clipped)) - return true; - - if (height > (clipped.y1 - clipped.y0)) - height = (clipped.y1 - clipped.y0); - - if (width > (clipped.x1 - clipped.x0)) - width = (clipped.x1 - clipped.x0); - - xoff = clipped.x0 - x; - yoff = (clipped.y0 - y) * bmp_width; - height = height * bmp_stride + yoff; - - /* plot the image */ - pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0); - - if (alpha) { - for (yloop = yoff; yloop < height; yloop += bmp_stride) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = pixel[yloop + xloop + xoff]; - if ((abpixel & 0xFF000000) != 0) { - if ((abpixel & 0xFF000000) != 0xFF000000) { - abpixel = nsfb_plot_ablend(abpixel, - pixel_to_colour(nsfb, *(pvideo + xloop))); - } - - *(pvideo + xloop) = colour_to_pixel(nsfb, abpixel); - } - } - pvideo += nsfb->linelen; - } - } else { - for (yloop = yoff; yloop < height; yloop += bmp_stride) { - for (xloop = 0; xloop < width; xloop++) { - abpixel = pixel[yloop + xloop + xoff]; - *(pvideo + xloop) = colour_to_pixel(nsfb, abpixel); - } - pvideo += nsfb->linelen; - } - } - return true; -} - - - - - - -const nsfb_plotter_fns_t _nsfb_8bpp_plotters = { - .line = line, - .fill = fill, - .point = point, - .bitmap = bitmap, - .glyph8 = glyph8, - .glyph1 = glyph1, -}; - - -/* - * Local Variables: - * c-basic-offset:8 - * End: - */ diff --git a/src/Makefile b/src/Makefile index 9774acd..f573d7a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ # Sources -DIR_SOURCES := libnsfb.c frontend.c frontend_sdl.c frontend_linux.c frontend_vnc.c frontend_able.c frontend_ram.c cursor.c plot.c plot_util.c plotters.c 32bpp_plotters.c 16bpp_plotters.c 8bpp_plotters.c - +DIR_SOURCES := libnsfb.c frontend.c frontend_sdl.c frontend_vnc.c frontend_able.c frontend_ram.c cursor.c +#frontend_linux.c include build/makefiles/Makefile.subdir diff --git a/src/frontend_linux.c b/src/frontend_linux.c index e65c888..e6e7601 100644 --- a/src/frontend_linux.c +++ b/src/frontend_linux.c @@ -37,7 +37,14 @@ static int linux_set_geometry(nsfb_t *nsfb, int width, int height, int bpp) static int linux_initialise(nsfb_t *nsfb) { - UNUSED(nsfb); + if (nsfb->frontend_priv != NULL) + return -1; + + /* sanity checked depth. */ + if ((nsfb->bpp != 32) && (nsfb->bpp != 16) && (nsfb->bpp != 8)) + return -1; + + return 0; } @@ -55,10 +62,69 @@ static bool linux_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout) return false; } +static int linux_claim(nsfb_t *nsfb, nsfb_bbox_t *box) +{ + struct nsfb_cursor_s *cursor = nsfb->cursor; + + if ((cursor != NULL) && + (cursor->plotted == true) && + (nsfb_plot_bbox_intersect(box, &cursor->loc))) { + + nsfb->plotter_fns->bitmap(nsfb, + &cursor->savloc, + cursor->sav, + cursor->sav_width, + cursor->sav_height, + cursor->sav_width, + false); + cursor->plotted = false; + } + return 0; +} + +static int linux_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor) +{ + nsfb_bbox_t sclip; + + if ((cursor != NULL) && (cursor->plotted == true)) { + sclip = nsfb->clip; + + nsfb->plotter_fns->set_clip(nsfb, NULL); + + nsfb->plotter_fns->bitmap(nsfb, + &cursor->savloc, + cursor->sav, + cursor->sav_width, + cursor->sav_height, + cursor->sav_width, + false); + + nsfb_cursor_plot(nsfb, cursor); + + nsfb->clip = sclip; + } + return true; +} + + +static int linux_release(nsfb_t *nsfb, nsfb_bbox_t *box) +{ + struct nsfb_cursor_s *cursor = nsfb->cursor; + + if ((cursor != NULL) && (cursor->plotted == false)) { + nsfb_cursor_plot(nsfb, cursor); + } + + return 0; +} + const nsfb_frontend_rtns_t linux_rtns = { .initialise = linux_initialise, .finalise = linux_finalise, .input = linux_input, + .claim = linux_claim, + .release = linux_release, + .cursor = linux_cursor, .geometry = linux_set_geometry, }; diff --git a/src/plot.c b/src/plot.c deleted file mode 100644 index 4de25c9..0000000 --- a/src/plot.c +++ /dev/null @@ -1,169 +0,0 @@ -/* public plotter interface */ - -#include - -#include "libnsfb.h" -#include "libnsfb_plot.h" - -#include "nsfb.h" -#include "plot.h" - -/** Sets a clip rectangle for subsequent plots. - * - * Sets a clipping area which constrains all subsequent plotting operations. - * The clipping area must lie within the framebuffer visible screen or false - * will be returned and the new clipping area not set. - */ -bool nsfb_plot_set_clip(nsfb_t *nsfb, nsfb_bbox_t *clip) -{ - return nsfb->plotter_fns->set_clip(nsfb, clip); -} - -/** Get the previously set clipping region. - */ -bool nsfb_plot_get_clip(nsfb_t *nsfb, nsfb_bbox_t *clip) -{ - return nsfb->plotter_fns->get_clip(nsfb, clip); -} - -/** Clears plotting area to a flat colour. - */ -bool nsfb_plot_clg(nsfb_t *nsfb, nsfb_colour_t c) -{ - return nsfb->plotter_fns->clg(nsfb, c); -} - -/** Plots a rectangle outline. - * - * The line can be solid, dotted or dashed. Top left corner at (x0,y0) and - * rectangle has given width and height. - */ -bool -nsfb_plot_rectangle(nsfb_t *nsfb, - nsfb_bbox_t *rect, - int line_width, - nsfb_colour_t c, - bool dotted, - bool dashed) -{ - return nsfb->plotter_fns->rectangle(nsfb, rect, line_width, c, dotted, dashed); - -} - -/** Plots a filled rectangle. Top left corner at (x0,y0), bottom - * right corner at (x1,y1). Note: (x0,y0) is inside filled area, - * but (x1,y1) is below and to the right. See diagram below. - */ -bool nsfb_plot_rectangle_fill(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t c) -{ - return nsfb->plotter_fns->fill(nsfb, rect, c); -} - -/** Plots a line. - * - * Draw a line from (x0,y0) to (x1,y1). Coordinates are at centre of line - * width/thickness. - */ -bool nsfb_plot_line(nsfb_t *nsfb, nsfb_bbox_t *line, nsfb_plot_pen_t *pen) -{ - return nsfb->plotter_fns->line(nsfb, 1, line, pen); -} - -/** Plots more than one line. - * - * Draw a line from (x0,y0) to (x1,y1). Coordinates are at centre of line - * width/thickness. - */ -bool nsfb_plot_lines(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen) -{ - return nsfb->plotter_fns->line(nsfb, linec, line, pen); -} - -/** Plots a filled polygon. - * - * Plots a filled polygon with straight lines between points. The lines around - * the edge of the ploygon are not plotted. The polygon is filled with a - * non-zero winding rule. - * - * - */ -bool nsfb_plot_polygon(nsfb_t *nsfb, const int *p, unsigned int n, nsfb_colour_t fill) -{ - return nsfb->plotter_fns->polygon(nsfb, p, n, fill); -} - -/** Plots an arc. - * - * around (x,y), from anticlockwise from angle1 to angle2. Angles are measured - * anticlockwise from horizontal, in degrees. - */ -bool nsfb_plot_arc(nsfb_t *nsfb, int x, int y, int radius, int angle1, int angle2, nsfb_colour_t c) -{ - return nsfb->plotter_fns->arc(nsfb, x, y, radius, angle1, angle2, c); -} - -/** Plots an alpha blended pixel. - * - * plots an alpha blended pixel. - */ -bool nsfb_plot_point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c) -{ - return nsfb->plotter_fns->point(nsfb, x, y, c); -} - -bool nsfb_plot_ellipse(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c) -{ - return nsfb->plotter_fns->ellipse(nsfb, ellipse, c); -} - -bool nsfb_plot_ellipse_fill(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c) -{ - return nsfb->plotter_fns->ellipse_fill(nsfb, ellipse, c); -} - -bool nsfb_plot_copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox) -{ - return nsfb->plotter_fns->copy(nsfb, srcbox, dstbox); -} - -bool nsfb_plot_bitmap(nsfb_t *nsfb, const nsfb_bbox_t *loc, const nsfb_colour_t *pixel, int bmp_width, int bmp_height, int bmp_stride, bool alpha) -{ - return nsfb->plotter_fns->bitmap(nsfb, loc, pixel, bmp_width, bmp_height, bmp_stride, alpha); -} - -/** Plot an 8 bit glyph. - */ -bool nsfb_plot_glyph8(nsfb_t *nsfb, nsfb_bbox_t *loc, const uint8_t *pixel, int pitch, nsfb_colour_t c) -{ - return nsfb->plotter_fns->glyph8(nsfb, loc, pixel, pitch, c); -} - - -/** Plot an 1 bit glyph. - */ -bool nsfb_plot_glyph1(nsfb_t *nsfb, nsfb_bbox_t *loc, const uint8_t *pixel, int pitch, nsfb_colour_t c) -{ - return nsfb->plotter_fns->glyph1(nsfb, loc, pixel, pitch, c); -} - -/* read a rectangle from screen into buffer */ -bool nsfb_plot_readrect(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer) -{ - return nsfb->plotter_fns->readrect(nsfb, rect, buffer); -} - - -bool nsfb_plot_cubic_bezier(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_point_t *ctrlb, nsfb_colour_t c) -{ - return nsfb->plotter_fns->cubic(nsfb, curve, ctrla, ctrlb, c); -} - -bool nsfb_plot_quadratic_bezier(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_colour_t c) -{ - return nsfb->plotter_fns->quadratic(nsfb, curve, ctrla, c); -} - -bool nsfb_plot_path(nsfb_t *nsfb, int pathc, nsfb_plot_pathop_t *pathop, nsfb_plot_pen_t *pen) -{ - return nsfb->plotter_fns->path(nsfb, pathc, pathop, pen); -} diff --git a/src/plot/16bpp.c b/src/plot/16bpp.c new file mode 100644 index 0000000..8feb095 --- /dev/null +++ b/src/plot/16bpp.c @@ -0,0 +1,448 @@ +/* + * Copyright 2009 Vincent Sanders + * + * This file is part of libnsfb, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + */ + +#include +#include +#include + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "libnsfb_plot_util.h" + +#include "nsfb.h" +#include "plot.h" + +static inline uint16_t *get_xy_loc(nsfb_t *nsfb, int x, int y) +{ + return (void *)(nsfb->ptr + (y * nsfb->linelen) + (x << 1)); +} + +static inline nsfb_colour_t pixel_to_colour(uint16_t pixel) +{ + return ((pixel & 0x1F) << 19) | + ((pixel & 0x7E0) << 5) | + ((pixel & 0xF800) >> 8); +} + +/* convert a colour value to a 16bpp pixel value ready for screen output */ +static inline uint16_t colour_to_pixel(nsfb_colour_t c) +{ + return ((c & 0xF8) << 8) | ((c & 0xFC00 ) >> 5) | ((c & 0xF80000) >> 19); +} + +#define SIGN(x) ((x<0) ? -1 : ((x>0) ? 1 : 0)) + + +static bool +line(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen) +{ + int w; + uint16_t ent; + uint16_t *pvideo; + int x, y, i; + int dx, dy, sdy; + int dxabs, dyabs; + + ent = colour_to_pixel(pen->stroke_colour); + + for (;linec > 0; linec--) { + + if (line->y0 == line->y1) { + /* horizontal line special cased */ + + if (!nsfb_plot_clip_ctx(nsfb, line)) { + /* line outside clipping */ + line++; + continue; + } + + pvideo = get_xy_loc(nsfb, line->x0, line->y0); + + w = line->x1 - line->x0; + while (w-- > 0) + *(pvideo + w) = ent; + + } else { + /* standard bresenham line */ + if (!nsfb_plot_clip_line_ctx(nsfb, line)) { + /* line outside clipping */ + line++; + continue; + } + + /* the horizontal distance of the line */ + dx = line->x1 - line->x0; + dxabs = abs (dx); + + /* the vertical distance of the line */ + dy = line->y1 - line->y0; + dyabs = abs (dy); + + sdy = dx ? SIGN(dy) * SIGN(dx) : SIGN(dy); + + if (dx >= 0) + pvideo = get_xy_loc(nsfb, line->x0, line->y0); + else + pvideo = get_xy_loc(nsfb, line->x1, line->y1); + + x = dyabs >> 1; + y = dxabs >> 1; + + if (dxabs >= dyabs) { + /* the line is more horizontal than vertical */ + for (i = 0; i < dxabs; i++) { + *pvideo = ent; + + pvideo++; + y += dyabs; + if (y >= dxabs) { + y -= dxabs; + pvideo += sdy * (nsfb->linelen>>1); + } + } + } else { + /* the line is more vertical than horizontal */ + for (i = 0; i < dyabs; i++) { + *pvideo = ent; + pvideo += sdy * (nsfb->linelen >> 1); + + x += dxabs; + if (x >= dyabs) { + x -= dyabs; + pvideo++; + } + } + } + + } + line++; + } + return true; +} + + + +static bool fill(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t c) +{ + int w; + uint16_t *pvid16; + uint16_t ent16; + uint32_t *pvid32; + uint32_t ent32; + uint32_t llen; + uint32_t width; + uint32_t height; + + if (!nsfb_plot_clip_ctx(nsfb, rect)) + return true; /* fill lies outside current clipping region */ + + ent16 = colour_to_pixel(c); + width = rect->x1 - rect->x0; + height = rect->y1 - rect->y0; + + pvid16 = get_xy_loc(nsfb, rect->x0, rect->y0); + + if (((rect->x0 & 1) == 0) && ((width & 1) == 0)) { + /* aligned to 32bit value and width is even */ + width = width >> 1; + llen = (nsfb->linelen >> 2) - width; + ent32 = ent16 | (ent16 << 16); + pvid32 = (uint32_t *)pvid16; + + while (height-- > 0) { + w = width; + while (w >= 16) { + *pvid32++ = ent32; *pvid32++ = ent32; + *pvid32++ = ent32; *pvid32++ = ent32; + *pvid32++ = ent32; *pvid32++ = ent32; + *pvid32++ = ent32; *pvid32++ = ent32; + *pvid32++ = ent32; *pvid32++ = ent32; + *pvid32++ = ent32; *pvid32++ = ent32; + *pvid32++ = ent32; *pvid32++ = ent32; + *pvid32++ = ent32; *pvid32++ = ent32; + w-=16; + } + while (w >= 4) { + *pvid32++ = ent32; *pvid32++ = ent32; + *pvid32++ = ent32; *pvid32++ = ent32; + w-=4; + } + while (w > 0) { + *pvid32++ = ent32; + w--; + } + // for (w = width; w > 0; w--) *pvid32++ = ent32; + pvid32 += llen; + } + + } else { + llen = (nsfb->linelen >> 1) - width; + + + while (height-- > 0) { + for (w = width; w > 0; w--) *pvid16++ = ent16; + pvid16 += llen; + } + } + return true; +} + + +static bool point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c) +{ + uint16_t *pvideo; + + /* check point lies within clipping region */ + if ((x < nsfb->clip.x0) || + (x >= nsfb->clip.x1) || + (y < nsfb->clip.y0) || + (y >= nsfb->clip.y1)) + return true; + + pvideo = get_xy_loc(nsfb, x, y); + + if ((c & 0xFF000000) != 0) { + if ((c & 0xFF000000) != 0xFF000000) { + c = nsfb_plot_ablend(c, pixel_to_colour(*pvideo)); + } + + *pvideo = colour_to_pixel(c); + } + return true; +} + +static bool +glyph1(nsfb_t *nsfb, + nsfb_bbox_t *loc, + const uint8_t *pixel, + int pitch, + nsfb_colour_t c) +{ + uint16_t *pvideo; + int xloop, yloop; + int xoff, yoff; /* x and y offset into image */ + int x = loc->x0; + int y = loc->y0; + int width = loc->x1 - loc->x0; + int height = loc->y1 - loc->y0; + uint16_t fgcol; + const uint8_t *fntd; + uint8_t row; + + if (!nsfb_plot_clip_ctx(nsfb, loc)) + return true; + + if (height > (loc->y1 - loc->y0)) + height = (loc->y1 - loc->y0); + + if (width > (loc->x1 - loc->x0)) + width = (loc->x1 - loc->x0); + + xoff = loc->x0 - x; + yoff = loc->y0 - y; + + pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); + + fgcol = colour_to_pixel(c); + + for (yloop = yoff; yloop < height; yloop++) { + fntd = pixel + (yloop * (pitch>>3)) + (xoff>>3); + row = (*fntd++) << (xoff & 3); + for (xloop = xoff; xloop < width ; xloop++) { + if (((xloop % 8) == 0) && (xloop != 0)) { + row = *fntd++; + } + + if ((row & 0x80) != 0) { + *(pvideo + xloop) = fgcol; + } + row = row << 1; + + } + + pvideo += (nsfb->linelen >> 1); + } + + return true; +} + +static bool +glyph8(nsfb_t *nsfb, + nsfb_bbox_t *loc, + const uint8_t *pixel, + int pitch, + nsfb_colour_t c) +{ + uint16_t *pvideo; + nsfb_colour_t abpixel; /* alphablended pixel */ + int xloop, yloop; + int xoff, yoff; /* x and y offset into image */ + int x = loc->x0; + int y = loc->y0; + int width = loc->x1 - loc->x0; + int height = loc->y1 - loc->y0; + uint16_t fgcol; + + if (!nsfb_plot_clip_ctx(nsfb, loc)) + return true; + + if (height > (loc->y1 - loc->y0)) + height = (loc->y1 - loc->y0); + + if (width > (loc->x1 - loc->x0)) + width = (loc->x1 - loc->x0); + + xoff = loc->x0 - x; + yoff = loc->y0 - y; + + pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); + + fgcol = c & 0xFFFFFF; + + for (yloop = 0; yloop < height; yloop++) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = (pixel[((yoff + yloop) * pitch) + xloop + xoff] << 24) | fgcol; + if ((abpixel & 0xFF000000) != 0) { + /* pixel is not transparent */ + if ((abpixel & 0xFF000000) != 0xFF000000) { + abpixel = nsfb_plot_ablend(abpixel, + pixel_to_colour(*(pvideo + xloop))); + } + + *(pvideo + xloop) = colour_to_pixel(abpixel); + } + } + pvideo += (nsfb->linelen >> 1); + } + + return true; +} + +static bool +bitmap(nsfb_t *nsfb, + const nsfb_bbox_t *loc, + const nsfb_colour_t *pixel, + int bmp_width, + int bmp_height, + int bmp_stride, + bool alpha) +{ + uint16_t *pvideo; + nsfb_colour_t abpixel; /* alphablended pixel */ + int xloop, yloop; + int xoff, yoff; /* x and y offset into image */ + int x = loc->x0; + int y = loc->y0; + int width = loc->x1 - loc->x0; + int height = loc->y1 - loc->y0; + nsfb_bbox_t clipped; /* clipped display */ + + + /* TODO here we should scale the image from bitmap->width to width, for + * now simply crop. + */ + if (width > bmp_width) + width = bmp_width; + + if (height > bmp_height) + height = bmp_height; + + /* The part of the scaled image actually displayed is cropped to the + * current context. + */ + clipped.x0 = x; + clipped.y0 = y; + clipped.x1 = x + width; + clipped.y1 = y + height; + + if (!nsfb_plot_clip_ctx(nsfb, &clipped)) + return true; + + if (height > (clipped.y1 - clipped.y0)) + height = (clipped.y1 - clipped.y0); + + if (width > (clipped.x1 - clipped.x0)) + width = (clipped.x1 - clipped.x0); + + + xoff = clipped.x0 - x; + yoff = (clipped.y0 - y) * bmp_width; + height = height * bmp_width + yoff; + + /* plot the image */ + pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0); + + if (alpha) { + for (yloop = yoff; yloop < height; yloop += bmp_stride) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = pixel[yloop + xloop + xoff]; + if ((abpixel & 0xFF000000) != 0) { + if ((abpixel & 0xFF000000) != 0xFF000000) { + abpixel = nsfb_plot_ablend(abpixel, + pixel_to_colour(*(pvideo + xloop))); + } + + *(pvideo + xloop) = colour_to_pixel(abpixel); + } + } + pvideo += (nsfb->linelen >> 1); + } + } else { + for (yloop = yoff; yloop < height; yloop += bmp_stride) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = pixel[yloop + xloop + xoff]; + *(pvideo + xloop) = colour_to_pixel(abpixel); + } + pvideo += (nsfb->linelen >> 1); + } + } + + return true; +} + + +static bool readrect(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer) +{ + uint16_t *pvideo; + int xloop, yloop; + int width; + + if (!nsfb_plot_clip_ctx(nsfb, rect)) { + return true; + } + + width = rect->x1 - rect->x0; + + pvideo = get_xy_loc(nsfb, rect->x0, rect->y0); + + for (yloop = rect->y0; yloop < rect->y1; yloop += 1) { + for (xloop = 0; xloop < width; xloop++) { + *buffer = pixel_to_colour(*(pvideo + xloop)); + buffer++; + } + pvideo += (nsfb->linelen >> 1); + } + return true; +} + + +const nsfb_plotter_fns_t _nsfb_16bpp_plotters = { + .line = line, + .fill = fill, + .point = point, + .bitmap = bitmap, + .glyph8 = glyph8, + .glyph1 = glyph1, + .readrect = readrect, +}; + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/src/plot/1bpp.c b/src/plot/1bpp.c new file mode 100644 index 0000000..bd511e7 --- /dev/null +++ b/src/plot/1bpp.c @@ -0,0 +1,266 @@ +/* + * Copyright 2008 Vincent Sanders + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include "utils/log.h" +#include "utils/utf8.h" +#include "desktop/plotters.h" + +#include "framebuffer/fb_gui.h" +#include "framebuffer/fb_plotters.h" +#include "framebuffer/fb_bitmap.h" +#include "framebuffer/fb_font.h" + +extern struct fb_info_s *fbinfo; + + +static bool fb_1bpp_rectangle(int x0, int y0, int width, int height, + int line_width, colour c, bool dotted, bool dashed) +{ + LOG(("%s(%d, %d, %d, %d, %d, 0x%lx, %d, %d)\n", __func__, + x0,y0,width,height,line_width,c,dotted,dashed)); + return true; +} + +static bool fb_1bpp_line(int x0, int y0, int x1, int y1, int width, + colour c, bool dotted, bool dashed) +{ + LOG(("%s(%d, %d, %d, %d, %d, 0x%lx, %d, %d)\n", __func__, + x0,y0,x1,y1,width,c,dotted,dashed)); + + return true; +} + +static bool fb_1bpp_polygon(const int *p, unsigned int n, colour fill) +{ + LOG(("%s(%p, %d, 0x%lx)\n", __func__, p,n,fill)); + return true; +} + + +static bool fb_1bpp_fill(int x0, int y0, int x1, int y1, colour c) +{ + int x; + int y; + int pent; + + LOG(("%s(%d, %d, %d, %d, 0x%lx)\n", __func__, + x0,y0,x1,y1,c)); + + if (c != 0) + pent = 0xff; + else + pent = 0; + + fb_plotters_clip_rect_ctx(&x0, &y0, &x1, &y1); + + x = x1 - x0; + for (y = y0; y < y1; y++) { + memset(fb_plotters_get_xy_loc(x0, y, fbinfo), pent, x); + } + return true; +} + +static bool fb_1bpp_clg(colour c) +{ + LOG(("%s(%lx)\n", __func__, c)); + fb_1bpp_fill(fb_plot_ctx.x0, + fb_plot_ctx.y0, + fb_plot_ctx.x1, + fb_plot_ctx.y1, + c); + return true; +} + + +static bool fb_1bpp_text(int x, int y, const struct css_style *style, + const char *text, size_t length, colour bg, colour c) +{ + const struct fb_font_desc* fb_font = fb_get_font(style); + u8_t *video_char_start; + const u8_t *font_data; + int yloop; + unsigned char row; + int chr; + + LOG(("%s(%d, %d, %p, %.*s , %d, 0x%lx, 0x%lx)\n", __func__, + x,y,style,length,text,length,bg,c)); + + for (chr=0; chr < length; chr++) { + video_char_start = fb_plotters_get_xy_loc(x + (chr * (fb_font->width)), y, fbinfo); + + /* move our font-data to the correct position */ + font_data = fb_font->data + (text[chr] * fb_font->height); + + for (yloop = 0; yloop < fb_font->height; yloop++) { + row = font_data[yloop]; + *video_char_start = row; + video_char_start += fbinfo->line_len; + } + } + return true; + + + /* copied from css/css.h - need to open the correct font here + * font properties * + css_font_family font_family; + struct { + css_font_size_type size; + union { + struct css_length length; + float absolute; + float percent; + } value; + } font_size; + css_font_style font_style; + css_font_variant font_variant; + css_font_weight font_weight; + */ + return true; +} + +static bool fb_1bpp_disc(int x, int y, int radius, colour c, bool filled) +{ + LOG(("%s(%d, %d, %d, 0x%lx, %d)\n", __func__, + x, y, radius, c, filled)); + return true; +} + +static bool fb_1bpp_arc(int x, int y, int radius, int angle1, int angle2, + colour c) +{ + LOG(("x %d, y %d, radius %d, angle1 %d, angle2 %d, c 0x%lx", + x, y, radius, angle1, angle2, c)); + return true; +} + +static inline colour ablend(colour pixel) +{ + return pixel; +} + + +static bool fb_1bpp_bitmap(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg, + struct content *content) +{ + u8_t *video_char_start; + colour *pixel = (colour *)bitmap->pixdata; + colour abpixel; /* alphablended pixel */ + int xloop,yloop; + + video_char_start = fb_plotters_get_xy_loc(x, y, fbinfo); + + for (yloop = 0; yloop < height; yloop++) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = pixel[(yloop * bitmap->width) + xloop]; + if ((abpixel & 0xFF000000) != 0) { + if ((abpixel & 0xFF000000) != 0xFF) + abpixel = ablend(abpixel); + if (abpixel == 0) + video_char_start[xloop] |= (1 << (xloop % 8)); + else + video_char_start[xloop] &= ~(1 << (xloop % 8)); + + } + } + video_char_start += fbinfo->line_len; + } + + return true; +} + +static bool fb_1bpp_bitmap_tile(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg, + bool repeat_x, bool repeat_y, + struct content *content) +{ + unsigned long xf,yf,wf,hf; + + if (!(repeat_x || repeat_y)) { + /* Not repeating at all, so just pass it on */ + return fb_1bpp_bitmap(x,y,width,height,bitmap,bg,content); + } + + for (xf = 0; xf < width; xf += bitmap->width) { + for(yf = 0;yf < height; yf += bitmap->height) { + if(width > xf+bitmap->width) + { + wf = width-(xf+bitmap->width); + } + else + { + wf=bitmap->width; + } + + if(height > yf+bitmap->height) + { + hf = height-(yf+bitmap->height); + } + else + { + hf=bitmap->height; + } + + fb_1bpp_bitmap(x+xf, y+yf, wf, hf, bitmap, bg, content); + + } + } + + return true; +} + +static bool fb_1bpp_flush(void) +{ + LOG(("%s()\n", __func__)); + return true; +} + +static bool fb_1bpp_path(const float *p, unsigned int n, colour fill, float width, + colour c, const float transform[6]) +{ + LOG(("%s(%f, %d, 0x%lx, %f, 0x%lx, %f)\n", __func__, + *p, n, fill, width, c, *transform)); + return true; +} + +const struct plotter_table framebuffer_1bpp_plot = { + .clg = fb_1bpp_clg, + .rectangle = fb_1bpp_rectangle, + .line = fb_1bpp_line, + .polygon = fb_1bpp_polygon, + .fill = fb_1bpp_fill, + .clip = fb_clip, + .text = fb_1bpp_text, + .disc = fb_1bpp_disc, + .arc = fb_1bpp_arc, + .bitmap = fb_1bpp_bitmap, + .bitmap_tile = fb_1bpp_bitmap_tile, + .flush = fb_1bpp_flush, + .path = fb_1bpp_path +}; + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/src/plot/24bpp.c b/src/plot/24bpp.c new file mode 100644 index 0000000..0fa53e9 --- /dev/null +++ b/src/plot/24bpp.c @@ -0,0 +1,442 @@ +/* + * Copyright 2009 Vincent Sanders + * + * This file is part of libnsfb, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + */ + +#include +#include +#include + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "libnsfb_plot_util.h" + +#include "nsfb.h" +#include "plot.h" + +static inline uint8_t * +get_xy_loc(nsfb_t *nsfb, int x, int y) +{ + return (uint8_t *)(nsfb->ptr + (y * nsfb->linelen) + (x * 3)); +} + +#if __BYTE_ORDER == __BIG_ENDIAN +static inline nsfb_colour_t pixel_to_colour(uint8_t pixel) +{ + return (pixel >> 8) & ~0xFF000000U; +} + +/* convert a colour value to a 32bpp pixel value ready for screen output */ +static inline uint32_t colour_to_pixel(nsfb_colour_t c) +{ + return (c << 8); +} +#else /* __BYTE_ORDER == __BIG_ENDIAN */ +static inline nsfb_colour_t pixel_to_colour(uint32_t pixel) +{ + return ((pixel & 0xFF) << 16) | + ((pixel & 0xFF00)) | + ((pixel & 0xFF0000) >> 16); +} + +/* convert a colour value to a 32bpp pixel value ready for screen output */ +static inline uint32_t colour_to_pixel(nsfb_colour_t c) +{ + return ((c & 0xff0000) >> 16) | (c & 0xff00) | ((c & 0xff) << 16); +} +#endif + +#define SIGN(x) ((x<0) ? -1 : ((x>0) ? 1 : 0)) + +static bool +line(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen) +{ + int w; + uint32_t ent; + uint32_t *pvideo; + int x, y, i; + int dx, dy, sdy; + int dxabs, dyabs; + + ent = colour_to_pixel(pen->stroke_colour); + + for (;linec > 0; linec--) { + + if (line->y0 == line->y1) { + /* horizontal line special cased */ + + if (!nsfb_plot_clip_ctx(nsfb, line)) { + /* line outside clipping */ + line++; + continue; + } + + pvideo = get_xy_loc(nsfb, line->x0, line->y0); + + w = line->x1 - line->x0; + while (w-- > 0) + *(pvideo + w) = ent; + + } else { + /* standard bresenham line */ + + if (!nsfb_plot_clip_line_ctx(nsfb, line)) { + /* line outside clipping */ + line++; + continue; + } + + /* the horizontal distance of the line */ + dx = line->x1 - line->x0; + dxabs = abs (dx); + + /* the vertical distance of the line */ + dy = line->y1 - line->y0; + dyabs = abs (dy); + + sdy = dx ? SIGN(dy) * SIGN(dx) : SIGN(dy); + + if (dx >= 0) + pvideo = get_xy_loc(nsfb, line->x0, line->y0); + else + pvideo = get_xy_loc(nsfb, line->x1, line->y1); + + x = dyabs >> 1; + y = dxabs >> 1; + + if (dxabs >= dyabs) { + /* the line is more horizontal than vertical */ + for (i = 0; i < dxabs; i++) { + *pvideo = ent; + + pvideo++; + y += dyabs; + if (y >= dxabs) { + y -= dxabs; + pvideo += sdy * (nsfb->linelen>>2); + } + } + } else { + /* the line is more vertical than horizontal */ + for (i = 0; i < dyabs; i++) { + *pvideo = ent; + pvideo += sdy * (nsfb->linelen >> 2); + + x += dxabs; + if (x >= dyabs) { + x -= dyabs; + pvideo++; + } + } + } + + } + line++; + } + return true; +} + + + +static bool fill(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t c) +{ + int w; + uint32_t *pvid; + uint32_t ent; + uint32_t llen; + uint32_t width; + uint32_t height; + + if (!nsfb_plot_clip_ctx(nsfb, rect)) + return true; /* fill lies outside current clipping region */ + + ent = colour_to_pixel(c); + width = rect->x1 - rect->x0; + height = rect->y1 - rect->y0; + llen = (nsfb->linelen >> 2) - width; + + pvid = get_xy_loc(nsfb, rect->x0, rect->y0); + + while (height-- > 0) { + w = width; + while (w >= 16) { + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + w-=16; + } + while (w >= 4) { + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + w-=4; + } + while (w > 0) { + *pvid++ = ent; + w--; + } + pvid += llen; + } + + return true; +} + + + + +static bool point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c) +{ + uint32_t *pvideo; + + /* check point lies within clipping region */ + if ((x < nsfb->clip.x0) || + (x >= nsfb->clip.x1) || + (y < nsfb->clip.y0) || + (y >= nsfb->clip.y1)) + return true; + + pvideo = get_xy_loc(nsfb, x, y); + + if ((c & 0xFF000000) != 0) { + if ((c & 0xFF000000) != 0xFF000000) { + c = nsfb_plot_ablend(c, pixel_to_colour(*pvideo)); + } + + *pvideo = colour_to_pixel(c); + } + return true; +} + +static bool +glyph1(nsfb_t *nsfb, + nsfb_bbox_t *loc, + const uint8_t *pixel, + int pitch, + nsfb_colour_t c) +{ + uint32_t *pvideo; + int xloop, yloop; + int xoff, yoff; /* x and y offset into image */ + int x = loc->x0; + int y = loc->y0; + int width = loc->x1 - loc->x0; + int height = loc->y1 - loc->y0; + uint32_t fgcol; + const uint8_t *fntd; + uint8_t row; + + if (!nsfb_plot_clip_ctx(nsfb, loc)) + return true; + + if (height > (loc->y1 - loc->y0)) + height = (loc->y1 - loc->y0); + + if (width > (loc->x1 - loc->x0)) + width = (loc->x1 - loc->x0); + + xoff = loc->x0 - x; + yoff = loc->y0 - y; + + pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); + + fgcol = colour_to_pixel(c); + + for (yloop = yoff; yloop < height; yloop++) { + fntd = pixel + (yloop * (pitch>>3)) + (xoff>>3); + row = (*fntd++) << (xoff & 3); + for (xloop = xoff; xloop < width ; xloop++) { + if (((xloop % 8) == 0) && (xloop != 0)) { + row = *fntd++; + } + + if ((row & 0x80) != 0) { + *(pvideo + xloop) = fgcol; + } + row = row << 1; + + } + + pvideo += (nsfb->linelen >> 2); + } + + return true; +} + +static bool +glyph8(nsfb_t *nsfb, + nsfb_bbox_t *loc, + const uint8_t *pixel, + int pitch, + nsfb_colour_t c) +{ + uint32_t *pvideo; + nsfb_colour_t abpixel; /* alphablended pixel */ + int xloop, yloop; + int xoff, yoff; /* x and y offset into image */ + int x = loc->x0; + int y = loc->y0; + int width = loc->x1 - loc->x0; + int height = loc->y1 - loc->y0; + uint32_t fgcol; + + if (!nsfb_plot_clip_ctx(nsfb, loc)) + return true; + + if (height > (loc->y1 - loc->y0)) + height = (loc->y1 - loc->y0); + + if (width > (loc->x1 - loc->x0)) + width = (loc->x1 - loc->x0); + + xoff = loc->x0 - x; + yoff = loc->y0 - y; + + pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); + + fgcol = c & 0xFFFFFF; + + for (yloop = 0; yloop < height; yloop++) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = (pixel[((yoff + yloop) * pitch) + xloop + xoff] << 24) | fgcol; + if ((abpixel & 0xFF000000) != 0) { + /* pixel is not transparent */ + if ((abpixel & 0xFF000000) != 0xFF000000) { + abpixel = nsfb_plot_ablend(abpixel, + pixel_to_colour(*(pvideo + xloop))); + } + + *(pvideo + xloop) = colour_to_pixel(abpixel); + } + } + pvideo += (nsfb->linelen >> 2); + } + + return true; +} + +static bool +bitmap(nsfb_t *nsfb, + const nsfb_bbox_t *loc, + const nsfb_colour_t *pixel, + int bmp_width, + int bmp_height, + int bmp_stride, + bool alpha) +{ + uint32_t *pvideo; + nsfb_colour_t abpixel = 0; /* alphablended pixel */ + int xloop, yloop; + int xoff, yoff; /* x and y offset into image */ + int x = loc->x0; + int y = loc->y0; + int width = loc->x1 - loc->x0; + int height = loc->y1 - loc->y0; + nsfb_bbox_t clipped; /* clipped display */ + + /* TODO here we should scale the image from bmp_width to width, for + * now simply crop. + */ + if (width > bmp_width) + width = bmp_width; + + if (height > bmp_height) + height = bmp_height; + + /* The part of the scaled image actually displayed is cropped to the + * current context. + */ + clipped.x0 = x; + clipped.y0 = y; + clipped.x1 = x + width; + clipped.y1 = y + height; + + if (!nsfb_plot_clip_ctx(nsfb, &clipped)) { + return true; + } + + if (height > (clipped.y1 - clipped.y0)) + height = (clipped.y1 - clipped.y0); + + if (width > (clipped.x1 - clipped.x0)) + width = (clipped.x1 - clipped.x0); + + xoff = clipped.x0 - x; + yoff = (clipped.y0 - y) * bmp_width; + height = height * bmp_stride + yoff; + + /* plot the image */ + pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0); + + if (alpha) { + for (yloop = yoff; yloop < height; yloop += bmp_stride) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = pixel[yloop + xloop + xoff]; + if ((abpixel & 0xFF000000) != 0) { + if ((abpixel & 0xFF000000) != 0xFF000000) { + abpixel = nsfb_plot_ablend(abpixel, + pixel_to_colour(*(pvideo + xloop))); + } + + *(pvideo + xloop) = colour_to_pixel(abpixel); + } + } + pvideo += (nsfb->linelen >> 2); + } + } else { + for (yloop = yoff; yloop < height; yloop += bmp_stride) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = pixel[yloop + xloop + xoff]; + *(pvideo + xloop) = colour_to_pixel(abpixel); + } + pvideo += (nsfb->linelen >> 2); + } + } + return true; +} + +static bool readrect(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer) +{ + uint32_t *pvideo; + int xloop, yloop; + int width; + + if (!nsfb_plot_clip_ctx(nsfb, rect)) { + return true; + } + + width = rect->x1 - rect->x0; + + pvideo = get_xy_loc(nsfb, rect->x0, rect->y0); + + for (yloop = rect->y0; yloop < rect->y1; yloop += 1) { + for (xloop = 0; xloop < width; xloop++) { + *buffer = pixel_to_colour(*(pvideo + xloop)); + buffer++; + } + pvideo += (nsfb->linelen >> 2); + } + return true; +} + +const nsfb_plotter_fns_t _nsfb_24bpp_plotters = { + .line = line, + .fill = fill, + .point = point, + .bitmap = bitmap, + .glyph8 = glyph8, + .glyph1 = glyph1, + .readrect = readrect, +}; + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/src/plot/32bpp.c b/src/plot/32bpp.c new file mode 100644 index 0000000..243cdb4 --- /dev/null +++ b/src/plot/32bpp.c @@ -0,0 +1,442 @@ +/* + * Copyright 2009 Vincent Sanders + * + * This file is part of libnsfb, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + */ + +#include +#include +#include + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "libnsfb_plot_util.h" + +#include "nsfb.h" +#include "plot.h" + +static inline uint32_t * +get_xy_loc(nsfb_t *nsfb, int x, int y) +{ + return (uint32_t *)(nsfb->ptr + (y * nsfb->linelen) + (x << 2)); +} + +#if __BYTE_ORDER == __BIG_ENDIAN +static inline nsfb_colour_t pixel_to_colour(uint32_t pixel) +{ + return (pixel >> 8) & ~0xFF000000U; +} + +/* convert a colour value to a 32bpp pixel value ready for screen output */ +static inline uint32_t colour_to_pixel(nsfb_colour_t c) +{ + return (c << 8); +} +#else /* __BYTE_ORDER == __BIG_ENDIAN */ +static inline nsfb_colour_t pixel_to_colour(uint32_t pixel) +{ + return ((pixel & 0xFF) << 16) | + ((pixel & 0xFF00)) | + ((pixel & 0xFF0000) >> 16); +} + +/* convert a colour value to a 32bpp pixel value ready for screen output */ +static inline uint32_t colour_to_pixel(nsfb_colour_t c) +{ + return ((c & 0xff0000) >> 16) | (c & 0xff00) | ((c & 0xff) << 16); +} +#endif + +#define SIGN(x) ((x<0) ? -1 : ((x>0) ? 1 : 0)) + +static bool +line(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen) +{ + int w; + uint32_t ent; + uint32_t *pvideo; + int x, y, i; + int dx, dy, sdy; + int dxabs, dyabs; + + ent = colour_to_pixel(pen->stroke_colour); + + for (;linec > 0; linec--) { + + if (line->y0 == line->y1) { + /* horizontal line special cased */ + + if (!nsfb_plot_clip_ctx(nsfb, line)) { + /* line outside clipping */ + line++; + continue; + } + + pvideo = get_xy_loc(nsfb, line->x0, line->y0); + + w = line->x1 - line->x0; + while (w-- > 0) + *(pvideo + w) = ent; + + } else { + /* standard bresenham line */ + + if (!nsfb_plot_clip_line_ctx(nsfb, line)) { + /* line outside clipping */ + line++; + continue; + } + + /* the horizontal distance of the line */ + dx = line->x1 - line->x0; + dxabs = abs (dx); + + /* the vertical distance of the line */ + dy = line->y1 - line->y0; + dyabs = abs (dy); + + sdy = dx ? SIGN(dy) * SIGN(dx) : SIGN(dy); + + if (dx >= 0) + pvideo = get_xy_loc(nsfb, line->x0, line->y0); + else + pvideo = get_xy_loc(nsfb, line->x1, line->y1); + + x = dyabs >> 1; + y = dxabs >> 1; + + if (dxabs >= dyabs) { + /* the line is more horizontal than vertical */ + for (i = 0; i < dxabs; i++) { + *pvideo = ent; + + pvideo++; + y += dyabs; + if (y >= dxabs) { + y -= dxabs; + pvideo += sdy * (nsfb->linelen>>2); + } + } + } else { + /* the line is more vertical than horizontal */ + for (i = 0; i < dyabs; i++) { + *pvideo = ent; + pvideo += sdy * (nsfb->linelen >> 2); + + x += dxabs; + if (x >= dyabs) { + x -= dyabs; + pvideo++; + } + } + } + + } + line++; + } + return true; +} + + + +static bool fill(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t c) +{ + int w; + uint32_t *pvid; + uint32_t ent; + uint32_t llen; + uint32_t width; + uint32_t height; + + if (!nsfb_plot_clip_ctx(nsfb, rect)) + return true; /* fill lies outside current clipping region */ + + ent = colour_to_pixel(c); + width = rect->x1 - rect->x0; + height = rect->y1 - rect->y0; + llen = (nsfb->linelen >> 2) - width; + + pvid = get_xy_loc(nsfb, rect->x0, rect->y0); + + while (height-- > 0) { + w = width; + while (w >= 16) { + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + w-=16; + } + while (w >= 4) { + *pvid++ = ent; *pvid++ = ent; + *pvid++ = ent; *pvid++ = ent; + w-=4; + } + while (w > 0) { + *pvid++ = ent; + w--; + } + pvid += llen; + } + + return true; +} + + + + +static bool point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c) +{ + uint32_t *pvideo; + + /* check point lies within clipping region */ + if ((x < nsfb->clip.x0) || + (x >= nsfb->clip.x1) || + (y < nsfb->clip.y0) || + (y >= nsfb->clip.y1)) + return true; + + pvideo = get_xy_loc(nsfb, x, y); + + if ((c & 0xFF000000) != 0) { + if ((c & 0xFF000000) != 0xFF000000) { + c = nsfb_plot_ablend(c, pixel_to_colour(*pvideo)); + } + + *pvideo = colour_to_pixel(c); + } + return true; +} + +static bool +glyph1(nsfb_t *nsfb, + nsfb_bbox_t *loc, + const uint8_t *pixel, + int pitch, + nsfb_colour_t c) +{ + uint32_t *pvideo; + int xloop, yloop; + int xoff, yoff; /* x and y offset into image */ + int x = loc->x0; + int y = loc->y0; + int width = loc->x1 - loc->x0; + int height = loc->y1 - loc->y0; + uint32_t fgcol; + const uint8_t *fntd; + uint8_t row; + + if (!nsfb_plot_clip_ctx(nsfb, loc)) + return true; + + if (height > (loc->y1 - loc->y0)) + height = (loc->y1 - loc->y0); + + if (width > (loc->x1 - loc->x0)) + width = (loc->x1 - loc->x0); + + xoff = loc->x0 - x; + yoff = loc->y0 - y; + + pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); + + fgcol = colour_to_pixel(c); + + for (yloop = yoff; yloop < height; yloop++) { + fntd = pixel + (yloop * (pitch>>3)) + (xoff>>3); + row = (*fntd++) << (xoff & 3); + for (xloop = xoff; xloop < width ; xloop++) { + if (((xloop % 8) == 0) && (xloop != 0)) { + row = *fntd++; + } + + if ((row & 0x80) != 0) { + *(pvideo + xloop) = fgcol; + } + row = row << 1; + + } + + pvideo += (nsfb->linelen >> 2); + } + + return true; +} + +static bool +glyph8(nsfb_t *nsfb, + nsfb_bbox_t *loc, + const uint8_t *pixel, + int pitch, + nsfb_colour_t c) +{ + uint32_t *pvideo; + nsfb_colour_t abpixel; /* alphablended pixel */ + int xloop, yloop; + int xoff, yoff; /* x and y offset into image */ + int x = loc->x0; + int y = loc->y0; + int width = loc->x1 - loc->x0; + int height = loc->y1 - loc->y0; + uint32_t fgcol; + + if (!nsfb_plot_clip_ctx(nsfb, loc)) + return true; + + if (height > (loc->y1 - loc->y0)) + height = (loc->y1 - loc->y0); + + if (width > (loc->x1 - loc->x0)) + width = (loc->x1 - loc->x0); + + xoff = loc->x0 - x; + yoff = loc->y0 - y; + + pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); + + fgcol = c & 0xFFFFFF; + + for (yloop = 0; yloop < height; yloop++) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = (pixel[((yoff + yloop) * pitch) + xloop + xoff] << 24) | fgcol; + if ((abpixel & 0xFF000000) != 0) { + /* pixel is not transparent */ + if ((abpixel & 0xFF000000) != 0xFF000000) { + abpixel = nsfb_plot_ablend(abpixel, + pixel_to_colour(*(pvideo + xloop))); + } + + *(pvideo + xloop) = colour_to_pixel(abpixel); + } + } + pvideo += (nsfb->linelen >> 2); + } + + return true; +} + +static bool +bitmap(nsfb_t *nsfb, + const nsfb_bbox_t *loc, + const nsfb_colour_t *pixel, + int bmp_width, + int bmp_height, + int bmp_stride, + bool alpha) +{ + uint32_t *pvideo; + nsfb_colour_t abpixel = 0; /* alphablended pixel */ + int xloop, yloop; + int xoff, yoff; /* x and y offset into image */ + int x = loc->x0; + int y = loc->y0; + int width = loc->x1 - loc->x0; + int height = loc->y1 - loc->y0; + nsfb_bbox_t clipped; /* clipped display */ + + /* TODO here we should scale the image from bmp_width to width, for + * now simply crop. + */ + if (width > bmp_width) + width = bmp_width; + + if (height > bmp_height) + height = bmp_height; + + /* The part of the scaled image actually displayed is cropped to the + * current context. + */ + clipped.x0 = x; + clipped.y0 = y; + clipped.x1 = x + width; + clipped.y1 = y + height; + + if (!nsfb_plot_clip_ctx(nsfb, &clipped)) { + return true; + } + + if (height > (clipped.y1 - clipped.y0)) + height = (clipped.y1 - clipped.y0); + + if (width > (clipped.x1 - clipped.x0)) + width = (clipped.x1 - clipped.x0); + + xoff = clipped.x0 - x; + yoff = (clipped.y0 - y) * bmp_width; + height = height * bmp_stride + yoff; + + /* plot the image */ + pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0); + + if (alpha) { + for (yloop = yoff; yloop < height; yloop += bmp_stride) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = pixel[yloop + xloop + xoff]; + if ((abpixel & 0xFF000000) != 0) { + if ((abpixel & 0xFF000000) != 0xFF000000) { + abpixel = nsfb_plot_ablend(abpixel, + pixel_to_colour(*(pvideo + xloop))); + } + + *(pvideo + xloop) = colour_to_pixel(abpixel); + } + } + pvideo += (nsfb->linelen >> 2); + } + } else { + for (yloop = yoff; yloop < height; yloop += bmp_stride) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = pixel[yloop + xloop + xoff]; + *(pvideo + xloop) = colour_to_pixel(abpixel); + } + pvideo += (nsfb->linelen >> 2); + } + } + return true; +} + +static bool readrect(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer) +{ + uint32_t *pvideo; + int xloop, yloop; + int width; + + if (!nsfb_plot_clip_ctx(nsfb, rect)) { + return true; + } + + width = rect->x1 - rect->x0; + + pvideo = get_xy_loc(nsfb, rect->x0, rect->y0); + + for (yloop = rect->y0; yloop < rect->y1; yloop += 1) { + for (xloop = 0; xloop < width; xloop++) { + *buffer = pixel_to_colour(*(pvideo + xloop)); + buffer++; + } + pvideo += (nsfb->linelen >> 2); + } + return true; +} + +const nsfb_plotter_fns_t _nsfb_32bpp_plotters = { + .line = line, + .fill = fill, + .point = point, + .bitmap = bitmap, + .glyph8 = glyph8, + .glyph1 = glyph1, + .readrect = readrect, +}; + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/src/plot/8bpp.c b/src/plot/8bpp.c new file mode 100644 index 0000000..c95565c --- /dev/null +++ b/src/plot/8bpp.c @@ -0,0 +1,425 @@ +/* + * Copyright 2009 Vincent Sanders + * + * This file is part of libnsfb, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + */ + +#include +#include +#include +#include +#include + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "libnsfb_plot_util.h" + +#include "nsfb.h" +#include "plot.h" + +static inline uint8_t *get_xy_loc(nsfb_t *nsfb, int x, int y) +{ + return (uint8_t *)(nsfb->ptr + (y * nsfb->linelen) + (x)); +} + + +static inline nsfb_colour_t pixel_to_colour(nsfb_t *nsfb, uint8_t pixel) +{ + return nsfb->palette[pixel]; +} + +static uint8_t +colour_to_pixel(nsfb_t *nsfb, nsfb_colour_t c) +{ + nsfb_colour_t palent; + int col; + + int dr, dg, db; /* delta red, green blue values */ + + int cur_distance; + int best_distance = INT_MAX; + uint8_t best_col = 0; + + for (col = 0; col < 256; col++) { + palent = nsfb->palette[col]; + + dr = (c & 0xFF) - (palent & 0xFF); + dg = ((c >> 8) & 0xFF) - ((palent >> 8) & 0xFF); + db = ((c >> 16) & 0xFF) - ((palent >> 16) & 0xFF); + cur_distance = ((dr * dr) + (dg * dg) + (db *db)); + if (cur_distance < best_distance) { + best_distance = cur_distance; + best_col = col; + } + } + + return best_col; +} + +#define SIGN(x) ((x<0) ? -1 : ((x>0) ? 1 : 0)) + +static bool +line(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen) +{ + int w; + uint8_t ent; + uint8_t *pvideo; + int x, y, i; + int dx, dy, sdy; + int dxabs, dyabs; + + ent = colour_to_pixel(nsfb, pen->stroke_colour); + + for (;linec > 0; linec--) { + + if (line->y0 == line->y1) { + /* horizontal line special cased */ + + if (!nsfb_plot_clip_ctx(nsfb, line)) { + /* line outside clipping */ + line++; + continue; + } + + pvideo = get_xy_loc(nsfb, line->x0, line->y0); + + w = line->x1 - line->x0; + while (w-- > 0) + *(pvideo + w) = ent; + + } else { + /* standard bresenham line */ + + if (!nsfb_plot_clip_line_ctx(nsfb, line)) { + /* line outside clipping */ + line++; + continue; + } + + /* the horizontal distance of the line */ + dx = line->x1 - line->x0; + dxabs = abs (dx); + + /* the vertical distance of the line */ + dy = line->y1 - line->y0; + dyabs = abs (dy); + + sdy = dx ? SIGN(dy) * SIGN(dx) : SIGN(dy); + + if (dx >= 0) + pvideo = get_xy_loc(nsfb, line->x0, line->y0); + else + pvideo = get_xy_loc(nsfb, line->x1, line->y1); + + x = dyabs >> 1; + y = dxabs >> 1; + + if (dxabs >= dyabs) { + /* the line is more horizontal than vertical */ + for (i = 0; i < dxabs; i++) { + *pvideo = ent; + + pvideo++; + y += dyabs; + if (y >= dxabs) { + y -= dxabs; + pvideo += sdy * nsfb->linelen; + } + } + } else { + /* the line is more vertical than horizontal */ + for (i = 0; i < dyabs; i++) { + *pvideo = ent; + pvideo += sdy * nsfb->linelen; + + x += dxabs; + if (x >= dyabs) { + x -= dyabs; + pvideo++; + } + } + } + + } + line++; + } + + return true; +} + +static bool fill(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t c) +{ + int y; + uint8_t ent; + uint8_t *pvideo; + + if (!nsfb_plot_clip_ctx(nsfb, rect)) + return true; /* fill lies outside current clipping region */ + + pvideo = get_xy_loc(nsfb, rect->x0, rect->y0); + + ent = colour_to_pixel(nsfb, c); + + for (y = rect->y0; y < rect->y1; y++) { + memset(pvideo, ent, rect->x1 - rect->x0); + pvideo += nsfb->linelen; + } + + return true; +} + +static bool point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c) +{ + uint8_t *pvideo; + + /* check point lies within clipping region */ + if ((x < nsfb->clip.x0) || + (x >= nsfb->clip.x1) || + (y < nsfb->clip.y0) || + (y >= nsfb->clip.y1)) + return true; + + pvideo = get_xy_loc(nsfb, x, y); + + if ((c & 0xFF000000) != 0) { + if ((c & 0xFF000000) != 0xFF000000) { + c = nsfb_plot_ablend(c, pixel_to_colour(nsfb, *pvideo)); + } + + *pvideo = colour_to_pixel(nsfb, c); + } + return true; +} + +static bool +glyph1(nsfb_t *nsfb, + nsfb_bbox_t *loc, + const uint8_t *pixel, + int pitch, + nsfb_colour_t c) +{ + uint8_t *pvideo; + int xloop, yloop; + int xoff, yoff; /* x and y offset into image */ + int x = loc->x0; + int y = loc->y0; + int width = loc->x1 - loc->x0; + int height = loc->y1 - loc->y0; + uint8_t fgcol; + const uint8_t *fntd; + uint8_t row; + + if (!nsfb_plot_clip_ctx(nsfb, loc)) + return true; + + if (height > (loc->y1 - loc->y0)) + height = (loc->y1 - loc->y0); + + if (width > (loc->x1 - loc->x0)) + width = (loc->x1 - loc->x0); + + xoff = loc->x0 - x; + yoff = loc->y0 - y; + + pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); + + fgcol = colour_to_pixel(nsfb, c); + + for (yloop = yoff; yloop < height; yloop++) { + fntd = pixel + (yloop * (pitch>>3)) + (xoff>>3); + row = (*fntd++) << (xoff & 3); + for (xloop = xoff; xloop < width ; xloop++) { + if (((xloop % 8) == 0) && (xloop != 0)) { + row = *fntd++; + } + + if ((row & 0x80) != 0) { + *(pvideo + xloop) = fgcol; + } + row = row << 1; + + } + + pvideo += nsfb->linelen; + } + + return true; +} + +static bool +glyph8(nsfb_t *nsfb, + nsfb_bbox_t *loc, + const uint8_t *pixel, + int pitch, + nsfb_colour_t c) +{ + uint8_t *pvideo; + nsfb_colour_t abpixel; /* alphablended pixel */ + int xloop, yloop; + int xoff, yoff; /* x and y offset into image */ + int x = loc->x0; + int y = loc->y0; + int width = loc->x1 - loc->x0; + int height = loc->y1 - loc->y0; + uint8_t fgcol; + + if (!nsfb_plot_clip_ctx(nsfb, loc)) + return true; + + if (height > (loc->y1 - loc->y0)) + height = (loc->y1 - loc->y0); + + if (width > (loc->x1 - loc->x0)) + width = (loc->x1 - loc->x0); + + xoff = loc->x0 - x; + yoff = loc->y0 - y; + + pvideo = get_xy_loc(nsfb, loc->x0, loc->y0); + + fgcol = c & 0xFFFFFF; + + for (yloop = 0; yloop < height; yloop++) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = (pixel[((yoff + yloop) * pitch) + xloop + xoff] << 24) | fgcol; + if ((abpixel & 0xFF000000) != 0) { + /* pixel is not transparent */ + if ((abpixel & 0xFF000000) != 0xFF000000) { + abpixel = nsfb_plot_ablend(abpixel, + pixel_to_colour(nsfb, *(pvideo + xloop))); + } + + *(pvideo + xloop) = colour_to_pixel(nsfb, abpixel); + } + } + pvideo += nsfb->linelen; + } + + return true; +} + +static bool +bitmap(nsfb_t *nsfb, + const nsfb_bbox_t *loc, + const nsfb_colour_t *pixel, + int bmp_width, + int bmp_height, + int bmp_stride, + bool alpha) +{ + uint8_t *pvideo; + nsfb_colour_t abpixel = 0; /* alphablended pixel */ + int xloop, yloop; + int xoff, yoff; /* x and y offset into image */ + int x = loc->x0; + int y = loc->y0; + int width = loc->x1 - loc->x0; + int height = loc->y1 - loc->y0; + nsfb_bbox_t clipped; /* clipped display */ + + /* TODO here we should scale the image from bmp_width to width, for + * now simply crop. + */ + if (width > bmp_width) + width = bmp_width; + + if (height > bmp_height) + height = bmp_height; + + /* The part of the scaled image actually displayed is cropped to the + * current context. + */ + clipped.x0 = x; + clipped.y0 = y; + clipped.x1 = x + width; + clipped.y1 = y + height; + + if (!nsfb_plot_clip_ctx(nsfb, &clipped)) + return true; + + if (height > (clipped.y1 - clipped.y0)) + height = (clipped.y1 - clipped.y0); + + if (width > (clipped.x1 - clipped.x0)) + width = (clipped.x1 - clipped.x0); + + xoff = clipped.x0 - x; + yoff = (clipped.y0 - y) * bmp_width; + height = height * bmp_stride + yoff; + + /* plot the image */ + pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0); + + if (alpha) { + for (yloop = yoff; yloop < height; yloop += bmp_stride) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = pixel[yloop + xloop + xoff]; + if ((abpixel & 0xFF000000) != 0) { + if ((abpixel & 0xFF000000) != 0xFF000000) { + abpixel = nsfb_plot_ablend(abpixel, + pixel_to_colour(nsfb, *(pvideo + xloop))); + } + + *(pvideo + xloop) = colour_to_pixel(nsfb, abpixel); + } + } + pvideo += nsfb->linelen; + } + } else { + for (yloop = yoff; yloop < height; yloop += bmp_stride) { + for (xloop = 0; xloop < width; xloop++) { + abpixel = pixel[yloop + xloop + xoff]; + *(pvideo + xloop) = colour_to_pixel(nsfb, abpixel); + } + pvideo += nsfb->linelen; + } + } + return true; +} + + +static bool readrect(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer) +{ + uint8_t *pvideo; + int xloop, yloop; + int width; + + if (!nsfb_plot_clip_ctx(nsfb, rect)) { + return true; + } + + width = rect->x1 - rect->x0; + + pvideo = get_xy_loc(nsfb, rect->x0, rect->y0); + + for (yloop = rect->y0; yloop < rect->y1; yloop += 1) { + for (xloop = 0; xloop < width; xloop++) { + *buffer = pixel_to_colour(nsfb,*(pvideo + xloop)); + buffer++; + } + pvideo += nsfb->linelen; + } + return true; +} + + + + +const nsfb_plotter_fns_t _nsfb_8bpp_plotters = { + .line = line, + .fill = fill, + .point = point, + .bitmap = bitmap, + .glyph8 = glyph8, + .glyph1 = glyph1, + .readrect = readrect, +}; + + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/src/plot/Makefile b/src/plot/Makefile new file mode 100644 index 0000000..0c51c02 --- /dev/null +++ b/src/plot/Makefile @@ -0,0 +1,4 @@ +# Sources +DIR_SOURCES := api.c util.c generic.c 32bpp.c 16bpp.c 8bpp.c + +include build/makefiles/Makefile.subdir diff --git a/src/plot/api.c b/src/plot/api.c new file mode 100644 index 0000000..4de25c9 --- /dev/null +++ b/src/plot/api.c @@ -0,0 +1,169 @@ +/* public plotter interface */ + +#include + +#include "libnsfb.h" +#include "libnsfb_plot.h" + +#include "nsfb.h" +#include "plot.h" + +/** Sets a clip rectangle for subsequent plots. + * + * Sets a clipping area which constrains all subsequent plotting operations. + * The clipping area must lie within the framebuffer visible screen or false + * will be returned and the new clipping area not set. + */ +bool nsfb_plot_set_clip(nsfb_t *nsfb, nsfb_bbox_t *clip) +{ + return nsfb->plotter_fns->set_clip(nsfb, clip); +} + +/** Get the previously set clipping region. + */ +bool nsfb_plot_get_clip(nsfb_t *nsfb, nsfb_bbox_t *clip) +{ + return nsfb->plotter_fns->get_clip(nsfb, clip); +} + +/** Clears plotting area to a flat colour. + */ +bool nsfb_plot_clg(nsfb_t *nsfb, nsfb_colour_t c) +{ + return nsfb->plotter_fns->clg(nsfb, c); +} + +/** Plots a rectangle outline. + * + * The line can be solid, dotted or dashed. Top left corner at (x0,y0) and + * rectangle has given width and height. + */ +bool +nsfb_plot_rectangle(nsfb_t *nsfb, + nsfb_bbox_t *rect, + int line_width, + nsfb_colour_t c, + bool dotted, + bool dashed) +{ + return nsfb->plotter_fns->rectangle(nsfb, rect, line_width, c, dotted, dashed); + +} + +/** Plots a filled rectangle. Top left corner at (x0,y0), bottom + * right corner at (x1,y1). Note: (x0,y0) is inside filled area, + * but (x1,y1) is below and to the right. See diagram below. + */ +bool nsfb_plot_rectangle_fill(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t c) +{ + return nsfb->plotter_fns->fill(nsfb, rect, c); +} + +/** Plots a line. + * + * Draw a line from (x0,y0) to (x1,y1). Coordinates are at centre of line + * width/thickness. + */ +bool nsfb_plot_line(nsfb_t *nsfb, nsfb_bbox_t *line, nsfb_plot_pen_t *pen) +{ + return nsfb->plotter_fns->line(nsfb, 1, line, pen); +} + +/** Plots more than one line. + * + * Draw a line from (x0,y0) to (x1,y1). Coordinates are at centre of line + * width/thickness. + */ +bool nsfb_plot_lines(nsfb_t *nsfb, int linec, nsfb_bbox_t *line, nsfb_plot_pen_t *pen) +{ + return nsfb->plotter_fns->line(nsfb, linec, line, pen); +} + +/** Plots a filled polygon. + * + * Plots a filled polygon with straight lines between points. The lines around + * the edge of the ploygon are not plotted. The polygon is filled with a + * non-zero winding rule. + * + * + */ +bool nsfb_plot_polygon(nsfb_t *nsfb, const int *p, unsigned int n, nsfb_colour_t fill) +{ + return nsfb->plotter_fns->polygon(nsfb, p, n, fill); +} + +/** Plots an arc. + * + * around (x,y), from anticlockwise from angle1 to angle2. Angles are measured + * anticlockwise from horizontal, in degrees. + */ +bool nsfb_plot_arc(nsfb_t *nsfb, int x, int y, int radius, int angle1, int angle2, nsfb_colour_t c) +{ + return nsfb->plotter_fns->arc(nsfb, x, y, radius, angle1, angle2, c); +} + +/** Plots an alpha blended pixel. + * + * plots an alpha blended pixel. + */ +bool nsfb_plot_point(nsfb_t *nsfb, int x, int y, nsfb_colour_t c) +{ + return nsfb->plotter_fns->point(nsfb, x, y, c); +} + +bool nsfb_plot_ellipse(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c) +{ + return nsfb->plotter_fns->ellipse(nsfb, ellipse, c); +} + +bool nsfb_plot_ellipse_fill(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c) +{ + return nsfb->plotter_fns->ellipse_fill(nsfb, ellipse, c); +} + +bool nsfb_plot_copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox) +{ + return nsfb->plotter_fns->copy(nsfb, srcbox, dstbox); +} + +bool nsfb_plot_bitmap(nsfb_t *nsfb, const nsfb_bbox_t *loc, const nsfb_colour_t *pixel, int bmp_width, int bmp_height, int bmp_stride, bool alpha) +{ + return nsfb->plotter_fns->bitmap(nsfb, loc, pixel, bmp_width, bmp_height, bmp_stride, alpha); +} + +/** Plot an 8 bit glyph. + */ +bool nsfb_plot_glyph8(nsfb_t *nsfb, nsfb_bbox_t *loc, const uint8_t *pixel, int pitch, nsfb_colour_t c) +{ + return nsfb->plotter_fns->glyph8(nsfb, loc, pixel, pitch, c); +} + + +/** Plot an 1 bit glyph. + */ +bool nsfb_plot_glyph1(nsfb_t *nsfb, nsfb_bbox_t *loc, const uint8_t *pixel, int pitch, nsfb_colour_t c) +{ + return nsfb->plotter_fns->glyph1(nsfb, loc, pixel, pitch, c); +} + +/* read a rectangle from screen into buffer */ +bool nsfb_plot_readrect(nsfb_t *nsfb, nsfb_bbox_t *rect, nsfb_colour_t *buffer) +{ + return nsfb->plotter_fns->readrect(nsfb, rect, buffer); +} + + +bool nsfb_plot_cubic_bezier(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_point_t *ctrlb, nsfb_colour_t c) +{ + return nsfb->plotter_fns->cubic(nsfb, curve, ctrla, ctrlb, c); +} + +bool nsfb_plot_quadratic_bezier(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_colour_t c) +{ + return nsfb->plotter_fns->quadratic(nsfb, curve, ctrla, c); +} + +bool nsfb_plot_path(nsfb_t *nsfb, int pathc, nsfb_plot_pathop_t *pathop, nsfb_plot_pen_t *pen) +{ + return nsfb->plotter_fns->path(nsfb, pathc, pathop, pen); +} diff --git a/src/plot/generic.c b/src/plot/generic.c new file mode 100644 index 0000000..d04559e --- /dev/null +++ b/src/plot/generic.c @@ -0,0 +1,663 @@ +/* + * Copyright 2009 Vincent Sanders + * Copyright 2009 Michael Drake + * + * This file is part of libnsfb, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + */ + +/** \file + * generic plotter functions which are not depth dependant (implementation). + */ + +#include +#include +#include +#include + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "libnsfb_plot_util.h" + +#include "nsfb.h" +#include "plot.h" +#include "frontend.h" + +extern const nsfb_plotter_fns_t _nsfb_1bpp_plotters; +extern const nsfb_plotter_fns_t _nsfb_8bpp_plotters; +extern const nsfb_plotter_fns_t _nsfb_16bpp_plotters; +extern const nsfb_plotter_fns_t _nsfb_24bpp_plotters; +extern const nsfb_plotter_fns_t _nsfb_32bpp_plotters; + +static bool set_clip(nsfb_t *nsfb, nsfb_bbox_t *clip) +{ + nsfb_bbox_t fbarea; + + /* screen area */ + fbarea.x0 = 0; + fbarea.y0 = 0; + fbarea.x1 = nsfb->width; + fbarea.y1 = nsfb->height; + + if (clip == NULL) { + nsfb->clip = fbarea; + } else { + if (!nsfb_plot_clip(&fbarea, clip)) + return false; + + nsfb->clip = *clip; + } + return true; +} + +static bool get_clip(nsfb_t *nsfb, nsfb_bbox_t *clip) +{ + *clip = nsfb->clip; + return true; +} + +static bool clg(nsfb_t *nsfb, nsfb_colour_t c) +{ + return nsfb->plotter_fns->fill(nsfb, &nsfb->clip, c); +} + +/** + * Find first filled span along horizontal line at given coordinate + * + * \param p array of polygon vertices (x1, y1, x2, y2, ... , xN, yN) + * \param n number of polygon vertex values (N * 2) + * \param x current position along current scan line + * \param y position of current scan line + * \param x0 updated to start of filled area + * \param x1 updated to end of filled area + * \return true if an intersection was found + */ +static bool find_span(const int *p, int n, int x, int y, int *x0, int *x1) +{ + int i; + int p_x0, p_y0; + int p_x1, p_y1; + int x_new; + bool direction = false; + + *x0 = *x1 = INT_MAX; + + for (i = 0; i < n; i = i + 2) { + /* get line endpoints */ + if (i != n - 2) { + /* not the last line */ + p_x0 = p[i]; p_y0 = p[i + 1]; + p_x1 = p[i + 2]; p_y1 = p[i + 3]; + } else { + /* last line; 2nd endpoint is first vertex */ + p_x0 = p[i]; p_y0 = p[i + 1]; + p_x1 = p[0]; p_y1 = p[1]; + } + /* ignore horizontal lines */ + if (p_y0 == p_y1) + continue; + + /* ignore lines that don't cross this y level */ + if ((y < p_y0 && y < p_y1) || (y > p_y0 && y > p_y1)) + continue; + + if (p_x0 == p_x1) { + /* vertical line, x is constant */ + x_new = p_x0; + } else { + /* find intersect */ + x_new = p_x0 + ((long long)(y - p_y0) * (p_x1 - p_x0)) / + (p_y1 - p_y0); + } + + /* ignore intersections before current x */ + if (x_new < x) + continue; + + /* set nearest intersections as filled area endpoints */ + if (x_new < *x0) { + /* nearer than first endpoint */ + *x1 = *x0; + *x0 = x_new; + direction = (p_y0 > p_y1); + } else if (x_new == *x0) { + /* same as first endpoint */ + if ((p_y0 > p_y1) != direction) + *x1 = x_new; + } else if (x_new < *x1) { + /* nearer than second endpoint */ + *x1 = x_new; + } + + } + if (*x0 == INT_MAX) + /* no span found */ + return false; + + /* span found */ + if (*x1 == INT_MAX) { + *x1 = *x0; + *x0 = x; + return true; + } + + return true; +} + + +/** + * Plot a polygon + * + * \param nsfb framebuffer context + * \param p array of polygon vertices (x1, y1, x2, y2, ... , xN, yN) + * \param n number of polygon vertices (N) + * \param c fill colour + * \return true if no errors + */ +static bool +polygon(nsfb_t *nsfb, const int *p, unsigned int n, nsfb_colour_t c) +{ + int poly_x0, poly_y0; /* Bounding box top left corner */ + int poly_x1, poly_y1; /* Bounding box bottom right corner */ + int i, j; /* indexes */ + int x0, x1; /* filled span extents */ + int y; /* current y coordinate */ + int y_max; /* bottom of plot area */ + nsfb_bbox_t fline; + nsfb_plot_pen_t pen; + + /* find no. of vertex values */ + int v = n * 2; + + /* Can't plot polygons with 2 or fewer vertices */ + if (n <= 2) + return true; + + pen.stroke_colour = c; + + /* Find polygon bounding box */ + poly_x0 = poly_x1 = *p; + poly_y0 = poly_y1 = p[1]; + for (i = 2; i < v; i = i + 2) { + j = i + 1; + if (p[i] < poly_x0) + poly_x0 = p[i]; + else if (p[i] > poly_x1) + poly_x1 = p[i]; + if (p[j] < poly_y0) + poly_y0 = p[j]; + else if (p[j] > poly_y1) + poly_y1 = p[j]; + } + + /* Don't try to plot it if it's outside the clip rectangle */ + if (nsfb->clip.y1 < poly_y0 || + nsfb->clip.y0 > poly_y1 || + nsfb->clip.x1 < poly_x0 || + nsfb->clip.x0 > poly_x1) + return true; + + /* Find the top of the important area */ + if (poly_y0 > nsfb->clip.y0) + y = poly_y0; + else + y = nsfb->clip.y0; + + /* Find the bottom of the important area */ + if (poly_y1 < nsfb->clip.y1) + y_max = poly_y1; + else + y_max = nsfb->clip.y1; + + for (; y < y_max; y++) { + x1 = poly_x0; + /* For each row */ + while (find_span(p, v, x1, y, &x0, &x1)) { + /* don't draw anything outside clip region */ + if (x1 < nsfb->clip.x0) + continue; + else if (x0 < nsfb->clip.x0) + x0 = nsfb->clip.x0; + if (x0 > nsfb->clip.x1) + break; + else if (x1 > nsfb->clip.x1) + x1 = nsfb->clip.x1; + + fline.x0 = x0; + fline.y0 = y; + fline.x1 = x1; + fline.y1 = y; + + /* draw this filled span on current row */ + nsfb->plotter_fns->line(nsfb, 1, &fline, &pen); + + /* don't look for more spans if already at end of clip + * region or polygon */ + if (x1 == nsfb->clip.x1 || x1 == poly_x1) + break; + + if (x0 == x1) + x1++; + } + } + return true; +} + +static bool +rectangle(nsfb_t *nsfb, nsfb_bbox_t *rect, + int line_width, nsfb_colour_t c, + bool dotted, bool dashed) +{ + nsfb_bbox_t side[4]; + nsfb_plot_pen_t pen; + + pen.stroke_colour = c; + pen.stroke_width = line_width; + if (dotted || dashed) { + pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN; + } else { + pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID; + } + + side[0] = *rect; + side[1] = *rect; + side[2] = *rect; + side[3] = *rect; + + side[0].y1 = side[0].y0; + side[1].y0 = side[1].y1; + side[2].x1 = side[2].x0; + side[3].x0 = side[3].x1; + + return nsfb->plotter_fns->line(nsfb, 4, side, &pen); +} + +/* plotter routine for ellipse points */ +static void +ellipsepoints(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c) +{ + nsfb->plotter_fns->point(nsfb, cx + x, cy + y, c); + nsfb->plotter_fns->point(nsfb, cx - x, cy + y, c); + nsfb->plotter_fns->point(nsfb, cx + x, cy - y, c); + nsfb->plotter_fns->point(nsfb, cx - x, cy - y, c); +} + +static void +ellipsefill(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c) +{ + nsfb_bbox_t fline[2]; + nsfb_plot_pen_t pen; + + pen.stroke_colour = c; + + fline[0].x0 = fline[1].x0 = cx - x; + fline[0].x1 = fline[1].x1 = cx + x; + fline[0].y0 = fline[0].y1 = cy + y; + fline[1].y0 = fline[1].y1 = cy - y; + + nsfb->plotter_fns->line(nsfb, 2, fline, &pen); + +} + +#define ROUND(a) ((int)(a+0.5)) + +static bool +ellipse_midpoint(nsfb_t *nsfb, + int cx, + int cy, + int rx, + int ry, + nsfb_colour_t c, + void (ellipsefn)(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c)) +{ + int rx2 = rx * rx; + int ry2 = ry * ry; + int tworx2 = 2 * rx2; + int twory2 = 2 * ry2; + int p; + int x = 0; + int y = ry; + int px = 0; + int py = tworx2 * y; + + ellipsefn(nsfb, cx, cy, x, y, c); + + /* region 1 */ + p = ROUND(ry2 - (rx2 * ry) + (0.25 * rx2)); + while (px < py) { + x++; + px += twory2; + if (p <0) { + p+=ry2 + px; + } else { + y--; + py -= tworx2; + p+=ry2 + px - py; + } + ellipsefn(nsfb, cx, cy, x, y, c); + } + + /* region 2 */ + p = ROUND(ry2*(x+0.5)*(x+0.5) + rx2*(y-1)*(y-1) - rx2*ry2); + while (y > 0) { + y--; + py -= tworx2; + if (p > 0) { + p+=rx2 - py; + } else { + x++; + px += twory2; + p+=rx2 - py + px; + } + ellipsefn(nsfb, cx, cy, x, y, c); + } + return true; +} + + +/* plotter routine for 8way circle symetry */ +static void +circlepoints(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c) +{ + nsfb->plotter_fns->point(nsfb, cx + x, cy + y, c); + nsfb->plotter_fns->point(nsfb, cx - x, cy + y, c); + nsfb->plotter_fns->point(nsfb, cx + x, cy - y, c); + nsfb->plotter_fns->point(nsfb, cx - x, cy - y, c); + nsfb->plotter_fns->point(nsfb, cx + y, cy + x, c); + nsfb->plotter_fns->point(nsfb, cx - y, cy + x, c); + nsfb->plotter_fns->point(nsfb, cx + y, cy - x, c); + nsfb->plotter_fns->point(nsfb, cx - y, cy - x, c); +} + +static void +circlefill(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c) +{ + nsfb_bbox_t fline[4]; + nsfb_plot_pen_t pen; + + pen.stroke_colour = c; + + fline[0].x0 = fline[1].x0 = cx - x; + fline[0].x1 = fline[1].x1 = cx + x; + fline[0].y0 = fline[0].y1 = cy + y; + fline[1].y0 = fline[1].y1 = cy - y; + + fline[2].x0 = fline[3].x0 = cx - y; + fline[2].x1 = fline[3].x1 = cx + y; + fline[2].y0 = fline[2].y1 = cy + x; + fline[3].y0 = fline[3].y1 = cy - x; + + nsfb->plotter_fns->line(nsfb, 4, fline, &pen); +} + +static bool circle_midpoint(nsfb_t *nsfb, + int cx, + int cy, + int r, + nsfb_colour_t c, + void (circfn)(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c)) +{ + int x = 0; + int y = r; + int p = 1 - r; + + circfn(nsfb, cx, cy, x, y, c); + while (x < y) { + x++; + if (p < 0) { + p += 2 * x + 1; + } else { + y--; + p += 2 * (x - y) + 1; + } + circfn(nsfb, cx, cy, x, y, c); + } + return true; +} + +static bool ellipse(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c) +{ + int width = (ellipse->x1 - ellipse->x0)>>1; + int height = (ellipse->y1 - ellipse->y0)>>1; + + if (width == height) { + /* circle */ + return circle_midpoint(nsfb, ellipse->x0 + width, ellipse->y0 + height, width, c, circlepoints); + } else { + return ellipse_midpoint(nsfb, ellipse->x0 + width, ellipse->y0 + height, width, height, c, ellipsepoints); + } +} + +static bool ellipse_fill(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c) +{ + int width = (ellipse->x1 - ellipse->x0) >> 1; + int height = (ellipse->y1 - ellipse->y0) >> 1; + + if (width == height) { + /* circle */ + return circle_midpoint(nsfb, ellipse->x0 + width, ellipse->y0 + height, width, c, circlefill); + } else { + return ellipse_midpoint(nsfb, ellipse->x0 + width, ellipse->y0 + height, width, height, c, ellipsefill); + } +} + + + +/* copy an area of screen from one location to another. + * + * @warning This implementation is woefully incomplete! + */ +static bool +copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox) +{ + int srcx = srcbox->x0; + int srcy = srcbox->y0; + int dstx = dstbox->x0; + int dsty = dstbox->y0; + int width = dstbox->x1 - dstbox->x0; + int height = dstbox->y1 - dstbox->y0; + uint8_t *srcptr; + uint8_t *dstptr; + int hloop; + nsfb_bbox_t allbox; + + nsfb_plot_add_rect(srcbox, dstbox, &allbox); + + nsfb->frontend_rtns->claim(nsfb, &allbox); + + srcptr = (nsfb->ptr + + (srcy * nsfb->linelen) + + ((srcx * nsfb->bpp) / 8)); + + dstptr = (nsfb->ptr + + (dsty * nsfb->linelen) + + ((dstx * nsfb->bpp) / 8)); + + + if (width == nsfb->width) { + /* take shortcut and use memmove */ + memmove(dstptr, srcptr, (width * height * nsfb->bpp) / 8); + } else { + if (srcy > dsty) { + for (hloop = height; hloop > 0; hloop--) { + memmove(dstptr, srcptr, (width * nsfb->bpp) / 8); + srcptr += nsfb->linelen; + dstptr += nsfb->linelen; + } + } else { + srcptr += height * nsfb->linelen; + dstptr += height * nsfb->linelen; + for (hloop = height; hloop > 0; hloop--) { + srcptr -= nsfb->linelen; + dstptr -= nsfb->linelen; + memmove(dstptr, srcptr, (width * nsfb->bpp) / 8); + } + } + } + + nsfb->frontend_rtns->update(nsfb, dstbox); + + return true; +} + +static bool arc(nsfb_t *nsfb, int x, int y, int radius, int angle1, int angle2, nsfb_colour_t c) +{ + nsfb=nsfb; + x = x; + y = y; + radius = radius; + c = c; + angle1=angle1; + angle2=angle2; + return true; +} + +#define N_SEG 30 + +static bool +cubic(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_point_t *ctrlb, nsfb_colour_t cl) +{ + nsfb_bbox_t line; + nsfb_plot_pen_t pen; + + unsigned int seg_loop; + double t; + double one_minus_t; + double a; + double b; + double c; + double d; + double x; + double y; + + pen.stroke_colour = cl; + + x = curve->x0; + y = curve->y0; + + for (seg_loop = 1; seg_loop <= N_SEG; ++seg_loop) { + t = (double)seg_loop / (double)N_SEG; + + one_minus_t = 1.0 - t; + + a = one_minus_t * one_minus_t * one_minus_t; + b = 3.0 * t * one_minus_t * one_minus_t; + c = 3.0 * t * t * one_minus_t; + d = t * t * t; + + line.x0 = x; + line.y0 = y; + + x = a * curve->x0 + b * ctrla->x + c * ctrlb->x + d * curve->x1; + y = a * curve->y0 + b * ctrla->y + c * ctrlb->y + d * curve->y1; + + line.x1 = x; + line.y1 = y; + + nsfb->plotter_fns->line(nsfb, 1, &line, &pen); + } + + return true; +} + +static bool quadratic(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_colour_t cl) +{ + nsfb_bbox_t line; + nsfb_plot_pen_t pen; + + unsigned int seg_loop; + double t; + double one_minus_t; + double a; + double b; + double c; + double x; + double y; + + pen.stroke_colour = cl; + + x = curve->x0; + y = curve->y0; + + for (seg_loop = 1; seg_loop <= N_SEG; ++seg_loop) { + t = (double)seg_loop / (double)N_SEG; + + one_minus_t = 1.0 - t; + + a = one_minus_t * one_minus_t; + b = 2.0 * t * one_minus_t; + c = t * t; + + line.x0 = x; + line.y0 = y; + + x = a * curve->x0 + b * ctrla->x + c * curve->x1; + y = a * curve->y0 + b * ctrla->y + c * curve->y1; + + line.x1 = x; + line.y1 = y; + + nsfb->plotter_fns->line(nsfb, 1, &line, &pen); + } + + return true; +} + +bool select_plotters(nsfb_t *nsfb) +{ + const nsfb_plotter_fns_t *table = NULL; + + switch (nsfb->bpp) { + /* case 1: + table = &_nsfb_1bpp_plotters; + break; + */ + case 8: + table = &_nsfb_8bpp_plotters; + break; + + case 16: + table = &_nsfb_16bpp_plotters; + break; + + /* + case 24: + table = &_nsfb_24bpp_plotters; + break; + */ + case 32: + table = &_nsfb_32bpp_plotters; + break; + + default: + return false; + } + + if (nsfb->plotter_fns != NULL) + free(nsfb->plotter_fns); + + nsfb->plotter_fns = calloc(1, sizeof(nsfb_plotter_fns_t)); + memcpy(nsfb->plotter_fns, table, sizeof(nsfb_plotter_fns_t)); + + /* set the generics */ + nsfb->plotter_fns->clg = clg; + nsfb->plotter_fns->set_clip = set_clip; + nsfb->plotter_fns->get_clip = get_clip; + nsfb->plotter_fns->polygon = polygon; + nsfb->plotter_fns->rectangle = rectangle; + nsfb->plotter_fns->ellipse = ellipse; + nsfb->plotter_fns->ellipse_fill = ellipse_fill; + nsfb->plotter_fns->copy = copy; + nsfb->plotter_fns->arc = arc; + nsfb->plotter_fns->quadratic = quadratic; + nsfb->plotter_fns->cubic = cubic; + + /* set default clip rectangle to size of framebuffer */ + nsfb->clip.x0 = 0; + nsfb->clip.y0 = 0; + nsfb->clip.x1 = nsfb->width; + nsfb->clip.y1 = nsfb->height; + + return true; +} diff --git a/src/plot/util.c b/src/plot/util.c new file mode 100644 index 0000000..cf2ec9b --- /dev/null +++ b/src/plot/util.c @@ -0,0 +1,199 @@ +#include + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "libnsfb_plot_util.h" + +#include "nsfb.h" + +enum { + POINT_LEFTOF_REGION = 1, + POINT_RIGHTOF_REGION = 2, + POINT_ABOVE_REGION = 4, + POINT_BELOW_REGION = 8, +}; + +#define REGION(x,y,cx1,cx2,cy1,cy2) \ + ( ( (y) > (cy2) ? POINT_BELOW_REGION : 0) | \ + ( (y) < (cy1) ? POINT_ABOVE_REGION : 0) | \ + ( (x) > (cx2) ? POINT_RIGHTOF_REGION : 0) | \ + ( (x) < (cx1) ? POINT_LEFTOF_REGION : 0) ) + +#define SWAP(a, b) do { int t; t=(a); (a)=(b); (b)=t; } while(0) + +/* clip a rectangle with another clipping rectangle. + * + * @param clip The rectangle to clip to. + * @param rect The rectangle to clip. + * @return false if the \a rect lies completely outside the \a clip rectangle, + * true if some of the \a rect is still visible. + */ +bool +nsfb_plot_clip(const nsfb_bbox_t * restrict clip, nsfb_bbox_t * restrict rect) +{ + char region1; + char region2; + + if (rect->x1 < rect->x0) SWAP(rect->x0, rect->x1); + + if (rect->y1 < rect->y0) SWAP(rect->y0, rect->y1); + + region1 = REGION(rect->x0, rect->y0, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); + region2 = REGION(rect->x1, rect->y1, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); + + /* area lies entirely outside the clipping rectangle */ + if ((region1 | region2) && (region1 & region2)) + return false; + + if (rect->x0 < clip->x0) + rect->x0 = clip->x0; + if (rect->x0 > clip->x1) + rect->x0 = clip->x1; + + if (rect->x1 < clip->x0) + rect->x1 = clip->x0; + if (rect->x1 > clip->x1) + rect->x1 = clip->x1; + + if (rect->y0 < clip->y0) + rect->y0 = clip->y0; + if (rect->y0 > clip->y1) + rect->y0 = clip->y1; + + if (rect->y1 < clip->y0) + rect->y1 = clip->y0; + if (rect->y1 > clip->y1) + rect->y1 = clip->y1; + + return true; +} + +bool +nsfb_plot_clip_ctx(nsfb_t *nsfb, nsfb_bbox_t * restrict rect) +{ + return nsfb_plot_clip(&nsfb->clip, rect); +} + +/** Clip a line to a bounding box. + */ +bool nsfb_plot_clip_line(const nsfb_bbox_t *clip, nsfb_bbox_t * restrict line) +{ + char region1; + char region2; + region1 = REGION(line->x0, line->y0, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); + region2 = REGION(line->x1, line->y1, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); + + while (region1 | region2) { + if (region1 & region2) { + /* line lies entirely outside the clipping rectangle */ + return false; + } + + if (region1) { + /* first point */ + if (region1 & POINT_BELOW_REGION) { + /* divide line at bottom */ + line->x0 = (line->x0 + (line->x1 - line->x0) * + (clip->y1 - 1 - line->y0) / (line->y1 - line->y0)); + line->y0 = clip->y1 - 1; + } else if (region1 & POINT_ABOVE_REGION) { + /* divide line at top */ + line->x0 = (line->x0 + (line->x1 - line->x0) * + (clip->y0 - line->y0) / (line->y1 - line->y0)); + line->y0 = clip->y0; + } else if (region1 & POINT_RIGHTOF_REGION) { + /* divide line at right */ + line->y0 = (line->y0 + (line->y1 - line->y0) * + (clip->x1 - 1 - line->x0) / (line->x1 - line->x0)); + line->x0 = clip->x1 - 1; + } else if (region1 & POINT_LEFTOF_REGION) { + /* divide line at right */ + line->y0 = (line->y0 + (line->y1 - line->y0) * + (clip->x0 - line->x0) / (line->x1 - line->x0)); + line->x0 = clip->x0; + } + + region1 = REGION(line->x0, line->y0, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); + } else { + /* second point */ + if (region2 & POINT_BELOW_REGION) { + /* divide line at bottom*/ + line->x1 = (line->x0 + (line->x1 - line->x0) * + (clip->y1 - 1 - line->y0) / (line->y1 - line->y0)); + line->y1 = clip->y1 - 1; + } else if (region2 & POINT_ABOVE_REGION) { + /* divide line at top*/ + line->x1 = (line->x0 + (line->x1 - line->x0) * + (clip->y0 - line->y0) / (line->y1 - line->y0)); + line->y1 = clip->y0; + } else if (region2 & POINT_RIGHTOF_REGION) { + /* divide line at right*/ + line->y1 = (line->y0 + (line->y1 - line->y0) * + (clip->x1 - 1 - line->x0) / (line->x1 - line->x0)); + line->x1 = clip->x1 - 1; + } else if (region2 & POINT_LEFTOF_REGION) { + /* divide line at right*/ + line->y1 = (line->y0 + (line->y1 - line->y0) * + (clip->x0 - line->x0) / (line->x1 - line->x0)); + line->x1 = clip->x0; + } + + region2 = REGION(line->x1, line->y1, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); + } + } + + return true; +} + +bool nsfb_plot_clip_line_ctx(nsfb_t *nsfb, nsfb_bbox_t * restrict line) +{ + return nsfb_plot_clip_line(&nsfb->clip, line); +} + +/* documented in libnsfb_plot_util.h */ +bool +nsfb_plot_add_rect(const nsfb_bbox_t *box1, const nsfb_bbox_t *box2, nsfb_bbox_t *result) +{ + /* lower x coordinate */ + if (box1->x0 < box2->x0) + result->x0 = box1->x0; + else + result->x0 = box2->x0; + + /* lower y coordinate */ + if (box1->y0 < box2->y0) + result->y0 = box1->y0; + else + result->y0 = box2->y0; + + /* upper x coordinate */ + if (box1->x1 > box2->x1) + result->x1 = box1->x1; + else + result->x1 = box2->x1; + + /* upper y coordinate */ + if (box1->y1 > box2->y1) + result->y1 = box1->y1; + else + result->y1 = box2->y1; + + return true; +} + +bool nsfb_plot_bbox_intersect(const nsfb_bbox_t *box1, const nsfb_bbox_t *box2) +{ + if (box2->x1 < box1->x0) + return false; + + if (box2->y1 < box1->y0) + return false; + + if (box2->x0 > box1->x1) + return false; + + if (box2->y0 > box1->y1) + return false; + + return true; +} diff --git a/src/plot_util.c b/src/plot_util.c deleted file mode 100644 index cf2ec9b..0000000 --- a/src/plot_util.c +++ /dev/null @@ -1,199 +0,0 @@ -#include - -#include "libnsfb.h" -#include "libnsfb_plot.h" -#include "libnsfb_plot_util.h" - -#include "nsfb.h" - -enum { - POINT_LEFTOF_REGION = 1, - POINT_RIGHTOF_REGION = 2, - POINT_ABOVE_REGION = 4, - POINT_BELOW_REGION = 8, -}; - -#define REGION(x,y,cx1,cx2,cy1,cy2) \ - ( ( (y) > (cy2) ? POINT_BELOW_REGION : 0) | \ - ( (y) < (cy1) ? POINT_ABOVE_REGION : 0) | \ - ( (x) > (cx2) ? POINT_RIGHTOF_REGION : 0) | \ - ( (x) < (cx1) ? POINT_LEFTOF_REGION : 0) ) - -#define SWAP(a, b) do { int t; t=(a); (a)=(b); (b)=t; } while(0) - -/* clip a rectangle with another clipping rectangle. - * - * @param clip The rectangle to clip to. - * @param rect The rectangle to clip. - * @return false if the \a rect lies completely outside the \a clip rectangle, - * true if some of the \a rect is still visible. - */ -bool -nsfb_plot_clip(const nsfb_bbox_t * restrict clip, nsfb_bbox_t * restrict rect) -{ - char region1; - char region2; - - if (rect->x1 < rect->x0) SWAP(rect->x0, rect->x1); - - if (rect->y1 < rect->y0) SWAP(rect->y0, rect->y1); - - region1 = REGION(rect->x0, rect->y0, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); - region2 = REGION(rect->x1, rect->y1, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); - - /* area lies entirely outside the clipping rectangle */ - if ((region1 | region2) && (region1 & region2)) - return false; - - if (rect->x0 < clip->x0) - rect->x0 = clip->x0; - if (rect->x0 > clip->x1) - rect->x0 = clip->x1; - - if (rect->x1 < clip->x0) - rect->x1 = clip->x0; - if (rect->x1 > clip->x1) - rect->x1 = clip->x1; - - if (rect->y0 < clip->y0) - rect->y0 = clip->y0; - if (rect->y0 > clip->y1) - rect->y0 = clip->y1; - - if (rect->y1 < clip->y0) - rect->y1 = clip->y0; - if (rect->y1 > clip->y1) - rect->y1 = clip->y1; - - return true; -} - -bool -nsfb_plot_clip_ctx(nsfb_t *nsfb, nsfb_bbox_t * restrict rect) -{ - return nsfb_plot_clip(&nsfb->clip, rect); -} - -/** Clip a line to a bounding box. - */ -bool nsfb_plot_clip_line(const nsfb_bbox_t *clip, nsfb_bbox_t * restrict line) -{ - char region1; - char region2; - region1 = REGION(line->x0, line->y0, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); - region2 = REGION(line->x1, line->y1, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); - - while (region1 | region2) { - if (region1 & region2) { - /* line lies entirely outside the clipping rectangle */ - return false; - } - - if (region1) { - /* first point */ - if (region1 & POINT_BELOW_REGION) { - /* divide line at bottom */ - line->x0 = (line->x0 + (line->x1 - line->x0) * - (clip->y1 - 1 - line->y0) / (line->y1 - line->y0)); - line->y0 = clip->y1 - 1; - } else if (region1 & POINT_ABOVE_REGION) { - /* divide line at top */ - line->x0 = (line->x0 + (line->x1 - line->x0) * - (clip->y0 - line->y0) / (line->y1 - line->y0)); - line->y0 = clip->y0; - } else if (region1 & POINT_RIGHTOF_REGION) { - /* divide line at right */ - line->y0 = (line->y0 + (line->y1 - line->y0) * - (clip->x1 - 1 - line->x0) / (line->x1 - line->x0)); - line->x0 = clip->x1 - 1; - } else if (region1 & POINT_LEFTOF_REGION) { - /* divide line at right */ - line->y0 = (line->y0 + (line->y1 - line->y0) * - (clip->x0 - line->x0) / (line->x1 - line->x0)); - line->x0 = clip->x0; - } - - region1 = REGION(line->x0, line->y0, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); - } else { - /* second point */ - if (region2 & POINT_BELOW_REGION) { - /* divide line at bottom*/ - line->x1 = (line->x0 + (line->x1 - line->x0) * - (clip->y1 - 1 - line->y0) / (line->y1 - line->y0)); - line->y1 = clip->y1 - 1; - } else if (region2 & POINT_ABOVE_REGION) { - /* divide line at top*/ - line->x1 = (line->x0 + (line->x1 - line->x0) * - (clip->y0 - line->y0) / (line->y1 - line->y0)); - line->y1 = clip->y0; - } else if (region2 & POINT_RIGHTOF_REGION) { - /* divide line at right*/ - line->y1 = (line->y0 + (line->y1 - line->y0) * - (clip->x1 - 1 - line->x0) / (line->x1 - line->x0)); - line->x1 = clip->x1 - 1; - } else if (region2 & POINT_LEFTOF_REGION) { - /* divide line at right*/ - line->y1 = (line->y0 + (line->y1 - line->y0) * - (clip->x0 - line->x0) / (line->x1 - line->x0)); - line->x1 = clip->x0; - } - - region2 = REGION(line->x1, line->y1, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); - } - } - - return true; -} - -bool nsfb_plot_clip_line_ctx(nsfb_t *nsfb, nsfb_bbox_t * restrict line) -{ - return nsfb_plot_clip_line(&nsfb->clip, line); -} - -/* documented in libnsfb_plot_util.h */ -bool -nsfb_plot_add_rect(const nsfb_bbox_t *box1, const nsfb_bbox_t *box2, nsfb_bbox_t *result) -{ - /* lower x coordinate */ - if (box1->x0 < box2->x0) - result->x0 = box1->x0; - else - result->x0 = box2->x0; - - /* lower y coordinate */ - if (box1->y0 < box2->y0) - result->y0 = box1->y0; - else - result->y0 = box2->y0; - - /* upper x coordinate */ - if (box1->x1 > box2->x1) - result->x1 = box1->x1; - else - result->x1 = box2->x1; - - /* upper y coordinate */ - if (box1->y1 > box2->y1) - result->y1 = box1->y1; - else - result->y1 = box2->y1; - - return true; -} - -bool nsfb_plot_bbox_intersect(const nsfb_bbox_t *box1, const nsfb_bbox_t *box2) -{ - if (box2->x1 < box1->x0) - return false; - - if (box2->y1 < box1->y0) - return false; - - if (box2->x0 > box1->x1) - return false; - - if (box2->y0 > box1->y1) - return false; - - return true; -} diff --git a/src/plotters.c b/src/plotters.c deleted file mode 100644 index d04559e..0000000 --- a/src/plotters.c +++ /dev/null @@ -1,663 +0,0 @@ -/* - * Copyright 2009 Vincent Sanders - * Copyright 2009 Michael Drake - * - * This file is part of libnsfb, http://www.netsurf-browser.org/ - * Licenced under the MIT License, - * http://www.opensource.org/licenses/mit-license.php - */ - -/** \file - * generic plotter functions which are not depth dependant (implementation). - */ - -#include -#include -#include -#include - -#include "libnsfb.h" -#include "libnsfb_plot.h" -#include "libnsfb_plot_util.h" - -#include "nsfb.h" -#include "plot.h" -#include "frontend.h" - -extern const nsfb_plotter_fns_t _nsfb_1bpp_plotters; -extern const nsfb_plotter_fns_t _nsfb_8bpp_plotters; -extern const nsfb_plotter_fns_t _nsfb_16bpp_plotters; -extern const nsfb_plotter_fns_t _nsfb_24bpp_plotters; -extern const nsfb_plotter_fns_t _nsfb_32bpp_plotters; - -static bool set_clip(nsfb_t *nsfb, nsfb_bbox_t *clip) -{ - nsfb_bbox_t fbarea; - - /* screen area */ - fbarea.x0 = 0; - fbarea.y0 = 0; - fbarea.x1 = nsfb->width; - fbarea.y1 = nsfb->height; - - if (clip == NULL) { - nsfb->clip = fbarea; - } else { - if (!nsfb_plot_clip(&fbarea, clip)) - return false; - - nsfb->clip = *clip; - } - return true; -} - -static bool get_clip(nsfb_t *nsfb, nsfb_bbox_t *clip) -{ - *clip = nsfb->clip; - return true; -} - -static bool clg(nsfb_t *nsfb, nsfb_colour_t c) -{ - return nsfb->plotter_fns->fill(nsfb, &nsfb->clip, c); -} - -/** - * Find first filled span along horizontal line at given coordinate - * - * \param p array of polygon vertices (x1, y1, x2, y2, ... , xN, yN) - * \param n number of polygon vertex values (N * 2) - * \param x current position along current scan line - * \param y position of current scan line - * \param x0 updated to start of filled area - * \param x1 updated to end of filled area - * \return true if an intersection was found - */ -static bool find_span(const int *p, int n, int x, int y, int *x0, int *x1) -{ - int i; - int p_x0, p_y0; - int p_x1, p_y1; - int x_new; - bool direction = false; - - *x0 = *x1 = INT_MAX; - - for (i = 0; i < n; i = i + 2) { - /* get line endpoints */ - if (i != n - 2) { - /* not the last line */ - p_x0 = p[i]; p_y0 = p[i + 1]; - p_x1 = p[i + 2]; p_y1 = p[i + 3]; - } else { - /* last line; 2nd endpoint is first vertex */ - p_x0 = p[i]; p_y0 = p[i + 1]; - p_x1 = p[0]; p_y1 = p[1]; - } - /* ignore horizontal lines */ - if (p_y0 == p_y1) - continue; - - /* ignore lines that don't cross this y level */ - if ((y < p_y0 && y < p_y1) || (y > p_y0 && y > p_y1)) - continue; - - if (p_x0 == p_x1) { - /* vertical line, x is constant */ - x_new = p_x0; - } else { - /* find intersect */ - x_new = p_x0 + ((long long)(y - p_y0) * (p_x1 - p_x0)) / - (p_y1 - p_y0); - } - - /* ignore intersections before current x */ - if (x_new < x) - continue; - - /* set nearest intersections as filled area endpoints */ - if (x_new < *x0) { - /* nearer than first endpoint */ - *x1 = *x0; - *x0 = x_new; - direction = (p_y0 > p_y1); - } else if (x_new == *x0) { - /* same as first endpoint */ - if ((p_y0 > p_y1) != direction) - *x1 = x_new; - } else if (x_new < *x1) { - /* nearer than second endpoint */ - *x1 = x_new; - } - - } - if (*x0 == INT_MAX) - /* no span found */ - return false; - - /* span found */ - if (*x1 == INT_MAX) { - *x1 = *x0; - *x0 = x; - return true; - } - - return true; -} - - -/** - * Plot a polygon - * - * \param nsfb framebuffer context - * \param p array of polygon vertices (x1, y1, x2, y2, ... , xN, yN) - * \param n number of polygon vertices (N) - * \param c fill colour - * \return true if no errors - */ -static bool -polygon(nsfb_t *nsfb, const int *p, unsigned int n, nsfb_colour_t c) -{ - int poly_x0, poly_y0; /* Bounding box top left corner */ - int poly_x1, poly_y1; /* Bounding box bottom right corner */ - int i, j; /* indexes */ - int x0, x1; /* filled span extents */ - int y; /* current y coordinate */ - int y_max; /* bottom of plot area */ - nsfb_bbox_t fline; - nsfb_plot_pen_t pen; - - /* find no. of vertex values */ - int v = n * 2; - - /* Can't plot polygons with 2 or fewer vertices */ - if (n <= 2) - return true; - - pen.stroke_colour = c; - - /* Find polygon bounding box */ - poly_x0 = poly_x1 = *p; - poly_y0 = poly_y1 = p[1]; - for (i = 2; i < v; i = i + 2) { - j = i + 1; - if (p[i] < poly_x0) - poly_x0 = p[i]; - else if (p[i] > poly_x1) - poly_x1 = p[i]; - if (p[j] < poly_y0) - poly_y0 = p[j]; - else if (p[j] > poly_y1) - poly_y1 = p[j]; - } - - /* Don't try to plot it if it's outside the clip rectangle */ - if (nsfb->clip.y1 < poly_y0 || - nsfb->clip.y0 > poly_y1 || - nsfb->clip.x1 < poly_x0 || - nsfb->clip.x0 > poly_x1) - return true; - - /* Find the top of the important area */ - if (poly_y0 > nsfb->clip.y0) - y = poly_y0; - else - y = nsfb->clip.y0; - - /* Find the bottom of the important area */ - if (poly_y1 < nsfb->clip.y1) - y_max = poly_y1; - else - y_max = nsfb->clip.y1; - - for (; y < y_max; y++) { - x1 = poly_x0; - /* For each row */ - while (find_span(p, v, x1, y, &x0, &x1)) { - /* don't draw anything outside clip region */ - if (x1 < nsfb->clip.x0) - continue; - else if (x0 < nsfb->clip.x0) - x0 = nsfb->clip.x0; - if (x0 > nsfb->clip.x1) - break; - else if (x1 > nsfb->clip.x1) - x1 = nsfb->clip.x1; - - fline.x0 = x0; - fline.y0 = y; - fline.x1 = x1; - fline.y1 = y; - - /* draw this filled span on current row */ - nsfb->plotter_fns->line(nsfb, 1, &fline, &pen); - - /* don't look for more spans if already at end of clip - * region or polygon */ - if (x1 == nsfb->clip.x1 || x1 == poly_x1) - break; - - if (x0 == x1) - x1++; - } - } - return true; -} - -static bool -rectangle(nsfb_t *nsfb, nsfb_bbox_t *rect, - int line_width, nsfb_colour_t c, - bool dotted, bool dashed) -{ - nsfb_bbox_t side[4]; - nsfb_plot_pen_t pen; - - pen.stroke_colour = c; - pen.stroke_width = line_width; - if (dotted || dashed) { - pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN; - } else { - pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID; - } - - side[0] = *rect; - side[1] = *rect; - side[2] = *rect; - side[3] = *rect; - - side[0].y1 = side[0].y0; - side[1].y0 = side[1].y1; - side[2].x1 = side[2].x0; - side[3].x0 = side[3].x1; - - return nsfb->plotter_fns->line(nsfb, 4, side, &pen); -} - -/* plotter routine for ellipse points */ -static void -ellipsepoints(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c) -{ - nsfb->plotter_fns->point(nsfb, cx + x, cy + y, c); - nsfb->plotter_fns->point(nsfb, cx - x, cy + y, c); - nsfb->plotter_fns->point(nsfb, cx + x, cy - y, c); - nsfb->plotter_fns->point(nsfb, cx - x, cy - y, c); -} - -static void -ellipsefill(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c) -{ - nsfb_bbox_t fline[2]; - nsfb_plot_pen_t pen; - - pen.stroke_colour = c; - - fline[0].x0 = fline[1].x0 = cx - x; - fline[0].x1 = fline[1].x1 = cx + x; - fline[0].y0 = fline[0].y1 = cy + y; - fline[1].y0 = fline[1].y1 = cy - y; - - nsfb->plotter_fns->line(nsfb, 2, fline, &pen); - -} - -#define ROUND(a) ((int)(a+0.5)) - -static bool -ellipse_midpoint(nsfb_t *nsfb, - int cx, - int cy, - int rx, - int ry, - nsfb_colour_t c, - void (ellipsefn)(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c)) -{ - int rx2 = rx * rx; - int ry2 = ry * ry; - int tworx2 = 2 * rx2; - int twory2 = 2 * ry2; - int p; - int x = 0; - int y = ry; - int px = 0; - int py = tworx2 * y; - - ellipsefn(nsfb, cx, cy, x, y, c); - - /* region 1 */ - p = ROUND(ry2 - (rx2 * ry) + (0.25 * rx2)); - while (px < py) { - x++; - px += twory2; - if (p <0) { - p+=ry2 + px; - } else { - y--; - py -= tworx2; - p+=ry2 + px - py; - } - ellipsefn(nsfb, cx, cy, x, y, c); - } - - /* region 2 */ - p = ROUND(ry2*(x+0.5)*(x+0.5) + rx2*(y-1)*(y-1) - rx2*ry2); - while (y > 0) { - y--; - py -= tworx2; - if (p > 0) { - p+=rx2 - py; - } else { - x++; - px += twory2; - p+=rx2 - py + px; - } - ellipsefn(nsfb, cx, cy, x, y, c); - } - return true; -} - - -/* plotter routine for 8way circle symetry */ -static void -circlepoints(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c) -{ - nsfb->plotter_fns->point(nsfb, cx + x, cy + y, c); - nsfb->plotter_fns->point(nsfb, cx - x, cy + y, c); - nsfb->plotter_fns->point(nsfb, cx + x, cy - y, c); - nsfb->plotter_fns->point(nsfb, cx - x, cy - y, c); - nsfb->plotter_fns->point(nsfb, cx + y, cy + x, c); - nsfb->plotter_fns->point(nsfb, cx - y, cy + x, c); - nsfb->plotter_fns->point(nsfb, cx + y, cy - x, c); - nsfb->plotter_fns->point(nsfb, cx - y, cy - x, c); -} - -static void -circlefill(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c) -{ - nsfb_bbox_t fline[4]; - nsfb_plot_pen_t pen; - - pen.stroke_colour = c; - - fline[0].x0 = fline[1].x0 = cx - x; - fline[0].x1 = fline[1].x1 = cx + x; - fline[0].y0 = fline[0].y1 = cy + y; - fline[1].y0 = fline[1].y1 = cy - y; - - fline[2].x0 = fline[3].x0 = cx - y; - fline[2].x1 = fline[3].x1 = cx + y; - fline[2].y0 = fline[2].y1 = cy + x; - fline[3].y0 = fline[3].y1 = cy - x; - - nsfb->plotter_fns->line(nsfb, 4, fline, &pen); -} - -static bool circle_midpoint(nsfb_t *nsfb, - int cx, - int cy, - int r, - nsfb_colour_t c, - void (circfn)(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c)) -{ - int x = 0; - int y = r; - int p = 1 - r; - - circfn(nsfb, cx, cy, x, y, c); - while (x < y) { - x++; - if (p < 0) { - p += 2 * x + 1; - } else { - y--; - p += 2 * (x - y) + 1; - } - circfn(nsfb, cx, cy, x, y, c); - } - return true; -} - -static bool ellipse(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c) -{ - int width = (ellipse->x1 - ellipse->x0)>>1; - int height = (ellipse->y1 - ellipse->y0)>>1; - - if (width == height) { - /* circle */ - return circle_midpoint(nsfb, ellipse->x0 + width, ellipse->y0 + height, width, c, circlepoints); - } else { - return ellipse_midpoint(nsfb, ellipse->x0 + width, ellipse->y0 + height, width, height, c, ellipsepoints); - } -} - -static bool ellipse_fill(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c) -{ - int width = (ellipse->x1 - ellipse->x0) >> 1; - int height = (ellipse->y1 - ellipse->y0) >> 1; - - if (width == height) { - /* circle */ - return circle_midpoint(nsfb, ellipse->x0 + width, ellipse->y0 + height, width, c, circlefill); - } else { - return ellipse_midpoint(nsfb, ellipse->x0 + width, ellipse->y0 + height, width, height, c, ellipsefill); - } -} - - - -/* copy an area of screen from one location to another. - * - * @warning This implementation is woefully incomplete! - */ -static bool -copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox) -{ - int srcx = srcbox->x0; - int srcy = srcbox->y0; - int dstx = dstbox->x0; - int dsty = dstbox->y0; - int width = dstbox->x1 - dstbox->x0; - int height = dstbox->y1 - dstbox->y0; - uint8_t *srcptr; - uint8_t *dstptr; - int hloop; - nsfb_bbox_t allbox; - - nsfb_plot_add_rect(srcbox, dstbox, &allbox); - - nsfb->frontend_rtns->claim(nsfb, &allbox); - - srcptr = (nsfb->ptr + - (srcy * nsfb->linelen) + - ((srcx * nsfb->bpp) / 8)); - - dstptr = (nsfb->ptr + - (dsty * nsfb->linelen) + - ((dstx * nsfb->bpp) / 8)); - - - if (width == nsfb->width) { - /* take shortcut and use memmove */ - memmove(dstptr, srcptr, (width * height * nsfb->bpp) / 8); - } else { - if (srcy > dsty) { - for (hloop = height; hloop > 0; hloop--) { - memmove(dstptr, srcptr, (width * nsfb->bpp) / 8); - srcptr += nsfb->linelen; - dstptr += nsfb->linelen; - } - } else { - srcptr += height * nsfb->linelen; - dstptr += height * nsfb->linelen; - for (hloop = height; hloop > 0; hloop--) { - srcptr -= nsfb->linelen; - dstptr -= nsfb->linelen; - memmove(dstptr, srcptr, (width * nsfb->bpp) / 8); - } - } - } - - nsfb->frontend_rtns->update(nsfb, dstbox); - - return true; -} - -static bool arc(nsfb_t *nsfb, int x, int y, int radius, int angle1, int angle2, nsfb_colour_t c) -{ - nsfb=nsfb; - x = x; - y = y; - radius = radius; - c = c; - angle1=angle1; - angle2=angle2; - return true; -} - -#define N_SEG 30 - -static bool -cubic(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_point_t *ctrlb, nsfb_colour_t cl) -{ - nsfb_bbox_t line; - nsfb_plot_pen_t pen; - - unsigned int seg_loop; - double t; - double one_minus_t; - double a; - double b; - double c; - double d; - double x; - double y; - - pen.stroke_colour = cl; - - x = curve->x0; - y = curve->y0; - - for (seg_loop = 1; seg_loop <= N_SEG; ++seg_loop) { - t = (double)seg_loop / (double)N_SEG; - - one_minus_t = 1.0 - t; - - a = one_minus_t * one_minus_t * one_minus_t; - b = 3.0 * t * one_minus_t * one_minus_t; - c = 3.0 * t * t * one_minus_t; - d = t * t * t; - - line.x0 = x; - line.y0 = y; - - x = a * curve->x0 + b * ctrla->x + c * ctrlb->x + d * curve->x1; - y = a * curve->y0 + b * ctrla->y + c * ctrlb->y + d * curve->y1; - - line.x1 = x; - line.y1 = y; - - nsfb->plotter_fns->line(nsfb, 1, &line, &pen); - } - - return true; -} - -static bool quadratic(nsfb_t *nsfb, nsfb_bbox_t *curve, nsfb_point_t *ctrla, nsfb_colour_t cl) -{ - nsfb_bbox_t line; - nsfb_plot_pen_t pen; - - unsigned int seg_loop; - double t; - double one_minus_t; - double a; - double b; - double c; - double x; - double y; - - pen.stroke_colour = cl; - - x = curve->x0; - y = curve->y0; - - for (seg_loop = 1; seg_loop <= N_SEG; ++seg_loop) { - t = (double)seg_loop / (double)N_SEG; - - one_minus_t = 1.0 - t; - - a = one_minus_t * one_minus_t; - b = 2.0 * t * one_minus_t; - c = t * t; - - line.x0 = x; - line.y0 = y; - - x = a * curve->x0 + b * ctrla->x + c * curve->x1; - y = a * curve->y0 + b * ctrla->y + c * curve->y1; - - line.x1 = x; - line.y1 = y; - - nsfb->plotter_fns->line(nsfb, 1, &line, &pen); - } - - return true; -} - -bool select_plotters(nsfb_t *nsfb) -{ - const nsfb_plotter_fns_t *table = NULL; - - switch (nsfb->bpp) { - /* case 1: - table = &_nsfb_1bpp_plotters; - break; - */ - case 8: - table = &_nsfb_8bpp_plotters; - break; - - case 16: - table = &_nsfb_16bpp_plotters; - break; - - /* - case 24: - table = &_nsfb_24bpp_plotters; - break; - */ - case 32: - table = &_nsfb_32bpp_plotters; - break; - - default: - return false; - } - - if (nsfb->plotter_fns != NULL) - free(nsfb->plotter_fns); - - nsfb->plotter_fns = calloc(1, sizeof(nsfb_plotter_fns_t)); - memcpy(nsfb->plotter_fns, table, sizeof(nsfb_plotter_fns_t)); - - /* set the generics */ - nsfb->plotter_fns->clg = clg; - nsfb->plotter_fns->set_clip = set_clip; - nsfb->plotter_fns->get_clip = get_clip; - nsfb->plotter_fns->polygon = polygon; - nsfb->plotter_fns->rectangle = rectangle; - nsfb->plotter_fns->ellipse = ellipse; - nsfb->plotter_fns->ellipse_fill = ellipse_fill; - nsfb->plotter_fns->copy = copy; - nsfb->plotter_fns->arc = arc; - nsfb->plotter_fns->quadratic = quadratic; - nsfb->plotter_fns->cubic = cubic; - - /* set default clip rectangle to size of framebuffer */ - nsfb->clip.x0 = 0; - nsfb->clip.y0 = 0; - nsfb->clip.x1 = nsfb->width; - nsfb->clip.y1 = nsfb->height; - - return true; -} -- cgit v1.2.3