Skip to content

Commit

Permalink
feat(gui): add canvas widget
Browse files Browse the repository at this point in the history
  • Loading branch information
lc-soft committed Oct 3, 2019
1 parent 5020b91 commit e246843
Show file tree
Hide file tree
Showing 7 changed files with 1,275 additions and 1,018 deletions.
906 changes: 455 additions & 451 deletions build/windows/LCUI/LCUI.vcxproj

Large diffs are not rendered by default.

1,134 changes: 570 additions & 564 deletions build/windows/LCUI/LCUI.vcxproj.filters

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions include/LCUI/gui/widget/canvas.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* canvas.h -- canvas, used to draw custom graphics
*
* Copyright (c) 2019, Liu chao <lc-soft@live.cn> All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of LCUI nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef LCUI_CANVAS_H
#define LCUI_CANVAS_H

LCUI_BEGIN_HEADER

typedef struct LCUI_CanvasRenderingContextRec_ LCUI_CanvasRenderingContextRec;
typedef struct LCUI_CanvasRenderingContextRec_ *LCUI_CanvasRenderingContext;
typedef LCUI_CanvasRenderingContext LCUI_CanvasContext;

struct LCUI_CanvasRenderingContextRec_ {
LCUI_BOOL available;
LCUI_Color fill_color;
LCUI_Graph buffer;
LCUI_Widget canvas;
LinkedListNode node;

float scale;
int width;
int height;

void (*fillRect)(LCUI_CanvasContext, int, int, int, int);
void (*clearRect)(LCUI_CanvasContext, int, int, int, int);
void (*release)(LCUI_CanvasContext);
};

LCUI_API LCUI_CanvasContext Canvas_GetContext(LCUI_Widget w);

void LCUIWidget_AddCanvas(void);

LCUI_END_HEADER

