/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * st-shadow.c: Boxed type holding for -st-shadow attributes * * Copyright 2009, 2010 Florian Müllner * * This program 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.1 of * the License, or (at your option) any later version. * * This program is distributed in the hope 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 License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "config.h" #include "st-shadow.h" /** * SECTION: st-shadow * @short_description: Boxed type for -st-shadow attributes * * #StShadow is a boxed type for storing attributes of the -st-shadow * property, modelled liberally after the CSS3 box-shadow property. * See http://www.css3.info/preview/box-shadow/ * */ /** * st_shadow_new: * @color: shadow's color * @xoffset: horizontal offset * @yoffset: vertical offset * @blur: blur radius * @spread: spread radius * @inset: whether the shadow should be inset * * Creates a new #StShadow * * Returns: the newly allocated shadow. Use st_shadow_free() when done */ StShadow * st_shadow_new (ClutterColor *color, gdouble xoffset, gdouble yoffset, gdouble blur, gdouble spread, gboolean inset) { StShadow *shadow; shadow = g_slice_new (StShadow); shadow->color = *color; shadow->xoffset = xoffset; shadow->yoffset = yoffset; shadow->blur = blur; shadow->spread = spread; shadow->inset = inset; shadow->ref_count = 1; return shadow; } /** * st_shadow_ref: * @shadow: a #StShadow * * Atomically increments the reference count of @shadow by one. * * Returns: the passed in #StShadow. */ StShadow * st_shadow_ref (StShadow *shadow) { g_return_val_if_fail (shadow != NULL, NULL); g_return_val_if_fail (shadow->ref_count > 0, shadow); g_atomic_int_add (&shadow->ref_count, 1); return shadow; } /** * st_shadow_unref: * @shadow: a #StShadow * * Atomically decrements the reference count of @shadow by one. * If the reference count drops to 0, all memory allocated by the * #StShadow is released. */ void st_shadow_unref (StShadow *shadow) { g_return_if_fail (shadow != NULL); g_return_if_fail (shadow->ref_count > 0); if (g_atomic_int_exchange_and_add (&shadow->ref_count, -1) - 1 == 0) g_slice_free (StShadow, shadow); } /** * st_shadow_equal: * @shadow: a #StShadow * @other: a different #StShadow * * Check if two shadow objects are identical. Note that two shadows may * compare non-identically if they differ only by floating point rounding * errors. * * Return value: %TRUE if the two shadows are identical */ gboolean st_shadow_equal (StShadow *shadow, StShadow *other) { g_return_val_if_fail (shadow != NULL, FALSE); g_return_val_if_fail (other != NULL, FALSE); /* We use strict equality to compare double quantities; this means * that, for example, a shadow offset of 0.25in does not necessarily * compare equal to a shadow offset of 18pt in this test. Assume * that a few false negatives are mostly harmless. */ return (clutter_color_equal (&shadow->color, &other->color) && shadow->xoffset == other->xoffset && shadow->yoffset == other->yoffset && shadow->blur == other->blur && shadow->spread == other->spread && shadow->inset == other->inset); } /** * st_shadow_get_box: * @shadow: a #StShadow * @actor_box: the box allocated to a #ClutterAlctor * @shadow_box: computed box occupied by @shadow * * Gets the box used to paint @shadow, which will be partly * outside of @actor_box */ void st_shadow_get_box (StShadow *shadow, const ClutterActorBox *actor_box, ClutterActorBox *shadow_box) { g_return_if_fail (shadow != NULL); g_return_if_fail (actor_box != NULL); g_return_if_fail (shadow_box != NULL); /* Inset shadows are drawn below the border, so returning * the original box is not actually correct; still, it's * good enough for the purpose of determing additional space * required outside the actor box. */ if (shadow->inset) { *shadow_box = *actor_box; return; } shadow_box->x1 = actor_box->x1 + shadow->xoffset - shadow->blur - shadow->spread; shadow_box->x2 = actor_box->x2 + shadow->xoffset + shadow->blur + shadow->spread; shadow_box->y1 = actor_box->y1 + shadow->yoffset - shadow->blur - shadow->spread; shadow_box->y2 = actor_box->y2 + shadow->yoffset + shadow->blur + shadow->spread; } GType st_shadow_get_type (void) { static GType _st_shadow_type = 0; if (G_UNLIKELY (_st_shadow_type == 0)) _st_shadow_type = g_boxed_type_register_static ("StShadow", (GBoxedCopyFunc) st_shadow_ref, (GBoxedFreeFunc) st_shadow_unref); return _st_shadow_type; }