Skip to content
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

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open

WIP: cops-ified view system #31

wants to merge 11 commits into from

Conversation

jcorbin
Copy link
Contributor

@jcorbin jcorbin commented Dec 14, 2017

No description provided.

@jcorbin
Copy link
Contributor Author

jcorbin commented Dec 14, 2017

Mostly past lint, only deathroom remains; then onto the view test failures.

The difficult part is the view.Grid => display.Display conversion...

@@ -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.
Copy link
Member

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.

if t != "" {
d.Text.Strings[i] = t
}
if f.A < 0xff {
Copy link
Member

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 {
Copy link
Member

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 {
Copy link
Member

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.


// 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 {
Copy link
Member

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.

Copy link
Contributor Author

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()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ll take *T.

Copy link
Contributor Author

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.

@@ -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)
Copy link
Member

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?

Copy link
Contributor Author

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

dm.buf = dm.buf[:copy(dm.buf[:m], dm.buf[n:])]
} else {
dm.buf = dm.buf[:0]
for attempts > 1 && err == io.ErrShortWrite {
Copy link
Member

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 :|

Copy link
Contributor Author

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

Copy link
Member

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.

@jcorbin
Copy link
Contributor Author

jcorbin commented Dec 19, 2017

Remaining display warts:

  • world grid smearing between frames; not even sure if it's a rendering or display drawing problem
  • something's still broken with color handling as you can see with Add a testpattern proof #37

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants