From 2615b1d81bde28e6de372f8c5357eb684469414b Mon Sep 17 00:00:00 2001 From: Ben You Date: Tue, 1 Oct 2024 22:19:20 +0800 Subject: [PATCH] Utilize pixman for efficient pixel manipulation According to issue #6, I replace original image compositing and trapezoid rasterization with Pixman function. Briefly, include: - pixman_image_composite: image compositing - pixman_fill_rect: use pixman_image_fill_rectangles to fill the image with retangles - pixman_image_fill_boxes: span is filled with the boxs Close #6 --- Makefile | 11 +++++ README.md | 4 +- apps/animation.c | 14 +++++++ apps/main.c | 30 +++++++++++++- apps/multi.c | 91 +++++++++++++++++++++++++++++++++++++++--- configs/Kconfig | 4 ++ configs/defconfig | 1 + include/twin.h | 31 ++++++++++++++ include/twin_private.h | 17 ++++++++ src/box.c | 17 +++++++- src/path.c | 27 +++++++++++++ src/pixman.c | 47 ++++++++++++++++++++++ src/pixmap.c | 4 ++ src/poly.c | 23 ++++++++++- src/widget.c | 12 +++++- src/window.c | 6 ++- 16 files changed, 325 insertions(+), 14 deletions(-) create mode 100644 src/pixman.c diff --git a/Makefile b/Makefile index 2890b42..8cadd25 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,13 @@ libtwin.a_includes-y := \ libtwin.a_files-$(CONFIG_LOGGING) += src/log.c libtwin.a_files-$(CONFIG_CURSOR) += src/cursor.c +# Pixman +ifeq ($(CONFIG_PIXMAN), y) +libtwin.a_files-y += src/pixman.c +libtwin.a_cflags-y += $(shell pkg-config --cflags pixman-1) +TARGET_LIBS += $(shell pkg-config --libs pixman-1) +endif + # Image loaders ifeq ($(CONFIG_LOADER_JPEG), y) @@ -118,6 +125,10 @@ endif CFLAGS += -include config.h +ifeq ($(CONFIG_PIXMAN), y) +CFLAGS += $(shell pkg-config --cflags pixman-1) +endif + check_goal := $(strip $(MAKECMDGOALS)) ifneq ($(check_goal), config) include mk/common.mk diff --git a/README.md b/README.md index 99bcb50..b217b67 100644 --- a/README.md +++ b/README.md @@ -63,9 +63,9 @@ benefiting the entire application stack. `Mado` is built with a minimalist design in mind. However, its verification relies on certain third-party packages for full functionality and access to all its features. To ensure proper operation, the development environment should -have the [SDL2 library](https://www.libsdl.org/), [libjpeg](https://www.ijg.org/), and [libpng](https://github.com/pnggroup/libpng) installed. +have the [SDL2 library](https://www.libsdl.org/), [libjpeg](https://www.ijg.org/), [libpng](https://github.com/pnggroup/libpng), and [libpixman-1](https://pixman.org/) installed. * macOS: `brew install sdl2 jpeg libpng` -* Ubuntu Linux / Debian: `sudo apt install libsdl2-dev libjpeg-dev libpng-dev` +* Ubuntu Linux / Debian: `sudo apt install libsdl2-dev libjpeg-dev libpng-dev libpixman-1-dev` Configure via [Kconfiglib](https://pypi.org/project/kconfiglib/) ```shell diff --git a/apps/animation.c b/apps/animation.c index c89a350..a124dfd 100644 --- a/apps/animation.c +++ b/apps/animation.c @@ -29,13 +29,27 @@ static void _apps_animation_paint(apps_animation_t *anim) } else { current_frame = anim->pix; } +#if defined(CONFIG_PIXMAN) + pixman_image_t *src = create_pixman_image_from_twin_pixmap(current_frame); + pixman_image_t *dst = + create_pixman_image_from_twin_pixmap(_apps_animation_pixmap(anim)); + + twin_coord_t ox, oy; + twin_pixmap_get_origin(_apps_animation_pixmap(anim), &ox, &oy); + pixman_image_composite(PIXMAN_OP_SRC, src, NULL, dst, 0, 0, 0, 0, ox, oy, + current_frame->width, current_frame->height); + + pixman_image_unref(src); + pixman_image_unref(dst); +#else twin_operand_t srcop = { .source_kind = TWIN_PIXMAP, .u.pixmap = current_frame, }; twin_composite(_apps_animation_pixmap(anim), 0, 0, &srcop, 0, 0, NULL, 0, 0, TWIN_SOURCE, current_frame->width, current_frame->height); +#endif } static twin_time_t _apps_animation_timeout(twin_time_t maybe_unused now, diff --git a/apps/main.c b/apps/main.c index 3b8120f..d2c4636 100644 --- a/apps/main.c +++ b/apps/main.c @@ -47,6 +47,34 @@ static twin_pixmap_t *load_background(twin_screen_t *screen, const char *path) twin_pixmap_destroy(raw_background); return twin_make_pattern(); } +#if defined(CONFIG_PIXMAN) + pixman_image_t *srcop_pix = + create_pixman_image_from_twin_pixmap(raw_background); + + pixman_transform_t transform; + pixman_transform_init_identity(&transform); + + pixman_fixed_t sx, sy; + sx = twin_fixed_div(twin_int_to_fixed(raw_background->width), + twin_int_to_fixed(screen->width)); + sy = twin_fixed_div(twin_int_to_fixed(raw_background->height), + twin_int_to_fixed(screen->height)); + + pixman_transform_scale(&transform, NULL, sx, sy); + pixman_image_set_transform(srcop_pix, &transform); + + pixman_image_t *scaled_background_pix = + create_pixman_image_from_twin_pixmap(scaled_background); + + twin_coord_t ox, oy; + twin_pixmap_get_origin(scaled_background, &ox, &oy); + pixman_image_composite(PIXMAN_OP_SRC, srcop_pix, NULL, + scaled_background_pix, 0, 0, 0, 0, ox, oy, + screen->width, screen->height); + + pixman_image_unref(srcop_pix); + pixman_image_unref(scaled_background_pix); +#else twin_fixed_t sx, sy; sx = twin_fixed_div(twin_int_to_fixed(raw_background->width), twin_int_to_fixed(screen->width)); @@ -60,7 +88,7 @@ static twin_pixmap_t *load_background(twin_screen_t *screen, const char *path) }; twin_composite(scaled_background, 0, 0, &srcop, 0, 0, NULL, 0, 0, TWIN_SOURCE, screen->width, screen->height); - +#endif twin_pixmap_destroy(raw_background); return scaled_background; diff --git a/apps/multi.c b/apps/multi.c index 1c9966f..046e196 100644 --- a/apps/multi.c +++ b/apps/multi.c @@ -17,7 +17,12 @@ static void apps_line_start(twin_screen_t *screen, int x, int y, int w, int h) twin_fixed_t fy; twin_path_translate(stroke, D(200), D(200)); +#if defined(CONFIG_PIXMAN) + pixman_fill_rect(pixmap, &(pixman_color_t){0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}, + pixmap->clip.left, pixmap->clip.top, w, h); +#else twin_fill(pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, w, h); +#endif twin_window_set_name(window, "line"); @@ -41,14 +46,22 @@ static void apps_circletext_start(twin_screen_t *screen, screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h); int wid = window->client.right - window->client.left; int hei = window->client.bottom - window->client.top; - twin_pixmap_t *pixmap = window->pixmap; twin_path_t *path = twin_path_create(); twin_path_t *pen = twin_path_create(); + +#if defined(CONFIG_PIXMAN) twin_pixmap_t *alpha = twin_pixmap_create(TWIN_A8, wid, hei); - int s; - twin_operand_t source, mask; + twin_rect_t win_clip = twin_pixmap_get_clip(window->pixmap); + pixman_fill_rect(window->pixmap, + &(pixman_color_t){0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}, + win_clip.left, win_clip.top, wid, hei); +#else + twin_pixmap_t *alpha = twin_pixmap_create(TWIN_A8, wid, hei); + twin_pixmap_t *pixmap = window->pixmap; twin_fill(pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, wid, hei); +#endif + twin_window_set_name(window, "circletext"); twin_path_set_font_style(path, TWIN_TEXT_UNHINTED); @@ -56,6 +69,7 @@ static void apps_circletext_start(twin_screen_t *screen, twin_path_translate(path, D(200), D(200)); twin_path_set_font_size(path, D(15)); + int s; for (s = 0; s < 41; s++) { twin_state_t state = twin_path_save(path); twin_path_rotate(path, twin_degrees_to_angle(9 * s)); @@ -66,12 +80,31 @@ static void apps_circletext_start(twin_screen_t *screen, twin_fill_path(alpha, path, 0, 0); twin_path_destroy(path); twin_path_destroy(pen); + +#if defined(CONFIG_PIXMAN) + pixman_image_t *mask = create_pixman_image_from_twin_pixmap(alpha); + pixman_image_t *source = pixman_image_create_solid_fill( + &(pixman_color_t){0x0000, 0x0000, 0x0000, 0xFFFF}); + pixman_image_t *dst = create_pixman_image_from_twin_pixmap(window->pixmap); + + twin_coord_t ox, oy; + twin_pixmap_get_origin(window->pixmap, &ox, &oy); + pixman_image_composite(PIXMAN_OP_OVER, source, mask, dst, 0, 0, 0, 0, ox, + oy, wid, hei); + + pixman_image_unref(source); + pixman_image_unref(mask); + pixman_image_unref(dst); +#else + twin_operand_t source, mask; source.source_kind = TWIN_SOLID; source.u.argb = 0xff000000; mask.source_kind = TWIN_PIXMAP; mask.u.pixmap = alpha; twin_composite(pixmap, 0, 0, &source, 0, 0, &mask, 0, 0, TWIN_OVER, wid, hei); +#endif + twin_pixmap_destroy(alpha); twin_window_show(window); } @@ -90,13 +123,16 @@ static void apps_quickbrown_start(twin_screen_t *screen, twin_path_t *path = twin_path_create(); twin_path_t *pen = twin_path_create(); twin_pixmap_t *alpha = twin_pixmap_create(TWIN_A8, wid, hei); - twin_operand_t source, mask; twin_fixed_t fx, fy; int s; twin_window_set_name(window, "Quick Brown"); - +#if defined(CONFIG_PIXMAN) + pixman_fill_rect(pixmap, &(pixman_color_t){0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}, + pixmap->clip.left, pixmap->clip.top, w, h); +#else twin_fill(pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, wid, hei); +#endif twin_path_circle(pen, 0, 0, D(1)); @@ -113,12 +149,29 @@ static void apps_quickbrown_start(twin_screen_t *screen, twin_fill_path(alpha, path, 0, 0); twin_path_destroy(path); twin_path_destroy(pen); +#if defined(CONFIG_PIXMAN) + pixman_image_t *mask = create_pixman_image_from_twin_pixmap(alpha); + pixman_image_t *src = pixman_image_create_solid_fill( + &(pixman_color_t){0x0000, 0x0000, 0x0000, 0xFFFF}); + pixman_image_t *dst = create_pixman_image_from_twin_pixmap(pixmap); + + twin_coord_t ox, oy; + twin_pixmap_get_origin(pixmap, &ox, &oy); + pixman_image_composite(PIXMAN_OP_OVER, src, mask, dst, 0, 0, 0, 0, ox, oy, + wid, hei); + + pixman_image_unref(src); + pixman_image_unref(mask); + pixman_image_unref(dst); +#else + twin_operand_t source, mask; source.source_kind = TWIN_SOLID; source.u.argb = 0xff000000; mask.source_kind = TWIN_PIXMAP; mask.u.pixmap = alpha; twin_composite(pixmap, 0, 0, &source, 0, 0, &mask, 0, 0, TWIN_OVER, wid, hei); +#endif twin_pixmap_destroy(alpha); twin_window_show(window); } @@ -133,13 +186,17 @@ static void apps_ascii_start(twin_screen_t *screen, int x, int y, int w, int h) twin_path_t *path = twin_path_create(); twin_path_t *pen = twin_path_create(); twin_pixmap_t *alpha = twin_pixmap_create(TWIN_A8, wid, hei); - twin_operand_t source, mask; twin_fixed_t fx, fy; int s; twin_window_set_name(window, "ASCII"); +#if defined(CONFIG_PIXMAN) + pixman_fill_rect(pixmap, &(pixman_color_t){0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}, + pixmap->clip.left, pixmap->clip.top, w, h); +#else twin_fill(pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, wid, hei); +#endif twin_path_circle(pen, 0, 0, D(1)); fx = D(3); @@ -161,12 +218,29 @@ static void apps_ascii_start(twin_screen_t *screen, int x, int y, int w, int h) twin_fill_path(alpha, path, 0, 0); twin_path_destroy(path); twin_path_destroy(pen); +#if defined(CONFIG_PIXMAN) + pixman_image_t *mask = create_pixman_image_from_twin_pixmap(alpha); + pixman_image_t *src = pixman_image_create_solid_fill( + &(pixman_color_t){0x0000, 0x0000, 0x0000, 0xFFFF}); + pixman_image_t *dst = create_pixman_image_from_twin_pixmap(pixmap); + + twin_coord_t ox, oy; + twin_pixmap_get_origin(pixmap, &ox, &oy); + pixman_image_composite(PIXMAN_OP_OVER, src, mask, dst, 0, 0, 0, 0, ox, oy, + wid, hei); + + pixman_image_unref(src); + pixman_image_unref(mask); + pixman_image_unref(dst); +#else + twin_operand_t source, mask; source.source_kind = TWIN_SOLID; source.u.argb = 0xff000000; mask.source_kind = TWIN_PIXMAP; mask.u.pixmap = alpha; twin_composite(pixmap, 0, 0, &source, 0, 0, &mask, 0, 0, TWIN_OVER, wid, hei); +#endif twin_pixmap_destroy(alpha); twin_window_show(window); } @@ -184,7 +258,12 @@ static void apps_jelly_start(twin_screen_t *screen, int x, int y, int w, int h) twin_window_set_name(window, "Jelly"); +#if defined(CONFIG_PIXMAN) + pixman_fill_rect(pixmap, &(pixman_color_t){0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}, + pixmap->clip.left, pixmap->clip.top, wid, hei); +#else twin_fill(pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, wid, hei); +#endif fx = D(3); fy = D(8); diff --git a/configs/Kconfig b/configs/Kconfig index 1d7966b..8e210c1 100644 --- a/configs/Kconfig +++ b/configs/Kconfig @@ -39,6 +39,10 @@ config CURSOR bool "Manipulate cursor" default n +config PIXMAN + bool "Pixman to pixel manipulation" + default y + endmenu menu "Image Loaders" diff --git a/configs/defconfig b/configs/defconfig index 212f69b..45537cc 100644 --- a/configs/defconfig +++ b/configs/defconfig @@ -1,4 +1,5 @@ CONFIG_BACKEND_SDL=y +CONFIG_PIXMAN=y CONFIG_LOADER_PNG=y CONFIG_LOADER_JPEG=y CONFIG_LOADER_GIF=y diff --git a/include/twin.h b/include/twin.h index d61dcf6..5280975 100644 --- a/include/twin.h +++ b/include/twin.h @@ -10,6 +10,10 @@ #include #include +#if defined(CONFIG_PIXMAN) +#include +#endif + typedef uint8_t twin_a8_t; typedef uint16_t twin_a16_t; typedef uint16_t twin_rgb16_t; @@ -984,6 +988,33 @@ bool twin_pixmap_transparent(twin_pixmap_t *pixmap, bool twin_pixmap_dispatch(twin_pixmap_t *pixmap, twin_event_t *event); +/* + * pixman.c + */ + +#if defined(CONFIG_PIXMAN) +void twin_argb32_to_pixman_color(twin_argb32_t argb, pixman_color_t *color); + +pixman_format_code_t twin_to_pixman_format(twin_format_t twin_format); + +pixman_op_t twin_to_pixman_op(twin_operator_t twin_op); + +void pixman_fill_rect(twin_pixmap_t *pixmap, + const pixman_color_t *color, + int origin_x, + int origin_y, + int width, + int height); + +#define create_pixman_image_from_twin_pixmap(pixmap) \ + ({ \ + typeof(pixmap) _pixmap = (pixmap); \ + pixman_image_create_bits(twin_to_pixman_format((_pixmap)->format), \ + (_pixmap)->width, (_pixmap)->height, \ + (_pixmap)->p.argb32, (_pixmap)->stride); \ + }) +#endif + /* * poly.c */ diff --git a/include/twin_private.h b/include/twin_private.h index 99586d3..ac901ba 100644 --- a/include/twin_private.h +++ b/include/twin_private.h @@ -88,6 +88,7 @@ typedef int8_t twin_gfixed_t; #define twin_sfixed_mod(f) ((f) & 0xf) #define twin_int_to_sfixed(i) ((twin_sfixed_t) ((i) * 16)) +#define twin_sfixed_to_int(i) ((int32_t) ((i) >> 4)) #define twin_sfixed_to_fixed(s) (((twin_fixed_t) (s)) << 12) #define twin_fixed_to_sfixed(f) ((twin_sfixed_t) ((f) >> 12)) @@ -168,6 +169,22 @@ typedef int8_t twin_gfixed_t; ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \ ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)) | 0xff000000) +#define min(x, y) \ + ({ \ + typeof(x) _x = (x); \ + typeof(y) _y = (y); \ + (void) (&_x == &_y); \ + _x < _y ? _x : _y; \ + }) + +#define max(x, y) \ + ({ \ + typeof(x) _x = (x); \ + typeof(y) _y = (y); \ + (void) (&_x == &_y); \ + _x > _y ? _x : _y; \ + }) + typedef union { twin_pointer_t p; twin_argb32_t c; diff --git a/src/box.c b/src/box.c index f85138d..cfb962e 100644 --- a/src/box.c +++ b/src/box.c @@ -193,11 +193,26 @@ twin_dispatch_result_t _twin_box_dispatch(twin_widget_t *widget, twin_coord_t ox, oy; twin_pixmap_get_origin(pixmap, &ox, &oy); - if (child->shape != TwinShapeRectangle) + if (child->shape != TwinShapeRectangle) { +#if defined(CONFIG_PIXMAN) + pixman_color_t color; + twin_argb32_to_pixman_color(widget->background, &color); + pixman_fill_rect( + child->window->pixmap, &color, ox + child->extents.left, + oy + child->extents.top, + child->extents.right - child->extents.left, + child->extents.bottom - child->extents.top); + twin_pixmap_damage(child->window->pixmap, + child->extents.left, child->extents.top, + child->extents.right, + child->extents.bottom); +#else twin_fill(child->window->pixmap, widget->background, TWIN_SOURCE, child->extents.left, child->extents.top, child->extents.right, child->extents.bottom); +#endif + } twin_pixmap_set_clip(pixmap, child->extents); twin_pixmap_origin_to_clip(pixmap); child->paint = false; diff --git a/src/path.c b/src/path.c index 27e57f3..8ce4827 100644 --- a/src/path.c +++ b/src/path.c @@ -466,6 +466,32 @@ void twin_composite_path(twin_pixmap_t *dst, twin_coord_t width = bounds.right - bounds.left; twin_coord_t height = bounds.bottom - bounds.top; + +#if defined(CONFIG_PIXMAN) + twin_pixmap_t *mask = twin_pixmap_create(TWIN_A8, width, height); + if (!mask) + return; + + twin_fill_path(mask, path, -bounds.left, -bounds.top); + pixman_image_t *msk = create_pixman_image_from_twin_pixmap(mask); + + pixman_color_t source_pixel; + twin_argb32_to_pixman_color(src->u.argb, &source_pixel); + pixman_image_t *source = pixman_image_create_solid_fill(&source_pixel); + + pixman_image_t *destination = create_pixman_image_from_twin_pixmap(dst); + + twin_coord_t ox, oy; + twin_pixmap_get_origin(dst, &ox, &oy); + pixman_image_composite(twin_to_pixman_op(operator), source, msk, + destination, src_x + bounds.left, src_y + bounds.top, + 0, 0, ox + bounds.left, oy + bounds.top, width, + height); + + pixman_image_unref(source); + pixman_image_unref(msk); + pixman_image_unref(destination); +#else twin_pixmap_t *mask = twin_pixmap_create(TWIN_A8, width, height); if (!mask) return; @@ -474,6 +500,7 @@ void twin_composite_path(twin_pixmap_t *dst, twin_operand_t msk = {.source_kind = TWIN_PIXMAP, .u.pixmap = mask}; twin_composite(dst, bounds.left, bounds.top, src, src_x + bounds.left, src_y + bounds.top, &msk, 0, 0, operator, width, height); +#endif twin_pixmap_destroy(mask); } diff --git a/src/pixman.c b/src/pixman.c new file mode 100644 index 0000000..fb80fba --- /dev/null +++ b/src/pixman.c @@ -0,0 +1,47 @@ +#include "twin_private.h" +void twin_argb32_to_pixman_color(twin_argb32_t argb, pixman_color_t *color) +{ + /* Extract ARGB every Byte */ + uint16_t a = (argb >> 24) & 0xFF; + uint16_t r = (argb >> 16) & 0xFF; + uint16_t g = (argb >> 8) & 0xFF; + uint16_t b = argb & 0xFF; + + /* 8bits -> 16bits (255 -> 65535) */ + color->alpha = (a << 8) + a; + color->red = (r << 8) + r; + color->green = (g << 8) + g; + color->blue = (b << 8) + b; +} + +static const pixman_format_code_t twin_pixman_format[3] = { + [TWIN_A8] = PIXMAN_a8, + [TWIN_RGB16] = PIXMAN_r5g6b5, + [TWIN_ARGB32] = PIXMAN_a8r8g8b8}; + +pixman_format_code_t twin_to_pixman_format(const twin_format_t twin_format) +{ + return twin_pixman_format[twin_format]; +} + +static const pixman_op_t twin_pixman_op[2] = + {[TWIN_OVER] = PIXMAN_OP_OVER, [TWIN_SOURCE] = PIXMAN_OP_SRC}; + +pixman_op_t twin_to_pixman_op(const twin_operator_t twin_op) +{ + return twin_pixman_op[twin_op]; +} + +void pixman_fill_rect(twin_pixmap_t *pixmap, + const pixman_color_t *color, + int origin_x, + int origin_y, + int width, + int height) +{ + pixman_image_t *src = create_pixman_image_from_twin_pixmap(pixmap); + pixman_image_fill_rectangles( + PIXMAN_OP_SRC, src, color, 1, + &(pixman_rectangle16_t){origin_x, origin_y, width, height}); + pixman_image_unref(src); +} \ No newline at end of file diff --git a/src/pixmap.c b/src/pixmap.c index 4e7557e..05f0d70 100644 --- a/src/pixmap.c +++ b/src/pixmap.c @@ -13,6 +13,10 @@ twin_pixmap_t *twin_pixmap_create(twin_format_t format, twin_coord_t height) { twin_coord_t stride = twin_bytes_per_pixel(format) * width; + /* Padding the stride to a multiple of 4 bytes */ + if (stride % 4 != 0) + stride += (4 - stride % 4); + twin_area_t space = (twin_area_t) stride * height; twin_area_t size = sizeof(twin_pixmap_t) + space; twin_pixmap_t *pixmap = malloc(size); diff --git a/src/poly.c b/src/poly.c index e966043..a154607 100644 --- a/src/poly.c +++ b/src/poly.c @@ -236,6 +236,9 @@ static void _twin_edge_fill(twin_pixmap_t *pixmap, int e = 0; twin_sfixed_t y = edges[0].top; active = 0; +#if defined(CONFIG_PIXMAN) + pixman_image_t *mask = create_pixman_image_from_twin_pixmap(pixmap); +#endif for (;;) { /* add in new edges */ for (; e < nedges && edges[e].top <= y; e++) { @@ -252,8 +255,23 @@ static void _twin_edge_fill(twin_pixmap_t *pixmap, if (w == 0) x0 = a->x; w += a->winding; - if (w == 0) + if (w == 0) { +#if defined(CONFIG_PIXMAN) + twin_sfixed_t left = + min(x0, twin_int_to_sfixed(pixmap->width - 1)); + twin_sfixed_t right = + min(a->x, twin_int_to_sfixed(pixmap->width - 1)); + + pixman_box32_t box = {.x1 = twin_sfixed_to_int(left), + .x2 = twin_sfixed_to_int(right), + .y1 = twin_sfixed_to_int(y), + .y2 = twin_sfixed_to_int(y) + 1}; + pixman_color_t white = {0xffff, 0xffff, 0xffff, 0xffff}; + pixman_image_fill_boxes(PIXMAN_OP_SRC, mask, &white, 1, &box); +#else _span_fill(pixmap, y, x0, a->x); +#endif + } } /* step down, clipping to pixmap */ @@ -289,6 +307,9 @@ static void _twin_edge_fill(twin_pixmap_t *pixmap, prev = &a->next; } } +#if defined(CONFIG_PIXMAN) + pixman_image_unref(mask); +#endif } void twin_fill_path(twin_pixmap_t *pixmap, diff --git a/src/widget.c b/src/widget.c index 2855e58..96af433 100644 --- a/src/widget.c +++ b/src/widget.c @@ -54,10 +54,18 @@ void _twin_widget_paint_shape(twin_widget_t *widget, { twin_pixmap_t *pixmap = widget->window->pixmap; - if (shape == TwinShapeRectangle) + if (shape == TwinShapeRectangle) { +#if defined(CONFIG_PIXMAN) + pixman_color_t color; + twin_argb32_to_pixman_color(widget->background, &color); + pixman_fill_rect(pixmap, &color, pixmap->clip.left, pixmap->clip.top, + right, bottom); + twin_pixmap_damage(pixmap, left, top, right, bottom); +#else twin_fill(pixmap, widget->background, TWIN_SOURCE, left, top, right, bottom); - else { +#endif + } else { twin_path_t *path = _twin_path_shape(shape, left, top, right, bottom, radius); if (path) { diff --git a/src/window.c b/src/window.c index 39c2add..9d643c3 100644 --- a/src/window.c +++ b/src/window.c @@ -187,9 +187,13 @@ static void twin_window_frame(twin_window_t *window) twin_pixmap_reset_clip(pixmap); twin_pixmap_origin_to_clip(pixmap); - +#if defined(CONFIG_PIXMAN) + pixman_fill_rect(pixmap, &(pixman_color_t){0, 0, 0, 0}, pixmap->clip.left, + pixmap->clip.top, pixmap->width, window->client.top); +#else twin_fill(pixmap, 0x00000000, TWIN_SOURCE, 0, 0, pixmap->width, window->client.top); +#endif path = twin_path_create();