]> git.sesse.net Git - casparcg/blob - core/producer/draw/freehand_producer.cpp
manually merged a72be89 from master
[casparcg] / core / producer / draw / freehand_producer.cpp
1 /*
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
3 *
4 * This file is part of CasparCG (www.casparcg.com).
5 *
6 * CasparCG is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CasparCG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Author: Helge Norberg, helge.norberg@svt.se
20 */
21
22 #include "../../stdafx.h"
23
24 #include "freehand_producer.h"
25
26 #include <core/producer/frame_producer.h>
27 #include <core/frame/frame.h>
28 #include <core/frame/draw_frame.h>
29 #include <core/frame/frame_factory.h>
30 #include <core/frame/pixel_format.h>
31 #include <core/monitor/monitor.h>
32
33 namespace caspar { namespace core {
34
35 std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>> empty_drawing(
36                 int width, int height)
37 {
38         std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>> result;
39
40         result.resize(width * height * 4);
41         std::fill(result.begin(), result.end(), 0);
42
43         return std::move(result);
44 }
45
46 class freehand_producer : public frame_producer_base
47 {
48         std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>>     drawing_;
49         spl::shared_ptr<core::frame_factory>                                            frame_factory_;
50         constraints                                                                                                     constraints_;
51         draw_frame                                                                                                      frame_;
52         bool                                                                                                            button_pressed_;
53         bool                                                                                                            modified_;
54 public:
55         explicit freehand_producer(
56                         const spl::shared_ptr<core::frame_factory>& frame_factory,
57                         int width,
58                         int height)
59                 : drawing_(std::move(empty_drawing(width, height)))
60                 , frame_factory_(frame_factory)
61                 , constraints_(width, height)
62                 , frame_(create_frame())
63                 , button_pressed_(false)
64                 , modified_(false)
65         {
66                 CASPAR_LOG(info) << print() << L" Initialized";
67         }
68
69         draw_frame create_frame()
70         {
71                 pixel_format_desc desc(pixel_format_def::bgra);
72                 desc.planes.push_back(pixel_format_desc::plane(
73                                 static_cast<int>(constraints_.width.get()),
74                                 static_cast<int>(constraints_.height.get()),
75                                 4));
76                 auto frame = frame_factory_->create_frame(this, desc);
77
78                 std::memcpy(frame.image_data().begin(), drawing_.data(), drawing_.size());
79
80                 return draw_frame(std::move(frame));
81         }
82
83         // frame_producer
84
85         void on_interaction(const interaction_event::ptr& event) override
86         {
87                 if (is<mouse_move_event>(event) && button_pressed_)
88                 {
89                         auto mouse_move = as<mouse_move_event>(event);
90
91                         int x = static_cast<int>(mouse_move->x * constraints_.width.get());
92                         int y = static_cast<int>(mouse_move->y * constraints_.height.get());
93
94                         if (x >= constraints_.width.get() 
95                                         || y >= constraints_.height.get()
96                                         || x < 0
97                                         || y < 0)
98                                 return;
99
100                         uint8_t* b = drawing_.data() + (y * static_cast<int>(constraints_.width.get()) + x) * 4;
101                         uint8_t* g = b + 1;
102                         uint8_t* r = b + 2;
103                         uint8_t* a = b + 3;
104
105                         *b = 255;
106                         *g = 255;
107                         *r = 255;
108                         *a = 255;
109
110                         modified_ = true;
111                 }
112                 else if (is<mouse_button_event>(event))
113                 {
114                         auto button_event = as<mouse_button_event>(event);
115
116                         if (button_event->button == 0)
117                                 button_pressed_ = button_event->pressed;
118                         else if (button_event->button == 1 && button_event->pressed)
119                         {
120                                 std::memset(drawing_.data(), 0, drawing_.size());
121                                 modified_ = true;
122                         }
123                 }
124         }
125
126         bool collides(double x, double y) const override
127         {
128                 return true;
129         }
130                         
131         draw_frame receive_impl() override
132         {
133                 if (modified_)
134                 {
135                         frame_ = create_frame();
136                         modified_ = false;
137                 }
138
139                 return frame_;
140         }
141
142         constraints& pixel_constraints() override
143         {
144                 return constraints_;
145         }
146         
147         std::wstring print() const override
148         {
149                 return L"freehand[]";
150         }
151
152         std::wstring name() const override
153         {
154                 return L"freehand";
155         }
156         
157         boost::property_tree::wptree info() const override
158         {
159                 boost::property_tree::wptree info;
160                 info.add(L"type", L"freehand");
161                 return info;
162         }
163
164         monitor::source& monitor_output()
165         {
166                 static monitor::subject monitor_subject(""); return monitor_subject;
167         }
168 };
169
170 spl::shared_ptr<frame_producer> create_freehand_producer(const spl::shared_ptr<frame_factory>& frame_factory, const std::vector<std::wstring>& params)
171 {
172         if(params.size() < 3 || !boost::iequals(params.at(0), L"[FREEHAND]"))
173                 return core::frame_producer::empty();
174
175         int width = boost::lexical_cast<int>(params.at(1));
176         int height = boost::lexical_cast<int>(params.at(2));
177
178         return spl::make_shared<freehand_producer>(frame_factory, width, height);
179 }
180
181 }}