Branch data Line data Source code
1 : : /* 2 : : * Copyright (C) 2021 James Westman <james@jwestman.net> 3 : : * 4 : : * This library is free software; you can redistribute it and/or 5 : : * modify it under the terms of the GNU Lesser General Public 6 : : * License as published by the Free Software Foundation; either 7 : : * version 2.1 of the License, or (at your option) any later version. 8 : : * 9 : : * This library is distributed in the hope that it will be useful, 10 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 : : * Lesser General Public License for more details. 13 : : * 14 : : * You should have received a copy of the GNU Lesser General Public 15 : : * License along with this library; if not, see <https://www.gnu.org/licenses/>. 16 : : */ 17 : : 18 : : #include <gtk/gtk.h> 19 : : #include "shumate-vector-expression-private.h" 20 : : #include "shumate-vector-fill-layer-private.h" 21 : : #include "shumate-vector-sprite-sheet.h" 22 : : #include "shumate-vector-utils-private.h" 23 : : #include "shumate-vector-value-private.h" 24 : : 25 : : struct _ShumateVectorFillLayer 26 : : { 27 : : ShumateVectorLayer parent_instance; 28 : : 29 : : ShumateVectorExpression *color; 30 : : ShumateVectorExpression *opacity; 31 : : ShumateVectorExpression *pattern; 32 : : }; 33 : : 34 [ + + + - ]: 18 : G_DEFINE_TYPE (ShumateVectorFillLayer, shumate_vector_fill_layer, SHUMATE_TYPE_VECTOR_LAYER) 35 : : 36 : : 37 : : ShumateVectorLayer * 38 : 6 : shumate_vector_fill_layer_create_from_json (JsonObject *object, GError **error) 39 : : { 40 : 6 : ShumateVectorFillLayer *layer = g_object_new (SHUMATE_TYPE_VECTOR_FILL_LAYER, NULL); 41 : 6 : JsonNode *paint_node; 42 : : 43 [ + - ]: 6 : if ((paint_node = json_object_get_member (object, "paint"))) 44 : : { 45 : 6 : JsonObject *paint; 46 : : 47 [ + - ]: 6 : if (!shumate_vector_json_get_object (paint_node, &paint, error)) 48 : 0 : return NULL; 49 : : 50 [ + - ]: 6 : if (!(layer->color = shumate_vector_expression_from_json (json_object_get_member (paint, "fill-color"), error))) 51 : : return NULL; 52 : : 53 [ + - ]: 6 : if (!(layer->opacity = shumate_vector_expression_from_json (json_object_get_member (paint, "fill-opacity"), error))) 54 : : return NULL; 55 : : 56 [ + - ]: 6 : if (!(layer->pattern = shumate_vector_expression_from_json (json_object_get_member (paint, "fill-pattern"), error))) 57 : : return NULL; 58 : : } 59 : : 60 : : return (ShumateVectorLayer *)layer; 61 : : } 62 : : 63 : : static cairo_pattern_t * 64 : 0 : create_pattern (ShumateVectorSprite *sprite, 65 : : ShumateVectorRenderScope *scope) 66 : : { 67 : 0 : int width = shumate_vector_sprite_get_width (sprite) * scope->scale_factor; 68 : 0 : int height = shumate_vector_sprite_get_height (sprite) * scope->scale_factor; 69 : 0 : cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); 70 : 0 : cairo_t *source_cr = cairo_create (surface); 71 : 0 : GtkSnapshot *snapshot = gtk_snapshot_new (); 72 : 0 : g_autoptr(GskRenderNode) node = NULL; 73 : 0 : cairo_pattern_t *pattern; 74 : 0 : cairo_matrix_t matrix; 75 : : 76 : 0 : gdk_paintable_snapshot (GDK_PAINTABLE (sprite), snapshot, width, height); 77 : 0 : node = gtk_snapshot_free_to_node (snapshot); 78 : : 79 : 0 : gsk_render_node_draw (node, source_cr); 80 : : 81 : 0 : pattern = cairo_pattern_create_for_surface (surface); 82 : 0 : cairo_matrix_init_scale (&matrix, 1 / scope->scale * scope->scale_factor, 1 / scope->scale * scope->scale_factor); 83 : 0 : cairo_pattern_set_matrix (pattern, &matrix); 84 : 0 : cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); 85 : : 86 : 0 : cairo_surface_destroy (surface); 87 : 0 : cairo_destroy (source_cr); 88 : : 89 [ # # ]: 0 : return pattern; 90 : : } 91 : : 92 : : 93 : : static void 94 : 6 : shumate_vector_fill_layer_render (ShumateVectorLayer *layer, ShumateVectorRenderScope *scope) 95 : : { 96 : 6 : ShumateVectorFillLayer *self = SHUMATE_VECTOR_FILL_LAYER (layer); 97 : 6 : GdkRGBA color = SHUMATE_VECTOR_COLOR_BLACK; 98 : 6 : double opacity; 99 : 12 : g_autoptr(ShumateVectorSprite) pattern_sprite = NULL; 100 : : 101 : 6 : shumate_vector_expression_eval_color (self->color, scope, &color); 102 : 6 : opacity = shumate_vector_expression_eval_number (self->opacity, scope, 1.0); 103 : 6 : pattern_sprite = shumate_vector_expression_eval_image (self->pattern, scope); 104 : : 105 : 6 : shumate_vector_render_scope_exec_geometry (scope); 106 : : 107 [ - + ]: 6 : if (pattern_sprite != NULL) 108 : : { 109 : 0 : cairo_pattern_t *pattern = create_pattern (pattern_sprite, scope); 110 : : 111 : 0 : cairo_set_source (scope->cr, pattern); 112 : : 113 : : /* Use cairo_paint_with_alpha so that we can set fill-opacity correctly. */ 114 : 0 : cairo_save (scope->cr); 115 : 0 : cairo_clip (scope->cr); 116 : 0 : cairo_paint_with_alpha (scope->cr, opacity); 117 : 0 : cairo_restore (scope->cr); 118 : : 119 : 0 : cairo_pattern_destroy (pattern); 120 : : } 121 : : else 122 : : { 123 : 6 : cairo_set_source_rgba (scope->cr, color.red, color.green, color.blue, color.alpha * opacity); 124 : 6 : cairo_fill (scope->cr); 125 : : } 126 : 6 : } 127 : : 128 : : 129 : : static void 130 : 6 : shumate_vector_fill_layer_finalize (GObject *object) 131 : : { 132 : 6 : ShumateVectorFillLayer *self = SHUMATE_VECTOR_FILL_LAYER (object); 133 : : 134 [ + - ]: 6 : g_clear_object (&self->color); 135 [ + - ]: 6 : g_clear_object (&self->opacity); 136 [ + - ]: 6 : g_clear_object (&self->pattern); 137 : : 138 : 6 : G_OBJECT_CLASS (shumate_vector_fill_layer_parent_class)->finalize (object); 139 : 6 : } 140 : : 141 : : 142 : : static void 143 : 6 : shumate_vector_fill_layer_class_init (ShumateVectorFillLayerClass *klass) 144 : : { 145 : 6 : GObjectClass *object_class = G_OBJECT_CLASS (klass); 146 : 6 : ShumateVectorLayerClass *layer_class = SHUMATE_VECTOR_LAYER_CLASS (klass); 147 : : 148 : 6 : object_class->finalize = shumate_vector_fill_layer_finalize; 149 : 6 : layer_class->render = shumate_vector_fill_layer_render; 150 : : } 151 : : 152 : : 153 : : static void 154 : 6 : shumate_vector_fill_layer_init (ShumateVectorFillLayer *self) 155 : : { 156 : 6 : }