NetSurf
ico.c
Go to the documentation of this file.
1/*
2 * Copyright 2006 Richard Wilson <info@tinct.net>
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 * implementation for image/ico content handler
22 */
23
24#include <stdbool.h>
25#include <stdlib.h>
26#include <libnsbmp.h>
27
28#include "utils/utils.h"
29#include "utils/log.h"
30#include "utils/messages.h"
31#include "netsurf/bitmap.h"
32#include "netsurf/content.h"
33#include "content/llcache.h"
37#include "desktop/bitmap.h"
38
39#include "image/image.h"
40#include "image/ico.h"
41
42typedef struct nsico_content {
43 struct content base;
44
45 struct ico_collection *ico; /** ICO collection data */
47
48/**
49 * Callback for libnsbmp; forwards the call to bitmap_create()
50 *
51 * \param width width of image in pixels
52 * \param height width of image in pixels
53 * \param bmp_state A flag word indicating the initial state
54 * \return an opaque struct bitmap, or NULL on memory exhaustion
55 */
56static void *nsico_bitmap_create(int width, int height, unsigned int bmp_state)
57{
58 unsigned int bitmap_state = BITMAP_NONE;
59
60 /* set bitmap state based on bmp state */
61 bitmap_state |= (bmp_state & BMP_OPAQUE) ? BITMAP_OPAQUE : 0;
62 bitmap_state |= (bmp_state & BMP_CLEAR_MEMORY) ?
63 BITMAP_CLEAR : 0;
64
65 /* return the created bitmap */
66 return guit->bitmap->create(width, height, bitmap_state);
67}
68
70{
71 bmp_bitmap_callback_vt bmp_bitmap_callbacks = {
72 .bitmap_create = nsico_bitmap_create,
73 .bitmap_destroy = guit->bitmap->destroy,
74 .bitmap_get_buffer = guit->bitmap->get_buffer,
75 };
76
77 c->ico = calloc(sizeof(ico_collection), 1);
78 if (c->ico == NULL) {
80 return NSERROR_NOMEM;
81 }
82 ico_collection_create(c->ico, &bmp_bitmap_callbacks);
83 return NSERROR_OK;
84}
85
86
87static nserror nsico_create(const content_handler *handler,
88 lwc_string *imime_type, const struct http_parameter *params,
89 llcache_handle *llcache, const char *fallback_charset,
90 bool quirks, struct content **c)
91{
93 nserror error;
94
95 result = calloc(1, sizeof(nsico_content));
96 if (result == NULL)
97 return NSERROR_NOMEM;
98
99 error = content__init(&result->base, handler, imime_type, params,
100 llcache, fallback_charset, quirks);
101 if (error != NSERROR_OK) {
102 free(result);
103 return error;
104 }
105
107 if (error != NSERROR_OK) {
108 free(result);
109 return error;
110 }
111
112 *c = (struct content *) result;
113
114 return NSERROR_OK;
115}
116
117
118
119static bool nsico_convert(struct content *c)
120{
121 nsico_content *ico = (nsico_content *) c;
122 struct bmp_image *bmp;
123 bmp_result res;
124 const uint8_t *data;
125 size_t size;
126 char *title;
127
128 /* set the ico data */
129 data = content__get_source_data(c, &size);
130
131 /* analyse the ico */
132 res = ico_analyse(ico->ico, size, (unsigned char *) data);
133
134 switch (res) {
135 case BMP_OK:
136 break;
137 case BMP_INSUFFICIENT_MEMORY:
139 return false;
140 case BMP_INSUFFICIENT_DATA:
141 case BMP_DATA_ERROR:
143 return false;
144 }
145
146 /* Store our content width, height and calculate size */
147 c->width = ico->ico->width;
148 c->height = ico->ico->height;
149 c->size += (ico->ico->width * ico->ico->height * 4) + 16 + 44;
150
151 /* set title text */
152 title = messages_get_buff("ICOTitle",
154 c->width, c->height);
155 if (title != NULL) {
156 content__set_title(c, title);
157 free(title);
158 }
159
160 /* select largest icon to ensure one can be selected */
161 bmp = ico_find(ico->ico, 255, 255);
162 if (bmp == NULL) {
163 /* return error */
164 NSLOG(netsurf, INFO, "Failed to select icon");
165 return false;
166 }
167
170
171 /* Done: update status bar */
172 content_set_status(c, "");
173 return true;
174}
175
176static bool nsico__decode(struct bmp_image *ico)
177{
178 if (ico->decoded == false) {
179 NSLOG(netsurf, DEBUG, "Decoding ICO %p", ico);
180 if (bmp_decode(ico) != BMP_OK) {
181 return false;
182 }
183
184 bitmap_format_to_client(ico->bitmap, &(bitmap_fmt_t) {
185 .layout = BITMAP_LAYOUT_R8G8B8A8,
186 });
187 guit->bitmap->modified(ico->bitmap);
188
189 }
190
191 return true;
192}
193
194static bool nsico_redraw(struct content *c, struct content_redraw_data *data,
195 const struct rect *clip, const struct redraw_context *ctx)
196{
197 nsico_content *ico = (nsico_content *)c;
198 struct bmp_image *bmp;
199
200 /* select most appropriate sized icon for size */
201 bmp = ico_find(ico->ico, data->width, data->height);
202 if (bmp == NULL) {
203 /* return error */
204 NSLOG(netsurf, INFO, "Failed to select icon");
205 return false;
206 }
207
208 /* ensure its decided */
209 if (!nsico__decode(bmp)) {
210 return false;
211 }
212
213 return image_bitmap_plot(bmp->bitmap, data, clip, ctx);
214}
215
216
217static void nsico_destroy(struct content *c)
218{
219 nsico_content *ico = (nsico_content *) c;
220
221 ico_finalise(ico->ico);
222 free(ico->ico);
223}
224
225static nserror nsico_clone(const struct content *old, struct content **newc)
226{
227 nsico_content *ico;
228 nserror error;
229
230 ico = calloc(1, sizeof(nsico_content));
231 if (ico == NULL)
232 return NSERROR_NOMEM;
233
234 error = content__clone(old, &ico->base);
235 if (error != NSERROR_OK) {
236 content_destroy(&ico->base);
237 return error;
238 }
239
240 /* Simply replay creation and conversion */
241 error = nsico_create_ico_data(ico);
242 if (error != NSERROR_OK) {
243 content_destroy(&ico->base);
244 return error;
245 }
246
247 if (old->status == CONTENT_STATUS_READY ||
248 old->status == CONTENT_STATUS_DONE) {
249 if (nsico_convert(&ico->base) == false) {
250 content_destroy(&ico->base);
252 }
253 }
254
255 *newc = (struct content *) ico;
256
257 return NSERROR_OK;
258}
259
260static void *nsico_get_internal(const struct content *c, void *context)
261{
262 nsico_content *ico = (nsico_content *) c;
263 /* TODO: Pick best size for purpose.
264 * Currently assumes it's for a URL bar. */
265 struct bmp_image *bmp;
266
267 bmp = ico_find(ico->ico, 16, 16);
268 if (bmp == NULL) {
269 /* return error */
270 NSLOG(netsurf, INFO, "Failed to select icon");
271 return NULL;
272 }
273
274 if (!nsico__decode(bmp)) {
275 return NULL;
276 }
277
278 return bmp->bitmap;
279}
280
282{
283 return CONTENT_IMAGE;
284}
285
286static bool nsico_is_opaque(struct content *c)
287{
288 nsico_content *ico = (nsico_content *) c;
289 struct bmp_image *bmp;
290
291 /**
292 * \todo Pick best size for purpose. Currently assumes
293 * it's for a URL bar.
294 */
295 bmp = ico_find(ico->ico, 16, 16);
296 if (bmp == NULL) {
297 /* return error */
298 NSLOG(netsurf, INFO, "Failed to select icon");
299 return false;
300 }
301
302 if (!nsico__decode(bmp)) {
303 return false;
304 }
305
306 return guit->bitmap->get_opaque(bmp->bitmap);
307}
308
311 .data_complete = nsico_convert,
312 .destroy = nsico_destroy,
313 .redraw = nsico_redraw,
314 .clone = nsico_clone,
315 .get_internal = nsico_get_internal,
316 .type = nsico_content_type,
317 .is_opaque = nsico_is_opaque,
318 .no_share = false,
319};
320
321static const char *nsico_types[] = {
322 "application/ico",
323 "application/x-ico",
324 "image/ico",
325 "image/vnd.microsoft.icon",
326 "image/x-icon"
327};
328
STATIC char result[100]
Definition: arexx.c:77
bool image_bitmap_plot(struct bitmap *bitmap, struct content_redraw_data *data, const struct rect *clip, const struct redraw_context *ctx)
Common image content handler bitmap plot call.
Definition: image.c:116
Initialisation/finalisation of image handlers.
void content_destroy(struct content *c)
Destroy and free a content.
Definition: content.c:354
void content_set_done(struct content *c)
Put a content in status CONTENT_STATUS_DONE.
Definition: content.c:299
bool content__set_title(struct content *c, const char *title)
Set title associated with content.
Definition: content.c:1090
nserror content__init(struct content *c, const content_handler *handler, lwc_string *imime_type, const struct http_parameter *params, llcache_handle *llcache, const char *fallback_charset, bool quirks)
Definition: content.c:190
const uint8_t * content__get_source_data(struct content *c, size_t *size)
Retrieve source of content.
Definition: content.c:1216
nserror content__clone(const struct content *c, struct content *nc)
Clone a content's data members.
Definition: content.c:1382
void content_set_ready(struct content *c)
Put a content in status CONTENT_STATUS_READY and unlock the content.
Definition: content.c:285
void content_set_status(struct content *c, const char *status_message)
Updates content with new status.
Definition: content.c:270
void content_broadcast_error(struct content *c, nserror errorcode, const char *msg)
Send an error message to all users.
Definition: content.c:769
Protected interface to Content handling.
@ CONTENT_STATUS_READY
Some parts of content still being loaded, but can be displayed.
Definition: content_type.h:92
@ CONTENT_STATUS_DONE
Content has completed all processing.
Definition: content_type.h:95
content_type
The type of a content.
Definition: content_type.h:53
@ CONTENT_IMAGE
All images.
Definition: content_type.h:67
Internal core bitmap interface.
static void bitmap_format_to_client(void *bitmap, const bitmap_fmt_t *current_fmt)
Convert a bitmap to the client bitmap format.
Definition: bitmap.h:117
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_ICO_ERROR
A ICO error occurred.
Definition: errors.h:41
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_CLONE_FAILED
Failed to clone handle.
Definition: errors.h:37
@ NSERROR_OK
No error.
Definition: errors.h:30
struct netsurf_table * guit
The global interface table.
Definition: gui_factory.c:49
Interface to core interface table.
struct nsico_content nsico_content
static nserror nsico_create(const content_handler *handler, lwc_string *imime_type, const struct http_parameter *params, llcache_handle *llcache, const char *fallback_charset, bool quirks, struct content **c)
Definition: ico.c:87
static bool nsico_redraw(struct content *c, struct content_redraw_data *data, const struct rect *clip, const struct redraw_context *ctx)
Definition: ico.c:194
CONTENT_FACTORY_REGISTER_TYPES(nsico, nsico_types, nsico_content_handler)
static content_type nsico_content_type(void)
Definition: ico.c:281
static bool nsico__decode(struct bmp_image *ico)
Definition: ico.c:176
static bool nsico_is_opaque(struct content *c)
Definition: ico.c:286
static const char * nsico_types[]
Definition: ico.c:321
static void nsico_destroy(struct content *c)
Definition: ico.c:217
static const content_handler nsico_content_handler
Definition: ico.c:309
static nserror nsico_create_ico_data(nsico_content *c)
Definition: ico.c:69
static nserror nsico_clone(const struct content *old, struct content **newc)
Definition: ico.c:225
static void * nsico_get_internal(const struct content *c, void *context)
Definition: ico.c:260
static void * nsico_bitmap_create(int width, int height, unsigned int bmp_state)
Callback for libnsbmp; forwards the call to bitmap_create()
Definition: ico.c:56
static bool nsico_convert(struct content *c)
Definition: ico.c:119
Content for image/ico (interface).
Generic bitmap handling interface.
@ BITMAP_CLEAR
memory should be wiped to 0
Definition: bitmap.h:39
@ BITMAP_OPAQUE
image is opaque
Definition: bitmap.h:38
@ BITMAP_NONE
Definition: bitmap.h:37
Public content interface.
static struct llcache_s * llcache
low level cache state
Definition: llcache.c:267
nsurl * llcache_handle_get_url(const llcache_handle *handle)
Retrieve the post-redirect URL of a low-level cache object.
Definition: llcache.c:4195
Low-level resource cache (interface)
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
char * messages_get_buff(const char *key,...)
Formatted message from a key in the global message hash.
Definition: messages.c:205
Localised message support (interface).
const char * nsurl_access_leaf(const nsurl *url)
Access a URL's path leaf as a string.
int width
Definition: gui.c:159
int height
Definition: gui.c:160
Bitmap format specifier.
Definition: bitmap.h:95
Content operation function table.
nserror(* create)(const struct content_handler *handler, lwc_string *imime_type, const struct http_parameter *params, struct llcache_handle *llcache, const char *fallback_charset, bool quirks, struct content **c)
parameters to content redraw
Definition: content.h:40
int height
vertical dimension
Definition: content.h:48
int width
dimensions to render content at (for scaling contents with intrinsic dimensions)
Definition: content.h:47
Content which corresponds to a single URL.
int height
Height dimension, if applicable.
int width
Width dimension, if applicable.
struct llcache_handle * llcache
Low-level cache object.
struct textsearch_context * context
content_status status
Current status.
unsigned int size
Estimated size of all data associated with this content.
void(* destroy)(void *bitmap)
Destroy a bitmap.
Definition: bitmap.h:143
void *(* create)(int width, int height, enum gui_bitmap_flags flags)
Create a new bitmap.
Definition: bitmap.h:136
bool(* get_opaque)(void *bitmap)
Get the opacity of a bitmap.
Definition: bitmap.h:159
void(* modified)(void *bitmap)
Marks a bitmap as modified.
Definition: bitmap.h:200
unsigned char *(* get_buffer)(void *bitmap)
Get the image buffer from a bitmap.
Definition: bitmap.h:169
Representation of an HTTP parameter.
Definition: parameter.c:31
Handle to low-level cache object.
Definition: llcache.c:76
struct gui_bitmap_table * bitmap
Bitmap table.
Definition: gui_table.h:144
struct ico_collection * ico
Definition: ico.c:45
struct content base
Definition: ico.c:43
Rectangle coordinates.
Definition: types.h:40
Redraw context.
Definition: plotters.h:51
Interface to a number of general purpose functionality.
static nserror clip(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.
Definition: plot.c:357