diff --git a/backends/x/draw.go b/backends/x/draw.go index c47bc4a..e46d186 100644 --- a/backends/x/draw.go +++ b/backends/x/draw.go @@ -53,7 +53,12 @@ func (backend *Backend) drawCells (forceRedraw bool) (areas []image.Rectangle) { if forceRedraw && content < 32 { continue } areas = append(areas, backend.boundsOfCell(x, y)) - backend.drawRune(x, y, content, cell.Color(), !forceRedraw) + backend.drawRune ( + x, y, + content, + cell.Color(), + cell.Style(), + !forceRedraw) }} if backend.drawBufferBounds && forceRedraw { @@ -74,68 +79,88 @@ func (backend *Backend) drawRune ( x, y int, character rune, runeColor stone.Color, + runeStyle stone.Style, drawBackground bool, ) { // TODO: cache these draws as non-transparent buffers with the // application background color as the background. that way, we won't // need to redraw the characters *or* composite them. - if drawBackground { + var background xgraphics.BGRA + var foreground xgraphics.BGRA + highlight := runeStyle & stone.StyleHighlight > 0 + + if highlight { + background = backend.colors[runeColor] + foreground = backend.colors[stone.ColorBackground] + } else { + background = backend.colors[stone.ColorBackground] + foreground = backend.colors[runeColor] + } + + if drawBackground || highlight { fillRectangle ( - &image.Uniform { - C: backend.config.Color(stone.ColorBackground), - }, + &image.Uniform { C: background }, backend.canvas, backend.boundsOfCell(x, y)) } - if character < 32 { return } - origin := backend.originOfCell(x, y + 1) - destinationRectangle, mask, maskPoint, _, ok := backend.font.face.Glyph ( - fixed.Point26_6 { - X: fixed.I(origin.X), - Y: fixed.I(origin.Y), - }, - character) - if !ok { - strokeRectangle ( - &image.Uniform { - C: backend.config.Color(stone.ColorForeground), + if character >= 32 { + destinationRectangle, mask, maskPoint, _, ok := backend.font.face.Glyph ( + fixed.Point26_6 { + X: fixed.I(origin.X), + Y: fixed.I(origin.Y), }, - backend.canvas, - backend.boundsOfCell(x, y)) - return + character) + + if !ok { + strokeRectangle ( + &image.Uniform { C: foreground }, + backend.canvas, + backend.boundsOfCell(x, y)) + return + } + + if backend.drawCellBounds { + strokeRectangle ( + &image.Uniform { C: foreground }, + backend.canvas, + backend.boundsOfCell(x, y)) + } + + // cue a series of pointless optimizations + alphaMask, isAlpha := mask.(*image.Alpha) + if isAlpha { + backend.sprayRuneMaskAlpha ( + alphaMask, destinationRectangle, + maskPoint, foreground, background) + } else { + backend.sprayRuneMask ( + mask, destinationRectangle, + maskPoint, foreground, background) + } } - if backend.drawCellBounds { - strokeRectangle ( - &image.Uniform { - C: backend.config.Color(stone.ColorForeground), - }, - backend.canvas, - backend.boundsOfCell(x, y)) - } - - // cue a series of pointless optimizations - alphaMask, isAlpha := mask.(*image.Alpha) - if isAlpha { - backend.sprayRuneMaskAlpha ( - alphaMask, destinationRectangle, - maskPoint, backend.colors[runeColor]) - } else { - backend.sprayRuneMask ( - mask, destinationRectangle, - maskPoint, backend.colors[runeColor]) + // underline + if runeStyle & stone.StyleUnderline > 0 { + maxX := origin.X + backend.metrics.cellWidth + y := + origin.Y - + backend.metrics.descent + for x := origin.X; x < maxX; x ++ { + backend.canvas.SetBGRA(x, y, foreground) + } } } func (backend *Backend) sprayRuneMask ( - mask image.Image, - bounds image.Rectangle, - maskPoint image.Point, - fill xgraphics.BGRA, + mask image.Image, + bounds image.Rectangle, + maskPoint image.Point, + fill xgraphics.BGRA, + background xgraphics.BGRA, ) { maxX := bounds.Max.X - bounds.Min.X maxY := bounds.Max.Y - bounds.Min.Y @@ -148,7 +173,7 @@ func (backend *Backend) sprayRuneMask ( x + bounds.Min.X, y + bounds.Min.Y - backend.metrics.descent, xgraphics.BlendBGRA ( - backend.colors[stone.ColorBackground], + background, xgraphics.BGRA { R: fill.R, G: fill.G, @@ -159,10 +184,11 @@ func (backend *Backend) sprayRuneMask ( } func (backend *Backend) sprayRuneMaskAlpha ( - mask *image.Alpha, - bounds image.Rectangle, - maskPoint image.Point, - fill xgraphics.BGRA, + mask *image.Alpha, + bounds image.Rectangle, + maskPoint image.Point, + fill xgraphics.BGRA, + background xgraphics.BGRA, ) { maxX := bounds.Max.X - bounds.Min.X maxY := bounds.Max.Y - bounds.Min.Y @@ -174,7 +200,7 @@ func (backend *Backend) sprayRuneMaskAlpha ( x + bounds.Min.X, y + bounds.Min.Y - backend.metrics.descent, xgraphics.BlendBGRA ( - backend.colors[stone.ColorBackground], + background, xgraphics.BGRA { R: fill.R, G: fill.G, diff --git a/buffer.go b/buffer.go index 1311e5c..669d9e0 100644 --- a/buffer.go +++ b/buffer.go @@ -21,11 +21,11 @@ const ( type Style uint8 const ( - StyleNormal Style = iota - StyleBold Style = iota >> 1 - StyleItalic - StyleUnderline - StyleHighlight + StyleNormal Style = 0 + StyleBold Style = 1 + StyleItalic Style = 2 + StyleUnderline Style = 4 + StyleHighlight Style = 8 StyleBoldItalic Style = StyleBold | StyleItalic )