summaryrefslogtreecommitdiff
path: root/src/plotters.c
diff options
context:
space:
mode:
authorVincent Sanders <vince@netsurf-browser.org>2010-01-20 17:18:28 +0000
committerVincent Sanders <vince@netsurf-browser.org>2010-01-20 17:18:28 +0000
commit131b6c4a00575c9e996a9ae60c90a9647fb5ef75 (patch)
treedba439673b801a22a833270dbd615628bf0614e4 /src/plotters.c
parenta3097232844a20ea918d63722dbe6a7c71493bab (diff)
downloadlibnsfb-131b6c4a00575c9e996a9ae60c90a9647fb5ef75.tar.gz
libnsfb-131b6c4a00575c9e996a9ae60c90a9647fb5ef75.tar.bz2
move plot functions to their own sub directory
fix 8 and 16bpp plotters when used with cursor svn path=/trunk/libnsfb/; revision=9850
Diffstat (limited to 'src/plotters.c')
-rw-r--r--src/plotters.c663
1 files changed, 0 insertions, 663 deletions
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 <vince@simtec.co.uk>
- * Copyright 2009 Michael Drake <tlsa@netsurf-browser.org>
- *
- * 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 <stdbool.h>
-#include <limits.h>
-#include <malloc.h>
-#include <string.h>
-
-#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;
-}