Skip to content

Commit

Permalink
Improve gradient speed by skipping off-canvas lines.
Browse files Browse the repository at this point in the history
  • Loading branch information
Erik Corry committed Dec 13, 2023
1 parent 80ed947 commit 0616e85
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/element.toit
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ abstract class CustomElement extends ClippingDiv_:
change-tracker.child-invalidated x y w h

draw canvas/Canvas -> none:
if not (x and y): return
if not (x and y and w and h): return
analysis := canvas.bounds-analysis x y w h
if analysis == Canvas.DISJOINT: return
autoclipped := analysis == Canvas.CANVAS-IN-AREA or analysis == Canvas.COINCIDENT
Expand Down
31 changes: 19 additions & 12 deletions src/gradient.toit
Original file line number Diff line number Diff line change
Expand Up @@ -243,14 +243,16 @@ class GradientRendering_:
// Use fixed point with 16 bits after the decimal point.
step := ((texture-length_ - h) << 16) / w
offset := 0
for i := 0; i < w; i += repeats:
lines := min repeats (w - i)
skew-adjusted-y := update-r-g-b-block.call y2 h lines orientation offset
if canvas.gray-scale:
canvas.pixmap (i + x2) skew-adjusted-y --pixels=b --source-width=source-width --orientation=orientation
else:
canvas.rgb-pixmap (i + x2) skew-adjusted-y --r=r --g=g --b=b --source-width=source-width --orientation=orientation
offset += step
canvas.visible-x-range x2 w: | x3 r3 |
offset += step * (x3 - x2)
for i := x3; i < r3; i += repeats:
lines := min repeats (r3 - i)
skew-adjusted-y := update-r-g-b-block.call y2 h lines orientation offset
if canvas.gray-scale:
canvas.pixmap i skew-adjusted-y --pixels=b --source-width=source-width --orientation=orientation
else:
canvas.rgb-pixmap i skew-adjusted-y --r=r --g=g --b=b --source-width=source-width --orientation=orientation
offset += step
else:
// The gradient goes broadly horizontally, and we draw in horizontal
// strips.
Expand All @@ -260,15 +262,20 @@ class GradientRendering_:
loop-body := : | i lines |
skew-adjusted-x := update-r-g-b-block.call x w lines ORIENTATION-0 offset
if canvas.gray-scale:
canvas.pixmap skew-adjusted-x (i + y) --pixels=b --source-width=source-width
canvas.pixmap skew-adjusted-x i --pixels=b --source-width=source-width
else:
canvas.rgb-pixmap skew-adjusted-x (i + y) --r=r --g=g --b=b --source-width=source-width
canvas.rgb-pixmap skew-adjusted-x i --r=r --g=g --b=b --source-width=source-width
offset += step
if up:
for i := 0; i < h; i += repeats: loop-body.call i (min repeats (h - i))
canvas.visible-y-range y (y + h): | y3 b3 |
offset += step * (y3 - y)
for i := y3; i < b3; i += repeats: loop-body.call i (min repeats (b3 - i))
else:
assert: repeats == 1
for i := h - 1; i >= 0; i--: loop-body.call i 1
b2 := y + h - 1
canvas.visible-y-range y b2: | y3 b3 |
offset += step * (b2 - b3)
for i := b3; i >= y3; i--: loop-body.call i 1

/// Returns a list of quadruples of the form starting-percent ending-percent start-color end-color.
static extract-ranges_ specifiers/List -> List:
Expand Down
12 changes: 12 additions & 0 deletions src/pixel-display.toit
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,18 @@ abstract class Canvas:
if x2 <= 0 and y2 <= 0 and right >= width_ and bottom >= height_: return CANVAS-IN-AREA
return OVERLAP

visible-x-range x/int w/int [block] -> none:
transform.invert.xywh 0 0 width_ + 1 height_ + 1: | x2 _ w2 _ |
block.call
max x x2
min (x + w) (x2 + w2)

visible-y-range y/int h/int [block] -> none:
transform.invert.xywh 0 0 (width_ + 1) (height_ + 1): | _ y2 _ h2 |
block.call
max y y2
min (y + h) (y2 + h2)

/**
Constant to indicate that all pixels are transparent.
For use with $composit.
Expand Down

0 comments on commit 0616e85

Please sign in to comment.