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.  *
  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/ico (implementation)
  21.  */
  22.  
  23. #include <assert.h>
  24. #include <string.h>
  25. #include <stdbool.h>
  26. #include <stdlib.h>
  27. #include <libnsbmp.h>
  28. #include "utils/config.h"
  29. #include "content/content_protected.h"
  30. #include "content/hlcache.h"
  31. #include "desktop/plotters.h"
  32. #include "image/bitmap.h"
  33. #include "image/bmp.h"
  34. #include "image/ico.h"
  35. #include "image/image.h"
  36. #include "utils/log.h"
  37. #include "utils/messages.h"
  38. #include "utils/utils.h"
  39.  
  40. typedef struct nsico_content {
  41.         struct content base;
  42.  
  43.         struct ico_collection *ico;     /** ICO collection data */
  44.  
  45. } nsico_content;
  46.  
  47.  
  48. static nserror nsico_create_ico_data(nsico_content *c)
  49. {
  50.         union content_msg_data msg_data;
  51.  
  52.         c->ico = calloc(sizeof(ico_collection), 1);
  53.         if (c->ico == NULL) {
  54.                 msg_data.error = messages_get("NoMemory");
  55.                 content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
  56.                 return NSERROR_NOMEM;
  57.         }
  58.         ico_collection_create(c->ico, &bmp_bitmap_callbacks);
  59.         return NSERROR_OK;
  60. }
  61.  
  62.  
  63. static nserror nsico_create(const content_handler *handler,
  64.                 lwc_string *imime_type, const struct http_parameter *params,
  65.                 llcache_handle *llcache, const char *fallback_charset,
  66.                 bool quirks, struct content **c)
  67. {
  68.         nsico_content *result;
  69.         nserror error;
  70.  
  71.         result = calloc(1, sizeof(nsico_content));
  72.         if (result == NULL)
  73.                 return NSERROR_NOMEM;
  74.  
  75.         error = content__init(&result->base, handler, imime_type, params,
  76.                         llcache, fallback_charset, quirks);
  77.         if (error != NSERROR_OK) {
  78.                 free(result);
  79.                 return error;
  80.         }
  81.  
  82.         error = nsico_create_ico_data(result);
  83.         if (error != NSERROR_OK) {
  84.                 free(result);
  85.                 return error;
  86.         }
  87.  
  88.         *c = (struct content *) result;
  89.  
  90.         return NSERROR_OK;
  91. }
  92.  
  93.  
  94.  
  95. static bool nsico_convert(struct content *c)
  96. {
  97.         nsico_content *ico = (nsico_content *) c;
  98.         struct bmp_image *bmp;
  99.         bmp_result res;
  100.         union content_msg_data msg_data;
  101.         const char *data;
  102.         unsigned long size;
  103.         char *title;
  104.  
  105.         /* set the ico data */
  106.         data = content__get_source_data(c, &size);
  107.  
  108.         /* analyse the ico */
  109.         res = ico_analyse(ico->ico, size, (unsigned char *) data);
  110.  
  111.         switch (res) {
  112.         case BMP_OK:
  113.                 break;
  114.         case BMP_INSUFFICIENT_MEMORY:
  115.                 msg_data.error = messages_get("NoMemory");
  116.                 content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
  117.                 return false;
  118.         case BMP_INSUFFICIENT_DATA:
  119.         case BMP_DATA_ERROR:
  120.                 msg_data.error = messages_get("BadICO");
  121.                 content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
  122.                 return false;
  123.         }
  124.  
  125.         /* Store our content width, height and calculate size */
  126.         c->width = ico->ico->width;
  127.         c->height = ico->ico->height;
  128.         c->size += (ico->ico->width * ico->ico->height * 4) + 16 + 44;
  129.  
  130.         /* set title text */
  131.         title = messages_get_buff("ICOTitle",
  132.                         nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
  133.                         c->width, c->height);
  134.         if (title != NULL) {
  135.                 content__set_title(c, title);
  136.                 free(title);
  137.         }
  138.  
  139.         /* select largest icon to ensure one can be selected */
  140.         bmp = ico_find(ico->ico, 255, 255);
  141.         if (bmp == NULL) {
  142.                 /* return error */
  143.                 LOG(("Failed to select icon"));
  144.                 return false;
  145.         }
  146.  
  147.         content_set_ready(c);
  148.         content_set_done(c);
  149.  
  150.         /* Done: update status bar */
  151.         content_set_status(c, "");
  152.         return true;
  153. }
  154.  
  155.  
  156. static bool nsico_redraw(struct content *c, struct content_redraw_data *data,
  157.                 const struct rect *clip, const struct redraw_context *ctx)
  158. {
  159.         nsico_content *ico = (nsico_content *)c;
  160.         struct bmp_image *bmp;
  161.  
  162.         /* select most appropriate sized icon for size */
  163.         bmp = ico_find(ico->ico, data->width, data->height);
  164.         if (bmp == NULL) {
  165.                 /* return error */
  166.                 LOG(("Failed to select icon"));
  167.                 return false;
  168.         }
  169.  
  170.         /* ensure its decided */
  171.         if (bmp->decoded == false) {
  172.                 if (bmp_decode(bmp) != BMP_OK) {
  173.                         return false;
  174.                 } else {
  175.                         LOG(("Decoding bitmap"));
  176.                         bitmap_modified(bmp->bitmap);
  177.                 }
  178.  
  179.         }
  180.  
  181.         return image_bitmap_plot(bmp->bitmap, data, clip, ctx);
  182. }
  183.  
  184.  
  185. static void nsico_destroy(struct content *c)
  186. {
  187.         nsico_content *ico = (nsico_content *) c;
  188.  
  189.         ico_finalise(ico->ico);
  190.         free(ico->ico);
  191. }
  192.  
  193. static nserror nsico_clone(const struct content *old, struct content **newc)
  194. {
  195.         nsico_content *ico;
  196.         nserror error;
  197.  
  198.         ico = calloc(1, sizeof(nsico_content));
  199.         if (ico == NULL)
  200.                 return NSERROR_NOMEM;
  201.  
  202.         error = content__clone(old, &ico->base);
  203.         if (error != NSERROR_OK) {
  204.                 content_destroy(&ico->base);
  205.                 return error;
  206.         }
  207.  
  208.         /* Simply replay creation and conversion */
  209.         error = nsico_create_ico_data(ico);
  210.         if (error != NSERROR_OK) {
  211.                 content_destroy(&ico->base);
  212.                 return error;
  213.         }
  214.  
  215.         if (old->status == CONTENT_STATUS_READY ||
  216.                         old->status == CONTENT_STATUS_DONE) {
  217.                 if (nsico_convert(&ico->base) == false) {
  218.                         content_destroy(&ico->base);
  219.                         return NSERROR_CLONE_FAILED;
  220.                 }
  221.         }
  222.  
  223.         *newc = (struct content *) ico;
  224.  
  225.         return NSERROR_OK;
  226. }
  227.  
  228. static void *nsico_get_internal(const struct content *c, void *context)
  229. {
  230.         nsico_content *ico = (nsico_content *) c;
  231.         /* TODO: Pick best size for purpose.
  232.          *       Currently assumes it's for a URL bar. */
  233.         struct bmp_image *bmp;
  234.  
  235.         bmp = ico_find(ico->ico, 16, 16);
  236.         if (bmp == NULL) {
  237.                 /* return error */
  238.                 LOG(("Failed to select icon"));
  239.                 return NULL;
  240.         }
  241.  
  242.         if (bmp->decoded == false) {
  243.                 if (bmp_decode(bmp) != BMP_OK) {
  244.                         return NULL;
  245.                 } else {
  246.                         bitmap_modified(bmp->bitmap);
  247.                 }
  248.         }
  249.  
  250.         return bmp->bitmap;
  251. }
  252.  
  253. static content_type nsico_content_type(void)
  254. {
  255.         return CONTENT_IMAGE;
  256. }
  257.  
  258. static const content_handler nsico_content_handler = {
  259.         .create = nsico_create,
  260.         .data_complete = nsico_convert,
  261.         .destroy = nsico_destroy,
  262.         .redraw = nsico_redraw,
  263.         .clone = nsico_clone,
  264.         .get_internal = nsico_get_internal,
  265.         .type = nsico_content_type,
  266.         .no_share = false,
  267. };
  268.  
  269. static const char *nsico_types[] = {
  270.         "application/ico",
  271.         "application/x-ico",
  272.         "image/ico",
  273.         "image/vnd.microsoft.icon",
  274.         "image/x-icon"
  275. };
  276.  
  277. CONTENT_FACTORY_REGISTER_TYPES(nsico, nsico_types, nsico_content_handler);
  278.