// File: /workspace/github_c_makefile_star2_O2/OnionIoT[P]lv_example/lvgl/src/lv_objx/lv_canvas.c
// Function: lv_canvas_rotate
void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_coord_t offset_x, lv_coord_t offset_y,
                      int32_t pivot_x, int32_t pivot_y)
{
    LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
    LV_ASSERT_NULL(img);

    lv_canvas_ext_t * ext_dst = lv_obj_get_ext_attr(canvas);
    const lv_style_t * style  = lv_canvas_get_style(canvas, LV_CANVAS_STYLE_MAIN);
    int32_t sinma             = lv_trigo_sin(-angle);
    int32_t cosma             = lv_trigo_sin(-angle + 90); /* cos */

    int32_t img_width   = img->header.w;
    int32_t img_height  = img->header.h;
    int32_t dest_width  = ext_dst->dsc.header.w;
    int32_t dest_height = ext_dst->dsc.header.h;

    int32_t x;
    int32_t y;
    for(x = -offset_x; x < dest_width - offset_x; x++) {
        for(y = -offset_y; y < dest_height - offset_y; y++) {
            /*Get the target point relative coordinates to the pivot*/
            int32_t xt = x - pivot_x;
            int32_t yt = y - pivot_y;

            /*Get the source pixel from the upscaled image*/
            int32_t xs = ((cosma * xt - sinma * yt) >> (LV_TRIGO_SHIFT - 8)) + pivot_x * 256;
            int32_t ys = ((sinma * xt + cosma * yt) >> (LV_TRIGO_SHIFT - 8)) + pivot_y * 256;

            /*Get the integer part of the source pixel*/
            int xs_int = xs >> 8;
            int ys_int = ys >> 8;

            if(xs_int >= img_width)
                continue;
            else if(xs_int < 0)
                continue;

            if(ys_int >= img_height)
                continue;
            else if(ys_int < 0)
                continue;

            /*Get the fractional part of the source pixel*/
            int xs_fract = xs & 0xff;
            int ys_fract = ys & 0xff;

            /* If the fractional < 0x70 mix the source pixel with the left/top pixel
             * If the fractional > 0x90 mix the source pixel with the right/bottom pixel
             * In the 0x70..0x90 range use the unchanged source pixel */

            int xn;      /*x neightboor*/
            lv_opa_t xr; /*x mix ratio*/
            if(xs_fract < 0x70) {
                xn = xs_int - 1;
                xr = xs_fract * 2;
            } else if(xs_fract > 0x90) {
                xn = xs_int + 1;
                xr = (0xFF - xs_fract) * 2;
            } else {
                xn = xs_int;
                xr = 0xFF;
            }

            /*Handle under/overflow*/
            if(xn >= img_width)
                continue;
            else if(xn < 0)
                continue;

            int yn;      /*y neightboor*/
            lv_opa_t yr; /*y mix ratio*/
            if(ys_fract < 0x70) {
                yn = ys_int - 1;
                yr = ys_fract * 2;
            } else if(ys_fract > 0x90) {
                yn = ys_int + 1;
                yr = (0xFF - ys_fract) * 2;
            } else {
                yn = ys_int;
                yr = 0xFF;
            }

            /*Handle under/overflow*/
            if(yn >= img_height)
                continue;
            else if(yn < 0)
                continue;

            /*Get the mixture of the original source and the neightboor pixels in both directions*/
            lv_color_t c_dest_int = lv_img_buf_get_px_color(img, xs_int, ys_int, style);

            if(lv_img_color_format_is_chroma_keyed(img->header.cf)) {
                lv_color_t ct = LV_COLOR_TRANSP;
                if(c_dest_int.full == ct.full) continue;
            }

            lv_color_t c_dest_xn = lv_img_buf_get_px_color(img, xn, ys_int, style);
            lv_color_t c_dest_yn = lv_img_buf_get_px_color(img, xs_int, yn, style);
            lv_color_t x_dest    = lv_color_mix(c_dest_int, c_dest_xn, xr);
            lv_color_t y_dest    = lv_color_mix(c_dest_int, c_dest_yn, yr);
            lv_color_t color_res = lv_color_mix(x_dest, y_dest, LV_OPA_50);

            if(x + offset_x >= 0 && x + offset_x < dest_width && y + offset_y >= 0 && y + offset_y < dest_height) {
                /*If the image has no alpha channel just simple set the result color on the canvas*/
                if(lv_img_color_format_has_alpha(img->header.cf) == false) {
                    lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, color_res);
                } else {
                    /*Get result pixel opacity*/
                    lv_opa_t opa_int = lv_img_buf_get_px_alpha(img, xs_int, ys_int);
                    lv_opa_t opa_xn  = lv_img_buf_get_px_alpha(img, xn, ys_int);
                    lv_opa_t opa_yn  = lv_img_buf_get_px_alpha(img, xs_int, yn);
                    lv_opa_t opa_x   = (opa_int * xr + (opa_xn * (255 - xr))) >> 8;
                    lv_opa_t opa_y   = (opa_int * yr + (opa_yn * (255 - yr))) >> 8;
                    lv_opa_t opa_res = (opa_x + opa_y) / 2;
                    if(opa_res <= LV_OPA_MIN) continue;

                    lv_color_t bg_color = lv_img_buf_get_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, style);

                    /*If the canvas has no alpha but the image has mix the image's color with
                     * canvas*/
                    if(lv_img_color_format_has_alpha(ext_dst->dsc.header.cf) == false) {
                        if(opa_res < LV_OPA_MAX) color_res = lv_color_mix(color_res, bg_color, opa_res);
                        lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, color_res);
                    }
                    /*Both the image and canvas has alpha channel. Some extra calculation is
                       required*/
                    else {
                        lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y);
                        /* Pick the foreground if it's fully opaque or the Background is fully
                         * transparent*/
                        if(opa_res >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) {
                            lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, color_res);
                            lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, opa_res);
                        }
                        /*Opaque background: use simple mix*/
                        else if(bg_opa >= LV_OPA_MAX) {
                            lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y,
                                                    lv_color_mix(color_res, bg_color, opa_res));
                        }
                        /*Both colors have alpha. Expensive calculation need to be applied*/
                        else {

                            /*Info:
                             * https://en.wikipedia.org/wiki/Alpha_compositing#Analytical_derivation_of_the_over_operator*/
                            lv_opa_t opa_res_2 = 255 - ((uint16_t)((uint16_t)(255 - opa_res) * (255 - bg_opa)) >> 8);
                            if(opa_res_2 == 0) {
                                opa_res_2 = 1; /*never happens, just to be sure*/
                            }
                            lv_opa_t ratio = (uint16_t)((uint16_t)opa_res * 255) / opa_res_2;

                            lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y,
                                                    lv_color_mix(color_res, bg_color, ratio));
                            lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, opa_res_2);
                        }
                    }
                }
            }
        }
    }

    lv_obj_invalidate(canvas);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movl %r9d, %r12d
