diff --git a/ChangeLog b/ChangeLog index 6e685b535..cff7534a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,77 @@ +2005-08-08 Billy Biggs + + reviewed by: cworth, otaylor + + * src/cairo.c: (cairo_set_antialias), (cairo_get_antialias): + * src/cairo.h: Add a new API for disabling antialiasing of shapes + drawn by cairo. This is a hint and is not supported by all backends. + + * src/cairoint.h: + * src/cairo-gstate-private.h: + * src/cairo-gstate.c: (_cairo_gstate_init), + (_composite_traps_draw_func), + (_cairo_surface_clip_and_composite_trapezoids), + (_cairo_gstate_clip_and_composite_trapezoids), + (_cairo_gstate_clip), (_cairo_gstate_set_antialias), + (_cairo_gstate_get_antialias): Store the antialiasing mode in the + gstate and pass it to the backend for trapezoid rendering and for + clipping. + + * src/cairo-clip-private.h: + * src/cairo-clip.c: (_cairo_clip_intersect_path), + (_cairo_clip_intersect_mask), (_cairo_clip_clip): Pass the + antialiasing parameter down to the backend where appropriate. + + * src/cairo-surface.c: (_fallback_composite_trapezoids), + (_cairo_surface_composite_trapezoids), (_cairo_surface_reset_clip), + (_cairo_surface_intersect_clip_path), + (_cairo_surface_set_clip_path_recursive), + (_cairo_surface_set_clip_path): Pass the antialiasing parameter down + to the backend where appropriate. + + * src/cairo-image-surface.c: + (_cairo_image_surface_composite_trapezoids): Add support for A1 format + trapezoid rendering, and remove the _create_mask_image function, + creating a temporary image from memory we allocate and clear. + + * src/cairo-xcb-surface.c: + (_cairo_xcb_surface_composite_trapezoids): Support A1 masks to disable + antialiasing using the RENDER extension when requested. + + * src/cairo-xlib-surface.c: (_create_trapezoid_mask), + (_cairo_xlib_surface_composite_trapezoids): Support A1 masks to disable + antialiasing using the RENDER extension when requested. + + * src/cairo-meta-surface-private.h: + * src/cairo-meta-surface.c: + (_cairo_meta_surface_composite_trapezoids), + (_cairo_meta_surface_intersect_clip_path), + (_cairo_meta_surface_replay): Blindly pass through the antialising + parameter. + + * src/cairo-glitz-surface.c: + (_cairo_glitz_surface_composite_trapezoids): + * src/cairo-pdf-surface.c: + (_cairo_pdf_surface_composite_trapezoids), + (_cairo_pdf_surface_intersect_clip_path): + * src/cairo-ps-surface.c: (_cairo_ps_surface_composite_trapezoids), + (_cairo_ps_surface_intersect_clip_path), + (_ps_output_composite_trapezoids), + (_ps_output_intersect_clip_path): Add the antialiasing parameter but + don't support it. + + * test/Makefile.am: + * test/unantialiased-shapes-ref.png: + * test/unantialiased-shapes.c: (big_star_path), (draw), (main): + Add a test case and a reference image from the latest libpixman. + + * doc/public/tmpl/cairo-font.sgml: + * doc/public/tmpl/cairo.sgml: + * doc/public/cairo-sections.txt: Add the new antialiasing disabling API to + the docs. + + * TODO: Update progress on a parameter to disable antialiasing. + 2005-08-08 Carl Worth * test/.cvsignore: Ignore clip-operator and unbounded-operator. diff --git a/TODO b/TODO index bb04c887f..7a8e1641d 100644 --- a/TODO +++ b/TODO @@ -11,7 +11,7 @@ Backwards compatible (API additions only) ----------------------------------------- cairo_begin_group, cairo_end_group, cairo_get_group PDR C cairo_surface_mark_dirty (see below for details) -PDR Add support for non-antialiased rendering. API ? +PDRTC Add support for non-antialiased rendering + API Add CAIRO_FILL_RULE_INVERSE_WINDING and CAIRO_FILL_RULE_INVERSE_EVEN_ODD Add cairo_text_glyphs (see below for details) Add support for programmatic patterns, (ie. arbitrary gradients) diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt index 1c0edccbc..a27a2945b 100644 --- a/doc/public/cairo-sections.txt +++ b/doc/public/cairo-sections.txt @@ -169,7 +169,6 @@ cairo_font_options_status cairo_font_options_merge cairo_font_options_hash cairo_font_options_equal -cairo_antialias_t cairo_font_options_set_antialias cairo_font_options_get_antialias cairo_subpixel_order_t @@ -203,6 +202,8 @@ cairo_set_source_rgba cairo_set_source cairo_set_source_surface cairo_set_tolerance +cairo_antialias_t +cairo_set_antialias cairo_fill_rule_t cairo_set_fill_rule cairo_set_line_width @@ -272,6 +273,7 @@ cairo_glyph_path cairo_get_operator cairo_get_source cairo_get_tolerance +cairo_get_antialias cairo_get_current_point cairo_get_fill_rule cairo_get_line_width diff --git a/doc/public/tmpl/cairo-font.sgml b/doc/public/tmpl/cairo-font.sgml index 6fd8e163a..78c9d3bfd 100644 --- a/doc/public/tmpl/cairo-font.sgml +++ b/doc/public/tmpl/cairo-font.sgml @@ -228,16 +228,6 @@ Font Handling @Returns: - - - - - -@CAIRO_ANTIALIAS_DEFAULT: -@CAIRO_ANTIALIAS_NONE: -@CAIRO_ANTIALIAS_GRAY: -@CAIRO_ANTIALIAS_SUBPIXEL: - diff --git a/doc/public/tmpl/cairo.sgml b/doc/public/tmpl/cairo.sgml index 8b29acc74..3f2ec8d6c 100644 --- a/doc/public/tmpl/cairo.sgml +++ b/doc/public/tmpl/cairo.sgml @@ -191,6 +191,25 @@ Drawing contexts. @tolerance: + + + + + +@CAIRO_ANTIALIAS_DEFAULT: +@CAIRO_ANTIALIAS_NONE: +@CAIRO_ANTIALIAS_GRAY: +@CAIRO_ANTIALIAS_SUBPIXEL: + + + + + + +@cr: +@antialias: + + @@ -846,6 +865,15 @@ Drawing contexts. @Returns: + + + + + +@cr: +@Returns: + + diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h index a56f57983..23eb78c90 100644 --- a/src/cairo-clip-private.h +++ b/src/cairo-clip-private.h @@ -49,6 +49,7 @@ struct _cairo_clip_path { cairo_path_fixed_t path; cairo_fill_rule_t fill_rule; double tolerance; + cairo_antialias_t antialias; cairo_clip_path_t *prev; }; @@ -100,6 +101,7 @@ _cairo_clip_clip (cairo_clip_t *clip, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, + cairo_antialias_t antialias, cairo_surface_t *target); cairo_private cairo_status_t diff --git a/src/cairo-clip.c b/src/cairo-clip.c index a4b8d5332..d479da8fc 100644 --- a/src/cairo-clip.c +++ b/src/cairo-clip.c @@ -246,6 +246,7 @@ _cairo_clip_intersect_path (cairo_clip_t *clip, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, + cairo_antialias_t antialias, cairo_surface_t *target) { cairo_clip_path_t *clip_path; @@ -265,6 +266,7 @@ _cairo_clip_intersect_path (cairo_clip_t *clip, clip_path->ref_count = 1; clip_path->fill_rule = fill_rule; clip_path->tolerance = tolerance; + clip_path->antialias = antialias; clip_path->prev = clip->path; clip->path = clip_path; clip->serial = _cairo_surface_allocate_clip_serial (target); @@ -339,9 +341,10 @@ _cairo_clip_intersect_region (cairo_clip_t *clip, } static cairo_status_t -_cairo_clip_intersect_mask (cairo_clip_t *clip, - cairo_traps_t *traps, - cairo_surface_t *target) +_cairo_clip_intersect_mask (cairo_clip_t *clip, + cairo_traps_t *traps, + cairo_antialias_t antialias, + cairo_surface_t *target) { cairo_pattern_union_t pattern; cairo_box_t extents; @@ -375,6 +378,7 @@ _cairo_clip_intersect_mask (cairo_clip_t *clip, status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN, &pattern.base, surface, + antialias, 0, 0, 0, 0, surface_rect.width, @@ -429,6 +433,7 @@ _cairo_clip_clip (cairo_clip_t *clip, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, + cairo_antialias_t antialias, cairo_surface_t *target) { cairo_status_t status; @@ -436,7 +441,7 @@ _cairo_clip_clip (cairo_clip_t *clip, status = _cairo_clip_intersect_path (clip, path, fill_rule, tolerance, - target); + antialias, target); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; @@ -452,7 +457,7 @@ _cairo_clip_clip (cairo_clip_t *clip, if (status != CAIRO_INT_STATUS_UNSUPPORTED) goto bail; - status = _cairo_clip_intersect_mask (clip, &traps, target); + status = _cairo_clip_intersect_mask (clip, &traps, antialias, target); bail: _cairo_traps_fini (&traps); diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c index 402b34f15..7e0f33876 100644 --- a/src/cairo-glitz-surface.c +++ b/src/cairo-glitz-surface.c @@ -936,6 +936,7 @@ static cairo_int_status_t _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, cairo_pattern_t *pattern, void *abstract_dst, + cairo_antialias_t antialias, int src_x, int src_y, int dst_x, diff --git a/src/cairo-gstate-private.h b/src/cairo-gstate-private.h index 7e82883d3..489afdba4 100644 --- a/src/cairo-gstate-private.h +++ b/src/cairo-gstate-private.h @@ -42,6 +42,7 @@ struct _cairo_gstate { cairo_operator_t operator; double tolerance; + cairo_antialias_t antialias; /* stroke style */ double line_width; diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index e63f29f6f..a657f15e5 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -92,6 +92,7 @@ _cairo_gstate_init (cairo_gstate_t *gstate, gstate->operator = CAIRO_GSTATE_OPERATOR_DEFAULT; gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT; + gstate->antialias = CAIRO_ANTIALIAS_DEFAULT; gstate->line_width = CAIRO_GSTATE_LINE_WIDTH_DEFAULT; gstate->line_cap = CAIRO_GSTATE_LINE_CAP_DEFAULT; @@ -1234,6 +1235,11 @@ _composite_trap_region_solid (cairo_clip_t *clip, return status; } +typedef struct { + cairo_traps_t *traps; + cairo_antialias_t antialias; +} cairo_composite_traps_info_t; + static cairo_status_t _composite_traps_draw_func (void *closure, cairo_operator_t operator, @@ -1243,24 +1249,24 @@ _composite_traps_draw_func (void *closure, int dst_y, const cairo_rectangle_t *extents) { - cairo_traps_t *traps = closure; + cairo_composite_traps_info_t *info = closure; cairo_pattern_union_t pattern; cairo_status_t status; if (dst_x != 0 || dst_y != 0) - _cairo_traps_translate (traps, - dst_x, - dst_y); + _cairo_traps_translate (info->traps, - dst_x, - dst_y); _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE); if (!src) src = &pattern.base; status = _cairo_surface_composite_trapezoids (operator, - src, dst, + src, dst, info->antialias, extents->x, extents->y, extents->x - dst_x, extents->y - dst_y, extents->width, extents->height, - traps->traps, - traps->num_traps); + info->traps->traps, + info->traps->num_traps); _cairo_pattern_fini (&pattern.base); return status; @@ -1285,11 +1291,13 @@ _cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src, cairo_operator_t operator, cairo_surface_t *dst, cairo_traps_t *traps, - cairo_clip_t *clip) + cairo_clip_t *clip, + cairo_antialias_t antialias) { cairo_status_t status; pixman_region16_t *trap_region; cairo_rectangle_t extents; + cairo_composite_traps_info_t traps_info; if (traps->num_traps == 0) return CAIRO_STATUS_SUCCESS; @@ -1350,10 +1358,12 @@ _cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src, goto out; } + traps_info.traps = traps; + traps_info.antialias = antialias; + status = _cairo_gstate_clip_and_composite (clip, operator, src, - _composite_traps_draw_func, traps, - dst, - &extents); + _composite_traps_draw_func, &traps_info, + dst, &extents); out: if (trap_region) @@ -1376,7 +1386,8 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate, gstate->operator, gstate->target, traps, - &gstate->clip); + &gstate->clip, + gstate->antialias); _cairo_pattern_fini (&pattern.base); @@ -1545,7 +1556,7 @@ _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path) { return _cairo_clip_clip (&gstate->clip, path, gstate->fill_rule, gstate->tolerance, - gstate->target); + gstate->antialias, gstate->target); } static void @@ -2005,3 +2016,19 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate, free (transformed_glyphs); return status; } + +cairo_private cairo_status_t +_cairo_gstate_set_antialias (cairo_gstate_t *gstate, + cairo_antialias_t antialias) +{ + gstate->antialias = antialias; + + return CAIRO_STATUS_SUCCESS; +} + +cairo_private cairo_antialias_t +_cairo_gstate_get_antialias (cairo_gstate_t *gstate) +{ + return gstate->antialias; +} + diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 7c284b467..f7dbc8cfe 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -655,34 +655,6 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface, return CAIRO_STATUS_SUCCESS; } -static pixman_image_t * -_create_mask_image (int width, - int height) -{ - pixman_image_t *image; - pixman_color_t pixman_color = { 0, 0, 0, 0 }; /* transparent */ - pixman_rectangle_t rect; - pixman_format_t *format; - - format = pixman_format_create (PIXMAN_FORMAT_NAME_A8); - if (!format) - return NULL; - - image = pixman_image_create (format, width, height); - if (!image) - return NULL; - - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - - pixman_fill_rectangles (PIXMAN_OPERATOR_SRC, image, - &pixman_color, &rect, 1); - - return image; -} - static cairo_bool_t _cairo_image_surface_is_alpha_only (cairo_image_surface_t *surface) { @@ -701,6 +673,7 @@ static cairo_int_status_t _cairo_image_surface_composite_trapezoids (cairo_operator_t operator, cairo_pattern_t *pattern, void *abstract_dst, + cairo_antialias_t antialias, int src_x, int src_y, int dst_x, @@ -715,6 +688,10 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator, cairo_image_surface_t *src; cairo_int_status_t status; pixman_image_t *mask; + pixman_format_t *format; + pixman_bits_t *mask_data; + int mask_stride; + int mask_bpp; /* Special case adding trapezoids onto a mask surface; we want to avoid * creating an intermediate temporary mask unecessarily. @@ -732,7 +709,8 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator, if (operator == CAIRO_OPERATOR_ADD && _cairo_pattern_is_opaque_solid (pattern) && _cairo_image_surface_is_alpha_only (dst) && - !dst->has_clip) + !dst->has_clip && + antialias != CAIRO_ANTIALIAS_NONE) { pixman_add_trapezoids (dst->pixman_image, 0, 0, (pixman_trapezoid_t *) traps, num_traps); @@ -750,10 +728,37 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator, if (status) goto CLEANUP_SOURCE; - mask = _create_mask_image (width, height); + switch (antialias) { + case CAIRO_ANTIALIAS_NONE: + format = pixman_format_create (PIXMAN_FORMAT_NAME_A1); + mask_stride = (width + 31)/8; + mask_bpp = 1; + break; + default: + format = pixman_format_create (PIXMAN_FORMAT_NAME_A8); + mask_stride = (width + 3) & ~3; + mask_bpp = 8; + break; + } + if (!format) { + status = CAIRO_STATUS_NO_MEMORY; + goto CLEANUP_SOURCE; + } + + /* The image must be initially transparent */ + mask_data = calloc (1, mask_stride * height); + if (!mask_data) { + status = CAIRO_STATUS_NO_MEMORY; + pixman_format_destroy (format); + goto CLEANUP_SOURCE; + } + + mask = pixman_image_create_for_data (mask_data, format, width, height, + mask_bpp, mask_stride); + pixman_format_destroy (format); if (!mask) { status = CAIRO_STATUS_NO_MEMORY; - goto CLEANUP_MASK; + goto CLEANUP_IMAGE_DATA; } /* XXX: The pixman_trapezoid_t cast is evil and needs to go away @@ -771,9 +776,11 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator, dst_x, dst_y, width, height); - CLEANUP_MASK: pixman_image_destroy (mask); + CLEANUP_IMAGE_DATA: + free (mask_data); + CLEANUP_SOURCE: _cairo_pattern_release_surface (pattern, &src->base, &attributes); diff --git a/src/cairo-meta-surface-private.h b/src/cairo-meta-surface-private.h index 234c6ccfc..f37a89164 100644 --- a/src/cairo-meta-surface-private.h +++ b/src/cairo-meta-surface-private.h @@ -77,6 +77,7 @@ typedef struct _cairo_command_composite_trapezoids { cairo_command_type_t type; cairo_operator_t operator; cairo_pattern_union_t pattern; + cairo_antialias_t antialias; int x_src; int y_src; int x_dst; @@ -99,6 +100,7 @@ typedef struct _cairo_command_intersect_clip_path { cairo_path_fixed_t path; cairo_fill_rule_t fill_rule; double tolerance; + cairo_antialias_t antialias; } cairo_command_intersect_clip_path_t; typedef struct _cairo_command_show_glyphs { @@ -123,6 +125,7 @@ typedef struct _cairo_command_fill_path { cairo_path_fixed_t path; cairo_fill_rule_t fill_rule; double tolerance; + cairo_antialias_t antialias; } cairo_command_fill_path_t; typedef union _cairo_command { diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c index 3781fabc3..f218ae240 100644 --- a/src/cairo-meta-surface.c +++ b/src/cairo-meta-surface.c @@ -217,6 +217,7 @@ static cairo_int_status_t _cairo_meta_surface_composite_trapezoids (cairo_operator_t operator, cairo_pattern_t *pattern, void *abstract_surface, + cairo_antialias_t antialias, int x_src, int y_src, int x_dst, @@ -236,6 +237,7 @@ _cairo_meta_surface_composite_trapezoids (cairo_operator_t operator, command->type = CAIRO_COMMAND_COMPOSITE_TRAPEZOIDS; command->operator = operator; _cairo_pattern_init_copy (&command->pattern.base, pattern); + command->antialias = antialias; command->x_src = x_src; command->y_src = y_src; command->x_dst = x_dst; @@ -267,7 +269,8 @@ static cairo_int_status_t _cairo_meta_surface_intersect_clip_path (void *dst, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, - double tolerance) + double tolerance, + cairo_antialias_t antialias) { cairo_meta_surface_t *meta = dst; cairo_command_intersect_clip_path_t *command; @@ -291,6 +294,7 @@ _cairo_meta_surface_intersect_clip_path (void *dst, } command->fill_rule = fill_rule; command->tolerance = tolerance; + command->antialias = antialias; if (_cairo_array_append (&meta->commands, &command, 1) == NULL) { if (path) @@ -494,6 +498,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface, (command->composite_trapezoids.operator, &command->composite_trapezoids.pattern.base, target, + command->composite_trapezoids.antialias, command->composite_trapezoids.x_src, command->composite_trapezoids.y_src, command->composite_trapezoids.x_dst, @@ -514,6 +519,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface, command->intersect_clip_path.path_pointer, command->intersect_clip_path.fill_rule, command->intersect_clip_path.tolerance, + command->intersect_clip_path.antialias, target); break; @@ -566,7 +572,8 @@ _cairo_meta_surface_replay (cairo_surface_t *surface, command->fill_path.operator, target, &traps, - &clip); + &clip, + command->fill_path.antialias); _cairo_traps_fini (&traps); break; diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index c068c8aaf..6b863721e 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -1151,6 +1151,7 @@ static cairo_int_status_t _cairo_pdf_surface_composite_trapezoids (cairo_operator_t operator, cairo_pattern_t *pattern, void *abstract_dst, + cairo_antialias_t antialias, int x_src, int y_src, int x_dst, @@ -1334,7 +1335,8 @@ static cairo_int_status_t _cairo_pdf_surface_intersect_clip_path (void *dst, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, - double tolerance) + double tolerance, + cairo_antialias_t antialias) { cairo_pdf_surface_t *surface = dst; cairo_pdf_document_t *document = surface->document; diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 0b2962c28..a897ed0ef 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -272,6 +272,7 @@ static cairo_int_status_t _cairo_ps_surface_composite_trapezoids (cairo_operator_t operator, cairo_pattern_t *pattern, void *abstract_dst, + cairo_antialias_t antialias, int x_src, int y_src, int x_dst, @@ -286,6 +287,7 @@ _cairo_ps_surface_composite_trapezoids (cairo_operator_t operator, return _cairo_surface_composite_trapezoids (operator, pattern, surface->current_page, + antialias, x_src, y_src, x_dst, @@ -324,14 +326,16 @@ static cairo_int_status_t _cairo_ps_surface_intersect_clip_path (void *dst, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, - double tolerance) + double tolerance, + cairo_antialias_t antialias) { cairo_ps_surface_t *surface = dst; return _cairo_surface_intersect_clip_path (surface->current_page, path, fill_rule, - tolerance); + tolerance, + antialias); } static cairo_int_status_t @@ -929,6 +933,7 @@ static cairo_int_status_t _ps_output_composite_trapezoids (cairo_operator_t operator, cairo_pattern_t *pattern, void *abstract_dst, + cairo_antialias_t antialias, int x_src, int y_src, int x_dst, @@ -1054,7 +1059,8 @@ static cairo_int_status_t _ps_output_intersect_clip_path (void *abstract_surface, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, - double tolerance) + double tolerance, + cairo_antialias_t antialias) { ps_output_surface_t *surface = abstract_surface; cairo_output_stream_t *stream = surface->parent->stream; diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 6c0c76919..8353d329a 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -991,6 +991,7 @@ static cairo_status_t _fallback_composite_trapezoids (cairo_operator_t operator, cairo_pattern_t *pattern, cairo_surface_t *dst, + cairo_antialias_t antialias, int src_x, int src_y, int dst_x, @@ -1043,6 +1044,7 @@ _fallback_composite_trapezoids (cairo_operator_t operator, state.image->base.backend->composite_trapezoids (operator, pattern, &state.image->base, + antialias, src_x, src_y, dst_x - state.image_rect.x, dst_y - state.image_rect.y, @@ -1060,6 +1062,7 @@ cairo_status_t _cairo_surface_composite_trapezoids (cairo_operator_t operator, cairo_pattern_t *pattern, cairo_surface_t *dst, + cairo_antialias_t antialias, int src_x, int src_y, int dst_x, @@ -1080,6 +1083,7 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator, if (dst->backend->composite_trapezoids) { status = dst->backend->composite_trapezoids (operator, pattern, dst, + antialias, src_x, src_y, dst_x, dst_y, width, height, @@ -1089,6 +1093,7 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator, } return _fallback_composite_trapezoids (operator, pattern, dst, + antialias, src_x, src_y, dst_x, dst_y, width, height, @@ -1191,7 +1196,8 @@ _cairo_surface_reset_clip (cairo_surface_t *surface) status = surface->backend->intersect_clip_path (surface, NULL, CAIRO_FILL_RULE_WINDING, - 0); + 0, + CAIRO_ANTIALIAS_DEFAULT); if (status) return status; } @@ -1237,7 +1243,8 @@ cairo_int_status_t _cairo_surface_intersect_clip_path (cairo_surface_t *surface, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, - double tolerance) + double tolerance, + cairo_antialias_t antialias) { if (surface->status) return surface->status; @@ -1250,7 +1257,8 @@ _cairo_surface_intersect_clip_path (cairo_surface_t *surface, return surface->backend->intersect_clip_path (surface, path, fill_rule, - tolerance); + tolerance, + antialias); } static cairo_status_t @@ -1269,7 +1277,8 @@ _cairo_surface_set_clip_path_recursive (cairo_surface_t *surface, return surface->backend->intersect_clip_path (surface, &clip_path->path, clip_path->fill_rule, - clip_path->tolerance); + clip_path->tolerance, + clip_path->antialias); } /** @@ -1299,7 +1308,8 @@ _cairo_surface_set_clip_path (cairo_surface_t *surface, status = surface->backend->intersect_clip_path (surface, NULL, CAIRO_FILL_RULE_WINDING, - 0); + 0, + CAIRO_ANTIALIAS_DEFAULT); if (status) return status; diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c index 05e39b55e..2a7395f6e 100644 --- a/src/cairo-xcb-surface.c +++ b/src/cairo-xcb-surface.c @@ -942,6 +942,7 @@ static cairo_int_status_t _cairo_xcb_surface_composite_trapezoids (cairo_operator_t operator, cairo_pattern_t *pattern, void *abstract_dst, + cairo_antialias_t antialias, int src_x, int src_y, int dst_x, @@ -980,9 +981,17 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t operator, render_src_x = src_x + render_reference_x - dst_x; render_src_y = src_y + render_reference_y - dst_y; + switch (antialias) { + case CAIRO_ANTIALIAS_NONE: + render_format = _format_from_cairo (dst->dpy, CAIRO_FORMAT_A1), + break; + default: + render_format = _format_from_cairo (dst->dpy, CAIRO_FORMAT_A8), + break; + } + /* XXX: The XTrapezoid cast is evil and needs to go away somehow. */ /* XXX: _format_from_cairo is slow. should cache something. */ - render_format = _format_from_cairo (dst->dpy, CAIRO_FORMAT_A8), status = _cairo_xcb_surface_set_attributes (src, &attributes); if (status == CAIRO_STATUS_SUCCESS) XCBRenderTrapezoids (dst->dpy, diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 9c87cc95d..7f4b84893 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -1266,8 +1266,8 @@ _create_trapezoid_mask (cairo_xlib_surface_t *dst, int dst_x, int dst_y, int width, - int height) - + int height, + XRenderPictFormat *pict_format) { XRenderColor transparent = { 0, 0, 0, 0 }; XRenderColor solid = { 0xffff, 0xffff, 0xffff, 0xffff }; @@ -1304,7 +1304,7 @@ _create_trapezoid_mask (cairo_xlib_surface_t *dst, XRenderCompositeTrapezoids (dst->dpy, PictOpAdd, solid_picture, mask_picture, - XRenderFindStandardFormat (dst->dpy, PictStandardA8), + pict_format, 0, 0, offset_traps, num_traps); @@ -1318,6 +1318,7 @@ static cairo_int_status_t _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator, cairo_pattern_t *pattern, void *abstract_dst, + cairo_antialias_t antialias, int src_x, int src_y, int dst_x, @@ -1334,6 +1335,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator, composite_operation_t operation; int render_reference_x, render_reference_y; int render_src_x, render_src_y; + XRenderPictFormat *pict_format; if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1354,6 +1356,15 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator, status = CAIRO_INT_STATUS_UNSUPPORTED; goto FAIL; } + + switch (antialias) { + case CAIRO_ANTIALIAS_NONE: + pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA1); + break; + default: + pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA8); + break; + } if (traps[0].left.p1.y < traps[0].left.p2.y) { render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x); @@ -1382,7 +1393,8 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator, * the mask somewhat cheaper.) */ Picture mask_picture = _create_trapezoid_mask (dst, traps, num_traps, - dst_x, dst_y, width, height); + dst_x, dst_y, width, height, + pict_format); if (!mask_picture) { status = CAIRO_STATUS_NO_MEMORY; goto FAIL; @@ -1406,7 +1418,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator, XRenderCompositeTrapezoids (dst->dpy, _render_operator (operator), src->src_picture, dst->dst_picture, - XRenderFindStandardFormat (dst->dpy, PictStandardA8), + pict_format, render_src_x + attributes.x_offset, render_src_y + attributes.y_offset, (XTrapezoid *) traps, num_traps); diff --git a/src/cairo.c b/src/cairo.c index 05c87a423..4c4b03ebe 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -535,6 +535,32 @@ cairo_set_tolerance (cairo_t *cr, double tolerance) _cairo_set_error (cr, cr->status); } +/** + * cairo_set_antialias: + * @cr: a #cairo_t + * @antialias: the new antialiasing mode + * + * Set the antialiasing mode of the rasterizer used for drawing shapes. + * This value is a hint, and a particular backend may or may not support + * a particular value. At the current time, no backend supports + * %CAIRO_ANTIALIAS_SUBPIXEL when drawing shapes. + * + * Note that this option does not affect text rendering, instead see + * cairo_font_options_set_antialias(). + **/ +void +cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias) +{ + if (cr->status) { + _cairo_set_error (cr, cr->status); + return; + } + + cr->status = _cairo_gstate_set_antialias (cr->gstate, antialias); + if (cr->status) + _cairo_set_error (cr, cr->status); +} + /** * cairo_set_fill_rule: * @cr: a #cairo_t @@ -2081,6 +2107,20 @@ cairo_get_tolerance (cairo_t *cr) return _cairo_gstate_get_tolerance (cr->gstate); } +/** + * cairo_get_antialias: + * @cr: a cairo context + * + * Gets the current shape antialiasing mode, as set by cairo_set_shape_antialias(). + * + * Return value: the current shape antialiasing mode. + **/ +cairo_antialias_t +cairo_get_antialias (cairo_t *cr) +{ + return _cairo_gstate_get_antialias (cr->gstate); +} + /** * cairo_get_current_point: * @cr: a cairo context diff --git a/src/cairo.h b/src/cairo.h index 41310be32..1d871c812 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -287,6 +287,29 @@ cairo_set_source_surface (cairo_t *cr, void cairo_set_tolerance (cairo_t *cr, double tolerance); +/** + * cairo_antialias_t: + * @CAIRO_ANTIALIAS_DEFAULT: Use the default antialiasing for + * the subsystem and target device + * @CAIRO_ANTIALIAS_NONE: Use a bilevel alpha mask + * @CAIRO_ANTIALIAS_GRAY: Perform single-color antialiasing (using + * shades of gray for black text on a white background, for example). + * @CAIRO_ANTIALIAS_SUBPIXEL: Perform antialiasing by taking + * advantage of the order of subpixel elements on devices + * such as LCD panels + * + * Specifies the type of antialiasing to do when rendering text or shapes. + **/ +typedef enum _cairo_antialias { + CAIRO_ANTIALIAS_DEFAULT, + CAIRO_ANTIALIAS_NONE, + CAIRO_ANTIALIAS_GRAY, + CAIRO_ANTIALIAS_SUBPIXEL +} cairo_antialias_t; + +void +cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias); + /** * cairo_fill_rule_t * @CAIRO_FILL_RULE_WINDING: If the path crosses the ray from @@ -659,26 +682,6 @@ typedef enum _cairo_font_weight { CAIRO_FONT_WEIGHT_BOLD } cairo_font_weight_t; -/** - * cairo_antialias_t: - * @CAIRO_ANTIALIAS_DEFAULT: Use the default antialiasing for - * the font subsystem and target device - * @CAIRO_ANTIALIAS_NONE: Do no antialiasing of fonts; use bilevel text - * @CAIRO_ANTIALIAS_GRAY: Perform single-color antialiasing (using - * shades of gray for black text on a white background, for example). - * @CAIRO_ANTIALIAS_SUBPIXEL: Perform antialiasing by taking - * advantage of the order of subpixel elements on devices - * such as LCD panels - * - * Specifies the type of antialiasing to do when rendering text. - **/ -typedef enum _cairo_antialias { - CAIRO_ANTIALIAS_DEFAULT, - CAIRO_ANTIALIAS_NONE, - CAIRO_ANTIALIAS_GRAY, - CAIRO_ANTIALIAS_SUBPIXEL -} cairo_antialias_t; - /** * cairo_subpixel_order_t: * @CAIRO_SUBPIXEL_ORDER_DEFAULT: Use the default subpixel order for @@ -920,6 +923,9 @@ cairo_get_source (cairo_t *cr); double cairo_get_tolerance (cairo_t *cr); +cairo_antialias_t +cairo_get_antialias (cairo_t *cr); + void cairo_get_current_point (cairo_t *cr, double *x, double *y); diff --git a/src/cairoint.h b/src/cairoint.h index b0a78784c..2a5f45e35 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -728,6 +728,7 @@ typedef struct _cairo_surface_backend { (*composite_trapezoids) (cairo_operator_t operator, cairo_pattern_t *pattern, void *dst, + cairo_antialias_t antialias, int src_x, int src_y, int dst_x, @@ -778,7 +779,8 @@ typedef struct _cairo_surface_backend { (*intersect_clip_path) (void *dst, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, - double tolerance); + double tolerance, + cairo_antialias_t antialias); /* Get the extents of the current surface. For many surface types * this will be as simple as { x=0, y=0, width=surface->width, @@ -1607,6 +1609,7 @@ cairo_private cairo_status_t _cairo_surface_composite_trapezoids (cairo_operator_t operator, cairo_pattern_t *pattern, cairo_surface_t *dst, + cairo_antialias_t antialias, int src_x, int src_y, int dst_x, @@ -1621,7 +1624,8 @@ _cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src, cairo_operator_t operator, cairo_surface_t *dst, cairo_traps_t *traps, - cairo_clip_t *clip); + cairo_clip_t *clip, + cairo_antialias_t antialias); cairo_private cairo_status_t _cairo_surface_copy_page (cairo_surface_t *surface); @@ -1676,7 +1680,8 @@ cairo_private cairo_int_status_t _cairo_surface_intersect_clip_path (cairo_surface_t *surface, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, - double tolerance); + double tolerance, + cairo_antialias_t antialias); cairo_private cairo_status_t _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip); @@ -1954,6 +1959,13 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src, cairo_surface_attributes_t *src_attributes, cairo_surface_attributes_t *mask_attributes); +cairo_private cairo_status_t +_cairo_gstate_set_antialias (cairo_gstate_t *gstate, + cairo_antialias_t antialias); + +cairo_private cairo_antialias_t +_cairo_gstate_get_antialias (cairo_gstate_t *gstate); + /* cairo_unicode.c */ diff --git a/test/Makefile.am b/test/Makefile.am index 29ccb8ecc..e30af427b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -42,6 +42,7 @@ text-rotate \ transforms \ translate-show-surface \ trap-clip \ +unantialiased-shapes \ unbounded-operator \ user-data \ rel-path @@ -99,6 +100,7 @@ text-antialias-none-ref.png \ transforms-ref.png \ translate-show-surface-ref.png \ trap-clip-ref.png \ +unantialiased-shapes-ref.png \ unbounded-operator-ref.png \ rel-path-ref.png @@ -200,6 +202,7 @@ text_rotate_LDADD = $(LDADDS) transforms_LDADD = $(LDADDS) translate_show_surface_LDADD = $(LDADDS) trap_clip_LDADD = $(LDADDS) +unantialiased_shapes_LDADD = $(LDADDS) unbounded_operator_LDADD = $(LDADDS) user_data_LDADD = $(LDADDS) rel_path_LDADD = $(LDADDS) diff --git a/test/unantialiased-shapes-ref.png b/test/unantialiased-shapes-ref.png new file mode 100644 index 000000000..b94859224 Binary files /dev/null and b/test/unantialiased-shapes-ref.png differ diff --git a/test/unantialiased-shapes.c b/test/unantialiased-shapes.c new file mode 100644 index 000000000..eaadf417a --- /dev/null +++ b/test/unantialiased-shapes.c @@ -0,0 +1,103 @@ +/* + * Copyright © 2005 Billy Biggs + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Billy Biggs not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Billy Biggs makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * BILLY BIGGS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL BILLY BIGGS BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Billy Biggs + */ + +#include "cairo-test.h" + +cairo_test_t test = { + "unantialiased-shapes", + "Test shape drawing without antialiasing", + 320, 240 +}; + +/* The star shape from the SVG test suite, from the fill rule test */ +static void +big_star_path (cairo_t *cr) +{ + cairo_move_to (cr, 40, 0); + cairo_rel_line_to (cr, 25, 80); + cairo_rel_line_to (cr, -65, -50); + cairo_rel_line_to (cr, 80, 0); + cairo_rel_line_to (cr, -65, 50); + cairo_close_path (cr); +} + +static cairo_test_status_t +draw (cairo_t *cr, int width, int height) +{ + int i; + + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_paint (cr); + + cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); + + /* Try a circle */ + cairo_arc (cr, 40, 40, 20, 0, 2 * M_PI); + cairo_set_source_rgb (cr, 1, 0, 0); + cairo_fill (cr); + + /* Try using clipping to draw a circle */ + cairo_arc (cr, 100, 40, 20, 0, 2 * M_PI); + cairo_clip (cr); + cairo_rectangle (cr, 80, 20, 40, 40); + cairo_set_source_rgb (cr, 0, 0, 1); + cairo_fill (cr); + + /* Reset the clipping */ + cairo_reset_clip (cr); + + /* Draw a bunch of lines */ + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgb (cr, 0, 1, 0); + for (i = 0; i < 10; i++) { + cairo_move_to (cr, 10, 70 + (i * 4)); + cairo_line_to (cr, 120, 70 + (i * 18)); + cairo_stroke (cr); + } + + /* Try filling a poly */ + cairo_translate (cr, 160, 120); + cairo_set_source_rgb (cr, 1, 1, 0); + big_star_path (cr); + cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); + cairo_fill (cr); + cairo_translate (cr, -160, -120); + + /* How about some curves? */ + cairo_set_source_rgb (cr, 1, 0, 1); + for (i = 0; i < 10; i++) { + cairo_move_to (cr, 150, 50 + (i * 5)); + cairo_curve_to (cr, 250, 50, 200, (i * 10), 300, 50 + (i * 10)); + cairo_stroke (cr); + } + + return CAIRO_TEST_SUCCESS; +} + +int +main (void) +{ + return cairo_test (&test, draw); +}