perf(charts): fill chart areas in one linear pass
The filled sparklines and the market price chart built their area fill with PathFillConcave, which runs a per-scanline pass over the whole filled region. For a simple area under an x-monotone curve that work is unnecessary. - A new helper fills the area between an x-monotone polyline and a horizontal baseline directly as a triangle strip, in one pass over the points. The market sparklines, the market price chart and the mining hashrate sparkline all use it. The fill is flat and non-anti-aliased; the anti-aliased curve drawn on top hides the stepped top edge, and the faint side and bottom edges are imperceptible at these alphas. Tests: the strip's vertex and index counts, index bounds, and that its triangle area matches the trapezoid area under the polyline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -73,6 +73,7 @@
|
||||
#include "ui/effects/border_sampling.h"
|
||||
#include "ui/effects/capture_extent.h"
|
||||
#include "ui/material/rect_cull.h"
|
||||
#include "ui/material/fill_strip.h"
|
||||
#include "ui/notifications.h"
|
||||
#include "data/seed_migration_resume.h"
|
||||
#include "data/pin_vault_policy.h"
|
||||
@@ -18020,6 +18021,23 @@ void testBootstrapCompletion()
|
||||
}
|
||||
}
|
||||
|
||||
void testFillStrip() {
|
||||
using namespace dragonx::ui::material;
|
||||
EXPECT_EQ(FillStripVertexCount(1), 0); EXPECT_EQ(FillStripIndexCount(1), 0);
|
||||
EXPECT_EQ(FillStripVertexCount(5), 10); EXPECT_EQ(FillStripIndexCount(5), 24);
|
||||
unsigned idx[24]; BuildFillStripIndices(5, 100, idx);
|
||||
for (int i = 0; i < 24; ++i) EXPECT_TRUE(idx[i] >= 100 && idx[i] < 110);
|
||||
// area under the polyline == sum of triangle areas (trapezoid rule)
|
||||
ImVec2 p[5] = {{0,5},{10,2},{20,8},{30,3},{40,7}}; const float baseY = 10.0f; float tri = 0, trap = 0;
|
||||
ImVec2 v[10]; for (int i = 0; i < 5; ++i) { v[2*i] = p[i]; v[2*i+1] = ImVec2(p[i].x, baseY); }
|
||||
for (int t = 0; t < 8; ++t) {
|
||||
ImVec2 a = v[idx[3*t]-100], b = v[idx[3*t+1]-100], c = v[idx[3*t+2]-100];
|
||||
tri += 0.5f * std::fabs((b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y));
|
||||
}
|
||||
for (int i = 0; i + 1 < 5; ++i) trap += (p[i+1].x - p[i].x) * ((baseY-p[i].y) + (baseY-p[i+1].y)) * 0.5f;
|
||||
EXPECT_NEAR(tri, trap, 1e-3f);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
@@ -18289,6 +18307,7 @@ int main()
|
||||
testEffectClock();
|
||||
testBorderSampling();
|
||||
testRectCull();
|
||||
testFillStrip();
|
||||
testFormatFeePercent();
|
||||
testPoolWeightedSelection();
|
||||
testCoalescingWriter();
|
||||
|
||||
Reference in New Issue
Block a user