diff --git a/src/api.c b/src/api.c index 262eee6..768ac75 100644 --- a/src/api.c +++ b/src/api.c @@ -140,7 +140,8 @@ imlib_context_set_colormap(Colormap colormap) ctxt_colormap = colormap; } -Colormap imlib_context_get_colormap(void) +Colormap +imlib_context_get_colormap(void) { return ctxt_colormap; } @@ -151,7 +152,8 @@ imlib_context_set_drawable(Drawable drawable) ctxt_drawable = drawable; } -Drawable imlib_context_get_drawable(void) +Drawable +imlib_context_get_drawable(void) { return ctxt_drawable; } @@ -162,7 +164,8 @@ imlib_context_set_mask(Pixmap mask) ctxt_mask = mask; } -Pixmap imlib_context_get_mask(void) +Pixmap +imlib_context_get_mask(void) { return ctxt_mask; } @@ -221,7 +224,8 @@ imlib_context_set_color_modifier(Imlib_Color_Modifier color_modifier) ctxt_color_modifier = color_modifier; } -Imlib_Color_Modifier imlib_context_get_color_modifier(void) +Imlib_Color_Modifier +imlib_context_get_color_modifier(void) { return ctxt_color_modifier; } @@ -232,7 +236,8 @@ imlib_context_set_operation(Imlib_Operation operation) ctxt_operation = operation; } -Imlib_Operation imlib_context_get_operation(void) +Imlib_Operation +imlib_context_get_operation(void) { return ctxt_operation; } @@ -243,7 +248,8 @@ imlib_context_set_font(Imlib_Font font) ctxt_font = font; } -Imlib_Font imlib_context_get_font(void) +Imlib_Font +imlib_context_get_font(void) { return ctxt_font; } @@ -266,7 +272,8 @@ imlib_context_get_angle(void) return ctxt_angle; } -Imlib_Text_Direction imlib_context_get_direction(void) +Imlib_Text_Direction +imlib_context_get_direction(void) { return ctxt_direction; } @@ -301,7 +308,8 @@ imlib_context_set_color_range(Imlib_Color_Range color_range) ctxt_color_range = color_range; } -Imlib_Color_Range imlib_context_get_color_range(void) +Imlib_Color_Range +imlib_context_get_color_range(void) { return ctxt_color_range; } @@ -312,7 +320,8 @@ imlib_context_set_progress_function(Imlib_Progress_Function progress_function) ctxt_progress_func = progress_function; } -Imlib_Progress_Function imlib_context_get_progress_function(void) +Imlib_Progress_Function +imlib_context_get_progress_function(void) { return ctxt_progress_func; } @@ -335,7 +344,8 @@ imlib_context_set_image(Imlib_Image image) ctxt_image = image; } -Imlib_Image imlib_context_get_image(void) +Imlib_Image +imlib_context_get_image(void) { return ctxt_image; } @@ -395,7 +405,8 @@ imlib_get_best_visual(Display * display, int screen, int *depth_return) return __imlib_BestVisual(display, screen, depth_return); } -Imlib_Image imlib_load_image(const char *file) +Imlib_Image +imlib_load_image(const char *file) { Imlib_Image im = NULL; Imlib_Image prev_ctxt_image; @@ -409,7 +420,8 @@ Imlib_Image imlib_load_image(const char *file) return (Imlib_Image) im; } -Imlib_Image imlib_load_image_immediately(const char *file) +Imlib_Image +imlib_load_image_immediately(const char *file) { Imlib_Image im = NULL; Imlib_Image prev_ctxt_image; @@ -424,7 +436,8 @@ Imlib_Image imlib_load_image_immediately(const char *file) return (Imlib_Image) im; } -Imlib_Image imlib_load_image_without_cache(const char *file) +Imlib_Image +imlib_load_image_without_cache(const char *file) { Imlib_Image im = NULL; Imlib_Image prev_ctxt_image; @@ -439,7 +452,8 @@ Imlib_Image imlib_load_image_without_cache(const char *file) return (Imlib_Image) im; } -Imlib_Image imlib_load_image_immediately_without_cache(const char *file) +Imlib_Image +imlib_load_image_immediately_without_cache(const char *file) { Imlib_Image im = NULL; Imlib_Image prev_ctxt_image; @@ -454,9 +468,9 @@ Imlib_Image imlib_load_image_immediately_without_cache(const char *file) return (Imlib_Image) im; } -Imlib_Image imlib_load_image_with_error_return(const char *file, - Imlib_Load_Error * - error_return) +Imlib_Image +imlib_load_image_with_error_return(const char *file, + Imlib_Load_Error * error_return) { Imlib_Image im = NULL; ImlibLoadError er; @@ -904,7 +918,8 @@ imlib_blend_image_onto_image(Imlib_Image source_image, char merge_alpha, ctxt_color_modifier, ctxt_operation); } -Imlib_Image imlib_create_image(int width, int height) +Imlib_Image +imlib_create_image(int width, int height) { DATA32 *data; @@ -916,8 +931,8 @@ Imlib_Image imlib_create_image(int width, int height) return NULL; } -Imlib_Image imlib_create_image_using_data(int width, int height, - DATA32 * data) +Imlib_Image +imlib_create_image_using_data(int width, int height, DATA32 * data) { ImlibImage *im; @@ -931,8 +946,8 @@ Imlib_Image imlib_create_image_using_data(int width, int height, return (Imlib_Image) im; } -Imlib_Image imlib_create_image_using_copied_data(int width, int height, - DATA32 * data) +Imlib_Image +imlib_create_image_using_copied_data(int width, int height, DATA32 * data) { ImlibImage *im; @@ -954,9 +969,9 @@ Imlib_Image imlib_create_image_using_copied_data(int width, int height, return NULL; } -Imlib_Image imlib_create_image_from_drawable(Pixmap mask, int x, int y, - int width, int height, - char need_to_grab_x) +Imlib_Image +imlib_create_image_from_drawable(Pixmap mask, int x, int y, int width, + int height, char need_to_grab_x) { ImlibImage *im; char domask = 0; @@ -972,14 +987,14 @@ Imlib_Image imlib_create_image_from_drawable(Pixmap mask, int x, int y, return (Imlib_Image) im; } -Imlib_Image imlib_create_scaled_image_from_drawable(Pixmap mask, int source_x, - int source_y, - int source_width, - int source_height, - int destination_width, - int destination_height, - char need_to_grab_x, - char get_mask_from_shape) +Imlib_Image +imlib_create_scaled_image_from_drawable(Pixmap mask, int source_x, + int source_y, int source_width, + int source_height, + int destination_width, + int destination_height, + char need_to_grab_x, + char get_mask_from_shape) { ImlibImage *im; char domask = 0, tmpmask = 0; @@ -1080,7 +1095,7 @@ imlib_copy_drawable_to_image(Pixmap mask, int x, int y, int width, int height, if (mask) domask = 1; CAST_IMAGE(im, ctxt_image); - + if ((!(im->data)) && (im->loader) && (im->loader->load)) im->loader->load(im, NULL, 0, 1); if (!(im->data)) @@ -1133,7 +1148,8 @@ imlib_copy_drawable_to_image(Pixmap mask, int x, int y, int width, int height, height, domask, need_to_grab_x); } -Imlib_Image imlib_clone_image(void) +Imlib_Image +imlib_clone_image(void) { ImlibImage *im, *im_old; @@ -1172,7 +1188,8 @@ Imlib_Image imlib_clone_image(void) return (Imlib_Image) im; } -Imlib_Image imlib_create_cropped_image(int x, int y, int width, int height) +Imlib_Image +imlib_create_cropped_image(int x, int y, int width, int height) { ImlibImage *im, *im_old; @@ -1196,11 +1213,11 @@ Imlib_Image imlib_create_cropped_image(int x, int y, int width, int height) return (Imlib_Image) im; } -Imlib_Image imlib_create_cropped_scaled_image(int source_x, int source_y, - int source_width, - int source_height, - int destination_width, - int destination_height) +Imlib_Image +imlib_create_cropped_scaled_image(int source_x, int source_y, + int source_width, int source_height, + int destination_width, + int destination_height) { ImlibImage *im, *im_old; @@ -1239,7 +1256,8 @@ Imlib_Image imlib_create_cropped_scaled_image(int source_x, int source_y, return (Imlib_Image) im; } -Imlib_Updates imlib_updates_clone(Imlib_Updates updates) +Imlib_Updates +imlib_updates_clone(Imlib_Updates updates) { ImlibUpdate *u; @@ -1247,8 +1265,8 @@ Imlib_Updates imlib_updates_clone(Imlib_Updates updates) return (Imlib_Updates) __imlib_DupUpdates(u); } -Imlib_Updates imlib_update_append_rect(Imlib_Updates updates, int x, int y, - int w, int h) +Imlib_Updates +imlib_update_append_rect(Imlib_Updates updates, int x, int y, int w, int h) { ImlibUpdate *u; @@ -1256,7 +1274,8 @@ Imlib_Updates imlib_update_append_rect(Imlib_Updates updates, int x, int y, return (Imlib_Updates) __imlib_AddUpdate(u, x, y, w, h); } -Imlib_Updates imlib_updates_merge(Imlib_Updates updates, int w, int h) +Imlib_Updates +imlib_updates_merge(Imlib_Updates updates, int w, int h) { ImlibUpdate *u; @@ -1264,8 +1283,8 @@ Imlib_Updates imlib_updates_merge(Imlib_Updates updates, int w, int h) return (Imlib_Updates) __imlib_MergeUpdate(u, w, h, 0); } -Imlib_Updates imlib_updates_merge_for_rendering(Imlib_Updates updates, int w, - int h) +Imlib_Updates +imlib_updates_merge_for_rendering(Imlib_Updates updates, int w, int h) { ImlibUpdate *u; @@ -1282,7 +1301,8 @@ imlib_updates_free(Imlib_Updates updates) __imlib_FreeUpdates(u); } -Imlib_Updates imlib_updates_get_next(Imlib_Updates updates) +Imlib_Updates +imlib_updates_get_next(Imlib_Updates updates) { ImlibUpdate *u; @@ -1350,13 +1370,15 @@ imlib_render_image_updates_on_drawable(Imlib_Updates updates, int x, int y) __imlib_SetMaxXImageCount(ctxt_display, 0); } -Imlib_Updates imlib_updates_init(void) +Imlib_Updates +imlib_updates_init(void) { return (Imlib_Updates) NULL; } -Imlib_Updates imlib_updates_append_updates(Imlib_Updates updates, - Imlib_Updates appended_updates) +Imlib_Updates +imlib_updates_append_updates(Imlib_Updates updates, + Imlib_Updates appended_updates) { ImlibUpdate *u, *uu; @@ -1549,7 +1571,8 @@ imlib_image_tile(void) __imlib_TileImageVert(im); } -Imlib_Font imlib_load_font(const char *font_name) +Imlib_Font +imlib_load_font(const char *font_name) { return (Imlib_Font) __imlib_load_font(font_name); } @@ -1697,9 +1720,9 @@ imlib_get_text_size(const char *text, int *width_return, int *height_return) } } -void imlib_get_text_advance(const char *text, - int *horizontal_advance_return, - int *vertical_advance_return) +void +imlib_get_text_advance(const char *text, int *horizontal_advance_return, + int *vertical_advance_return) { ImlibFont *fn; int w, h; @@ -1714,7 +1737,8 @@ void imlib_get_text_advance(const char *text, *vertical_advance_return = h; } -int imlib_get_text_inset(const char *text) +int +imlib_get_text_inset(const char *text) { ImlibFont *fn; int w, h; @@ -1967,7 +1991,8 @@ imlib_get_maximum_font_descent(void) return ((ImlibFont *) ctxt_font)->max_descent / 64; } -Imlib_Color_Modifier imlib_create_color_modifier(void) +Imlib_Color_Modifier +imlib_create_color_modifier(void) { return (Imlib_Color_Modifier) __imlib_CreateCmod(); } @@ -2098,8 +2123,8 @@ imlib_apply_color_modifier_to_rectangle(int x, int y, int width, int height) (ImlibColorModifier *) ctxt_color_modifier); } -Imlib_Updates imlib_image_draw_line(int x1, int y1, int x2, int y2, - char make_updates) +Imlib_Updates +imlib_image_draw_line(int x1, int y1, int x2, int y2, char make_updates) { ImlibImage *im; @@ -2117,18 +2142,17 @@ Imlib_Updates imlib_image_draw_line(int x1, int y1, int x2, int y2, return (Imlib_Updates) __imlib_draw_line_clipped(im, x1, y1, x2, y2, ctxt_cliprect.x, ctxt_cliprect.x + - ctxt_cliprect.w, + ctxt_cliprect.w - 1, ctxt_cliprect.y, ctxt_cliprect.y + - ctxt_cliprect.h, + ctxt_cliprect.h - 1, (DATA8) ctxt_color.red, - (DATA8) - ctxt_color.green, - (DATA8) - ctxt_color.blue, - (DATA8) - ctxt_color.alpha, - ctxt_operation, + (DATA8) ctxt_color. + green, + (DATA8) ctxt_color. + blue, + (DATA8) ctxt_color. + alpha, ctxt_operation, (char) make_updates); } else @@ -2303,7 +2327,8 @@ imlib_image_copy_rect(int x, int y, int width, int height, int new_x, __imlib_copy_image_data(im, x, y, width, height, new_x, new_y); } -Imlib_Color_Range imlib_create_color_range(void) +Imlib_Color_Range +imlib_create_color_range(void) { return (Imlib_Color_Range) __imlib_CreateRange(); } @@ -2496,7 +2521,8 @@ imlib_save_image_with_error_return(const char *filename, ctxt_image = prev_ctxt_image; } -Imlib_Image imlib_create_rotated_image(double angle) +Imlib_Image +imlib_create_rotated_image(double angle) { ImlibImage *im, *im_old; int x, y, dx, dy, sz; @@ -2688,7 +2714,8 @@ imlib_image_filter(void) __imlib_FilterImage(im, (ImlibFilter *) ctxt_filter); } -Imlib_Filter imlib_create_filter(int initsize) +Imlib_Filter +imlib_create_filter(int initsize) { return (Imlib_Filter) __imlib_CreateFilter(initsize); } @@ -2707,7 +2734,8 @@ imlib_context_set_filter(Imlib_Filter filter) ctxt_filter = filter; } -Imlib_Filter imlib_context_get_filter(void) +Imlib_Filter +imlib_context_get_filter(void) { return ctxt_filter; } @@ -2798,7 +2826,8 @@ imlib_apply_filter(char *script, ...) va_end(param_list); } -ImlibPolygon imlib_polygon_new(void) +ImlibPolygon +imlib_polygon_new(void) { return (ImlibPolygon) __imlib_polygon_new(); } @@ -2833,9 +2862,9 @@ imlib_image_draw_polygon(ImlibPolygon poly, unsigned char closed) if (ctxt_cliprect.w) { __imlib_draw_polygon_clipped(im, poly, closed, ctxt_cliprect.x, - ctxt_cliprect.x + ctxt_cliprect.w, + ctxt_cliprect.x + ctxt_cliprect.w - 1, ctxt_cliprect.y, - ctxt_cliprect.y + ctxt_cliprect.h, + ctxt_cliprect.y + ctxt_cliprect.h - 1, ctxt_color.red, ctxt_color.green, ctxt_color.blue, ctxt_color.alpha, ctxt_operation); @@ -2866,7 +2895,7 @@ imlib_image_fill_polygon(ImlibPolygon poly) ctxt_cliprect.y + ctxt_cliprect.h, ctxt_color.red, ctxt_color.green, ctxt_color.blue, ctxt_color.alpha, - ctxt_operation); + ctxt_operation, ctxt_anti_alias); } @@ -2895,9 +2924,9 @@ imlib_image_draw_ellipse(int xc, int yc, int a, int b) if (ctxt_cliprect.w) { __imlib_draw_ellipse_clipped(im, xc, yc, a, b, ctxt_cliprect.x, - ctxt_cliprect.x + ctxt_cliprect.w, + ctxt_cliprect.x + ctxt_cliprect.w - 1, ctxt_cliprect.y, - ctxt_cliprect.y + ctxt_cliprect.h, + ctxt_cliprect.y + ctxt_cliprect.h - 1, ctxt_color.red, ctxt_color.green, ctxt_color.blue, ctxt_color.alpha, ctxt_operation); @@ -2924,18 +2953,18 @@ imlib_image_fill_ellipse(int xc, int yc, int a, int b) __imlib_DirtyPixmapsForImage(im); __imlib_fill_ellipse(im, xc, yc, a, b, ctxt_cliprect.x, - ctxt_cliprect.x + ctxt_cliprect.w, - ctxt_cliprect.y, - ctxt_cliprect.y + ctxt_cliprect.h, - ctxt_color.red, ctxt_color.green, - ctxt_color.blue, ctxt_color.alpha, - ctxt_operation); + ctxt_cliprect.x + ctxt_cliprect.w, + ctxt_cliprect.y, + ctxt_cliprect.y + ctxt_cliprect.h, ctxt_color.red, + ctxt_color.green, ctxt_color.blue, ctxt_color.alpha, + ctxt_operation, ctxt_anti_alias); } unsigned char imlib_polygon_contains_point(ImlibPolygon poly, int x, int y) { - CHECK_PARAM_POINTER_RETURN("imlib_polygon_contains_point", "polygon", poly, 0); + CHECK_PARAM_POINTER_RETURN("imlib_polygon_contains_point", "polygon", poly, + 0); return __imlib_polygon_contains_point(poly, x, y); } diff --git a/src/rgbadraw.c b/src/rgbadraw.c index e649123..6fe2914 100644 --- a/src/rgbadraw.c +++ b/src/rgbadraw.c @@ -15,9 +15,10 @@ #define round(a) floor(a+0.5) -static void -span(ImlibImage * im, int y, edgeRec * pt1, edgeRec * pt2, DATA8 r, DATA8 g, - DATA8 b, DATA8 a, ImlibOp op); +static void span(ImlibImage * im, int y, edgeRec * pt1, edgeRec * pt2, + DATA8 r, DATA8 g, DATA8 b, DATA8 a, ImlibOp op); +static void spanAA(ImlibImage * im, int y, edgeRec * pt1, edgeRec * pt2, + DATA8 r, DATA8 g, DATA8 b, DATA8 a, ImlibOp op); void __imlib_FlipImageHoriz(ImlibImage * im) @@ -1540,7 +1541,7 @@ __imlib_draw_line_clipped(ImlibImage * im, int x1, int y1, int x2, int y2, int cx0, cx1, cy0, cy1; if (imlib_clip_line - (x1, y1, x2, y2, clip_xmin, clip_xmax, clip_ymin, clip_ymax, &cx0, + (x1, y1, x2, y2, clip_xmin, clip_xmax - 1, clip_ymin, clip_ymax, &cx0, &cy0, &cx1, &cy1)) { return __imlib_draw_line(im, cx0, cy0, cx1, cy1, r, g, b, a, op, @@ -1790,20 +1791,22 @@ __imlib_draw_ellipse(ImlibImage * im, int xc, int yc, int aa, int bb, DATA8 r, void __imlib_fill_ellipse(ImlibImage * im, int xc, int yc, int aa, int bb, - int clip_xmin, int clip_xmax, int clip_ymin, - int clip_ymax, DATA8 r, DATA8 g, DATA8 b, - DATA8 a, ImlibOp op) + int clip_xmin, int clip_xmax, int clip_ymin, + int clip_ymax, DATA8 r, DATA8 g, DATA8 b, DATA8 a, + ImlibOp op, unsigned char antialias) { int a2 = aa * aa; int b2 = bb * bb; - int i; - int x, y, dec; + int y; + int x, dec; int miny, maxy, iy1; edgeRec *table1, *table2; - table1 = malloc(sizeof(edgeRec) * im->h); - table2 = malloc(sizeof(edgeRec) * im->h); + table1 = malloc(sizeof(edgeRec) * (im->h + 1)); + table2 = malloc(sizeof(edgeRec) * (im->h + 1)); + memset(table1, 0, sizeof(edgeRec) * (im->h + 1)); + memset(table2, 0, sizeof(edgeRec) * (im->h + 1)); miny = yc - bb; maxy = yc + bb; @@ -1817,8 +1820,8 @@ __imlib_fill_ellipse(ImlibImage * im, int xc, int yc, int aa, int bb, table1[yc + y].x = xc - x; table2[yc + y].x = xc + x; - if (dec >= 0) - dec += 4 * a2 * (1 - (y--)); + if (dec >= 0.0) + dec += 4.0 * a2 * (1 - (y--)); dec += b2 * (4 * x + 6); } @@ -1837,19 +1840,32 @@ __imlib_fill_ellipse(ImlibImage * im, int xc, int yc, int aa, int bb, } /* clip spans to screen */ - __spanlist_clip(table1, table2, &miny, &maxy, 0, im->w, 0, im->h); + __spanlist_clip(table1, table2, &miny, &maxy, 0, im->w - 1, 0, im->h); /* clip to clip rect if it's there */ if (clip_xmin != clip_xmax) __spanlist_clip(table1, table2, &miny, &maxy, clip_xmin, clip_xmax, clip_ymin, clip_ymax); - do + if (antialias) { - span(im, miny, &table1[miny], &table2[miny], r, g, b, a, op); - miny++; + do + { + spanAA(im, miny, table1, table2, r, g, b, a, op); + miny++; + } + while (miny <= maxy); + } + else + { + + do + { + span(im, miny, &table1[miny], &table2[miny], r, g, b, a, op); + miny++; + } + while (miny <= maxy); } - while (miny < maxy); free(table1); free(table2); } @@ -1904,7 +1920,7 @@ __imlib_draw_ellipse_clipped(ImlibImage * im, int xc, int yc, int aa, int bb, static void edge(edgeRec * table, ImlibPoint * pt1, ImlibPoint * pt2) { - long x, dx; + double x, dx; int idy, iy1, iy2; if (pt2->y < pt1->y) @@ -1916,14 +1932,14 @@ edge(edgeRec * table, ImlibPoint * pt1, ImlibPoint * pt2) return; idy = MAX(2, idy - 1); x = pt1->x; - dx = (pt2->x - pt1->x) / idy; + dx = (pt2->x - pt1->x) / (double) idy; do { table[iy1].x = x; x += dx; iy1++; } - while (iy1 < iy2); + while (iy1 <= iy2); } static void @@ -1938,56 +1954,353 @@ span(ImlibImage * im, int y, edgeRec * pt1, edgeRec * pt2, DATA8 r, DATA8 g, ix2 = pt2->x; if (ix1 == ix2) return; - + p = &(im->data[(im->w * y) + ix1]); switch (op) - { - /* unrolled loop - on loop inside each render mode per span */ + { + /* unrolled loop - on loop inside each render mode per span */ case OP_RESHADE: - do - { - BLEND_RE(r, g, b, a, p); - p++; - ix1++; - } - while (ix1 < ix2); - break; + do + { + BLEND_RE(r, g, b, a, p); + p++; + ix1++; + } + while (ix1 <= ix2); + break; case OP_SUBTRACT: - do - { - BLEND_SUB(r, g, b, a, p); - p++; - ix1++; - } - while (ix1 < ix2); - break; + do + { + BLEND_SUB(r, g, b, a, p); + p++; + ix1++; + } + while (ix1 <= ix2); + break; case OP_ADD: - do - { - BLEND_ADD(r, g, b, a, p); - p++; - ix1++; - } - while (ix1 < ix2); - break; + do + { + BLEND_ADD(r, g, b, a, p); + p++; + ix1++; + } + while (ix1 <= ix2); + break; case OP_COPY: - do - { - BLEND(r, g, b, a, p); - p++; - ix1++; - } - while (ix1 < ix2); - break; + do + { + BLEND(r, g, b, a, p); + p++; + ix1++; + } + while (ix1 <= ix2); + break; default: - break; - } + break; + } + +} + +static void +spanAA(ImlibImage * im, int y, edgeRec * pt1, edgeRec * pt2, DATA8 r, DATA8 g, + DATA8 b, DATA8 a, ImlibOp op) +{ + int x1, x2; + DATA32 *p; + int tmp; + + double upramp_gradient = 0.0, downramp_gradient = 0.0; + int upramp_len = 0, downramp_len = 0; + int upramp_len1 = 0, downramp_len1 = 0; + int ux1, ux2, top = 0, bottom = 0; + + x1 = pt1[y].x; + x2 = pt2[y].x; + if (x1 == x2) + return; + + /* see if there is a line above this one */ + if ((y > 0) && (pt1[y - 1].x != pt2[y - 1].x)) + { + if (pt1[y - 1].x > pt1[y].x) + { + upramp_len = pt1[y - 1].x - pt1[y].x; + upramp_gradient = 1.0 / (pt1[y - 1].x - pt1[y].x); + } + if (pt2[y].x > pt2[y - 1].x) + { + downramp_len = pt2[y].x - pt2[y - 1].x; + downramp_gradient = 1.0 / (pt2[y - 1].x - pt2[y].x); + } + } + else + { + /* there isn't - this is a special case for the top of a shape */ + top = 1; + } + + /* see if there is a line below this one */ + if ((pt1[y + 1].x != pt2[y + 1].x)) + { + if (pt1[y + 1].x > pt1[y].x) + { + upramp_len1 = pt1[y + 1].x - pt1[y].x; + if (upramp_gradient != 0.0) + upramp_gradient = 1.0 / (pt1[y].x - pt1[y + 1].x); + } + if (pt2[y].x > pt2[y + 1].x) + { + downramp_len1 = pt2[y].x - pt2[y + 1].x; + if (downramp_gradient != 0.0) + downramp_gradient = 1.0 / (pt2[y].x - pt2[y + 1].x); + } + } + else + { + /* there isn't - this is a special case for the bottom of a shape */ + bottom = 1; + } + + upramp_len = MAX(upramp_len, upramp_len1); + downramp_len = MAX(downramp_len, downramp_len1); + + if (top && !upramp_len && !downramp_len) + { + if ((pt1[y + 1].x != pt2[y + 1].x)) + { + if (pt1[y + 1].x < pt1[y].x) + { + upramp_len = pt1[y].x - pt1[y + 1].x; + upramp_gradient = 1.0 / (pt1[y + 1].x - pt1[y].x); + } + if (pt2[y].x < pt2[y + 1].x) + { + downramp_len = pt2[y + 1].x - pt2[y].x; + downramp_gradient = 1.0 / (pt2[y + 1].x - pt2[y].x); + } + } + } + + if (bottom && !upramp_len && !downramp_len) + { + if ((pt1[y - 1].x != pt2[y - 1].x)) + { + if (pt1[y - 1].x < pt1[y].x) + { + upramp_len = pt1[y].x - pt1[y - 1].x; + upramp_gradient = 1.0 / (pt1[y - 1].x - pt1[y].x); + } + if (pt2[y].x < pt2[y - 1].x) + { + downramp_len = pt2[y - 1].x - pt2[y].x; + downramp_gradient = 1.0 / (pt2[y - 1].x - pt2[y].x); + } + } + } + + if (upramp_len > 0) + { + /* need to do an upramp */ + if (upramp_gradient >= 1.0 || upramp_gradient <= -1.0) + { + /* it's mostly vertical */ + double aa, x; + DATA8 alpha; + + x = pt1[y].x; + aa = x - (double) ((int) x); + alpha = (1.0 - aa) * a; + p = &(im->data[(im->w * y) + (int) x]); + switch (op) + { + case OP_RESHADE: + BLEND_RE(r, g, b, alpha, p); + break; + case OP_SUBTRACT: + BLEND_SUB(r, g, b, alpha, p); + break; + case OP_ADD: + BLEND_ADD(r, g, b, alpha, p); + break; + case OP_COPY: + BLEND(r, g, b, alpha, p); + break; + default: + break; + } + /* the final span start is shifted right */ + x1 += 2; + } + else + { + /* it's mostly horizontal */ + int da; /* change in alpha per pixel */ + DATA8 alpha; + + if (upramp_len == 1) + da = a / 2; + else + da = a / (upramp_len); + alpha = da; + /* draw the upramp */ + for (ux1 = pt1[y].x; ux1 <= (pt1[y].x + upramp_len); ux1++) + { + p = &(im->data[(im->w * y) + ux1]); + switch (op) + { + case OP_RESHADE: + BLEND_RE(r, g, b, alpha, p); + break; + case OP_SUBTRACT: + BLEND_SUB(r, g, b, alpha, p); + break; + case OP_ADD: + BLEND_ADD(r, g, b, alpha, p); + break; + case OP_COPY: + BLEND(r, g, b, alpha, p); + break; + default: + break; + } + if (alpha + da > 255) + alpha = 255; + else + alpha += da; + } + /* the final span start is shifted */ + x1 += upramp_len + 1; + } + } + + if (downramp_len > 0) + { + /* need to do a downramp */ + if (downramp_gradient <= -1.0 || downramp_gradient >= 1.0) + { + /* it's mostly vertical */ + double aa, x; + DATA8 alpha; + + x = pt2[y].x; + aa = x - (double) ((int) x); + alpha = (1.0 - aa) * a; + p = &(im->data[(im->w * y) + (int) x]); + switch (op) + { + case OP_RESHADE: + BLEND_RE(r, g, b, alpha, p); + break; + case OP_SUBTRACT: + BLEND_SUB(r, g, b, alpha, p); + break; + case OP_ADD: + BLEND_ADD(r, g, b, alpha, p); + break; + case OP_COPY: + BLEND(r, g, b, alpha, p); + break; + default: + break; + } + /* the final span is shorter */ + x2 -= 2; + } + else + { + /* it's mostly horizontal */ + int da; /* change in alpha per pixel */ + DATA8 alpha; + + if (downramp_len == 1) + da = a / 2; + else + da = a / (downramp_len); + alpha = a; + /* draw the downramp (note: we are drawing right to left) */ + for (ux1 = pt2[y].x - downramp_len; ux1 <= pt2[y].x; ux1++) + { + p = &(im->data[(im->w * y) + ux1]); + switch (op) + { + case OP_RESHADE: + BLEND_RE(r, g, b, alpha, p); + break; + case OP_SUBTRACT: + BLEND_SUB(r, g, b, alpha, p); + break; + case OP_ADD: + BLEND_ADD(r, g, b, alpha, p); + break; + case OP_COPY: + BLEND(r, g, b, alpha, p); + break; + default: + break; + } + if (alpha < da) + alpha = 0; + else + alpha -= da; + } + /* the final span is shorter */ + x2 -= downramp_len + 1; + } + } + if (x1 == x2) + return; + + /* just fill the remaining span */ + p = &(im->data[(im->w * y) + x1]); + switch (op) + { + /* unrolled loop - on loop inside each render mode per span */ + case OP_RESHADE: + do + { + BLEND_RE(r, g, b, a, p); + p++; + x1++; + } + while (x1 <= x2); + break; + case OP_SUBTRACT: + do + { + BLEND_SUB(r, g, b, a, p); + p++; + x1++; + } + while (x1 <= x2); + break; + case OP_ADD: + do + { + BLEND_ADD(r, g, b, a, p); + p++; + x1++; + } + while (x1 <= x2); + break; + case OP_COPY: + do + { + BLEND(r, g, b, a, p); + p++; + x1++; + } + while (x1 <= x2); + break; + default: + break; + } } void __imlib_draw_polygon_filled(ImlibImage * im, ImlibPoly poly, int clip_xmin, int clip_xmax, int clip_ymin, int clip_ymax, - DATA8 r, DATA8 g, DATA8 b, DATA8 a, ImlibOp op) + DATA8 r, DATA8 g, DATA8 b, DATA8 a, ImlibOp op, + unsigned char antialias) { long maxy, miny; int iy1, iy2; @@ -2001,8 +2314,12 @@ __imlib_draw_polygon_filled(ImlibImage * im, ImlibPoly poly, int clip_xmin, return; } - table1 = malloc(sizeof(edgeRec) * im->h); - table2 = malloc(sizeof(edgeRec) * im->h); + /* one bigger than needed so the clipping code doesn't need to be told the + * max y */ + table1 = malloc(sizeof(edgeRec) * (im->h + 1)); + table2 = malloc(sizeof(edgeRec) * (im->h + 1)); + memset(table1, 0, sizeof(edgeRec) * (im->h + 1)); + memset(table2, 0, sizeof(edgeRec) * (im->h + 1)); maxy = miny = poly->points[0].y; imaxy = iminy = 0; @@ -2061,20 +2378,32 @@ __imlib_draw_polygon_filled(ImlibImage * im, ImlibPoly poly, int clip_xmin, while (pnt1 != iminy); /* clip spans to screen */ - __spanlist_clip(table1, table2, &iy1, &iy2, 0, im->w, 0, im->h); + __spanlist_clip(table1, table2, &iy1, &iy2, 0, im->w - 1, 0, im->h); /* clip to clip rect if it's there */ if (clip_xmin != clip_xmax) __spanlist_clip(table1, table2, &iy1, &iy2, clip_xmin, clip_xmax, clip_ymin, clip_ymax); - do + /* fill spans */ + if (antialias) { - /* fill spans */ - span(im, iy1, &table1[iy1], &table2[iy1], r, g, b, a, op); - iy1++; + do + { + spanAA(im, iy1, table1, table2, r, g, b, a, op); + iy1++; + } + while (iy1 <= iy2); + } + else + { + do + { + span(im, iy1, &table1[iy1], &table2[iy1], r, g, b, a, op); + iy1++; + } + while (iy1 <= iy2); } - while (iy1 < iy2); free(table1); free(table2); @@ -2098,12 +2427,13 @@ __spanlist_clip(edgeRec * table1, edgeRec * table2, int *sy, int *ey, pt2 = &(table2)[iy1]; if (pt2->x < pt1->x) - SWAP(pt2->x, pt1->x); + exchange(double, pt2->x, pt1->x); + pt1->x = MAX(pt1->x, xmin); pt2->x = MIN(pt2->x, xmax); iy1++; } - while (iy1 < iy2); + while (iy1 <= iy2); } unsigned char diff --git a/src/rgbadraw.h b/src/rgbadraw.h index 1d100fa..3d14c7b 100644 --- a/src/rgbadraw.h +++ b/src/rgbadraw.h @@ -29,8 +29,6 @@ #define __imlib_point_inside_segment(p_x, p_y, s1_x, s1_y, s2_x,s2_y) \ (s1_y != s2_y) ? (p_y <= MAX(s1_y, s2_y) && p_y >= MIN(s1_y, s2_y)) : (p_x <= MAX(s1_x, s2_x) && p_x >= MIN(s1_x, s2_x)) -#define SWAP(a,b) {int _tmp_; _tmp_ = a; a = b; b = _tmp_;} - #define __imlib_point_on_segment(p_x, p_y, s1_x, s1_y, s2_x, s2_y) \ __imlib_segments_intersect(p_x, p_y, p_x, p_y, s1_x, s1_y, s2_x, s2_y) @@ -91,7 +89,7 @@ __imlib_segments_intersect(p_x, p_y, p_x, p_y, s1_x, s1_y, s2_x, s2_y) typedef struct _edgerec { - int x; + double x; } edgeRec; @@ -185,11 +183,11 @@ void __imlib_draw_ellipse_clipped(ImlibImage * im, int xc, int yc, int aa, void __imlib_draw_polygon_filled(ImlibImage * im, ImlibPoly poly, int clip_xmin, int clip_xmax, int clip_ymin, int clip_ymax, DATA8 r, DATA8 g, DATA8 b, - DATA8 a, ImlibOp op); + DATA8 a, ImlibOp op, unsigned char antialias); void __imlib_fill_ellipse(ImlibImage * im, int xc, int yc, int aa, int bb, int clip_xmin, int clip_xmax, int clip_ymin, int clip_ymax, DATA8 r, DATA8 g, DATA8 b, DATA8 a, - ImlibOp op); + ImlibOp op, unsigned char antialias); unsigned char __imlib_polygon_contains_point(ImlibPoly poly, int x, int y); unsigned char __imlib_segments_intersect(int r1_x, int r1_y, int r2_x, int r2_y, int s1_x, int s1_y, diff --git a/test/main.c b/test/main.c index 10ed054..bfb04d4 100644 --- a/test/main.c +++ b/test/main.c @@ -310,6 +310,7 @@ int main (int argc, char **argv) imlib_polygon_add_point(poly3, 450,300); imlib_polygon_add_point(poly3, 350,300); + if (loop) { printf("loop\n"); @@ -774,12 +775,12 @@ int main (int argc, char **argv) { Imlib_Updates uu; + imlib_context_set_cliprect(0,0,0,0); imlib_context_set_color(255, 255, 255, 255); uu = imlib_image_draw_line(200, 200, x, y, 1); up = imlib_updates_append_updates(up, uu); /* test ellipses */ - imlib_context_set_cliprect(0,0,0,0); imlib_context_set_color(255, 255, 255, 255); imlib_image_draw_ellipse(50,250,30,40); imlib_image_fill_ellipse(50,300,30,40); @@ -847,7 +848,7 @@ int main (int argc, char **argv) up = imlib_update_append_rect(up, 30,120,50,50); imlib_context_set_cliprect(0,0,0,0); - + /* test polygons */ imlib_context_set_color(255, 0, 0, 128); imlib_image_fill_polygon(poly);