Compare commits
5 Commits
wip/matthi
...
wip/cosimo
Author | SHA1 | Date | |
---|---|---|---|
|
d525d3d4ec | ||
|
a240d2b3cd | ||
|
ec1bc09183 | ||
|
5e69a9dfb1 | ||
|
973ad918b9 |
@@ -60,6 +60,36 @@ gtk_css_image_real_get_aspect_ratio (GtkCssImage *image)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
gtk_css_image_real_get_surface (GtkCssImage *image,
|
||||
cairo_surface_t *target,
|
||||
int surface_width,
|
||||
int surface_height)
|
||||
{
|
||||
cairo_surface_t *result;
|
||||
cairo_t *cr;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_IMAGE (image), NULL);
|
||||
g_return_val_if_fail (surface_width > 0, NULL);
|
||||
g_return_val_if_fail (surface_height > 0, NULL);
|
||||
|
||||
if (target)
|
||||
result = cairo_surface_create_similar (target,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
surface_width,
|
||||
surface_height);
|
||||
else
|
||||
result = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
surface_width,
|
||||
surface_height);
|
||||
|
||||
cr = cairo_create (result);
|
||||
_gtk_css_image_draw (image, cr, surface_width, surface_height);
|
||||
cairo_destroy (cr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GtkCssImage *
|
||||
gtk_css_image_real_compute (GtkCssImage *image,
|
||||
guint property_id,
|
||||
@@ -99,6 +129,7 @@ _gtk_css_image_class_init (GtkCssImageClass *klass)
|
||||
klass->get_width = gtk_css_image_real_get_width;
|
||||
klass->get_height = gtk_css_image_real_get_height;
|
||||
klass->get_aspect_ratio = gtk_css_image_real_get_aspect_ratio;
|
||||
klass->get_surface = gtk_css_image_real_get_surface;
|
||||
klass->compute = gtk_css_image_real_compute;
|
||||
klass->equal = gtk_css_image_real_equal;
|
||||
klass->transition = gtk_css_image_real_transition;
|
||||
@@ -145,6 +176,21 @@ _gtk_css_image_get_aspect_ratio (GtkCssImage *image)
|
||||
return klass->get_aspect_ratio (image);
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
_gtk_css_image_get_surface (GtkCssImage *image,
|
||||
cairo_surface_t *target,
|
||||
int surface_width,
|
||||
int surface_height)
|
||||
{
|
||||
GtkCssImageClass *klass;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_IMAGE (image), NULL);
|
||||
|
||||
klass = GTK_CSS_IMAGE_GET_CLASS (image);
|
||||
|
||||
return klass->get_surface (image, target, surface_width, surface_height);
|
||||
}
|
||||
|
||||
GtkCssImage *
|
||||
_gtk_css_image_compute (GtkCssImage *image,
|
||||
guint property_id,
|
||||
@@ -377,39 +423,6 @@ _gtk_css_image_get_concrete_size (GtkCssImage *image,
|
||||
}
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
_gtk_css_image_get_surface (GtkCssImage *image,
|
||||
cairo_surface_t *target,
|
||||
int surface_width,
|
||||
int surface_height)
|
||||
{
|
||||
cairo_surface_t *result;
|
||||
cairo_t *cr;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_IMAGE (image), NULL);
|
||||
g_return_val_if_fail (surface_width > 0, NULL);
|
||||
g_return_val_if_fail (surface_height > 0, NULL);
|
||||
|
||||
|
||||
if (target)
|
||||
{
|
||||
result = cairo_surface_create_similar (target,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
surface_width,
|
||||
surface_height);
|
||||
}
|
||||
else
|
||||
result = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
surface_width,
|
||||
surface_height);
|
||||
|
||||
cr = cairo_create (result);
|
||||
_gtk_css_image_draw (image, cr, surface_width, surface_height);
|
||||
cairo_destroy (cr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GType
|
||||
gtk_css_image_get_parser_type (GtkCssParser *parser)
|
||||
{
|
||||
|
@@ -126,7 +126,135 @@ gtk_css_image_linear_compute_start_point (double angle_in_degrees,
|
||||
*x = c / (slope - perpendicular);
|
||||
*y = perpendicular * *x + c;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gtk_css_image_linear_ensure_surface (GtkCssImageLinear *linear,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
if (linear->cached_surface != NULL &&
|
||||
width != cairo_image_surface_get_width (linear->cached_surface) &&
|
||||
height != cairo_image_surface_get_height (linear->cached_surface))
|
||||
{
|
||||
cairo_surface_destroy (linear->cached_surface);
|
||||
linear->cached_surface = NULL;
|
||||
}
|
||||
|
||||
if (linear->cached_surface == NULL)
|
||||
{
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *surface;
|
||||
cairo_pattern_t *pattern;
|
||||
double angle; /* actual angle of the gradiant line in degrees */
|
||||
double x, y; /* coordinates of start point */
|
||||
double length; /* distance in pixels for 100% */
|
||||
double start, end; /* position of first/last point on gradient line - with gradient line being [0, 1] */
|
||||
double offset;
|
||||
int i, last;
|
||||
|
||||
if (_gtk_css_number_value_get_unit (linear->angle) == GTK_CSS_NUMBER)
|
||||
{
|
||||
guint side = _gtk_css_number_value_get (linear->angle, 100);
|
||||
|
||||
/* special casing the regular cases here so we don't get rounding errors */
|
||||
switch (side)
|
||||
{
|
||||
case 1 << GTK_CSS_RIGHT:
|
||||
angle = 90;
|
||||
break;
|
||||
case 1 << GTK_CSS_LEFT:
|
||||
angle = 270;
|
||||
break;
|
||||
case 1 << GTK_CSS_TOP:
|
||||
angle = 0;
|
||||
break;
|
||||
case 1 << GTK_CSS_BOTTOM:
|
||||
angle = 180;
|
||||
break;
|
||||
default:
|
||||
angle = atan2 (side & 1 << GTK_CSS_TOP ? -width : width,
|
||||
side & 1 << GTK_CSS_LEFT ? -height : height);
|
||||
angle = 180 * angle / G_PI + 90;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = _gtk_css_number_value_get (linear->angle, 100);
|
||||
}
|
||||
|
||||
gtk_css_image_linear_compute_start_point (angle,
|
||||
width, height,
|
||||
&x, &y);
|
||||
|
||||
length = sqrt (x * x + y * y);
|
||||
gtk_css_image_linear_get_start_end (linear, length, &start, &end);
|
||||
pattern = cairo_pattern_create_linear (x * (start - 0.5), y * (start - 0.5),
|
||||
x * (end - 0.5), y * (end - 0.5));
|
||||
if (linear->repeating)
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
|
||||
else
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
|
||||
|
||||
offset = start;
|
||||
last = -1;
|
||||
for (i = 0; i < linear->stops->len; i++)
|
||||
{
|
||||
GtkCssImageLinearColorStop *stop;
|
||||
double pos, step;
|
||||
|
||||
stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, i);
|
||||
|
||||
if (stop->offset == NULL)
|
||||
{
|
||||
if (i == 0)
|
||||
pos = 0.0;
|
||||
else if (i + 1 == linear->stops->len)
|
||||
pos = 1.0;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else
|
||||
pos = _gtk_css_number_value_get (stop->offset, length) / length;
|
||||
|
||||
pos = MAX (pos, offset);
|
||||
step = (pos - offset) / (i - last);
|
||||
for (last = last + 1; last <= i; last++)
|
||||
{
|
||||
const GdkRGBA *rgba;
|
||||
|
||||
stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, last);
|
||||
|
||||
rgba = _gtk_css_rgba_value_get_rgba (stop->color);
|
||||
offset += step;
|
||||
|
||||
cairo_pattern_add_color_stop_rgba (pattern,
|
||||
(offset - start) / (end - start),
|
||||
rgba->red,
|
||||
rgba->green,
|
||||
rgba->blue,
|
||||
rgba->alpha);
|
||||
}
|
||||
|
||||
offset = pos;
|
||||
last = i;
|
||||
}
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
width, height);
|
||||
cr = cairo_create (surface);
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_translate (cr, width / 2, height / 2);
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
cairo_pattern_destroy (pattern);
|
||||
|
||||
linear->cached_surface = surface;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_linear_draw (GtkCssImage *image,
|
||||
cairo_t *cr,
|
||||
@@ -134,110 +262,28 @@ gtk_css_image_linear_draw (GtkCssImage *image,
|
||||
double height)
|
||||
{
|
||||
GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
|
||||
cairo_pattern_t *pattern;
|
||||
double angle; /* actual angle of the gradiant line in degrees */
|
||||
double x, y; /* coordinates of start point */
|
||||
double length; /* distance in pixels for 100% */
|
||||
double start, end; /* position of first/last point on gradient line - with gradient line being [0, 1] */
|
||||
double offset;
|
||||
int i, last;
|
||||
|
||||
if (_gtk_css_number_value_get_unit (linear->angle) == GTK_CSS_NUMBER)
|
||||
{
|
||||
guint side = _gtk_css_number_value_get (linear->angle, 100);
|
||||
|
||||
/* special casing the regular cases here so we don't get rounding errors */
|
||||
switch (side)
|
||||
{
|
||||
case 1 << GTK_CSS_RIGHT:
|
||||
angle = 90;
|
||||
break;
|
||||
case 1 << GTK_CSS_LEFT:
|
||||
angle = 270;
|
||||
break;
|
||||
case 1 << GTK_CSS_TOP:
|
||||
angle = 0;
|
||||
break;
|
||||
case 1 << GTK_CSS_BOTTOM:
|
||||
angle = 180;
|
||||
break;
|
||||
default:
|
||||
angle = atan2 (side & 1 << GTK_CSS_TOP ? -width : width,
|
||||
side & 1 << GTK_CSS_LEFT ? -height : height);
|
||||
angle = 180 * angle / G_PI + 90;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = _gtk_css_number_value_get (linear->angle, 100);
|
||||
}
|
||||
|
||||
gtk_css_image_linear_compute_start_point (angle,
|
||||
width, height,
|
||||
&x, &y);
|
||||
|
||||
length = sqrt (x * x + y * y);
|
||||
gtk_css_image_linear_get_start_end (linear, length, &start, &end);
|
||||
pattern = cairo_pattern_create_linear (x * (start - 0.5), y * (start - 0.5),
|
||||
x * (end - 0.5), y * (end - 0.5));
|
||||
if (linear->repeating)
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
|
||||
else
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
|
||||
|
||||
offset = start;
|
||||
last = -1;
|
||||
for (i = 0; i < linear->stops->len; i++)
|
||||
{
|
||||
GtkCssImageLinearColorStop *stop;
|
||||
double pos, step;
|
||||
|
||||
stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, i);
|
||||
|
||||
if (stop->offset == NULL)
|
||||
{
|
||||
if (i == 0)
|
||||
pos = 0.0;
|
||||
else if (i + 1 == linear->stops->len)
|
||||
pos = 1.0;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else
|
||||
pos = _gtk_css_number_value_get (stop->offset, length) / length;
|
||||
|
||||
pos = MAX (pos, offset);
|
||||
step = (pos - offset) / (i - last);
|
||||
for (last = last + 1; last <= i; last++)
|
||||
{
|
||||
const GdkRGBA *rgba;
|
||||
|
||||
stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, last);
|
||||
|
||||
rgba = _gtk_css_rgba_value_get_rgba (stop->color);
|
||||
offset += step;
|
||||
|
||||
cairo_pattern_add_color_stop_rgba (pattern,
|
||||
(offset - start) / (end - start),
|
||||
rgba->red,
|
||||
rgba->green,
|
||||
rgba->blue,
|
||||
rgba->alpha);
|
||||
}
|
||||
|
||||
offset = pos;
|
||||
last = i;
|
||||
}
|
||||
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_translate (cr, width / 2, height / 2);
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
gtk_css_image_linear_ensure_surface (linear, width, height);
|
||||
cairo_set_source_surface (cr, linear->cached_surface, 0, 0);
|
||||
cairo_paint (cr);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
gtk_css_image_linear_get_surface (GtkCssImage *image,
|
||||
cairo_surface_t *target,
|
||||
int surface_width,
|
||||
int surface_height)
|
||||
{
|
||||
GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
|
||||
|
||||
if (linear->cached_surface != NULL &&
|
||||
surface_width == cairo_image_surface_get_width (linear->cached_surface) &&
|
||||
surface_height == cairo_image_surface_get_height (linear->cached_surface))
|
||||
return cairo_surface_reference (linear->cached_surface);
|
||||
|
||||
return GTK_CSS_IMAGE_CLASS (_gtk_css_image_linear_parent_class)->get_surface
|
||||
(image, target, surface_width, surface_height);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_linear_parse (GtkCssImage *image,
|
||||
@@ -586,6 +632,12 @@ gtk_css_image_linear_dispose (GObject *object)
|
||||
linear->angle = NULL;
|
||||
}
|
||||
|
||||
if (linear->cached_surface)
|
||||
{
|
||||
cairo_surface_destroy (linear->cached_surface);
|
||||
linear->cached_surface = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (_gtk_css_image_linear_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@@ -595,6 +647,7 @@ _gtk_css_image_linear_class_init (GtkCssImageLinearClass *klass)
|
||||
GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
image_class->get_surface = gtk_css_image_linear_get_surface;
|
||||
image_class->draw = gtk_css_image_linear_draw;
|
||||
image_class->parse = gtk_css_image_linear_parse;
|
||||
image_class->print = gtk_css_image_linear_print;
|
||||
|
@@ -48,6 +48,8 @@ struct _GtkCssImageLinear
|
||||
GtkCssValue *angle; /* warning: We use GTK_CSS_NUMBER as an enum for the corners */
|
||||
GArray *stops;
|
||||
guint repeating :1;
|
||||
|
||||
cairo_surface_t *cached_surface;
|
||||
};
|
||||
|
||||
struct _GtkCssImageLinearClass
|
||||
|
@@ -54,6 +54,12 @@ struct _GtkCssImageClass
|
||||
/* aspect ratio (width / height) of image or 0 if it has no aspect ratio (optional) */
|
||||
double (* get_aspect_ratio) (GtkCssImage *image);
|
||||
|
||||
/* returns a surface for specified width and height */
|
||||
cairo_surface_t * (* get_surface) (GtkCssImage *image,
|
||||
cairo_surface_t *target,
|
||||
int surface_width,
|
||||
int surface_height);
|
||||
|
||||
/* create "computed value" in CSS terms, returns a new reference */
|
||||
GtkCssImage *(* compute) (GtkCssImage *image,
|
||||
guint property_id,
|
||||
|
@@ -39,6 +39,22 @@ gtk_css_image_surface_get_height (GtkCssImage *image)
|
||||
return cairo_image_surface_get_height (surface->surface);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
gtk_css_image_surface_get_surface (GtkCssImage *image,
|
||||
cairo_surface_t *target,
|
||||
int surface_width,
|
||||
int surface_height)
|
||||
{
|
||||
GtkCssImageSurface *surface = GTK_CSS_IMAGE_SURFACE (image);
|
||||
|
||||
if (surface_width == cairo_image_surface_get_width (surface->surface) &&
|
||||
surface_height == cairo_image_surface_get_height (surface->surface))
|
||||
return cairo_surface_reference (surface->surface);
|
||||
|
||||
return GTK_CSS_IMAGE_CLASS (_gtk_css_image_surface_parent_class)->get_surface
|
||||
(image, target, surface_width, surface_height);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_surface_draw (GtkCssImage *image,
|
||||
cairo_t *cr,
|
||||
@@ -112,6 +128,7 @@ _gtk_css_image_surface_class_init (GtkCssImageSurfaceClass *klass)
|
||||
|
||||
image_class->get_width = gtk_css_image_surface_get_width;
|
||||
image_class->get_height = gtk_css_image_surface_get_height;
|
||||
image_class->get_surface = gtk_css_image_surface_get_surface;
|
||||
image_class->draw = gtk_css_image_surface_draw;
|
||||
image_class->print = gtk_css_image_surface_print;
|
||||
|
||||
|
@@ -108,6 +108,18 @@ gtk_css_image_url_get_aspect_ratio (GtkCssImage *image)
|
||||
return _gtk_css_image_get_aspect_ratio (gtk_css_image_url_load_image (url));
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
gtk_css_image_url_get_surface (GtkCssImage *image,
|
||||
cairo_surface_t *target,
|
||||
int surface_width,
|
||||
int surface_height)
|
||||
{
|
||||
GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image);
|
||||
|
||||
return _gtk_css_image_get_surface (gtk_css_image_url_load_image (url),
|
||||
target, surface_width, surface_height);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_url_draw (GtkCssImage *image,
|
||||
cairo_t *cr,
|
||||
@@ -173,6 +185,7 @@ _gtk_css_image_url_class_init (GtkCssImageUrlClass *klass)
|
||||
image_class->get_width = gtk_css_image_url_get_width;
|
||||
image_class->get_height = gtk_css_image_url_get_height;
|
||||
image_class->get_aspect_ratio = gtk_css_image_url_get_aspect_ratio;
|
||||
image_class->get_surface = gtk_css_image_url_get_surface;
|
||||
image_class->compute = gtk_css_image_url_compute;
|
||||
image_class->draw = gtk_css_image_url_draw;
|
||||
image_class->parse = gtk_css_image_url_parse;
|
||||
|
@@ -247,7 +247,7 @@ gtk_border_image_compute_slice_size (GtkBorderImageSliceSize sizes[3],
|
||||
sizes[1].offset = sizes[0].size;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
gtk_border_image_render (GtkBorderImage *image,
|
||||
const double border_width[4],
|
||||
cairo_t *cr,
|
||||
@@ -267,8 +267,6 @@ gtk_border_image_render (GtkBorderImage *image,
|
||||
width, height,
|
||||
&source_width, &source_height);
|
||||
|
||||
/* XXX: Optimize for (source_width == width && source_height == height) */
|
||||
|
||||
surface = _gtk_css_image_get_surface (image->source,
|
||||
cairo_get_target (cr),
|
||||
source_width, source_height);
|
||||
|
Reference in New Issue
Block a user