summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2010-07-08 14:09:42 (GMT)
committer Michael Drake <tlsa@netsurf-browser.org>2010-07-08 14:09:42 (GMT)
commitaadc4de420d33d0c26e1d767bac5ca720cb432d2 (patch)
tree92a6514b8dde269ce97b40f3b4dfdce18423ace7
parent54848b89d52e23c614977834433a6893c1a1c3cb (diff)
downloadlibnsfb-aadc4de420d33d0c26e1d767bac5ca720cb432d2.tar.gz
libnsfb-aadc4de420d33d0c26e1d767bac5ca720cb432d2.tar.bz2
Add support for scaled bitmap plotting.
svn path=/trunk/libnsfb/; revision=10608
-rw-r--r--src/plot/32bpp.c150
1 files changed, 141 insertions, 9 deletions
diff --git a/src/plot/32bpp.c b/src/plot/32bpp.c
index 243cdb4..01cdfbb 100644
--- a/src/plot/32bpp.c
+++ b/src/plot/32bpp.c
@@ -1,5 +1,6 @@
/*
* Copyright 2009 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2010 Michael Drake <tlsa@netsurf-browser.org>
*
* This file is part of libnsfb, http://www.netsurf-browser.org/
* Licenced under the MIT License,
@@ -321,6 +322,137 @@ glyph8(nsfb_t *nsfb,
return true;
}
+static bool bitmap_scaled(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, *pvideo_limit;
+ nsfb_colour_t abpixel = 0; /* alphablended pixel */
+ int xloop;
+ int xoff, yoff, xoffs; /* x and y offsets into image */
+ int x = loc->x0;
+ int y = loc->y0;
+ int width = loc->x1 - loc->x0; /* size to scale to */
+ int height = loc->y1 - loc->y0; /* size to scale to */
+ int rheight, rwidth; /* post-clipping render area dimensions */
+ int dx, dy; /* scale factor (integer part) */
+ int dxr, dyr; /* scale factor (remainder) */
+ int rx, ry; /* remainder trackers */
+ nsfb_bbox_t clipped; /* clipped display */
+
+ /* 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;
+ }
+
+ /* get height of rendering region, after clipping */
+ if (height > (clipped.y1 - clipped.y0))
+ rheight = (clipped.y1 - clipped.y0);
+ else
+ rheight = height;
+
+ /* get width of rendering region, after clipping */
+ if (width > (clipped.x1 - clipped.x0))
+ rwidth = (clipped.x1 - clipped.x0);
+ else
+ rwidth = width;
+
+ /* start offsets to part of image being scaled, after clipping */
+ xoffs = ((clipped.x0 - x) * bmp_width) / width;
+ yoff = (((clipped.y0 - y) * bmp_height) / height) * bmp_stride;
+
+ /* get veritcal (y) and horizontal (x) scale factors; both integer
+ * part and remainder */
+ dx = bmp_width / width;
+ dy = bmp_height / height;
+ dxr = bmp_width % width;
+ dyr = bmp_height % height;
+ rx = ry = 0; /* initialise remainder counters */
+
+ /* plot the image */
+ pvideo = get_xy_loc(nsfb, clipped.x0, clipped.y0);
+ pvideo_limit = pvideo + (nsfb->linelen >> 2) * rheight;
+ if (alpha) {
+ for (; pvideo < pvideo_limit; pvideo += (nsfb->linelen >> 2)) {
+ /* looping through render area vertically */
+ xoff = xoffs;
+ rx = 0;
+ for (xloop = 0; xloop < rwidth; xloop++) {
+ /* looping through render area horizontally */
+ /* get value of source pixel in question */
+ abpixel = pixel[yoff + xoff];
+ if ((abpixel & 0xFF000000) != 0) {
+ /* pixel is not transparent; have to
+ * plot something */
+ if ((abpixel & 0xFF000000) !=
+ 0xFF000000) {
+ /* pixel is not opaque; need to
+ * blend */
+ abpixel = nsfb_plot_ablend(
+ abpixel,
+ pixel_to_colour(
+ *(pvideo +
+ xloop)));
+ }
+ /* plot pixel */
+ *(pvideo + xloop) = colour_to_pixel(
+ abpixel);
+ }
+ /* handle horizontal interpolation */
+ xoff += dx;
+ rx += dxr;
+ if (rx >= width) {
+ xoff++;
+ rx -= width;
+ }
+ }
+ /* handle vertical interpolation */
+ yoff += bmp_stride * dy;
+ ry += dyr;
+ if (ry >= height) {
+ yoff += bmp_stride;
+ ry -= height;
+ }
+ }
+ } else {
+ for (; pvideo < pvideo_limit; pvideo += (nsfb->linelen >> 2)) {
+ /* looping through render area vertically */
+ xoff = xoffs;
+ rx = 0;
+ for (xloop = 0; xloop < rwidth; xloop++) {
+ /* looping through render area horizontally */
+ /* get value of source pixel in question */
+ abpixel = pixel[yoff + xoff];
+ /* plot pixel */
+ *(pvideo + xloop) = colour_to_pixel(abpixel);
+
+ /* handle horizontal interpolation */
+ xoff += dx;
+ rx += dxr;
+ if (rx >= width) {
+ xoff++;
+ rx -= width;
+ }
+ }
+ /* handle vertical interpolation */
+ yoff += bmp_stride * dy;
+ ry += dyr;
+ if (ry >= height) {
+ yoff += bmp_stride;
+ ry -= height;
+ }
+ }
+ }
+ return true;
+}
+
static bool
bitmap(nsfb_t *nsfb,
const nsfb_bbox_t *loc,
@@ -340,14 +472,10 @@ bitmap(nsfb_t *nsfb,
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;
+ /* Scaled bitmaps are handled by a separate function */
+ if (width != bmp_width || height != bmp_height)
+ return bitmap_scaled(nsfb, loc, pixel, bmp_width, bmp_height,
+ bmp_stride, alpha);
/* The part of the scaled image actually displayed is cropped to the
* current context.
@@ -368,7 +496,7 @@ bitmap(nsfb_t *nsfb,
width = (clipped.x1 - clipped.x0);
xoff = clipped.x0 - x;
- yoff = (clipped.y0 - y) * bmp_width;
+ yoff = (clipped.y0 - y) * bmp_stride;
height = height * bmp_stride + yoff;
/* plot the image */
@@ -379,7 +507,11 @@ bitmap(nsfb_t *nsfb,
for (xloop = 0; xloop < width; xloop++) {
abpixel = pixel[yloop + xloop + xoff];
if ((abpixel & 0xFF000000) != 0) {
+ /* pixel is not transparent; have to
+ * plot something */
if ((abpixel & 0xFF000000) != 0xFF000000) {
+ /* pixel is not opaque; need to
+ * blend */
abpixel = nsfb_plot_ablend(abpixel,
pixel_to_colour(*(pvideo + xloop)));
}