Skip to content

Commit e246843

Browse files
committed
feat(gui): add canvas widget
1 parent 5020b91 commit e246843

File tree

7 files changed

+1275
-1018
lines changed

7 files changed

+1275
-1018
lines changed

build/windows/LCUI/LCUI.vcxproj

+455-451
Large diffs are not rendered by default.

build/windows/LCUI/LCUI.vcxproj.filters

+570-564
Large diffs are not rendered by default.

include/LCUI/gui/widget/canvas.h

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* canvas.h -- canvas, used to draw custom graphics
3+
*
4+
* Copyright (c) 2019, Liu chao <lc-soft@live.cn> All rights reserved.
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions are met:
8+
*
9+
* * Redistributions of source code must retain the above copyright notice,
10+
* this list of conditions and the following disclaimer.
11+
* * Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
* * Neither the name of LCUI nor the names of its contributors may be used
15+
* to endorse or promote products derived from this software without
16+
* specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
* POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
31+
#ifndef LCUI_CANVAS_H
32+
#define LCUI_CANVAS_H
33+
34+
LCUI_BEGIN_HEADER
35+
36+
typedef struct LCUI_CanvasRenderingContextRec_ LCUI_CanvasRenderingContextRec;
37+
typedef struct LCUI_CanvasRenderingContextRec_ *LCUI_CanvasRenderingContext;
38+
typedef LCUI_CanvasRenderingContext LCUI_CanvasContext;
39+
40+
struct LCUI_CanvasRenderingContextRec_ {
41+
LCUI_BOOL available;
42+
LCUI_Color fill_color;
43+
LCUI_Graph buffer;
44+
LCUI_Widget canvas;
45+
LinkedListNode node;
46+
47+
float scale;
48+
int width;
49+
int height;
50+
51+
void (*fillRect)(LCUI_CanvasContext, int, int, int, int);
52+
void (*clearRect)(LCUI_CanvasContext, int, int, int, int);
53+
void (*release)(LCUI_CanvasContext);
54+
};
55+
56+
LCUI_API LCUI_CanvasContext Canvas_GetContext(LCUI_Widget w);
57+
58+
void LCUIWidget_AddCanvas(void);
59+
60+
LCUI_END_HEADER
61+
62+
#endif

src/gui/Makefile.am

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ widget/textedit.c \
3131
widget/sidebar.c \
3232
widget/scrollbar.c \
3333
widget/anchor.c \
34-
widget/button.c
34+
widget/button.c \
35+
widget/canvas.c

src/gui/widget.c

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <LCUI_Build.h>
3333
#include <LCUI/LCUI.h>
3434
#include <LCUI/gui/widget.h>
35+
#include <LCUI/gui/widget/canvas.h>
3536
#include <LCUI/gui/widget/textview.h>
3637
#include <LCUI/gui/widget/textcaret.h>
3738
#include <LCUI/gui/widget/textedit.h>
@@ -49,6 +50,7 @@ void LCUI_InitWidget(void)
4950
LCUIWidget_InitRenderer();
5051
LCUIWidget_InitImageLoader();
5152
LCUIWidget_AddTextView();
53+
LCUIWidget_AddCanvas();
5254
LCUIWidget_AddAnchor();
5355
LCUIWidget_AddButton();
5456
LCUIWidget_AddSideBar();

src/gui/widget/canvas.c

