b5c22c868b7f0217d02888670d616a988be20e1b
[platform/core/graphics/tizenvg.git] / src / lib / tvgCanvasImpl.h
1 /*
2  * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
3
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 #ifndef _TVG_CANVAS_IMPL_H_
23 #define _TVG_CANVAS_IMPL_H_
24
25 #include "tvgPaint.h"
26
27 /************************************************************************/
28 /* Internal Class Implementation                                        */
29 /************************************************************************/
30
31 struct Canvas::Impl
32 {
33     Array<Paint*> paints;
34     RenderMethod* renderer;
35     bool refresh = false;   //if all paints should be updated by force.
36
37     Impl(RenderMethod* pRenderer):renderer(pRenderer)
38     {
39     }
40
41     ~Impl()
42     {
43         clear(true);
44         delete(renderer);
45     }
46
47     Result push(unique_ptr<Paint> paint)
48     {
49         auto p = paint.release();
50         if (!p) return Result::MemoryCorruption;
51         paints.push(p);
52
53         return update(p, true);
54     }
55
56     Result clear(bool free)
57     {
58         //Clear render target before drawing
59         if (!renderer || !renderer->clear()) return Result::InsufficientCondition;
60
61         //free paints
62         if (free) {
63             for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
64                 (*paint)->pImpl->dispose(*renderer);
65                 delete(*paint);
66             }
67         }
68
69         paints.clear();
70
71         return Result::Success;
72     }
73
74     void needRefresh()
75     {
76         refresh = true;
77     }
78
79     Result update(Paint* paint, bool force)
80     {
81         if (!renderer) return Result::InsufficientCondition;
82
83         Array<RenderData> clips;
84         auto flag = RenderUpdateFlag::None;
85         if (refresh || force) flag = RenderUpdateFlag::All;
86
87         //Update single paint node
88         if (paint) {
89             dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) update a paint(%p)", this, paint);
90             paint->pImpl->update(*renderer, nullptr, 255, clips, flag);
91         //Update all retained paint nodes
92         } else {
93             dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) update paints count(%d)", this, paints.count);
94             for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
95                 (*paint)->pImpl->update(*renderer, nullptr, 255, clips, flag);
96             }
97         }
98
99         refresh = false;
100
101         dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) update finished", this);
102
103         return Result::Success;
104     }
105
106     Result draw()
107     {
108         if (!renderer || !renderer->preRender()) return Result::InsufficientCondition;
109
110         dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) draw paints count(%d)", this, paints.count);
111
112         for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
113             if (!(*paint)->pImpl->render(*renderer)) return Result::InsufficientCondition;
114         }
115
116         if (!renderer->postRender()) return Result::InsufficientCondition;
117
118         dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) draw finished", this);
119
120         return Result::Success;
121     }
122 };
123
124 #endif /* _TVG_CANVAS_IMPL_H_ */