diff options
Diffstat (limited to 'vendor/github.com/mattermost/rsc/qr/web/pic.go')
-rw-r--r-- | vendor/github.com/mattermost/rsc/qr/web/pic.go | 506 |
1 files changed, 0 insertions, 506 deletions
diff --git a/vendor/github.com/mattermost/rsc/qr/web/pic.go b/vendor/github.com/mattermost/rsc/qr/web/pic.go deleted file mode 100644 index 6baef94d2..000000000 --- a/vendor/github.com/mattermost/rsc/qr/web/pic.go +++ /dev/null @@ -1,506 +0,0 @@ -package web - -import ( - "bytes" - "fmt" - "image" - "image/color" - "image/draw" - "image/png" - "net/http" - "strconv" - "strings" - - "code.google.com/p/freetype-go/freetype" - "github.com/mattermost/rsc/appfs/fs" - "github.com/mattermost/rsc/qr" - "github.com/mattermost/rsc/qr/coding" -) - -func makeImage(req *http.Request, caption, font string, pt, size, border, scale int, f func(x, y int) uint32) *image.RGBA { - d := (size + 2*border) * scale - csize := 0 - if caption != "" { - if pt == 0 { - pt = 11 - } - csize = pt * 2 - } - c := image.NewRGBA(image.Rect(0, 0, d, d+csize)) - - // white - u := &image.Uniform{C: color.White} - draw.Draw(c, c.Bounds(), u, image.ZP, draw.Src) - - for y := 0; y < size; y++ { - for x := 0; x < size; x++ { - r := image.Rect((x+border)*scale, (y+border)*scale, (x+border+1)*scale, (y+border+1)*scale) - rgba := f(x, y) - u.C = color.RGBA{byte(rgba >> 24), byte(rgba >> 16), byte(rgba >> 8), byte(rgba)} - draw.Draw(c, r, u, image.ZP, draw.Src) - } - } - - if csize != 0 { - if font == "" { - font = "data/luxisr.ttf" - } - ctxt := fs.NewContext(req) - dat, _, err := ctxt.Read(font) - if err != nil { - panic(err) - } - tfont, err := freetype.ParseFont(dat) - if err != nil { - panic(err) - } - ft := freetype.NewContext() - ft.SetDst(c) - ft.SetDPI(100) - ft.SetFont(tfont) - ft.SetFontSize(float64(pt)) - ft.SetSrc(image.NewUniform(color.Black)) - ft.SetClip(image.Rect(0, 0, 0, 0)) - wid, err := ft.DrawString(caption, freetype.Pt(0, 0)) - if err != nil { - panic(err) - } - p := freetype.Pt(d, d+3*pt/2) - p.X -= wid.X - p.X /= 2 - ft.SetClip(c.Bounds()) - ft.DrawString(caption, p) - } - - return c -} - -func makeFrame(req *http.Request, font string, pt, vers, l, scale, dots int) image.Image { - lev := coding.Level(l) - p, err := coding.NewPlan(coding.Version(vers), lev, 0) - if err != nil { - panic(err) - } - - nd := p.DataBytes / p.Blocks - nc := p.CheckBytes / p.Blocks - extra := p.DataBytes - nd*p.Blocks - - cap := fmt.Sprintf("QR v%d, %s", vers, lev) - if dots > 0 { - cap = fmt.Sprintf("QR v%d order, from bottom right", vers) - } - m := makeImage(req, cap, font, pt, len(p.Pixel), 0, scale, func(x, y int) uint32 { - pix := p.Pixel[y][x] - switch pix.Role() { - case coding.Data: - if dots > 0 { - return 0xffffffff - } - off := int(pix.Offset() / 8) - nd := nd - var i int - for i = 0; i < p.Blocks; i++ { - if i == extra { - nd++ - } - if off < nd { - break - } - off -= nd - } - return blockColors[i%len(blockColors)] - case coding.Check: - if dots > 0 { - return 0xffffffff - } - i := (int(pix.Offset()/8) - p.DataBytes) / nc - return dark(blockColors[i%len(blockColors)]) - } - if pix&coding.Black != 0 { - return 0x000000ff - } - return 0xffffffff - }) - - if dots > 0 { - b := m.Bounds() - for y := 0; y <= len(p.Pixel); y++ { - for x := 0; x < b.Dx(); x++ { - m.SetRGBA(x, y*scale-(y/len(p.Pixel)), color.RGBA{127, 127, 127, 255}) - } - } - for x := 0; x <= len(p.Pixel); x++ { - for y := 0; y < b.Dx(); y++ { - m.SetRGBA(x*scale-(x/len(p.Pixel)), y, color.RGBA{127, 127, 127, 255}) - } - } - order := make([]image.Point, (p.DataBytes+p.CheckBytes)*8+1) - for y, row := range p.Pixel { - for x, pix := range row { - if r := pix.Role(); r != coding.Data && r != coding.Check { - continue - } - // draw.Draw(m, m.Bounds().Add(image.Pt(x*scale, y*scale)), dot, image.ZP, draw.Over) - order[pix.Offset()] = image.Point{x*scale + scale/2, y*scale + scale/2} - } - } - - for mode := 0; mode < 2; mode++ { - for i, p := range order { - q := order[i+1] - if q.X == 0 { - break - } - line(m, p, q, mode) - } - } - } - return m -} - -func line(m *image.RGBA, p, q image.Point, mode int) { - x := 0 - y := 0 - dx := q.X - p.X - dy := q.Y - p.Y - xsign := +1 - ysign := +1 - if dx < 0 { - xsign = -1 - dx = -dx - } - if dy < 0 { - ysign = -1 - dy = -dy - } - pt := func() { - switch mode { - case 0: - for dx := -2; dx <= 2; dx++ { - for dy := -2; dy <= 2; dy++ { - if dy*dx <= -4 || dy*dx >= 4 { - continue - } - m.SetRGBA(p.X+x*xsign+dx, p.Y+y*ysign+dy, color.RGBA{255, 192, 192, 255}) - } - } - - case 1: - m.SetRGBA(p.X+x*xsign, p.Y+y*ysign, color.RGBA{128, 0, 0, 255}) - } - } - if dx > dy { - for x < dx || y < dy { - pt() - x++ - if float64(x)*float64(dy)/float64(dx)-float64(y) > 0.5 { - y++ - } - } - } else { - for x < dx || y < dy { - pt() - y++ - if float64(y)*float64(dx)/float64(dy)-float64(x) > 0.5 { - x++ - } - } - } - pt() -} - -func pngEncode(c image.Image) []byte { - var b bytes.Buffer - png.Encode(&b, c) - return b.Bytes() -} - -// Frame handles a request for a single QR frame. -func Frame(w http.ResponseWriter, req *http.Request) { - arg := func(s string) int { x, _ := strconv.Atoi(req.FormValue(s)); return x } - v := arg("v") - scale := arg("scale") - if scale == 0 { - scale = 8 - } - - w.Header().Set("Cache-Control", "public, max-age=3600") - w.Write(pngEncode(makeFrame(req, req.FormValue("font"), arg("pt"), v, arg("l"), scale, arg("dots")))) -} - -// Frames handles a request for multiple QR frames. -func Frames(w http.ResponseWriter, req *http.Request) { - vs := strings.Split(req.FormValue("v"), ",") - - arg := func(s string) int { x, _ := strconv.Atoi(req.FormValue(s)); return x } - scale := arg("scale") - if scale == 0 { - scale = 8 - } - font := req.FormValue("font") - pt := arg("pt") - dots := arg("dots") - - var images []image.Image - l := arg("l") - for _, v := range vs { - l := l - if i := strings.Index(v, "."); i >= 0 { - l, _ = strconv.Atoi(v[i+1:]) - v = v[:i] - } - vv, _ := strconv.Atoi(v) - images = append(images, makeFrame(req, font, pt, vv, l, scale, dots)) - } - - b := images[len(images)-1].Bounds() - - dx := arg("dx") - if dx == 0 { - dx = b.Dx() - } - x, y := 0, 0 - xmax := 0 - sep := arg("sep") - if sep == 0 { - sep = 10 - } - var points []image.Point - for i, m := range images { - if x > 0 { - x += sep - } - if x > 0 && x+m.Bounds().Dx() > dx { - y += sep + images[i-1].Bounds().Dy() - x = 0 - } - points = append(points, image.Point{x, y}) - x += m.Bounds().Dx() - if x > xmax { - xmax = x - } - - } - - c := image.NewRGBA(image.Rect(0, 0, xmax, y+b.Dy())) - for i, m := range images { - draw.Draw(c, c.Bounds().Add(points[i]), m, image.ZP, draw.Src) - } - - w.Header().Set("Cache-Control", "public, max-age=3600") - w.Write(pngEncode(c)) -} - -// Mask handles a request for a single QR mask. -func Mask(w http.ResponseWriter, req *http.Request) { - arg := func(s string) int { x, _ := strconv.Atoi(req.FormValue(s)); return x } - v := arg("v") - m := arg("m") - scale := arg("scale") - if scale == 0 { - scale = 8 - } - - w.Header().Set("Cache-Control", "public, max-age=3600") - w.Write(pngEncode(makeMask(req, req.FormValue("font"), arg("pt"), v, m, scale))) -} - -// Masks handles a request for multiple QR masks. -func Masks(w http.ResponseWriter, req *http.Request) { - arg := func(s string) int { x, _ := strconv.Atoi(req.FormValue(s)); return x } - v := arg("v") - scale := arg("scale") - if scale == 0 { - scale = 8 - } - font := req.FormValue("font") - pt := arg("pt") - var mm []image.Image - for m := 0; m < 8; m++ { - mm = append(mm, makeMask(req, font, pt, v, m, scale)) - } - dx := mm[0].Bounds().Dx() - dy := mm[0].Bounds().Dy() - - sep := arg("sep") - if sep == 0 { - sep = 10 - } - c := image.NewRGBA(image.Rect(0, 0, (dx+sep)*4-sep, (dy+sep)*2-sep)) - for m := 0; m < 8; m++ { - x := (m % 4) * (dx + sep) - y := (m / 4) * (dy + sep) - draw.Draw(c, c.Bounds().Add(image.Pt(x, y)), mm[m], image.ZP, draw.Src) - } - - w.Header().Set("Cache-Control", "public, max-age=3600") - w.Write(pngEncode(c)) -} - -var maskName = []string{ - "(x+y) % 2", - "y % 2", - "x % 3", - "(x+y) % 3", - "(y/2 + x/3) % 2", - "xy%2 + xy%3", - "(xy%2 + xy%3) % 2", - "(xy%3 + (x+y)%2) % 2", -} - -func makeMask(req *http.Request, font string, pt int, vers, mask, scale int) image.Image { - p, err := coding.NewPlan(coding.Version(vers), coding.L, coding.Mask(mask)) - if err != nil { - panic(err) - } - m := makeImage(req, maskName[mask], font, pt, len(p.Pixel), 0, scale, func(x, y int) uint32 { - pix := p.Pixel[y][x] - switch pix.Role() { - case coding.Data, coding.Check: - if pix&coding.Invert != 0 { - return 0x000000ff - } - } - return 0xffffffff - }) - return m -} - -var blockColors = []uint32{ - 0x7777ffff, - 0xffff77ff, - 0xff7777ff, - 0x77ffffff, - 0x1e90ffff, - 0xffffe0ff, - 0x8b6969ff, - 0x77ff77ff, - 0x9b30ffff, - 0x00bfffff, - 0x90e890ff, - 0xfff68fff, - 0xffec8bff, - 0xffa07aff, - 0xffa54fff, - 0xeee8aaff, - 0x98fb98ff, - 0xbfbfbfff, - 0x54ff9fff, - 0xffaeb9ff, - 0xb23aeeff, - 0xbbffffff, - 0x7fffd4ff, - 0xff7a7aff, - 0x00007fff, -} - -func dark(x uint32) uint32 { - r, g, b, a := byte(x>>24), byte(x>>16), byte(x>>8), byte(x) - r = r/2 + r/4 - g = g/2 + g/4 - b = b/2 + b/4 - return uint32(r)<<24 | uint32(g)<<16 | uint32(b)<<8 | uint32(a) -} - -func clamp(x int) byte { - if x < 0 { - return 0 - } - if x > 255 { - return 255 - } - return byte(x) -} - -func max(x, y int) int { - if x > y { - return x - } - return y -} - -// Arrow handles a request for an arrow pointing in a given direction. -func Arrow(w http.ResponseWriter, req *http.Request) { - arg := func(s string) int { x, _ := strconv.Atoi(req.FormValue(s)); return x } - dir := arg("dir") - size := arg("size") - if size == 0 { - size = 50 - } - del := size / 10 - - m := image.NewRGBA(image.Rect(0, 0, size, size)) - - if dir == 4 { - draw.Draw(m, m.Bounds(), image.Black, image.ZP, draw.Src) - draw.Draw(m, image.Rect(5, 5, size-5, size-5), image.White, image.ZP, draw.Src) - } - - pt := func(x, y int, c color.RGBA) { - switch dir { - case 0: - m.SetRGBA(x, y, c) - case 1: - m.SetRGBA(y, size-1-x, c) - case 2: - m.SetRGBA(size-1-x, size-1-y, c) - case 3: - m.SetRGBA(size-1-y, x, c) - } - } - - for y := 0; y < size/2; y++ { - for x := 0; x < del && x < y; x++ { - pt(x, y, color.RGBA{0, 0, 0, 255}) - } - for x := del; x < y-del; x++ { - pt(x, y, color.RGBA{128, 128, 255, 255}) - } - for x := max(y-del, 0); x <= y; x++ { - pt(x, y, color.RGBA{0, 0, 0, 255}) - } - } - for y := size / 2; y < size; y++ { - for x := 0; x < del && x < size-1-y; x++ { - pt(x, y, color.RGBA{0, 0, 0, 255}) - } - for x := del; x < size-1-y-del; x++ { - pt(x, y, color.RGBA{128, 128, 192, 255}) - } - for x := max(size-1-y-del, 0); x <= size-1-y; x++ { - pt(x, y, color.RGBA{0, 0, 0, 255}) - } - } - - w.Header().Set("Cache-Control", "public, max-age=3600") - w.Write(pngEncode(m)) -} - -// Encode encodes a string using the given version, level, and mask. -func Encode(w http.ResponseWriter, req *http.Request) { - val := func(s string) int { - v, _ := strconv.Atoi(req.FormValue(s)) - return v - } - - l := coding.Level(val("l")) - v := coding.Version(val("v")) - enc := coding.String(req.FormValue("t")) - m := coding.Mask(val("m")) - - p, err := coding.NewPlan(v, l, m) - if err != nil { - panic(err) - } - cc, err := p.Encode(enc) - if err != nil { - panic(err) - } - - c := &qr.Code{Bitmap: cc.Bitmap, Size: cc.Size, Stride: cc.Stride, Scale: 8} - w.Header().Set("Content-Type", "image/png") - w.Header().Set("Cache-Control", "public, max-age=3600") - w.Write(c.PNG()) -} - |