From 7ead3572a5250cc74ef71a0b836541b9e8234ad8 Mon Sep 17 00:00:00 2001 From: Laurent Callarec Date: Sun, 14 Jan 2024 22:55:08 +0100 Subject: [PATCH] Fix area Region color --- src/region.vala | 12 +- src/smooth_line.vala | 29 ++-- src/smooth_line_area.vala | 101 ++++++++----- tests/fakes.vala | 9 +- tests/runner.vala | 19 +++ tests/smooth_line_area.vala | 285 +++++++++++++++++++++++++++++++----- 6 files changed, 365 insertions(+), 90 deletions(-) diff --git a/src/region.vala b/src/region.vala index e771bfd..60b6dfb 100644 --- a/src/region.vala +++ b/src/region.vala @@ -14,8 +14,8 @@ namespace LiveChart { public delegate Coord? GetIntersection(double at_value); public class Region { - public Gdk.RGBA line_color { get; set; default = Gdk.RGBA () { red = 1f, green = 1f, blue = 1f, alpha = 1f }; } - public Gdk.RGBA area_color { get; set; default = Gdk.RGBA () { red = 1f, green = 1f, blue = 1f, alpha = 0.5f }; } + public Gdk.RGBA? line_color { get; set; } + public Gdk.RGBA? area_color { get; set; } private double floor; private double ceil; @@ -27,6 +27,14 @@ namespace LiveChart { this.resolver = new CrossRegionResolver(this.floor, this.ceil); } + public bool has_line_color() { + return this.line_color != null; + } + + public bool has_area_color() { + return this.area_color != null; + } + public Region.between(double above, double below) { this(above, below); } diff --git a/src/smooth_line.vala b/src/smooth_line.vala index da00785..73adbec 100644 --- a/src/smooth_line.vala +++ b/src/smooth_line.vala @@ -1,11 +1,11 @@ using Cairo; namespace LiveChart { + public class SmoothLine : SerieRenderer { public Region? region {get; set; default = null; } - private SmoothLineDrawer drawer = new SmoothLineDrawer(); - private SmoothLineLineDrawer line_drawer = new SmoothLineLineDrawer(); + private SmoothLineSerieDrawer drawer = new SmoothLineSerieDrawer(); public SmoothLine(Values values = new Values()) { base(); @@ -17,24 +17,19 @@ namespace LiveChart { drawer.draw(ctx, config, this.line, Points.create(values, config), this.region); } } - - public Cairo.Path draw_smooth_line(Points points, Context ctx, Config config) { - line_drawer.draw(ctx, config, this.line, points, region); - return ctx.copy_path(); - } } - public class SmoothLineDrawer { - private SmoothLineLineDrawer line_drawer = new SmoothLineLineDrawer(); - private SmoothLineRegionOnLineDrawer region_on_line_drawer = new SmoothLineRegionOnLineDrawer(); + public class SmoothLineSerieDrawer : Drawer { + private SmoothLineDrawer line_drawer = new SmoothLineDrawer(); + private RegionOnLineDrawer region_on_line_drawer = new RegionOnLineDrawer(); - public void draw(Context ctx, Config config, Path line, Points points, Region? region) { + public Intersections draw(Context ctx, Config config, Path line, Points points, Region? region) { if(points.size > 0) { + var intersections = line_drawer.draw(ctx, config, line, points, region); if (region != null) { ctx.push_group(); } - var intersections = line_drawer.draw(ctx, config, line, points, region); ctx.stroke(); if (region != null) { @@ -44,11 +39,14 @@ namespace LiveChart { ctx.pop_group_to_source(); ctx.paint(); } - } + return intersections; + } + + return new Intersections(); } } - public class SmoothLineLineDrawer : Drawer { + public class SmoothLineDrawer : Drawer { public Intersections draw(Context ctx, Config config, Path line, Points points, Region? region) { var intersections = new Intersections(); var first_point = points.first(); @@ -85,7 +83,7 @@ namespace LiveChart { } } - public class SmoothLineRegionOnLineDrawer { + public class RegionOnLineDrawer { public void draw(Context ctx, Config config, Intersections intersections) { var boundaries = config.boundaries(); intersections.foreach((intersection) => { @@ -95,7 +93,6 @@ namespace LiveChart { } return true; }); - ctx.fill(); } } } \ No newline at end of file diff --git a/src/smooth_line_area.vala b/src/smooth_line_area.vala index b65cc0b..b1572b4 100644 --- a/src/smooth_line_area.vala +++ b/src/smooth_line_area.vala @@ -4,7 +4,7 @@ namespace LiveChart { public class SmoothLineArea : SmoothLine { public double area_alpha {get; set; default = 0.1;} - private SmoothLineAreaDrawer drawer = new SmoothLineAreaDrawer(); + private SmoothLineAreaSerieDrawer drawer = new SmoothLineAreaSerieDrawer(); public SmoothLineArea(Values values = new Values()) { base(values); @@ -16,52 +16,83 @@ namespace LiveChart { } } - public class SmoothLineRegionAreaDrawer { - public void draw(Context ctx, Config config, Intersections intersections) { - var boundaries = config.boundaries(); - intersections.foreach((intersection) => { - if (intersection != null) { - ctx.rectangle(intersection.start_x, boundaries.y.min, intersection.end_x - intersection.start_x, boundaries.height); - ctx.set_source_rgba(intersection.region.area_color.red, intersection.region.area_color.green, intersection.region.area_color.blue, intersection.region.area_color.alpha); - ctx.fill(); - } - return true; - }); - } - } - - public class SmoothLineAreaDrawer { + public class SmoothLineAreaSerieDrawer { - private SmoothLineRegionAreaDrawer region_drawer = new SmoothLineRegionAreaDrawer(); - private SmoothLineRegionOnLineDrawer region_on_line_drawer = new SmoothLineRegionOnLineDrawer(); - private SmoothLineLineDrawer smooth_line_drawer = new SmoothLineLineDrawer(); + private RegionAreaDrawer region_drawer = new RegionAreaDrawer(); + private RegionOnLineDrawer region_on_line_drawer = new RegionOnLineDrawer(); + private SmoothLineDrawer smooth_line_drawer = new SmoothLineDrawer(); public void draw(Context ctx, Config config, Path line, Points points, Gdk.RGBA color, double alpha, Region? region) { if(points.size > 0) { - ctx.push_group(); - var intersections = smooth_line_drawer.draw(ctx, config, line, points, region); - var path = ctx.copy_path(); + var intersections = smooth_line_drawer.draw(ctx, config, line, points, region); + var curve = ctx.copy_path(); + + if(region != null && region.has_line_color()) { + ctx.push_group(); + ctx.stroke(); - ctx.stroke_preserve(); + ctx.set_operator(Operator.IN); + region_on_line_drawer.draw(ctx, config, intersections); + ctx.fill(); + ctx.pop_group_to_source(); + ctx.paint(); + } else { + ctx.stroke(); + } + ctx.push_group(); + ctx.append_path(curve); var area = new Area(points, color, alpha); area.draw(ctx, config); ctx.fill(); - - ctx.set_operator(Operator.ATOP); - region_on_line_drawer.draw(ctx, config, intersections); - ctx.fill(); - ctx.pop_group_to_source(); + + // Clear pixels that overlaps existing path + ctx.append_path(curve); + ctx.set_operator(Operator.CLEAR); + ctx.stroke(); - ctx.save(); - ctx.append_path(path); - area.draw(ctx, config); - ctx.clip(); - - region_drawer.draw(ctx, config, intersections); - ctx.restore(); + if (region != null && region.has_area_color()) { + + // Clear existing area if regions + ctx.set_operator(Operator.CLEAR); + region_drawer.draw(ctx, config, intersections); + } + + ctx.pop_group_to_source(); ctx.paint(); + + if (region != null && region.has_area_color()) { + ctx.push_group(); + //Create a clip to match the region area only, without the line + ctx.append_path(curve); + area.draw(ctx, config); + ctx.clip(); + + region_drawer.draw(ctx, config, intersections); + + ctx.append_path(curve); + ctx.set_operator(Operator.CLEAR); + ctx.stroke(); + + ctx.pop_group_to_source(); + + ctx.paint(); + } } } } + + public class RegionAreaDrawer { + public void draw(Context ctx, Config config, Intersections intersections) { + var boundaries = config.boundaries(); + intersections.foreach((intersection) => { + if (intersection != null) { + ctx.set_source_rgba(intersection.region.area_color.red, intersection.region.area_color.green, intersection.region.area_color.blue, intersection.region.area_color.alpha); + ctx.rectangle(intersection.start_x, boundaries.y.min, intersection.end_x - intersection.start_x, boundaries.height); + } + return true; + }); + ctx.fill(); + } + } } \ No newline at end of file diff --git a/tests/fakes.vala b/tests/fakes.vala index 606a40d..8985cc4 100644 --- a/tests/fakes.vala +++ b/tests/fakes.vala @@ -127,15 +127,16 @@ private ColorAtCoodinates get_color_at_from_pixels(uint8[] pixels, int stride, i }; } -public void screenshot(TestContext context, string filename) { +public void screenshot(TestContext context, string suffix = "") { int width = context.surface.get_width(); int height = context.surface.get_height(); var pixbuff = Gdk.pixbuf_get_from_surface(context.surface, 0, 0, width, height); + var test_path = Test.get_path().replace("/", "____"); try { - pixbuff.save(filename, "png"); - } catch { - + pixbuff.save(@"screenshots/$(test_path).png", "png"); + } catch (Error e) { + message(@"Screenshot error in $(test_path): $(e.message)"); } } diff --git a/tests/runner.vala b/tests/runner.vala index 590b53a..52e8d57 100644 --- a/tests/runner.vala +++ b/tests/runner.vala @@ -3,6 +3,8 @@ void main (string[] args) { Test.init(ref args); Gtk.init(); + prepare_screenshots_directory(); + register_config(); register_bounds(); register_values(); @@ -28,4 +30,21 @@ void main (string[] args) { register_intersections(); Test.run(); +} + +private void prepare_screenshots_directory() { + try { + var directory = File.new_for_path("screenshots"); + if(directory.query_exists()) { + Dir screenshot_dir = Dir.open("screenshots", 0); + string? name = null; + while ((name = screenshot_dir.read_name ()) != null) { + File.new_for_path(@"screenshots/$(name)").delete(); + } + directory.delete(); + } + directory.make_directory(); + } catch (Error e) { + message(@"Error while preparing screenshots directory : $(e.message)"); + } } \ No newline at end of file diff --git a/tests/smooth_line_area.vala b/tests/smooth_line_area.vala index ffa589f..3a8d73f 100644 --- a/tests/smooth_line_area.vala +++ b/tests/smooth_line_area.vala @@ -12,7 +12,8 @@ private void register_smooth_line_area() { //When line.draw(context.ctx, create_config()); - + screenshot(context); + //Then assert(has_only_one_color(context)(DEFAULT_BACKGROUND_COLOR)); }); @@ -34,48 +35,266 @@ private void register_smooth_line_area() { //When line.draw(context.ctx, create_config(43, 20)); - + screenshot(context); + //Then the curve colors are... - assert(get_color_at(context)({x: 0, y: 14}) == green); - assert(get_color_at(context)({x: 22, y: 0}) == green); - assert(get_color_at(context)({x: 42, y: 14}) == green); + assert(get_color_at(context)({x: 0, y: 14}) == green); + assert(get_color_at(context)({x: 22, y: 0}) == green); + assert(get_color_at(context)({x: 42, y: 14}) == green); //And below the curve, color is... - var area_color = Gdk.RGBA() { red = 0.5f, green = 1f, blue = 0.5f, alpha = 1f }; - assert(get_color_at(context)({x: 22, y: 7}).equal(area_color)); + var flattened_area_color = Gdk.RGBA() { red = 0.5f, green = 1f, blue = 0.5f, alpha = 1f }; + assert(get_color_at(context)({x: 22, y: 7}).equal(flattened_area_color)); }); - Test.add_func("/SmoothLineArea/should_render_a_smooth_line_area_with_region", () => { - //Given - var green = Gdk.RGBA() { red = 0.0f, green = 1.0f, blue = 0.0f, alpha = 1.0f }; - var red = Gdk.RGBA() { red = 1.0f, green = 0f, blue = 0.0f, alpha = 1.0f }; + Test.add_func("/SmoothLineArea/Regions", () => { + Test.add_func("/SmoothLineArea/should_render_a_smooth_line_area_with_plain_line_region", () => { + //Given + var green = Gdk.RGBA() { red = 0.0f, green = 1.0f, blue = 0.0f, alpha = 1.0f }; + var red = Gdk.RGBA() { red = 1.0f, green = 0f, blue = 0.0f, alpha = 1f }; - var context = create_context(43, 20); + var context = create_context(43, 20); - var values = new LiveChart.Values(); - values.add({timestamp: (GLib.get_real_time() / 1000) - 7200, value: 5}); - values.add({timestamp: (GLib.get_real_time() / 1000) - 3600, value: 20}); - values.add({timestamp: (GLib.get_real_time() / 1000), value: 5}); - - var line = new LiveChart.SmoothLineArea(values); - line.region = new LiveChart.Region.between(3, 10).with_line_color(red); - line.line.color = green; - line.area_alpha = 0.5f; + var values = new LiveChart.Values(); + values.add({timestamp: (GLib.get_real_time() / 1000) - 7200, value: 5}); + values.add({timestamp: (GLib.get_real_time() / 1000) - 3600, value: 20}); + values.add({timestamp: (GLib.get_real_time() / 1000), value: 5}); + + var line = new LiveChart.SmoothLineArea(values); + line.region = new LiveChart.Region.between(3, 10).with_line_color(red); + line.line.color = green; + line.area_alpha = 0.5f; - //When - line.draw(context.ctx, create_config(43, 20)); + //When + line.draw(context.ctx, create_config(43, 20)); + screenshot(context); - //Then the curve colors are... - assert(get_color_at(context)({x: 0, y: 14}) == red); - assert(get_color_at(context)({x: 22, y: 0}) == green); - assert(get_color_at(context)({x: 42, y: 14}) == red); + //Then the curve colors are... + assert(get_color_at(context)({x: 0, y: 14}) == red); + assert(get_color_at(context)({x: 22, y: 0}) == green); + assert(get_color_at(context)({x: 42, y: 14}) == red); - //And below the curve, color is... - var normal_area_color = Gdk.RGBA() { red = 0.5f, green = 1f, blue = 0.5f, alpha = 1f }; - var within_region_area_color = Gdk.RGBA() { red = 1f, green = 0.5f, blue = 0.5f, alpha = 1f }; + //And below the curve, color is still a semi-transparent green + var flattened_area_color = Gdk.RGBA() { red = 0.5f, green = 1f, blue = 0.5f, alpha = 1f }; + + assert(get_color_at(context)({x: 0, y: 18}).equal(flattened_area_color)); + assert(get_color_at(context)({x: 22, y: 18}).equal(flattened_area_color)); + assert(get_color_at(context)({x: 42, y: 18}).equal(flattened_area_color)); + }); + Test.add_func("/SmoothLineArea/should_render_a_smooth_line_area_with_semi_transparent_line_region", () => { + //Given + var green = Gdk.RGBA() { red = 0.0f, green = 1.0f, blue = 0.0f, alpha = 1.0f }; + var transparent_red = Gdk.RGBA() { red = 1.0f, green = 0f, blue = 0.0f, alpha = 0.5f }; + + var context = create_context(43, 20); + + var values = new LiveChart.Values(); + values.add({timestamp: (GLib.get_real_time() / 1000) - 7200, value: 5}); + values.add({timestamp: (GLib.get_real_time() / 1000) - 3600, value: 20}); + values.add({timestamp: (GLib.get_real_time() / 1000), value: 5}); + + var line = new LiveChart.SmoothLineArea(values); + line.region = new LiveChart.Region.between(3, 10).with_line_color(transparent_red); + line.line.color = green; + line.area_alpha = 0.5f; + + //When + line.draw(context.ctx, create_config(43, 20)); + screenshot(context); + + var flattened_transparent_red = Gdk.RGBA() { red = 1f, green = 0.5f, blue = 0.5f, alpha = 1f }; + //Then the curve colors are... + assert(get_color_at(context)({x: 0, y: 14}) == flattened_transparent_red); + assert(get_color_at(context)({x: 22, y: 0}) == green); + assert(get_color_at(context)({x: 42, y: 14}) == flattened_transparent_red); + + //And below the curve, color is... + var flattened_area_color = Gdk.RGBA() { red = 0.5f, green = 1f, blue = 0.5f, alpha = 1f }; + + assert(get_color_at(context)({x: 0, y: 18}).equal(flattened_area_color)); + assert(get_color_at(context)({x: 22, y: 18}).equal(flattened_area_color)); + assert(get_color_at(context)({x: 42, y: 18}).equal(flattened_area_color)); + }); + + Test.add_func("/SmoothLineArea/should_render_a_smooth_line_area_with_plain_area_region", () => { + //Given + var green = Gdk.RGBA() { red = 0.0f, green = 1.0f, blue = 0.0f, alpha = 1.0f }; + var red = Gdk.RGBA() { red = 1.0f, green = 0f, blue = 0.0f, alpha = 1f }; + + var context = create_context(43, 20); + + var values = new LiveChart.Values(); + values.add({timestamp: (GLib.get_real_time() / 1000) - 7200, value: 5}); + values.add({timestamp: (GLib.get_real_time() / 1000) - 3600, value: 20}); + values.add({timestamp: (GLib.get_real_time() / 1000), value: 5}); + + var line = new LiveChart.SmoothLineArea(values); + line.region = new LiveChart.Region.between(3, 10).with_area_color(red); + line.line.color = green; + line.area_alpha = 0.5f; + + //When + line.draw(context.ctx, create_config(43, 20)); + screenshot(context); + + //Then the area color is... + var flattened_green = Gdk.RGBA() { red = 0.5f, green = 1f, blue = 0.5f, alpha = 1f }; + + assert(get_color_at(context)({x: 0, y: 18}).equal(red)); + assert(get_color_at(context)({x: 22, y: 18}).equal(flattened_green)); + assert(get_color_at(context)({x: 42, y: 18}).equal(red)); + + //And the curve colors are... + assert(get_color_at(context)({x: 0, y: 14}) == green); + assert(get_color_at(context)({x: 22, y: 0}) == green); + assert(get_color_at(context)({x: 42, y: 14}) == green); + }); + + Test.add_func("/SmoothLineArea/should_render_a_smooth_line_area_with_semi_transparent_area_region", () => { + //Given + var green = Gdk.RGBA() { red = 0.0f, green = 1.0f, blue = 0.0f, alpha = 1.0f }; + var transparent_red = Gdk.RGBA() { red = 1.0f, green = 0f, blue = 0.0f, alpha = 0.5f }; + + var context = create_context(43, 20); + + var values = new LiveChart.Values(); + values.add({timestamp: (GLib.get_real_time() / 1000) - 7200, value: 5}); + values.add({timestamp: (GLib.get_real_time() / 1000) - 3600, value: 20}); + values.add({timestamp: (GLib.get_real_time() / 1000), value: 5}); + + var line = new LiveChart.SmoothLineArea(values); + line.region = new LiveChart.Region.between(3, 10).with_line_color(transparent_red); + line.line.color = green; + line.area_alpha = 0.5f; + + //When + line.draw(context.ctx, create_config(43, 20)); + screenshot(context); + + var flattened_transparent_red = Gdk.RGBA() { red = 1f, green = 0.5f, blue = 0.5f, alpha = 1f }; + + //Then the curve colors are... + assert(get_color_at(context)({x: 0, y: 14}) == flattened_transparent_red); + assert(get_color_at(context)({x: 22, y: 0}) == green); + assert(get_color_at(context)({x: 42, y: 14}) == flattened_transparent_red); + + //And below the curve, color is still a semi-transparent green + var flattened_area_color = Gdk.RGBA() { red = 0.5f, green = 1f, blue = 0.5f, alpha = 1f }; + + assert(get_color_at(context)({x: 0, y: 18}).equal(flattened_area_color)); + assert(get_color_at(context)({x: 22, y: 18}).equal(flattened_area_color)); + assert(get_color_at(context)({x: 42, y: 18}).equal(flattened_area_color)); + }); + + Test.add_func("/SmoothLineArea/should_render_a_smooth_line_area_with_plain_line_and_plain_area_region", () => { + //Given + var green = Gdk.RGBA() { red = 0.0f, green = 1.0f, blue = 0.0f, alpha = 1.0f }; + var red = Gdk.RGBA() { red = 1.0f, green = 0f, blue = 0.0f, alpha = 1f }; + var blue = Gdk.RGBA() { red = 0.0f, green = 0f, blue = 1.0f, alpha = 1f }; + + var context = create_context(43, 20); + + var values = new LiveChart.Values(); + values.add({timestamp: (GLib.get_real_time() / 1000) - 7200, value: 5}); + values.add({timestamp: (GLib.get_real_time() / 1000) - 3600, value: 20}); + values.add({timestamp: (GLib.get_real_time() / 1000), value: 5}); + + var line = new LiveChart.SmoothLineArea(values); + line.region = new LiveChart.Region.between(3, 10).with_line_color(red).with_area_color(blue); + line.line.color = green; + line.area_alpha = 0.5f; + + //When + line.draw(context.ctx, create_config(43, 20)); + screenshot(context); + + //Then the curve colors are... + assert(get_color_at(context)({x: 0, y: 14}) == red); + assert(get_color_at(context)({x: 22, y: 0}) == green); + assert(get_color_at(context)({x: 42, y: 14}) == red); + + //And below the curve, color is still a semi-transparent green + var flattened_area_color = Gdk.RGBA() { red = 0.5f, green = 1f, blue = 0.5f, alpha = 1f }; + + assert(get_color_at(context)({x: 0, y: 18}).equal(blue)); + assert(get_color_at(context)({x: 22, y: 18}).equal(flattened_area_color)); + assert(get_color_at(context)({x: 42, y: 18}).equal(blue)); + }); + + Test.add_func("/SmoothLineArea/should_render_a_smooth_line_area_with_semi_transparent_line_and_semi_transparent_area_region", () => { + //Given + var green = Gdk.RGBA() { red = 0.0f, green = 1.0f, blue = 0.0f, alpha = 1.0f }; + var transparent_red = Gdk.RGBA() { red = 1.0f, green = 0f, blue = 0.0f, alpha = 0.5f }; + var transparent_blue = Gdk.RGBA() { red = 0.0f, green = 0f, blue = 1.0f, alpha = 0.5f }; + + var context = create_context(43, 20); + + var values = new LiveChart.Values(); + values.add({timestamp: (GLib.get_real_time() / 1000) - 7200, value: 5}); + values.add({timestamp: (GLib.get_real_time() / 1000) - 3600, value: 20}); + values.add({timestamp: (GLib.get_real_time() / 1000), value: 5}); + + var line = new LiveChart.SmoothLineArea(values); + line.region = new LiveChart.Region.between(3, 10).with_line_color(transparent_red).with_area_color(transparent_blue); + line.line.color = green; + line.area_alpha = 0.5f; + + //When + line.draw(context.ctx, create_config(43, 20)); + screenshot(context); + + //Then the curve colors are... + var flattened_transparent_red = Gdk.RGBA() { red = 1f, green = 0.5f, blue = 0.5f, alpha = 1f }; + + assert(get_color_at(context)({x: 0, y: 14}) == flattened_transparent_red); + assert(get_color_at(context)({x: 22, y: 0}) == green); + assert(get_color_at(context)({x: 42, y: 14}) == flattened_transparent_red); + + //And below the curve, color is still a semi-transparent green + var flattened_area_color = Gdk.RGBA() { red = 0.5f, green = 1f, blue = 0.5f, alpha = 1f }; + var flattened_transparent_blue = Gdk.RGBA() { red = 0.5f, green = 0.5f, blue = 1f, alpha = 1f }; + + message("get_color_at(context)({x: 0, y: 18}) %s", get_color_at(context)({x: 0, y: 18}).to_string()); + assert(get_color_at(context)({x: 0, y: 18}).equal(flattened_transparent_blue)); + assert(get_color_at(context)({x: 22, y: 18}).equal(flattened_area_color)); + assert(get_color_at(context)({x: 42, y: 18}).equal(flattened_transparent_blue)); + }); + + Test.add_func("/SmoothLineArea/should_render_a_smooth_line_area_with_semi_transparent_line_and_plain_area_region", () => { + //Given + var green = Gdk.RGBA() { red = 0.0f, green = 1.0f, blue = 0.0f, alpha = 1.0f }; + var transparent_red = Gdk.RGBA() { red = 1.0f, green = 0f, blue = 0.0f, alpha = 0.5f }; + var blue = Gdk.RGBA() { red = 0.0f, green = 0f, blue = 1.0f, alpha = 1f }; + + var context = create_context(43, 20); + + var values = new LiveChart.Values(); + values.add({timestamp: (GLib.get_real_time() / 1000) - 7200, value: 5}); + values.add({timestamp: (GLib.get_real_time() / 1000) - 3600, value: 20}); + values.add({timestamp: (GLib.get_real_time() / 1000), value: 5}); + + var line = new LiveChart.SmoothLineArea(values); + line.region = new LiveChart.Region.between(3, 10).with_line_color(transparent_red).with_area_color(blue); + line.line.color = green; + line.area_alpha = 0.5f; + + //When + line.draw(context.ctx, create_config(43, 20)); + screenshot(context); + + //Then the curve colors are... + var flattened_transparent_red = Gdk.RGBA() { red = 1f, green = 0.5f, blue = 0.5f, alpha = 1f }; + + assert(get_color_at(context)({x: 0, y: 14}) == flattened_transparent_red); + assert(get_color_at(context)({x: 22, y: 0}) == green); + assert(get_color_at(context)({x: 42, y: 14}) == flattened_transparent_red); + + //And below the curve, color is still a semi-transparent green + var flattened_area_color = Gdk.RGBA() { red = 0.5f, green = 1f, blue = 0.5f, alpha = 1f }; - assert(get_color_at(context)({x: 0, y: 18}).equal(within_region_area_color)); - assert(get_color_at(context)({x: 22, y: 18}).equal(normal_area_color)); - assert(get_color_at(context)({x: 42, y: 18}).equal(within_region_area_color)); + assert(get_color_at(context)({x: 0, y: 18}).equal(blue)); + assert(get_color_at(context)({x: 22, y: 18}).equal(flattened_area_color)); + assert(get_color_at(context)({x: 42, y: 18}).equal(blue)); + }); }); } \ No newline at end of file