{ int x, y, w; int *lin_ptr, *lp; int *interp_x, *interp_y, *ix, *iy; DATA32 *buf, *dptr; DATA32 **row_ptr, **rp; DATA32 *ptr, *ptr2, *ptr3, *ptr4; DATA32 *src_data, *src_end, col; Gfx_Func_Blend_Src_Cmod_Dst func_cmod; Gfx_Func_Blend_Src_Mul_Dst func_mul; Gfx_Func_Blend_Src_Dst func; lin_ptr = (int *)malloc(dst_clip_w * sizeof(int)); row_ptr = (DATA32 **)malloc(dst_clip_h * sizeof(DATA32 *)); interp_x = (int *)malloc(dst_clip_w * sizeof(int)); interp_y = (int *)malloc(dst_clip_h * sizeof(int)); if ( (!lin_ptr) || (!row_ptr) || (!interp_x) || (!interp_y) ) goto done_scale_up; /* a scanline buffer */ buf = (DATA32 *)malloc(dst_clip_w * sizeof(DATA32)); if (!buf) goto done_scale_up; src_data = src->image->data; for (x = 0; x < dst_clip_w; x++) { if (src_region_w > 1) { lin_ptr[x] = (((x + dst_clip_x - dst_region_x) * (src_region_w)) / dst_region_w); if (dst_region_w > 262144) interp_x[x] = (((((x + dst_clip_x - dst_region_x) * (src_region_w))) / dst_region_w) - (lin_ptr[x])) << 8; else if (dst_region_w > 131072) interp_x[x] = (((((x + dst_clip_x - dst_region_x) * (src_region_w)) << 1) / dst_region_w) - (lin_ptr[x] << 1)) << 7; else if (dst_region_w > 65536) interp_x[x] = (((((x + dst_clip_x - dst_region_x) * (src_region_w)) << 2) / dst_region_w) - (lin_ptr[x] << 2)) << 6; else if (dst_region_w > 37268) interp_x[x] = (((((x + dst_clip_x - dst_region_x) * (src_region_w)) << 3) / dst_region_w) - (lin_ptr[x] << 3)) << 5; else if (dst_region_w > 16384) interp_x[x] = (((((x + dst_clip_x - dst_region_x) * (src_region_w)) << 4) / dst_region_w) - (lin_ptr[x] << 4)) << 4; else if (dst_region_w > 8192) interp_x[x] = (((((x + dst_clip_x - dst_region_x) * (src_region_w)) << 5) / dst_region_w) - (lin_ptr[x] << 5)) << 3; else if (dst_region_w > 4096) interp_x[x] = (((((x + dst_clip_x - dst_region_x) * (src_region_w)) << 6) / dst_region_w) - (lin_ptr[x] << 6)) << 2; else if (dst_region_w > 2048) interp_x[x] = (((((x + dst_clip_x - dst_region_x) * (src_region_w)) << 7) / dst_region_w) - (lin_ptr[x] << 7)) << 1; else interp_x[x] = (((((x + dst_clip_x - dst_region_x) * (src_region_w)) << 8) / dst_region_w) - (lin_ptr[x] << 8)); lin_ptr[x] += src_region_x; } else { lin_ptr[x] = (((x + dst_clip_x - dst_region_x) * src_region_w) / dst_region_w); interp_x[x] = 0; lin_ptr[x] += src_region_x; } } for (y = 0; y < dst_clip_h; y++) { int pos; if (src_region_h > 1) { pos = (((y + dst_clip_y - dst_region_y) * (src_region_h)) / dst_region_h); row_ptr[y] = src_data + ((pos + src_region_y) * src_w); if (dst_region_h > 262144) interp_y[y] = (((((y + dst_clip_y - dst_region_y) * (src_region_h))) / dst_region_h) - (pos)) << 8; else if (dst_region_h > 131072) interp_y[y] = (((((y + dst_clip_y - dst_region_y) * (src_region_h)) << 1) / dst_region_h) - (pos << 1)) << 7; else if (dst_region_h > 65536) interp_y[y] = (((((y + dst_clip_y - dst_region_y) * (src_region_h)) << 2) / dst_region_h) - (pos << 2)) << 6; else if (dst_region_h > 32768) interp_y[y] = (((((y + dst_clip_y - dst_region_y) * (src_region_h)) << 3) / dst_region_h) - (pos << 3)) << 5; else if (dst_region_h > 16384) interp_y[y] = (((((y + dst_clip_y - dst_region_y) * (src_region_h)) << 4) / dst_region_h) - (pos << 4)) << 4; else if (dst_region_h > 8192) interp_y[y] = (((((y + dst_clip_y - dst_region_y) * (src_region_h)) << 5) / dst_region_h) - (pos << 5)) << 3; else if (dst_region_h > 4096) interp_y[y] = (((((y + dst_clip_y - dst_region_y) * (src_region_h)) << 6) / dst_region_h) - (pos << 6)) << 2; else if (dst_region_h > 2048) interp_y[y] = (((((y + dst_clip_y - dst_region_y) * (src_region_h)) << 7) / dst_region_h) - (pos << 7)) << 1; else interp_y[y] = (((((y + dst_clip_y - dst_region_y) * (src_region_h)) << 8) / dst_region_h) - (pos << 8)); } else { pos = (((y + dst_clip_y - dst_region_y) * src_region_h) / dst_region_h); row_ptr[y] = src_data + ((pos + src_region_y) * src_w); interp_y[y] = 0; } } src_end = src_data + (src_w * src_h) - 1; col = dc->mul.col; func = evas_common_draw_func_blend_get (src, dst, dst_clip_w); func_cmod = evas_common_draw_func_blend_cmod_get (src, dst, dst_clip_w); func_mul = evas_common_draw_func_blend_mul_get (src, col, dst, dst_clip_w); dptr = dst_ptr; rp = row_ptr; iy = interp_y; lp = lin_ptr; ix = interp_x; w = dst_clip_w; #ifndef SCALE_USING_MMX if (src->flags & RGBA_IMAGE_HAS_ALPHA) { while (dst_clip_h--) { int k = *interp_y++, px = -1; DATA32 *lptr1 = *row_ptr++, *lptr2 = (lptr1 + src_w); DATA32 p1 = 0, p2 = 0; if (lptr2 > src_end) lptr2 = lptr1; dst_ptr = buf; while (dst_clip_w--) { int i = *interp_x++, cx = *lin_ptr++; /* if we have a new pair of horizontal pixels to */ /* interpolate between them vertically */ if (px != cx) { px = cx; ptr = lptr1 + px; ptr2 = ptr + 1; ptr3 = lptr2 + px; ptr4 = ptr3 + 1; if (px >= (src_w - 1)) { ptr2--; ptr4--; } p1 = p2 = 0; if (A_VAL(ptr) | A_VAL(ptr3) | A_VAL(ptr2) | A_VAL(ptr4)) { p1 = *ptr; p1 += ARGB_JOIN( (k * (A_VAL(ptr3) - A_VAL(ptr))) >> 8, (k * (R_VAL(ptr3) - R_VAL(ptr))) >> 8, (k * (G_VAL(ptr3) - G_VAL(ptr))) >> 8, (k * (B_VAL(ptr3) - B_VAL(ptr))) >> 8 ); p2 = *ptr2; p2 += ARGB_JOIN( (k * (A_VAL(ptr4) - A_VAL(ptr2))) >> 8, (k * (R_VAL(ptr4) - R_VAL(ptr2))) >> 8, (k * (G_VAL(ptr4) - G_VAL(ptr2))) >> 8, (k * (B_VAL(ptr4) - B_VAL(ptr2))) >> 8 ); } } *dst_ptr = p1; /* interpolate horizontally */ if (A_VAL(&p1) | A_VAL(&p2)) { *dst_ptr += ARGB_JOIN( (i * (A_VAL(&p2) - A_VAL(dst_ptr))) >> 8, (i * (R_VAL(&p2) - R_VAL(dst_ptr))) >> 8, (i * (G_VAL(&p2) - G_VAL(dst_ptr))) >> 8, (i * (B_VAL(&p2) - B_VAL(dst_ptr))) >> 8 ); } dst_ptr++; } /* * blend here [clip_w *] buf -> dptr * */ if (dc->mod.use) func_cmod(buf, dptr, dst_clip_w, dc->mod.r, dc->mod.g, dc->mod.b, dc->mod.a); else if (dc->mul.use) func_mul(buf, dptr, dst_clip_w, col); else func(buf, dptr, dst_clip_w); dptr += dst_w; dst_clip_w = w; interp_x = ix; lin_ptr = lp; } } else { while (dst_clip_h--) { int k = *interp_y++, px = -1; DATA32 *lptr1 = *row_ptr++, *lptr2 = (lptr1 + src_w); DATA32 p1 = 0xff000000, p2 = 0; if (lptr2 > src_end) lptr2 = lptr1; dst_ptr = buf; while (dst_clip_w--) { int i = *interp_x++, cx = *lin_ptr++; /* if we have a new pair of horizontal pixels to */ /* interpolate between them vertically */ if (px != cx) { px = cx; ptr = lptr1 + px; ptr2 = ptr + 1; ptr3 = lptr2 + px; ptr4 = ptr3 + 1; if (px >= (src_w - 1)) { ptr2--; ptr4--; } p1 = *ptr | 0xff000000; p1 += RGB_JOIN( (k * (R_VAL(ptr3) - R_VAL(ptr))) >> 8, (k * (G_VAL(ptr3) - G_VAL(ptr))) >> 8, (k * (B_VAL(ptr3) - B_VAL(ptr))) >> 8 ); p2 = *ptr2; p2 += RGB_JOIN( (k * (R_VAL(ptr4) - R_VAL(ptr2))) >> 8, (k * (G_VAL(ptr4) - G_VAL(ptr2))) >> 8, (k * (B_VAL(ptr4) - B_VAL(ptr2))) >> 8 ); } *dst_ptr = p1; /* interpolate horizontally */ *dst_ptr += RGB_JOIN( (i * (R_VAL(&p2) - R_VAL(dst_ptr))) >> 8, (i * (G_VAL(&p2) - G_VAL(dst_ptr))) >> 8, (i * (B_VAL(&p2) - B_VAL(dst_ptr))) >> 8 ); dst_ptr++; } /* * blend here [clip_w *] buf -> dptr * */ if (dc->mod.use) func_cmod(buf, dptr, dst_clip_w, dc->mod.r, dc->mod.g, dc->mod.b, dc->mod.a); else if (dc->mul.use) func_mul(buf, dptr, dst_clip_w, col); else func(buf, dptr, dst_clip_w); dptr += dst_w; dst_clip_w = w; interp_x = ix; lin_ptr = lp; } } #else if (src->flags & RGBA_IMAGE_HAS_ALPHA) { pxor_r2r(mm0, mm0); pxor_r2r(mm1, mm1); pxor_r2r(mm2, mm2); while (dst_clip_h--) { int k = *interp_y++, px = -1; DATA32 *lptr1 = *row_ptr++, *lptr2 = (lptr1 + src_w); if (lptr2 > src_end) lptr2 = lptr1; /* mm5 = k */ movd_m2r(k, mm5); punpcklwd_r2r(mm5, mm5); punpckldq_r2r(mm5, mm5); dst_ptr = buf; while (dst_clip_w--) { int i = *interp_x++, cx = *lin_ptr++; /* if we have a new pair of horizontal pixels to */ /* interpolate between them vertically */ if (px != cx) { px = cx; ptr = lptr1 + px; ptr2 = ptr + 1; ptr3 = lptr2 + px; ptr4 = ptr3 + 1; if (px >= (src_w - 1)) { ptr2--; ptr4--; } movd_m2r(*ptr, mm1); punpcklwd_r2r(mm0, mm1); movd_m2r(*ptr2, mm2); punpcklwd_r2r(mm0, mm2); if (A_VAL(ptr) | A_VAL(ptr3) | A_VAL(ptr2) | A_VAL(ptr4)) { movd_m2r(*ptr3, mm3); punpcklwd_r2r(mm0, mm3); psubusw_r2r(mm1, mm3); pmullw_r2r(mm5, mm3); psrlw_i2r(8, mm3); paddw_r2r(mm3, mm1); movd_m2r(*ptr4, mm4); punpcklwd_r2r(mm0, mm4); psubusw_r2r(mm2, mm4); pmullw_r2r(mm5, mm4); psrlw_i2r(8, mm4); paddw_r2r(mm4, mm2); } } /* interpolate horizontally */ movd_m2r(i, mm6); punpcklwd_r2r(mm6, mm6); punpckldq_r2r(mm6, mm6); movq_r2r(mm1, mm3); movq_r2r(mm2, mm4); psubusw_r2r(mm3, mm4); pmullw_r2r(mm6, mm4); psrlw_i2r(8, mm4); paddw_r2r(mm4, mm3); packuswb_r2r(mm0, mm3); movd_r2m(mm3, *dst_ptr); dst_ptr++; } /* * blend here [clip_w *] buf -> dptr * */ if (dc->mod.use) func_cmod(buf, dptr, dst_clip_w, dc->mod.r, dc->mod.g, dc->mod.b, dc->mod.a); else if (dc->mul.use) func_mul(buf, dptr, dst_clip_w, col); else func(buf, dptr, dst_clip_w); dptr += dst_w; dst_clip_w = w; interp_x = ix; lin_ptr = lp; } } else { pxor_r2r(mm0, mm0); while (dst_clip_h--) { int k = *interp_y++, px = -1; DATA32 *lptr1 = *row_ptr++, *lptr2 = (lptr1 + src_w); if (lptr2 > src_end) lptr2 = lptr1; /* mm5 = k */ movd_m2r(k, mm5); punpcklwd_r2r(mm5, mm5); punpckldq_r2r(mm5, mm5); psrlq_i2r(16, mm5); dst_ptr = buf; *dst_ptr = 0xff000000; movd_m2r(*dst_ptr, mm1); punpcklwd_r2r(mm0, mm1); pxor_r2r(mm2, mm2); while (dst_clip_w--) { int i = *interp_x++, cx = *lin_ptr++; /* if we have a new pair of horizontal pixels to */ /* interpolate between them vertically */ if (px != cx) { px = cx; ptr = lptr1 + px; ptr2 = ptr + 1; ptr3 = lptr2 + px; ptr4 = ptr3 + 1; if (px >= (src_w - 1)) { ptr2--; ptr4--; } movd_m2r(*ptr & 0xff000000, mm1); punpcklwd_r2r(mm0, mm1); movd_m2r(*ptr3, mm3); punpcklwd_r2r(mm0, mm3); psubusw_r2r(mm1, mm3); pmullw_r2r(mm5, mm3); psrlw_i2r(8, mm3); paddw_r2r(mm3, mm1); movd_m2r(*ptr2, mm2); punpcklwd_r2r(mm0, mm2); movd_m2r(*ptr4, mm4); punpcklwd_r2r(mm0, mm4); psubusw_r2r(mm2, mm4); pmullw_r2r(mm5, mm4); psrlw_i2r(8, mm4); paddw_r2r(mm4, mm2); } /* interpolate horizontally */ movd_m2r(i, mm6); punpcklwd_r2r(mm6, mm6); punpckldq_r2r(mm6, mm6); psrlq_i2r(16, mm6); movq_r2r(mm1, mm3); movq_r2r(mm2, mm4); psubusw_r2r(mm3, mm4); pmullw_r2r(mm6, mm4); psrlw_i2r(8, mm4); paddw_r2r(mm4, mm3); packuswb_r2r(mm0, mm3); movd_r2m(mm3, *dst_ptr); dst_ptr++; } /* * blend here [clip_w *] buf -> dptr * */ if (dc->mod.use) func_cmod(buf, dptr, dst_clip_w, dc->mod.r, dc->mod.g, dc->mod.b, dc->mod.a); else if (dc->mul.use) func_mul(buf, dptr, dst_clip_w, col); else func(buf, dptr, dst_clip_w); dptr += dst_w; dst_clip_w = w; interp_x = ix; lin_ptr = lp; } } #endif row_ptr = rp; interp_y = iy; lin_ptr = lp; interp_x = ix; done_scale_up: if (buf) free(buf); if (interp_y) free(interp_y); if (interp_x) free(interp_x); if (row_ptr) free(row_ptr); if (lin_ptr) free(lin_ptr); }