Module: PSDNative::Renderer::Mask

Defined in:
ext/psd_native/psd_native_ext.c

Instance Method Summary collapse

Instance Method Details

#apply!Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'ext/psd_native/mask.c', line 3

VALUE psd_native_mask_apply_bang(VALUE self) {
  psd_logger("debug", "Applying mask with native code");

  int doc_width = FIX2INT(rb_iv_get(self, "@doc_width"));
  int doc_height = FIX2INT(rb_iv_get(self, "@doc_height"));

  VALUE layer = rb_iv_get(self, "@layer");
  VALUE canvas = rb_iv_get(self, "@canvas");
  VALUE mask = rb_funcall(layer, rb_intern("mask"), 0);
  VALUE *mask_data = RARRAY_PTR(rb_funcall(rb_funcall(layer, rb_intern("image"), 0), rb_intern("mask_data"), 0));

  int mask_height = FIX2INT(rb_funcall(mask, rb_intern("height"), 0));
  int mask_width = FIX2INT(rb_funcall(mask, rb_intern("width"), 0));
  int mask_left = FIX2INT(rb_funcall(mask, rb_intern("left"), 0));
  int mask_top = FIX2INT(rb_funcall(mask, rb_intern("top"), 0));

  int layer_height = FIX2INT(rb_funcall(layer, rb_intern("height"), 0));
  int layer_width = FIX2INT(rb_funcall(layer, rb_intern("width"), 0));
  int layer_left = FIX2INT(rb_funcall(layer, rb_intern("left"), 0));
  int layer_top = FIX2INT(rb_funcall(layer, rb_intern("top"), 0));

  PIXEL color;
  int x, y, doc_x, doc_y, layer_x, layer_y, alpha;
  int i = 0;
  for (y = 0; y < mask_height; y++) {
    for (x = 0; x < mask_width; x++) {
      doc_x = mask_left + x;
      doc_y = mask_top + y;
      layer_x = doc_x - layer_left;
      layer_y = doc_y - layer_top;

      if (layer_x < 0 || layer_x >= layer_width || layer_y < 0 || layer_y >= layer_height) continue;

      color = FIX2UINT(rb_funcall(canvas, rb_intern("[]"), 2, INT2FIX(layer_x), INT2FIX(layer_y)));

      if (doc_x < 0 || doc_x >= doc_width || doc_y < 0 || doc_y > doc_height) {
        alpha = 0;
      } else {
        alpha = mask_data[i];
      }

      color = (color & 0xffffff00) | (A(color) * alpha / 255);
      rb_funcall(canvas, rb_intern("[]="), 3, INT2FIX(layer_x), INT2FIX(layer_y), INT2FIX(color));

      i++;
    }
  }

  return Qnil;
}