Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2006 Richard Wilson <info@tinct.net>
  3.  * Copyright 2008 Sean Fox <dyntryx@gmail.com>
  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. /** \file
  21.  * Content for image/bmp (implementation)
  22.  */
  23.  
  24. #include <assert.h>
  25. #include <string.h>
  26. #include <stdbool.h>
  27. #include <stdlib.h>
  28. #include <libnsbmp.h>
  29.  
  30. #include "utils/config.h"
  31. #include "content/content_protected.h"
  32. #include "content/hlcache.h"
  33. #include "desktop/plotters.h"
  34. #include "utils/log.h"
  35. #include "utils/messages.h"
  36. #include "utils/utils.h"
  37.  
  38. #include "image/bitmap.h"
  39. #include "image/bmp.h"
  40.  
  41. typedef struct nsbmp_content {
  42.         struct content base;
  43.  
  44.         bmp_image *bmp; /** BMP image data */
  45.  
  46.         struct bitmap *bitmap;  /**< Created NetSurf bitmap */
  47. } nsbmp_content;
  48.  
  49. static nserror nsbmp_create_bmp_data(nsbmp_content *bmp)
  50. {      
  51.         union content_msg_data msg_data;
  52.  
  53.         bmp->bmp = calloc(sizeof(struct bmp_image), 1);
  54.         if (bmp->bmp == NULL) {
  55.                 msg_data.error = messages_get("NoMemory");
  56.                 content_broadcast(&bmp->base, CONTENT_MSG_ERROR, msg_data);
  57.                 return NSERROR_NOMEM;
  58.         }
  59.  
  60.         bmp_create(bmp->bmp, &bmp_bitmap_callbacks);
  61.  
  62.         return NSERROR_OK;
  63. }
  64.  
  65.  
  66. static nserror nsbmp_create(const content_handler *handler,
  67.                 lwc_string *imime_type, const struct http_parameter *params,
  68.                 llcache_handle *llcache, const char *fallback_charset,
  69.                 bool quirks, struct content **c)
  70. {
  71.         nsbmp_content *bmp;
  72.         nserror error;
  73.  
  74.         bmp = calloc(1, sizeof(nsbmp_content));
  75.         if (bmp == NULL)
  76.                 return NSERROR_NOMEM;
  77.  
  78.         error = content__init(&bmp->base, handler, imime_type, params,
  79.                         llcache, fallback_charset, quirks);
  80.         if (error != NSERROR_OK) {
  81.                 free(bmp);
  82.                 return error;
  83.         }
  84.  
  85.         error = nsbmp_create_bmp_data(bmp);
  86.         if (error != NSERROR_OK) {
  87.                 free(bmp);
  88.                 return error;
  89.         }
  90.  
  91.         *c = (struct content *) bmp;
  92.  
  93.         return NSERROR_OK;
  94. }
  95.  
  96. /**
  97.  * Callback for libnsbmp; forwards the call to bitmap_create()
  98.  *
  99.  * \param  width   width of image in pixels
  100.  * \param  height  width of image in pixels
  101.  * \param  state   a flag word indicating the initial state
  102.  * \return an opaque struct bitmap, or NULL on memory exhaustion
  103.  */
  104. static void *nsbmp_bitmap_create(int width, int height, unsigned int bmp_state)
  105. {
  106.         unsigned int bitmap_state = BITMAP_NEW;
  107.  
  108.         /* set bitmap state based on bmp state */
  109.         bitmap_state |= (bmp_state & BMP_OPAQUE) ? BITMAP_OPAQUE : 0;
  110.         bitmap_state |= (bmp_state & BMP_CLEAR_MEMORY) ?
  111.                         BITMAP_CLEAR_MEMORY : 0;
  112.  
  113.         /* return the created bitmap */
  114.         return bitmap_create(width, height, bitmap_state);
  115. }
  116.  
  117. /* The Bitmap callbacks function table;
  118.  * necessary for interaction with nsbmplib.
  119.  */
  120. bmp_bitmap_callback_vt bmp_bitmap_callbacks = {
  121.         .bitmap_create = nsbmp_bitmap_create,
  122.         .bitmap_destroy = bitmap_destroy,
  123.         .bitmap_get_buffer = bitmap_get_buffer,
  124.         .bitmap_get_bpp = bitmap_get_bpp
  125. };
  126.  
  127. static bool nsbmp_convert(struct content *c)
  128. {
  129.         nsbmp_content *bmp = (nsbmp_content *) c;
  130.         bmp_result res;
  131.         union content_msg_data msg_data;
  132.         uint32_t swidth;
  133.         const char *data;
  134.         unsigned long size;
  135.         char *title;
  136.  
  137.         /* set the bmp data */
  138.         data = content__get_source_data(c, &size);
  139.  
  140.         /* analyse the BMP */
  141.         res = bmp_analyse(bmp->bmp, size, (unsigned char *) data);
  142.         switch (res) {
  143.                 case BMP_OK:
  144.                         break;
  145.                 case BMP_INSUFFICIENT_MEMORY:
  146.                         msg_data.error = messages_get("NoMemory");
  147.                         content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
  148.                         return false;
  149.                 case BMP_INSUFFICIENT_DATA:
  150.                 case BMP_DATA_ERROR:
  151.                         msg_data.error = messages_get("BadBMP");
  152.                         content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
  153.                         return false;
  154.         }
  155.  
  156.         /* Store our content width and description */
  157.         c->width = bmp->bmp->width;
  158.         c->height = bmp->bmp->height;
  159.         swidth = bmp->bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bmp->bitmap) *
  160.                         bmp->bmp->width;
  161.         c->size += (swidth * bmp->bmp->height) + 16 + 44;
  162.  
  163.         /* set title text */
  164.         title = messages_get_buff("BMPTitle",
  165.                         nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
  166.                         c->width, c->height);
  167.         if (title != NULL) {
  168.                 content__set_title(c, title);
  169.                 free(title);
  170.         }
  171.  
  172.         /* exit as a success */
  173.         bmp->bitmap = bmp->bmp->bitmap;
  174.         bitmap_modified(bmp->bitmap);
  175.  
  176.         content_set_ready(c);
  177.         content_set_done(c);
  178.  
  179.         /* Done: update status bar */
  180.         content_set_status(c, "");
  181.         return true;
  182. }
  183.  
  184. static bool nsbmp_redraw(struct content *c, struct content_redraw_data *data,
  185.                 const struct rect *clip, const struct redraw_context *ctx)
  186. {
  187.         nsbmp_content *bmp = (nsbmp_content *) c;
  188.         bitmap_flags_t flags = BITMAPF_NONE;
  189.  
  190.         if (bmp->bmp->decoded == false)
  191.                 if (bmp_decode(bmp->bmp) != BMP_OK)
  192.                         return false;
  193.  
  194.         bmp->bitmap = bmp->bmp->bitmap;
  195.  
  196.         if (data->repeat_x)
  197.                 flags |= BITMAPF_REPEAT_X;
  198.         if (data->repeat_y)
  199.                 flags |= BITMAPF_REPEAT_Y;
  200.  
  201.         return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
  202.                         bmp->bitmap, data->background_colour, flags);
  203. }
  204.  
  205.  
  206. static void nsbmp_destroy(struct content *c)
  207. {
  208.         nsbmp_content *bmp = (nsbmp_content *) c;
  209.  
  210.         bmp_finalise(bmp->bmp);
  211.         free(bmp->bmp);
  212. }
  213.  
  214.  
  215. static nserror nsbmp_clone(const struct content *old, struct content **newc)
  216. {
  217.         nsbmp_content *new_bmp;
  218.         nserror error;
  219.  
  220.         new_bmp = calloc(1, sizeof(nsbmp_content));
  221.         if (new_bmp == NULL)
  222.                 return NSERROR_NOMEM;
  223.  
  224.         error = content__clone(old, &new_bmp->base);
  225.         if (error != NSERROR_OK) {
  226.                 content_destroy(&new_bmp->base);
  227.                 return error;
  228.         }
  229.  
  230.         /* We "clone" the old content by replaying creation and conversion */
  231.         error = nsbmp_create_bmp_data(new_bmp);
  232.         if (error != NSERROR_OK) {
  233.                 content_destroy(&new_bmp->base);
  234.                 return error;
  235.         }
  236.  
  237.         if (old->status == CONTENT_STATUS_READY ||
  238.                         old->status == CONTENT_STATUS_DONE) {
  239.                 if (nsbmp_convert(&new_bmp->base) == false) {
  240.                         content_destroy(&new_bmp->base);
  241.                         return NSERROR_CLONE_FAILED;
  242.                 }
  243.         }
  244.  
  245.         *newc = (struct content *) new_bmp;
  246.  
  247.         return NSERROR_OK;
  248. }
  249.  
  250. static void *nsbmp_get_internal(const struct content *c, void *context)
  251. {
  252.         nsbmp_content *bmp = (nsbmp_content *)c;
  253.  
  254.         return bmp->bitmap;
  255. }
  256.  
  257. static content_type nsbmp_content_type(void)
  258. {
  259.         return CONTENT_IMAGE;
  260. }
  261.  
  262.  
  263. static const content_handler nsbmp_content_handler = {
  264.         .create = nsbmp_create,
  265.         .data_complete = nsbmp_convert,
  266.         .destroy = nsbmp_destroy,
  267.         .redraw = nsbmp_redraw,
  268.         .clone = nsbmp_clone,
  269.         .get_internal = nsbmp_get_internal,
  270.         .type = nsbmp_content_type,
  271.         .no_share = false,
  272. };
  273.  
  274. static const char *nsbmp_types[] = {
  275.         "application/bmp",
  276.         "application/preview",
  277.         "application/x-bmp",
  278.         "application/x-win-bitmap",
  279.         "image/bmp",
  280.         "image/ms-bmp",
  281.         "image/x-bitmap",
  282.         "image/x-bmp",
  283.         "image/x-ms-bmp",
  284.         "image/x-win-bitmap",
  285.         "image/x-windows-bmp",
  286.         "image/x-xbitmap"
  287. };
  288.  
  289. CONTENT_FACTORY_REGISTER_TYPES(nsbmp, nsbmp_types, nsbmp_content_handler);
  290.