func drawsq(b draw.Image, p image.Point, ptx int) { var r image.Rectangle r.Min = p r.Max.X = r.Min.X + pcsz r.Max.Y = r.Min.Y + pcsz draw.Draw(b, r, image.Black, image.ZP) draw.Draw(b, r.Inset(1), txpix[ptx], image.ZP) }
func drawsq(b *draw.Image, p image.Point, ptx int) { var r image.Rectangle r.Min = p r.Max.X = r.Min.X + pcsz r.Max.Y = r.Min.Y + pcsz b.Draw(r, display.Black, nil, image.ZP) b.Draw(r.Inset(1), tx[ptx], nil, image.ZP) }
func setpiece(p *Piece) { bb.Draw(bb.R, display.White, nil, image.ZP) bbmask.Draw(bb.R, display.Transparent, nil, image.ZP) br = image.Rect(0, 0, 0, 0) br2 = br piece = p if p == nil { return } var op image.Point var r image.Rectangle r.Min = bb.R.Min for i, pt := range p.d { r.Min.X += pt.X * pcsz r.Min.Y += pt.Y * pcsz r.Max.X = r.Min.X + pcsz r.Max.Y = r.Min.Y + pcsz if i == 0 { bb.Draw(r, display.Black, nil, image.ZP) bb.Draw(r.Inset(1), tx[piece.tx], nil, image.ZP) bbmask.Draw(r, display.Opaque, nil, image.ZP) op = r.Min } else { bb.Draw(r, bb, nil, op) bbmask.Draw(r, bbmask, nil, op) } if br.Max.X < r.Max.X { br.Max.X = r.Max.X } if br.Max.Y < r.Max.Y { br.Max.Y = r.Max.Y } } br.Max = br.Max.Sub(bb.R.Min) delta := image.Pt(0, DY) br2.Max = br.Max.Add(delta) r = br.Add(bb2.R.Min) r2 := br2.Add(bb2.R.Min) bb2.Draw(r2, display.White, nil, image.ZP) bb2.Draw(r.Add(delta), bb, nil, bb.R.Min) bb2mask.Draw(r2, display.Transparent, nil, image.ZP) bb2mask.Draw(r, display.Opaque, bbmask, bb.R.Min) bb2mask.Draw(r.Add(delta), display.Opaque, bbmask, bb.R.Min) }
func setpiece(p *Piece) { draw.Draw(bb, bbr, image.White, image.ZP) draw.Draw(bbmask, bbr, image.Transparent, image.ZP) br = image.Rect(0, 0, 0, 0) br2 = br piece = p if p == nil { return } var op image.Point var r image.Rectangle r.Min = bbr.Min for i, pt := range p.d { r.Min.X += pt.X * pcsz r.Min.Y += pt.Y * pcsz r.Max.X = r.Min.X + pcsz r.Max.Y = r.Min.Y + pcsz if i == 0 { draw.Draw(bb, r, image.Black, image.ZP) draw.Draw(bb, r.Inset(1), txpix[piece.tx], image.ZP) draw.Draw(bbmask, r, image.Opaque, image.ZP) op = r.Min } else { draw.Draw(bb, r, bb, op) draw.Draw(bbmask, r, bbmask, op) } if br.Max.X < r.Max.X { br.Max.X = r.Max.X } if br.Max.Y < r.Max.Y { br.Max.Y = r.Max.Y } } br.Max = br.Max.Sub(bbr.Min) delta := image.Pt(0, DY) br2.Max = br.Max.Add(delta) r = br.Add(bb2r.Min) r2 := br2.Add(bb2r.Min) draw.Draw(bb2, r2, image.White, image.ZP) draw.Draw(bb2, r.Add(delta), bb, bbr.Min) draw.Draw(bb2mask, r2, image.Transparent, image.ZP) draw.DrawMask(bb2mask, r, image.Opaque, bbr.Min, bbmask, image.ZP, draw.Over) draw.DrawMask(bb2mask, r.Add(delta), image.Opaque, bbr.Min, bbmask, image.ZP, draw.Over) }
// Returns a sub-image of the input image. The bounding rectangle is the // smallest possible rectangle that includes all pixels that have alpha > 0, // with one pixel of border on all sides. func minimalSubImage(src image.Image) *subImage { bounds := src.Bounds() var new_bounds image.Rectangle new_bounds.Max = bounds.Min new_bounds.Min = bounds.Max for x := bounds.Min.X; x <= bounds.Max.X; x++ { for y := bounds.Min.Y; y <= bounds.Max.Y; y++ { c := src.At(x, y) _, _, _, a := c.RGBA() if a > 0 { if x < new_bounds.Min.X { new_bounds.Min.X = x } if y < new_bounds.Min.Y { new_bounds.Min.Y = y } if x > new_bounds.Max.X { new_bounds.Max.X = x } if y > new_bounds.Max.Y { new_bounds.Max.Y = y } } } } // // We want one row/col of boundary between characters so that we don't get // // annoying artifacts new_bounds.Min.X-- new_bounds.Min.Y-- new_bounds.Max.X++ new_bounds.Max.Y++ if new_bounds.Min.X > new_bounds.Max.X || new_bounds.Min.Y > new_bounds.Max.Y { new_bounds = image.Rect(0, 0, 0, 0) } return &subImage{src, new_bounds} }
// Add finds a position for the given image in the atlas and copies the image // there. It returns the new sub-image. If there is no more space in the atlas, // it returns an error. func (a *Atlas) Add(id string, img image.Image) (SubImage, error) { // determine the position of the new image rect, err := a.packer.Insert(img.Bounds().Dx(), img.Bounds().Dy()) if err != nil { return SubImage{}, errors.New("unable to add image to atlas: " + err.Error()) } var bounds image.Rectangle bounds.Min = a.Image.Bounds().Min.Add(image.Pt(rect.X, rect.Y)) bounds.Max = bounds.Min.Add(image.Pt(rect.Width, rect.Height)) // copy the image data into the atlas draw.Draw(a.Image, bounds, img, img.Bounds().Min, draw.Src) sub := SubImage{ Image: subImage{ a.Image, bounds, }, ID: id, } a.SubImages = append(a.SubImages, sub) return sub, nil }
func (f *Frame) Insert(r []rune, p0 uint64) { if p0 > uint64(f.nchars) || len(r) == 0 || f.Background == nil { return } var rect image.Rectangle var col, tcol *draw.Image pts := make([]points, 0) n0 := f.findbox(0, 0, p0) cn0 := p0 nn0 := n0 pt0 := f.ptofcharnb(p0, n0) ppt0 := pt0 opt0 := pt0 pt1 := f.bxscan(r, &ppt0) ppt1 := pt1 b := f.box[n0] if n0 < f.nbox { f.cklinewrap(&pt0, b) f.cklinewrap0(&ppt1, b) } f.modified = true /* * ppt0 and ppt1 are start and end of insertion as they will appear when * insertion is complete. pt0 is current location of insertion position * (p0); pt1 is terminal point (without line wrap) of insertion. */ if f.p0 == f.p1 { f.Tick(f.Ptofchar(f.p0), false) } /* * Find point where old and new x's line up * Invariants: * pt0 is where the next box (b, n0) is now * pt1 is where it will be after the insertion * If pt1 goes off the rectangle, we can toss everything from there on */ npts := 0 for ; pt1.X != pt0.X && pt1.Y != f.Rect.Max.Y && n0 < f.nbox; npts++ { b := f.box[n0] f.cklinewrap(&pt0, b) f.cklinewrap0(&pt1, b) if b.Nrune > 0 { n, fits := f.canfit(pt1, b) if !fits { panic("frame.canfit == 0") } if n != b.Nrune { f.splitbox(uint64(n0), uint64(n)) b = f.box[n0] } } if npts == nalloc { pts = append(pts, make([]points, npts+DELTA)...) nalloc += DELTA b = f.box[n0] } pts[npts].pt0 = pt0 pts[npts].pt1 = pt1 if pt1.Y == f.Rect.Max.Y { break } f.advance(&pt0, b) pt1.X += f.newwid(pt1, b) cn0 += uint64(nrune(b)) n0++ } if pt1.Y > f.Rect.Max.Y { panic("frame.Insert pt1 too far") } if pt1.Y == f.Rect.Max.Y && n0 < f.nbox { f.nchars -= f.strlen(n0) f.delbox(n0, f.nbox-1) } if n0 == f.nbox { div := f.Font.Height if pt1.X > f.Rect.Min.X { div++ } f.nlines = (pt1.Y - f.Rect.Min.Y) / div } else if pt1.Y != pt0.Y { y := f.Rect.Max.Y q0 := pt0.Y + f.Font.Height q1 := pt1.Y + f.Font.Height f.nlines += (q1 - q0) / f.Font.Height if f.nlines > f.maxlines { f.chop(ppt1, p0, nn0) } if pt1.Y < y { rect = f.Rect rect.Min.Y = q1 rect.Max.Y = y if q1 < y { f.Background.Draw(rect, f.Background, nil, image.Pt(f.Rect.Min.X, q0)) } rect.Min = pt1 rect.Max.X = pt1.X + (f.Rect.Max.X - pt0.X) rect.Max.Y += q1 f.Background.Draw(rect, f.Background, nil, pt0) } } /* * Move the old stuff down to make room. The loop will move the stuff * between the insertion and the point where the x's lined up. * The draw()s above moved everything down after the point they lined up. */ y := 0 if pt1.Y == f.Rect.Max.Y { y = pt1.Y } for n0 = n0 - 1; npts >= 0; n0-- { b := f.box[n0] pt := pts[npts].pt1 if b.Nrune > 0 { rect.Min = pt rect.Max = rect.Min rect.Max.X += b.Wid rect.Max.Y += f.Font.Height f.Background.Draw(rect, f.Background, nil, pts[npts].pt0) /* clear bit hanging off right */ if npts == 0 && pt.Y > pt0.Y { rect.Min = opt0 rect.Max = opt0 rect.Max.X = f.Rect.Max.X rect.Max.Y += f.Font.Height if f.p0 <= cn0 && cn0 < f.p1 { /* b+1 is inside selection */ col = f.Cols[colHigh] } else { col = f.Cols[colBack] } f.Background.Draw(rect, col, nil, rect.Min) } else if pt.Y < y { rect.Min = pt rect.Max = pt rect.Min.X += b.Wid rect.Max.X = f.Rect.Max.X rect.Max.Y += f.Font.Height if f.p0 <= cn0 && cn0 < f.p1 { col = f.Cols[colHigh] } else { col = f.Cols[colBack] } f.Background.Draw(rect, col, nil, rect.Min) } y = pt.Y cn0 -= uint64(b.Nrune) } else { rect.Min = pt rect.Max = pt rect.Max.X += b.Wid rect.Max.Y += f.Font.Height if rect.Max.X >= f.Rect.Max.X { rect.Max.X = f.Rect.Max.X } cn0-- if f.p0 <= cn0 && cn0 < f.p1 { col = f.Cols[colHigh] tcol = f.Cols[colHText] } else { col = f.Cols[colBack] tcol = f.Cols[colText] } f.Background.Draw(rect, col, nil, rect.Min) y = 0 if pt.X == f.Rect.Min.X { y = pt.Y } } } if f.p0 < p0 && p0 <= f.p1 { col = f.Cols[colHigh] tcol = f.Cols[colHText] } else { col = f.Cols[colBack] tcol = f.Cols[colText] } f.SelectPaint(ppt0, ppt1, col) f.DrawText(ppt0, tcol, col) f.addbox(uint64(nn0), uint64(frame.nbox)) for n := 0; n < frame.nbox; n++ { f.box[nn0+n] = frame.box[n] } if nn0 > 0 && f.box[nn0-1].Nrune >= 0 && ppt0.X-f.box[nn0-1].Wid >= f.Rect.Min.X { nn0-- ppt0.X -= f.box[nn0].Wid } n0 += frame.nbox if n0 < f.nbox-1 { n0++ } f.clean(ppt0, nn0, n0) f.nchars += frame.nchars if f.p0 >= p0 { f.p0 += uint64(frame.nchars) } if f.p0 >= uint64(f.nchars) { f.p0 = uint64(f.nchars) } if f.p1 >= p0 { f.p1 += uint64(frame.nchars) } if f.p1 >= uint64(f.nchars) { f.p1 += uint64(f.nchars) } if f.p0 == f.p1 { f.Tick(f.Ptofchar(f.p0), true) } }