From 236c52b095661be395021d511d2dca0b532f83e9 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 6 Nov 2007 14:52:24 -0800 Subject: Handle overflow/underflow gracefully when converting to 16.16 fixed --- src/cairo-fixed-private.h | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/cairo-fixed-private.h b/src/cairo-fixed-private.h index 35b3748d..cb42ac13 100644 --- a/src/cairo-fixed-private.h +++ b/src/cairo-fixed-private.h @@ -51,7 +51,7 @@ typedef cairo_int128_t cairo_fixed_96_32_t; /* Eventually, we should allow changing this, but I think * there are some assumptions in the tesselator about the - * size of a fixed type. + * size of a fixed type. For now, it must be 32. */ #define CAIRO_FIXED_BITS 32 @@ -206,10 +206,26 @@ _cairo_fixed_integer_ceil (cairo_fixed_t f) static inline cairo_fixed_16_16_t _cairo_fixed_to_16_16 (cairo_fixed_t f) { -#if CAIRO_FIXED_FRAC_BITS > 16 +#if (CAIRO_FIXED_FRAC_BITS == 16) && (CAIRO_FIXED_BITS == 32) + return f; +#elif CAIRO_FIXED_FRAC_BITS > 16 + /* We're just dropping the low bits, so we won't ever got over/underflow here */ return f >> (CAIRO_FIXED_FRAC_BITS - 16); #else - return f << (16 - CAIRO_FIXED_FRAC_BITS); + cairo_fixed_16_16_t x; + + /* Handle overflow/underflow by claping to the lowest/highest + * value representable as 16.16 + */ + if ((f >> CAIRO_FIXED_FRAC_BITS) < INT16_MIN) { + x = INT32_MIN; + } else if ((f >> CAIRO_FIXED_FRAC_BITS) > INT16_MAX) { + x = INT32_MAX; + } else { + x = f << (16 - CAIRO_FIXED_FRAC_BITS); + } + + return x; #endif } -- cgit v1.2.3 From fa7e36669ae24fdbb5bd89a9fc1b6906408a5823 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 6 Nov 2007 14:53:09 -0800 Subject: [quartz] Fix for 10.5 SDK; the FloatToFixed macro started doing strange things --- src/cairo-quartz-surface.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index 77911de5..5fa4cc25 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -38,6 +38,14 @@ #include "cairo-quartz-private.h" +/* The 10.5 SDK includes a funky new definition of FloatToFixed which + * causes all sorts of breakage; so reset to old-style definition + */ +#ifdef FloatToFixed +#undef FloatToFixed +#define FloatToFixed(a) ((Fixed)((float)(a) * fixed1)) +#endif + #include #undef QUARTZ_DEBUG -- cgit v1.2.3 From 9b8d9f2859ce66b742c887eb673407a84095f488 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 6 Nov 2007 14:54:59 -0800 Subject: [win32] Skip doing some work if we can't call StretchDIBits --- src/cairo-win32-printing-surface.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c index 2dee9eb8..58dc74f9 100644 --- a/src/cairo-win32-printing-surface.c +++ b/src/cairo-win32-printing-surface.c @@ -494,6 +494,12 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf RECT clip; const cairo_color_t *background_color; + /* If we can't use StretchDIBits with this surface, we can't do anything + * here. + */ + if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHDIB)) + return CAIRO_INT_STATUS_UNSUPPORTED; + if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) background_color = CAIRO_COLOR_WHITE; else -- cgit v1.2.3 From 95ede9ea59eb1e2d7fe10fbc698f3f9fff192e79 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 6 Nov 2007 15:06:06 -0800 Subject: Use correct surface resolution when creating paginated fallback image If a surface resolution is set via _cairo_surface_set_resolution, it needs to be used when the fallback image is created. The user sets the fallback resolution on the paginated surface, so we need to divide that by the resolution of the actual (target) surface, not the paginated surface. --- src/cairo-paginated-surface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index e25204e0..d3c6a450 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -241,8 +241,8 @@ static cairo_int_status_t _paint_fallback_image (cairo_paginated_surface_t *surface, cairo_box_int_t *box) { - double x_scale = surface->base.x_fallback_resolution / surface->base.x_resolution; - double y_scale = surface->base.y_fallback_resolution / surface->base.y_resolution; + double x_scale = surface->base.x_fallback_resolution / surface->target->x_resolution; + double y_scale = surface->base.y_fallback_resolution / surface->target->y_resolution; cairo_matrix_t matrix; int x, y, width, height; cairo_status_t status; -- cgit v1.2.3 From f11f7524b62df29aa377382f5ceeda8c3beb2d54 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 6 Nov 2007 15:40:30 -0800 Subject: [quartz] work around Quartz bugs with images bigger than a certain size Quartz has a bug with images greater than (signed) 16 bits in height; avoid creating or working with those. Also fixes some memory leaks. Patch from John Daggett. --- src/cairo-quartz-surface.c | 61 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index 5fa4cc25..508b8a34 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -47,6 +47,7 @@ #endif #include +#include #undef QUARTZ_DEBUG @@ -107,6 +108,26 @@ extern void CGContextClipToMask (CGContextRef, CGRect, CGImageRef) __attribute__ static void quartz_surface_to_png (cairo_quartz_surface_t *nq, char *dest); static void quartz_image_to_png (CGImageRef, char *dest); +/* CoreGraphics limitation with flipped CTM surfaces: height must be less than signed 16-bit max */ + +#define CG_MAX_HEIGHT SHRT_MAX +#define CG_MAX_WIDTH USHRT_MAX + +/* is the desired size of the surface within bounds? */ +static cairo_bool_t verify_surface_size(int width, int height) +{ + /* hmmm, allow width, height == 0 ? */ + if (width < 0 || height < 0) { + return FALSE; + } + + if (width > CG_MAX_WIDTH || height > CG_MAX_HEIGHT) { + return FALSE; + } + + return TRUE; +} + /* * Cairo path -> Quartz path conversion helpers */ @@ -466,6 +487,14 @@ _cairo_quartz_surface_to_quartz (cairo_surface_t *target, if (status) return status; + if (new_surf && + cairo_surface_get_type (new_surf) != CAIRO_SURFACE_TYPE_QUARTZ) + { + ND((stderr, "got a non-quartz surface, format=%d width=%u height=%u type=%d\n", cairo_surface_get_type (pat_surf), rect.width, rect.height, cairo_surface_get_type (new_surf))); + cairo_surface_destroy (new_surf); + return CAIRO_INT_STATUS_UNSUPPORTED; + } + *quartz_surf = (cairo_quartz_surface_t *) new_surf; } else { /* If it's a quartz surface, we can try to see if it's a CGBitmapContext; @@ -979,6 +1008,7 @@ _cairo_quartz_surface_release_dest_image (void *abstract_surface, if (!CGBitmapContextGetData (surface->cgContext)) { CGDataProviderRef dataProvider; + CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); CGImageRef img; dataProvider = CGDataProviderCreateWithData (NULL, imageData, @@ -988,12 +1018,13 @@ _cairo_quartz_surface_release_dest_image (void *abstract_surface, img = CGImageCreate (surface->extents.width, surface->extents.height, 8, 32, surface->extents.width * 4, - CGColorSpaceCreateDeviceRGB(), + rgb, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, dataProvider, NULL, false, kCGRenderingIntentDefault); + CGColorSpaceRelease (rgb); CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositeCopy); @@ -1028,6 +1059,12 @@ _cairo_quartz_surface_create_similar (void *abstract_surface, format = CAIRO_FORMAT_A8; else return NULL; + + // verify width and height of surface + if (!verify_surface_size(width, height)) { + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return NULL; + } return cairo_quartz_surface_create (format, width, height); } @@ -1043,6 +1080,13 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface, { cairo_quartz_surface_t *new_surface = NULL; cairo_format_t new_format; + + *clone_out = NULL; + + // verify width and height of surface + if (!verify_surface_size(width, height)) { + return CAIRO_INT_STATUS_UNSUPPORTED; + } CGImageRef quartz_image = NULL; @@ -1107,8 +1151,10 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface, cairo_quartz_surface_create (new_format, CGImageGetWidth (quartz_image), CGImageGetHeight (quartz_image)); - if (!new_surface || new_surface->base.status) + if (!new_surface || new_surface->base.status) { + CGImageRelease (quartz_image); return CAIRO_INT_STATUS_UNSUPPORTED; + } CGContextSetCompositeOperation (new_surface->cgContext, kPrivateCGCompositeCopy); @@ -1679,6 +1725,9 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = { #endif /* CAIRO_HAS_ATSUI_FONT */ NULL, /* snapshot */ + NULL, /* is_similar */ + NULL, /* reset */ + NULL /* fill_stroke */ }; static cairo_quartz_surface_t * @@ -1796,6 +1845,12 @@ cairo_quartz_surface_create (cairo_format_t format, int stride; int bitsPerComponent; + // verify width and height of surface + if (!verify_surface_size(width, height)) { + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t*) &_cairo_surface_nil; + } + if (format == CAIRO_FORMAT_ARGB32) { cgColorspace = CGColorSpaceCreateDeviceRGB(); stride = width * 4; @@ -1844,6 +1899,7 @@ cairo_quartz_surface_create (cairo_format_t format, if (!cgc) { _cairo_error (CAIRO_STATUS_NO_MEMORY); + free (imageData); return (cairo_surface_t*) &_cairo_surface_nil; } @@ -1855,6 +1911,7 @@ cairo_quartz_surface_create (cairo_format_t format, width, height); if (!surf) { CGContextRelease (cgc); + free (imageData); // create_internal will have set an error return (cairo_surface_t*) &_cairo_surface_nil; } -- cgit v1.2.3 From 0901b83ca56e197d5c96d71ab8cfe53f21b4c8bb Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 6 Nov 2007 15:49:57 -0800 Subject: [win32] Don't use GetGlyphOutline on non-TrueType fonts win32-glyph-metrics.patch: GetGlyphOutline only works on Truetype fonts, so for non-Truetype fonts, assume no left or right bearing and use the font ascent and descent for the glyph extents. --- src/cairo-win32-font.c | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c index dbabbef3..7d4a10cf 100644 --- a/src/cairo-win32-font.c +++ b/src/cairo-win32-font.c @@ -99,6 +99,7 @@ typedef struct { HFONT scaled_hfont; HFONT unscaled_hfont; + cairo_bool_t is_truetype; cairo_bool_t glyph_indexing; cairo_bool_t delete_scaled_hfont; @@ -741,11 +742,11 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font) } - if ((metrics.tmPitchAndFamily & TMPF_TRUETYPE) || - (GetFontData (hdc, OPENTYPE_CFF_TAG, 0, NULL, 0) != GDI_ERROR)) - scaled_font->glyph_indexing = TRUE; - else - scaled_font->glyph_indexing = FALSE; + scaled_font->is_truetype = (metrics.tmPitchAndFamily & TMPF_TRUETYPE) != 0; + scaled_font->glyph_indexing = scaled_font->is_truetype || + (GetFontData (hdc, OPENTYPE_CFF_TAG, 0, NULL, 0) != GDI_ERROR); + // XXX in what situations does this OPENTYPE_CFF thing not have the + // TMPF_TRUETYPE flag? GetFontData says it only works on Truetype fonts... _cairo_scaled_font_set_metrics (&scaled_font->base, &extents); @@ -761,18 +762,35 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f cairo_status_t status; cairo_text_extents_t extents; HDC hdc; - UINT glyph_index_option; hdc = _get_global_font_dc (); if (!hdc) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - if (scaled_font->glyph_indexing) - glyph_index_option = GGO_GLYPH_INDEX; - else - glyph_index_option = 0; + if (!scaled_font->is_truetype) { + /* GetGlyphOutline will not work. Assume that the glyph does not extend outside the font box. */ + cairo_font_extents_t font_extents; + INT width = 0; + UINT charIndex = _cairo_scaled_glyph_index (scaled_glyph); + + cairo_scaled_font_extents (&scaled_font->base, &font_extents); + + status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); + if (!status) { + if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) { + status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32"); + width = 0; + } + } + cairo_win32_scaled_font_done_font (&scaled_font->base); - if (scaled_font->preserve_axes && scaled_font->base.options.hint_style != CAIRO_HINT_METRICS_OFF) { + extents.x_bearing = 0; + extents.y_bearing = -font_extents.ascent / scaled_font->y_scale; + extents.width = width / scaled_font->x_scale; + extents.height = (font_extents.ascent + font_extents.descent) / scaled_font->y_scale; + extents.x_advance = extents.width; + extents.y_advance = 0; + } else if (scaled_font->preserve_axes && scaled_font->base.options.hint_style != CAIRO_HINT_METRICS_OFF) { /* If we aren't rotating / skewing the axes, then we get the metrics * from the GDI in device space and convert to font space. */ @@ -780,7 +798,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f if (status) return status; if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_METRICS | glyph_index_option, + GGO_METRICS | GGO_GLYPH_INDEX, &metrics, 0, NULL, &matrix) == GDI_ERROR) { status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW"); memset (&metrics, 0, sizeof (GLYPHMETRICS)); @@ -819,7 +837,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f */ status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_METRICS | glyph_index_option, + GGO_METRICS | GGO_GLYPH_INDEX, &metrics, 0, NULL, &matrix) == GDI_ERROR) { status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW"); memset (&metrics, 0, sizeof (GLYPHMETRICS)); -- cgit v1.2.3 From d72bb8c12efcffe7c576afe63212b2fe47e8154c Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 6 Nov 2007 16:08:59 -0800 Subject: [win32] Fix FIXED_to_fixed when cairo's fixed format isn't 16.16 --- src/cairo-win32-font.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c index 7d4a10cf..992f6754 100644 --- a/src/cairo-win32-font.c +++ b/src/cairo-win32-font.c @@ -1335,13 +1335,11 @@ _cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix, FIXED Fx, FIXED Fy, cairo_fixed_t *fx, cairo_fixed_t *fy) { - double x, y; - - x = _cairo_fixed_to_double (*((cairo_fixed_t *)&Fx)); - y = _cairo_fixed_to_double (*((cairo_fixed_t *)&Fy)); + double x = Fx.value + Fx.fract / 65536.0; + double y = Fy.value + Fy.fract / 65536.0; cairo_matrix_transform_point (matrix, &x, &y); - *fx = _cairo_fixed_from_double (x); - *fy = _cairo_fixed_from_double (y); + *fx = _cairo_fixed_from_double (x); + *fy = _cairo_fixed_from_double (y); } static cairo_status_t -- cgit v1.2.3 From 28412f780ebf52914aa374bb2bdd3d539bd29241 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 6 Nov 2007 16:11:06 -0800 Subject: [win32-printing] bail out early if we don't have anything to do in paint_surf --- src/cairo-win32-printing-surface.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c index 58dc74f9..57f1ab07 100644 --- a/src/cairo-win32-printing-surface.c +++ b/src/cairo-win32-printing-surface.c @@ -522,6 +522,11 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf goto FINISH2; } + if (image->width == 0 || image->height == 0) { + status = CAIRO_STATUS_SUCCESS; + goto FINISH2; + } + if (image->format != CAIRO_FORMAT_RGB24) { opaque_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, image->width, -- cgit v1.2.3 From 15fc1bbefb49fefedca53c47ccfc7edace0acbfe Mon Sep 17 00:00:00 2001 From: Brian Ewins Date: Sat, 10 Nov 2007 01:33:47 +0000 Subject: [test] log tested paths so that they can be parsed. The test logs currently do not record the paths of image output, the reference images tested against, and the diffs created. This means that make-html.pl has to duplicate the policy in cairo-test.c. Fix this by teaching cairo-test.c to log the paths. --- test/cairo-test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/cairo-test.c b/test/cairo-test.c index de8ed1bc..d2e41570 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -387,6 +387,7 @@ cairo_test_for_target (cairo_test_t *test, xunlink (png_name); (target->write_to_png) (surface, png_name); + cairo_test_log ("OUTPUT: %s\n", png_name); if (!ref_name) { cairo_test_log ("Error: Cannot find reference image for %s/%s-%s-%s%s\n",srcdir, test->name, @@ -397,7 +398,8 @@ cairo_test_for_target (cairo_test_t *test, goto UNWIND_CAIRO; } - cairo_test_log ("Comparing result against reference image: %s\n", ref_name); + cairo_test_log ("REFERENCE: %s\n", ref_name); + cairo_test_log ("DIFFERENCE: %s\n", diff_name); if (target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED) { diff_status= image_diff_flattened (png_name, ref_name, diff_name, -- cgit v1.2.3 From f8ee0cdf186bfb30bdeb487b63d42f274c1073ce Mon Sep 17 00:00:00 2001 From: Brian Ewins Date: Sat, 10 Nov 2007 01:34:01 +0000 Subject: [test] Link to the correct reference image. The generated test html guesses the names of the reference images used in the tests. This is quite often wrong, and makes it harder to change policy in cairo-test. Teach make-html.pl to parse the log for the path to the reference image. --- test/make-html.pl | 102 ++++++++++++++++++++++++------------------------------ 1 file changed, 45 insertions(+), 57 deletions(-) diff --git a/test/make-html.pl b/test/make-html.pl index 9720c067..8bc961e5 100755 --- a/test/make-html.pl +++ b/test/make-html.pl @@ -54,20 +54,40 @@ if ($#ARGV >= 0) { @files = @ARGV; } else { @files = <*.log>; } foreach (<@files>) { my $testname; + my $out_path, $diff_path, $ref_path; my $fn = $_; (open LOG, $fn) || next; while () { + if (/^OUTPUT: (.*)$/) { + $out_path = $1; + next; + } + if (/^DIFFERENCE: (.*)$/) { + $diff_path = $1; + next; + } + if (/^REFERENCE: (.*)$/) { + $ref_path = $1; + next; + } next unless /^TEST: (.*) TARGET: (.*) FORMAT: (.*) OFFSET: (.*) SIMILAR: (.*) RESULT: ([A-Z]*).*$/; $testname = $1 if !defined($testname); $tests->{$1} = {} unless $tests->{$1}; $tests->{$1}->{$2} = {} unless $tests->{$1}->{$2}; $tests->{$1}->{$2}->{$3} = {} unless $tests->{$1}->{$2}->{$3}; $tests->{$1}->{$2}->{$3}->{$4} = {} unless $tests->{$1}->{$2}->{$3}->{$4}; - $tests->{$1}->{$2}->{$3}->{$4}->{$5} = $6; + $tests->{$1}->{$2}->{$3}->{$4}->{$5}->{'out'} = $out_path; + $tests->{$1}->{$2}->{$3}->{$4}->{$5}->{'diff'} = $diff_path; + $tests->{$1}->{$2}->{$3}->{$4}->{$5}->{'ref'} = $ref_path; + $tests->{$1}->{$2}->{$3}->{$4}->{$5}->{'result'} = $6; $teststats->{$2} = {"PASS" => 0, "FAIL" => 0, "XFAIL" => 0, "UNTESTED" => 0, "CRASHED" =>0} unless $teststats->{$2}; ($teststats->{$2}->{$6})++; + + undef $out_path; + undef $diff_path; + undef $ref_path; } close LOG; @@ -158,7 +178,6 @@ printl ''; printl ''; print ''; -print '' if $config_show_ref; foreach my $target (@targets) { print ''; @@ -166,7 +185,6 @@ foreach my $target (@targets) { printl ''; print ''; -print '' if $config_show_ref; foreach my $target (@targets) { print ''; -sub testref { - my ($test, $format, $rest) = @_; - my $fmtstr = ""; - if ($format eq "rgb24") { - $fmtstr = "-rgb24"; - } - - return "$test$fmtstr-ref.png"; -} - -sub testfiles { - my ($test, $target, $format, $offset, $similar, $rest) = @_; - my $fmtstr = ""; - my $offstr = ""; - my $simstr = ""; - if ($format eq "rgb24") { - $fmtstr = "-rgb24"; - } elsif ($format eq "argb32") { - $fmtstr = "-argb32"; - } - if ($similar ne "0") { - $simstr = "-similar"; - } - if ($offset ne "0") { - $offstr = "-" . $offset; - } - - return ("out" => "$test-$target$fmtstr$simstr$offstr-out.png", - "diff" => "$test-$target$fmtstr$simstr$offstr-diff.png"); -} - sub img_for { my ($fn, $withlink) = @_; @@ -237,35 +224,42 @@ foreach my $test (sort(keys %$tests)) { if ($tgtdata) { my $testres = $tgtdata->{$format}->{$offset}->{$similar}; if ($testres) { - my %testfiles = testfiles($test, $target, $format, - $offset, $similar); - $testline .= ""; } else { @@ -275,23 +269,18 @@ foreach my $test (sort(keys %$tests)) { $testline .= ''; } } - my $testref = testref($test, $format); print ''; - if ($config_show_ref) { - print ""; - } - print $testline; print "\n"; @@ -301,4 +290,3 @@ foreach my $test (sort(keys %$tests)) { } print "
TestRef', $target, '
'; @@ -178,37 +196,6 @@ foreach my $target (@targets) { } printl '
"; + my %testfiles; + $testfiles{'out'} = $testres->{'out'}; + $testfiles{'diff'} = $testres->{'diff'}; + $testfiles{'ref'} = $testres->{'ref'}; + + $testline .= "{'result'}\">"; $teststats{$target}{$testres}++; - if ($testres eq "PASS") { + if ($testres->{'result'} eq "PASS") { if ($config_show_all) { - $testline .= img_for($testfiles{'out'},1); + $testline .= img_for($testfiles{'out'},1); } - } elsif ($testres eq "FAIL") { + } elsif ($testres->{'result'} eq "FAIL") { if ($config_show_fail || $config_show_all) { - $testline .= img_for($testfiles{'out'},1); + $testline .= img_for($testfiles{'out'},1); $testline .= " "; - $testline .= img_for($testfiles{'diff'},1); + $testline .= img_for($testfiles{'diff'},1); + $testline .= " "; + $testline .= img_for($testfiles{'ref'},1); } - } elsif ($testres eq "CRASHED") { - $testline .= "!!!CRASHED!!!"; - } elsif ($testres eq "XFAIL") { + } elsif ($testres->{'result'} eq "CRASHED") { + $testline .= "!!!CRASHED!!!"; + } elsif ($testres->{'result'} eq "XFAIL") { #nothing if ($config_show_all) { - $testline .= img_for($testfiles{'out'},1); + $testline .= img_for($testfiles{'out'},1); #$testline .= "
"; $testline .= " "; - $testline .= img_for($testfiles{'diff'},1); + $testline .= img_for($testfiles{'diff'},1); + $testline .= " "; + $testline .= img_for($testfiles{'ref'},1); } - } elsif ($testres eq "UNTESTED") { + } elsif ($testres->{'result'} eq "UNTESTED") { #nothing } else { - $testline .= "UNSUPPORTED STATUS (update make-html.pl)"; - } + $testline .= "UNSUPPORTED STATUS '$testres->{'result'}' (update make-html.pl)"; + } $testline .= "
'; if ($config_show_inline) { print "$test ($format/$offset) "; print "({$test}) . "\">log)"; } else { - print "", $test, ' (', $format, '/', $offset, ($similar ? ' similar' : ''), ') '; + print $test, ' (', $format, '/', $offset, ($similar ? ' similar' : ''), ') '; print "(log)"; } print '" . img_for($testref,1) . "
\n"; - -- cgit v1.2.3 From 77e9b05b2b011ce964287ff493c2b421977107ee Mon Sep 17 00:00:00 2001 From: Brian Ewins Date: Sat, 10 Nov 2007 01:34:03 +0000 Subject: [test] support using a previous build as a reference Allow using a previous test output directory as a source of reference images. To make use of this, set the environment variable 'CAIRO_REF_DIR' to point at an old test directory, relative to the current test directory. This is useful for testing backends when reference images haven't been created yet, or which the current reference image structure can't accomodate, like multiple font backends. --- test/README | 8 ++++++++ test/cairo-test.c | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/test/README b/test/README index 90f02876..840e1add 100644 --- a/test/README +++ b/test/README @@ -69,6 +69,14 @@ The work involved is similar the work described above for new bugs. The only distinction is that the test is expected to pass so it should not be added to the XFAIL_TESTS list. +While working on a test +----------------------- +Before a bugfix or feature is ready, it may be useful to compare +output from different builds. For convenience, you can set +CAIRO_REF_DIR to point at a previous test directory, relative +to the current test directory, and any previous output will be +used by preference as reference images. + When a bug is fixed ------------------- diff --git a/test/cairo-test.c b/test/cairo-test.c index d2e41570..f036163b 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -96,6 +96,7 @@ static const char *vector_ignored_tests[] = { * context object there, (though not a whole lot). */ FILE *cairo_test_log_file = NULL; const char *srcdir; +const char *refdir; /* Used to catch crashes in a test, such that we report it as such and * continue testing, although one crasher may already have corrupted memory in @@ -158,7 +159,20 @@ cairo_ref_name_for_test_target_format (const char *test_name, { char *ref_name = NULL; - /* First look for a target/format-specific reference image. */ + /* First look for a previous build for comparison. */ + if (refdir) { + xasprintf (&ref_name, "%s/%s-%s-%s%s", refdir, + test_name, + target_name, + format, + CAIRO_TEST_PNG_SUFFIX); + if (access (ref_name, F_OK) != 0) + free (ref_name); + else + goto done; + } + + /* Next look for a target/format-specific reference image. */ xasprintf (&ref_name, "%s/%s-%s-%s%s", srcdir, test_name, target_name, @@ -477,6 +491,7 @@ cairo_test_expecting (cairo_test_t *test, srcdir = getenv ("srcdir"); if (!srcdir) srcdir = "."; + refdir = getenv ("CAIRO_REF_DIR"); cairo_test_init (test->name); printf ("%s\n", test->description); -- cgit v1.2.3