1 /* This file is an image processing operation for GEGL 2 * 3 * GEGL is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 3 of the License, or (at your option) any later version. 7 * 8 * GEGL is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with GEGL; if not, see <https://www.gnu.org/licenses/>. 15 * 16 * Copyright 2006, 2010 Øyvind Kolås <pippin@gimp.org> 17 */ 18 19 #include "config.h" 20 #include <glib/gi18n-lib.h> 21 22 23 #ifdef GEGL_PROPERTIES 24 25 /* Should correspond to GeglMedianBlurNeighborhood in median-blur.c */ 26 enum_start (gegl_dropshadow_grow_shape) 27 enum_value (GEGL_DROPSHADOW_GROW_SHAPE_SQUARE, "square", N_("Square")) 28 enum_value (GEGL_DROPSHADOW_GROW_SHAPE_CIRCLE, "circle", N_("Circle")) 29 enum_value (GEGL_DROPSHADOW_GROW_SHAPE_DIAMOND, "diamond", N_("Diamond")) 30 enum_end (GeglDropshadowGrowShape) 31 32 property_double (x, _("X"), 20.0) 33 description (_("Horizontal shadow offset")) 34 ui_range (-40.0, 40.0) 35 ui_steps (1, 10) 36 ui_meta ("unit", "pixel-distance") 37 ui_meta ("axis", "x") 38 39 property_double (y, _("Y"), 20.0) 40 description (_("Vertical shadow offset")) 41 ui_range (-40.0, 40.0) 42 ui_steps (1, 10) 43 ui_meta ("unit", "pixel-distance") 44 ui_meta ("axis", "y") 45 46 property_double (radius, _("Blur radius"), 10.0) 47 value_range (0.0, G_MAXDOUBLE) 48 ui_range (0.0, 300.0) 49 ui_steps (1, 5) 50 ui_gamma (1.5) 51 ui_meta ("unit", "pixel-distance") 52 53 property_enum (grow_shape, _("Grow shape"), 54 GeglDropshadowGrowShape, gegl_dropshadow_grow_shape, 55 GEGL_DROPSHADOW_GROW_SHAPE_CIRCLE) 56 description (_("The shape to expand or contract the shadow in")) 57 58 property_double (grow_radius, _("Grow radius"), 0.0) 59 value_range (-100.0, 100.0) 60 ui_range (-50.0, 50.0) 61 ui_digits (0) 62 ui_steps (1, 5) 63 ui_gamma (1.5) 64 ui_meta ("unit", "pixel-distance") 65 description (_("The distance to expand the shadow before blurring; a negative value will contract the shadow instead")) 66 67 property_color (color, _("Color"), "black") 68 /* TRANSLATORS: the string 'black' should not be translated */ 69 description (_("The shadow's color (defaults to 'black')")) 70 71 /* It does make sense to sometimes have opacities > 1 (see GEGL logo 72 * for example) 73 */ 74 property_double (opacity, _("Opacity"), 0.5) 75 value_range (0.0, 2.0) 76 ui_steps (0.01, 0.10) 77 78 #else 79 80 #define GEGL_OP_META 81 #define GEGL_OP_NAME dropshadow 82 #define GEGL_OP_C_SOURCE dropshadow.c 83 84 #include "gegl-op.h" 85 86 typedef struct 87 { 88 GeglNode *input; 89 GeglNode *grow; 90 GeglNode *darken; 91 } State; 92 93 static void 94 update_graph (GeglOperation *operation) 95 { 96 GeglProperties *o = GEGL_PROPERTIES (operation); 97 State *state = o->user_data; 98 if (!state) return; 99 100 if (o->grow_radius > 0.0001) 101 { 102 gegl_node_link_many (state->input, state->grow, state->darken, NULL); 103 } 104 else 105 { 106 gegl_node_link_many (state->input, state->darken, NULL); 107 } 108 } 109 110 111 /* in attach we hook into graph adding the needed nodes */ 112 static void 113 attach (GeglOperation *operation) 114 { 115 GeglProperties *o = GEGL_PROPERTIES (operation); 116 GeglNode *gegl = operation->node; 117 GeglNode *input, *output, *over, *translate, *opacity, *grow, *blur, *darken, *color; 118 GeglColor *black_color = gegl_color_new ("rgb(0.0,0.0,0.0)"); 119 120 input = gegl_node_get_input_proxy (gegl, "input"); 121 output = gegl_node_get_output_proxy (gegl, "output"); 122 over = gegl_node_new_child (gegl, "operation", "gegl:over", NULL); 123 translate = gegl_node_new_child (gegl, "operation", "gegl:translate", NULL); 124 opacity = gegl_node_new_child (gegl, "operation", "gegl:opacity", NULL); 125 blur = gegl_node_new_child (gegl, "operation", "gegl:gaussian-blur", 126 "clip-extent", FALSE, 127 "abyss-policy", 0, 128 NULL); 129 grow = gegl_node_new_child (gegl, "operation", "gegl:median-blur", 130 "percentile", 100.0, 131 "alpha-percentile", 100.0, 132 "abyss-policy", GEGL_ABYSS_NONE, 133 NULL); 134 darken = gegl_node_new_child (gegl, "operation", "gegl:src-in", NULL); 135 color = gegl_node_new_child (gegl, "operation", "gegl:color", 136 "value", black_color, 137 NULL); 138 State *state = g_malloc0 (sizeof (State)); 139 o->user_data = state; 140 state->input = input; 141 state->grow = grow; 142 state->darken = darken; 143 144 g_object_unref (black_color); 145 146 gegl_node_link_many (input, grow, darken, blur, opacity, translate, over, output, 147 NULL); 148 gegl_node_connect_from (over, "aux", input, "output"); 149 gegl_node_connect_from (darken, "aux", color, "output"); 150 151 gegl_operation_meta_redirect (operation, "grow-shape", grow, "neighborhood"); 152 gegl_operation_meta_redirect (operation, "grow-radius", grow, "radius"); 153 gegl_operation_meta_redirect (operation, "radius", blur, "std-dev-x"); 154 gegl_operation_meta_redirect (operation, "radius", blur, "std-dev-y"); 155 gegl_operation_meta_redirect (operation, "x", translate, "x"); 156 gegl_operation_meta_redirect (operation, "y", translate, "y"); 157 gegl_operation_meta_redirect (operation, "color", color, "value"); 158 gegl_operation_meta_redirect (operation, "opacity", opacity, "value"); 159 } 160 161 static void 162 dispose (GObject *object) 163 { 164 GeglProperties *o = GEGL_PROPERTIES (object); 165 g_clear_pointer (&o->user_data, g_free); 166 G_OBJECT_CLASS (gegl_op_parent_class)->dispose (object); 167 } 168 169 static void 170 gegl_op_class_init (GeglOpClass *klass) 171 { 172 GObjectClass *object_class; 173 GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass); 174 GeglOperationMetaClass *operation_meta_class = GEGL_OPERATION_META_CLASS (klass); 175 176 operation_class->attach = attach; 177 operation_meta_class->update = update_graph; 178 179 object_class = G_OBJECT_CLASS (klass); 180 object_class->dispose = dispose; 181 182 gegl_operation_class_set_keys (operation_class, 183 "name", "gegl:dropshadow", 184 "title", _("Dropshadow"), 185 "categories", "light", 186 "reference-hash", "1784365a0e801041189309f3a4866b1a", 187 "description", 188 _("Creates a dropshadow effect on the input buffer"), 189 NULL); 190 } 191 192 #endif 193