+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* canvas.c -- canvas, used to draw custom graphics
3+
*
4+
* Copyright (c) 2019, Liu chao <lc-soft@live.cn> All rights reserved.
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions are met:
8+
*
9+
* * Redistributions of source code must retain the above copyright notice,
10+
* this list of conditions and the following disclaimer.
11+
* * Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
* * Neither the name of LCUI nor the names of its contributors may be used
15+
* to endorse or promote products derived from this software without
16+
* specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
* POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
31+
#include <stdlib.h>
32+
#include <LCUI_Build.h>
33+
#include <LCUI/LCUI.h>
34+
#include <LCUI/gui/widget.h>
35+
#include <LCUI/gui/metrics.h>
36+
#include <LCUI/gui/widget/canvas.h>
37+
38+
typedef struct CanvasRec_ {
39+
LCUI_Graph buffer;
40+
LinkedList contexts;
41+
} CanvasRec, *Canvas;
42+
43+
struct {
44+
LCUI_WidgetPrototype proto;
45+
} self;
46+
47+
static void Canvas_OnResize(LCUI_Widget w, LCUI_WidgetEvent e, void *arg)
48+
{
49+
float scale = LCUIMetrics_GetScale();
50+
unsigned width = (unsigned)(w->box.content.width * scale);
51+
unsigned height = (unsigned)(w->box.content.height * scale);
52+
53+
LCUI_Graph buffer;
54+
Canvas canvas = Widget_GetData(w, self.proto);
55+
56+
Graph_Init(&buffer);
57+
buffer.color_type = LCUI_COLOR_TYPE_ARGB;
58+
Graph_Create(&buffer, width, height);
59+
Graph_Replace(&buffer, &canvas->buffer, 0, 0);
60+
Graph_Free(&canvas->buffer);
61+
canvas->buffer = buffer;
62+
}
63+
64+
static void Canvas_OnInit(LCUI_Widget w)
65+
{
66+
Canvas canvas = Widget_AddData(w, self.proto, sizeof(CanvasRec));
67+
68+
Graph_Init(&canvas->buffer);
69+
LinkedList_Init(&canvas->contexts);
70+
Widget_BindEventById(w, LCUI_WEVENT_RESIZE, Canvas_OnResize, NULL,
71+
NULL);
72+
}
73+
74+
static void Canvas_OnDestroy(LCUI_Widget w)
75+
{
76+
LinkedListNode *node;
77+
LCUI_CanvasContext ctx;
78+
Canvas canvas = Widget_AddData(w, self.proto, sizeof(CanvasRec));
79+
80+
for (LinkedList_Each(node, &canvas->contexts)) {
81+
ctx = node->data;
82+
ctx->available = FALSE;
83+
}
84+
LinkedList_ClearData(&canvas->contexts, NULL);
85+
Graph_Free(&canvas->buffer);
86+
}
87+
88+
static void Canvas_AutoSize(LCUI_Widget w, float *width, float *height)
89+
{
90+
*width = 300;
91+
*height = 150;
92+
}
93+
94+
static void Canvas_OnPaint(LCUI_Widget w, LCUI_PaintContext paint,
95+
LCUI_WidgetActualStyle style)
96+
{
97+
LCUI_Graph src, dest;
98+
LCUI_Rect content_rect, rect;
99+
Canvas canvas = Widget_GetData(w, self.proto);
100+
101+
content_rect.width = style->content_box.width;
102+
content_rect.height = style->content_box.height;
103+
content_rect.x = style->content_box.x - style->canvas_box.x;
104+
content_rect.y = style->content_box.y - style->canvas_box.y;
105+
if (!LCUIRect_GetOverlayRect(&content_rect, &paint->rect, &rect)) {
106+
return;
107+
}
108+
content_rect.x = rect.x - content_rect.x;
109+
content_rect.y = rect.y - content_rect.y;
110+
content_rect.width = rect.width;
111+
content_rect.height = rect.height;
112+
rect.x -= paint->rect.x;
113+
rect.y -= paint->rect.y;
114+
Graph_Quote(&dest, &paint->canvas, &rect);
115+
Graph_Quote(&src, &canvas->buffer, &content_rect);
116+
Graph_Replace(&dest, &src, 0, 0);
117+
}
118+
119+
static void CanvasContext_ClearRect(LCUI_CanvasContext ctx, int x, int y,
120+
int width, int height)
121+
{
122+
LCUI_Rect rect;
123+
124+
rect.x = x;
125+
rect.y = y;
126+
rect.width = width;
127+
rect.height = height;
128+
Graph_FillRect(&ctx->buffer, ARGB(0, 0, 0, 0), &rect, TRUE);
129+
}
130+
131+
static void CanvasContext_FillRect(LCUI_CanvasContext ctx, int x, int y,
132+
int width, int height)
133+
{
134+
LCUI_Rect rect;
135+
136+
rect.x = x;
137+
rect.y = y;
138+
rect.width = width;
139+
rect.height = height;
140+
Graph_FillRect(&ctx->buffer, ctx->fill_color, &rect, TRUE);
141+
}
142+
143+
static void CanvasContext_Release(LCUI_CanvasContext ctx)
144+
{
145+
Canvas canvas;
146+
147+
if (ctx->available) {
148+
canvas = Widget_GetData(ctx->canvas, self.proto);
149+
LinkedList_Unlink(&canvas->contexts, &ctx->node);
150+
}
151+
free(ctx);
152+
}
153+
154+
LCUI_CanvasContext Canvas_GetContext(LCUI_Widget w)
155+
{
156+
ASSIGN(ctx, LCUI_CanvasRenderingContext);
157+
Canvas canvas = Widget_GetData(w, self.proto);
158+
159+
ctx->canvas = w;
160+
ctx->available = TRUE;
161+
ctx->buffer = canvas->buffer;
162+
ctx->width = ctx->buffer.width;
163+
ctx->height = ctx->buffer.height;
164+
ctx->fill_color = RGB(0, 0, 0);
165+
ctx->scale = LCUIMetrics_GetScale();
166+
ctx->clearRect = CanvasContext_ClearRect;
167+
ctx->fillRect = CanvasContext_FillRect;
168+
ctx->release = CanvasContext_Release;
169+
ctx->node.data = ctx;
170+
ctx->node.next = ctx->node.prev = NULL;
171+
LinkedList_AppendNode(&canvas->contexts, &ctx->node);
172+
return ctx;
173+
}
174+
175+
void LCUIWidget_AddCanvas(void)
176+
{
177+
self.proto = LCUIWidget_NewPrototype("canvas", NULL);
178+
self.proto->init = Canvas_OnInit;
179+
self.proto->destroy = Canvas_OnDestroy;
180+
self.proto->paint = Canvas_OnPaint;
181+
self.proto->autosize = Canvas_AutoSize;
182+
}

test/Makefile.am

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
AUTOMAKE_OPTIONS=foreign
1+
AUTOMAKE_OPTIONS=subdir-objects foreign
22
##设定在编译时头文件的查找位置
3-
AM_CFLAGS = -I$(top_builddir)/include $(CODE_COVERAGE_CFLAGS)
3+
AM_CFLAGS = -I$(top_srcdir)/include $(CODE_COVERAGE_CFLAGS)
44
##需要编译的测试程序, noinst指的是不安装
55
noinst_PROGRAMS = helloworld test test_charset test_touch test_char_render \
66
test_string_render test_widget_render test_widget_layout test_widget_rect \

0 commit comments

Comments
 (0)