mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-24 04:56:50 +03:00
c105738fa3
This changes the LOG macro to be varadic removing the need for all callsites to have double bracketing and allows for future improvement on how we use the logging macros. The callsites were changed with coccinelle and the changes checked by hand. Compile tested for several frontends but not all. A formatting annotation has also been added which allows the compiler to check the parameters and types passed to the logging.
427 lines
9.5 KiB
C
427 lines
9.5 KiB
C
/*
|
|
* Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
|
|
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* \file
|
|
* win32 implementation of the bitmap operations.
|
|
*/
|
|
|
|
#include "utils/config.h"
|
|
|
|
#include <inttypes.h>
|
|
#include <sys/types.h>
|
|
#include <string.h>
|
|
#include <windows.h>
|
|
|
|
#include "utils/log.h"
|
|
#include "image/bitmap.h"
|
|
#include "content/content.h"
|
|
|
|
#include "windows/plot.h"
|
|
#include "windows/bitmap.h"
|
|
|
|
/**
|
|
* Create a bitmap.
|
|
*
|
|
* \param width width of image in pixels
|
|
* \param height width of image in pixels
|
|
* \param state a flag word indicating the initial state
|
|
* \return an opaque struct bitmap, or NULL on memory exhaustion
|
|
*/
|
|
void *win32_bitmap_create(int width, int height, unsigned int state)
|
|
{
|
|
struct bitmap *bitmap;
|
|
BITMAPV5HEADER *pbmi;
|
|
HBITMAP windib;
|
|
uint8_t *pixdata;
|
|
|
|
LOG("width %d, height %d, state %u", width, height, state);
|
|
|
|
pbmi = calloc(1, sizeof(BITMAPV5HEADER));
|
|
if (pbmi == NULL) {
|
|
return NULL;
|
|
}
|
|
pbmi->bV5Size = sizeof(BITMAPV5HEADER);
|
|
pbmi->bV5Width = width;
|
|
pbmi->bV5Height = -height;
|
|
pbmi->bV5Planes = 1;
|
|
pbmi->bV5BitCount = 32;
|
|
pbmi->bV5Compression = BI_BITFIELDS;
|
|
|
|
pbmi->bV5RedMask = 0xff; /* red mask */
|
|
pbmi->bV5GreenMask = 0xff00; /* green mask */
|
|
pbmi->bV5BlueMask = 0xff0000; /* blue mask */
|
|
pbmi->bV5AlphaMask = 0xff000000; /* alpha mask */
|
|
|
|
windib = CreateDIBSection(NULL, (BITMAPINFO *)pbmi, DIB_RGB_COLORS, (void **)&pixdata, NULL, 0);
|
|
|
|
|
|
if (windib == NULL) {
|
|
free(pbmi);
|
|
return NULL;
|
|
}
|
|
|
|
bitmap = calloc(1 , sizeof(struct bitmap));
|
|
if (bitmap == NULL) {
|
|
DeleteObject(windib);
|
|
free(pbmi);
|
|
return NULL;
|
|
}
|
|
|
|
bitmap->width = width;
|
|
bitmap->height = height;
|
|
bitmap->windib = windib;
|
|
bitmap->pbmi = pbmi;
|
|
bitmap->pixdata = pixdata;
|
|
if ((state & BITMAP_OPAQUE) != 0) {
|
|
bitmap->opaque = true;
|
|
} else {
|
|
bitmap->opaque = false;
|
|
}
|
|
|
|
LOG("bitmap %p", bitmap);
|
|
|
|
return bitmap;
|
|
}
|
|
|
|
|
|
/**
|
|
* Return a pointer to the pixel data in a bitmap.
|
|
*
|
|
* The pixel data is packed as BITMAP_FORMAT, possibly with padding at the end
|
|
* of rows. The width of a row in bytes is given by bitmap_get_rowstride().
|
|
*
|
|
* \param bitmap a bitmap, as returned by bitmap_create()
|
|
* \return pointer to the pixel buffer
|
|
*/
|
|
static unsigned char *bitmap_get_buffer(void *bitmap)
|
|
{
|
|
struct bitmap *bm = bitmap;
|
|
if (bitmap == NULL) {
|
|
LOG("NULL bitmap!");
|
|
return NULL;
|
|
}
|
|
|
|
return bm->pixdata;
|
|
}
|
|
|
|
|
|
/**
|
|
* Find the width of a pixel row in bytes.
|
|
*
|
|
* \param bitmap a bitmap, as returned by bitmap_create()
|
|
* \return width of a pixel row in the bitmap
|
|
*/
|
|
static size_t bitmap_get_rowstride(void *bitmap)
|
|
{
|
|
struct bitmap *bm = bitmap;
|
|
|
|
if (bitmap == NULL) {
|
|
LOG("NULL bitmap!");
|
|
return 0;
|
|
}
|
|
|
|
return (bm->width) * 4;
|
|
}
|
|
|
|
|
|
/**
|
|
* Free a bitmap.
|
|
*
|
|
* \param bitmap a bitmap, as returned by bitmap_create()
|
|
*/
|
|
void win32_bitmap_destroy(void *bitmap)
|
|
{
|
|
struct bitmap *bm = bitmap;
|
|
|
|
if (bitmap == NULL) {
|
|
LOG("NULL bitmap!");
|
|
return;
|
|
}
|
|
|
|
DeleteObject(bm->windib);
|
|
free(bm->pbmi);
|
|
free(bm);
|
|
}
|
|
|
|
|
|
/**
|
|
* Save a bitmap in the platform's native format.
|
|
*
|
|
* \param bitmap a bitmap, as returned by bitmap_create()
|
|
* \param path pathname for file
|
|
* \param flags flags controlling how the bitmap is saved.
|
|
* \return true on success, false on error and error reported
|
|
*/
|
|
static bool bitmap_save(void *bitmap, const char *path, unsigned flags)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* The bitmap image has changed, so flush any persistant cache.
|
|
*
|
|
* \param bitmap a bitmap, as returned by bitmap_create()
|
|
*/
|
|
static void bitmap_modified(void *bitmap) {
|
|
}
|
|
|
|
/**
|
|
* Sets whether a bitmap should be plotted opaque
|
|
*
|
|
* \param bitmap a bitmap, as returned by bitmap_create()
|
|
* \param opaque whether the bitmap should be plotted opaque
|
|
*/
|
|
static void bitmap_set_opaque(void *bitmap, bool opaque)
|
|
{
|
|
struct bitmap *bm = bitmap;
|
|
|
|
if (bitmap == NULL) {
|
|
LOG("NULL bitmap!");
|
|
return;
|
|
}
|
|
|
|
LOG("setting bitmap %p to %s", bm, opaque ? "opaque" : "transparent");
|
|
bm->opaque = opaque;
|
|
}
|
|
|
|
|
|
/**
|
|
* Tests whether a bitmap has an opaque alpha channel
|
|
*
|
|
* \param bitmap a bitmap, as returned by bitmap_create()
|
|
* \return whether the bitmap is opaque
|
|
*/
|
|
static bool bitmap_test_opaque(void *bitmap)
|
|
{
|
|
int tst;
|
|
struct bitmap *bm = bitmap;
|
|
|
|
if (bitmap == NULL) {
|
|
LOG("NULL bitmap!");
|
|
return false;
|
|
}
|
|
|
|
tst = bm->width * bm->height;
|
|
|
|
while (tst-- > 0) {
|
|
if (bm->pixdata[(tst << 2) + 3] != 0xff) {
|
|
LOG("bitmap %p has transparency", bm);
|
|
return false;
|
|
}
|
|
}
|
|
LOG("bitmap %p is opaque", bm);
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Gets whether a bitmap should be plotted opaque
|
|
*
|
|
* \param bitmap a bitmap, as returned by bitmap_create()
|
|
*/
|
|
static bool bitmap_get_opaque(void *bitmap)
|
|
{
|
|
struct bitmap *bm = bitmap;
|
|
|
|
if (bitmap == NULL) {
|
|
LOG("NULL bitmap!");
|
|
return false;
|
|
}
|
|
|
|
return bm->opaque;
|
|
}
|
|
|
|
static int bitmap_get_width(void *bitmap)
|
|
{
|
|
struct bitmap *bm = bitmap;
|
|
|
|
if (bitmap == NULL) {
|
|
LOG("NULL bitmap!");
|
|
return 0;
|
|
}
|
|
|
|
return(bm->width);
|
|
}
|
|
|
|
static int bitmap_get_height(void *bitmap)
|
|
{
|
|
struct bitmap *bm = bitmap;
|
|
|
|
if (bitmap == NULL) {
|
|
LOG("NULL bitmap!");
|
|
return 0;
|
|
}
|
|
|
|
return(bm->height);
|
|
}
|
|
|
|
static size_t bitmap_get_bpp(void *bitmap)
|
|
{
|
|
return 4;
|
|
}
|
|
|
|
struct bitmap *bitmap_scale(struct bitmap *prescale, int width, int height)
|
|
{
|
|
struct bitmap *ret = malloc(sizeof(struct bitmap));
|
|
int i, ii, v, vv;
|
|
uint32_t *retpixdata, *inpixdata; /* 4 byte types for quicker
|
|
* transfer */
|
|
if (ret == NULL)
|
|
return NULL;
|
|
retpixdata = malloc(width * height * 4);
|
|
if (retpixdata == NULL) {
|
|
free(ret);
|
|
return NULL;
|
|
}
|
|
inpixdata = (uint32_t *)prescale->pixdata;
|
|
ret->pixdata = (uint8_t *)retpixdata;
|
|
ret->height = height;
|
|
ret->width = width;
|
|
for (i = 0; i < height; i++) {
|
|
v = i * width;
|
|
vv = (int)((i * prescale->height) / height) * prescale->width;
|
|
for (ii = 0; ii < width; ii++) {
|
|
retpixdata[v + ii] = inpixdata[vv + (int)
|
|
((ii * prescale->width) / width)];
|
|
}
|
|
}
|
|
return ret;
|
|
|
|
}
|
|
|
|
struct bitmap *bitmap_pretile(struct bitmap *untiled, int width, int height,
|
|
bitmap_flags_t flags)
|
|
{
|
|
struct bitmap *ret = malloc(sizeof(struct bitmap));
|
|
if (ret == NULL)
|
|
return NULL;
|
|
int i, hrepeat, vrepeat, repeat;
|
|
vrepeat = ((flags & BITMAPF_REPEAT_Y) != 0) ?
|
|
((height + untiled->height - 1) / untiled->height) : 1;
|
|
hrepeat = ((flags & BITMAPF_REPEAT_X) != 0) ?
|
|
((width + untiled->width - 1) / untiled->width) : 1;
|
|
width = untiled->width * hrepeat;
|
|
height = untiled->height * vrepeat;
|
|
uint8_t *indata = untiled->pixdata;
|
|
uint8_t *newdata = malloc(4 * width * height);
|
|
if (newdata == NULL) {
|
|
free(ret);
|
|
return NULL;
|
|
}
|
|
ret->pixdata = newdata;
|
|
size_t stride = untiled->width * 4;
|
|
|
|
/* horizontal tiling */
|
|
for (i = 0; i < untiled->height; i++) {
|
|
for (repeat = 0; repeat < hrepeat; repeat ++) {
|
|
memcpy(newdata, indata, stride);
|
|
newdata += stride;
|
|
}
|
|
indata += stride;
|
|
}
|
|
|
|
/* vertical tiling */
|
|
stride = untiled->height * width * 4;
|
|
newdata = ret->pixdata + stride;
|
|
indata = ret->pixdata;
|
|
|
|
for (repeat = 1; repeat < vrepeat; repeat++) {
|
|
memcpy(newdata, indata, stride);
|
|
newdata += stride;
|
|
}
|
|
ret->width = width;
|
|
ret->height = height;
|
|
return ret;
|
|
}
|
|
|
|
static nserror bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content)
|
|
{
|
|
int width;
|
|
int height;
|
|
HDC hdc, bufferdc, minidc;
|
|
struct bitmap *fsbitmap;
|
|
struct redraw_context ctx = {
|
|
.interactive = false,
|
|
.background_images = true,
|
|
.plot = &win_plotters
|
|
};
|
|
|
|
width = min(content_get_width(content), 1024);
|
|
height = ((width * bitmap->height) + (bitmap->width / 2)) /
|
|
bitmap->width;
|
|
|
|
LOG("bitmap %p for content %p width %d, height %d", bitmap, content, width, height);
|
|
|
|
/* create two memory device contexts to put the bitmaps in */
|
|
bufferdc = CreateCompatibleDC(NULL);
|
|
if ((bufferdc == NULL)) {
|
|
return NSERROR_NOMEM;
|
|
}
|
|
|
|
minidc = CreateCompatibleDC(NULL);
|
|
if ((minidc == NULL)) {
|
|
DeleteDC(bufferdc);
|
|
return NSERROR_NOMEM;
|
|
}
|
|
|
|
/* create a full size bitmap and plot into it */
|
|
fsbitmap = win32_bitmap_create(width, height, BITMAP_NEW | BITMAP_CLEAR_MEMORY | BITMAP_OPAQUE);
|
|
|
|
SelectObject(bufferdc, fsbitmap->windib);
|
|
|
|
hdc = plot_hdc;
|
|
plot_hdc = bufferdc;
|
|
/* render the content */
|
|
content_scaled_redraw(content, width, height, &ctx);
|
|
plot_hdc = hdc;
|
|
|
|
/* scale bitmap bufferbm into minibm */
|
|
SelectObject(minidc, bitmap->windib);
|
|
|
|
bitmap->opaque = true;
|
|
|
|
StretchBlt(minidc, 0, 0, bitmap->width, bitmap->height, bufferdc, 0, 0, width, height, SRCCOPY);
|
|
|
|
DeleteDC(bufferdc);
|
|
DeleteDC(minidc);
|
|
win32_bitmap_destroy(fsbitmap);
|
|
|
|
return NSERROR_OK;
|
|
}
|
|
|
|
static struct gui_bitmap_table bitmap_table = {
|
|
.create = win32_bitmap_create,
|
|
.destroy = win32_bitmap_destroy,
|
|
.set_opaque = bitmap_set_opaque,
|
|
.get_opaque = bitmap_get_opaque,
|
|
.test_opaque = bitmap_test_opaque,
|
|
.get_buffer = bitmap_get_buffer,
|
|
.get_rowstride = bitmap_get_rowstride,
|
|
.get_width = bitmap_get_width,
|
|
.get_height = bitmap_get_height,
|
|
.get_bpp = bitmap_get_bpp,
|
|
.save = bitmap_save,
|
|
.modified = bitmap_modified,
|
|
.render = bitmap_render,
|
|
};
|
|
|
|
struct gui_bitmap_table *win32_bitmap_table = &bitmap_table;
|