Documentation ¶
Overview ¶
Package frame provides plan9-like editable text images on a raster display. This implementation preserves NUL bytes, and uses a set of replacement characters for unrenderable text glyphs generated with a smaller sized font (hexadecimal or ascii representation).
A frame's text is not addressable. Once the characters are written to the frame, there is no mechanism to retrieve their position from within the frame. Use a buffer to store text for reading and the range addresses of the frame to access bytes from that buffer.
See github.com/as/ui/win for an example.
A frame is created using the New function
img := image.NewRGBA(image.Rect(0,0,100,100)) fr := frame.New(img, img.Bounds(), frame.NewGoMono(), frame.Mono)
A frame supports these common operations
Insert: Insert text Delete: Delete text IndexOf: Index for point PointOf: Point for index Select: Select range Dot: Return selected range
Insert and Delete ¶
Frames supports two operations for rendering text: Insert and Delete. Insert inserts text at the given index and moves existing characters after the index to the right. Delete deletes text in the given range (a range is a pair of indices) and moves existing character after the index to the left.
The two operations are inverses of each other.
fr.Insert([]byte("hello world."), 0) fr.Delete(0, 11)
Insert and delete return the number of characters inserted or deleted.
To delete the last insertion:
p0 := 0 n := fr.Insert([]byte("123"), p0) fr.Delete(p0, p0+n)
To execute a traditional "write" operation:
s := []byte("hello") fr.Delete(0, int64(len(s))) fr.Insert(s, 0)
Projection ¶
Frames can translate between coordinates of the mouse and character offsets in the frame itself using IndexOf and PointOf.
p0 := fr.IndexOf(image.Pt(0, 0)) // Returns the index under the 2D point (0,0) pt0 := fr.PointOf(5) // Returns the 2D point over the index
Selection ¶
Frames support selecting ranges of text along with returning those selected ranges.
fr.Select(p0, p1) fr.Dot()
A more complicated facility exists for making a live selection. See example/basic for an example of how to use it.
fr.Sweep(...)
Drawing ¶
No special operations are needed after a call to Insert, Delete, or Select. The frame's bitmap is updated. However, there are four functions that will redraw the frame on the bitmap if this is necessary.
Recolor(pt image.Point, p0, p1 int64, cols Palette)
Recolor colors the range p0:p1 by redrawing the foreground, background, and font glyphs
Redraw(pt image.Point, p0, p1 int64, issel bool)
Redraw redraws the characters between p0:p1. It accesses the cache of drawn glyph widths to avoid remeasuring strings
RedrawAt(pt image.Point, text, back image.Image)
RedrawAt refreshes the entire image to the right of the given pt. Everything below is redrawn.
Refresh()
Refresh recomputes the state of the frame from scratch. This is an expensive operation compared to redraw
Display Sync ¶
After any operation that alters the frame, one can be sure that the changes can be written to the frame's bitmap. However, the same can not be said for the exp/shiny window. There currently exists an optimization (see github.com/as/drawcache) that caches rectangles that need to be redrawn to the screen. This is because shiny (or the native drivers for it) are too slow to refresh the entire window is that window's resolution is very high.
This rendering pipeline is bottlenecked, so an optimization is located between the |*|
insert | frame | shiny buffer |*| shiny window
Index ¶
- Constants
- Variables
- func Printable(b byte) bool
- type Color
- type Config
- type Drawer
- type EventPipe
- type Frame
- func (f *Frame) Bounds() image.Rectangle
- func (f *Frame) Close() error
- func (f *Frame) Config() *Config
- func (f *Frame) Delete(p0, p1 int64) int
- func (f *Frame) Dirty() bool
- func (f *Frame) Dot() (p0, p1 int64)
- func (f *Frame) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point, op draw.Op)
- func (f *Frame) Flags() int
- func (f *Frame) Full() bool
- func (f *Frame) Grid(pt image.Point) image.Point
- func (f *Frame) IndexOf(pt image.Point) (p int64)
- func (f *Frame) Insert(s []byte, p0 int64) (wrote int)
- func (f *Frame) Len() int64
- func (f *Frame) Line() int
- func (f *Frame) Mark()
- func (f *Frame) MaxLine() int
- func (f *Frame) Paint(p0, p1 image.Point, col image.Image)
- func (f *Frame) PointOf(p int64) image.Point
- func (f *Frame) RGBA() *image.RGBA
- func (f *Frame) Recolor(pt image.Point, p0, p1 int64, cols Palette)
- func (f *Frame) Redraw(pt image.Point, p0, p1 int64, issel bool)
- func (f *Frame) RedrawAt(pt image.Point, text, back image.Image)
- func (f *Frame) Refresh()
- func (f *Frame) Reset(r image.Rectangle, b *image.RGBA, ft font.Face)
- func (f *Frame) Select(p0, p1 int64)
- func (f *Frame) SetDirty(dirty bool)
- func (f *Frame) SetFlags(flags int)
- func (f *Frame) SetFont(ft font.Face)
- func (f *Frame) SetOp(op draw.Op)
- func (f *Frame) SetTick(style int)
- func (f *Frame) Size() image.Point
- func (f *Frame) Sweep(ep EventPipe, flush func())
- func (f *Frame) Tick()
- func (f *Frame) Untick()
- type Palette
- type Projector
- type ScrollEvent
- type Selector
- type Sweeper
Constants ¶
const ( FrElastic = 1 << iota FrUTF8 )
const ( TickOff = 0 TickOn = 1 )
Variables ¶
var ( Yellow = solid(255, 255, 224) Green = solid(0x99, 0xCC, 0x99) Red = solid(0xCC, 0x99, 0x99) Gray = solid(0x12, 0x12, 0x12) Mauve = solid(0x99, 0x99, 0xDD) Ozone = solid(216, 216, 232) Strata = solid(248, 242, 248) AntiPeach = solid(0, 12, 24) Peach = solid(255, 248, 232) BBody = solid(243, 248, 254) BTag = solid(214, 230, 252) GBody = solid(226, 235, 232) GTag = solid(226, 225, 232) PTag = solid(222, 207, 236) PBody = solid(252, 232, 252) MMauve = solid(0x66, 0x55, 0x88) MTagG = solid(28-10, 31-13, 38-15) MTagC = MTagW MTagW = solid(28, 31, 38) MBodyW = solid(43, 50, 59) MTextW = solid(255-59, 255-50, 255-43) )
var ( Acme = Color{ Palette: Palette{Text: Gray, Back: Yellow}, Hi: Palette{Text: image.White, Back: Mauve}, } Mono = Color{ Palette: Palette{Text: image.Black, Back: image.White}, Hi: Palette{Text: image.White, Back: image.Black}, } A = Color{ Palette: Palette{ Text: AntiPeach, Back: Peach, }, Hi: Palette{ Back: Mauve, Text: image.White, }, } ATag0 = Color{ Palette: Palette{ Text: Gray, Back: Ozone, }, Hi: Palette{ Back: Mauve, Text: image.White, }, } ATag1 = Color{ Palette: Palette{ Text: Gray, Back: Strata, }, Hi: Palette{ Back: Mauve, Text: image.White, }, } )
var ( ForceElastic bool ForceUTF8 bool )
var (
ErrBadDst = errors.New("bad dst")
)
Functions ¶
Types ¶
type Drawer ¶
type Drawer interface { Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point, op draw.Op) // StringBG draws a string to dst at point p StringBG(dst draw.Image, p image.Point, src image.Image, sp image.Point, ft font.Face, s []byte, bg image.Image, bgp image.Point) int // Flush requests that prior calls to the draw and string methods are flushed from an underlying soft-screen. The list of rectangles provide // optional residency information. Implementations may refresh a superset of r, or ignore it entirely, as long as the entire region is // refreshed Flush(r ...image.Rectangle) error }
Drawer implements the set of methods a frame needs to draw on a draw.Image. The frame's default behavior is to use the native image/draw package and x/exp/font packages to satisfy this interface.
func NewDefaultDrawer ¶
func NewDefaultDrawer() Drawer
type EventPipe ¶
type EventPipe interface { Send(e interface{}) SendFirst(e interface{}) NextEvent() interface{} }
type Frame ¶
type Frame struct { box.Run Face Face Color Ticked bool Scroll func(int) Drawer // contains filtered or unexported fields }
Frame is a write-only container for editable text
func (*Frame) Delete ¶
Delete deletes the range [p0:p1) and returns the number of characters deleted
func (*Frame) Dirty ¶
Dirty returns true if the contents of the frame have changes since the last redraw
func (*Frame) Insert ¶
Insert inserts the contents of s at index p0 in the frame and returns the number of characters written.
func (*Frame) Paint ¶
Paint paints the color col on the frame at points pt0-pt1. The result is a Z shaped fill consisting of at-most 3 rectangles. No text is redrawn.
func (*Frame) Refresh ¶
func (f *Frame) Refresh()
Refresh renders the entire frame, including the underlying bitmap. Refresh should not be called after insertion and deletion unless the frame's RGBA bitmap was painted over by another draw operation.
func (*Frame) Select ¶
Select selects the region [p0:p1). The operation highlights the range of text under that region. If p0 = p1, a tick is drawn to indicate a null selection.
func (*Frame) SetFlags ¶
Flag sets the flags for the frame. At this time only FrElastic is supported.
type ScrollEvent ¶
type ScrollEvent struct { }