diff --git a/AUTHORS b/AUTHORS index 9f729e6..2ab03ba 100644 --- a/AUTHORS +++ b/AUTHORS @@ -6,3 +6,4 @@ KainX (Michael Jennings) Eric Dorland Chutt (Isaac Richards) gilbertt (Tom Gilbert) +Takis diff --git a/imlib2.spec b/imlib2.spec index 927e0ef..436dda7 100644 --- a/imlib2.spec +++ b/imlib2.spec @@ -1,6 +1,6 @@ # Note that this is NOT a relocatable package -%define ver 0.0.2 -%define rel SNAP +%define ver 0.0.4 +%define rel 1 %define prefix /usr Summary: Powerful image loading and rendering library for X11R6 diff --git a/src/Imlib2.h b/src/Imlib2.h index 6ae96c6..d52e83b 100644 --- a/src/Imlib2.h +++ b/src/Imlib2.h @@ -32,7 +32,8 @@ enum _imlib_text_direction IMLIB_TEXT_TO_RIGHT = 0, IMLIB_TEXT_TO_LEFT = 1, IMLIB_TEXT_TO_DOWN = 2, - IMLIB_TEXT_TO_UP = 3 + IMLIB_TEXT_TO_UP = 3, + IMLIB_TEXT_TO_ANGLE = 4 }; enum _imlib_load_error @@ -95,6 +96,7 @@ void imlib_context_set_color_modifier(Imlib_Color_Modifier color_modifier); void imlib_context_set_operation(Imlib_Operation operation); void imlib_context_set_font(Imlib_Font font); void imlib_context_set_direction(Imlib_Text_Direction direction); +void imlib_context_set_angle(double angle); void imlib_context_set_color(int red, int green, int blue, int alpha); void imlib_context_set_color_range(Imlib_Color_Range color_range); void imlib_context_set_progress_function(Imlib_Progress_Function progress_function); @@ -230,7 +232,8 @@ void imlib_save_image_with_error_return(const char *filename, Imlib_Load_Error * /* need to add arbitary rotation routines */ Imlib_Image imlib_create_rotated_image(double angle); -void imlib_blend_image_onto_image_at_angle(Imlib_Image source_image, char merge_alpha, int source_x, int source_y, int source_width, int source_height, int destination_x1, int destination_y1, int destination_x2, int destination_y2); +void imlib_blend_image_onto_image_at_angle(Imlib_Image source_image, char merge_alpha, int source_x, int source_y, int source_width, int source_height, int destination_x, int destination_y, int angle_x, int angle_y); +void imlib_blend_image_onto_image_skewed(Imlib_Image source_image, char merge_alpha, int source_x, int source_y, int source_width, int source_height, int destination_x, int destination_y, int h_angle_x, int h_angle_y, int v_angle_x, int v_angle_y); void imlib_image_filter(void); Imlib_Filter imlib_create_filter(int initsize); diff --git a/src/api.c b/src/api.c index 98faeb3..2aaf643 100644 --- a/src/api.c +++ b/src/api.c @@ -75,6 +75,7 @@ static Imlib_Color_Modifier ctxt_color_modifier = NULL; static Imlib_Operation ctxt_operation = IMLIB_OP_COPY; static Imlib_Font ctxt_font = NULL; static Imlib_Text_Direction ctxt_direction = IMLIB_TEXT_TO_RIGHT; +static double ctxt_angle = 0.0; static Imlib_Color ctxt_color = {255, 255, 255, 255}; static Imlib_Color_Range ctxt_color_range = NULL; static Imlib_Image ctxt_image = NULL; @@ -235,6 +236,12 @@ imlib_context_set_direction(Imlib_Text_Direction direction) ctxt_direction = direction; } +void +imlib_context_set_angle(double angle) +{ + ctxt_angle = angle; +} + Imlib_Text_Direction imlib_context_get_direction(void) { @@ -1488,7 +1495,7 @@ imlib_text_draw(int x, int y, const char *text) __imlib_render_str(im, ctxt_font, x, y, text, (DATA8)ctxt_color.red, (DATA8)ctxt_color.green, (DATA8)ctxt_color.blue, (DATA8)ctxt_color.alpha, (char)ctxt_direction, - NULL, NULL, 0, NULL, NULL, + ctxt_angle, NULL, NULL, 0, NULL, NULL, ctxt_operation); } @@ -1515,7 +1522,7 @@ imlib_text_draw_with_return_metrics(int x, int y, const char *text, __imlib_render_str(im, fn, x, y, text, (DATA8)ctxt_color.red, (DATA8)ctxt_color.green, (DATA8)ctxt_color.blue, (DATA8)ctxt_color.alpha, (char)ctxt_direction, - width_return, height_return, 0, + ctxt_angle, width_return, height_return, 0, horizontal_advance_return, vertical_advance_return, ctxt_operation); } @@ -1546,6 +1553,43 @@ imlib_get_text_size(const char *text, int *width_return, int *height_return) if (height_return) *height_return = w; break; + case IMLIB_TEXT_TO_ANGLE: + if (width_return || height_return) + { + double sa, ca; + sa = sin(ctxt_angle); + ca = cos(ctxt_angle); + + if (width_return) { + double x1, x2, xt; + x1 = x2 = 0.0; + xt = ca * w; + if (xt < x1) x1 = xt; + if (xt > x2) x2 = xt; + xt = -(sa * h); + if (xt < x1) x1 = xt; + if (xt > x2) x2 = xt; + xt = ca * w - sa * h; + if (xt < x1) x1 = xt; + if (xt > x2) x2 = xt; + *width_return = (int)(x2 - x1); + } + if (height_return) { + double y1, y2, yt; + y1 = y2 = 0.0; + yt = sa * w; + if (yt < y1) y1 = yt; + if (yt > y2) y2 = yt; + yt = ca * h; + if (yt < y1) y1 = yt; + if (yt > y2) y2 = yt; + yt = sa * w + ca * h; + if (yt < y1) y1 = yt; + if (yt > y2) y2 = yt; + *height_return = (int)(y2 - y1); + } + } + break; default: break; } @@ -2213,15 +2257,18 @@ imlib_create_rotated_image(double angle) #ifdef DO_MMX_ASM if (__imlib_get_cpuid() & CPUID_MMX) __imlib_mmx_RotateAA(im_old->data, im->data, im_old->w, - im_old->w, im_old->h, im->w, sz, sz, x, y, dx, dy); + im_old->w, im_old->h, im->w, sz, sz, x, y, + dx, dy, -dy, dx); else #endif __imlib_RotateAA(im_old->data, im->data, im_old->w, - im_old->w, im_old->h, im->w, sz, sz, x, y, dx, dy); + im_old->w, im_old->h, im->w, sz, sz, x, y, + dx, dy, -dy, dx); } else { __imlib_RotateSample(im_old->data, im->data, im_old->w, - im_old->w, im_old->h, im->w, sz, sz, x, y, dx, dy); + im_old->w, im_old->h, im->w, sz, sz, x, y, + dx, dy, -dy, dx); } SET_FLAG(im->flags, F_HAS_ALPHA); @@ -2233,8 +2280,8 @@ imlib_blend_image_onto_image_at_angle(Imlib_Image source_image, char merge_alpha, int source_x, int source_y, int source_width, int source_height, - int destination_x1, int destination_y1, - int destination_x2, int destination_y2) + int destination_x, int destination_y, + int angle_x, int angle_y) { ImlibImage *im_src, *im_dst; @@ -2244,11 +2291,37 @@ imlib_blend_image_onto_image_at_angle(Imlib_Image source_image, CAST_IMAGE(im_dst, ctxt_image); __imlib_DirtyImage(im_dst); __imlib_DirtyPixmapsForImage(im_dst); - __imlib_BlendImageToImageAtAngle(im_src, im_dst, ctxt_anti_alias, - ctxt_blend, merge_alpha, source_x, source_y, - source_width, source_height, destination_x1, - destination_y1, destination_x2, destination_y2, - ctxt_color_modifier, ctxt_operation); + __imlib_BlendImageToImageSkewed(im_src, im_dst, ctxt_anti_alias, + ctxt_blend, merge_alpha, source_x, source_y, + source_width, source_height, + destination_x, destination_y, + angle_x, angle_y, 0, 0, + ctxt_color_modifier, ctxt_operation); +} + +void +imlib_blend_image_onto_image_skewed(Imlib_Image source_image, + char merge_alpha, + int source_x, int source_y, + int source_width, int source_height, + int destination_x, int destination_y, + int h_angle_x, int h_angle_y, + int v_angle_x, int v_angle_y) +{ + ImlibImage *im_src, *im_dst; + + CHECK_PARAM_POINTER("imlib_blend_image_onto_image_skewed", "source_image", source_image); + CHECK_PARAM_POINTER("imlib_blend_image_onto_image_skewed", "image", ctxt_image); + CAST_IMAGE(im_src, source_image); + CAST_IMAGE(im_dst, ctxt_image); + __imlib_DirtyImage(im_dst); + __imlib_DirtyPixmapsForImage(im_dst); + __imlib_BlendImageToImageSkewed(im_src, im_dst, ctxt_anti_alias, + ctxt_blend, merge_alpha, source_x, source_y, + source_width, source_height, + destination_x, destination_y, + h_angle_x, h_angle_y, v_angle_x, v_angle_y, + ctxt_color_modifier, ctxt_operation); } void diff --git a/src/asm_rotate.S b/src/asm_rotate.S index 72df63b..4bc1af1 100644 --- a/src/asm_rotate.S +++ b/src/asm_rotate.S @@ -15,7 +15,8 @@ .align 8 /*\ Prototype: __imlib_mmx_RotateAA(DATA32 *src, DATA32 *dest, int sow, int sw, -|*| int sh, int dow, int dw, int dh, int x, int y, int dx, int dy) +|*| int sh, int dow, int dw, int dh, int x, int y, +|*| int dxh, int dyh, int dxv, int dyv) \*/ #define src 8(%ebp) @@ -28,8 +29,10 @@ #define dh 36(%ebp) #define x 40(%ebp) #define y 44(%ebp) -#define dx 48(%ebp) -#define dy 52(%ebp) +#define dxh 48(%ebp) +#define dyh 52(%ebp) +#define dxv 56(%ebp) +#define dyv 60(%ebp) /*\ Local variables \*/ #define j -4(%ebp) @@ -74,18 +77,18 @@ __imlib_mmx_RotateAA: movl dw, %eax leal (%edi, %eax, 4), %edi - /*\ dlx = -dy - dw * dx \*/ + /*\ dlx = dxv - dw * dxh \*/ movl dw, %eax - imull dx, %eax + imull dxh, %eax negl %eax - subl dy, %eax + addl dxv, %eax movl %eax, dlx - /*\ dly = dx - dw * dy \*/ + /*\ dly = dyv - dw * dyh \*/ movl dw, %eax - imull dy, %eax + imull dyh, %eax negl %eax - addl dx, %eax + addl dyv, %eax movl %eax, dly /*\ j = dh \*/ @@ -98,19 +101,19 @@ __imlib_mmx_RotateAA: movl x, %ecx cmpl %edx, %ecx jae .rotate_outside - /*\ x + dx * dw < sw \*/ - movl dx, %ebx + /*\ x + dxh * dw < sw \*/ + movl dxh, %ebx imull dw, %ebx addl %ebx, %ecx cmpl %edx, %ecx jae .rotate_outside - /*\ x + dx * dw - dy * dh < sw \*/ - movl dy, %eax + /*\ x + dxh * dw + dxv * dh < sw \*/ + movl dxv, %eax imull dh, %eax subl %eax, %ecx cmpl %edx, %ecx jae .rotate_outside - /*\ x - dy * dh < sw \*/ + /*\ x + dxv * dh < sw \*/ subl %ebx, %ecx cmpl %edx, %ecx jae .rotate_outside @@ -120,19 +123,19 @@ __imlib_mmx_RotateAA: movl y, %ecx cmpl %edx, %ecx jae .rotate_outside - /*\ y + dy * dw < sh \*/ - movl dx, %ebx + /*\ y + dyh * dw < sh \*/ + movl dyh, %ebx imull dw, %ebx addl %ebx, %ecx cmpl %edx, %ecx jae .rotate_outside - /*\ y + dy * dw + dx * dh < sh \*/ - movl dy, %eax + /*\ y + dyh * dw + dyv * dh < sh \*/ + movl dyv, %eax imull dh, %eax addl %eax, %ecx cmpl %edx, %ecx jae .rotate_outside - /*\ y + dx * dh < sh \*/ + /*\ y + dyv * dh < sh \*/ subl %ebx, %ecx cmpl %edx, %ecx jae .rotate_outside @@ -196,7 +199,7 @@ __imlib_mmx_RotateAA: packuswb %mm5, %mm5 movd %mm5, (%edi, %ecx, 4) - paddd dx, %mm6 + paddd dxh, %mm6 incl %ecx jnz .inside_loop_x @@ -421,7 +424,7 @@ __imlib_mmx_RotateAA: movl %eax, (%edi, %ecx, 4) .outside_il_end: - paddd dx, %mm6 + paddd dxh, %mm6 incl %ecx jnz .outside_loop_x diff --git a/src/font.c b/src/font.c index 165b072..d7602bf 100644 --- a/src/font.c +++ b/src/font.c @@ -12,9 +12,11 @@ #include "font.h" #include #include +#include #include "file.h" #include "updates.h" #include "rgbadraw.h" +#include "rotate.h" #define TT_VALID( handle ) ( ( handle ).z != NULL ) @@ -382,13 +384,13 @@ __imlib_calc_size(ImlibFont *f, int *width, int *height, const char *text) void __imlib_render_str(ImlibImage *im, ImlibFont *fn, int drx, int dry, const char *text, DATA8 r, DATA8 g, DATA8 b, DATA8 a, - char dir, int *retw, int *reth, int blur, + char dir, double angle, int *retw, int *reth, int blur, int *nextx, int *nexty, ImlibOp op) { DATA32 lut[9], *p, *tmp; TT_Glyph_Metrics metrics; TT_F26Dot6 x, y, xmin, ymin, xmax, ymax; - int w, h, i, ioff, iread, xor, yor; + int w, h, i, ioff, iread, tw, th; char *off, *read, *_off, *_read; int x_offset, y_offset; unsigned char j; @@ -424,14 +426,15 @@ __imlib_render_str(ImlibImage *im, ImlibFont *fn, int drx, int dry, const char * /* figure out the size this text string is going to be */ __imlib_calc_size(fn, &w, &h, text); + tw = w; th = w; switch(dir) { case 0: case 1: if (retw) - *retw = w; + *retw = tw; if (reth) - *reth = h; + *reth = th; if (nexty) *nexty = fn->ascent + fn->descent; if (nextx) @@ -444,10 +447,11 @@ __imlib_render_str(ImlibImage *im, ImlibFont *fn, int drx, int dry, const char * break; case 2: case 3: + tw = h; th = w; if (retw) - *retw = h; + *retw = tw; if (reth) - *reth = w; + *reth = th; if (nextx) *nextx = fn->ascent + fn->descent; if (nexty) @@ -458,11 +462,57 @@ __imlib_render_str(ImlibImage *im, ImlibFont *fn, int drx, int dry, const char * (metrics.bbox.xMax / 64); } break; + case 4: + { + double sa, ca; + double x1, x2, xt; + double y1, y2, yt; + sa = sin(angle); + ca = cos(angle); + + x1 = x2 = 0.0; + xt = ca * w; + if (xt < x1) x1 = xt; + if (xt > x2) x2 = xt; + xt = -(sa * h); + if (xt < x1) x1 = xt; + if (xt > x2) x2 = xt; + xt = ca * w - sa * h; + if (xt < x1) x1 = xt; + if (xt > x2) x2 = xt; + tw = (int)(x2 - x1); + + y1 = y2 = 0.0; + yt = sa * w; + if (yt < y1) y1 = yt; + if (yt > y2) y2 = yt; + yt = ca * h; + if (yt < y1) y1 = yt; + if (yt > y2) y2 = yt; + yt = sa * w + ca * h; + if (yt < y1) y1 = yt; + if (yt > y2) y2 = yt; + th = (int)(y2 - y1); + } + if (retw) + *retw = tw; + if (reth) + *reth = th; + if (nexty) + *nexty = fn->ascent + fn->descent; + if (nextx) + { + j = text[strlen(text) - 1]; + TT_Get_Glyph_Metrics(fn->glyphs[j], &metrics); + *nextx = w - x_offset + (metrics.advance / 64) - + (metrics.bbox.xMax / 64); + } + break; default: break; } /* if the text is completely outside the image - give up */ - if (((drx + w) <= 0) || ((dry + h) <= 0)) + if (((drx + tw) <= 0) || ((dry + th) <= 0)) return; /* create a scratch pad for it */ rmap = __imlib_create_font_raster(w, h); @@ -588,27 +638,50 @@ __imlib_render_str(ImlibImage *im, ImlibFont *fn, int drx, int dry, const char * switch(dir) { case 0: /* to right */ + angle = 0.0; break; case 1: /* to left */ - __imlib_FlipImageHoriz(&im2); - __imlib_FlipImageVert(&im2); + angle = 0.0; + __imlib_FlipImageBoth(&im2); break; case 2: /* to down */ - __imlib_FlipImageDiagonal(&im2, 0); + angle = 0.0; + __imlib_FlipImageDiagonal(&im2, 1); break; case 3: /* to up */ - __imlib_FlipImageDiagonal(&im2, 0); - __imlib_FlipImageHoriz(&im2); - __imlib_FlipImageVert(&im2); + angle = 0.0; + __imlib_FlipImageDiagonal(&im2, 2); break; default: break; } tmp = im2.data; - __imlib_BlendRGBAToData(tmp, im2.w, im2.h, - im->data, im->w, im->h, - 0, 0, drx, dry, im2.w, im2.h, - 1, IMAGE_HAS_ALPHA(im), NULL, op, 0); + if (angle == 0.0) { + __imlib_BlendRGBAToData(tmp, im2.w, im2.h, + im->data, im->w, im->h, + 0, 0, drx, dry, im2.w, im2.h, + 1, IMAGE_HAS_ALPHA(im), NULL, op, 0); + } else { + int xx, yy; + double sa, ca; + sa = sin(angle); + ca = cos(angle); + xx = drx; + yy = dry; + if (sa > 0.0) + xx += sa * im2.h; + else + yy -= sa * im2.w; + if (ca < 0.0) { + xx -= ca * im2.w; + yy -= ca * im2.h; + } + __imlib_BlendImageToImageSkewed(&im2, im, 1, 1, + IMAGE_HAS_ALPHA(im), + 0, 0, im2.w, im2.h, + xx, yy, (w * ca), (w * sa), 0, 0, + NULL, op); + } free(tmp); } __imlib_destroy_font_raster(rmap); diff --git a/src/font.h b/src/font.h index 67bbbca..dc0c1aa 100644 --- a/src/font.h +++ b/src/font.h @@ -36,7 +36,7 @@ void __imlib_calc_size(ImlibFont *f, int *width, int *height, void __imlib_render_str(ImlibImage *im, ImlibFont *fn, int drx, int dry, const char *text, DATA8 r, DATA8 g, DATA8 b, DATA8 a, - char dir, int *retw, int *reth, int blur, + char dir, double angle, int *retw, int *reth, int blur, int *nextx, int *nexty, ImlibOp op); int __imlib_char_pos(ImlibFont *fn, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch); diff --git a/src/rotate.c b/src/rotate.c index 8189fb1..3f75aab 100644 --- a/src/rotate.c +++ b/src/rotate.c @@ -51,7 +51,8 @@ /*\ Rotate by pixel sampling only, target inside source \*/ static void __imlib_RotateSampleInside(DATA32 *src, DATA32 *dest, int sow, int dow, - int dw, int dh, int x, int y, int dx, int dy) + int dw, int dh, int x, int y, + int dxh, int dyh, int dxv, int dyv) { int i; @@ -62,14 +63,14 @@ __imlib_RotateSampleInside(DATA32 *src, DATA32 *dest, int sow, int dow, do { *dest = src[(x >> _ROTATE_PREC) + ((y >> _ROTATE_PREC) * sow)]; /*\ RIGHT; \*/ - x += dx; - y += dy; + x += dxh; + y += dyh; dest++; } while (--i >= 0); if (--dh <= 0) break; /*\ DOWN/LEFT; \*/ - x += -dy - dw * dx; - y += dx - dw * dy; + x += dxv - dw * dxh; + y += dyv - dw * dyh; dest += (dow - dw); } } @@ -77,7 +78,8 @@ __imlib_RotateSampleInside(DATA32 *src, DATA32 *dest, int sow, int dow, /*\ Same as last function, but with antialiasing \*/ static void __imlib_RotateAAInside(DATA32 *src, DATA32 *dest, int sow, int dow, - int dw, int dh, int x, int y, int dx, int dy) + int dw, int dh, int x, int y, + int dxh, int dyh, int dxv, int dyv) { int i; @@ -90,14 +92,14 @@ __imlib_RotateAAInside(DATA32 *src, DATA32 *dest, int sow, int dow, ((y >> _ROTATE_PREC) * sow)); INTERP_ARGB(dest, src_x_y, sow, x, y); /*\ RIGHT; \*/ - x += dx; - y += dy; + x += dxh; + y += dyh; dest++; } while (--i >= 0); if (--dh <= 0) break; /*\ DOWN/LEFT; \*/ - x += -dy - dw * dx; - y += dx - dw * dy; + x += dxv - dw * dxh; + y += dyv - dw * dyh; dest += (dow - dw); } } @@ -110,7 +112,7 @@ __imlib_RotateAAInside(DATA32 *src, DATA32 *dest, int sow, int dow, |*| v in [-t .. 0) is also special, as its the same as ~v in [0 .. t) \*/ static int -__check_inside_coords(int x, int y, int dx, int dy, +__check_inside_coords(int x, int y, int dxh, int dyh, int dxv, int dyv, int dw, int dh, int sw, int sh) { sw <<= _ROTATE_PREC; @@ -118,13 +120,13 @@ __check_inside_coords(int x, int y, int dx, int dy, if (((unsigned)x >= sw) || ((unsigned)y >= sh)) return 0; - x += dx * dw; y += dy * dw; + x += dxh * dw; y += dyh * dw; if (((unsigned)x >= sw) || ((unsigned)y >= sh)) return 0; - x -= dy * dh; y += dx * dh; + x += dxv * dh; y += dyv * dh; if (((unsigned)x >= sw) || ((unsigned)y >= sh)) return 0; - x -= dx * dw; y -= dy * dw; + x -= dxh * dw; y -= dyh * dw; if (((unsigned)x >= sw) || ((unsigned)y >= sh)) return 0; @@ -134,14 +136,16 @@ __check_inside_coords(int x, int y, int dx, int dy, /*\ These ones don't need the target to be inside the source \*/ void __imlib_RotateSample(DATA32 *src, DATA32 *dest, int sow, int sw, int sh, - int dow, int dw, int dh, int x, int y, int dx, int dy) + int dow, int dw, int dh, int x, int y, + int dxh, int dyh, int dxv, int dyv) { int i; if ((dw < 1) || (dh < 1)) return; - if (__check_inside_coords(x, y, dx, dy, dw, dh, sw, sh)) { - __imlib_RotateSampleInside(src, dest, sow, dow, dw, dh, x, y, dx, dy); + if (__check_inside_coords(x, y, dxh, dyh, dxv, dyv, dw, dh, sw, sh)) { + __imlib_RotateSampleInside(src, dest, sow, dow, dw, dh, x, y, + dxh, dyh, dxv, dyv); return; } @@ -155,15 +159,15 @@ __imlib_RotateSample(DATA32 *src, DATA32 *dest, int sow, int sw, int sh, *dest = src[(x >> _ROTATE_PREC) + ((y >> _ROTATE_PREC) * sow)]; else *dest = 0; /*\ RIGHT; \*/ - x += dx; - y += dy; + x += dxh; + y += dyh; dest++; } while (--i >= 0); if (--dh <= 0) break; /*\ DOWN/LEFT; \*/ - x += -dy - dw * dx; - y += dx - dw * dy; + x += dxv - dw * dxh; + y += dyv - dw * dyh; dest += (dow - dw); } @@ -177,14 +181,16 @@ __imlib_RotateSample(DATA32 *src, DATA32 *dest, int sow, int sw, int sh, \*/ void __imlib_RotateAA(DATA32 *src, DATA32 *dest, int sow, int sw, int sh, - int dow, int dw, int dh, int x, int y, int dx, int dy) + int dow, int dw, int dh, int x, int y, + int dxh, int dyh, int dxv, int dyv) { int i; if ((dw < 1) || (dh < 1)) return; - if (__check_inside_coords(x, y, dx, dy, dw, dh, sw - 1, sh - 1)) { - __imlib_RotateAAInside(src, dest, sow, dow, dw, dh, x, y, dx, dy); + if (__check_inside_coords(x, y, dxh, dyh, dxv, dyv, dw, dh, sw-1, sh-1)) { + __imlib_RotateAAInside(src, dest, sow, dow, dw, dh, x, y, + dxh, dyh, dxv, dyv); return; } @@ -250,15 +256,15 @@ __imlib_RotateAA(DATA32 *src, DATA32 *dest, int sow, int sw, int sh, } else *dest = 0; } else *dest = 0; /*\ RIGHT; \*/ - x += dx; - y += dy; + x += dxh; + y += dyh; dest++; } while (--i >= 0); if (--dh <= 0) break; /*\ DOWN/LEFT; \*/ - x += -dy - dw * dx; - y += dx - dw * dy; + x += dxv - dw * dxh; + y += dyv - dw * dyh; dest += (dow - dw); } @@ -269,17 +275,18 @@ __imlib_RotateAA(DATA32 *src, DATA32 *dest, int sow, int sw, int sh, #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) void -__imlib_BlendImageToImageAtAngle(ImlibImage *im_src, ImlibImage *im_dst, - char aa, char blend, char merge_alpha, - int ssx, int ssy, int ssw, int ssh, - int ddx1, int ddy1, int ddx2, int ddy2, - ImlibColorModifier *cm, ImlibOp op) +__imlib_BlendImageToImageSkewed(ImlibImage *im_src, ImlibImage *im_dst, + char aa, char blend, char merge_alpha, + int ssx, int ssy, int ssw, int ssh, + int ddx, int ddy, + int hsx, int hsy, int vsx, int vsy, + ImlibColorModifier *cm, ImlibOp op) { - int ddw, ddh, x, y, dx, dy, i; + int x, y, dxh, dyh, dxv, dyv, i; double xy2; DATA32 *data, *src; int do_mmx; - + if ((ssw < 0) || (ssh < 0)) return; @@ -292,31 +299,27 @@ __imlib_BlendImageToImageAtAngle(ImlibImage *im_src, ImlibImage *im_dst, if (!im_dst->data) return; - ddw = ddx2 - ddx1; - ddh = ddy2 - ddy1; - if ((ssw == ddw) & (ssh == ddh)) { - if (!IMAGE_HAS_ALPHA(im_src)) - blend = 0; - if (!IMAGE_HAS_ALPHA(im_dst)) - merge_alpha = 0; - - __imlib_BlendRGBAToData(im_src->data, im_src->w, im_src->h, - im_dst->data, im_dst->w, im_dst->h, - ssx, ssy, ddx1, ddy1, - ssw, ssh, blend, merge_alpha, cm, op, 0); - return; - - } /*\ Complicated gonio. Works on paper.. |*| Too bad it doesn't all fit into integer math.. \*/ - xy2 = (double)(ddh * ddh + ddw * ddw); - if (xy2 == 0) return; - dx = (((double)((ssh * ddh) + (ssw * ddw)) * _ROTATE_PREC_MAX) / xy2); - dy = (((double)((ssh * ddw) - (ssw * ddh)) * _ROTATE_PREC_MAX) / xy2); - x = ddy1 * dy - ddx1 * dx; - y = -ddx1 * dy - ddy1 * dx; - + if (vsx | vsy) { + xy2 = (double)(hsx * vsy - vsx * hsy) / _ROTATE_PREC_MAX; + if (xy2 == 0.0) return; + dxh = (double)(ssw * vsy) / xy2; + dxv = (double)-(ssw * vsx) / xy2; + dyh = (double)-(ssh * hsy) / xy2; + dyv = (double)(ssh * hsx) / xy2; + } else { + xy2 = (double)(hsx * hsx + hsy * hsy) / _ROTATE_PREC_MAX; + if (xy2 == 0.0) return; + dxh = (double)(ssw * hsx) / xy2; + dyh = (double)-(ssw * hsy) / xy2; + dxv = -dyh; + dyv = dxh; + } + x = - (ddx * dxh + ddy * dxv); + y = - (ddx * dyh + ddy * dyv); + if (ssx < 0) { x += ssx * _ROTATE_PREC_MAX; ssw += ssx; @@ -349,8 +352,8 @@ __imlib_BlendImageToImageAtAngle(ImlibImage *im_src, ImlibImage *im_dst, h = MIN(LINESIZE, im_dst->h - i); - x2 = x - h * dy; - y2 = y + h * dx; + x2 = x + h * dxv; + y2 = y + h * dyv; w = ssw << _ROTATE_PREC; h = ssh << _ROTATE_PREC; @@ -360,43 +363,43 @@ __imlib_BlendImageToImageAtAngle(ImlibImage *im_src, ImlibImage *im_dst, h += 2 << _ROTATE_PREC; } /*\ Pretty similar code \*/ - if (dx > 0) { - if (dy > 0) { - l = MAX(-y2 / dy, -x / dx); - r = MIN((h - y) / dy, (w - x2) / dx); + if (dxh > 0) { + if (dyh > 0) { + l = MAX(-MAX(y, y2) / dyh, -MAX(x, x2) / dxh); + r = MIN((h - MIN(y, y2)) / dyh, (w - MIN(x, x2)) / dxh); - } else if (dy < 0) { - l = MAX(-x2 / dx, (h - y) / dy); - r = MIN(-y2 / dy, (w - x) / dx); + } else if (dyh < 0) { + l = MAX(-MAX(x, x2) / dxh, (h - MIN(y, y2)) / dyh); + r = MIN(-MAX(y, y2) / dyh, (w - MIN(x, x2)) / dxh); } else { - l = -x / dx; - r = (w - x) / dx; + l = -MAX(x, x2) / dxh; + r = (w - MIN(x, x2)) / dxh; } - } else if (dx < 0) { - if (dy > 0) { - l = MAX(-y / dy, (w - x2) / dx); - r = MIN(-x / dx, (h - y2) / dy); + } else if (dxh < 0) { + if (dyh > 0) { + l = MAX(-MAX(y, y2) / dyh, (w - MIN(x, x2)) / dxh); + r = MIN(-MAX(x, x2) / dxh, (h - MIN(y, y2)) / dyh); - } else if (dy < 0) { - l = MAX((h - y2) / dy, (w - x) / dx); - r = MIN(-y / dy, -x2 / dx); + } else if (dyh < 0) { + l = MAX((h - MIN(y, y2)) / dyh, (w - MIN(x, x2)) / dxh); + r = MIN(-MAX(y, y2) / dyh, -MAX(x, x2) / dxh); } else { - l = (w - x) / dx; - r = -x / dx; + l = (w - MIN(x, x2)) / dxh; + r = -MAX(x, x2) / dxh; } } else { - if (dy > 0) { - l = -y / dy; - r = (h - y) / dy; + if (dyh > 0) { + l = -MAX(y, y2) / dyh; + r = (h - MIN(y, y2)) / dyh; - } else if (dy < 0) { - l = (h - y) / dy; - r = -y / dy; + } else if (dyh < 0) { + l = (h - MIN(y, y2)) / dyh; + r = -MAX(y, y2) / dyh; } else { l = 0; @@ -416,22 +419,22 @@ __imlib_BlendImageToImageAtAngle(ImlibImage *im_src, ImlibImage *im_dst, w = r - l; h = MIN(LINESIZE, im_dst->h - i); - x += l * dx; - y += l * dy; + x += l * dxh; + y += l * dyh; if (aa) { x -= _ROTATE_PREC_MAX; y -= _ROTATE_PREC_MAX; #ifdef DO_MMX_ASM if (do_mmx) __imlib_mmx_RotateAA(src, data, im_src->w, ssw, ssh, w, w, h, - x, y, dx, dy); + x, y, dxh, dyh, dxv, dyv); else #endif __imlib_RotateAA(src, data, im_src->w, ssw, ssh, w, w, h, - x, y, dx, dy); + x, y, dxh, dyh, dxv, dyv); } else { __imlib_RotateSample(src, data, im_src->w, ssw, ssh, w, w, h, - x, y, dx, dy); + x, y, dxh, dyh, dxv, dyv); } __imlib_BlendRGBAToData(data, w, h, im_dst->data, diff --git a/src/rotate.h b/src/rotate.h index d1a331c..7c2c0c1 100644 --- a/src/rotate.h +++ b/src/rotate.h @@ -12,17 +12,21 @@ #define _ROTATE_PREC_BITS (_ROTATE_PREC_MAX - 1) void __imlib_RotateSample(DATA32 *src, DATA32 *dest, int sow, int sw, int sh, - int dow, int dw, int dh, int x, int y, int dx, int dy); + int dow, int dw, int dh, int x, int y, + int dxh, int dyh, int dxv, int dyv); void __imlib_RotateAA(DATA32 *src, DATA32 *dest, int sow, int sw, int sh, - int dow, int dw, int dh, int x, int y, int dx, int dy); -void __imlib_BlendImageToImageAtAngle(ImlibImage *im_src, ImlibImage *im_dst, - char aa, char blend, char merge_alpha, - int ssx, int ssy, int ssw, int ssh, - int ddx, int ddy, int ddw, int ddh, - ImlibColorModifier *cm, ImlibOp op); + int dow, int dw, int dh, int x, int y, + int dx, int dy, int dxv, int dyv); +void __imlib_BlendImageToImageSkewed(ImlibImage *im_src, ImlibImage *im_dst, + char aa, char blend, char merge_alpha, + int ssx, int ssy, int ssw, int ssh, + int ddx, int ddy, + int hsx, int hsy, int vsx, int vsy, + ImlibColorModifier *cm, ImlibOp op); #ifdef DO_MMX_ASM void __imlib_mmx_RotateAA(DATA32 *src, DATA32 *dest, int sow, int sw, int sh, - int dow, int dw, int dh, int x, int y, int dx, int dy); + int dow, int dw, int dh, int x, int y, + int dx, int dy, int dxv, int dyv); #endif #endif diff --git a/test/main.c b/test/main.c index 516a255..b67bc1c 100644 --- a/test/main.c +++ b/test/main.c @@ -738,6 +738,10 @@ int main (int argc, char **argv) for (i = 0; i < 16; i++) { int al; + double an = (double)i / 10.0; + + imlib_context_set_direction(IMLIB_TEXT_TO_ANGLE); + imlib_context_set_angle(an); al = (15 - i) * 16; if (al > 255) @@ -749,6 +753,7 @@ int main (int argc, char **argv) up = imlib_update_append_rect(up, 50, ty, retw, reth); ty += ny; } + imlib_context_set_direction(IMLIB_TEXT_TO_RIGHT); cp = imlib_text_get_index_and_location(str, x - 50, y - 50, &cx, &cy, &cw, &ch); if (cp >= 0)