movl %r8d, %ebp
movl %ecx, %r15d
movl %edx, %r14d
movq %rsi, %r13
movq %rdi, %rbx
movl 0xd0(%rsp), %eax
movl %eax, 0x38(%rsp)
callq 0x7994
testb %al, %al
je 0x16c4a
movq %r13, %rdi
callq 0x7994
testb %al, %al
je 0x16c5b
movq %rbx, %rdi
callq 0x6747
movq %rax, 0x40(%rsp)
movq %rbx, %rdi
xorl %esi, %esi
callq 0x164d2
movq %rax, 0x50(%rsp)
movl %r14d, %eax
negl %eax
movswl %ax, %edi
callq 0x28d8c
movl %ebp, 0x3c(%rsp)
movswl %ax, %ebp
pushq $0x5a
popq %rax
subl %r14d, %eax
movswl %ax, %edi
callq 0x28d8c
movl %ebp, %r8d
movq %r13, 0x58(%rsp)
movl (%r13), %r9d
movq 0x40(%rsp), %rdi
movl %r9d, %r10d
shrl $0xa, %r10d
movl $0x7ff, %ecx            # imm = 0x7FF
andl %ecx, %r10d
shrl $0x15, %r9d
movl 0x18(%rdi), %esi
addq $0x18, %rdi
movl %esi, %edx
shrl $0xa, %edx
andl %ecx, %edx
shrl $0x15, %esi
movswl %r15w, %r11d
movl %r11d, %r14d
negl %r14d
movl %edx, 0x68(%rsp)
movl %edx, %ebp
subl %r11d, %ebp
movswl 0x3c(%rsp), %r13d
movl %r13d, %edx
negl %edx
movl %esi, 0x60(%rsp)
movl %esi, %r15d
subl %r13d, %r15d
movl %r12d, %ecx
shll $0x8, %ecx
movq %rcx, 0x30(%rsp)
movl 0x38(%rsp), %esi
movl %r12d, %ecx
movl %esi, %r12d
shll $0x8, %r12d
movq %r12, 0x90(%rsp)
cmpl %r15d, %edx
cmovgl %edx, %r15d
cmpl %ebp, %r14d
cmovgl %r14d, %ebp
movl %ebp, 0x64(%rsp)
movswl %ax, %edx
addl %r13d, %r15d
movq %r11, 0x78(%rsp)
addl %r11d, %ecx
movq 0x30(%rsp), %r11
negl %ecx
movl %ecx, %eax
imull %edx, %eax
addl %r13d, %esi
movl %esi, %r13d
negl %r13d
imull %r8d, %esi
addl %eax, %esi
movl %esi, 0x38(%rsp)
imull %r8d, %ecx
movl %edx, 0x3c(%rsp)
imull %edx, %r13d
addl %ecx, %r13d
movq %rbx, 0x80(%rsp)
movq %rdi, 0x40(%rsp)
movl %r8d, 0x18(%rsp)
movl %r9d, 0x14(%rsp)
movl %r10d, 0x10(%rsp)
movl %r15d, 0xc(%rsp)
cmpl 0x64(%rsp), %r14d
je 0x16c6c
movq 0x78(%rsp), %rax
movq %r14, 0x88(%rsp)
addl %r14d, %eax
movl %eax, 0x4c(%rsp)
xorl %ebp, %ebp
movl %r13d, 0x6c(%rsp)
movl 0x38(%rsp), %ebx
cmpl %ebp, %r15d
je 0x16c22
movl %ebx, %esi
sarl $0x7, %esi
leal (%rsi,%r11), %eax
sarl $0x8, %eax
cmpl %r10d, %eax
jae 0x16b4b
movl %r13d, %edx
sarl $0x7, %edx
movq 0x90(%rsp), %rcx
addl %edx, %ecx
sarl $0x8, %ecx
cmpl %r9d, %ecx
jae 0x16b4b
movl %esi, %edi
movl $0xff, %r14d
andl %r14d, %edi
cmpl $0x6f, %edi
ja 0x16854
leal -0x1(%rax), %r14d
jmp 0x16869
movb $-0x1, %r12b
movl %eax, %r14d
cmpl $0x91, %edi
jb 0x1686f
leal 0x1(%rax), %r14d
notb %sil
addb %sil, %sil
movl %esi, %r12d
movb %r12b, 0x1c(%rsp)
cmpl %r10d, %r14d
jae 0x16b4b
movl %edx, %esi
movl $0xff, %edi
andl %edi, %esi
cmpl $0x6f, %esi
ja 0x16891
leal -0x1(%rcx), %r12d
jmp 0x168a5
movb $-0x1, %dil
movl %ecx, %r12d
cmpl $0x91, %esi
jb 0x168a9
leal 0x1(%rcx), %r12d
notb %dl
addb %dl, %dl
movl %edx, %edi
movb %dil, 0x28(%rsp)
cmpl %r9d, %r12d
jae 0x16b4b
movswl %ax, %esi
movswl %cx, %edx
movq 0x58(%rsp), %r15
movq %r15, %rdi
movl %esi, 0x2c(%rsp)
movl %edx, 0x20(%rsp)
movq 0x50(%rsp), %rcx
callq 0x383d3
movl %eax, 0x24(%rsp)
movl (%r15), %edi
movl 0xc(%rsp), %r15d
andl $0x1f, %edi
callq 0x389a9
movq 0x30(%rsp), %r11
movl 0x10(%rsp), %r10d
movl 0x14(%rsp), %r9d
movl 0x18(%rsp), %r8d
testb %al, %al
je 0x16910
cmpw $0x7e0, 0x24(%rsp)      # imm = 0x7E0
je 0x16b4b
movswl %r14w, %esi
movq 0x58(%rsp), %r14
movq %r14, %rdi
movl %esi, 0x74(%rsp)
movl 0x20(%rsp), %edx
movq 0x50(%rsp), %r15
movq %r15, %rcx
callq 0x383d3
movl %eax, 0x48(%rsp)
movswl %r12w, %edx
movq %r14, %rdi
movl 0x2c(%rsp), %esi
movl %edx, 0x70(%rsp)
movq %r15, %rcx
callq 0x383d3
movl %eax, %r14d
movzbl 0x1c(%rsp), %edx
movl 0x24(%rsp), %r12d
movl %r12d, %edi
movl 0x48(%rsp), %esi
movl %edx, 0x48(%rsp)
callq 0x16c85
movl %eax, %r15d
movzbl 0x28(%rsp), %edx
movl %r12d, %edi
movl %r14d, %esi
movl %edx, 0x1c(%rsp)
callq 0x16c85
movl %r15d, %edi
movl 0xc(%rsp), %r15d
movl %eax, %esi
pushq $0x7f
popq %rdx
callq 0x16c85
movq 0x30(%rsp), %r11
movl 0x10(%rsp), %r10d
movl 0x14(%rsp), %r9d
movl 0x18(%rsp), %r8d
movl %eax, %r14d
movl 0x4c(%rsp), %eax
cmpl 0x68(%rsp), %eax
jae 0x16b4b
cmpl 0x60(%rsp), %ebp
jae 0x16b4b
movq 0x58(%rsp), %r15
movl (%r15), %edi
andl $0x1f, %edi
callq 0x389bb
movswl 0x4c(%rsp), %esi
testb %al, %al
je 0x16b22
movl %esi, 0x28(%rsp)
movq %r15, %rdi
movl 0x2c(%rsp), %r12d
movl %r12d, %esi
movl 0x20(%rsp), %edx
callq 0x38530
movl %r14d, 0x24(%rsp)
movl %eax, %r14d
movq %r15, %rdi
movl 0x74(%rsp), %esi
movl 0x20(%rsp), %edx
callq 0x38530
movq %r15, %rdi
movl %eax, %r15d
movl %r12d, %esi
movl 0x70(%rsp), %edx
callq 0x38530
movzbl %r14b, %ecx
movl %ecx, %edx
movl 0x48(%rsp), %r8d
imull %r8d, %edx
movzbl %r15b, %esi
movl $0xff, %edi
xorl %edi, %r8d
imull %esi, %r8d
addl %edx, %r8d
shrl $0x8, %r8d
movl 0x1c(%rsp), %r12d
imull %r12d, %ecx
movzbl %al, %eax
xorl %edi, %r12d
imull %eax, %r12d
addl %ecx, %r12d
shrl $0x8, %r12d
andl %edi, %r8d
andl %edi, %r12d
addl %r8d, %r12d
cmpl $0x22, %r12d
movl 0x18(%rsp), %r8d
movl 0x14(%rsp), %r9d
movl 0x10(%rsp), %r10d
movl 0xc(%rsp), %r15d
movq 0x30(%rsp), %r11
jb 0x16b4b
movl %r12d, %eax
movl 0x28(%rsp), %r12d
movl %eax, %r15d
movl %eax, 0x1c(%rsp)
shrl %r15d
movswl %bp, %edx
movq 0x40(%rsp), %r14
movq %r14, %rdi
movl %r12d, %esi
movq 0x50(%rsp), %rcx
callq 0x383d3
movl %eax, 0x20(%rsp)
movl (%r14), %edi
andl $0x1f, %edi
callq 0x389bb
movzbl %r15b, %edx
testb %al, %al
je 0x16b5a
movl %edx, 0x2c(%rsp)
movswl %bp, %edx
movq %r14, %rdi
movl %r12d, %esi
callq 0x38530
cmpl $0x1f5, 0x1c(%rsp)      # imm = 0x1F5
ja 0x16b82
cmpb $0x10, %al
jbe 0x16b82
cmpb $-0x5, %al
jb 0x16bb1
movl 0x24(%rsp), %edi
movl 0x20(%rsp), %esi
movl 0x2c(%rsp), %edx
callq 0x16c85
movswl %bp, %edx
movq 0x40(%rsp), %rdi
movl 0x28(%rsp), %esi
movl %eax, %ecx
jmp 0x16b2d
movswl %bp, %edx
movq 0x40(%rsp), %rdi
movl %r14d, %ecx
callq 0x3864c
movl 0x18(%rsp), %r8d
movl 0x14(%rsp), %r9d
movl 0x10(%rsp), %r10d
movl 0xc(%rsp), %r15d
movq 0x30(%rsp), %r11
incl %ebp
subl %r8d, %ebx
addl 0x3c(%rsp), %r13d
jmp 0x16804
cmpl $0x1f5, 0x1c(%rsp)      # imm = 0x1F5
movl 0x24(%rsp), %ecx
ja 0x16b75
movl %ecx, %edi
movl 0x20(%rsp), %esi
callq 0x16c85
movl %eax, %ecx
movswl %bp, %edx
movq 0x40(%rsp), %rdi
movl %r12d, %esi
jmp 0x16b2d
movswl %bp, %r14d
movq 0x40(%rsp), %r12
movq %r12, %rdi
movl 0x28(%rsp), %r15d
movl %r15d, %esi
movl %r14d, %edx
movl 0x24(%rsp), %ecx
callq 0x3864c
movq %r12, %rdi
movl %r15d, %esi
movl %r14d, %edx
movl 0x2c(%rsp), %ecx
jmp 0x16c18
imull $0xff, %r15d, %ecx
movl $0xff, %esi
xorl %esi, %r15d
notb %al
movzbl %al, %eax
imull %r15d, %eax
shrl $0x8, %eax
notb %al
movzbl %al, %edi
movl %edi, 0x1c(%rsp)
movl %ecx, %eax
xorl %edx, %edx
divw %di
andl %esi, %eax
movl 0x24(%rsp), %edi
movl 0x20(%rsp), %esi
movl %eax, %edx
callq 0x16c85
movswl %bp, %r14d
movq 0x40(%rsp), %r12
movq %r12, %rdi
movl 0x28(%rsp), %r15d
movl %r15d, %esi
movl %r14d, %edx
movl %eax, %ecx
callq 0x3864c
movq %r12, %rdi
movl %r15d, %esi
movl %r14d, %edx
movl 0x1c(%rsp), %ecx
callq 0x387ed
jmp 0x16b32
movq 0x88(%rsp), %r14
incl %r14d
movl 0x3c(%rsp), %eax
addl %eax, 0x38(%rsp)
movl 0x6c(%rsp), %r13d
addl %r8d, %r13d
movq 0x80(%rsp), %rbx
jmp 0x167da
leaq 0x244f3(%rip), %rdi     # 0x3b144
movq %rbx, %rsi
callq 0x7b01
jmp 0x16c59
leaq 0x244e2(%rip), %rdi     # 0x3b144
movq %r13, %rsi
callq 0x7b01
jmp 0x16c6a
movq %rbx, %rdi
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x493a