NetSurf
bitmap.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
3  * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
4  *
5  * This file is part of NetSurf, http://www.netsurf-browser.org/
6  *
7  * NetSurf is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; version 2 of the License.
10  *
11  * NetSurf is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 /**
21  * \file
22  * win32 implementation of the bitmap operations.
23  */
24 
25 #include "utils/config.h"
26 
27 #include <inttypes.h>
28 #include <sys/types.h>
29 #include <string.h>
30 #include <windows.h>
31 
32 #include "utils/log.h"
33 #include "netsurf/bitmap.h"
34 #include "netsurf/plotters.h"
35 #include "netsurf/content.h"
36 
37 #include "windows/plot.h"
38 #include "windows/bitmap.h"
39 
40 /**
41  * Create a bitmap.
42  *
43  * \param width width of image in pixels
44  * \param height height of image in pixels
45  * \param state flags flags for bitmap creation
46  * \return an opaque struct bitmap, or NULL on memory exhaustion
47  */
48 static void *win32_bitmap_create(int width, int height, enum gui_bitmap_flags flags)
49 {
50  struct bitmap *bitmap;
51  BITMAPV5HEADER *pbmi;
52  HBITMAP windib;
53  uint8_t *pixdata;
54 
55  NSLOG(netsurf, INFO, "width %d, height %d, flags %u", width, height,
56  (unsigned)flags);
57 
58  pbmi = calloc(1, sizeof(BITMAPV5HEADER));
59  if (pbmi == NULL) {
60  return NULL;
61  }
62 
63  pbmi->bV5Size = sizeof(BITMAPV5HEADER);
64  pbmi->bV5Width = width;
65  pbmi->bV5Height = -height;
66  pbmi->bV5Planes = 1;
67  pbmi->bV5BitCount = 32;
68  pbmi->bV5Compression = BI_BITFIELDS;
69 
70  pbmi->bV5RedMask = 0xff; /* red mask */
71  pbmi->bV5GreenMask = 0xff00; /* green mask */
72  pbmi->bV5BlueMask = 0xff0000; /* blue mask */
73  pbmi->bV5AlphaMask = 0xff000000; /* alpha mask */
74 
75  windib = CreateDIBSection(NULL, (BITMAPINFO *)pbmi, DIB_RGB_COLORS, (void **)&pixdata, NULL, 0);
76 
77  if (windib == NULL) {
78  free(pbmi);
79  return NULL;
80  }
81 
82  bitmap = calloc(1 , sizeof(struct bitmap));
83  if (bitmap == NULL) {
84  DeleteObject(windib);
85  free(pbmi);
86  return NULL;
87  }
88 
89  bitmap->width = width;
90  bitmap->height = height;
91  bitmap->windib = windib;
92  bitmap->pbmi = pbmi;
93  bitmap->pixdata = pixdata;
94  if ((flags & BITMAP_OPAQUE) != 0) {
95  bitmap->opaque = true;
96  } else {
97  bitmap->opaque = false;
98  }
99 
100  NSLOG(netsurf, INFO, "bitmap %p", bitmap);
101 
102  return bitmap;
103 }
104 
105 
106 /**
107  * Return a pointer to the pixel data in a bitmap.
108  *
109  * The pixel data is packed as BITMAP_FORMAT, possibly with padding at the end
110  * of rows. The width of a row in bytes is given by bitmap_get_rowstride().
111  *
112  * \param bitmap a bitmap, as returned by bitmap_create()
113  * \return pointer to the pixel buffer
114  */
115 static unsigned char *bitmap_get_buffer(void *bitmap)
116 {
117  struct bitmap *bm = bitmap;
118  if (bitmap == NULL) {
119  NSLOG(netsurf, INFO, "NULL bitmap!");
120  return NULL;
121  }
122 
123  return bm->pixdata;
124 }
125 
126 
127 /**
128  * Find the width of a pixel row in bytes.
129  *
130  * \param bitmap a bitmap, as returned by bitmap_create()
131  * \return width of a pixel row in the bitmap
132  */
133 static size_t bitmap_get_rowstride(void *bitmap)
134 {
135  struct bitmap *bm = bitmap;
136 
137  if (bitmap == NULL) {
138  NSLOG(netsurf, INFO, "NULL bitmap!");
139  return 0;
140  }
141 
142  return (bm->width) * 4;
143 }
144 
145 
146 /**
147  * Free a bitmap.
148  *
149  * \param bitmap a bitmap, as returned by bitmap_create()
150  */
152 {
153  struct bitmap *bm = bitmap;
154 
155  if (bitmap == NULL) {
156  NSLOG(netsurf, INFO, "NULL bitmap!");
157  return;
158  }
159 
160  DeleteObject(bm->windib);
161  free(bm->pbmi);
162  free(bm);
163 }
164 
165 
166 /**
167  * The bitmap image has changed, so flush any persistant cache.
168  *
169  * \param bitmap a bitmap, as returned by bitmap_create()
170  */
171 static void bitmap_modified(void *bitmap) {
172 }
173 
174 /**
175  * Sets whether a bitmap should be plotted opaque
176  *
177  * \param bitmap a bitmap, as returned by bitmap_create()
178  * \param opaque whether the bitmap should be plotted opaque
179  */
180 static void bitmap_set_opaque(void *bitmap, bool opaque)
181 {
182  struct bitmap *bm = bitmap;
183 
184  if (bitmap == NULL) {
185  NSLOG(netsurf, INFO, "NULL bitmap!");
186  return;
187  }
188 
189  NSLOG(netsurf, INFO, "setting bitmap %p to %s", bm,
190  opaque ? "opaque" : "transparent");
191  bm->opaque = opaque;
192 }
193 
194 
195 /**
196  * Tests whether a bitmap has an opaque alpha channel
197  *
198  * \param bitmap a bitmap, as returned by bitmap_create()
199  * \return whether the bitmap is opaque
200  */
201 static bool bitmap_test_opaque(void *bitmap)
202 {
203  int tst;
204  struct bitmap *bm = bitmap;
205 
206  if (bitmap == NULL) {
207  NSLOG(netsurf, INFO, "NULL bitmap!");
208  return false;
209  }
210 
211  tst = bm->width * bm->height;
212 
213  while (tst-- > 0) {
214  if (bm->pixdata[(tst << 2) + 3] != 0xff) {
215  NSLOG(netsurf, INFO, "bitmap %p has transparency", bm);
216  return false;
217  }
218  }
219  NSLOG(netsurf, INFO, "bitmap %p is opaque", bm);
220  return true;
221 }
222 
223 
224 /**
225  * Gets whether a bitmap should be plotted opaque
226  *
227  * \param bitmap a bitmap, as returned by bitmap_create()
228  */
229 static bool bitmap_get_opaque(void *bitmap)
230 {
231  struct bitmap *bm = bitmap;
232 
233  if (bitmap == NULL) {
234  NSLOG(netsurf, INFO, "NULL bitmap!");
235  return false;
236  }
237 
238  return bm->opaque;
239 }
240 
241 static int bitmap_get_width(void *bitmap)
242 {
243  struct bitmap *bm = bitmap;
244 
245  if (bitmap == NULL) {
246  NSLOG(netsurf, INFO, "NULL bitmap!");
247  return 0;
248  }
249 
250  return(bm->width);
251 }
252 
253 static int bitmap_get_height(void *bitmap)
254 {
255  struct bitmap *bm = bitmap;
256 
257  if (bitmap == NULL) {
258  NSLOG(netsurf, INFO, "NULL bitmap!");
259  return 0;
260  }
261 
262  return(bm->height);
263 }
264 
265 struct bitmap *bitmap_scale(struct bitmap *prescale, int width, int height)
266 {
267  struct bitmap *ret = malloc(sizeof(struct bitmap));
268  int i, ii, v, vv;
269  uint32_t *retpixdata, *inpixdata; /* 4 byte types for quicker
270  * transfer */
271  if (ret == NULL)
272  return NULL;
273 
274  retpixdata = malloc(width * height * 4);
275  if (retpixdata == NULL) {
276  free(ret);
277  return NULL;
278  }
279 
280  inpixdata = (uint32_t *)prescale->pixdata;
281  ret->pixdata = (uint8_t *)retpixdata;
282  ret->height = height;
283  ret->width = width;
284  for (i = 0; i < height; i++) {
285  v = i * width;
286  vv = (int)((i * prescale->height) / height) * prescale->width;
287  for (ii = 0; ii < width; ii++) {
288  retpixdata[v + ii] = inpixdata[vv + (int)
289  ((ii * prescale->width) / width)];
290  }
291  }
292  return ret;
293 
294 }
295 
296 
297 static nserror
299 {
300  int width;
301  int height;
302  HDC hdc, bufferdc, minidc;
303  struct bitmap *fsbitmap;
304  struct redraw_context ctx = {
305  .interactive = false,
306  .background_images = true,
307  .plot = &win_plotters
308  };
309 
310  width = min(max(content_get_width(content), bitmap->width), 1024);
311  height = ((width * bitmap->height) + (bitmap->width / 2)) /
312  bitmap->width;
313 
314  NSLOG(netsurf, INFO, "bitmap %p for content %p width %d, height %d",
315  bitmap, content, width, height);
316 
317  /* create two memory device contexts to put the bitmaps in */
318  bufferdc = CreateCompatibleDC(NULL);
319  if ((bufferdc == NULL)) {
320  return NSERROR_NOMEM;
321  }
322 
323  minidc = CreateCompatibleDC(NULL);
324  if ((minidc == NULL)) {
325  DeleteDC(bufferdc);
326  return NSERROR_NOMEM;
327  }
328 
329  /* create a full size bitmap and plot into it */
330  fsbitmap = win32_bitmap_create(width, height, BITMAP_CLEAR | BITMAP_OPAQUE);
331 
332  SelectObject(bufferdc, fsbitmap->windib);
333 
334  hdc = plot_hdc;
335  plot_hdc = bufferdc;
336  /* render the content */
337  content_scaled_redraw(content, width, height, &ctx);
338  plot_hdc = hdc;
339 
340  /* scale bitmap bufferbm into minibm */
341  SelectObject(minidc, bitmap->windib);
342 
343  bitmap->opaque = true;
344 
345  StretchBlt(minidc, 0, 0, bitmap->width, bitmap->height, bufferdc, 0, 0, width, height, SRCCOPY);
346 
347  DeleteDC(bufferdc);
348  DeleteDC(minidc);
349  win32_bitmap_destroy(fsbitmap);
350 
351  return NSERROR_OK;
352 }
353 
356  .destroy = win32_bitmap_destroy,
357  .set_opaque = bitmap_set_opaque,
358  .get_opaque = bitmap_get_opaque,
359  .test_opaque = bitmap_test_opaque,
360  .get_buffer = bitmap_get_buffer,
361  .get_rowstride = bitmap_get_rowstride,
362  .get_width = bitmap_get_width,
363  .get_height = bitmap_get_height,
364  .modified = bitmap_modified,
365  .render = bitmap_render,
366 };
367 
Target independent plotting interface.
static bool bitmap_get_opaque(void *bitmap)
Gets whether a bitmap should be plotted opaque.
Definition: bitmap.c:229
int bitmap_get_height(void *bitmap)
get height of a bitmap.
Definition: bitmap.c:355
Interface to utility string handling.
Public content interface.
Memory exhaustion.
Definition: errors.h:32
struct bitmap * bitmap_scale(struct bitmap *prescale, int width, int height)
Definition: bitmap.c:265
const struct plotter_table win_plotters
win32 API plot operation table
Definition: plot.c:1040
static nserror bitmap(const struct redraw_context *ctx, struct bitmap *bitmap, int x, int y, int width, int height, colour bg, bitmap_flags_t flags)
Plot a bitmap.
Definition: plot.c:857
#define min(x, y)
Definition: utils.h:46
static nserror bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content)
Definition: bitmap.c:298
bool interactive
Redraw to show interactive features.
Definition: plotters.h:59
void win32_bitmap_destroy(void *bitmap)
Free a bitmap.
Definition: bitmap.c:151
nserror
Enumeration of error codes.
Definition: errors.h:29
int height
height of bitmap
Definition: bitmap.c:70
image is opaque
Definition: bitmap.h:60
static void bitmap_modified(void *bitmap)
The bitmap image has changed, so flush any persistant cache.
Definition: bitmap.c:171
High-level cache handle.
Definition: hlcache.c:65
BITMAPV5HEADER * pbmi
Definition: bitmap.h:27
static void bitmap_set_opaque(void *bitmap, bool opaque)
Sets whether a bitmap should be plotted opaque.
Definition: bitmap.c:180
Content which corresponds to a single URL.
static unsigned char * bitmap_get_buffer(void *bitmap)
Return a pointer to the pixel data in a bitmap.
Definition: bitmap.c:115
static size_t bitmap_get_rowstride(void *bitmap)
Find the width of a pixel row in bytes.
Definition: bitmap.c:133
No error.
Definition: errors.h:30
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:115
RISC OS wimp toolkit bitmap.
Definition: bitmap.c:68
static bool bitmap_test_opaque(void *bitmap)
Tests whether a bitmap has an opaque alpha channel.
Definition: bitmap.c:201
gui_bitmap_flags
Bitmap creation flags.
Definition: bitmap.h:58
Bitmap operations.
Definition: bitmap.h:71
memory should be wiped to 0
Definition: bitmap.h:61
Redraw context.
Definition: plotters.h:51
bool opaque
Whether the bitmap is opaque.
Definition: bitmap.c:74
Netsurf additional integer type formatting macros.
HDC plot_hdc
Definition: plot.c:44
int height
Definition: gui.c:181
UBYTE * pixdata
Definition: bitmap.c:71
HBITMAP windib
Definition: bitmap.h:26
int width
width of bitmap
Definition: bitmap.c:69
int content_get_width(struct hlcache_handle *h)
Retrieve width of content.
Definition: content.c:1158
Generic bitmap handling interface.
int bitmap_get_width(void *bitmap)
get width of a bitmap.
Definition: bitmap.c:338
struct gui_bitmap_table * win32_bitmap_table
Definition: bitmap.c:368
bool content_scaled_redraw(struct hlcache_handle *h, int width, int height, const struct redraw_context *ctx)
Redraw a content with scale set for horizontal fit.
Definition: content.c:583
#define max(x, y)
Definition: utils.h:50
int width
Definition: gui.c:180
void *(* create)(int width, int height, enum gui_bitmap_flags flags)
Create a new bitmap.
Definition: bitmap.h:82
static struct gui_bitmap_table bitmap_table
Definition: bitmap.c:354
static void * win32_bitmap_create(int width, int height, enum gui_bitmap_flags flags)
Create a bitmap.
Definition: bitmap.c:48