From 43a3c65b829933aff521a8ccd2ecf93cc1e98339 Mon Sep 17 00:00:00 2001 From: VIFEX Date: Sat, 9 Nov 2024 15:01:22 +0800 Subject: [PATCH] feat(obj): add transform matrix attribute (#7187) --- examples/widgets/lv_example_widgets.h | 1 + examples/widgets/obj/index.rst | 5 + examples/widgets/obj/lv_example_obj_3.c | 42 ++++++++ src/core/lv_obj.c | 7 ++ src/core/lv_obj_pos.c | 102 ++++++++++++++++++ src/core/lv_obj_pos.h | 22 ++++ src/core/lv_obj_private.h | 3 + src/core/lv_obj_style.c | 3 + src/core/lv_refr.c | 50 ++++++--- .../widgets/obj_transform_identity.png | Bin 0 -> 2807 bytes .../widgets/obj_transform_rotate.png | Bin 0 -> 5788 bytes .../widgets/obj_transform_scale.png | Bin 0 -> 2968 bytes .../widgets/obj_transform_skew.png | Bin 0 -> 4839 bytes .../widgets/obj_transform_translate.png | Bin 0 -> 2807 bytes .../test_cases/widgets/test_obj_transform.c | 62 +++++++++++ 15 files changed, 283 insertions(+), 14 deletions(-) create mode 100644 examples/widgets/obj/lv_example_obj_3.c create mode 100644 tests/ref_imgs_vg_lite/widgets/obj_transform_identity.png create mode 100644 tests/ref_imgs_vg_lite/widgets/obj_transform_rotate.png create mode 100644 tests/ref_imgs_vg_lite/widgets/obj_transform_scale.png create mode 100644 tests/ref_imgs_vg_lite/widgets/obj_transform_skew.png create mode 100644 tests/ref_imgs_vg_lite/widgets/obj_transform_translate.png create mode 100644 tests/src/test_cases/widgets/test_obj_transform.c diff --git a/examples/widgets/lv_example_widgets.h b/examples/widgets/lv_example_widgets.h index 2262921e1..596733102 100644 --- a/examples/widgets/lv_example_widgets.h +++ b/examples/widgets/lv_example_widgets.h @@ -111,6 +111,7 @@ void lv_example_msgbox_2(void); void lv_example_obj_1(void); void lv_example_obj_2(void); +void lv_example_obj_3(void); void lv_example_roller_1(void); void lv_example_roller_2(void); diff --git a/examples/widgets/obj/index.rst b/examples/widgets/obj/index.rst index be26ac70f..5d0a416ab 100644 --- a/examples/widgets/obj/index.rst +++ b/examples/widgets/obj/index.rst @@ -11,3 +11,8 @@ Make an object draggable .. lv_example:: widgets/obj/lv_example_obj_2 :language: c +Transform object using a 3x3 matrix +----------------------------------- + +.. lv_example:: widgets/obj/lv_example_obj_3 + :language: c diff --git a/examples/widgets/obj/lv_example_obj_3.c b/examples/widgets/obj/lv_example_obj_3.c new file mode 100644 index 000000000..b8582a949 --- /dev/null +++ b/examples/widgets/obj/lv_example_obj_3.c @@ -0,0 +1,42 @@ +#include "../../lv_examples.h" +#if LV_BUILD_EXAMPLES +#if LV_DRAW_TRANSFORM_USE_MATRIX + +static void timer_cb(lv_timer_t * timer) +{ + lv_obj_t * obj = lv_timer_get_user_data(timer); + + static float value = 0.1f; + lv_matrix_t matrix; + lv_matrix_identity(&matrix); + lv_matrix_scale(&matrix, value, 1); + lv_matrix_rotate(&matrix, value * 360); + lv_obj_set_transform(obj, &matrix); + + value += 0.01f; + + if(value > 2.0f) { + lv_obj_reset_transform(obj); + value = 0.1f; + } +} + +void lv_example_obj_3(void) +{ + lv_obj_t * obj = lv_obj_create(lv_screen_active()); + lv_obj_center(obj); + + lv_timer_create(timer_cb, 20, obj); +} + +#else + +void lv_example_obj_3(void) +{ + lv_obj_t * label = lv_label_create(lv_screen_active()); + lv_label_set_text_static(label, "LV_DRAW_TRANSFORM_USE_MATRIX is not enabled"); + lv_obj_center(label); +} + +#endif /*LV_DRAW_TRANSFORM_USE_MATRIX*/ +#endif /*LV_BUILD_EXAMPLES*/ diff --git a/src/core/lv_obj.c b/src/core/lv_obj.c index c8e1cb88c..afeba25a7 100644 --- a/src/core/lv_obj.c +++ b/src/core/lv_obj.c @@ -541,6 +541,13 @@ static void lv_obj_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_event_remove_all(&obj->spec_attr->event_list); +#if LV_DRAW_TRANSFORM_USE_MATRIX + if(obj->spec_attr->matrix) { + lv_free(obj->spec_attr->matrix); + obj->spec_attr->matrix = NULL; + } +#endif + lv_free(obj->spec_attr); obj->spec_attr = NULL; } diff --git a/src/core/lv_obj_pos.c b/src/core/lv_obj_pos.c index 543b0bd80..196b8a75b 100644 --- a/src/core/lv_obj_pos.c +++ b/src/core/lv_obj_pos.c @@ -10,6 +10,7 @@ #include "../layouts/lv_layout_private.h" #include "lv_obj_event_private.h" #include "lv_obj_draw_private.h" +#include "lv_obj_style_private.h" #include "lv_obj_private.h" #include "../display/lv_display.h" #include "../display/lv_display_private.h" @@ -983,6 +984,82 @@ void lv_obj_center(lv_obj_t * obj) lv_obj_align(obj, LV_ALIGN_CENTER, 0, 0); } +void lv_obj_set_transform(lv_obj_t * obj, const lv_matrix_t * matrix) +{ +#if LV_DRAW_TRANSFORM_USE_MATRIX + LV_ASSERT_OBJ(obj, MY_CLASS); + + if(!matrix) { + lv_obj_reset_transform(obj); + return; + } + + lv_obj_allocate_spec_attr(obj); + if(!obj->spec_attr->matrix) { + obj->spec_attr->matrix = lv_malloc(sizeof(lv_matrix_t));; + LV_ASSERT_MALLOC(obj->spec_attr->matrix); + } + + /* Invalidate the old area */ + lv_obj_invalidate(obj); + + /* Copy the matrix */ + *obj->spec_attr->matrix = *matrix; + + /* Matrix is set. Update the layer type */ + lv_obj_update_layer_type(obj); + + /* Invalidate the new area */ + lv_obj_invalidate(obj); +#else + LV_UNUSED(obj); + LV_UNUSED(matrix); + LV_LOG_WARN("Transform matrix is not used because LV_DRAW_TRANSFORM_USE_MATRIX is disabled"); +#endif +} + +void lv_obj_reset_transform(lv_obj_t * obj) +{ +#if LV_DRAW_TRANSFORM_USE_MATRIX + LV_ASSERT_OBJ(obj, MY_CLASS); + if(!obj->spec_attr) { + return; + } + + if(!obj->spec_attr->matrix) { + return; + } + + /* Invalidate the old area */ + lv_obj_invalidate(obj); + + /* Free the matrix */ + lv_free(obj->spec_attr->matrix); + obj->spec_attr->matrix = NULL; + + /* Matrix is cleared. Update the layer type */ + lv_obj_update_layer_type(obj); + + /* Invalidate the new area */ + lv_obj_invalidate(obj); +#else + LV_UNUSED(obj); +#endif +} + +const lv_matrix_t * lv_obj_get_transform(const lv_obj_t * obj) +{ +#if LV_DRAW_TRANSFORM_USE_MATRIX + LV_ASSERT_OBJ(obj, MY_CLASS); + if(obj->spec_attr) { + return obj->spec_attr->matrix; + } +#else + LV_UNUSED(obj); +#endif + return NULL; +} + /********************** * STATIC FUNCTIONS **********************/ @@ -1170,6 +1247,31 @@ static void layout_update_core(lv_obj_t * obj) static void transform_point_array(const lv_obj_t * obj, lv_point_t * p, size_t p_count, bool inv) { +#if LV_DRAW_TRANSFORM_USE_MATRIX + const lv_matrix_t * obj_matrix = lv_obj_get_transform(obj); + if(obj_matrix) { + lv_matrix_t m; + lv_matrix_identity(&m); + lv_matrix_translate(&m, obj->coords.x1, obj->coords.y1); + lv_matrix_multiply(&m, obj_matrix); + lv_matrix_translate(&m, -obj->coords.x1, -obj->coords.y1); + + if(inv) { + lv_matrix_t inv_m; + lv_matrix_inverse(&inv_m, &m); + m = inv_m; + } + + for(size_t i = 0; i < p_count; i++) { + lv_point_precise_t p_precise = lv_point_to_precise(&p[i]); + lv_point_precise_t res = lv_matrix_transform_precise_point(&m, &p_precise); + p[i] = lv_point_from_precise(&res); + } + + return; + } +#endif /* LV_DRAW_TRANSFORM_USE_MATRIX */ + int32_t angle = lv_obj_get_style_transform_rotation(obj, 0); int32_t scale_x = lv_obj_get_style_transform_scale_x_safe(obj, 0); int32_t scale_y = lv_obj_get_style_transform_scale_y_safe(obj, 0); diff --git a/src/core/lv_obj_pos.h b/src/core/lv_obj_pos.h index 584f0b7e8..717564254 100644 --- a/src/core/lv_obj_pos.h +++ b/src/core/lv_obj_pos.h @@ -197,6 +197,21 @@ void lv_obj_align_to(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, in */ void lv_obj_center(lv_obj_t * obj); +/** + * Set the transfrom matrix of an object + * @param obj pointer to an object + * @param matrix pointer to a matrix to set + * @note `LV_DRAW_TRANSFORM_USE_MATRIX` needs to be enabled. + */ +void lv_obj_set_transform(lv_obj_t * obj, const lv_matrix_t * matrix); + +/** + * Reset the transfrom matrix of an object to identity matrix + * @param obj pointer to an object + * @note `LV_DRAW_TRANSFORM_USE_MATRIX` needs to be enabled. + */ +void lv_obj_reset_transform(lv_obj_t * obj); + /** * Copy the coordinates of an object to an area * @param obj pointer to an object @@ -342,6 +357,13 @@ void lv_obj_move_to(lv_obj_t * obj, int32_t x, int32_t y); void lv_obj_move_children_by(lv_obj_t * obj, int32_t x_diff, int32_t y_diff, bool ignore_floating); +/** + * Get the transform matrix of an object + * @param obj pointer to an object + * @return pointer to the transform matrix or NULL if not set + */ +const lv_matrix_t * lv_obj_get_transform(const lv_obj_t * obj); + /** * Transform a point using the angle and zoom style properties of an object * @param obj pointer to an object whose style properties should be used diff --git a/src/core/lv_obj_private.h b/src/core/lv_obj_private.h index 865b9771b..e6c62f1e2 100644 --- a/src/core/lv_obj_private.h +++ b/src/core/lv_obj_private.h @@ -31,6 +31,9 @@ extern "C" { struct _lv_obj_spec_attr_t { lv_obj_t ** children; /**< Store the pointer of the children in an array.*/ lv_group_t * group_p; +#if LV_DRAW_TRANSFORM_USE_MATRIX + lv_matrix_t * matrix; /**< The transform matrix*/ +#endif lv_event_list_t event_list; lv_point_t scroll; /**< The current X/Y scroll offset*/ diff --git a/src/core/lv_obj_style.c b/src/core/lv_obj_style.c index 8562de850..23c266602 100644 --- a/src/core/lv_obj_style.c +++ b/src/core/lv_obj_style.c @@ -966,6 +966,9 @@ static void trans_anim_completed_cb(lv_anim_t * a) static lv_layer_type_t calculate_layer_type(lv_obj_t * obj) { +#if LV_DRAW_TRANSFORM_USE_MATRIX + if(lv_obj_get_transform(obj) != NULL) return LV_LAYER_TYPE_TRANSFORM; +#endif if(lv_obj_get_style_transform_rotation(obj, 0) != 0) return LV_LAYER_TYPE_TRANSFORM; if(lv_obj_get_style_transform_scale_x(obj, 0) != 256) return LV_LAYER_TYPE_TRANSFORM; if(lv_obj_get_style_transform_scale_y(obj, 0) != 256) return LV_LAYER_TYPE_TRANSFORM; diff --git a/src/core/lv_refr.c b/src/core/lv_refr.c index e54318248..66f2fd7fa 100644 --- a/src/core/lv_refr.c +++ b/src/core/lv_refr.c @@ -969,11 +969,17 @@ static bool alpha_test_area_on_obj(lv_obj_t * obj, const lv_area_t * area) #if LV_DRAW_TRANSFORM_USE_MATRIX -static void refr_obj_matrix(lv_layer_t * layer, lv_obj_t * obj) +static bool obj_get_matrix(lv_obj_t * obj, lv_matrix_t * matrix) { - lv_matrix_t ori_matrix = layer->matrix; - lv_matrix_t obj_matrix; - lv_matrix_identity(&obj_matrix); + lv_matrix_identity(matrix); + + const lv_matrix_t * obj_matrix = lv_obj_get_transform(obj); + if(obj_matrix) { + lv_matrix_translate(matrix, obj->coords.x1, obj->coords.y1); + lv_matrix_multiply(matrix, obj_matrix); + lv_matrix_translate(matrix, -obj->coords.x1, -obj->coords.y1); + return true; + } lv_point_t pivot = { .x = lv_obj_get_style_transform_pivot_x(obj, 0), @@ -991,39 +997,55 @@ static void refr_obj_matrix(lv_layer_t * layer, lv_obj_t * obj) if(scale_x <= 0 || scale_y <= 0) { /* NOT draw if scale is negative or zero */ - return; + return false; } /* generate the obj matrix */ - lv_matrix_translate(&obj_matrix, pivot.x, pivot.y); + lv_matrix_translate(matrix, pivot.x, pivot.y); if(rotation != 0) { - lv_matrix_rotate(&obj_matrix, rotation * 0.1f); + lv_matrix_rotate(matrix, rotation * 0.1f); } if(scale_x != LV_SCALE_NONE || scale_y != LV_SCALE_NONE) { lv_matrix_scale( - &obj_matrix, + matrix, (float)scale_x / LV_SCALE_NONE, (float)scale_y / LV_SCALE_NONE ); } if(skew_x != 0 || skew_y != 0) { - lv_matrix_skew(&obj_matrix, skew_x, skew_y); + lv_matrix_skew(matrix, skew_x, skew_y); } - lv_matrix_translate(&obj_matrix, -pivot.x, -pivot.y); + lv_matrix_translate(matrix, -pivot.x, -pivot.y); + return true; +} + +static void refr_obj_matrix(lv_layer_t * layer, lv_obj_t * obj) +{ + lv_matrix_t obj_matrix; + if(!obj_get_matrix(obj, &obj_matrix)) { + /* NOT draw if obj matrix is not available */ + return; + } + + lv_matrix_t matrix_inv; + if(!lv_matrix_inverse(&matrix_inv, &obj_matrix)) { + /* NOT draw if matrix is not invertible */ + return; + } + + /* save original matrix */ + lv_matrix_t ori_matrix = layer->matrix; /* apply the obj matrix */ lv_matrix_multiply(&layer->matrix, &obj_matrix); /* calculate clip area without transform */ - lv_matrix_t matrix_reverse; - lv_matrix_inverse(&matrix_reverse, &obj_matrix); - lv_area_t clip_area = layer->_clip_area; lv_area_t clip_area_ori = layer->_clip_area; - clip_area = lv_matrix_transform_area(&matrix_reverse, &clip_area); + clip_area = lv_matrix_transform_area(&matrix_inv, &clip_area); /* increase the clip area by 1 pixel to avoid rounding errors */ if(!lv_matrix_is_identity_or_translation(&obj_matrix)) { diff --git a/tests/ref_imgs_vg_lite/widgets/obj_transform_identity.png b/tests/ref_imgs_vg_lite/widgets/obj_transform_identity.png new file mode 100644 index 0000000000000000000000000000000000000000..aefddbe5ddbbb4a53f9d3d7f31759884b87b7f83 GIT binary patch literal 2807 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV0^&A1QfZHI&TpJ1J^!J7srr_IdAVA%$wyY z)^PEVL~_cFE#fDC@1JXaFCod`#up}4ZvK-gOZ<6lEuV9)d&g9}YX6FpX`3Y(7)tW= zY#A61{FiQIWe^aKU|=vDWsC;GXiA_g7i_%k&Cl@1I%oUs?c28>e)!?z$3h!9ecN;P zSw=JO+_`fmZS(HkyMNZyy)0~~Zv#8pe_OUYIJWlhuTalF8=}_k ztNCektfIE|?%T5Ia_l>Tn7A$8m+blb-8V|lp6l4Y-ljvcKhw` z-@kLripxr`Wo?~xHtqfU_k0^0HnWHo9J_t{wnXyQsMx9ruS>noUtYvuCm3-+vi)#k zPhow1{Y%Gn*ON9%B+vO5!ttT=0Mof2KYmCg-?>-S{bRY`X-i$M2f~f4a|)|g|Mjna z|Ej(y>fHQqD{Mc^W)Wj>@JV1~I5NthVIZXYs7*FJ_OW8m7lrGux6FY>p1HYsa?jz1 z1)#{wv|R4WSo3H(qeZgW>|R4)N?6LiGj9F*^^bo;qq@AjJh|sC>lw?9*uQ z2PKReyZL_0fB%h3p1U<}{rBI0ORVOee?EO4>kcYXuqV%@+*X#Y01>G8)33z@k1`1rWEZ@>RaByWtc*vC}on85h|Xx{eQIcC6QJ6-OH zme2CbPm5l@;re0P$ogm6-MsJLzHPhz-rmmc-xhWc^~opCo;{mm2F$6&t7U)4GI28~ pJey=anjA;7;%Iq9yAIrMCRl@(kzqlTeb$AV5ZilSvlL=Cse$+*?(cngm&#AP6pvZF{ANK?Nc0M1>&oU zXo)cb5w$eI5mVaN!;@_ z!QpY3Z1Zh(*(KPAJ&{@+99ZmMy}Up<$LLS=-Wk4SHtnDp2a$D@V6>dEKP5SNZb_&0 zT{!v?P3?))ETBai$VEN3wdiG`<*InU71np)JT^+ZprBHE{3Cn4Ma4en>;IB>nKvaM%}JqEii@oo zHNnnSR#v|AOu^{2{gr_n)CtQ-qkTbywv!Z*f;UL=vavMHvtRx;waVAmSESICU>ibh zElg*gUwtXqxjrPGSFj(79NJ~sk7LU!?{E8$M338<#4*~+| zeL=puX__$r9nN!R7iPI5y&&t4ZArVs(&YIJgFq`pZo!pu!9_x?pS0%}s zQ#Ib?k)ik>0vx3(&u5p-nv5XhzyuY6hF#FgmY2FaMGzpwVOQMMhLS&7g=*U0(U4dD z>hCgjxrZRu(`Dj!q6oWCGiF`eBv5H)$dwd(#w|NzmxR7 zK4r;3y>Xa%jtTd1Q_?Ql^iX@gfA#5EujS808cD1tRaBUVpZML#wNj9KzCO%#ALS%V zytTNKDEio0p!sHO##^6RJY@ED{liD0OdmA5BDEowEA5KF4%GLNxCbir0dznB8w&a@ zMy8s?W2Fa$RCWleib@5joo2MUNDhAXFoK*T$Q?V^oEEcpi@i_Aj`T9VgOIIIC^|0P z#Xjke)@8|{O4yaCrmUc#AbeR%`rO2N{*QAi+XGOd@~;VPrBV{Nuw!^>X^BqFa!xN( zb0x8k_ir6Y%098JPX6#S#%AZz?tClzTDk6Rh7UO_t5?&Et(n$lCXXYooFKG$xZvC^ zO!J1~LuOIC*(gdNT{yaj7R(Yu^D%KQ={vGz8$#k6APocChPpj%$LF+N5p1ani|L8v zh{rBS_zv;P71m))WnvoIPS%@2J!E&Vs^QE5|twx&H_GR&*!IG1c zflY4dWgANr3mHD}q{H@rE^B#!WP~K$hk^t@jhu&8i~Ht?;y;+v@rE`7%twLy-vO1c zJsVH-j+3?SOfM62q$OqcBe zfpF5#Li}Tj#$%Jkzxt`KNL|uk|HyBtI=DuQxaBunV4JXv0%yOF(kMT+d*bIL0{M5Yj*Y;`Ez( zuJF2Ku?hHy{gCM0OE5YOJh%r-2T3svZwb4gcU|gb>T`^j;f=rPvdCyVN>5~cQiVM?l$peXa`NTsQ2XUyZjgLATh zp@dzNPq%kR?CH`pOI3e9M@+6?VO_xkIg+YA%sj9D`ZTCxS_@2MRT2*}9s8nAK9G5# z=hUo&xINlbPFscYiqYzp61^KjcgF0hMwJUekD~T&De~9j2jYR}Jlyt1+;3rb(Z~%$ zXj_2UpIQZT0b)h_`d-1mA#oXJsaXQ^kL!%DI1Aas4zmVOT@uiCgypK)a zA+|)ajuYA>5)!w=FIHb9g{FPzx2U}zX3`+aeSUM5k+EnIl*)JJ(d)g@t*)Pg395Pb&iSR zb0J&b=Pv1YTy|4>z)*1{(>ILdGpkVY)s=ztOCE=~(w#sBYpDIkj`caiN4EJ!c~}0C z`c9enG!lUssy6FA(h|-Jb_TvDdc#y9O4V~96xf;pnXDYZuLg|o4hu;gj>)Z37>3sx zZFiIka^10EK3-H&%Z^17qd%H2gDDKG(??nkKfaFI3)odDs6Ls_t--%syr+29Zz0$Z z0u%mxkkk_HYgcUVn}wRa{ZRpR2NFg%#PSf`+w0`b!Oo?xqJWe^^genJ6_joGS1mOW zZKu$rvL70G8J7-ExXTB?1ukS%5%DzaW(!kb(apK#39c;bJWCA8cy*he`W&izl_LR; z>FWc-cGhz7OQ~uWHtmm|>7nc+ijWR<@^LVaVXlRmkemrbbu9c(vy zd}?a9ki9SN-S>g=0O&(B=-a#-H=I@6IRZU8dzknzz|k;hTfsgYG#B{lMF(HD)4EV^ z@j#14rsh3Gb}(9?R6m!12OK+JCRl(Hw%zU=0b`TYI+xZm6rU2K{>6v9)GUbwJbS^W z6>bY*!pNbgOq{WMnGErpOhcU`{|AeTmOS0?em zw~ACN7a)1y5CCNOMVW%`jpU$&SPWFx%ciR9G=22i!t`_mlosv|lWwi=>d!E7kSjEI zautiQ`Q^wIjdjd~lrKPLxrsC|7$vcMaag`UaRNK^4el<_5xuHJ~gHxlr>w9T=dE@S&ReOd=~a|i2+xb zTCB-(5?2~T^}+Wb!l2_8ol>j7dFYew94UYI!{pRRXZw)+t)F~72$Gu@+)E@+n=aG) zlmN^|?;i}U)HOIbNZ6Hfi)uCb7?LXo#!F($6sd;R9$HgElt8Fu#JG3O`!)rM*d?cetv%H zGRQ|$1gtm>4h8OkW}LK^cky0}cjwYTrrwgcfZ+?(&j{aR1f$&spKow+@NQ^v$!Qy37&jwxOq!pfMQ{O)@6=ZXJ%lS zd-f8Lyylj`$Z&*3jKRTYlrb6zqbY&1T=1soCF24A2L%>)?%#j^{rBUKJHAZ&e>!dR z%w;d1J$v@(QPNA@1G7LG&^w>u-^H@scfY^CKRr(H_lJjvuU@@+NxR`{kt@faxyzR? z|9bVR0nh&b|9)S-d>JObv~u46(D3*7_wV1g@88Y*Ykcj8f#7Ap{r&a-|NQ)H(dXUI z6m~*X@x%1I{Cs&ixnqTYetmsiwmY`UFKzqnzn@O)f413Q`}^D7-R0ir89^!w?%AB* zeK${{O+S9$nw9I?5^v;fkKb1#*_OEd_Sw&SzQ`oBvWOMj)3n=m`|a7YXD>xpnVXy6 zep@#0`SIh&mu_d!R@u<-+3)GcmzS3>ZQnEH@o>%mG;EX~ zE&E0*0P<@=P$u&B{~-uVO6fUfvq3q(OFnVl^Rve$3v^VjVR*iG(g7>E{>K)2dzm7n z8(HUUyqN>czn8S@TK?AQZ)livfa%`AkCb0ylg=ilEY&k}cN$Ep3kjYn+G@BjDf^~=fc-rw818&qD|OMd
4HXzPj3) z=WyEQpMQRCKEM>$bb#sKxw`%Fud^fM?dxhjKRXL7?n=SMVCJlQ`|J0A>AKg>FMmb! zLs3l}{||j&No3*+EJ1(&{g?iq^~KpVW8cfbqUn6yb{=;csa1e&EVSY( literal 0 HcmV?d00001 diff --git a/tests/ref_imgs_vg_lite/widgets/obj_transform_skew.png b/tests/ref_imgs_vg_lite/widgets/obj_transform_skew.png new file mode 100644 index 0000000000000000000000000000000000000000..49690b2e970dde710168bf342e17aa7d77e12e88 GIT binary patch literal 4839 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 literal 0 HcmV?d00001 diff --git a/tests/ref_imgs_vg_lite/widgets/obj_transform_translate.png b/tests/ref_imgs_vg_lite/widgets/obj_transform_translate.png new file mode 100644 index 0000000000000000000000000000000000000000..4f5b567bd134b1c92d850f747cb4b8a02dda0220 GIT binary patch literal 2807 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV0^&A1QfZHI&TpJ1J^!J7srr_IdAVA%!`T? zbGX=Tc&Y|L3aDOGq-fafLxOX!rAt{jFEN?e<$X28Ox2 zSF$rO{HRynz`&5i#Lb|fHp&`fJszoehR8Vg({@(yC?lf z-F&m=_qW`hkKeulZC@tGE)a3Rcc;v*`oF)f)-K);wCc~Nr>B4HR7!|q;@%SnU4gKKpFi#)z7l8jB-MCpmQzy9%as3|(rPyei`vyn5sW`8Sh`|-zxcJuY8pI({XXg?PiC>a_ zhxXrm|6N~SKe^{?mF-uZ2B74rqMb2o!;*WRKTm%iu^(vm^XJbEk7aHBR4cIVAdu^8 z%Y5K{Wo_->(%IE}*vNE{0dC=yw);&@87>a{`lkP&!7FP8%oS(12d|wSa*9n`}SK8Z*k}_G|cdR kN4rQEHJS8`zHvW8?S)Tk11fW`02{Onp00i_>zopr0A+l=N&o-= literal 0 HcmV?d00001 diff --git a/tests/src/test_cases/widgets/test_obj_transform.c b/tests/src/test_cases/widgets/test_obj_transform.c new file mode 100644 index 000000000..f4759917f --- /dev/null +++ b/tests/src/test_cases/widgets/test_obj_transform.c @@ -0,0 +1,62 @@ +#if LV_BUILD_TEST +#include "../lvgl.h" +#include "unity/unity.h" + +void setUp(void) +{ + /* Function run before every test */ +} + +void tearDown(void) +{ + /* Function run after every test */ + lv_obj_clean(lv_screen_active()); +} + +void test_obj_transform(void) +{ +#if LV_DRAW_TRANSFORM_USE_MATRIX + lv_obj_t * obj = lv_obj_create(lv_screen_active()); + lv_obj_set_size(obj, 100, 100); + lv_obj_center(obj); + + lv_matrix_t matrix; + + lv_matrix_identity(&matrix); + lv_obj_set_transform(obj, &matrix); + TEST_ASSERT_EQUAL_SCREENSHOT("widgets/obj_transform_identity.png"); + + lv_matrix_identity(&matrix); + lv_matrix_translate(&matrix, 50, 100); + lv_obj_set_transform(obj, &matrix); + TEST_ASSERT_EQUAL_SCREENSHOT("widgets/obj_transform_translate.png"); + + lv_matrix_identity(&matrix); + lv_matrix_rotate(&matrix, 30); + lv_obj_set_transform(obj, &matrix); + TEST_ASSERT_EQUAL_SCREENSHOT("widgets/obj_transform_rotate.png"); + + lv_matrix_identity(&matrix); + lv_matrix_scale(&matrix, 0.8f, 1.6f); + lv_obj_set_transform(obj, &matrix); + TEST_ASSERT_EQUAL_SCREENSHOT("widgets/obj_transform_scale.png"); + + lv_matrix_identity(&matrix); + lv_matrix_skew(&matrix, 10.0f, 20.0f); + lv_obj_set_transform(obj, &matrix); + TEST_ASSERT_EQUAL_SCREENSHOT("widgets/obj_transform_skew.png"); + + const lv_matrix_t * obj_transform = lv_obj_get_transform(obj); + TEST_ASSERT_NOT_NULL(obj_transform); + TEST_ASSERT_EQUAL(lv_memcmp(&matrix, obj_transform, sizeof(lv_matrix_t)), 0); + + lv_obj_reset_transform(obj); + TEST_ASSERT_EQUAL_SCREENSHOT("widgets/obj_transform_identity.png"); + TEST_ASSERT_NULL(lv_obj_get_transform(obj)); + +#else + TEST_PASS(); +#endif +} + +#endif