// Requires visual inspection of stdout func TestMakeFragments(t *testing.T) { const ( w = 20 h = 30 a = 12 b = 14 ) src := MakeAnimation(5, false, 1) dst := nimble.MakePixMap(w, h, make([]nimble.Pixel, w*h), w) background := nimble.RGB(0.5, 0.25, 1) foreground := nimble.RGB(0.25, 1, 0.25) dst.Fill(background) Draw(dst, a, b, src[0], foreground) // Result should be a filled circle for y := int32(0); y < dst.Height(); y++ { for x := int32(0); x < dst.Width(); x++ { r2 := (x-a)*(x-a) + (y-b)*(y-b) var e nimble.Pixel if r2 <= 25 { e = foreground } else { e = background } if e != dst.Pixel(x, y) { t.Fail() panic(fmt.Sprintf("x=%v y=%v e=%v\n", x, y, e)) } } } }
// Get pixels for the kth frame in the animation of the radar. // Frames are constructed lazily to avoid introducing a big delay when the color scheme changes. func getFrame(k int32) []nimble.Pixel { f := frameStorage[k*frameSize : (k+1)*frameSize] if !frameValid[k] { // Need to compute the frame width, height := xSize, ySize // Construct the frame, incorporating "sweep" θ := float32(k)/nFrame*(2*π) - π for i := int32(0); i < height; i++ { for j := int32(0); j < width; j++ { var color nimble.Pixel φ := angle[i*width+j] if φ != outsideUnitCircle { factor := (φ - θ) * (1 / (2 * π)) if factor < 0 { factor += 1 } c := clut[i*width+j] color = nimble.RGB(c.r*factor, c.g*factor, c.b*factor) } else { color = nimble.Black } f[i*width+j] = color } } frameValid[k] = true } return f }
// Init prepares state used by Draw. func Init(width, height int32) { if width < 3 || height < 3 { panic(fmt.Sprintf("score.Init: width=%v height=%v\n", width, height)) } lightWidth = width / 6 lightHeight = height lightStorage = make([]nimble.Pixel, nLight*2*lightHeight*lightWidth) xScale := 2.0 / float32(lightWidth-2) yScale := 2.0 / float32(lightHeight-2) xOffset := -.5 * xScale * float32(lightWidth) yOffset := -.5 * yScale * float32(lightHeight) for k, color := range lightColor { for s := state(0); s < state(2); s++ { pm := nimble.MakePixMap(lightWidth, lightHeight, getLight(k, s), lightWidth) for i := int32(0); i < lightHeight; i++ { for j := int32(0); j < lightWidth; j++ { x := float32(j)*xScale + xOffset y := float32(i)*yScale + yOffset factor := 1 - x*x - y*y if factor < 0 { factor = 0 } if s == 0 { // The light is off, so dim the image factor *= .25 } pm.SetPixel(j, i, nimble.RGB(color.r*factor, color.g*factor, color.b*factor)) } } } } }
func fontColor() []nimble.Pixel { c := make([]nimble.Pixel, 32) for i := range c { green := (math32.Exp(-float32(i)*.2) + 0.5) * (2. / 3.) // Classic version had 0.5 for red red := (math32.Exp(-float32(i) * .4)) * 0.4 c[i] = nimble.RGB(red, green, 0) } return c }
// PastelPalette returns a palette of pastel colors. // The pallette is returned as a PixMap with one row for each hue, // which fades to black with increasing column indices. func PastelPalette(nHue, nShade int32) (pm nimble.PixMap) { pm = nimble.MakePixMap(nShade, nHue, make([]nimble.Pixel, nHue*nShade), nShade) for h := int32(0); h < nHue; h++ { r, g, b := rgbOfHue(h, nHue) scale := 1 / float32(nShade) row := pm.Row(h) for j := int32(0); j < nShade; j++ { f := float32(nShade-j) * scale row[j] = nimble.RGB(r*f, g*f, b*f) } } return }
// setColoring sets the CLUT to given colorMap. func setColoring(cm colorMap) { if cm == currentMap { return } currentMap = cm for i := range clut { y := clutCoor(i) for j := range clut[i] { x := clutCoor(j) clut[i][j] = nimble.RGB(cm.Color(x, y)) } } }
package menu import ( "github.com/ArchRobison/Gophetica/nimble" ) var ( foregroundColor = nimble.Black disabledForegroundColor = nimble.Gray(0.5) backgroundColor = nimble.White itemHilightColor = nimble.RGB(0.875, 0.875, 1) tabHilightColor = nimble.RGB(0, 0, 1) separatorColor = nimble.Gray(0.75) ) var menuFont, checkFont *nimble.Font // Each "item" row of the menu is drawn as: // | margin checkWidth margin | margin itemWidth margin | var ( checkWidth int32 // Width of "check" column (not including margins) marginWidth int32 // Margin in pixels between text and border ) // Return b ? p : q func choose(b bool, p, q nimble.Pixel) nimble.Pixel { if b { return p } else { return q }