NetSurf
bitmap.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
3  *
4  * This file is part of NetSurf, http://www.netsurf-browser.org/
5  *
6  * NetSurf is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * NetSurf is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /**
20  * \file
21  * Framebuffer implementation of generic bitmap interface.
22  */
23 
24 #include <inttypes.h>
25 #include <sys/types.h>
26 #include <stdbool.h>
27 #include <assert.h>
28 #include <libnsfb.h>
29 #include <libnsfb_plot.h>
30 
31 #include "utils/log.h"
32 #include "utils/utils.h"
33 #include "netsurf/bitmap.h"
34 #include "netsurf/plotters.h"
35 #include "netsurf/content.h"
36 
37 #include "framebuffer/gui.h"
38 #include "framebuffer/fbtk.h"
40 #include "framebuffer/bitmap.h"
41 
42 /**
43  * Create a bitmap.
44  *
45  * \param width width of image in pixels
46  * \param height width of image in pixels
47  * \param state a flag word indicating the initial state
48  * \return an opaque struct bitmap, or NULL on memory exhaustion
49  */
50 static void *bitmap_create(int width, int height, enum gui_bitmap_flags flags)
51 {
52  nsfb_t *bm;
53 
54  bm = nsfb_new(NSFB_SURFACE_RAM);
55  if (bm == NULL) {
56  return NULL;
57  }
58 
59  if ((flags & BITMAP_OPAQUE) == 0) {
60  nsfb_set_geometry(bm, width, height, NSFB_FMT_ABGR8888);
61  } else {
62  nsfb_set_geometry(bm, width, height, NSFB_FMT_XBGR8888);
63  }
64 
65  if (nsfb_init(bm) == -1) {
66  nsfb_free(bm);
67  return NULL;
68  }
69 
70  return bm;
71 }
72 
73 
74 /**
75  * Return a pointer to the pixel data in a bitmap.
76  *
77  * \param bitmap a bitmap, as returned by bitmap_create()
78  * \return pointer to the pixel buffer
79  *
80  * The pixel data is packed as BITMAP_FORMAT, possibly with padding at the end
81  * of rows. The width of a row in bytes is given by bitmap_get_rowstride().
82  */
83 static unsigned char *bitmap_get_buffer(void *bitmap)
84 {
85  nsfb_t *bm = bitmap;
86  unsigned char *bmpptr;
87 
88  assert(bm != NULL);
89 
90  nsfb_get_buffer(bm, &bmpptr, NULL);
91 
92  return bmpptr;
93 }
94 
95 
96 /**
97  * Find the width of a pixel row in bytes.
98  *
99  * \param bitmap a bitmap, as returned by bitmap_create()
100  * \return width of a pixel row in the bitmap
101  */
102 static size_t bitmap_get_rowstride(void *bitmap)
103 {
104  nsfb_t *bm = bitmap;
105  int bmpstride;
106 
107  assert(bm != NULL);
108 
109  nsfb_get_buffer(bm, NULL, &bmpstride);
110 
111  return bmpstride;
112 }
113 
114 
115 /**
116  * Free a bitmap.
117  *
118  * \param bitmap a bitmap, as returned by bitmap_create()
119  */
120 static void bitmap_destroy(void *bitmap)
121 {
122  nsfb_t *bm = bitmap;
123 
124  assert(bm != NULL);
125 
126  nsfb_free(bm);
127 }
128 
129 
130 /**
131  * The bitmap image has changed, so flush any persistant cache.
132  *
133  * \param bitmap a bitmap, as returned by bitmap_create()
134  */
135 static void bitmap_modified(void *bitmap) {
136 }
137 
138 /**
139  * Sets wether a bitmap should be plotted opaque
140  *
141  * \param bitmap a bitmap, as returned by bitmap_create()
142  * \param opaque whether the bitmap should be plotted opaque
143  */
144 static void bitmap_set_opaque(void *bitmap, bool opaque)
145 {
146  nsfb_t *bm = bitmap;
147 
148  assert(bm != NULL);
149 
150  if (opaque) {
151  nsfb_set_geometry(bm, 0, 0, NSFB_FMT_XBGR8888);
152  } else {
153  nsfb_set_geometry(bm, 0, 0, NSFB_FMT_ABGR8888);
154  }
155 }
156 
157 
158 /**
159  * Tests whether a bitmap has an opaque alpha channel
160  *
161  * \param bitmap a bitmap, as returned by bitmap_create()
162  * \return whether the bitmap is opaque
163  */
164 static bool bitmap_test_opaque(void *bitmap)
165 {
166  int tst;
167  nsfb_t *bm = bitmap;
168  unsigned char *bmpptr;
169  int width;
170  int height;
171 
172  assert(bm != NULL);
173 
174  nsfb_get_buffer(bm, &bmpptr, NULL);
175 
176  nsfb_get_geometry(bm, &width, &height, NULL);
177 
178  tst = width * height;
179 
180  while (tst-- > 0) {
181  if (bmpptr[(tst << 2) + 3] != 0xff) {
182  NSLOG(netsurf, INFO, "bitmap %p has transparency", bm);
183  return false;
184  }
185  }
186  NSLOG(netsurf, INFO, "bitmap %p is opaque", bm);
187  return true;
188 }
189 
190 
191 /**
192  * Gets weather a bitmap should be plotted opaque
193  *
194  * \param bitmap a bitmap, as returned by bitmap_create()
195  */
197 {
198  nsfb_t *bm = bitmap;
199  enum nsfb_format_e format;
200 
201  assert(bm != NULL);
202 
203  nsfb_get_geometry(bm, NULL, NULL, &format);
204 
205  if (format == NSFB_FMT_ABGR8888)
206  return false;
207 
208  return true;
209 }
210 
211 static int bitmap_get_width(void *bitmap)
212 {
213  nsfb_t *bm = bitmap;
214  int width;
215 
216  assert(bm != NULL);
217 
218  nsfb_get_geometry(bm, &width, NULL, NULL);
219 
220  return(width);
221 }
222 
223 static int bitmap_get_height(void *bitmap)
224 {
225  nsfb_t *bm = bitmap;
226  int height;
227 
228  assert(bm != NULL);
229 
230  nsfb_get_geometry(bm, NULL, &height, NULL);
231 
232  return(height);
233 }
234 
235 /**
236  * Render content into a bitmap.
237  *
238  * \param bitmap the bitmap to draw to
239  * \param content content structure to render
240  * \return true on success and bitmap updated else false
241  */
242 static nserror
244  struct hlcache_handle *content)
245 {
246  nsfb_t *tbm = (nsfb_t *)bitmap; /* target bitmap */
247  nsfb_t *bm; /* temporary bitmap */
248  nsfb_t *current; /* current main fb */
249  int width, height; /* target bitmap width height */
250  int cwidth, cheight;/* content width /height */
251  nsfb_bbox_t loc;
252 
253  struct redraw_context ctx = {
254  .interactive = false,
255  .background_images = true,
256  .plot = &fb_plotters
257  };
258 
259  nsfb_get_geometry(tbm, &width, &height, NULL);
260 
261  NSLOG(netsurf, INFO, "width %d, height %d", width, height);
262 
263  /* Calculate size of buffer to render the content into */
264  /* We get the width from the largest of the bitmap width and the content
265  * width, unless it exceeds 1024, in which case we use 1024. This means
266  * we never create excessively large render buffers for huge contents,
267  * which would eat memory and cripple performance. */
268  cwidth = max(width, min(content_get_width(content), 1024));
269  /* The height is set in proportion with the width, according to the
270  * aspect ratio of the required thumbnail. */
271  cheight = ((cwidth * height) + (width / 2)) / width;
272 
273  /* create temporary surface */
274  bm = nsfb_new(NSFB_SURFACE_RAM);
275  if (bm == NULL) {
276  return NSERROR_NOMEM;
277  }
278 
279  nsfb_set_geometry(bm, cwidth, cheight, NSFB_FMT_XBGR8888);
280 
281  if (nsfb_init(bm) == -1) {
282  nsfb_free(bm);
283  return NSERROR_NOMEM;
284  }
285 
286  current = framebuffer_set_surface(bm);
287 
288  /* render the content into temporary surface */
289  content_scaled_redraw(content, cwidth, cheight, &ctx);
290 
291  framebuffer_set_surface(current);
292 
293  loc.x0 = 0;
294  loc.y0 = 0;
295  loc.x1 = width;
296  loc.y1 = height;
297 
298  nsfb_plot_copy(bm, NULL, tbm, &loc);
299 
300  nsfb_free(bm);
301 
302  return NSERROR_OK;
303 }
304 
307  .destroy = bitmap_destroy,
308  .set_opaque = bitmap_set_opaque,
309  .get_opaque = framebuffer_bitmap_get_opaque,
310  .test_opaque = bitmap_test_opaque,
311  .get_buffer = bitmap_get_buffer,
312  .get_rowstride = bitmap_get_rowstride,
313  .get_width = bitmap_get_width,
314  .get_height = bitmap_get_height,
315  .modified = bitmap_modified,
316  .render = bitmap_render,
317 };
318 
320 
321 
322 /*
323  * Local Variables:
324  * c-basic-offset:8
325  * End:
326  */
framebuffer interface.
struct gui_bitmap_table * framebuffer_bitmap_table
Definition: bitmap.c:319
Target independent plotting interface.
static size_t bitmap_get_rowstride(void *bitmap)
Find the width of a pixel row in bytes.
Definition: bitmap.c:102
int bitmap_get_height(void *bitmap)
get height of a bitmap.
Definition: bitmap.c:355
static struct gui_bitmap_table bitmap_table
Definition: bitmap.c:305
Public content interface.
Memory exhaustion.
Definition: errors.h:32
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
bool framebuffer_bitmap_get_opaque(void *bitmap)
Gets weather a bitmap should be plotted opaque.
Definition: bitmap.c:196
bool interactive
Redraw to show interactive features.
Definition: plotters.h:59
const struct plotter_table fb_plotters
framebuffer plot operation table
Definition: framebuffer.c:525
nserror
Enumeration of error codes.
Definition: errors.h:29
image is opaque
Definition: bitmap.h:60
High-level cache handle.
Definition: hlcache.c:65
static void bitmap_modified(void *bitmap)
The bitmap image has changed, so flush any persistant cache.
Definition: bitmap.c:135
Content which corresponds to a single URL.
No error.
Definition: errors.h:30
static nserror bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content)
Render content into a bitmap.
Definition: bitmap.c:243
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:115
RISC OS wimp toolkit bitmap.
Definition: bitmap.c:68
gui_bitmap_flags
Bitmap creation flags.
Definition: bitmap.h:58
Bitmap operations.
Definition: bitmap.h:71
Redraw context.
Definition: plotters.h:51
nsfb_t * framebuffer_set_surface(nsfb_t *new_nsfb)
Set framebuffer surface to render into.
Definition: framebuffer.c:649
Netsurf additional integer type formatting macros.
int height
Definition: gui.c:181
static unsigned char * bitmap_get_buffer(void *bitmap)
Return a pointer to the pixel data in a bitmap.
Definition: bitmap.c:83
static void bitmap_set_opaque(void *bitmap, bool opaque)
Sets wether a bitmap should be plotted opaque.
Definition: bitmap.c:144
static bool bitmap_test_opaque(void *bitmap)
Tests whether a bitmap has an opaque alpha channel.
Definition: bitmap.c:164
int content_get_width(struct hlcache_handle *h)
Retrieve width of content.
Definition: content.c:1158
Interface to a number of general purpose functionality.
static void bitmap_destroy(void *bitmap)
Free a bitmap.
Definition: bitmap.c:120
Generic bitmap handling interface.
int bitmap_get_width(void *bitmap)
get width of a bitmap.
Definition: bitmap.c:338
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 void * bitmap_create(int width, int height, enum gui_bitmap_flags flags)
Create a bitmap.
Definition: bitmap.c:50