2023-09-26 00:35:21 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* This is a plug-in for PIKA.
|
|
|
|
*
|
|
|
|
* Generates images containing vector type drawings.
|
|
|
|
*
|
|
|
|
* Copyright (C) 1997 Andy Thomas alt@picnic.demon.co.uk
|
|
|
|
*
|
|
|
|
* 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 <libpika/pika.h>
|
|
|
|
#include <libpika/pikaui.h>
|
|
|
|
|
|
|
|
#include "libpika/stdplugins-intl.h"
|
|
|
|
|
|
|
|
#include "gfig.h"
|
|
|
|
#include "gfig-dobject.h"
|
|
|
|
#include "gfig-style.h"
|
|
|
|
|
|
|
|
|
|
|
|
static void gfig_read_resource (gchar **text,
|
|
|
|
gint nitems,
|
|
|
|
const gchar *tag,
|
|
|
|
PikaResource **style_entry,
|
|
|
|
GType resource_type);
|
|
|
|
|
|
|
|
static void gfig_read_parameter_int (gchar **text,
|
|
|
|
gint nitems,
|
|
|
|
const gchar *name,
|
|
|
|
gint *style_entry);
|
|
|
|
|
|
|
|
static void gfig_read_parameter_double (gchar **text,
|
|
|
|
gint nitems,
|
|
|
|
const gchar *name,
|
|
|
|
gdouble *style_entry);
|
|
|
|
|
|
|
|
static void gfig_read_parameter_pika_rgb (gchar **text,
|
|
|
|
gint nitems,
|
|
|
|
const gchar *name,
|
|
|
|
PikaRGB *style_entry);
|
|
|
|
|
|
|
|
/* From a style string, read a resource name,
|
|
|
|
* create a resource object, and put it in
|
|
|
|
* given entry of a style.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
gfig_read_resource (gchar **text,
|
|
|
|
gint nitems,
|
|
|
|
const gchar *tag,
|
|
|
|
PikaResource **style_entry,
|
|
|
|
GType resource_type)
|
|
|
|
{
|
|
|
|
gint n = 0;
|
|
|
|
gchar *ptr;
|
|
|
|
gchar *tmpstr;
|
|
|
|
|
|
|
|
while (n < nitems)
|
|
|
|
{
|
|
|
|
ptr = strchr (text[n], ':');
|
|
|
|
if (ptr)
|
|
|
|
{
|
|
|
|
tmpstr = g_strndup (text[n], ptr - text[n]);
|
|
|
|
ptr++;
|
|
|
|
if (!strcmp (tmpstr, tag))
|
|
|
|
{
|
|
|
|
const gchar *resource_name = g_strchug (ptr);
|
|
|
|
|
|
|
|
*style_entry = pika_resource_get_by_name (resource_type,
|
|
|
|
resource_name);
|
|
|
|
g_free (tmpstr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (tmpstr);
|
|
|
|
}
|
|
|
|
|
|
|
|
++n;
|
|
|
|
}
|
|
|
|
|
|
|
|
*style_entry = NULL;
|
|
|
|
g_message ("Parameter '%s' not found", tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
gfig_read_parameter_int (gchar **text,
|
|
|
|
gint nitems,
|
|
|
|
const gchar *name,
|
|
|
|
gint *style_entry)
|
|
|
|
{
|
|
|
|
gint n = 0;
|
|
|
|
gchar *ptr;
|
|
|
|
gchar *tmpstr;
|
|
|
|
|
|
|
|
*style_entry = 0;
|
|
|
|
|
|
|
|
while (n < nitems)
|
|
|
|
{
|
|
|
|
ptr = strchr (text[n], ':');
|
|
|
|
if (ptr)
|
|
|
|
{
|
|
|
|
tmpstr = g_strndup (text[n], ptr - text[n]);
|
|
|
|
ptr++;
|
|
|
|
if (!strcmp (tmpstr, name))
|
|
|
|
{
|
|
|
|
*style_entry = atoi (g_strchug (ptr));
|
|
|
|
g_free (tmpstr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
g_free (tmpstr);
|
|
|
|
}
|
|
|
|
++n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gfig_read_parameter_double (gchar **text,
|
|
|
|
gint nitems,
|
|
|
|
const gchar *name,
|
|
|
|
gdouble *style_entry)
|
|
|
|
{
|
|
|
|
gint n = 0;
|
|
|
|
gchar *ptr;
|
|
|
|
gchar *endptr;
|
|
|
|
gchar *tmpstr;
|
|
|
|
|
|
|
|
*style_entry = 0.;
|
|
|
|
|
|
|
|
while (n < nitems)
|
|
|
|
{
|
|
|
|
ptr = strchr (text[n], ':');
|
|
|
|
if (ptr)
|
|
|
|
{
|
|
|
|
tmpstr = g_strndup (text[n], ptr - text[n]);
|
|
|
|
ptr++;
|
|
|
|
if (!strcmp (tmpstr, name))
|
|
|
|
{
|
|
|
|
*style_entry = g_ascii_strtod (g_strchug (ptr), &endptr);
|
|
|
|
g_free (tmpstr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
g_free (tmpstr);
|
|
|
|
}
|
|
|
|
++n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gfig_read_parameter_pika_rgb (gchar **text,
|
|
|
|
gint nitems,
|
|
|
|
const gchar *name,
|
|
|
|
PikaRGB *style_entry)
|
|
|
|
{
|
|
|
|
gint n = 0;
|
|
|
|
gchar *ptr;
|
|
|
|
gchar *tmpstr;
|
|
|
|
gchar *endptr;
|
|
|
|
gchar fmt_str[32];
|
|
|
|
gchar colorstr_r[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar colorstr_g[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar colorstr_b[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar colorstr_a[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
|
|
|
|
style_entry->r = style_entry->g = style_entry->b = style_entry->a = 0.;
|
|
|
|
|
|
|
|
snprintf (fmt_str, sizeof (fmt_str),
|
|
|
|
"%%%" G_GSIZE_FORMAT "s"
|
|
|
|
" %%%" G_GSIZE_FORMAT "s"
|
|
|
|
" %%%" G_GSIZE_FORMAT "s"
|
|
|
|
" %%%" G_GSIZE_FORMAT "s",
|
|
|
|
sizeof (colorstr_r) - 1, sizeof (colorstr_g) - 1,
|
|
|
|
sizeof (colorstr_b) - 1, sizeof (colorstr_a) - 1);
|
|
|
|
|
|
|
|
while (n < nitems)
|
|
|
|
{
|
|
|
|
ptr = strchr (text[n], ':');
|
|
|
|
if (ptr)
|
|
|
|
{
|
|
|
|
tmpstr = g_strndup (text[n], ptr - text[n]);
|
|
|
|
ptr++;
|
|
|
|
if (!strcmp (tmpstr, name))
|
|
|
|
{
|
|
|
|
sscanf (ptr, fmt_str,
|
|
|
|
colorstr_r, colorstr_g, colorstr_b, colorstr_a);
|
|
|
|
style_entry->r = g_ascii_strtod (colorstr_r, &endptr);
|
|
|
|
style_entry->g = g_ascii_strtod (colorstr_g, &endptr);
|
|
|
|
style_entry->b = g_ascii_strtod (colorstr_b, &endptr);
|
|
|
|
style_entry->a = g_ascii_strtod (colorstr_a, &endptr);
|
|
|
|
g_free (tmpstr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
g_free (tmpstr);
|
|
|
|
}
|
|
|
|
++n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MAX_STYLE_TEXT_ENTRIES 100
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gfig_load_style (Style *style,
|
|
|
|
FILE *fp)
|
|
|
|
{
|
|
|
|
gulong offset;
|
|
|
|
gchar load_buf2[MAX_LOAD_LINE];
|
|
|
|
gchar *style_text[MAX_STYLE_TEXT_ENTRIES];
|
|
|
|
gint nitems = 0;
|
|
|
|
gint value;
|
|
|
|
gint k;
|
|
|
|
gchar name[100];
|
|
|
|
|
|
|
|
offset = ftell (fp);
|
|
|
|
|
|
|
|
get_line (load_buf2, MAX_LOAD_LINE, fp, 0);
|
|
|
|
/* nuke final > and preserve spaces in name */
|
|
|
|
if (1 != sscanf (load_buf2, "<Style %99[^>]>", name))
|
|
|
|
{
|
|
|
|
/* no style data, copy default style and fail silently */
|
|
|
|
gfig_style_copy (style, &gfig_context->default_style, "default style");
|
|
|
|
fseek (fp, offset, SEEK_SET);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("Loading style '%s' -- ", name);
|
|
|
|
|
|
|
|
style->name = g_strdup (name);
|
|
|
|
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
get_line (load_buf2, MAX_LOAD_LINE, fp, 0);
|
|
|
|
if (!strcmp (load_buf2, "</Style>") || feof (fp))
|
|
|
|
break;
|
|
|
|
|
|
|
|
style_text[nitems] = g_strdup (load_buf2);
|
|
|
|
nitems++;
|
|
|
|
|
|
|
|
if (nitems >= MAX_STYLE_TEXT_ENTRIES)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (feof (fp) || (nitems >= MAX_STYLE_TEXT_ENTRIES))
|
|
|
|
{
|
|
|
|
g_message ("Error reading style data");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gfig_read_resource (style_text, nitems, "BrushName",
|
|
|
|
(PikaResource**) &style->brush, PIKA_TYPE_BRUSH);
|
|
|
|
|
|
|
|
if (style->brush == NULL)
|
|
|
|
g_message ("Error loading style: missing brush.");
|
|
|
|
|
|
|
|
gfig_read_resource (style_text, nitems, "Pattern",
|
|
|
|
(PikaResource**) &style->pattern, PIKA_TYPE_PATTERN);
|
|
|
|
gfig_read_resource (style_text, nitems, "Gradient",
|
|
|
|
(PikaResource**) &style->gradient, PIKA_TYPE_GRADIENT);
|
|
|
|
|
|
|
|
gfig_read_parameter_pika_rgb (style_text, nitems, "Foreground",
|
|
|
|
&style->foreground);
|
|
|
|
gfig_read_parameter_pika_rgb (style_text, nitems, "Background",
|
|
|
|
&style->background);
|
|
|
|
|
|
|
|
gfig_read_parameter_int (style_text, nitems, "FillType", &value);
|
|
|
|
style->fill_type = value;
|
|
|
|
|
|
|
|
gfig_read_parameter_int (style_text, nitems, "PaintType", &value);
|
|
|
|
style->paint_type = value;
|
|
|
|
|
|
|
|
gfig_read_parameter_double (style_text, nitems, "FillOpacity",
|
|
|
|
&style->fill_opacity);
|
|
|
|
|
|
|
|
for (k = 0; k < nitems; k++)
|
|
|
|
{
|
|
|
|
g_free (style_text[k]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("done\n");
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gfig_skip_style (Style *style,
|
|
|
|
FILE *fp)
|
|
|
|
{
|
|
|
|
gulong offset;
|
|
|
|
gchar load_buf2[MAX_LOAD_LINE];
|
|
|
|
|
|
|
|
offset = ftell (fp);
|
|
|
|
|
|
|
|
get_line (load_buf2, MAX_LOAD_LINE, fp, 0);
|
|
|
|
if (strncmp (load_buf2, "<Style ", 7))
|
|
|
|
{
|
|
|
|
/* no style data */
|
|
|
|
fseek (fp, offset, SEEK_SET);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
get_line (load_buf2, MAX_LOAD_LINE, fp, 0);
|
|
|
|
if (!strcmp (load_buf2, "</Style>") || feof (fp))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (feof (fp))
|
|
|
|
{
|
|
|
|
g_message ("Error trying to skip style data");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: need to make this load a list of styles if there are more than one.
|
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
gfig_load_styles (GFigObj *gfig,
|
|
|
|
FILE *fp)
|
|
|
|
{
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("Loading global styles -- ");
|
|
|
|
|
|
|
|
/* currently we only have the default style */
|
|
|
|
gfig_load_style (&gfig_context->default_style, fp);
|
|
|
|
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("done\n");
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfig_save_style (Style *style,
|
|
|
|
GString *string)
|
|
|
|
{
|
|
|
|
gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar buffer_r[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar buffer_g[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar buffer_b[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar buffer_a[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gint blen = G_ASCII_DTOSTR_BUF_SIZE;
|
|
|
|
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("Saving style %s, brush name '%s'\n", style->name,
|
|
|
|
pika_resource_get_name (PIKA_RESOURCE (style->brush)));
|
|
|
|
|
|
|
|
g_string_append_printf (string, "<Style %s>\n", style->name);
|
|
|
|
g_string_append_printf (string, "BrushName: %s\n",
|
|
|
|
pika_resource_get_name (PIKA_RESOURCE (style->brush)));
|
|
|
|
if (!style->brush)
|
|
|
|
g_message ("Error saving style %s: saving NULL for brush name", style->name);
|
|
|
|
|
|
|
|
g_string_append_printf (string, "PaintType: %d\n", style->paint_type);
|
|
|
|
|
|
|
|
g_string_append_printf (string, "FillType: %d\n", style->fill_type);
|
|
|
|
|
|
|
|
g_string_append_printf (string, "FillOpacity: %s\n",
|
|
|
|
g_ascii_dtostr (buffer, blen, style->fill_opacity));
|
|
|
|
|
|
|
|
g_string_append_printf (string, "Pattern: %s\n",
|
|
|
|
pika_resource_get_name (PIKA_RESOURCE (style->pattern)));
|
|
|
|
g_string_append_printf (string, "Gradient: %s\n",
|
|
|
|
pika_resource_get_name (PIKA_RESOURCE (style->gradient)));
|
|
|
|
|
|
|
|
g_string_append_printf (string, "Foreground: %s %s %s %s\n",
|
|
|
|
g_ascii_dtostr (buffer_r, blen, style->foreground.r),
|
|
|
|
g_ascii_dtostr (buffer_g, blen, style->foreground.g),
|
|
|
|
g_ascii_dtostr (buffer_b, blen, style->foreground.b),
|
|
|
|
g_ascii_dtostr (buffer_a, blen, style->foreground.a));
|
|
|
|
|
|
|
|
g_string_append_printf (string, "Background: %s %s %s %s\n",
|
|
|
|
g_ascii_dtostr (buffer_r, blen, style->background.r),
|
|
|
|
g_ascii_dtostr (buffer_g, blen, style->background.g),
|
|
|
|
g_ascii_dtostr (buffer_b, blen, style->background.b),
|
|
|
|
g_ascii_dtostr (buffer_a, blen, style->background.a));
|
|
|
|
|
|
|
|
g_string_append_printf (string, "</Style>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfig_style_save_as_attributes (Style *style,
|
|
|
|
GString *string)
|
|
|
|
{
|
|
|
|
gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar buffer_r[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar buffer_g[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar buffer_b[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar buffer_a[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gint blen = G_ASCII_DTOSTR_BUF_SIZE;
|
|
|
|
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("Saving style %s as attributes\n", style->name);
|
|
|
|
|
|
|
|
/* Tags must match the ones written, see below in the code. */
|
|
|
|
g_string_append_printf (string, "BrushName=\"%s\" ",
|
|
|
|
pika_resource_get_name (PIKA_RESOURCE (style->brush)));
|
|
|
|
/* Why only brush and not pattern and gradient? */
|
|
|
|
|
|
|
|
g_string_append_printf (string, "Foreground=\"%s %s %s %s\" ",
|
|
|
|
g_ascii_dtostr (buffer_r, blen, style->foreground.r),
|
|
|
|
g_ascii_dtostr (buffer_g, blen, style->foreground.g),
|
|
|
|
g_ascii_dtostr (buffer_b, blen, style->foreground.b),
|
|
|
|
g_ascii_dtostr (buffer_a, blen, style->foreground.a));
|
|
|
|
|
|
|
|
g_string_append_printf (string, "Background=\"%s %s %s %s\" ",
|
|
|
|
g_ascii_dtostr (buffer_r, blen, style->background.r),
|
|
|
|
g_ascii_dtostr (buffer_g, blen, style->background.g),
|
|
|
|
g_ascii_dtostr (buffer_b, blen, style->background.b),
|
|
|
|
g_ascii_dtostr (buffer_a, blen, style->background.a));
|
|
|
|
|
|
|
|
g_string_append_printf (string, "FillType=%d ", style->fill_type);
|
|
|
|
|
|
|
|
g_string_append_printf (string, "PaintType=%d ", style->paint_type);
|
|
|
|
|
|
|
|
g_string_append_printf (string, "FillOpacity=%s ",
|
|
|
|
g_ascii_dtostr (buffer, blen, style->fill_opacity));
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfig_save_styles (GString *string)
|
|
|
|
{
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("Saving global styles.\n");
|
|
|
|
|
|
|
|
gfig_save_style (&gfig_context->default_style, string);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* set_foreground_callback() is the callback for the Foreground color select
|
|
|
|
* widget. It reads the color from the widget, and applies this color to the
|
|
|
|
* current style. It then produces a repaint (which will be suppressed if
|
|
|
|
* gfig_context->enable_repaint is FALSE).
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
set_foreground_callback (PikaColorButton *button,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
PikaRGB color2;
|
|
|
|
Style *current_style;
|
|
|
|
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("Setting foreground color from color selector\n");
|
|
|
|
|
|
|
|
current_style = gfig_context_get_current_style ();
|
|
|
|
|
|
|
|
pika_color_button_get_color (button, &color2);
|
|
|
|
|
|
|
|
pika_rgba_set (¤t_style->foreground,
|
|
|
|
color2.r, color2.g, color2.b, color2.a);
|
|
|
|
|
|
|
|
gfig_paint_callback ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
set_background_callback (PikaColorButton *button,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
PikaRGB color2;
|
|
|
|
Style *current_style;
|
|
|
|
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("Setting background color from color selector\n");
|
|
|
|
|
|
|
|
current_style = gfig_context_get_current_style ();
|
|
|
|
|
|
|
|
pika_color_button_get_color (button, &color2);
|
|
|
|
pika_rgba_set (¤t_style->background,
|
|
|
|
color2.r, color2.g, color2.b, color2.a);
|
|
|
|
|
|
|
|
gfig_paint_callback ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
set_paint_type_callback (GtkToggleButton *toggle,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
gboolean paint_type;
|
|
|
|
Style *current_style;
|
|
|
|
|
|
|
|
current_style = gfig_context_get_current_style ();
|
|
|
|
paint_type = gtk_toggle_button_get_active (toggle);
|
|
|
|
current_style->paint_type = paint_type;
|
|
|
|
gfig_paint_callback ();
|
|
|
|
|
|
|
|
gtk_widget_set_sensitive (GTK_WIDGET (data), paint_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* gfig_brush_changed_callback() is the callback for the brush
|
|
|
|
* selector widget. It receives the brush from the widget, and
|
|
|
|
* sets the brush in the current style, as well as the gfig_context->bdesc
|
|
|
|
* values. It then produces a repaint (which will be suppressed if
|
|
|
|
* gfig_context->enable_repaint is FALSE).
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
gfig_brush_changed_callback (gpointer user_data,
|
|
|
|
PikaBrush *brush,
|
|
|
|
gboolean dialog_closing)
|
|
|
|
{
|
|
|
|
Style *current_style;
|
|
|
|
|
|
|
|
current_style = gfig_context_get_current_style ();
|
|
|
|
current_style->brush = brush;
|
|
|
|
|
|
|
|
/* this will soon be unneeded. How soon? */
|
|
|
|
set_context_bdesc (brush);
|
|
|
|
|
|
|
|
pika_context_set_brush (brush);
|
|
|
|
pika_context_set_brush_default_size ();
|
|
|
|
|
|
|
|
gfig_paint_callback ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfig_pattern_changed_callback (gpointer user_data,
|
|
|
|
PikaPattern *pattern,
|
|
|
|
gboolean dialog_closing)
|
|
|
|
{
|
|
|
|
Style *current_style;
|
|
|
|
|
|
|
|
current_style = gfig_context_get_current_style ();
|
|
|
|
current_style->pattern = pattern;
|
|
|
|
|
|
|
|
gfig_paint_callback ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfig_gradient_changed_callback (gpointer user_data,
|
|
|
|
PikaGradient *gradient,
|
|
|
|
gboolean dialog_closing)
|
|
|
|
{
|
|
|
|
Style *current_style;
|
|
|
|
|
|
|
|
current_style = gfig_context_get_current_style ();
|
|
|
|
current_style->gradient = gradient;
|
|
|
|
|
|
|
|
gfig_paint_callback ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfig_rgba_copy (PikaRGB *color1,
|
|
|
|
PikaRGB *color2)
|
|
|
|
{
|
|
|
|
color1->r = color2->r;
|
|
|
|
color1->g = color2->g;
|
|
|
|
color1->b = color2->b;
|
|
|
|
color1->a = color2->a;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfig_style_copy (Style *style1,
|
|
|
|
Style *style0,
|
|
|
|
const gchar *name)
|
|
|
|
{
|
|
|
|
if (name)
|
|
|
|
style1->name = g_strdup (name);
|
|
|
|
else
|
|
|
|
g_message ("Error: name is NULL in gfig_style_copy.");
|
|
|
|
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("Copying style %s as style %s\n", style0->name, name);
|
|
|
|
|
|
|
|
gfig_rgba_copy (&style1->foreground, &style0->foreground);
|
|
|
|
gfig_rgba_copy (&style1->background, &style0->background);
|
|
|
|
|
|
|
|
if (!style0->brush)
|
|
|
|
g_message ("Error copying style %s: brush name is NULL.", style0->name);
|
|
|
|
|
|
|
|
/* ownership issues ? */
|
|
|
|
style1->brush = style0->brush;
|
|
|
|
style1->gradient = style0->gradient;
|
|
|
|
style1->pattern = style0->pattern;
|
|
|
|
|
|
|
|
style1->fill_type = style0->fill_type;
|
|
|
|
style1->fill_opacity = style0->fill_opacity;
|
|
|
|
style1->paint_type = style0->paint_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* gfig_style_apply() applies the settings from the specified style to
|
|
|
|
* the PIKA core. It does not change any widgets, and does not cause
|
|
|
|
* a repaint.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
gfig_style_apply (Style *style)
|
|
|
|
{
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("Applying style '%s' -- ", style->name);
|
|
|
|
|
|
|
|
pika_context_set_foreground (&style->foreground);
|
|
|
|
|
|
|
|
pika_context_set_background (&style->background);
|
|
|
|
|
|
|
|
if (! pika_context_set_brush (style->brush))
|
|
|
|
g_message ("Style apply: Failed to set brush to '%s' in style '%s'",
|
|
|
|
pika_resource_get_name (PIKA_RESOURCE (style->brush)),
|
|
|
|
style->name);
|
|
|
|
|
|
|
|
pika_context_set_brush_default_size ();
|
|
|
|
|
|
|
|
g_assert (style->pattern != NULL);
|
|
|
|
pika_context_set_pattern (style->pattern);
|
|
|
|
|
|
|
|
pika_context_set_gradient (style->gradient);
|
|
|
|
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("done.\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* gfig_read_pika_style() reads the style settings from the Pika core,
|
|
|
|
* and applies them to the specified style, giving that style the
|
|
|
|
* specified name. This is mainly useful as a way of initializing
|
|
|
|
* a style. The function does not cause a repaint.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
gfig_read_pika_style (Style *style,
|
|
|
|
const gchar *name)
|
|
|
|
{
|
|
|
|
gint dummy;
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
g_message ("Error: name is NULL in gfig_read_pika_style.");
|
|
|
|
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("Reading Pika settings as style %s\n", name);
|
|
|
|
style->name = g_strdup (name);
|
|
|
|
|
|
|
|
pika_context_get_foreground (&style->foreground);
|
|
|
|
pika_context_get_background (&style->background);
|
|
|
|
|
|
|
|
style->brush = pika_context_get_brush ();
|
|
|
|
style->gradient = pika_context_get_gradient ();
|
|
|
|
style->pattern = pika_context_get_pattern ();
|
|
|
|
|
|
|
|
style->fill_opacity = 100.;
|
|
|
|
|
|
|
|
/* Cache attributes of brush. */
|
|
|
|
pika_brush_get_info (style->brush,
|
|
|
|
&style->brush_width, &style->brush_height,
|
|
|
|
&dummy, &dummy);
|
|
|
|
style->brush_spacing = pika_brush_get_spacing (style->brush);
|
|
|
|
|
|
|
|
set_context_bdesc (style->brush);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* gfig_style_set_content_from_style() sets all of the style control widgets
|
|
|
|
* to values from the specified style. This in turn sets the Pika core's
|
|
|
|
* values to the same things. Repainting is suppressed while this happens,
|
|
|
|
* so calling this function will not produce a repaint.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
gfig_style_set_context_from_style (Style *style)
|
|
|
|
{
|
|
|
|
gboolean enable_repaint;
|
|
|
|
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("Setting context from style '%s' -- ", style->name);
|
|
|
|
|
|
|
|
enable_repaint = gfig_context->enable_repaint;
|
|
|
|
gfig_context->enable_repaint = FALSE;
|
|
|
|
|
|
|
|
pika_color_button_set_color (PIKA_COLOR_BUTTON (gfig_context->fg_color_button),
|
|
|
|
&style->foreground);
|
|
|
|
pika_color_button_set_color (PIKA_COLOR_BUTTON (gfig_context->bg_color_button),
|
|
|
|
&style->background);
|
|
|
|
if (! pika_context_set_brush (style->brush))
|
|
|
|
g_message ("Style from context: Failed to set brush");
|
|
|
|
|
|
|
|
pika_context_set_brush_default_size ();
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
pika_resource_chooser_set_resource (PIKA_RESOURCE_CHOOSER (gfig_context->brush_select),
|
|
|
|
PIKA_RESOURCE (style->brush));
|
2023-09-26 00:35:21 +02:00
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
pika_resource_chooser_set_resource (PIKA_RESOURCE_CHOOSER (gfig_context->pattern_select),
|
|
|
|
PIKA_RESOURCE (style->pattern));
|
2023-09-26 00:35:21 +02:00
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
pika_resource_chooser_set_resource (PIKA_RESOURCE_CHOOSER (gfig_context->gradient_select),
|
|
|
|
PIKA_RESOURCE (style->gradient));
|
2023-09-26 00:35:21 +02:00
|
|
|
|
|
|
|
set_context_bdesc (style->brush);
|
|
|
|
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("done.\n");
|
|
|
|
|
|
|
|
pika_int_combo_box_set_active (PIKA_INT_COMBO_BOX (gfig_context->fillstyle_combo),
|
|
|
|
(gint) style->fill_type);
|
|
|
|
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gfig_context->paint_type_toggle),
|
|
|
|
style->paint_type);
|
|
|
|
gfig_context->enable_repaint = enable_repaint;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* gfig_style_set_style_from_context() sets the values in the specified
|
|
|
|
* style to those that appear in the style control widgets f
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
gfig_style_set_style_from_context (Style *style)
|
|
|
|
{
|
|
|
|
Style *current_style;
|
|
|
|
PikaRGB color;
|
|
|
|
gint value;
|
|
|
|
|
|
|
|
style->name = "object";
|
|
|
|
current_style = gfig_context_get_current_style ();
|
|
|
|
|
|
|
|
pika_color_button_get_color (PIKA_COLOR_BUTTON (gfig_context->fg_color_button),
|
|
|
|
&color);
|
|
|
|
if (gfig_context->debug_styles)
|
|
|
|
g_printerr ("Setting foreground color to %lg %lg %lg\n",
|
|
|
|
color.r, color.g, color.b);
|
|
|
|
|
|
|
|
gfig_rgba_copy (&style->foreground, &color);
|
|
|
|
pika_color_button_get_color (PIKA_COLOR_BUTTON (gfig_context->bg_color_button),
|
|
|
|
&color);
|
|
|
|
gfig_rgba_copy (&style->background, &color);
|
|
|
|
|
|
|
|
/* FIXME: issues of ownership.
|
|
|
|
* A resource is a pointer to an object.
|
|
|
|
* We own each resource object returned by pika_context_get_<resource> and should unref it.
|
|
|
|
* Here this is possibly overwriting a reference that should be unreffed.
|
|
|
|
* Also, this is copying a reference, so we should ref the object.
|
|
|
|
*
|
|
|
|
* For now, its just a plugin, we don't care much about leaks.
|
|
|
|
*/
|
|
|
|
style->brush = current_style->brush;
|
|
|
|
style->pattern = current_style->pattern;
|
|
|
|
style->gradient = current_style->gradient;
|
|
|
|
|
|
|
|
if (pika_int_combo_box_get_active (PIKA_INT_COMBO_BOX (gfig_context->fillstyle_combo), &value))
|
|
|
|
style->fill_type = value;
|
|
|
|
|
|
|
|
/* FIXME when there is an opacity control widget to read */
|
|
|
|
style->fill_opacity = 100.;
|
|
|
|
|
|
|
|
style->paint_type = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gfig_context->paint_type_toggle));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set bdesc from brush. Side effects on gfig_context->bdesc */
|
|
|
|
void
|
|
|
|
set_context_bdesc (PikaBrush *brush)
|
|
|
|
{
|
|
|
|
gint width;
|
|
|
|
gint height;
|
|
|
|
gint dummy;
|
|
|
|
|
|
|
|
g_return_if_fail (brush != NULL);
|
|
|
|
g_return_if_fail (PIKA_IS_BRUSH (brush));
|
|
|
|
|
|
|
|
if (brush && pika_brush_get_info (brush, &width, &height, &dummy, &dummy))
|
|
|
|
{
|
|
|
|
gfig_context->bdesc.brush = brush;
|
|
|
|
gfig_context->bdesc.width = MAX (width, 32);
|
|
|
|
gfig_context->bdesc.height = MAX (height, 32);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_message ("Failed to get brush info");
|
|
|
|
gfig_context->bdesc.width = 48;
|
|
|
|
gfig_context->bdesc.height = 48;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Style *
|
|
|
|
gfig_context_get_current_style (void)
|
|
|
|
{
|
|
|
|
if (gfig_context->selected_obj)
|
|
|
|
return &gfig_context->selected_obj->style;
|
|
|
|
else
|
|
|
|
return &gfig_context->default_style;
|
|
|
|
}
|