76 lines · 2.7 KB
// Package overflow answers one question about a rendering: is any of it
// off the side of the screen it was taken for.
//
// A full-page screenshot is captured at the page's own content size, not
// at the viewport's, so a page that scrolls sideways on a phone comes back
// wider than the phone. That number was already in every report and read
// as a size, which is how a card that pushed its status badge off a 390px
// screen sat in thirty-odd screenshots without anyone calling it a bug.
//
// Width alone is not enough to act on, though. An absolutely positioned
// tooltip bubble -- invisible at rest, still counted -- widens a page by
// forty pixels with nothing drawn out there, and a check that reports that
// the same way it reports clipped content is a check that gets ignored. So
// this also says whether anything is actually painted past the edge.
package overflow

import "image"

// Result is what a rendering looks like at its right-hand edge.
type Result struct {
	// Past is how many CSS pixels the rendering extends beyond the
	// viewport. Zero means it fits.
	Past int
	// Ink says whether anything is drawn out there. False means the page
	// scrolls sideways onto blank space: still a bug, but a different and
	// much smaller one than content a person cannot see.
	Ink bool
}

// Overflows reports whether there is anything to say at all.
func (r Result) Overflows() bool { return r.Past > 0 }

// tolerance is how different two pixels in the band must be before one of
// them counts as ink, on the 16-bit scale image.Color uses. A background
// that shades gently across forty pixels is not content; a badge is.
const tolerance = 12 << 8

// Measure compares a rendering against the viewport it was taken for.
//
// scale is the device pixel ratio the shot was captured at, so that this