ID-Remap - Step one: core work (cleanup and rework of generic ID datablock handling).
[blender.git] / source / blender / compositor / operations / COM_MaskOperation.cpp
1 /*
2
3  * Copyright 2012, Blender Foundation.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * Contributor:
20  *              Jeroen Bakker
21  *              Monique Dewanchand
22  *              Sergey Sharybin
23  */
24
25 #include "COM_MaskOperation.h"
26
27 #include "MEM_guardedalloc.h"
28
29 #include "BLI_listbase.h"
30 #include "BLI_math.h"
31
32 extern "C" {
33 #  include "BKE_mask.h"
34 }
35
36 MaskOperation::MaskOperation() : NodeOperation()
37 {
38         this->addOutputSocket(COM_DT_VALUE);
39         this->m_mask = NULL;
40         this->m_maskWidth = 0;
41         this->m_maskHeight = 0;
42         this->m_maskWidthInv = 0.0f;
43         this->m_maskHeightInv = 0.0f;
44         this->m_frame_shutter = 0.0f;
45         this->m_frame_number = 0;
46         this->m_rasterMaskHandleTot = 1;
47         memset(this->m_rasterMaskHandles, 0, sizeof(this->m_rasterMaskHandles));
48 }
49
50 void MaskOperation::initExecution()
51 {
52         if (this->m_mask && this->m_rasterMaskHandles[0] == NULL) {
53                 if (this->m_rasterMaskHandleTot == 1) {
54                         this->m_rasterMaskHandles[0] = BKE_maskrasterize_handle_new();
55
56                         BKE_maskrasterize_handle_init(this->m_rasterMaskHandles[0], this->m_mask,
57                                 this->m_maskWidth, this->m_maskHeight,
58                                 true, this->m_do_smooth, this->m_do_feather);
59                 }
60                 else {
61                         /* make a throw away copy of the mask */
62                         const float frame = (float)this->m_frame_number - this->m_frame_shutter;
63                         const float frame_step = (this->m_frame_shutter * 2.0f) / this->m_rasterMaskHandleTot;
64                         float frame_iter = frame;
65
66                         Mask *mask_temp;
67
68                         mask_temp = BKE_mask_copy_nolib(this->m_mask);
69
70                         /* trick so we can get unkeyed edits to display */
71                         {
72                                 MaskLayer *masklay;
73                                 MaskLayerShape *masklay_shape;
74
75                                 for (masklay = (MaskLayer *)mask_temp->masklayers.first;
76                                      masklay;
77                                      masklay = masklay->next)
78                                 {
79                                         masklay_shape = BKE_mask_layer_shape_verify_frame(masklay, this->m_frame_number);
80                                         BKE_mask_layer_shape_from_mask(masklay, masklay_shape);
81                                 }
82                         }
83
84                         for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) {
85                                 this->m_rasterMaskHandles[i] = BKE_maskrasterize_handle_new();
86
87                                 /* re-eval frame info */
88                                 BKE_mask_evaluate(mask_temp, frame_iter, true);
89
90                                 BKE_maskrasterize_handle_init(this->m_rasterMaskHandles[i], mask_temp,
91                                                               this->m_maskWidth, this->m_maskHeight,
92                                                               true, this->m_do_smooth, this->m_do_feather);
93
94                                 frame_iter += frame_step;
95                         }
96
97                         BKE_mask_free(mask_temp);
98                         MEM_freeN(mask_temp);
99                 }
100         }
101 }
102
103 void MaskOperation::deinitExecution()
104 {
105         for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) {
106                 if (this->m_rasterMaskHandles[i]) {
107                         BKE_maskrasterize_handle_free(this->m_rasterMaskHandles[i]);
108                         this->m_rasterMaskHandles[i] = NULL;
109                 }
110         }
111 }
112
113 void MaskOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
114 {
115         if (this->m_maskWidth == 0 || this->m_maskHeight == 0) {
116                 NodeOperation::determineResolution(resolution, preferredResolution);
117         }
118         else {
119                 unsigned int nr[2];
120
121                 nr[0] = this->m_maskWidth;
122                 nr[1] = this->m_maskHeight;
123
124                 NodeOperation::determineResolution(resolution, nr);
125
126                 resolution[0] = this->m_maskWidth;
127                 resolution[1] = this->m_maskHeight;
128         }
129 }
130
131 void MaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
132 {
133         const float xy[2] = {
134             (x * this->m_maskWidthInv)  + this->m_mask_px_ofs[0],
135             (y * this->m_maskHeightInv) + this->m_mask_px_ofs[1]};
136
137         if (this->m_rasterMaskHandleTot == 1) {
138                 if (this->m_rasterMaskHandles[0]) {
139                         output[0] = BKE_maskrasterize_handle_sample(this->m_rasterMaskHandles[0], xy);
140                 }
141                 else {
142                         output[0] = 0.0f;
143                 }
144         }
145         else {
146                 /* incase loop below fails */
147                 output[0] = 0.0f;
148
149                 for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) {
150                         if (this->m_rasterMaskHandles[i]) {
151                                 output[0] += BKE_maskrasterize_handle_sample(this->m_rasterMaskHandles[i], xy);
152                         }
153                 }
154
155                 /* until we get better falloff */
156                 output[0] /= this->m_rasterMaskHandleTot;
157         }
158 }