add vgcanvas_get_clip_rect

This commit is contained in:
lixianjing 2021-11-05 06:49:44 +08:00
parent 0e7df7ba2d
commit 9c063d57c6
19 changed files with 294 additions and 137 deletions

View File

@ -1045,6 +1045,36 @@ static void nvg__isectRects(float* dst,
dst[3] = nvg__maxf(0.0f, maxy - miny);
}
int nvgGetCurrScissor(NVGcontext* ctx, float* x, float* y, float* w, float* h)
{
NVGstate* state = nvg__getState(ctx);
float pxform[6], invxorm[6];
float rect[4];
float ex, ey, tex, tey;
// If no previous scissor has been set, set the scissor as current scissor.
if (state->scissor.extent[0] < 0) {
*w = 0;
*h = 0;
return 0;
}
// Transform the current scissor rect into current transform space.
// If there is difference in rotation, this will be approximation.
memcpy(pxform, state->scissor.xform, sizeof(float)*6);
ex = state->scissor.extent[0];
ey = state->scissor.extent[1];
nvgTransformInverse(invxorm, state->xform);
nvgTransformMultiply(pxform, invxorm);
tex = ex*nvg__absf(pxform[0]) + ey*nvg__absf(pxform[2]);
tey = ex*nvg__absf(pxform[1]) + ey*nvg__absf(pxform[3]);
*x = pxform[4] - tex;
*y = pxform[5] - tey;
*w = tex * 2;
*h = tey * 2;
return 1;
}
void nvgIntersectScissorForOtherRect(NVGcontext* ctx, float x, float y, float w, float h, float dx, float dy, float dw, float dh)
{

View File

@ -457,13 +457,26 @@ void nvgIntersectScissor(NVGcontext* ctx, float x, float y, float w, float h);
* @param {float_t} w
* @param {float_t} h
*
* @return {ret_t} RET_OK表示成功
*/
void nvgIntersectScissor_ex(NVGcontext* ctx, float* x, float* y, float* w, float* h);
// Reset and disables scissoring.
void nvgResetScissor(NVGcontext* ctx);
/**
* @method nvgGetCurrScissor
*
*
* @annotation ["scriptable"]
* @param {NVGcontext*} ctx nanovg的对象
* @param {float_t*} x x坐标
* @param {float_t*} y y坐标
* @param {float_t*} w
* @param {float_t*} h
*
* @return {int} 1 0
*/
int nvgGetCurrScissor(NVGcontext* ctx, float* x, float* y, float* w, float* h);
/**
* @method nvgIntersectScissorForOtherRect

View File

@ -1,5 +1,8 @@
# 最新动态
2021/11/05
* 增加了nanovg获取当前裁剪区的函数和增加矩形是否在裁剪区的函数以及统一修改相关判断是否在裁剪区的代码感谢智明提供补丁
2021/11/03
* 增加 fs\_foreach\_file
* 完善 demoui 界面(感谢兆坤提供补丁)

View File

@ -146,64 +146,30 @@ ret_t canvas_get_clip_rect(canvas_t* c, rect_t* r) {
return RET_OK;
}
bool_t canvas_is_rect_in_clip_rect(canvas_t* c, xy_t left, xy_t top, xy_t right, xy_t bottom) {
if (c->lcd->is_rect_in_clip_rect != NULL) {
return c->lcd->is_rect_in_clip_rect(c->lcd, left, top, right, bottom);
} else {
if (left > c->clip_right || right < c->clip_left || top > c->clip_bottom || bottom < c->clip_top) {
return FALSE;
}
return TRUE;
}
}
ret_t canvas_set_clip_rect(canvas_t* c, const rect_t* r_in) {
wh_t lcd_w = 0;
wh_t lcd_h = 0;
rect_t r_fix = rect_init(0, 0, 0, 0);
rect_t* r = canvas_fix_rect(r_in, &r_fix);
#ifdef FRAGMENT_FRAME_BUFFER_SIZE
rect_t dirty_r;
lcd_get_dirty_rect(c->lcd, &dirty_r);
#endif
return_value_if_fail(c != NULL, RET_BAD_PARAMS);
lcd_w = lcd_get_width(c->lcd);
lcd_h = lcd_get_height(c->lcd);
if (r) {
#ifdef FRAGMENT_FRAME_BUFFER_SIZE
r_fix = rect_intersect(&r_fix, &dirty_r);
#endif
c->clip_left = tk_max(0, r->x);
c->clip_top = tk_max(0, r->y);
c->clip_right = r->x + r->w - 1;
c->clip_bottom = r->y + r->h - 1;
} else {
#ifdef FRAGMENT_FRAME_BUFFER_SIZE
c->clip_left = tk_max(0, dirty_r.x);
c->clip_top = tk_max(0, dirty_r.y);
c->clip_right = dirty_r.x + dirty_r.w - 1;
c->clip_bottom = dirty_r.y + dirty_r.h - 1;
#else
c->clip_left = 0;
c->clip_top = 0;
c->clip_right = lcd_w - 1;
c->clip_bottom = lcd_h - 1;
#endif
}
if (c->clip_left < 0) {
c->clip_left = 0;
}
if (c->clip_top < 0) {
c->clip_top = 0;
}
if (c->clip_right >= lcd_w) {
c->clip_right = lcd_w - 1;
}
if (c->clip_bottom >= lcd_h) {
c->clip_bottom = lcd_h - 1;
}
if (c->lcd->set_clip_rect != NULL) {
/* 在 opengl 的状态下让 vg 来处理裁剪区的大小直接交给 vg 来处理,去除 LCD 的大小限制的问题 */
if (r) {
if (r != NULL) {
rect_t clip_r = rect_init(tk_max(0, r->x), tk_max(0, r->y), tk_max(0, r->w), tk_max(0, r->h));
lcd_set_clip_rect(c->lcd, &clip_r);
} else {
@ -211,12 +177,25 @@ ret_t canvas_set_clip_rect(canvas_t* c, const rect_t* r_in) {
lcd_set_clip_rect(c->lcd, &clip_r);
}
#ifdef WITH_GPU
/* 兼容以前的逻辑,以免以前的用户不使用 canvas_is_rect_in_clip_rect 来判断出问题 */
/* 把 canvas 的裁剪区设置为无限大,在 opengl 的状态下让 vg 来处理裁剪区的问题 */
c->clip_left = 0;
c->clip_top = 0;
c->clip_right = 0x7fffffff;
c->clip_bottom = 0x7fffffff;
#endif
} else {
if (r != NULL) {
c->clip_left = tk_max(0, r->x);
c->clip_top = tk_max(0, r->y);
c->clip_right = tk_min(lcd_w - 1, r->x + r->w - 1);
c->clip_bottom = tk_min(lcd_h - 1, r->y + r->h - 1);
} else {
c->clip_left = 0;
c->clip_top = 0;
c->clip_right = lcd_w - 1;
c->clip_bottom = lcd_h - 1;
}
}
return RET_OK;
@ -389,14 +368,16 @@ ret_t canvas_begin_frame(canvas_t* c, const dirty_rects_t* dirty_rects, lcd_draw
}
static ret_t canvas_draw_hline_impl(canvas_t* c, xy_t x, xy_t y, wh_t w) {
rect_t r;
xy_t x2 = x + w - 1;
if (y < c->clip_top || y > c->clip_bottom || x2 < c->clip_left || x > c->clip_right) {
if (!canvas_is_rect_in_clip_rect(c, x, y, x2, y)) {
return RET_OK;
}
canvas_get_clip_rect(c, &r);
x = tk_max(x, c->clip_left);
x2 = tk_min(x2, c->clip_right);
x = tk_max(x, r.x);
x2 = tk_min(x2, r.x + r.w - 1);
w = x2 - x + 1;
return lcd_draw_hline(c->lcd, x, y, w);
@ -413,14 +394,16 @@ ret_t canvas_draw_hline(canvas_t* c, xy_t x, xy_t y, wh_t w) {
}
static ret_t canvas_draw_vline_impl(canvas_t* c, xy_t x, xy_t y, wh_t h) {
rect_t r;
xy_t y2 = y + h - 1;
if (x < c->clip_left || x > c->clip_right || y2 < c->clip_top || y > c->clip_bottom) {
if (!canvas_is_rect_in_clip_rect(c, x, y, x, y2)) {
return RET_OK;
}
canvas_get_clip_rect(c, &r);
y = tk_max(y, c->clip_top);
y2 = tk_min(y2, c->clip_bottom);
y = tk_max(y, r.y);
y2 = tk_min(y2, r.y + r.h - 1);
h = y2 - y + 1;
return lcd_draw_vline(c->lcd, x, y, h);
@ -438,11 +421,6 @@ ret_t canvas_draw_vline(canvas_t* c, xy_t x, xy_t y, wh_t h) {
}
static ret_t canvas_draw_line_impl(canvas_t* c, xy_t x1, xy_t y1, xy_t x2, xy_t y2) {
if ((x1 < c->clip_left && x2 < c->clip_left) || (x1 > c->clip_right && x2 > c->clip_right) ||
(y1 < c->clip_top && y2 < c->clip_top) || (y1 > c->clip_bottom && y2 > c->clip_bottom)) {
return RET_OK;
}
if (x1 == x2) {
return canvas_draw_vline_impl(c, x1, y1, tk_abs(y2 - y1) + 1);
} else if (y1 == y2) {
@ -464,22 +442,20 @@ ret_t canvas_draw_line(canvas_t* c, xy_t x1, xy_t y1, xy_t x2, xy_t y2) {
static ret_t canvas_do_draw_points(canvas_t* c, const point_t* points, uint32_t nr) {
uint32_t i = 0;
uint32_t real_nr = 0;
xy_t left = c->clip_left;
xy_t top = c->clip_top;
xy_t right = c->clip_right;
xy_t bottom = c->clip_bottom;
point_t real_points[MAX_POINTS_PER_DRAW];
return_value_if_fail(nr <= MAX_POINTS_PER_DRAW, RET_BAD_PARAMS);
for (i = 0; i < nr; i++) {
const point_t* p = points + i;
if (p->x < left || p->x > right || p->y < top || p->y > bottom) {
xy_t x = p->x + c->ox;
xy_t y = p->y + c->oy;
if (!canvas_is_rect_in_clip_rect(c, x, y, x, y)) {
continue;
}
real_points[real_nr].x = p->x + c->ox;
real_points[real_nr].y = p->y + c->oy;
real_points[real_nr].x = x;
real_points[real_nr].y = y;
real_nr++;
}
@ -512,17 +488,19 @@ ret_t canvas_draw_points(canvas_t* c, const point_t* points, uint32_t nr) {
}
static ret_t canvas_fill_rect_impl(canvas_t* c, xy_t x, xy_t y, wh_t w, wh_t h) {
rect_t r;
xy_t x2 = x + w - 1;
xy_t y2 = y + h - 1;
if (x > c->clip_right || x2 < c->clip_left || y > c->clip_bottom || y2 < c->clip_top) {
if (!canvas_is_rect_in_clip_rect(c, x, y, x2, y2)) {
return RET_OK;
}
canvas_get_clip_rect(c, &r);
x = tk_max(x, c->clip_left);
y = tk_max(y, c->clip_top);
x2 = tk_min(x2, c->clip_right);
y2 = tk_min(y2, c->clip_bottom);
x = tk_max(x, r.x);
y = tk_max(y, r.y);
x2 = tk_min(x2, r.x + r.w - 1);
y2 = tk_min(y2, r.y + r.h - 1);
w = x2 - x + 1;
h = y2 - y + 1;
@ -538,18 +516,21 @@ ret_t canvas_fill_rect(canvas_t* c, xy_t x, xy_t y, wh_t w, wh_t h) {
static ret_t canvas_fill_rect_gradient_impl(canvas_t* c, xy_t x, xy_t y, wh_t w, wh_t h,
gradient_t* gradient) {
rect_t r;
xy_t x2 = x + w - 1;
xy_t y2 = y + h - 1;
vgcanvas_t* vg = NULL;
if (x > c->clip_right || x2 < c->clip_left || y > c->clip_bottom || y2 < c->clip_top) {
if (!canvas_is_rect_in_clip_rect(c, x, y, x2, y2)) {
return RET_OK;
}
x = tk_max(x, c->clip_left);
y = tk_max(y, c->clip_top);
x2 = tk_min(x2, c->clip_right);
y2 = tk_min(y2, c->clip_bottom);
canvas_get_clip_rect(c, &r);
x = tk_max(x, r.x);
y = tk_max(y, r.y);
x2 = tk_min(x2, r.x + r.w - 1);
y2 = tk_min(y2, r.y + r.h - 1);
w = x2 - x + 1;
h = y2 - y + 1;
if (w == 0 || h == 0) {
@ -596,17 +577,20 @@ ret_t canvas_fill_rect_gradient(canvas_t* c, xy_t x, xy_t y, wh_t w, wh_t h, gra
}
static ret_t canvas_clear_rect_impl(canvas_t* c, xy_t x, xy_t y, wh_t w, wh_t h) {
rect_t r;
xy_t x2 = x + w - 1;
xy_t y2 = y + h - 1;
if (x > c->clip_right || x2 < c->clip_left || y > c->clip_bottom || y2 < c->clip_top) {
if (!canvas_is_rect_in_clip_rect(c, x, y, x2, y2)) {
return RET_OK;
}
x = tk_max(x, c->clip_left);
y = tk_max(y, c->clip_top);
x2 = tk_min(x2, c->clip_right);
y2 = tk_min(y2, c->clip_bottom);
canvas_get_clip_rect(c, &r);
x = tk_max(x, r.x);
y = tk_max(y, r.y);
x2 = tk_min(x2, r.x + r.w - 1);
y2 = tk_min(y2, r.y + r.h - 1);
w = x2 - x + 1;
h = y2 - y + 1;
@ -643,20 +627,21 @@ ret_t canvas_stroke_rect(canvas_t* c, xy_t x, xy_t y, wh_t w, wh_t h) {
}
static ret_t canvas_draw_glyph(canvas_t* c, glyph_t* g, xy_t x, xy_t y) {
rect_t r;
rect_t src;
rect_t dst;
xy_t x2 = x + g->w - 1;
xy_t y2 = y + g->h - 1;
if (g->data == NULL || x > c->clip_right || x2 < c->clip_left || y > c->clip_bottom ||
y2 < c->clip_top) {
if (g->data == NULL || !canvas_is_rect_in_clip_rect(c, x, y, x2, y2)) {
return RET_OK;
}
canvas_get_clip_rect(c, &r);
dst.x = tk_max(x, c->clip_left);
dst.y = tk_max(y, c->clip_top);
dst.w = tk_min(x2, c->clip_right) - dst.x + 1;
dst.h = tk_min(y2, c->clip_bottom) - dst.y + 1;
dst.x = tk_max(x, r.x);
dst.y = tk_max(y, r.y);
dst.w = tk_min(x2, r.x + r.w - 1) - dst.x + 1;
dst.h = tk_min(y2, r.y + r.h - 1) - dst.y + 1;
src.x = dst.x - x;
src.y = dst.y - y;
@ -752,6 +737,7 @@ ret_t canvas_draw_utf8(canvas_t* c, const char* str, xy_t x, xy_t y) {
}
static ret_t canvas_do_draw_image(canvas_t* c, bitmap_t* img, const rect_t* s, const rect_t* d) {
rect_t r;
rectf_t src;
rectf_t dst;
float_t scale_w = 0;
@ -762,15 +748,16 @@ static ret_t canvas_do_draw_image(canvas_t* c, bitmap_t* img, const rect_t* s, c
xy_t x2 = d->x + d->w - 1;
xy_t y2 = d->y + d->h - 1;
if (d->w <= 0 || d->h <= 0 || s->w <= 0 || s->h <= 0 || x > c->clip_right || x2 < c->clip_left ||
y > c->clip_bottom || y2 < c->clip_top) {
if (d->w <= 0 || d->h <= 0 || s->w <= 0 || s->h <= 0 ||
!canvas_is_rect_in_clip_rect(c, x, y, x2, y2)) {
return RET_OK;
}
canvas_get_clip_rect(c, &r);
dst.x = tk_max(x, c->clip_left);
dst.y = tk_max(y, c->clip_top);
dst.w = tk_min(x2, c->clip_right) - dst.x + 1;
dst.h = tk_min(y2, c->clip_bottom) - dst.y + 1;
dst.x = tk_max(x, r.x);
dst.y = tk_max(y, r.y);
dst.w = tk_min(x2, r.x + r.w - 1) - dst.x + 1;
dst.h = tk_min(y2, r.y + r.h - 1) - dst.y + 1;
/* 因为 blend 函数中缩放,使用 256 倍的定点数,所以这里为了减低多次转换数据出现误差 */
scale_w = ((s->w << 8) / d->w / 256.0f);
@ -1611,8 +1598,7 @@ ret_t canvas_draw_image_matrix(canvas_t* c, bitmap_t* img, matrix_t* matrix) {
info.matrix = *matrix;
info.src = rect_init(0, 0, img->w, img->h);
info.dst = rect_init(0, 0, img->w, img->h);
info.clip = rect_init(c->clip_left, c->clip_top, c->clip_right - c->clip_left,
c->clip_bottom - c->clip_top);
canvas_get_clip_rect(c, &info.clip);
return lcd_draw_image_matrix(c->lcd, &info);
}

View File

@ -215,6 +215,19 @@ wh_t canvas_get_height(canvas_t* c);
*/
ret_t canvas_get_clip_rect(canvas_t* c, rect_t* r);
/**
* @method canvas_is_rect_in_clip_rect
*
* @param {canvas_t*} c canvas对象
* @param {xy_t} left
* @param {xy_t} top
* @param {xy_t} right
* @param {xy_t} bottom
*
* @return {ret_t} RET_OK表示成功
*/
bool_t canvas_is_rect_in_clip_rect(canvas_t* c, xy_t left, xy_t top, xy_t right, xy_t bottom);
/**
* @method canvas_set_clip_rect
*

View File

@ -273,8 +273,7 @@ ret_t canvas_offline_begin_draw(canvas_t* canvas) {
c = (canvas_offline_gpu_t*)canvas;
if (vg != NULL && canvas_offline->begin_draw == 0) {
canvas_get_clip_rect(canvas, &canvas_offline->canvas_clip_rect);
canvas_offline->vg_clip_rect =
rect_init(vg->clip_rect.x, vg->clip_rect.y, vg->clip_rect.w, vg->clip_rect.h);
canvas_offline->vg_clip_rect = rect_from_rectf(vgcanvas_get_clip_rect(vg));
c->base.lcd_w = canvas->lcd->w;
c->base.lcd_h = canvas->lcd->h;

View File

@ -1062,8 +1062,7 @@ static ret_t ffr_draw_fill_rounded_rect_ex(canvas_t* c, const rect_t* r, const r
xy_t y2 = y + r->h - 1;
return_value_if_fail(c != NULL && r != NULL && gradient != NULL, RET_BAD_PARAMS);
if (x > c->clip_right || x2 < c->clip_left ||
y > c->clip_bottom || y2 < c->clip_top) {
if (!canvas_is_rect_in_clip_rect(c, x, y, x2, y2)) {
return RET_OK;
}
@ -1092,8 +1091,7 @@ static ret_t ffr_draw_stroke_rounded_rect_ex(canvas_t* c, const rect_t* r, const
xy_t y2 = y + r->h - 1;
return_value_if_fail(c != NULL && r != NULL && color != NULL, RET_BAD_PARAMS);
tc = *color;
if (x > c->clip_right || x2 < c->clip_left ||
y > c->clip_bottom || y2 < c->clip_top || border_model == BORDER_NONE) {
if (!canvas_is_rect_in_clip_rect(c, x, y, x2, y2) || border_model == BORDER_NONE) {
return RET_OK;
}

View File

@ -49,6 +49,7 @@ typedef ret_t (*lcd_get_dirty_rect_t)(lcd_t* lcd, rect_t* r);
typedef const dirty_rects_t* (*lcd_get_dirty_rects_t)(lcd_t* lcd);
typedef ret_t (*lcd_begin_frame_t)(lcd_t* lcd, const dirty_rects_t* dirty_rects);
typedef bool_t(*lcd_is_rect_in_clip_rect_t)(lcd_t* lcd, xy_t left, xy_t top, xy_t right, xy_t bottom);
typedef ret_t (*lcd_set_clip_rect_t)(lcd_t* lcd, const rect_t* rect);
typedef ret_t (*lcd_get_clip_rect_t)(lcd_t* lcd, rect_t* rect);
typedef ret_t (*lcd_set_orientation_t)(lcd_t* lcd, lcd_orientation_t old_orientation,
@ -180,6 +181,7 @@ struct _lcd_t {
lcd_begin_frame_t begin_frame;
lcd_set_clip_rect_t set_clip_rect;
lcd_get_clip_rect_t get_clip_rect;
lcd_is_rect_in_clip_rect_t is_rect_in_clip_rect;
lcd_set_global_alpha_t set_global_alpha;
lcd_set_text_color_t set_text_color;
lcd_set_stroke_color_t set_stroke_color;

View File

@ -101,32 +101,28 @@ ret_t vgcanvas_clip_path(vgcanvas_t* vg) {
return vg->vt->clip_path(vg);
}
bool_t vgcanvas_is_rectf_int_clip_rect(vgcanvas_t* vg, float_t left, float_t top, float_t right, float_t bottom) {
return_value_if_fail(vg != NULL && vg->vt->is_rectf_int_clip_rect != NULL, FALSE);
return vg->vt->is_rectf_int_clip_rect(vg, left, top, right, bottom);
}
const rectf_t* vgcanvas_get_clip_rect(vgcanvas_t* vg) {
return_value_if_fail(vg != NULL && vg->vt->get_clip_rect != NULL, NULL);
return vg->vt->get_clip_rect(vg);
}
ret_t vgcanvas_clip_rect(vgcanvas_t* vg, float_t x, float_t y, float_t w, float_t h) {
return_value_if_fail(vg != NULL && vg->vt->clip_rect != NULL, RET_BAD_PARAMS);
fix_xywh(x, y, w, h);
vg->clip_rect.x = x;
vg->clip_rect.y = y;
vg->clip_rect.w = w;
vg->clip_rect.h = h;
return vg->vt->clip_rect(vg, x, y, w, h);
}
ret_t vgcanvas_intersect_clip_rect(vgcanvas_t* vg, float_t x, float_t y, float_t w, float_t h) {
ret_t ret = RET_OK;
return_value_if_fail(vg != NULL && vg->vt->intersect_clip_rect != NULL, RET_BAD_PARAMS);
fix_xywh(x, y, w, h);
ret = vg->vt->intersect_clip_rect(vg, &x, &y, &w, &h);
vg->clip_rect.x = x;
vg->clip_rect.y = y;
vg->clip_rect.w = w;
vg->clip_rect.h = h;
return ret;
return vg->vt->intersect_clip_rect(vg, &x, &y, &w, &h);
}
ret_t vgcanvas_fill(vgcanvas_t* vg) {

View File

@ -85,6 +85,8 @@ typedef ret_t (*vgcanvas_set_transform_t)(vgcanvas_t* vg, float_t a, float_t b,
float_t d, float_t e, float_t f);
typedef ret_t (*vgcanvas_clip_path_t)(vgcanvas_t* vg);
typedef const rectf_t* (*vgcanvas_get_clip_rect_t)(vgcanvas_t* vg);
typedef bool_t(*vgcanvas_is_rectf_int_clip_rect_t)(vgcanvas_t* vg, float_t left, float_t top, float_t right, float_t bottom);
typedef ret_t (*vgcanvas_clip_rect_t)(vgcanvas_t* vg, float_t x, float_t y, float_t w, float_t h);
typedef ret_t (*vgcanvas_nanovg_intersect_clip_rect_t)(vgcanvas_t* vg, float_t* x, float_t* y,
float_t* w, float_t* h);
@ -185,6 +187,8 @@ typedef struct _vgcanvas_vtable_t {
vgcanvas_clip_path_t clip_path;
vgcanvas_clip_rect_t clip_rect;
vgcanvas_get_clip_rect_t get_clip_rect;
vgcanvas_is_rectf_int_clip_rect_t is_rectf_int_clip_rect;
vgcanvas_nanovg_intersect_clip_rect_t intersect_clip_rect;
vgcanvas_fill_t fill;
vgcanvas_stroke_t stroke;
@ -398,7 +402,7 @@ struct _vgcanvas_t {
* frame buffer format
*/
bitmap_format_t format;
rect_t clip_rect;
rectf_t clip_rect;
rect_t dirty_rect;
const vgcanvas_vtable_t* vt;
assets_manager_t* assets_manager;
@ -792,6 +796,32 @@ ret_t vgcanvas_clip_path(vgcanvas_t* vg);
*/
ret_t vgcanvas_clip_rect(vgcanvas_t* vg, float_t x, float_t y, float_t w, float_t h);
/**
* @method vgcanvas_get_clip_rect
*
*
* @annotation ["scriptable"]
* @param {vgcanvas_t*} vg vgcanvas对象
*
* @return {const rectf_t*}
*/
const rectf_t* vgcanvas_get_clip_rect(vgcanvas_t* vg);
/**
* @method vgcanvas_is_rectf_int_clip_rect
*
*
* @annotation ["scriptable"]
* @param {vgcanvas_t*} vg vgcanvas对象
* @param {float_t} left
* @param {float_t} top
* @param {float_t} right
* @param {float_t} bottom
*
* @return {bool_t} TURE FALSE
*/
bool_t vgcanvas_is_rectf_int_clip_rect(vgcanvas_t* vg, float_t left, float_t top, float_t right, float_t bottom);
/**
* @method vgcanvas_intersect_clip_rect
*

View File

@ -114,8 +114,7 @@ ret_t widget_on_paint_children_default(widget_t* widget, canvas_t* c) {
int32_t bottom = top + iter->h + 2 * tolerance;
int32_t right = left + iter->w + 2 * tolerance;
if (left > c->clip_right || right < c->clip_left || top > c->clip_bottom ||
bottom < c->clip_top) {
if (!canvas_is_rect_in_clip_rect(c, left, top, right, bottom)) {
iter->dirty = FALSE;
continue;
}
@ -248,7 +247,7 @@ ret_t widget_paint_with_clip(widget_t* widget, rect_t* clip, canvas_t* c,
canvas_get_clip_rect(c, &r_save);
if (vg != NULL) {
vgcanvas_save(vg);
r_vg_save = rect_init(vg->clip_rect.x, vg->clip_rect.y, vg->clip_rect.w, vg->clip_rect.h);
r_vg_save = rect_from_rectf(vgcanvas_get_clip_rect(vg));
}
if (clip != NULL) {

View File

@ -24,15 +24,18 @@
} while (0)
void draw_line(canvas_t* c, int x1, int y1, int x2, int y2) {
rect_t r;
point_t p;
lcd_t* lcd = c->lcd;
xy_t xmin = c->clip_left;
xy_t xmax = c->clip_right;
xy_t ymin = c->clip_top;
xy_t ymax = c->clip_bottom;
xy_t xmin, xmax, ymin, ymax;
color_t* color = &(c->lcd->stroke_color);
double dx = (double)x2 - (double)x1;
double dy = (double)y2 - (double)y1;
canvas_get_clip_rect(c, &r);
xmin = r.x;
xmax = r.x + r.w - 1;
ymin = r.y;
ymax = r.y + r.h - 1;
if (fabs(dx) > fabs(dy)) {
if (x2 < x1) {

View File

@ -328,8 +328,7 @@ static ret_t list_view_on_scroll_view_paint_children(widget_t* widget, canvas_t*
continue;
}
if (left > c->clip_right || right < c->clip_left || top > c->clip_bottom ||
bottom < c->clip_top) {
if (!canvas_is_rect_in_clip_rect(c, left, top, right, bottom)) {
iter->dirty = FALSE;
continue;
}

View File

@ -124,11 +124,16 @@ static rect_t slide_menu_get_clip_r(widget_t* widget) {
}
static ret_t slide_menu_paint_children(widget_t* widget, canvas_t* c) {
rect_t r;
xy_t clip_right, clip_left;
canvas_get_clip_rect(c, &r);
clip_left = r.x;
clip_right = r.x + r.w - 1;
WIDGET_FOR_EACH_CHILD_BEGIN(widget, iter, i)
int32_t left = c->ox + iter->x;
int32_t right = left + iter->w;
if (left >= (c->clip_right - 1) || right <= (c->clip_left + 1)) {
if (left >= (clip_right - 1) || right <= (clip_left + 1)) {
iter->dirty = FALSE;
continue;
}

View File

@ -35,6 +35,9 @@ typedef struct _lcd_mem_fragment_t {
xy_t y;
wh_t w;
wh_t h;
rect_t dirty_rect;
bitmap_t fb;
graphic_buffer_t* gb;
pixel_t buff[FRAGMENT_FRAME_BUFFER_SIZE];
@ -302,12 +305,52 @@ uint8_t* lcd_mem_fragment_get_buff(lcd_t* lcd) {
return (uint8_t*)mem->buff;
}
static ret_t lcd_mem_fragment_set_clip_rect(lcd_t* lcd, const rect_t* r) {
rect_t dirty_r;
rect_t r_fix = rect_init(0, 0, 0, 0);
lcd_mem_fragment_t* mem = (lcd_mem_fragment_t*)lcd;
return_value_if_fail(mem != NULL && r != NULL, RET_BAD_PARAMS);
lcd_get_dirty_rect(lcd, &dirty_r);
mem->dirty_rect = rect_intersect(r, &dirty_r);
return RET_OK;
}
static bool_t lcd_mem_fragment_is_rect_in_clip_rect(lcd_t* lcd, xy_t left, xy_t top, xy_t right, xy_t bottom) {
lcd_mem_fragment_t* mem = (lcd_mem_fragment_t*)lcd;
xy_t clip_left, clip_top, clip_right, clip_bottom;
return_value_if_fail(mem != NULL, FALSE);
clip_left = mem->dirty_rect.x;
clip_top = mem->dirty_rect.y;
clip_right = mem->dirty_rect.x + mem->dirty_rect.w - 1;
clip_bottom = mem->dirty_rect.y + mem->dirty_rect.h - 1;
if (left > clip_right || right < clip_left || top > clip_bottom || bottom < clip_top) {
return FALSE;
}
return TRUE;
}
static ret_t lcd_mem_fragment_get_clip_rect(lcd_t* lcd, rect_t* rect) {
lcd_mem_fragment_t* mem = (lcd_mem_fragment_t*)lcd;
return_value_if_fail(mem != NULL, RET_BAD_PARAMS);
rect->x = mem->dirty_rect.x;
rect->y = mem->dirty_rect.y;
rect->w = mem->dirty_rect.w;
rect->h = mem->dirty_rect.h;
return RET_OK;
}
lcd_t* lcd_mem_fragment_create(wh_t w, wh_t h) {
lcd_mem_fragment_t* mem = &s_lcd_mem_fragment;
lcd_t* base = (lcd_t*)mem;
system_info_t* info = system_info();
base->begin_frame = lcd_mem_fragment_begin_frame;
base->set_clip_rect = lcd_mem_fragment_set_clip_rect;
base->get_clip_rect = lcd_mem_fragment_get_clip_rect;
base->is_rect_in_clip_rect = lcd_mem_fragment_is_rect_in_clip_rect;
base->draw_vline = lcd_mem_fragment_draw_vline;
base->draw_hline = lcd_mem_fragment_draw_hline;
base->fill_rect = lcd_mem_fragment_fill_rect;

View File

@ -70,10 +70,14 @@ static ret_t lcd_vgcanvas_set_clip_rect(lcd_t* lcd, const rect_t* r) {
return vgcanvas_clip_rect(LCD(lcd)->canvas, r->x, r->y, r->w, r->h);
}
static bool_t lcd_vgcanvas_is_rect_in_clip_rect(lcd_t* lcd, xy_t left, xy_t top, xy_t right, xy_t bottom) {
vgcanvas_t* canvas = LCD(lcd)->canvas;
return vgcanvas_is_rectf_int_clip_rect(canvas, (float_t)left, (float_t)top, (float_t)right, (float_t)bottom);
}
static ret_t lcd_vgcanvas_get_clip_rect(lcd_t* lcd, rect_t* r) {
vgcanvas_t* canvas = LCD(lcd)->canvas;
*r = canvas->clip_rect;
*r = rect_from_rectf(vgcanvas_get_clip_rect(canvas));
return RET_OK;
}
@ -321,6 +325,7 @@ lcd_t* lcd_vgcanvas_init(wh_t w, wh_t h, vgcanvas_t* canvas) {
base->begin_frame = lcd_vgcanvas_begin_frame;
base->set_clip_rect = lcd_vgcanvas_set_clip_rect;
base->get_clip_rect = lcd_vgcanvas_get_clip_rect;
base->is_rect_in_clip_rect = lcd_vgcanvas_is_rect_in_clip_rect;
base->draw_vline = lcd_vgcanvas_draw_vline;
base->draw_hline = lcd_vgcanvas_draw_hline;
base->fill_rect = lcd_vgcanvas_fill_rect;

View File

@ -256,7 +256,7 @@ static ret_t vgcanvas_nanovg_intersect_clip_rect(vgcanvas_t* vgcanvas, float_t*
NVGcontext* vg = ((vgcanvas_nanovg_t*)vgcanvas)->vg;
nvgIntersectScissor_ex(vg, x, y, w, h);
nvgGetCurrScissor(vg, &vgcanvas->clip_rect.x, &vgcanvas->clip_rect.y, &vgcanvas->clip_rect.w, &vgcanvas->clip_rect.h);
return RET_OK;
}
@ -331,10 +331,26 @@ static ret_t vgcanvas_nanovg_clip_rect(vgcanvas_t* vgcanvas, float_t x, float_t
#else
nvgScissor(vg, x, y, w, h);
#endif
nvgGetCurrScissor(vg, &vgcanvas->clip_rect.x, &vgcanvas->clip_rect.y, &vgcanvas->clip_rect.w, &vgcanvas->clip_rect.h);
return RET_OK;
}
static bool_t vgcanvas_nanovg_is_rectf_int_clip_rect(vgcanvas_t* vgcanvas, float_t left, float_t top, float_t right, float_t bottom) {
float_t clip_left = vgcanvas->clip_rect.x;
float_t clip_right = vgcanvas->clip_rect.x + vgcanvas->clip_rect.w;
float_t clip_top = vgcanvas->clip_rect.y;
float_t clip_bottom = vgcanvas->clip_rect.y + vgcanvas->clip_rect.h;
if (left > clip_right || right < clip_left || top > clip_bottom || bottom < clip_top) {
return FALSE;
}
return TRUE;
}
const rectf_t* vgcanvas_nanovg_get_clip_rect(vgcanvas_t* vgcanvas) {
return &(vgcanvas->clip_rect);
}
static ret_t vgcanvas_nanovg_fill(vgcanvas_t* vgcanvas) {
NVGcontext* vg = ((vgcanvas_nanovg_t*)vgcanvas)->vg;
@ -717,6 +733,8 @@ static const vgcanvas_vtable_t vt = {
.transform = vgcanvas_nanovg_transform,
.set_transform = vgcanvas_nanovg_set_transform,
.clip_rect = vgcanvas_nanovg_clip_rect,
.get_clip_rect = vgcanvas_nanovg_get_clip_rect,
.is_rectf_int_clip_rect = vgcanvas_nanovg_is_rectf_int_clip_rect,
.intersect_clip_rect = vgcanvas_nanovg_intersect_clip_rect,
.path_winding = vgcanvas_nanovg_path_winding,
.fill = vgcanvas_nanovg_fill,

View File

@ -13,7 +13,6 @@ typedef struct _vgcanvas_nanovg_plus_t {
vgcanvas_t base;
int font_id;
char font_name[TK_NAME_LEN];
nvgp_context_t* vg;
uint32_t text_align_v;
uint32_t text_align_h;

View File

@ -256,17 +256,35 @@ static ret_t vgcanvas_nanovg_plus_intersect_clip_rect(vgcanvas_t* vgcanvas, floa
nvgp_context_t* vg = ((vgcanvas_nanovg_plus_t*)vgcanvas)->vg;
nvgp_intersect_scissor(vg, x, y, w, h);
nvgp_get_curr_clip_rect(vg, &vgcanvas->clip_rect.x, &vgcanvas->clip_rect.y, &vgcanvas->clip_rect.w, &vgcanvas->clip_rect.h);
return RET_OK;
}
static bool_t vgcanvas_nanovg_plus_is_rectf_int_clip_rect(vgcanvas_t* vgcanvas, float_t left, float_t top, float_t right, float_t bottom) {
vgcanvas_nanovg_plus_t* canvas = (vgcanvas_nanovg_plus_t*)vgcanvas;
float_t clip_left = vgcanvas->clip_rect.x;
float_t clip_right = vgcanvas->clip_rect.x + vgcanvas->clip_rect.w;
float_t clip_top = vgcanvas->clip_rect.y;
float_t clip_bottom = vgcanvas->clip_rect.y + vgcanvas->clip_rect.h;
if (left > clip_right || right < clip_left || top > clip_bottom || bottom < clip_top) {
return FALSE;
}
return TRUE;
}
static ret_t vgcanvas_nanovg_plus_clip_rect(vgcanvas_t* vgcanvas, float_t x, float_t y, float_t w,
float_t h) {
nvgp_context_t* vg = ((vgcanvas_nanovg_plus_t*)vgcanvas)->vg;
nvgp_scissor(vg, x, y, w, h);
nvgp_get_curr_clip_rect(vg, &vgcanvas->clip_rect.x, &vgcanvas->clip_rect.y, &vgcanvas->clip_rect.w, &vgcanvas->clip_rect.h);
return RET_OK;
}
const rectf_t* vgcanvas_nanovg_plus_get_clip_rect(vgcanvas_t* vgcanvas) {
return &(vgcanvas->clip_rect);
}
static ret_t vgcanvas_nanovg_plus_fill(vgcanvas_t* vgcanvas) {
nvgp_context_t* vg = ((vgcanvas_nanovg_plus_t*)vgcanvas)->vg;
@ -381,9 +399,6 @@ static ret_t vgcanvas_nanovg_plus_set_font(vgcanvas_t* vgcanvas, const char* nam
nvgp_context_t* vg = ((vgcanvas_nanovg_plus_t*)vgcanvas)->vg;
vgcanvas_nanovg_plus_t* canvas = (vgcanvas_nanovg_plus_t*)vgcanvas;
return_value_if_fail(name && *name, RET_BAD_PARAMS);
if (tk_str_eq(canvas->font_name, name)) {
return RET_OK;
}
font_id = tk_pointer_to_int(vgcanvas_asset_manager_get_font_ctx(vgcanvas_asset_manager(), vgcanvas, name, &reuslt));
@ -420,7 +435,6 @@ static ret_t vgcanvas_nanovg_plus_set_font(vgcanvas_t* vgcanvas, const char* nam
}
canvas->font_id = font_id;
memcpy(canvas->font_name, name, sizeof(name));
nvgp_font_face_id(vg, font_id);
return RET_OK;
@ -738,6 +752,8 @@ static const vgcanvas_vtable_t vt = {
.transform = vgcanvas_nanovg_plus_transform,
.set_transform = vgcanvas_nanovg_plus_set_transform,
.clip_rect = vgcanvas_nanovg_plus_clip_rect,
.get_clip_rect = vgcanvas_nanovg_plus_get_clip_rect,
.is_rectf_int_clip_rect = vgcanvas_nanovg_plus_is_rectf_int_clip_rect,
.intersect_clip_rect = vgcanvas_nanovg_plus_intersect_clip_rect,
.path_winding = vgcanvas_nanovg_plus_path_winding,
.fill = vgcanvas_nanovg_plus_fill,