2011-05-19 18:47:17 +00:00
|
|
|
/* GTK - The GIMP Toolkit
|
|
|
|
* Copyright (C) 2011 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* Author: Cosimo Cecchi <cosimoc@gnome.org>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-02-27 13:01:10 +00:00
|
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
2011-05-19 18:47:17 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2012-03-28 01:34:19 +00:00
|
|
|
#include "gtkcssshadowvalueprivate.h"
|
2012-01-02 14:44:45 +00:00
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
#include "gtkcssnumbervalueprivate.h"
|
2012-04-03 10:07:53 +00:00
|
|
|
#include "gtkcssrgbavalueprivate.h"
|
2012-01-02 14:44:45 +00:00
|
|
|
#include "gtkstylecontextprivate.h"
|
2012-04-03 10:07:53 +00:00
|
|
|
#include "gtksymboliccolorprivate.h"
|
2011-06-02 00:58:53 +00:00
|
|
|
#include "gtkthemingengineprivate.h"
|
2011-05-20 20:05:57 +00:00
|
|
|
#include "gtkpango.h"
|
2011-05-19 18:47:17 +00:00
|
|
|
|
2012-04-03 09:49:46 +00:00
|
|
|
struct _GtkCssValue {
|
|
|
|
GTK_CSS_VALUE_BASE
|
|
|
|
guint inset :1;
|
2011-05-19 18:47:17 +00:00
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
GtkCssValue *hoffset;
|
|
|
|
GtkCssValue *voffset;
|
|
|
|
GtkCssValue *radius;
|
|
|
|
GtkCssValue *spread;
|
2011-05-19 18:47:17 +00:00
|
|
|
|
2012-04-03 10:07:53 +00:00
|
|
|
GtkCssValue *color;
|
2011-05-19 18:47:17 +00:00
|
|
|
};
|
|
|
|
|
2012-03-27 23:56:57 +00:00
|
|
|
static void
|
|
|
|
gtk_css_value_shadow_free (GtkCssValue *shadow)
|
2011-05-19 18:47:17 +00:00
|
|
|
{
|
2012-04-03 11:29:29 +00:00
|
|
|
_gtk_css_value_unref (shadow->hoffset);
|
|
|
|
_gtk_css_value_unref (shadow->voffset);
|
|
|
|
_gtk_css_value_unref (shadow->radius);
|
|
|
|
_gtk_css_value_unref (shadow->spread);
|
2012-04-03 10:07:53 +00:00
|
|
|
_gtk_css_value_unref (shadow->color);
|
2012-04-03 09:49:46 +00:00
|
|
|
|
2012-03-28 01:31:20 +00:00
|
|
|
g_slice_free (GtkCssValue, shadow);
|
2012-03-27 23:56:57 +00:00
|
|
|
}
|
2011-05-19 18:47:17 +00:00
|
|
|
|
2012-03-27 23:56:57 +00:00
|
|
|
static gboolean
|
|
|
|
gtk_css_value_shadow_equal (const GtkCssValue *shadow1,
|
|
|
|
const GtkCssValue *shadow2)
|
|
|
|
{
|
|
|
|
/* FIXME */
|
|
|
|
return shadow1 == shadow2;
|
2011-05-19 18:47:17 +00:00
|
|
|
}
|
|
|
|
|
2012-03-30 15:47:26 +00:00
|
|
|
static GtkCssValue *
|
|
|
|
gtk_css_value_shadow_transition (GtkCssValue *start,
|
|
|
|
GtkCssValue *end,
|
|
|
|
double progress)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-03-27 23:56:57 +00:00
|
|
|
static void
|
|
|
|
gtk_css_value_shadow_print (const GtkCssValue *shadow,
|
|
|
|
GString *string)
|
2011-05-19 18:47:17 +00:00
|
|
|
{
|
2012-04-03 11:29:29 +00:00
|
|
|
_gtk_css_value_print (shadow->hoffset, string);
|
|
|
|
g_string_append_c (string, ' ');
|
|
|
|
_gtk_css_value_print (shadow->voffset, string);
|
|
|
|
g_string_append_c (string, ' ');
|
|
|
|
if (_gtk_css_number_value_get (shadow->radius, 100) != 0 ||
|
|
|
|
_gtk_css_number_value_get (shadow->spread, 100) != 0)
|
|
|
|
{
|
|
|
|
_gtk_css_value_print (shadow->radius, string);
|
|
|
|
g_string_append_c (string, ' ');
|
|
|
|
}
|
2011-05-19 18:47:17 +00:00
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
if (_gtk_css_number_value_get (shadow->spread, 100) != 0)
|
|
|
|
{
|
|
|
|
_gtk_css_value_print (shadow->spread, string);
|
|
|
|
g_string_append_c (string, ' ');
|
|
|
|
}
|
2011-05-19 18:47:17 +00:00
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
_gtk_css_value_print (shadow->color, string);
|
2011-05-19 18:47:17 +00:00
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
if (shadow->inset)
|
|
|
|
g_string_append (string, " inset");
|
2011-05-19 18:47:17 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-03-27 23:56:57 +00:00
|
|
|
static const GtkCssValueClass GTK_CSS_VALUE_SHADOW = {
|
|
|
|
gtk_css_value_shadow_free,
|
|
|
|
gtk_css_value_shadow_equal,
|
2012-03-30 15:47:26 +00:00
|
|
|
gtk_css_value_shadow_transition,
|
2012-03-27 23:56:57 +00:00
|
|
|
gtk_css_value_shadow_print
|
|
|
|
};
|
|
|
|
|
2012-04-03 09:49:46 +00:00
|
|
|
static GtkCssValue *
|
2012-04-03 11:29:29 +00:00
|
|
|
gtk_css_shadow_value_new (GtkCssValue *hoffset,
|
|
|
|
GtkCssValue *voffset,
|
|
|
|
GtkCssValue *radius,
|
|
|
|
GtkCssValue *spread,
|
|
|
|
gboolean inset,
|
2012-04-03 10:07:53 +00:00
|
|
|
GtkCssValue *color)
|
2012-03-27 23:56:57 +00:00
|
|
|
{
|
2012-04-03 09:49:46 +00:00
|
|
|
GtkCssValue *retval;
|
|
|
|
|
|
|
|
retval = _gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_SHADOW);
|
|
|
|
|
|
|
|
retval->hoffset = hoffset;
|
|
|
|
retval->voffset = voffset;
|
|
|
|
retval->radius = radius;
|
|
|
|
retval->spread = spread;
|
|
|
|
retval->inset = inset;
|
2012-04-03 10:07:53 +00:00
|
|
|
retval->color = color;
|
2012-04-03 09:49:46 +00:00
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
2012-03-27 23:56:57 +00:00
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
static gboolean
|
|
|
|
value_is_done_parsing (GtkCssParser *parser)
|
|
|
|
{
|
|
|
|
return _gtk_css_parser_is_eof (parser) ||
|
|
|
|
_gtk_css_parser_begins_with (parser, ',') ||
|
|
|
|
_gtk_css_parser_begins_with (parser, ';') ||
|
|
|
|
_gtk_css_parser_begins_with (parser, '}');
|
|
|
|
}
|
|
|
|
|
2012-03-28 01:31:20 +00:00
|
|
|
GtkCssValue *
|
|
|
|
_gtk_css_shadow_value_parse (GtkCssParser *parser)
|
2011-05-19 18:47:17 +00:00
|
|
|
{
|
2012-04-03 11:29:29 +00:00
|
|
|
enum {
|
|
|
|
HOFFSET,
|
|
|
|
VOFFSET,
|
|
|
|
RADIUS,
|
|
|
|
SPREAD,
|
|
|
|
COLOR,
|
|
|
|
N_VALUES
|
|
|
|
};
|
|
|
|
GtkCssValue *values[N_VALUES] = { NULL, };
|
|
|
|
gboolean inset;
|
2012-03-28 00:25:22 +00:00
|
|
|
guint i;
|
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
inset = _gtk_css_parser_try (parser, "inset", TRUE);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (values[HOFFSET] == NULL &&
|
|
|
|
_gtk_css_parser_has_number (parser))
|
|
|
|
{
|
|
|
|
values[HOFFSET] = _gtk_css_number_value_parse (parser,
|
|
|
|
GTK_CSS_PARSE_LENGTH
|
|
|
|
| GTK_CSS_NUMBER_AS_PIXELS);
|
|
|
|
if (values[HOFFSET] == NULL)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
values[VOFFSET] = _gtk_css_number_value_parse (parser,
|
|
|
|
GTK_CSS_PARSE_LENGTH
|
|
|
|
| GTK_CSS_NUMBER_AS_PIXELS);
|
|
|
|
if (values[VOFFSET] == NULL)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (_gtk_css_parser_has_number (parser))
|
|
|
|
{
|
|
|
|
values[RADIUS] = _gtk_css_number_value_parse (parser,
|
|
|
|
GTK_CSS_PARSE_LENGTH
|
|
|
|
| GTK_CSS_POSITIVE_ONLY
|
|
|
|
| GTK_CSS_NUMBER_AS_PIXELS);
|
|
|
|
if (values[RADIUS] == NULL)
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
values[RADIUS] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
|
|
|
|
|
|
|
|
if (_gtk_css_parser_has_number (parser))
|
|
|
|
{
|
|
|
|
values[SPREAD] = _gtk_css_number_value_parse (parser,
|
|
|
|
GTK_CSS_PARSE_LENGTH
|
|
|
|
| GTK_CSS_NUMBER_AS_PIXELS);
|
|
|
|
if (values[SPREAD] == NULL)
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
values[SPREAD] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
|
|
|
|
}
|
|
|
|
else if (!inset && _gtk_css_parser_try (parser, "inset", TRUE))
|
|
|
|
{
|
|
|
|
if (values[HOFFSET] == NULL)
|
|
|
|
goto fail;
|
|
|
|
inset = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (values[COLOR] == NULL)
|
|
|
|
{
|
|
|
|
GtkSymbolicColor *symbolic;
|
|
|
|
|
|
|
|
if (_gtk_css_parser_try (parser, "currentcolor", TRUE))
|
|
|
|
symbolic = gtk_symbolic_color_ref (_gtk_symbolic_color_get_current_color ());
|
|
|
|
else
|
|
|
|
symbolic = _gtk_css_parser_read_symbolic_color (parser);
|
|
|
|
if (symbolic == NULL)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
values[COLOR] = _gtk_css_value_new_take_symbolic_color (symbolic);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* We parsed everything and there's still stuff left?
|
|
|
|
* Pretend we didn't notice and let the normal code produce
|
|
|
|
* a 'junk at end of value' error */
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (values[HOFFSET] == NULL || !value_is_done_parsing (parser));
|
|
|
|
|
|
|
|
if (values[COLOR] == NULL)
|
|
|
|
values[COLOR] = _gtk_css_value_new_take_symbolic_color (
|
|
|
|
gtk_symbolic_color_ref (
|
|
|
|
_gtk_symbolic_color_get_current_color ()));
|
|
|
|
|
|
|
|
return gtk_css_shadow_value_new (values[HOFFSET], values[VOFFSET],
|
|
|
|
values[RADIUS], values[SPREAD],
|
|
|
|
inset, values[COLOR]);
|
|
|
|
|
|
|
|
fail:
|
|
|
|
for (i = 0; i < N_VALUES; i++)
|
2012-03-28 00:25:22 +00:00
|
|
|
{
|
2012-04-03 11:29:29 +00:00
|
|
|
if (values[i])
|
|
|
|
_gtk_css_value_unref (values[i]);
|
2012-04-03 09:49:46 +00:00
|
|
|
}
|
2012-03-28 00:25:22 +00:00
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
return NULL;
|
2011-05-19 18:47:17 +00:00
|
|
|
}
|
|
|
|
|
2012-03-28 01:31:20 +00:00
|
|
|
GtkCssValue *
|
|
|
|
_gtk_css_shadow_value_compute (GtkCssValue *shadow,
|
|
|
|
GtkStyleContext *context)
|
2011-05-19 18:47:17 +00:00
|
|
|
{
|
2012-04-03 10:07:53 +00:00
|
|
|
GtkCssValue *color;
|
2011-05-19 18:47:17 +00:00
|
|
|
|
2012-04-03 10:07:53 +00:00
|
|
|
color = _gtk_css_rgba_value_compute_from_symbolic (shadow->color,
|
|
|
|
_gtk_css_value_new_take_symbolic_color (
|
|
|
|
gtk_symbolic_color_ref (
|
|
|
|
_gtk_symbolic_color_get_current_color ())),
|
|
|
|
context,
|
|
|
|
FALSE);
|
2011-05-19 18:47:17 +00:00
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
return gtk_css_shadow_value_new (_gtk_css_number_value_compute (shadow->hoffset, context),
|
|
|
|
_gtk_css_number_value_compute (shadow->voffset, context),
|
|
|
|
_gtk_css_number_value_compute (shadow->radius, context),
|
|
|
|
_gtk_css_number_value_compute (shadow->spread, context),
|
|
|
|
shadow->inset,
|
2012-04-03 10:07:53 +00:00
|
|
|
color);
|
2011-05-19 18:47:17 +00:00
|
|
|
}
|
2011-05-20 20:05:57 +00:00
|
|
|
|
|
|
|
void
|
2012-03-28 01:31:20 +00:00
|
|
|
_gtk_css_shadow_value_paint_layout (const GtkCssValue *shadow,
|
|
|
|
cairo_t *cr,
|
|
|
|
PangoLayout *layout)
|
2011-05-20 20:05:57 +00:00
|
|
|
{
|
2012-04-03 09:49:46 +00:00
|
|
|
g_return_if_fail (shadow->class == >K_CSS_VALUE_SHADOW);
|
2011-05-20 20:05:57 +00:00
|
|
|
|
2011-05-22 02:24:23 +00:00
|
|
|
if (!cairo_has_current_point (cr))
|
|
|
|
cairo_move_to (cr, 0, 0);
|
|
|
|
|
2012-04-03 09:49:46 +00:00
|
|
|
cairo_save (cr);
|
2011-05-20 20:05:57 +00:00
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
cairo_rel_move_to (cr,
|
|
|
|
_gtk_css_number_value_get (shadow->hoffset, 0),
|
|
|
|
_gtk_css_number_value_get (shadow->voffset, 0));
|
2012-04-03 10:07:53 +00:00
|
|
|
gdk_cairo_set_source_rgba (cr, _gtk_css_rgba_value_get_rgba (shadow->color));
|
2012-04-03 09:49:46 +00:00
|
|
|
_gtk_pango_fill_layout (cr, layout);
|
2011-05-20 20:05:57 +00:00
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
cairo_rel_move_to (cr,
|
|
|
|
- _gtk_css_number_value_get (shadow->hoffset, 0),
|
|
|
|
- _gtk_css_number_value_get (shadow->voffset, 0));
|
2012-04-03 09:49:46 +00:00
|
|
|
cairo_restore (cr);
|
2011-05-20 20:05:57 +00:00
|
|
|
}
|
|
|
|
|
2011-05-21 03:51:16 +00:00
|
|
|
void
|
2012-03-28 01:31:20 +00:00
|
|
|
_gtk_css_shadow_value_paint_icon (const GtkCssValue *shadow,
|
|
|
|
cairo_t *cr)
|
2011-05-21 03:51:16 +00:00
|
|
|
{
|
|
|
|
cairo_pattern_t *pattern;
|
|
|
|
|
2012-04-03 09:49:46 +00:00
|
|
|
g_return_if_fail (shadow->class == >K_CSS_VALUE_SHADOW);
|
2011-05-21 03:51:16 +00:00
|
|
|
|
2012-04-03 09:49:46 +00:00
|
|
|
cairo_save (cr);
|
|
|
|
pattern = cairo_pattern_reference (cairo_get_source (cr));
|
2012-04-03 10:07:53 +00:00
|
|
|
gdk_cairo_set_source_rgba (cr, _gtk_css_rgba_value_get_rgba (shadow->color));
|
2011-05-21 03:51:16 +00:00
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
cairo_translate (cr,
|
|
|
|
_gtk_css_number_value_get (shadow->hoffset, 0),
|
|
|
|
_gtk_css_number_value_get (shadow->voffset, 0));
|
2012-04-03 09:49:46 +00:00
|
|
|
cairo_mask (cr, pattern);
|
2011-05-21 03:51:16 +00:00
|
|
|
|
2012-04-03 09:49:46 +00:00
|
|
|
cairo_restore (cr);
|
|
|
|
cairo_pattern_destroy (pattern);
|
2011-05-21 03:51:16 +00:00
|
|
|
}
|
2011-06-06 15:38:45 +00:00
|
|
|
|
|
|
|
void
|
2012-03-28 01:31:20 +00:00
|
|
|
_gtk_css_shadow_value_paint_spinner (const GtkCssValue *shadow,
|
|
|
|
cairo_t *cr,
|
|
|
|
gdouble radius,
|
|
|
|
gdouble progress)
|
2011-06-06 15:38:45 +00:00
|
|
|
{
|
2012-04-03 09:49:46 +00:00
|
|
|
g_return_if_fail (shadow->class == >K_CSS_VALUE_SHADOW);
|
2011-06-06 15:38:45 +00:00
|
|
|
|
2012-04-03 09:49:46 +00:00
|
|
|
cairo_save (cr);
|
2011-06-06 15:38:45 +00:00
|
|
|
|
2012-04-03 11:29:29 +00:00
|
|
|
cairo_translate (cr,
|
|
|
|
_gtk_css_number_value_get (shadow->hoffset, 0),
|
|
|
|
_gtk_css_number_value_get (shadow->voffset, 0));
|
2012-04-03 09:49:46 +00:00
|
|
|
_gtk_theming_engine_paint_spinner (cr,
|
|
|
|
radius, progress,
|
2012-04-03 10:07:53 +00:00
|
|
|
_gtk_css_rgba_value_get_rgba (shadow->color));
|
2011-06-06 15:38:45 +00:00
|
|
|
|
2012-04-03 09:49:46 +00:00
|
|
|
cairo_restore (cr);
|
2011-06-06 15:38:45 +00:00
|
|
|
}
|
2011-06-02 00:58:53 +00:00
|
|
|
|
|
|
|
void
|
2012-03-28 01:31:20 +00:00
|
|
|
_gtk_css_shadow_value_paint_box (const GtkCssValue *shadow,
|
|
|
|
cairo_t *cr,
|
|
|
|
const GtkRoundedBox *padding_box)
|
2011-06-02 00:58:53 +00:00
|
|
|
{
|
|
|
|
GtkRoundedBox box;
|
2012-04-03 11:29:29 +00:00
|
|
|
double spread;
|
2012-04-03 09:49:46 +00:00
|
|
|
|
|
|
|
g_return_if_fail (shadow->class == >K_CSS_VALUE_SHADOW);
|
2011-06-02 00:58:53 +00:00
|
|
|
|
|
|
|
cairo_save (cr);
|
|
|
|
cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
|
|
|
|
|
|
|
|
_gtk_rounded_box_path (padding_box, cr);
|
|
|
|
cairo_clip (cr);
|
|
|
|
|
2012-04-03 09:49:46 +00:00
|
|
|
box = *padding_box;
|
2012-04-03 11:29:29 +00:00
|
|
|
_gtk_rounded_box_move (&box,
|
|
|
|
_gtk_css_number_value_get (shadow->hoffset, 0),
|
|
|
|
_gtk_css_number_value_get (shadow->voffset, 0));
|
|
|
|
spread = _gtk_css_number_value_get (shadow->spread, 0);
|
|
|
|
_gtk_rounded_box_shrink (&box, spread, spread, spread, spread);
|
2011-06-02 00:58:53 +00:00
|
|
|
|
2012-04-03 09:49:46 +00:00
|
|
|
_gtk_rounded_box_path (&box, cr);
|
|
|
|
_gtk_rounded_box_clip_path (padding_box, cr);
|
2011-06-02 00:58:53 +00:00
|
|
|
|
2012-04-03 10:07:53 +00:00
|
|
|
gdk_cairo_set_source_rgba (cr, _gtk_css_rgba_value_get_rgba (shadow->color));
|
2012-04-03 09:49:46 +00:00
|
|
|
cairo_fill (cr);
|
2011-06-02 00:58:53 +00:00
|
|
|
|
|
|
|
cairo_restore (cr);
|
|
|
|
}
|