-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: cops-ified view system #31
base: master
Are you sure you want to change the base?
Conversation
Mostly past lint, only deathroom remains; then onto the view test failures. The difficult part is the |
@@ -92,6 +98,30 @@ func (d *Display) SetRGBA(x, y int, t string, f, b color.RGBA) { | |||
} | |||
} | |||
|
|||
// MergeRGBA sets the given string and colors if they are | |||
// non-empty and not transparent respectively. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For least surprise, I expect this method to be behaviorally equivalent to:
mini := display.New(image.Rect(0, 0, 1, 1))
mini.Set(0, 0, t, f, b)
display.Draw(d, image.Rect(x, y, x + 1, y + 1), mini, image.ZP, draw.Over)
That accounts for the opacity of the foreground and background, over the underlying foreground and background, replacing text only if there’s text. Would be a good way to validate this method.
The tricky part is nontrivial alpha values. It is certainly possible to borrow the algorithm from "image/draw". See the inner loop of drawNRGBAOver
.
I’m fine with adding the method with a partial implementation, provided it can grow into this behavior.
internal/cops/display/display.go
Outdated
if t != "" { | ||
d.Text.Strings[i] = t | ||
} | ||
if f.A < 0xff { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe you mean to do full replacement when the opacity is 1.0, not less than 1.0, do nothing when opacity is 0. I would like to go all the way and implement blending for intermediate values.
I’ll note that display.Draw takes into account the non-obvious case of blending the top background color over the underlying foreground, which causes the underlying text to fade into the background. See the hicops
example for the visual effect.
draw.Draw(dst.Background, r, src.Background, sp, op)
draw.Draw(dst.Foreground, r, src.Background, sp, op)
draw.Draw(dst.Foreground, r, src.Foreground, sp, op)
textile.Draw(dst.Text, r, src.Text, sp)
// returning how many cells were affected. | ||
// | ||
// NOTE does not support multi-rune glyphs | ||
func (d *Display) WriteString(x, y int, f, b color.Color, mess string, args ...interface{}) int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ve used msg
elsewhere, stylewise. Three letter abbreviations are emerging as an aesthetic with this library, buf
, cur
, dis
(now that we don’t distinguish front
and back
in usage).
// string and the diplay). | ||
// | ||
// NOTE does not support multi-rune glyphs | ||
func (d *Display) WriteStringRTL(x, y int, f, b color.Color, mess string, args ...interface{}) int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you might mean RightAlign. RTL implies the Semitic mode.
internal/cops/display/display.go
Outdated
|
||
// Lines returns a slice of row strings from the display, filling in any zero | ||
// runes with the given one. | ||
func (d *Display) Lines(fillZero string) []string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is fillZero ever not space? I can only imagine the case where a display is composited over a background of uniform text.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is used only as a test convenience utility; so maybe will punt it to an ancillary test package. In testing circumstances, I have occasionally found it useful to fill with some obvious glyph to differentiate "explicit space".
@@ -19,6 +19,8 @@ type Terminal struct { | |||
|
|||
// New returns a Terminal for the given file descriptor, capable of restoring | |||
// that terminal to its current state. | |||
// | |||
// FIXME New() *T; value can be Make() T or T.Init() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ll take *T.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, the T.Init()
form is chiefly useful when embedding is your use case; e.g. how internal/ecs
makes heavy use of that convention.
internal/view/view.go
Outdated
@@ -69,7 +68,7 @@ func (dm *displayModel) Close() error { | |||
func (dm *displayModel) updateSize() error { | |||
bounds, err := dm.term.Bounds() | |||
if err == nil { | |||
dm.Display = display.New(bounds) | |||
dm.dis = display.New(bounds) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of a (*Display)Resize(Rectangle)*Display method that reallocates if necessary, reuses if possible, on the append
precedent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would love it, meant to drop a TODO about it; only been avoiding due to scope
internal/view/view.go
Outdated
dm.buf = dm.buf[:copy(dm.buf[:m], dm.buf[n:])] | ||
} else { | ||
dm.buf = dm.buf[:0] | ||
for attempts > 1 && err == io.ErrShortWrite { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, look what you found :|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, once I get through this PR I want to holistically benchmark rendering, evaluating things like:
- whether isolating Display => buf rendering from client rendering and input processing (by putting it in a dedicated goroutine and renditioning displays with it is worth it ; probably)
- whether / when differential rendeing is worth it from an stime / syscall perspective vs the couple millisecond utime hit; especially once that couple ms is parallelizable per prior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ought to take this and see if it fixes whole pages of family of four.
20df38f
to
f7e34da
Compare
Remaining display warts:
|
No description provided.