#endif
3 changes: 2 additions & 1 deletion src/gui/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ widget/textedit.c \
widget/sidebar.c \
widget/scrollbar.c \
widget/anchor.c \
widget/button.c
widget/button.c \
widget/canvas.c
2 changes: 2 additions & 0 deletions src/gui/widget.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <LCUI_Build.h>
#include <LCUI/LCUI.h>
#include <LCUI/gui/widget.h>
#include <LCUI/gui/widget/canvas.h>
#include <LCUI/gui/widget/textview.h>
#include <LCUI/gui/widget/textcaret.h>
#include <LCUI/gui/widget/textedit.h>
Expand All @@ -49,6 +50,7 @@ void LCUI_InitWidget(void)
LCUIWidget_InitRenderer();
LCUIWidget_InitImageLoader();
LCUIWidget_AddTextView();
LCUIWidget_AddCanvas();
LCUIWidget_AddAnchor();
LCUIWidget_AddButton();
LCUIWidget_AddSideBar();
Expand Down
182 changes: 182 additions & 0 deletions src/gui/widget/canvas.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/*
* canvas.c -- canvas, used to draw custom graphics
*
* Copyright (c) 2019, Liu chao <lc-soft@live.cn> All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of LCUI nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include <stdlib.h>
#include <LCUI_Build.h>
#include <LCUI/LCUI.h>
#include <LCUI/gui/widget.h>
#include <LCUI/gui/metrics.h>
#include <LCUI/gui/widget/canvas.h>

typedef struct CanvasRec_ {
LCUI_Graph buffer;
LinkedList contexts;
} CanvasRec, *Canvas;

struct {
LCUI_WidgetPrototype proto;
} self;

static void Canvas_OnResize(LCUI_Widget w, LCUI_WidgetEvent e, void *arg)
{
float scale = LCUIMetrics_GetScale();
unsigned width = (unsigned)(w->box.content.width * scale);
unsigned height = (unsigned)(w->box.content.height * scale);

LCUI_Graph buffer;
Canvas canvas = Widget_GetData(w, self.proto);

Graph_Init(&buffer);
buffer.color_type = LCUI_COLOR_TYPE_ARGB;
Graph_Create(&buffer, width, height);
Graph_Replace(&buffer, &canvas->buffer, 0, 0);
Graph_Free(&canvas->buffer);
canvas->buffer = buffer;
}

static void Canvas_OnInit(LCUI_Widget w)
{
Canvas canvas = Widget_AddData(w, self.proto, sizeof(CanvasRec));

Graph_Init(&canvas->buffer);
LinkedList_Init(&canvas->contexts);
Widget_BindEventById(w, LCUI_WEVENT_RESIZE, Canvas_OnResize, NULL,
NULL);
}

static void Canvas_OnDestroy(LCUI_Widget w)
{
LinkedListNode *node;
LCUI_CanvasContext ctx;
Canvas canvas = Widget_AddData(w, self.proto, sizeof(CanvasRec));

for (LinkedList_Each(node, &canvas->contexts)) {
ctx = node->data;
ctx->available = FALSE;
}
LinkedList_ClearData(&canvas->contexts, NULL);
Graph_Free(&canvas->buffer);
}

static void Canvas_AutoSize(LCUI_Widget w, float *width, float *height)
{
*width = 300;
*height = 150;
}

static void Canvas_OnPaint(LCUI_Widget w, LCUI_PaintContext paint,
LCUI_WidgetActualStyle style)
{
LCUI_Graph src, dest;
LCUI_Rect content_rect, rect;
Canvas canvas = Widget_GetData(w, self.proto);

content_rect.width = style->content_box.width;
content_rect.height = style->content_box.height;
content_rect.x = style->content_box.x - style->canvas_box.x;
content_rect.y = style->content_box.y - style->canvas_box.y;
if (!LCUIRect_GetOverlayRect(&content_rect, &paint->rect, &rect)) {
return;
}
content_rect.x = rect.x - content_rect.x;
content_rect.y = rect.y - content_rect.y;
content_rect.width = rect.width;
content_rect.height = rect.height;
rect.x -= paint->rect.x;
rect.y -= paint->rect.y;
Graph_Quote(&dest, &paint->canvas, &rect);
Graph_Quote(&src, &canvas->buffer, &content_rect);
Graph_Replace(&dest, &src, 0, 0);
}

static void CanvasContext_ClearRect(LCUI_CanvasContext ctx, int x, int y,
int width, int height)
{
LCUI_Rect rect;

rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
Graph_FillRect(&ctx->buffer, ARGB(0, 0, 0, 0), &rect, TRUE);
}

static void CanvasContext_FillRect(LCUI_CanvasContext ctx, int x, int y,
int width, int height)
{
LCUI_Rect rect;

rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
Graph_FillRect(&ctx->buffer, ctx->fill_color, &rect, TRUE);
}

static void CanvasContext_Release(LCUI_CanvasContext ctx)
{
Canvas canvas;

if (ctx->available) {
canvas = Widget_GetData(ctx->canvas, self.proto);
LinkedList_Unlink(&canvas->contexts, &ctx->node);
}
free(ctx);
}

LCUI_CanvasContext Canvas_GetContext(LCUI_Widget w)
{
ASSIGN(ctx, LCUI_CanvasRenderingContext);
Canvas canvas = Widget_GetData(w, self.proto);

ctx->canvas = w;
ctx->available = TRUE;
ctx->buffer = canvas->buffer;
ctx->width = ctx->buffer.width;
ctx->height = ctx->buffer.height;
ctx->fill_color = RGB(0, 0, 0);
ctx->scale = LCUIMetrics_GetScale();
ctx->clearRect = CanvasContext_ClearRect;
ctx->fillRect = CanvasContext_FillRect;
ctx->release = CanvasContext_Release;
ctx->node.data = ctx;
ctx->node.next = ctx->node.prev = NULL;
LinkedList_AppendNode(&canvas->contexts, &ctx->node);
return ctx;
}

void LCUIWidget_AddCanvas(void)
{
self.proto = LCUIWidget_NewPrototype("canvas", NULL);
self.proto->init = Canvas_OnInit;
self.proto->destroy = Canvas_OnDestroy;
self.proto->paint = Canvas_OnPaint;
self.proto->autosize = Canvas_AutoSize;
}
4 changes: 2 additions & 2 deletions test/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS=foreign
AUTOMAKE_OPTIONS=subdir-objects foreign
##设定在编译时头文件的查找位置
AM_CFLAGS = -I$(top_builddir)/include $(CODE_COVERAGE_CFLAGS)
AM_CFLAGS = -I$(top_srcdir)/include $(CODE_COVERAGE_CFLAGS)
##需要编译的测试程序, noinst指的是不安装
noinst_PROGRAMS = helloworld test test_charset test_touch test_char_render \
test_string_render test_widget_render test_widget_layout test_widget_rect \
Expand Down

0 comments on commit e246843

Please sign in to comment.