Initial checkin of Pika from heckimp
This commit is contained in:
704
plug-ins/file-ico/ico-dialog.c
Normal file
704
plug-ins/file-ico/ico-dialog.c
Normal file
@ -0,0 +1,704 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* PIKA Plug-in for Windows Icon files.
|
||||
* Copyright (C) 2002 Christian Kreibich <christian@whoop.org>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <libpika/pika.h>
|
||||
#include <libpika/pikaui.h>
|
||||
|
||||
/* #define ICO_DBG */
|
||||
|
||||
#include "ico.h"
|
||||
#include "ico-dialog.h"
|
||||
#include "ico-save.h"
|
||||
|
||||
#include "libpika/stdplugins-intl.h"
|
||||
|
||||
static void ico_dialog_bpp_changed (GtkWidget *combo,
|
||||
GObject *hbox);
|
||||
static void ico_dialog_toggle_compress (GtkWidget *checkbox,
|
||||
GObject *hbox);
|
||||
static void ico_dialog_check_compat (GtkWidget *dialog,
|
||||
IcoSaveInfo *info);
|
||||
static void ico_dialog_ani_update_inam (GtkEntry *entry,
|
||||
gpointer data);
|
||||
static void ico_dialog_ani_update_iart (GtkEntry *entry,
|
||||
gpointer data);
|
||||
|
||||
|
||||
GtkWidget *
|
||||
ico_dialog_new (IcoSaveInfo *info,
|
||||
AniFileHeader *ani_header,
|
||||
AniSaveInfo *ani_info)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *main_vbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *scrolled_window;
|
||||
GtkWidget *viewport;
|
||||
GtkWidget *warning;
|
||||
|
||||
dialog = pika_export_dialog_new (ani_header ?
|
||||
_("Windows Animated Cursor") : info->is_cursor ?
|
||||
_("Windows Cursor") : _("Windows Icon"),
|
||||
PLUG_IN_BINARY,
|
||||
"plug-in-winicon");
|
||||
|
||||
/* We store an array that holds each icon's requested bit depth
|
||||
with the dialog. It's queried when the dialog is closed so the
|
||||
save routine knows what colormaps etc to generate in the saved
|
||||
file. We store twice the number necessary because in the second
|
||||
set, the color depths that are automatically suggested are stored
|
||||
for later comparison.
|
||||
*/
|
||||
|
||||
g_object_set_data (G_OBJECT (dialog), "save_info", info);
|
||||
if (ani_header)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (dialog), "save_ani_header", ani_header);
|
||||
g_object_set_data (G_OBJECT (dialog), "save_ani_info", ani_info);
|
||||
}
|
||||
|
||||
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 6);
|
||||
gtk_box_pack_start (GTK_BOX (pika_export_dialog_get_content_area (dialog)),
|
||||
main_vbox, TRUE, TRUE, 0);
|
||||
gtk_widget_show (main_vbox);
|
||||
|
||||
/*Animated Cursor */
|
||||
if (ani_header)
|
||||
{
|
||||
GtkWidget *grid;
|
||||
GtkAdjustment *adjustment;
|
||||
GtkWidget *spin;
|
||||
GtkWidget *label;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *entry;
|
||||
|
||||
frame = pika_frame_new (_("Animated Cursor Settings"));
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
|
||||
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
|
||||
gtk_container_add (GTK_CONTAINER (frame), grid);
|
||||
gtk_widget_show (grid);
|
||||
|
||||
/* Cursor Name */
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
pika_grid_attach_aligned (GTK_GRID (grid), 0, 1,
|
||||
_("_Cursor Name (Optional)"),
|
||||
0.0, 0.5,
|
||||
hbox, 1);
|
||||
|
||||
entry = gtk_entry_new ();
|
||||
gtk_entry_set_text (GTK_ENTRY (entry),
|
||||
ani_info->inam ? ani_info->inam : "");
|
||||
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
|
||||
gtk_widget_show (entry);
|
||||
|
||||
g_signal_connect (GTK_ENTRY (entry), "focus-out-event",
|
||||
G_CALLBACK (ico_dialog_ani_update_inam),
|
||||
NULL);
|
||||
|
||||
/* Author Name */
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
pika_grid_attach_aligned (GTK_GRID (grid), 0, 3,
|
||||
_("_Author Name (Optional)"),
|
||||
0.0, 0.5,
|
||||
hbox, 1);
|
||||
|
||||
entry = gtk_entry_new ();
|
||||
gtk_entry_set_text (GTK_ENTRY (entry),
|
||||
ani_info->iart ? ani_info->iart : "");
|
||||
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
|
||||
gtk_widget_show (entry);
|
||||
|
||||
g_signal_connect (GTK_ENTRY (entry), "focus-out-event",
|
||||
G_CALLBACK (ico_dialog_ani_update_iart),
|
||||
NULL);
|
||||
|
||||
/* Default delay spin */
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
pika_grid_attach_aligned (GTK_GRID (grid), 0, 5,
|
||||
_("_Delay between frames:"),
|
||||
0.0, 0.5,
|
||||
hbox, 1);
|
||||
|
||||
adjustment = gtk_adjustment_new (ani_header->jif_rate, 1, G_MAXINT,
|
||||
1, 10, 0);
|
||||
spin = pika_spin_button_new (adjustment, 1, 0);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), spin, FALSE, FALSE, 0);
|
||||
gtk_widget_show (spin);
|
||||
|
||||
label = gtk_label_new (_(" jiffies (16.66 ms)"));
|
||||
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
g_signal_connect (adjustment, "value-changed",
|
||||
G_CALLBACK (pika_int_adjustment_update),
|
||||
&ani_header->jif_rate);
|
||||
}
|
||||
|
||||
/* Cursor */
|
||||
frame = pika_frame_new (_("Icon Details"));
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 4);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
|
||||
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
||||
gtk_container_add (GTK_CONTAINER (frame), scrolled_window);
|
||||
gtk_widget_show (scrolled_window);
|
||||
|
||||
viewport = gtk_viewport_new (NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (scrolled_window), viewport);
|
||||
gtk_widget_show (viewport);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
|
||||
g_object_set_data (G_OBJECT (dialog), "icons_vbox", vbox);
|
||||
gtk_container_add (GTK_CONTAINER (viewport), vbox);
|
||||
gtk_widget_show (vbox);
|
||||
|
||||
warning = g_object_new (PIKA_TYPE_HINT_BOX,
|
||||
"icon-name", PIKA_ICON_DIALOG_WARNING,
|
||||
"hint",
|
||||
_("Large icons and compression are not supported "
|
||||
"by all programs. Older applications may not "
|
||||
"open this file correctly."),
|
||||
NULL);
|
||||
gtk_box_pack_end (GTK_BOX (main_vbox), warning, FALSE, FALSE, 12);
|
||||
/* don't show the warning here */
|
||||
|
||||
g_object_set_data (G_OBJECT (dialog), "warning", warning);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
ico_preview_new (PikaDrawable *layer)
|
||||
{
|
||||
GtkWidget *image;
|
||||
GdkPixbuf *pixbuf;
|
||||
gint width = pika_drawable_get_width (layer);
|
||||
gint height = pika_drawable_get_height (layer);
|
||||
|
||||
pixbuf = pika_drawable_get_thumbnail (layer,
|
||||
MIN (width, 128), MIN (height, 128),
|
||||
PIKA_PIXBUF_SMALL_CHECKS);
|
||||
image = gtk_image_new_from_pixbuf (pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/* This function creates and returns an hbox for an icon,
|
||||
which then gets added to the dialog's main vbox. */
|
||||
static GtkWidget *
|
||||
ico_create_icon_hbox (GtkWidget *icon_preview,
|
||||
PikaDrawable *layer,
|
||||
gint layer_num,
|
||||
IcoSaveInfo *info)
|
||||
{
|
||||
static GtkSizeGroup *size = NULL;
|
||||
|
||||
GtkWidget *frame;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *combo;
|
||||
GtkWidget *checkbox;
|
||||
gchar *frame_header;
|
||||
gint width = pika_drawable_get_width (layer);
|
||||
gint height = pika_drawable_get_height (layer);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
|
||||
frame_header = g_strdup_printf ("%dx%d", width, height);
|
||||
|
||||
frame = pika_frame_new (frame_header);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_set_visible (frame, TRUE);
|
||||
g_free (frame_header);
|
||||
|
||||
/* To make life easier for the callbacks, we store the
|
||||
layer's ID and stacking number with the hbox. */
|
||||
|
||||
g_object_set_data (G_OBJECT (hbox),
|
||||
"icon_layer", layer);
|
||||
g_object_set_data (G_OBJECT (hbox),
|
||||
"icon_layer_num", GINT_TO_POINTER (layer_num));
|
||||
|
||||
g_object_set_data (G_OBJECT (hbox), "icon_preview", icon_preview);
|
||||
gtk_widget_set_halign (icon_preview, GTK_ALIGN_END);
|
||||
gtk_widget_set_valign (icon_preview, GTK_ALIGN_CENTER);
|
||||
gtk_container_add (GTK_CONTAINER (frame), icon_preview);
|
||||
gtk_widget_show (icon_preview);
|
||||
|
||||
if (! size)
|
||||
size = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
||||
|
||||
gtk_size_group_add_widget (size, icon_preview);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (vbox);
|
||||
|
||||
combo = pika_int_combo_box_new (_("1 bpp, 1-bit alpha, 2-slot palette"), 1,
|
||||
_("4 bpp, 1-bit alpha, 16-slot palette"), 4,
|
||||
_("8 bpp, 1-bit alpha, 256-slot palette"), 8,
|
||||
_("24 bpp, 1-bit alpha, no palette"), 24,
|
||||
_("32 bpp, 8-bit alpha, no palette"), 32,
|
||||
NULL);
|
||||
pika_int_combo_box_set_active (PIKA_INT_COMBO_BOX (combo),
|
||||
info->depths[layer_num]);
|
||||
gtk_widget_set_margin_top (GTK_WIDGET (combo), 6);
|
||||
|
||||
g_signal_connect (combo, "changed",
|
||||
G_CALLBACK (ico_dialog_bpp_changed),
|
||||
hbox);
|
||||
|
||||
g_object_set_data (G_OBJECT (hbox), "icon_menu", combo);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
|
||||
gtk_widget_show (combo);
|
||||
|
||||
checkbox = gtk_check_button_new_with_label (_("Compressed (PNG)"));
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox),
|
||||
info->compress[layer_num]);
|
||||
g_signal_connect (checkbox, "toggled",
|
||||
G_CALLBACK (ico_dialog_toggle_compress), hbox);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), checkbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (checkbox);
|
||||
|
||||
return hbox;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
ico_dialog_get_layer_preview (GtkWidget *dialog,
|
||||
PikaDrawable *layer)
|
||||
{
|
||||
GtkWidget *preview;
|
||||
GtkWidget *icon_hbox;
|
||||
gchar key[ICO_MAXBUF];
|
||||
|
||||
g_snprintf (key, sizeof (key), "layer_%i_hbox",
|
||||
pika_item_get_id (PIKA_ITEM (layer)));
|
||||
icon_hbox = g_object_get_data (G_OBJECT (dialog), key);
|
||||
|
||||
if (!icon_hbox)
|
||||
{
|
||||
D(("Something's wrong -- couldn't look up hbox by layer ID\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
preview = g_object_get_data (G_OBJECT (icon_hbox), "icon_preview");
|
||||
|
||||
if (!icon_hbox)
|
||||
{
|
||||
D(("Something's wrong -- couldn't look up preview from hbox\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return preview;
|
||||
}
|
||||
|
||||
static void
|
||||
ico_dialog_update_icon_preview (GtkWidget *dialog,
|
||||
PikaDrawable *layer,
|
||||
gint bpp)
|
||||
{
|
||||
GtkWidget *preview = ico_dialog_get_layer_preview (dialog, layer);
|
||||
GdkPixbuf *pixbuf;
|
||||
const Babl *format;
|
||||
gint w = pika_drawable_get_width (layer);
|
||||
gint h = pika_drawable_get_height (layer);
|
||||
|
||||
if (! preview)
|
||||
return;
|
||||
|
||||
switch (pika_drawable_type (layer))
|
||||
{
|
||||
case PIKA_RGB_IMAGE:
|
||||
format = babl_format ("R'G'B' u8");
|
||||
break;
|
||||
|
||||
case PIKA_RGBA_IMAGE:
|
||||
format = babl_format ("R'G'B'A u8");
|
||||
break;
|
||||
|
||||
case PIKA_GRAY_IMAGE:
|
||||
format = babl_format ("Y' u8");
|
||||
break;
|
||||
|
||||
case PIKA_GRAYA_IMAGE:
|
||||
format = babl_format ("Y'A u8");
|
||||
break;
|
||||
|
||||
case PIKA_INDEXED_IMAGE:
|
||||
case PIKA_INDEXEDA_IMAGE:
|
||||
format = pika_drawable_get_format (layer);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
if (bpp <= 8)
|
||||
{
|
||||
GeglBuffer *buffer;
|
||||
GeglBuffer *tmp;
|
||||
PikaImage *image;
|
||||
PikaImage *tmp_image;
|
||||
PikaLayer *tmp_layer;
|
||||
guchar *buf;
|
||||
guchar *cmap;
|
||||
gint num_colors;
|
||||
|
||||
image = pika_item_get_image (PIKA_ITEM (layer));
|
||||
|
||||
tmp_image = pika_image_new (w, h, pika_image_get_base_type (image));
|
||||
pika_image_undo_disable (tmp_image);
|
||||
|
||||
if (pika_drawable_is_indexed (layer))
|
||||
{
|
||||
cmap = pika_image_get_colormap (image, NULL, &num_colors);
|
||||
pika_image_set_colormap (tmp_image, cmap, num_colors);
|
||||
g_free (cmap);
|
||||
}
|
||||
|
||||
tmp_layer = pika_layer_new (tmp_image, "temporary", w, h,
|
||||
pika_drawable_type (layer),
|
||||
100,
|
||||
pika_image_get_default_new_layer_mode (tmp_image));
|
||||
pika_image_insert_layer (tmp_image, tmp_layer, NULL, 0);
|
||||
|
||||
buffer = pika_drawable_get_buffer (layer);
|
||||
tmp = pika_drawable_get_buffer (PIKA_DRAWABLE (tmp_layer));
|
||||
|
||||
buf = g_malloc (w * h * 4);
|
||||
|
||||
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0,
|
||||
format, buf,
|
||||
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||
|
||||
gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, tmp, NULL);
|
||||
|
||||
g_object_unref (tmp);
|
||||
g_object_unref (buffer);
|
||||
|
||||
if (pika_drawable_is_indexed (layer))
|
||||
pika_image_convert_rgb (tmp_image);
|
||||
|
||||
pika_image_convert_indexed (tmp_image,
|
||||
PIKA_CONVERT_DITHER_FS,
|
||||
PIKA_CONVERT_PALETTE_GENERATE,
|
||||
1 << bpp, TRUE, FALSE, "dummy");
|
||||
|
||||
cmap = pika_image_get_colormap (tmp_image, NULL, &num_colors);
|
||||
|
||||
if (num_colors == (1 << bpp) &&
|
||||
! ico_cmap_contains_black (cmap, num_colors))
|
||||
{
|
||||
/* Windows icons with color maps need the color black.
|
||||
* We need to eliminate one more color to make room for black.
|
||||
*/
|
||||
if (pika_drawable_is_indexed (layer))
|
||||
{
|
||||
g_free (cmap);
|
||||
cmap = pika_image_get_colormap (image, NULL, &num_colors);
|
||||
pika_image_set_colormap (tmp_image, cmap, num_colors);
|
||||
}
|
||||
else if (pika_drawable_is_gray (layer))
|
||||
{
|
||||
pika_image_convert_grayscale (tmp_image);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_image_convert_rgb (tmp_image);
|
||||
}
|
||||
|
||||
tmp = pika_drawable_get_buffer (PIKA_DRAWABLE (tmp_layer));
|
||||
|
||||
gegl_buffer_set (tmp, GEGL_RECTANGLE (0, 0, w, h), 0,
|
||||
format, buf, GEGL_AUTO_ROWSTRIDE);
|
||||
|
||||
g_object_unref (tmp);
|
||||
|
||||
if (!pika_drawable_is_rgb (layer))
|
||||
pika_image_convert_rgb (tmp_image);
|
||||
|
||||
pika_image_convert_indexed (tmp_image,
|
||||
PIKA_CONVERT_DITHER_FS,
|
||||
PIKA_CONVERT_PALETTE_GENERATE,
|
||||
(1 << bpp) - 1, TRUE, FALSE, "dummy");
|
||||
}
|
||||
|
||||
g_free (cmap);
|
||||
g_free (buf);
|
||||
|
||||
pixbuf = pika_drawable_get_thumbnail (PIKA_DRAWABLE (tmp_layer),
|
||||
MIN (w, 128), MIN (h, 128),
|
||||
PIKA_PIXBUF_SMALL_CHECKS);
|
||||
|
||||
pika_image_delete (tmp_image);
|
||||
}
|
||||
else if (bpp == 24)
|
||||
{
|
||||
GeglBuffer *buffer;
|
||||
GeglBuffer *tmp;
|
||||
PikaImage *image;
|
||||
PikaImage *tmp_image;
|
||||
PikaLayer *tmp_layer;
|
||||
PikaValueArray *return_vals;
|
||||
|
||||
image = pika_item_get_image (PIKA_ITEM (layer));
|
||||
|
||||
tmp_image = pika_image_new (w, h, pika_image_get_base_type (image));
|
||||
pika_image_undo_disable (tmp_image);
|
||||
|
||||
if (pika_drawable_is_indexed (layer))
|
||||
{
|
||||
guchar *cmap;
|
||||
gint num_colors;
|
||||
|
||||
cmap = pika_image_get_colormap (image, NULL, &num_colors);
|
||||
pika_image_set_colormap (tmp_image, cmap, num_colors);
|
||||
g_free (cmap);
|
||||
}
|
||||
|
||||
tmp_layer = pika_layer_new (tmp_image, "temporary", w, h,
|
||||
pika_drawable_type (layer),
|
||||
100,
|
||||
pika_image_get_default_new_layer_mode (tmp_image));
|
||||
pika_image_insert_layer (tmp_image, tmp_layer, NULL, 0);
|
||||
|
||||
buffer = pika_drawable_get_buffer (layer);
|
||||
tmp = pika_drawable_get_buffer (PIKA_DRAWABLE (tmp_layer));
|
||||
|
||||
gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, tmp, NULL);
|
||||
|
||||
g_object_unref (tmp);
|
||||
g_object_unref (buffer);
|
||||
|
||||
if (pika_drawable_is_indexed (layer))
|
||||
pika_image_convert_rgb (tmp_image);
|
||||
|
||||
return_vals =
|
||||
pika_pdb_run_procedure (pika_get_pdb (),
|
||||
"plug-in-threshold-alpha",
|
||||
PIKA_TYPE_RUN_MODE, PIKA_RUN_NONINTERACTIVE,
|
||||
PIKA_TYPE_IMAGE, tmp_image,
|
||||
PIKA_TYPE_DRAWABLE, tmp_layer,
|
||||
G_TYPE_INT, ICO_ALPHA_THRESHOLD,
|
||||
G_TYPE_NONE);
|
||||
|
||||
pika_value_array_unref (return_vals);
|
||||
|
||||
pixbuf = pika_drawable_get_thumbnail (PIKA_DRAWABLE (tmp_layer),
|
||||
MIN (w, 128), MIN (h, 128),
|
||||
PIKA_PIXBUF_SMALL_CHECKS);
|
||||
|
||||
pika_image_delete (tmp_image);
|
||||
}
|
||||
else
|
||||
{
|
||||
pixbuf = pika_drawable_get_thumbnail (layer,
|
||||
MIN (w, 128), MIN (h, 128),
|
||||
PIKA_PIXBUF_SMALL_CHECKS);
|
||||
}
|
||||
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
|
||||
void
|
||||
ico_dialog_add_icon (GtkWidget *dialog,
|
||||
PikaDrawable *layer,
|
||||
gint layer_num)
|
||||
{
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *preview;
|
||||
gchar key[ICO_MAXBUF];
|
||||
IcoSaveInfo *info;
|
||||
|
||||
vbox = g_object_get_data (G_OBJECT (dialog), "icons_vbox");
|
||||
info = g_object_get_data (G_OBJECT (dialog), "save_info");
|
||||
|
||||
preview = ico_preview_new (layer);
|
||||
hbox = ico_create_icon_hbox (preview, layer, layer_num, info);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
/* Let's make the hbox accessible through the layer ID */
|
||||
g_snprintf (key, sizeof (key), "layer_%i_hbox",
|
||||
pika_item_get_id (PIKA_ITEM (layer)));
|
||||
g_object_set_data (G_OBJECT (dialog), key, hbox);
|
||||
|
||||
ico_dialog_update_icon_preview (dialog, layer, info->depths[layer_num]);
|
||||
|
||||
ico_dialog_check_compat (dialog, info);
|
||||
|
||||
/* Cursor */
|
||||
if (info->is_cursor)
|
||||
{
|
||||
GtkWidget *grid;
|
||||
GtkAdjustment *adj;
|
||||
GtkWidget *spinbutton;
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
|
||||
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), grid, FALSE, FALSE, 0);
|
||||
gtk_widget_show (grid);
|
||||
|
||||
adj = (GtkAdjustment *)
|
||||
gtk_adjustment_new (info->hot_spot_x[layer_num], 0,
|
||||
G_MAXUINT16, 1, 10, 0);
|
||||
spinbutton = pika_spin_button_new (adj, 1.0, 0);
|
||||
gtk_spin_button_set_range (GTK_SPIN_BUTTON (spinbutton),
|
||||
0, G_MAXUINT16);
|
||||
pika_grid_attach_aligned (GTK_GRID (grid), 0, 0,
|
||||
_("Hot spot _X:"), 0.0, 0.5,
|
||||
spinbutton, 1);
|
||||
g_signal_connect (adj, "value-changed",
|
||||
G_CALLBACK (pika_int_adjustment_update),
|
||||
&info->hot_spot_x[layer_num]);
|
||||
|
||||
adj = (GtkAdjustment *)
|
||||
gtk_adjustment_new (info->hot_spot_y[layer_num], 0,
|
||||
G_MAXUINT16, 1, 10, 0);
|
||||
spinbutton = pika_spin_button_new (adj, 1.0, 0);
|
||||
gtk_spin_button_set_range (GTK_SPIN_BUTTON (spinbutton),
|
||||
0, G_MAXUINT16);
|
||||
pika_grid_attach_aligned (GTK_GRID (grid), 0, 1,
|
||||
_("Hot spot _Y:"), 0.0, 0.5,
|
||||
spinbutton, 1);
|
||||
g_signal_connect (adj, "value-changed",
|
||||
G_CALLBACK (pika_int_adjustment_update),
|
||||
&info->hot_spot_y[layer_num]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ico_dialog_bpp_changed (GtkWidget *combo,
|
||||
GObject *hbox)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
PikaDrawable *layer;
|
||||
gint layer_num;
|
||||
gint bpp;
|
||||
IcoSaveInfo *info;
|
||||
|
||||
dialog = gtk_widget_get_toplevel (combo);
|
||||
|
||||
pika_int_combo_box_get_active (PIKA_INT_COMBO_BOX (combo), &bpp);
|
||||
|
||||
info = g_object_get_data (G_OBJECT (dialog), "save_info");
|
||||
g_assert (info);
|
||||
|
||||
layer = g_object_get_data (hbox, "icon_layer");
|
||||
layer_num = GPOINTER_TO_INT (g_object_get_data (hbox, "icon_layer_num"));
|
||||
|
||||
/* Update vector entry for later when we're actually saving,
|
||||
and update the preview right away ... */
|
||||
info->depths[layer_num] = bpp;
|
||||
ico_dialog_update_icon_preview (dialog, layer, bpp);
|
||||
}
|
||||
|
||||
static void
|
||||
ico_dialog_toggle_compress (GtkWidget *checkbox,
|
||||
GObject *hbox)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
gint layer_num;
|
||||
IcoSaveInfo *info;
|
||||
|
||||
dialog = gtk_widget_get_toplevel (checkbox);
|
||||
|
||||
info = g_object_get_data (G_OBJECT (dialog), "save_info");
|
||||
g_assert (info);
|
||||
layer_num = GPOINTER_TO_INT (g_object_get_data (hbox, "icon_layer_num"));
|
||||
|
||||
/* Update vector entry for later when we're actually saving */
|
||||
info->compress[layer_num] =
|
||||
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox));
|
||||
|
||||
ico_dialog_check_compat (dialog, info);
|
||||
}
|
||||
|
||||
static void
|
||||
ico_dialog_check_compat (GtkWidget *dialog,
|
||||
IcoSaveInfo *info)
|
||||
{
|
||||
GtkWidget *warning;
|
||||
GList *iter;
|
||||
gboolean warn = FALSE;
|
||||
gint i;
|
||||
|
||||
for (iter = info->layers, i = 0; iter; iter = iter->next, i++)
|
||||
{
|
||||
if (pika_drawable_get_width (iter->data) > 255 ||
|
||||
pika_drawable_get_height (iter->data) > 255 ||
|
||||
info->compress[i])
|
||||
{
|
||||
warn = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
warning = g_object_get_data (G_OBJECT (dialog), "warning");
|
||||
|
||||
gtk_widget_set_visible (warning, warn);
|
||||
}
|
||||
|
||||
static void
|
||||
ico_dialog_ani_update_inam (GtkEntry *entry,
|
||||
gpointer data)
|
||||
{
|
||||
AniSaveInfo *ani_info;
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_widget_get_toplevel (GTK_WIDGET (entry));
|
||||
|
||||
ani_info = g_object_get_data (G_OBJECT (dialog), "save_ani_info");
|
||||
ani_info->inam = g_strdup_printf ("%s", gtk_entry_get_text (entry));
|
||||
}
|
||||
|
||||
static void
|
||||
ico_dialog_ani_update_iart (GtkEntry *entry,
|
||||
gpointer data)
|
||||
{
|
||||
AniSaveInfo *ani_info;
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_widget_get_toplevel (GTK_WIDGET (entry));
|
||||
|
||||
ani_info = g_object_get_data (G_OBJECT (dialog), "save_ani_info");
|
||||
ani_info->iart = g_strdup_printf ("%s", gtk_entry_get_text (entry));
|
||||
}
|
36
plug-ins/file-ico/ico-dialog.h
Normal file
36
plug-ins/file-ico/ico-dialog.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* PIKA Plug-in for Windows Icon files.
|
||||
* Copyright (C) 2002 Christian Kreibich <christian@whoop.org>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ICO_DIALOG_H__
|
||||
#define __ICO_DIALOG_H__
|
||||
|
||||
|
||||
GtkWidget * ico_dialog_new (IcoSaveInfo *info,
|
||||
AniFileHeader *ani_header,
|
||||
AniSaveInfo *ani_info);
|
||||
void ico_dialog_add_icon (GtkWidget *dialog,
|
||||
PikaDrawable *layer,
|
||||
gint layer_num);
|
||||
|
||||
#endif /* __ICO_DIALOG_H__ */
|
1091
plug-ins/file-ico/ico-load.c
Normal file
1091
plug-ins/file-ico/ico-load.c
Normal file
File diff suppressed because it is too large
Load Diff
55
plug-ins/file-ico/ico-load.h
Normal file
55
plug-ins/file-ico/ico-load.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* PIKA Plug-in for Windows Icon files.
|
||||
* Copyright (C) 2002 Christian Kreibich <christian@whoop.org>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ICO_LOAD_H__
|
||||
#define __ICO_LOAD_H__
|
||||
|
||||
|
||||
PikaImage * ico_load_image (GFile *file,
|
||||
gint32 *file_offset,
|
||||
gint frame_num,
|
||||
GError **error);
|
||||
PikaImage * ani_load_image (GFile *file,
|
||||
gboolean load_thumb,
|
||||
gint *width,
|
||||
gint *height,
|
||||
GError **error);
|
||||
PikaImage * ico_load_thumbnail_image (GFile *file,
|
||||
gint *width,
|
||||
gint *height,
|
||||
gint32 file_offset,
|
||||
GError **error);
|
||||
|
||||
gint ico_get_bit_from_data (const guint8 *data,
|
||||
gint line_width,
|
||||
gint bit);
|
||||
gint ico_get_nibble_from_data (const guint8 *data,
|
||||
gint line_width,
|
||||
gint nibble);
|
||||
gint ico_get_byte_from_data (const guint8 *data,
|
||||
gint line_width,
|
||||
gint byte);
|
||||
|
||||
|
||||
#endif /* __ICO_LOAD_H__ */
|
1713
plug-ins/file-ico/ico-save.c
Normal file
1713
plug-ins/file-ico/ico-save.c
Normal file
File diff suppressed because it is too large
Load Diff
58
plug-ins/file-ico/ico-save.h
Normal file
58
plug-ins/file-ico/ico-save.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* PIKA Plug-in for Windows Icon files.
|
||||
* Copyright (C) 2002 Christian Kreibich <christian@whoop.org>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ICO_SAVE_H__
|
||||
#define __ICO_SAVE_H__
|
||||
|
||||
|
||||
PikaPDBStatusType ico_save_image (GFile *file,
|
||||
PikaImage *image,
|
||||
gint32 run_mode,
|
||||
GError **error);
|
||||
|
||||
PikaPDBStatusType cur_save_image (GFile *file,
|
||||
PikaImage *image,
|
||||
gint32 run_mode,
|
||||
gint *n_hot_spot_x,
|
||||
gint32 **hot_spot_x,
|
||||
gint *n_hot_spot_y,
|
||||
gint32 **hot_spot_y,
|
||||
GError **error);
|
||||
|
||||
PikaPDBStatusType ani_save_image (GFile *file,
|
||||
PikaImage *image,
|
||||
gint32 run_mode,
|
||||
gint *n_hot_spot_x,
|
||||
gint32 **hot_spot_x,
|
||||
gint *n_hot_spot_y,
|
||||
gint32 **hot_spot_y,
|
||||
AniFileHeader *header,
|
||||
AniSaveInfo *ani_info,
|
||||
GError **error);
|
||||
|
||||
gboolean ico_cmap_contains_black (const guchar *cmap,
|
||||
gint num_colors);
|
||||
|
||||
|
||||
#endif /* __ICO_SAVE_H__ */
|
780
plug-ins/file-ico/ico.c
Normal file
780
plug-ins/file-ico/ico.c
Normal file
@ -0,0 +1,780 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* PIKA Plug-in for Windows Icon files.
|
||||
* Copyright (C) 2002 Christian Kreibich <christian@whoop.org>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include <libpika/pika.h>
|
||||
#include <libpika/pikaui.h>
|
||||
|
||||
/* #define ICO_DBG */
|
||||
|
||||
#include "ico.h"
|
||||
#include "ico-load.h"
|
||||
#include "ico-save.h"
|
||||
|
||||
#include "libpika/stdplugins-intl.h"
|
||||
|
||||
#define LOAD_PROC "file-ico-load"
|
||||
#define LOAD_CUR_PROC "file-cur-load"
|
||||
#define LOAD_ANI_PROC "file-ani-load"
|
||||
#define LOAD_THUMB_PROC "file-ico-load-thumb"
|
||||
#define LOAD_ANI_THUMB_PROC "file-ani-load-thumb"
|
||||
#define SAVE_PROC "file-ico-save"
|
||||
#define SAVE_CUR_PROC "file-cur-save"
|
||||
#define SAVE_ANI_PROC "file-ani-save"
|
||||
|
||||
|
||||
typedef struct _Ico Ico;
|
||||
typedef struct _IcoClass IcoClass;
|
||||
|
||||
struct _Ico
|
||||
{
|
||||
PikaPlugIn parent_instance;
|
||||
};
|
||||
|
||||
struct _IcoClass
|
||||
{
|
||||
PikaPlugInClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
#define ICO_TYPE (ico_get_type ())
|
||||
#define ICO (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ICO_TYPE, Ico))
|
||||
|
||||
GType ico_get_type (void) G_GNUC_CONST;
|
||||
|
||||
static GList * ico_query_procedures (PikaPlugIn *plug_in);
|
||||
static PikaProcedure * ico_create_procedure (PikaPlugIn *plug_in,
|
||||
const gchar *name);
|
||||
|
||||
static PikaValueArray * ico_load (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
GFile *file,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data);
|
||||
static PikaValueArray * ani_load (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
GFile *file,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data);
|
||||
static PikaValueArray * ico_load_thumb (PikaProcedure *procedure,
|
||||
GFile *file,
|
||||
gint size,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data);
|
||||
static PikaValueArray * ani_load_thumb (PikaProcedure *procedure,
|
||||
GFile *file,
|
||||
gint size,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data);
|
||||
static PikaValueArray * ico_save (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
PikaImage *image,
|
||||
gint n_drawables,
|
||||
PikaDrawable **drawables,
|
||||
GFile *file,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data);
|
||||
static PikaValueArray * cur_save (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
PikaImage *image,
|
||||
gint n_drawables,
|
||||
PikaDrawable **drawables,
|
||||
GFile *file,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data);
|
||||
static PikaValueArray * ani_save (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
PikaImage *image,
|
||||
gint n_drawables,
|
||||
PikaDrawable **drawables,
|
||||
GFile *file,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (Ico, ico, PIKA_TYPE_PLUG_IN)
|
||||
|
||||
PIKA_MAIN (ICO_TYPE)
|
||||
DEFINE_STD_SET_I18N
|
||||
|
||||
|
||||
static void
|
||||
ico_class_init (IcoClass *klass)
|
||||
{
|
||||
PikaPlugInClass *plug_in_class = PIKA_PLUG_IN_CLASS (klass);
|
||||
|
||||
plug_in_class->query_procedures = ico_query_procedures;
|
||||
plug_in_class->create_procedure = ico_create_procedure;
|
||||
plug_in_class->set_i18n = STD_SET_I18N;
|
||||
}
|
||||
|
||||
static void
|
||||
ico_init (Ico *ico)
|
||||
{
|
||||
}
|
||||
|
||||
static GList *
|
||||
ico_query_procedures (PikaPlugIn *plug_in)
|
||||
{
|
||||
GList *list = NULL;
|
||||
|
||||
list = g_list_append (list, g_strdup (LOAD_THUMB_PROC));
|
||||
list = g_list_append (list, g_strdup (LOAD_ANI_THUMB_PROC));
|
||||
list = g_list_append (list, g_strdup (LOAD_PROC));
|
||||
list = g_list_append (list, g_strdup (LOAD_CUR_PROC));
|
||||
list = g_list_append (list, g_strdup (LOAD_ANI_PROC));
|
||||
list = g_list_append (list, g_strdup (SAVE_PROC));
|
||||
list = g_list_append (list, g_strdup (SAVE_CUR_PROC));
|
||||
list = g_list_append (list, g_strdup (SAVE_ANI_PROC));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static PikaProcedure *
|
||||
ico_create_procedure (PikaPlugIn *plug_in,
|
||||
const gchar *name)
|
||||
{
|
||||
PikaProcedure *procedure = NULL;
|
||||
|
||||
if (! strcmp (name, LOAD_PROC))
|
||||
{
|
||||
procedure = pika_load_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_PLUGIN,
|
||||
ico_load, NULL, NULL);
|
||||
|
||||
pika_procedure_set_menu_label (procedure, _("Microsoft Windows icon"));
|
||||
pika_procedure_set_icon_name (procedure, PIKA_ICON_BRUSH);
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
"Loads files of Windows ICO file format",
|
||||
"Loads files of Windows ICO file format",
|
||||
name);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Christian Kreibich <christian@whoop.org>",
|
||||
"Christian Kreibich <christian@whoop.org>",
|
||||
"2002");
|
||||
|
||||
pika_file_procedure_set_mime_types (PIKA_FILE_PROCEDURE (procedure),
|
||||
"image/x-ico");
|
||||
pika_file_procedure_set_extensions (PIKA_FILE_PROCEDURE (procedure),
|
||||
"ico");
|
||||
/* We do not set magics here, since that interferes with certain types
|
||||
of TGA images. */
|
||||
|
||||
pika_load_procedure_set_thumbnail_loader (PIKA_LOAD_PROCEDURE (procedure),
|
||||
LOAD_THUMB_PROC);
|
||||
}
|
||||
else if (! strcmp (name, LOAD_CUR_PROC))
|
||||
{
|
||||
procedure = pika_load_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_PLUGIN,
|
||||
ico_load, NULL, NULL);
|
||||
|
||||
pika_procedure_set_menu_label (procedure, _("Microsoft Windows cursor"));
|
||||
pika_procedure_set_icon_name (procedure, PIKA_ICON_BRUSH);
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
"Loads files of Windows CUR file format",
|
||||
"Loads files of Windows CUR file format",
|
||||
name);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Christian Kreibich <christian@whoop.org>, "
|
||||
"Nikc M.",
|
||||
"Christian Kreibich <christian@whoop.org>, "
|
||||
"Nikc M.",
|
||||
"2002-2022");
|
||||
|
||||
pika_file_procedure_set_mime_types (PIKA_FILE_PROCEDURE (procedure),
|
||||
"image/vnd.microsoft.icon");
|
||||
pika_file_procedure_set_extensions (PIKA_FILE_PROCEDURE (procedure),
|
||||
"cur");
|
||||
/* We do not set magics here, since that interferes with certain types
|
||||
of TGA images. */
|
||||
|
||||
pika_load_procedure_set_thumbnail_loader (PIKA_LOAD_PROCEDURE (procedure),
|
||||
LOAD_THUMB_PROC);
|
||||
}
|
||||
else if (! strcmp (name, LOAD_ANI_PROC))
|
||||
{
|
||||
procedure = pika_load_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_PLUGIN,
|
||||
ani_load, NULL, NULL);
|
||||
|
||||
pika_procedure_set_menu_label (procedure, _("Microsoft Windows animated cursor"));
|
||||
pika_procedure_set_icon_name (procedure, PIKA_ICON_BRUSH);
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
_("Loads files of Windows ANI file format"),
|
||||
"Loads files of Windows ANI file format",
|
||||
name);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Christian Kreibich <christian@whoop.org>, "
|
||||
"James Huang, Alex S.",
|
||||
"Christian Kreibich <christian@whoop.org>, "
|
||||
"James Huang, Alex S.",
|
||||
"2007-2022");
|
||||
|
||||
pika_file_procedure_set_mime_types (PIKA_FILE_PROCEDURE (procedure),
|
||||
"application/x-navi-animation");
|
||||
pika_file_procedure_set_extensions (PIKA_FILE_PROCEDURE (procedure),
|
||||
"ani");
|
||||
pika_file_procedure_set_magics (PIKA_FILE_PROCEDURE (procedure),
|
||||
"8,string,ACON");
|
||||
|
||||
pika_load_procedure_set_thumbnail_loader (PIKA_LOAD_PROCEDURE (procedure),
|
||||
LOAD_ANI_THUMB_PROC);
|
||||
}
|
||||
else if (! strcmp (name, LOAD_THUMB_PROC))
|
||||
{
|
||||
procedure = pika_thumbnail_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_PLUGIN,
|
||||
ico_load_thumb, NULL, NULL);
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
"Loads a preview from a Windows ICO or CUR files",
|
||||
"",
|
||||
name);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Dom Lachowicz, Sven Neumann",
|
||||
"Sven Neumann <sven@gimp.org>",
|
||||
"2005");
|
||||
}
|
||||
else if (! strcmp (name, LOAD_ANI_THUMB_PROC))
|
||||
{
|
||||
procedure = pika_thumbnail_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_PLUGIN,
|
||||
ani_load_thumb, NULL, NULL);
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
_("Loads a preview from a Windows ANI files"),
|
||||
"",
|
||||
name);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Dom Lachowicz, Sven Neumann, James Huang, "
|
||||
"Alex S.",
|
||||
"Dom Lachowicz, "
|
||||
"Sven Neumann <sven@gimp.org>, "
|
||||
"James Huang, Alex S.",
|
||||
"2007-2022");
|
||||
}
|
||||
else if (! strcmp (name, SAVE_PROC))
|
||||
{
|
||||
procedure = pika_save_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_PLUGIN,
|
||||
ico_save, NULL, NULL);
|
||||
|
||||
pika_procedure_set_image_types (procedure, "*");
|
||||
|
||||
pika_procedure_set_menu_label (procedure, _("Microsoft Windows icon"));
|
||||
pika_procedure_set_icon_name (procedure, PIKA_ICON_BRUSH);
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
"Saves files in Windows ICO file format",
|
||||
"Saves files in Windows ICO file format",
|
||||
name);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Christian Kreibich <christian@whoop.org>",
|
||||
"Christian Kreibich <christian@whoop.org>",
|
||||
"2002");
|
||||
|
||||
pika_file_procedure_set_mime_types (PIKA_FILE_PROCEDURE (procedure),
|
||||
"image/x-ico");
|
||||
pika_file_procedure_set_extensions (PIKA_FILE_PROCEDURE (procedure),
|
||||
"ico");
|
||||
}
|
||||
else if (! strcmp (name, SAVE_CUR_PROC))
|
||||
{
|
||||
procedure = pika_save_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_PLUGIN,
|
||||
cur_save, NULL, NULL);
|
||||
|
||||
pika_procedure_set_image_types (procedure, "*");
|
||||
|
||||
pika_procedure_set_menu_label (procedure, _("Microsoft Windows cursor"));
|
||||
pika_procedure_set_icon_name (procedure, PIKA_ICON_BRUSH);
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
"Saves files in Windows CUR file format",
|
||||
"Saves files in Windows CUR file format",
|
||||
name);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Christian Kreibich <christian@whoop.org>, "
|
||||
"Nikc M.",
|
||||
"Christian Kreibich <christian@whoop.org>, "
|
||||
"Nikc M.",
|
||||
"2002-2022");
|
||||
|
||||
pika_file_procedure_set_mime_types (PIKA_FILE_PROCEDURE (procedure),
|
||||
"image/vnd.microsoft.icon");
|
||||
pika_file_procedure_set_extensions (PIKA_FILE_PROCEDURE (procedure),
|
||||
"cur");
|
||||
|
||||
PIKA_PROC_ARG_INT (procedure, "n-hot-spot-x",
|
||||
"Number of hot spot's X coordinates",
|
||||
"Number of hot spot's X coordinates",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE);
|
||||
PIKA_PROC_ARG_INT32_ARRAY (procedure, "hot-spot-x",
|
||||
"Hot spot X",
|
||||
"X coordinates of hot spot (one per layer)",
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
PIKA_PROC_ARG_INT (procedure, "n-hot-spot-y",
|
||||
"Number of hot spot's Y coordinates",
|
||||
"Number of hot spot's Y coordinates",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE);
|
||||
PIKA_PROC_ARG_INT32_ARRAY (procedure, "hot-spot-y",
|
||||
"Hot spot Y",
|
||||
"Y coordinates of hot spot (one per layer)",
|
||||
G_PARAM_READWRITE);
|
||||
}
|
||||
else if (! strcmp (name, SAVE_ANI_PROC))
|
||||
{
|
||||
procedure = pika_save_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_PLUGIN,
|
||||
ani_save, NULL, NULL);
|
||||
|
||||
pika_procedure_set_image_types (procedure, "*");
|
||||
|
||||
pika_procedure_set_menu_label (procedure, _("Microsoft Windows animated cursor"));
|
||||
pika_procedure_set_icon_name (procedure, PIKA_ICON_BRUSH);
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
_("Saves files in Windows ANI file format"),
|
||||
_("Saves files in Windows ANI file format"),
|
||||
name);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
"Christian Kreibich <christian@whoop.org>, "
|
||||
"James Huang, Alex S.",
|
||||
"Christian Kreibich <christian@whoop.org>, "
|
||||
"James Huang, Alex S.",
|
||||
"2007-2022");
|
||||
|
||||
pika_file_procedure_set_mime_types (PIKA_FILE_PROCEDURE (procedure),
|
||||
"application/x-navi-animation");
|
||||
pika_file_procedure_set_extensions (PIKA_FILE_PROCEDURE (procedure),
|
||||
"ani");
|
||||
|
||||
PIKA_PROC_ARG_STRING (procedure, "cursor-name",
|
||||
"Cursor Name",
|
||||
_("Cursor Name (Optional)"),
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
PIKA_PROC_ARG_STRING (procedure, "author-name",
|
||||
"Cursor Author",
|
||||
_("Cursor Author (Optional)"),
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
PIKA_PROC_ARG_INT (procedure, "default-delay",
|
||||
"Default delay",
|
||||
"Default delay between frames "
|
||||
"in jiffies (1/60 of a second)",
|
||||
0, G_MAXINT, 8,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
PIKA_PROC_ARG_INT (procedure, "n-hot-spot-x",
|
||||
"Number of hot spot's X coordinates",
|
||||
"Number of hot spot's X coordinates",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE);
|
||||
PIKA_PROC_ARG_INT32_ARRAY (procedure, "hot-spot-x",
|
||||
"Hot spot X",
|
||||
"X coordinates of hot spot (one per layer)",
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
PIKA_PROC_ARG_INT (procedure, "n-hot-spot-y",
|
||||
"Number of hot spot's Y coordinates",
|
||||
"Number of hot spot's Y coordinates",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE);
|
||||
PIKA_PROC_ARG_INT32_ARRAY (procedure, "hot-spot-y",
|
||||
"Hot spot Y",
|
||||
"Y coordinates of hot spot (one per layer)",
|
||||
G_PARAM_READWRITE);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
static PikaValueArray *
|
||||
ico_load (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
GFile *file,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data)
|
||||
{
|
||||
PikaValueArray *return_vals;
|
||||
PikaImage *image;
|
||||
GError *error = NULL;
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
image = ico_load_image (file, NULL, -1, &error);
|
||||
|
||||
if (! image)
|
||||
return pika_procedure_new_return_values (procedure,
|
||||
PIKA_PDB_EXECUTION_ERROR,
|
||||
error);
|
||||
|
||||
return_vals = pika_procedure_new_return_values (procedure,
|
||||
PIKA_PDB_SUCCESS,
|
||||
NULL);
|
||||
|
||||
PIKA_VALUES_SET_IMAGE (return_vals, 1, image);
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
|
||||
static PikaValueArray *
|
||||
ani_load (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
GFile *file,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data)
|
||||
{
|
||||
PikaValueArray *return_vals;
|
||||
PikaImage *image;
|
||||
GError *error = NULL;
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
image = ani_load_image (file, FALSE,
|
||||
NULL, NULL, &error);
|
||||
|
||||
if (! image)
|
||||
return pika_procedure_new_return_values (procedure,
|
||||
PIKA_PDB_EXECUTION_ERROR,
|
||||
error);
|
||||
|
||||
return_vals = pika_procedure_new_return_values (procedure,
|
||||
PIKA_PDB_SUCCESS,
|
||||
NULL);
|
||||
|
||||
PIKA_VALUES_SET_IMAGE (return_vals, 1, image);
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
|
||||
static PikaValueArray *
|
||||
ico_load_thumb (PikaProcedure *procedure,
|
||||
GFile *file,
|
||||
gint size,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data)
|
||||
{
|
||||
PikaValueArray *return_vals;
|
||||
gint width;
|
||||
gint height;
|
||||
PikaImage *image;
|
||||
GError *error = NULL;
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
width = size;
|
||||
height = size;
|
||||
|
||||
image = ico_load_thumbnail_image (file,
|
||||
&width, &height, 0, &error);
|
||||
|
||||
if (! image)
|
||||
return pika_procedure_new_return_values (procedure,
|
||||
PIKA_PDB_EXECUTION_ERROR,
|
||||
error);
|
||||
|
||||
return_vals = pika_procedure_new_return_values (procedure,
|
||||
PIKA_PDB_SUCCESS,
|
||||
NULL);
|
||||
|
||||
PIKA_VALUES_SET_IMAGE (return_vals, 1, image);
|
||||
PIKA_VALUES_SET_INT (return_vals, 2, width);
|
||||
PIKA_VALUES_SET_INT (return_vals, 3, height);
|
||||
|
||||
pika_value_array_truncate (return_vals, 4);
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
|
||||
static PikaValueArray *
|
||||
ani_load_thumb (PikaProcedure *procedure,
|
||||
GFile *file,
|
||||
gint size,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data)
|
||||
{
|
||||
PikaValueArray *return_vals;
|
||||
gint width;
|
||||
gint height;
|
||||
PikaImage *image;
|
||||
GError *error = NULL;
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
width = size;
|
||||
height = size;
|
||||
|
||||
image = ani_load_image (file, TRUE,
|
||||
&width, &height, &error);
|
||||
|
||||
if (! image)
|
||||
return pika_procedure_new_return_values (procedure,
|
||||
PIKA_PDB_EXECUTION_ERROR,
|
||||
error);
|
||||
|
||||
return_vals = pika_procedure_new_return_values (procedure,
|
||||
PIKA_PDB_SUCCESS,
|
||||
NULL);
|
||||
|
||||
PIKA_VALUES_SET_IMAGE (return_vals, 1, image);
|
||||
PIKA_VALUES_SET_INT (return_vals, 2, width);
|
||||
PIKA_VALUES_SET_INT (return_vals, 3, height);
|
||||
|
||||
pika_value_array_truncate (return_vals, 4);
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
|
||||
static PikaValueArray *
|
||||
ico_save (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
PikaImage *image,
|
||||
gint n_drawables,
|
||||
PikaDrawable **drawables,
|
||||
GFile *file,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data)
|
||||
{
|
||||
PikaPDBStatusType status;
|
||||
GError *error = NULL;
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
status = ico_save_image (file, image, run_mode, &error);
|
||||
|
||||
return pika_procedure_new_return_values (procedure, status, error);
|
||||
}
|
||||
|
||||
static PikaValueArray *
|
||||
cur_save (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
PikaImage *image,
|
||||
gint n_drawables,
|
||||
PikaDrawable **drawables,
|
||||
GFile *file,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data)
|
||||
{
|
||||
PikaProcedureConfig *config;
|
||||
PikaPDBStatusType status;
|
||||
GError *error = NULL;
|
||||
gint32 *hot_spot_x = NULL;
|
||||
gint32 *hot_spot_y = NULL;
|
||||
gint n_hot_spot_x = 0;
|
||||
gint n_hot_spot_y = 0;
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
config = pika_procedure_create_config (procedure);
|
||||
pika_procedure_config_begin_run (config, image, run_mode, args);
|
||||
|
||||
g_object_get (config,
|
||||
"n-hot-spot-x", &n_hot_spot_x,
|
||||
"n-hot-spot-y", &n_hot_spot_y,
|
||||
"hot-spot-x", &hot_spot_x,
|
||||
"hot-spot-y", &hot_spot_y,
|
||||
NULL);
|
||||
|
||||
status = cur_save_image (file, image, run_mode,
|
||||
&n_hot_spot_x, &hot_spot_x,
|
||||
&n_hot_spot_y, &hot_spot_y,
|
||||
&error);
|
||||
|
||||
if (status == PIKA_PDB_SUCCESS)
|
||||
{
|
||||
/* XXX: seems libpikaconfig is not able to serialize
|
||||
* PikaInt32Array args yet anyway. Still leave this here for now,
|
||||
* as reminder of missing feature when we see the warnings.
|
||||
*/
|
||||
g_object_set (config,
|
||||
"n-hot-spot-x", n_hot_spot_x,
|
||||
"n-hot-spot-y", n_hot_spot_y,
|
||||
/*"hot-spot-x", hot_spot_x,*/
|
||||
/*"hot-spot-y", hot_spot_y,*/
|
||||
NULL);
|
||||
g_free (hot_spot_x);
|
||||
g_free (hot_spot_y);
|
||||
}
|
||||
|
||||
pika_procedure_config_end_run (config, status);
|
||||
g_object_unref (config);
|
||||
|
||||
return pika_procedure_new_return_values (procedure, status, error);
|
||||
}
|
||||
|
||||
static PikaValueArray *
|
||||
ani_save (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
PikaImage *image,
|
||||
gint n_drawables,
|
||||
PikaDrawable **drawables,
|
||||
GFile *file,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data)
|
||||
{
|
||||
PikaProcedureConfig *config;
|
||||
PikaPDBStatusType status;
|
||||
GError *error = NULL;
|
||||
gchar *inam = NULL;
|
||||
gchar *iart = NULL;
|
||||
gint jif_rate = 0;
|
||||
gint32 *hot_spot_x = NULL;
|
||||
gint32 *hot_spot_y = NULL;
|
||||
gint n_hot_spot_x = 0;
|
||||
gint n_hot_spot_y = 0;
|
||||
AniFileHeader header;
|
||||
AniSaveInfo ani_info;
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
config = pika_procedure_create_config (procedure);
|
||||
pika_procedure_config_begin_run (config, image, run_mode, args);
|
||||
|
||||
g_object_get (config,
|
||||
"cursor-name", &inam,
|
||||
"author-name", &iart,
|
||||
"default-delay", &jif_rate,
|
||||
"n-hot-spot-x", &n_hot_spot_x,
|
||||
"n-hot-spot-y", &n_hot_spot_y,
|
||||
"hot-spot-x", &hot_spot_x,
|
||||
"hot-spot-y", &hot_spot_y,
|
||||
NULL);
|
||||
|
||||
/* Jiffies (1/60th of a second) used if rate chunk not present. */
|
||||
header.jif_rate = jif_rate;
|
||||
ani_info.inam = inam;
|
||||
ani_info.iart = iart;
|
||||
|
||||
status = ani_save_image (file, image, run_mode,
|
||||
&n_hot_spot_x, &hot_spot_x,
|
||||
&n_hot_spot_y, &hot_spot_y,
|
||||
&header, &ani_info, &error);
|
||||
|
||||
if (status == PIKA_PDB_SUCCESS)
|
||||
{
|
||||
/* XXX: seems libpikaconfig is not able to serialize
|
||||
* PikaInt32Array args yet anyway. Still leave this here for now,
|
||||
* as reminder of missing feature when we see the warnings.
|
||||
*/
|
||||
g_object_set (config,
|
||||
"cursor-name", NULL,
|
||||
"author-name", NULL,
|
||||
"default-delay", header.jif_rate,
|
||||
"n-hot-spot-x", n_hot_spot_x,
|
||||
"n-hot-spot-y", n_hot_spot_y,
|
||||
/*"hot-spot-x", hot_spot_x,*/
|
||||
/*"hot-spot-y", hot_spot_y,*/
|
||||
NULL);
|
||||
g_free (hot_spot_x);
|
||||
g_free (hot_spot_y);
|
||||
|
||||
g_free (inam);
|
||||
g_free (iart);
|
||||
g_free (ani_info.inam);
|
||||
g_free (ani_info.iart);
|
||||
memset (&ani_info, 0, sizeof (AniSaveInfo));
|
||||
}
|
||||
|
||||
pika_procedure_config_end_run (config, status);
|
||||
g_object_unref (config);
|
||||
|
||||
return pika_procedure_new_return_values (procedure, status, error);
|
||||
}
|
||||
|
||||
gint
|
||||
ico_rowstride (gint width,
|
||||
gint bpp)
|
||||
{
|
||||
switch (bpp)
|
||||
{
|
||||
case 1:
|
||||
if ((width % 32) == 0)
|
||||
return width / 8;
|
||||
else
|
||||
return 4 * (width/32 + 1);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if ((width % 8) == 0)
|
||||
return width / 2;
|
||||
else
|
||||
return 4 * (width/8 + 1);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
if ((width % 4) == 0)
|
||||
return width;
|
||||
else
|
||||
return 4 * (width/4 + 1);
|
||||
break;
|
||||
|
||||
case 24:
|
||||
if (((width*3) % 4) == 0)
|
||||
return width * 3;
|
||||
else
|
||||
return 4 * (width*3/4+1);
|
||||
|
||||
case 32:
|
||||
return width * 4;
|
||||
|
||||
default:
|
||||
g_warning ("invalid bitrate: %d\n", bpp);
|
||||
g_assert_not_reached ();
|
||||
return width * (bpp/8);
|
||||
}
|
||||
}
|
||||
|
||||
guint8 *
|
||||
ico_alloc_map (gint width,
|
||||
gint height,
|
||||
gint bpp,
|
||||
gint *length)
|
||||
{
|
||||
gint len = 0;
|
||||
guint8 *map = NULL;
|
||||
|
||||
len = ico_rowstride (width, bpp) * height;
|
||||
|
||||
*length = len;
|
||||
map = g_new0 (guint8, len);
|
||||
|
||||
return map;
|
||||
}
|
134
plug-ins/file-ico/ico.h
Normal file
134
plug-ins/file-ico/ico.h
Normal file
@ -0,0 +1,134 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* PIKA Plug-in for Windows Icon files.
|
||||
* Copyright (C) 2002 Christian Kreibich <christian@whoop.org>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ICO_H__
|
||||
#define __ICO_H__
|
||||
|
||||
|
||||
#ifdef ICO_DBG
|
||||
#define D(x) \
|
||||
{ \
|
||||
printf("ICO plugin: "); \
|
||||
printf x; \
|
||||
}
|
||||
#else
|
||||
#define D(x)
|
||||
#endif
|
||||
|
||||
#define PLUG_IN_BINARY "file-ico"
|
||||
#define PLUG_IN_ROLE "pika-file-ico"
|
||||
|
||||
#define ICO_PNG_MAGIC 0x474e5089
|
||||
#define ICO_ALPHA_THRESHOLD 127
|
||||
#define ICO_MAXBUF 4096
|
||||
|
||||
|
||||
typedef struct _IcoFileHeader
|
||||
{
|
||||
guint16 reserved;
|
||||
guint16 resource_type;
|
||||
guint16 icon_count;
|
||||
} IcoFileHeader;
|
||||
|
||||
typedef struct _IcoFileEntry
|
||||
{
|
||||
guint8 width; /* Width of icon in pixels */
|
||||
guint8 height; /* Height of icon in pixels */
|
||||
guint8 num_colors; /* Number of colors of paletted image */
|
||||
guint8 reserved; /* Must be 0 */
|
||||
guint16 planes; /* Must be 1 for ICO, x position of hot spot for CUR */
|
||||
guint16 bpp; /* 1, 4, 8, 24 or 32 bits per pixel for ICO, y position of hot spot for CUR */
|
||||
guint32 size; /* Size of icon (including data header) */
|
||||
guint32 offset; /* Absolute offset of data in a file */
|
||||
} IcoFileEntry;
|
||||
|
||||
typedef struct _IcoFileDataHeader
|
||||
{
|
||||
guint32 header_size; /* 40 bytes */
|
||||
guint32 width; /* Width of image in pixels */
|
||||
guint32 height; /* Height of image in pixels */
|
||||
guint16 planes; /* Must be 1 */
|
||||
guint16 bpp;
|
||||
guint32 compression; /* Not used for icons */
|
||||
guint32 image_size; /* Size of image (without this header) */
|
||||
guint32 x_res;
|
||||
guint32 y_res;
|
||||
guint32 used_clrs;
|
||||
guint32 important_clrs;
|
||||
} IcoFileDataHeader;
|
||||
|
||||
|
||||
typedef struct _IcoLoadInfo
|
||||
{
|
||||
guint width;
|
||||
guint height;
|
||||
gint bpp;
|
||||
gint planes;
|
||||
gint offset;
|
||||
gint size;
|
||||
} IcoLoadInfo;
|
||||
|
||||
typedef struct _IcoSaveInfo
|
||||
{
|
||||
gint *depths;
|
||||
gint *default_depths;
|
||||
gboolean *compress;
|
||||
GList *layers;
|
||||
gint num_icons;
|
||||
gboolean is_cursor;
|
||||
gint *hot_spot_x;
|
||||
gint *hot_spot_y;
|
||||
} IcoSaveInfo;
|
||||
|
||||
typedef struct _AniFileHeader
|
||||
{
|
||||
guint32 bSizeOf; /* Number of bytes in AniFileHeader (36 bytes) */
|
||||
guint32 frames; /* Number of unique icons in this cursor */
|
||||
guint32 steps; /* Number of Blits before the animation cycles */
|
||||
guint32 x, y; /* Reserved, must be zero. */
|
||||
guint32 bpp, planes; /* Reserved, must be zero. */
|
||||
guint32 jif_rate; /* Default Jiffies (1/60th of a second) if rate chunk's not present. */
|
||||
guint32 flags; /* Animation Flag */
|
||||
} AniFileHeader;
|
||||
|
||||
typedef struct _AniSaveInfo
|
||||
{
|
||||
gchar *inam; /* Cursor name metadata */
|
||||
gchar *iart; /* Author name metadata */
|
||||
} AniSaveInfo;
|
||||
|
||||
/* Miscellaneous helper functions below: */
|
||||
|
||||
gint ico_rowstride (gint width,
|
||||
gint bpp);
|
||||
|
||||
/* Allocates a 32-bit padded bitmap for various color depths.
|
||||
Returns the allocated array directly, and the length of the
|
||||
array in the len pointer */
|
||||
guint8 * ico_alloc_map (gint width,
|
||||
gint height,
|
||||
gint bpp,
|
||||
gint *len);
|
||||
|
||||
#endif /* __ICO_H__ */
|
32
plug-ins/file-ico/meson.build
Normal file
32
plug-ins/file-ico/meson.build
Normal file
@ -0,0 +1,32 @@
|
||||
plugin_name = 'file-ico'
|
||||
|
||||
plugin_sources = [
|
||||
'ico-dialog.c',
|
||||
'ico-load.c',
|
||||
'ico-save.c',
|
||||
'ico.c',
|
||||
]
|
||||
|
||||
if platform_windows
|
||||
plugin_sources += windows.compile_resources(
|
||||
pika_plugins_rc,
|
||||
args: [
|
||||
'--define', 'ORIGINALFILENAME_STR="@0@"'.format(plugin_name+'.exe'),
|
||||
'--define', 'INTERNALNAME_STR="@0@"' .format(plugin_name),
|
||||
'--define', 'TOP_SRCDIR="@0@"' .format(meson.project_source_root()),
|
||||
],
|
||||
include_directories: [
|
||||
rootInclude, appInclude,
|
||||
],
|
||||
)
|
||||
endif
|
||||
|
||||
executable(plugin_name,
|
||||
plugin_sources,
|
||||
dependencies: [
|
||||
libpikaui_dep,
|
||||
libpng,
|
||||
],
|
||||
install: true,
|
||||
install_dir: pikaplugindir / 'plug-ins' / plugin_name,
|
||||
)
|
Reference in New Issue
Block a user