Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1.  /*
  2.  * Copyright 2010 Chris Young <chris@unsatisfactorysoftware.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. /** \file
  20.  * Content for image/webp (libwebp implementation).
  21.  *
  22.  */
  23.  
  24. #include <assert.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include <webp/decode.h>
  28. #include "desktop/plotters.h"
  29. #include "image/bitmap.h"
  30. #include "content/content_protected.h"
  31. #include "utils/log.h"
  32. #include "utils/messages.h"
  33. #include "utils/utils.h"
  34.  
  35. typedef struct webp_content
  36. {
  37.         struct content base;
  38.  
  39.         struct bitmap *bitmap;  /**< Created NetSurf bitmap */
  40. } webp_content;
  41.  
  42.  
  43. static nserror webp_create(const content_handler *handler,
  44.                 lwc_string *imime_type, const http_parameter *params,
  45.                 llcache_handle *llcache, const char *fallback_charset,
  46.                 bool quirks, struct content **c)
  47. {
  48.         webp_content *webp;
  49.         nserror error;
  50.  
  51.         webp = calloc(1, sizeof(webp_content));
  52.         if (webp == NULL)
  53.                 return NSERROR_NOMEM;
  54.  
  55.         error = content__init(&webp->base, handler, imime_type, params,
  56.                         llcache, fallback_charset, quirks);
  57.         if (error != NSERROR_OK) {
  58.                 free(webp);
  59.                 return error;
  60.         }
  61.  
  62.         *c = (struct content *) webp;
  63.  
  64.         return NSERROR_OK;
  65. }
  66.  
  67. /**
  68.  * Convert a CONTENT_WEBP for display.
  69.  *
  70.  * No conversion is necessary. We merely read the WebP dimensions.
  71.  */
  72.  
  73. static bool webp_convert(struct content *c)
  74. {
  75.         webp_content *webp = (webp_content *)c;
  76.         union content_msg_data msg_data;
  77.         const uint8_t *data;
  78.         unsigned char *imagebuf = NULL;
  79.         unsigned long size;
  80.         int width = 0, height = 0;
  81.         char *title;
  82.         int res = 0;
  83.         uint8_t *res_p = NULL;
  84.  
  85.         data = (uint8_t *)content__get_source_data(c, &size);
  86.  
  87.         res = WebPGetInfo(data, size, &width, &height);
  88.         if (res == 0) {
  89.                 msg_data.error = messages_get("NoMemory");
  90.                 content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
  91.                 return false;
  92.         }
  93.  
  94.         webp->bitmap = bitmap_create(width, height, BITMAP_NEW | BITMAP_OPAQUE);
  95.         if (!webp->bitmap) {
  96.                 msg_data.error = messages_get("NoMemory");
  97.                 content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
  98.                 return false;
  99.         }
  100.  
  101.         imagebuf = bitmap_get_buffer(webp->bitmap);
  102.         if (!imagebuf) {
  103.                 msg_data.error = messages_get("NoMemory");
  104.                 content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
  105.                 return false;
  106.         }
  107.         unsigned int row_width = bitmap_get_rowstride(webp->bitmap);
  108.  
  109.         res_p = WebPDecodeRGBAInto(data, size, imagebuf,
  110.                                 row_width * height, row_width);
  111.         if (res_p == NULL) {
  112.                 msg_data.error = messages_get("NoMemory");
  113.                 content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
  114.                 return false;
  115.         }
  116.  
  117.         c->width = width;
  118.         c->height = height;
  119.  
  120.         /* set title */
  121.         title = messages_get_buff("WebPTitle",
  122.                         nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
  123.                         c->width, c->height);
  124.         if (title != NULL) {
  125.                 content__set_title(c, title);
  126.                 free(title);
  127.         }
  128.  
  129.         bitmap_modified(webp->bitmap);
  130.  
  131.         content_set_ready(c);
  132.         content_set_done(c);
  133.  
  134.         content_set_status(c, "");
  135.         return true;
  136. }
  137.  
  138.  
  139. /**
  140.  * Destroy a CONTENT_WEBP and free all resources it owns.
  141.  */
  142.  
  143. static void webp_destroy(struct content *c)
  144. {
  145.         webp_content *webp = (webp_content *)c;
  146.  
  147.         if (webp->bitmap != NULL)
  148.                 bitmap_destroy(webp->bitmap);
  149. }
  150.  
  151.  
  152. /**
  153.  * Redraw a CONTENT_WEBP.
  154.  */
  155.  
  156. static bool webp_redraw(struct content *c, struct content_redraw_data *data,
  157.                 const struct rect *clip, const struct redraw_context *ctx)
  158. {
  159.         webp_content *webp = (webp_content *)c;
  160.         bitmap_flags_t flags = BITMAPF_NONE;
  161.  
  162.         if (data->repeat_x)
  163.                 flags |= BITMAPF_REPEAT_X;
  164.         if (data->repeat_y)
  165.                 flags |= BITMAPF_REPEAT_Y;
  166.  
  167.         return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
  168.                         webp->bitmap, data->background_colour, flags);
  169. }
  170.  
  171.  
  172. static nserror webp_clone(const struct content *old, struct content **newc)
  173. {
  174.         webp_content *webp;
  175.         nserror error;
  176.  
  177.         webp = calloc(1, sizeof(webp_content));
  178.         if (webp == NULL)
  179.                 return NSERROR_NOMEM;
  180.  
  181.         error = content__clone(old, &webp->base);
  182.         if (error != NSERROR_OK) {
  183.                 content_destroy(&webp->base);
  184.                 return error;
  185.         }
  186.  
  187.         /* Simply replay convert */
  188.         if (old->status == CONTENT_STATUS_READY ||
  189.                         old->status == CONTENT_STATUS_DONE) {
  190.                 if (webp_convert(&webp->base) == false) {
  191.                         content_destroy(&webp->base);
  192.                         return NSERROR_CLONE_FAILED;
  193.                 }
  194.         }
  195.  
  196.         *newc = (struct content *) webp;
  197.  
  198.         return NSERROR_OK;
  199. }
  200.  
  201. static void *webp_get_internal(const struct content *c, void *context)
  202. {
  203.         webp_content *webp = (webp_content *)c;
  204.  
  205.         return webp->bitmap;
  206. }
  207.  
  208. static content_type webp_content_type(void)
  209. {
  210.         return CONTENT_IMAGE;
  211. }
  212.  
  213. static const content_handler webp_content_handler = {
  214.         .create = webp_create,
  215.         .data_complete = webp_convert,
  216.         .destroy = webp_destroy,
  217.         .redraw = webp_redraw,
  218.         .clone = webp_clone,
  219.         .get_internal = webp_get_internal,
  220.         .type = webp_content_type,
  221.         .no_share = false,
  222. };
  223.  
  224. static const char *webp_types[] = {
  225.         "image/webp"
  226. };
  227.  
  228. CONTENT_FACTORY_REGISTER_TYPES(webp, webp_types, webp_content_handler);
  229.  
  230.