// Shouldn't have tabs nor newlines func (o *OpenGlStream) PrintSegment(s string) { if s == "" { return } if o.BackgroundColor != nil && o.BorderColor == nil { gl.PushAttrib(gl.CURRENT_BIT) gl.Color3dv((*float64)(&o.BackgroundColor[0])) gl.PushMatrix() gl.Translated(float64(o.pos[0]), float64(o.pos[1]), 0) for range s { gl.CallList(oFontBackground) } gl.PopMatrix() gl.PopAttrib() } gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_LOD_BIAS, float32(lodBias*0.01)) gl.Enable(gl.BLEND) defer gl.Disable(gl.BLEND) gl.Enable(gl.TEXTURE_2D) defer gl.Disable(gl.TEXTURE_2D) gl.PushMatrix() gl.Translated(float64(o.pos[0]), float64(o.pos[1]), 0) gl.ListBase(oFontBase + uint32(o.FontOptions)*96) gl.CallLists(int32(len(s)), gl.UNSIGNED_BYTE, gl.Ptr(&[]byte(s)[0])) gl.PopMatrix() //CheckGLError() }
func setModelViewOptions() { gl.Enable(gl.TEXTURE_2D) gl.Disable(gl.LIGHTING) gl.Disable(gl.DITHER) gl.Enable(gl.CULL_FACE) gl.CullFace(gl.FRONT) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.Enable(gl.BLEND) gl.Enable(gl.ALPHA_TEST) gl.DepthFunc(gl.LEQUAL) gl.Disable(gl.DEPTH_TEST) }
func setupScene(width int, height int) { gl.Disable(gl.DEPTH_TEST) gl.Disable(gl.LIGHTING) gl.ClearColor(0.5, 0.5, 0.5, 0.0) gl.MatrixMode(gl.PROJECTION) gl.LoadIdentity() gl.Ortho(0, float64(width), 0, float64(height), -1, 1) gl.MatrixMode(gl.MODELVIEW) gl.LoadIdentity() }
func (atlas *FontAtlas) Draw(text string, b Bounds) { atlas.LoadGlyphs(text) gl.Enable(gl.BLEND) defer gl.Disable(gl.BLEND) gl.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) gl.Enable(gl.TEXTURE_2D) defer gl.Disable(gl.TEXTURE_2D) gl.BindTexture(gl.TEXTURE_2D, atlas.Texture) x := b.Min.X + atlas.drawPadding y := (b.Max.Y+b.Min.Y)/2 + (ceilPxf(atlas.maxBounds.Min.Y)+ceilPxf(atlas.maxBounds.Max.Y))/2 p := rune(0) for _, r := range text { glyph := atlas.Rendered[r] dx := float32(glyph.Loc.Dx()) dy := float32(glyph.Loc.Dy()) px := x + ceilPxf(glyph.Bounds.Min.X) - glyphPadding py := y + ceilPxf(glyph.Bounds.Min.Y) - glyphPadding // this is not the ideal way of positioning the letters // will create positioning artifacts // but it the result is more px = float32(math.Trunc(float64(px))) py = float32(math.Trunc(float64(py))) gl.Begin(gl.QUADS) { gl.TexCoord2f(glyph.RelLoc.Min.X, glyph.RelLoc.Min.Y) gl.Vertex2f(px, py) gl.TexCoord2f(glyph.RelLoc.Max.X, glyph.RelLoc.Min.Y) gl.Vertex2f(px+dx, py) gl.TexCoord2f(glyph.RelLoc.Max.X, glyph.RelLoc.Max.Y) gl.Vertex2f(px+dx, py+dy) gl.TexCoord2f(glyph.RelLoc.Min.X, glyph.RelLoc.Max.Y) gl.Vertex2f(px, py+dy) } gl.End() k := atlas.Face.Kern(p, r) p = r x += ceilPxf(glyph.Advance + k) } }
func (ctx *DrawContext) drawHud(o *orrery.Orrery, frametime time.Duration) { txt, size, err := ctx.createHudTexture(o, frametime) if err != nil { log.Fatalf(`can't create texture from text surface: %s`, err) } defer gl.DeleteTextures(1, &txt) gl.MatrixMode(gl.PROJECTION) gl.PushMatrix() gl.LoadIdentity() gl.Ortho(0.0, float64(ctx.width), float64(ctx.height), 0.0, -1.0, 1.0) gl.MatrixMode(gl.MODELVIEW) gl.LoadIdentity() gl.Clear(gl.DEPTH_BUFFER_BIT) gl.BindTexture(gl.TEXTURE_2D, txt) gl.Enable(gl.TEXTURE_2D) defer gl.Disable(gl.TEXTURE_2D) gl.Color3f(1, 1, 1) gl.Begin(gl.QUADS) gl.TexCoord2f(0, 0) gl.Vertex2f(0.0, 0.0) gl.TexCoord2f(1, 0) gl.Vertex2f(float32(size[0]), 0.0) gl.TexCoord2f(1, 1) gl.Vertex2f(float32(size[0]), float32(size[1])) gl.TexCoord2f(0, 1) gl.Vertex2f(0.0, float32(size[1])) gl.End() gl.PopMatrix() }
func (atlas *FontAtlas) draw(rendered *image.RGBA, b Bounds) { var texture uint32 gl.Enable(gl.TEXTURE_2D) gl.GenTextures(1, &texture) gl.BindTexture(gl.TEXTURE_2D, texture) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, int32(rendered.Bounds().Dx()), int32(rendered.Bounds().Dy()), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rendered.Pix)) gl.Enable(gl.BLEND) gl.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) gl.Begin(gl.QUADS) { gl.TexCoord2f(0, 0) gl.Vertex2f(b.Min.X, b.Min.Y) gl.TexCoord2f(1, 0) gl.Vertex2f(b.Max.X, b.Min.Y) gl.TexCoord2f(1, 1) gl.Vertex2f(b.Max.X, b.Max.Y) gl.TexCoord2f(0, 1) gl.Vertex2f(b.Min.X, b.Max.Y) } gl.End() gl.Disable(gl.BLEND) gl.DeleteTextures(1, &texture) gl.Disable(gl.TEXTURE_2D) }
func main() { runtime.LockOSThread() if err := glfw.Init(); err != nil { panic(err) } defer glfw.Terminate() window, err := glfw.CreateWindow(800, 600, "fontstash example", nil, nil) if err != nil { panic(err) } window.MakeContextCurrent() glfw.SwapInterval(1) gl.Init() data, err := ioutil.ReadFile(filepath.Join("..", "ClearSans-Regular.ttf")) if err != nil { panic(err) } gl.Enable(gl.TEXTURE_2D) tmpBitmap := make([]byte, 512*512) cdata, err, _, tmpBitmap := truetype.BakeFontBitmap(data, 0, 32, tmpBitmap, 512, 512, 32, 96) var ftex uint32 gl.GenTextures(1, &ftex) gl.BindTexture(gl.TEXTURE_2D, ftex) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, 512, 512, 0, gl.ALPHA, gl.UNSIGNED_BYTE, unsafe.Pointer(&tmpBitmap[0])) gl.ClearColor(0.3, 0.3, 0.32, 1.) for !window.ShouldClose() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) gl.MatrixMode(gl.PROJECTION) gl.LoadIdentity() gl.Ortho(0, 800, 600, 0, 0, 1) gl.MatrixMode(gl.MODELVIEW) gl.LoadIdentity() gl.Disable(gl.DEPTH_TEST) gl.Color4ub(255, 255, 255, 255) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) my_print(100, 100, "The quick brown fox jumps over the fence", ftex, cdata) window.SwapBuffers() glfw.PollEvents() } }
func (stash *Stash) FlushDraw() { i := 0 texture := stash.ttTextures[i] tt := true for { if texture.nverts > 0 { gl.Enable(gl.TEXTURE_2D) gl.BindTexture(gl.TEXTURE_2D, texture.id) for k := 0; k < texture.nverts; k++ { gl.Begin(gl.QUADS) gl.Color4fv(&texture.color[0]) gl.TexCoord2f(texture.verts[k*4+2], texture.verts[k*4+3]) gl.Vertex2f(texture.verts[k*4+0], texture.verts[k*4+1]) k++ gl.Color4fv(&texture.color[0]) gl.TexCoord2f(texture.verts[k*4+2], texture.verts[k*4+3]) gl.Vertex2f(texture.verts[k*4+0], texture.verts[k*4+1]) k++ gl.Color4fv(&texture.color[0]) gl.TexCoord2f(texture.verts[k*4+2], texture.verts[k*4+3]) gl.Vertex2f(texture.verts[k*4+0], texture.verts[k*4+1]) k++ gl.Color4fv(&texture.color[0]) gl.TexCoord2f(texture.verts[k*4+2], texture.verts[k*4+3]) gl.Vertex2f(texture.verts[k*4+0], texture.verts[k*4+1]) gl.End() } gl.Disable(gl.TEXTURE_2D) texture.nverts = 0 } if tt { if i < len(stash.ttTextures)-1 { i++ texture = stash.ttTextures[i] } else { i = 0 if len(stash.bmTextures) > 0 { texture = stash.bmTextures[i] tt = false } else { break } } } else { if i < len(stash.bmTextures)-1 { i++ texture = stash.bmTextures[i] } else { break } } } }
func (state *State) Reset(window *glfw.Window) { gl.ClearColor(1, 1, 1, 1) gl.Clear(gl.COLOR_BUFFER_BIT) gl.MatrixMode(gl.MODELVIEW) gl.LoadIdentity() gl.Disable(gl.DEPTH) gl.Enable(gl.FRAMEBUFFER_SRGB) width, height := window.GetSize() gl.Viewport(0, 0, int32(width), int32(height)) gl.Ortho(0, float64(width), float64(height), 0, 30, -30) }
func glRect(x, y, w, h, r, g, b, a float32) { gl.Disable(gl.TEXTURE_2D) // TODO do this once and remember the state gl.Begin(gl.QUADS) gl.Color4f(r, g, b, a) gl.Vertex2f(x, y) gl.Color4f(r, g, b, a) gl.Vertex2f(x+w, y) gl.Color4f(r, g, b, a) gl.Vertex2f(x+w, y+h) gl.Color4f(r, g, b, a) gl.Vertex2f(x, y+h) gl.End() }
func List(width, height int, list *draw.List) { gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.Enable(gl.SCISSOR_TEST) defer gl.Disable(gl.SCISSOR_TEST) gl.EnableClientState(gl.VERTEX_ARRAY) defer gl.DisableClientState(gl.VERTEX_ARRAY) gl.EnableClientState(gl.COLOR_ARRAY) defer gl.DisableClientState(gl.COLOR_ARRAY) gl.EnableClientState(gl.TEXTURE_COORD_ARRAY) defer gl.DisableClientState(gl.TEXTURE_COORD_ARRAY) gl.VertexPointer(2, gl.FLOAT, vertexStride, unsafe.Pointer(&(list.Vertices[0].P))) gl.TexCoordPointer(2, gl.FLOAT, vertexStride, unsafe.Pointer(&(list.Vertices[0].UV))) gl.ColorPointer(4, gl.UNSIGNED_BYTE, vertexStride, unsafe.Pointer(&(list.Vertices[0].Color))) offset := 0 for _, cmd := range list.Commands { if cmd.Count == 0 { continue } if cmd.Texture == 0 { gl.Disable(gl.TEXTURE_2D) } else { gl.Enable(gl.TEXTURE_2D) gl.BindTexture(gl.TEXTURE_2D, uint32(cmd.Texture)) } x, y, w, h := cmd.Clip.AsInt32() gl.Scissor(x, int32(height)-y-h, w, h) gl.DrawElements(gl.TRIANGLES, int32(cmd.Count), indexType, gl.Ptr(list.Indicies[offset:])) offset += int(cmd.Count) } }
func (ctx *DrawContext) drawGrid() { gl.Disable(gl.DEPTH_TEST) defer gl.Enable(gl.DEPTH_TEST) for i := float32(-500); i <= 500; i += 5 { gl.Begin(gl.LINES) gl.Color3f(0.2, 0.2, 0.2) gl.Vertex3f(-500, i, 0) gl.Vertex3f(500, i, 0) gl.Vertex3f(i, -500, 0) gl.Vertex3f(i, 500, 0) gl.End() } }
func (m *menu) draw() { return // TODO gl.Disable(gl.TEXTURE_2D) gl.Begin(gl.QUADS) gl.Color4f(m.color.r, m.color.g, m.color.b, m.color.a) gl.Vertex2f(m.pos.x, m.pos.y) gl.Color4f(m.color.r, m.color.g, m.color.b, m.color.a) gl.Vertex2f(m.pos.x+m.pos.w, m.pos.y) gl.Color4f(m.color.r, m.color.g, m.color.b, m.color.a) gl.Vertex2f(m.pos.x+m.pos.w, m.pos.y+m.pos.h) gl.Color4f(m.color.r, m.color.g, m.color.b, m.color.a) gl.Vertex2f(m.pos.x, m.pos.y+m.pos.h) gl.End() }
func reshape(window *glfw.Window, w, h int) { gl.ClearColor(1, 1, 1, 1) //fmt.Println(gl.GetString(gl.EXTENSIONS)) gl.Viewport(0, 0, int32(w), int32(h)) /* Establish viewing area to cover entire window. */ gl.MatrixMode(gl.PROJECTION) /* Start modifying the projection matrix. */ gl.LoadIdentity() /* Reset project matrix. */ gl.Ortho(0, float64(w), 0, float64(h), -1, 1) /* Map abstract coords directly to window coords. */ gl.Scalef(1, -1, 1) /* Invert Y axis so increasing Y goes down. */ gl.Translatef(0, float32(-h), 0) /* Shift origin up to upper-left corner. */ gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.Disable(gl.DEPTH_TEST) width, height = w, h }
func (atlas *FontAtlas) upload() { if !atlas.Dirty { return } atlas.Dirty = false gl.Enable(gl.TEXTURE_2D) if atlas.Texture != 0 { gl.DeleteTextures(1, &atlas.Texture) atlas.Texture = 0 } gl.GenTextures(1, &atlas.Texture) gl.BindTexture(gl.TEXTURE_2D, atlas.Texture) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, int32(atlas.Image.Rect.Size().X), int32(atlas.Image.Rect.Size().Y), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(atlas.Image.Pix)) if err := gl.GetError(); err != 0 { log.Println(err) } gl.Disable(gl.TEXTURE_2D) }
func New(cachew, cacheh int) *Stash { stash := &Stash{} // Create data for clearing the textures stash.emptyData = make([]byte, cachew*cacheh) // Create first texture for the cache stash.tw = cachew stash.th = cacheh stash.itw = 1 / float64(cachew) stash.ith = 1 / float64(cacheh) gl.Enable(gl.TEXTURE_2D) stash.ttTextures = make([]*Texture, 1) stash.ttTextures[0] = &Texture{} gl.GenTextures(1, &stash.ttTextures[0].id) gl.BindTexture(gl.TEXTURE_2D, stash.ttTextures[0].id) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, int32(cachew), int32(cacheh), 0, gl.ALPHA, gl.UNSIGNED_BYTE, unsafe.Pointer(&stash.emptyData[0])) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.Disable(gl.TEXTURE_2D) return stash }
func drawThumbnail(x, y, tx, ty, tw, th float32) { sx := x + 4 sy := y + 4 gl.Disable(gl.TEXTURE_2D) gl.Color3f(0.2, 0.2, 0.2) gl.Begin(gl.QUADS) gl.Vertex2f(sx, sy) gl.Vertex2f(sx+256, sy) gl.Vertex2f(sx+256, sy+240) gl.Vertex2f(sx, sy+240) gl.End() gl.Enable(gl.TEXTURE_2D) gl.Color3f(1, 1, 1) gl.Begin(gl.QUADS) gl.TexCoord2f(tx, ty) gl.Vertex2f(x, y) gl.TexCoord2f(tx+tw, ty) gl.Vertex2f(x+256, y) gl.TexCoord2f(tx+tw, ty+th) gl.Vertex2f(x+256, y+240) gl.TexCoord2f(tx, ty+th) gl.Vertex2f(x, y+240) gl.End() }
func main() { runtime.LockOSThread() if err := glfw.Init(); err != nil { panic(err) } defer glfw.Terminate() window, err := glfw.CreateWindow(800, 600, "fontstash example", nil, nil) if err != nil { panic(err) } window.MakeContextCurrent() glfw.SwapInterval(1) gl.Init() stash := fontstash.New(512, 512) clearSansRegular, err := stash.AddFont(filepath.Join("..", "ClearSans-Regular.ttf")) if err != nil { panic(err) } clearSansItalic, err := stash.AddFont(filepath.Join("..", "ClearSans-Italic.ttf")) if err != nil { panic(err) } clearSansBold, err := stash.AddFont(filepath.Join("..", "ClearSans-Bold.ttf")) if err != nil { panic(err) } droidJapanese, err := stash.AddFont(filepath.Join("..", "DroidSansJapanese.ttf")) if err != nil { panic(err) } gl.ClearColor(0.3, 0.3, 0.32, 1.) for !window.ShouldClose() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) gl.MatrixMode(gl.PROJECTION) gl.LoadIdentity() gl.Ortho(0, 800, 0, 600, -1, 1) gl.MatrixMode(gl.MODELVIEW) gl.LoadIdentity() gl.Disable(gl.DEPTH_TEST) gl.Color4ub(255, 255, 255, 255) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.Disable(gl.TEXTURE_2D) gl.Begin(gl.QUADS) gl.Vertex2i(0, -5) gl.Vertex2i(5, -5) gl.Vertex2i(5, -11) gl.Vertex2i(0, -11) gl.End() sx := float64(100) sy := float64(250) stash.BeginDraw() dx := sx dy := sy dx = stash.DrawText(clearSansRegular, 24, dx, dy, "The quick ", [4]float32{0, 0, 0, 1}) dx = stash.DrawText(clearSansItalic, 48, dx, dy, "brown ", [4]float32{1, 1, 0.5, 1}) dx = stash.DrawText(clearSansRegular, 24, dx, dy, "fox ", [4]float32{0, 1, 0.5, 1}) _, _, lh := stash.VMetrics(clearSansItalic, 24) dx = sx dy -= lh * 1.2 dx = stash.DrawText(clearSansItalic, 24, dx, dy, "jumps over ", [4]float32{0, 1, 1, 1}) dx = stash.DrawText(clearSansBold, 24, dx, dy, "the lazy ", [4]float32{1, 0, 1, 1}) dx = stash.DrawText(clearSansRegular, 24, dx, dy, "dog.", [4]float32{0, 1, 0, 1}) dx = sx dy -= lh * 1.2 dx = stash.DrawText(clearSansRegular, 12, dx, dy, "Now is the time for all good men to come to the aid of the party.", [4]float32{0, 0, 1, 1}) _, _, lh = stash.VMetrics(clearSansItalic, 12) dx = sx dy -= lh * 1.2 * 2 dx = stash.DrawText(clearSansItalic, 18, dx, dy, "Ég get etið gler án þess að meiða mig.", [4]float32{1, 0, 0, 1}) _, _, lh = stash.VMetrics(clearSansItalic, 18) dx = sx dy -= lh * 1.2 stash.DrawText(droidJapanese, 18, dx, dy, "どこかに置き忘れた、サングラスと打ち明け話。", [4]float32{1, 1, 1, 1}) stash.EndDraw() gl.Enable(gl.DEPTH_TEST) window.SwapBuffers() glfw.PollEvents() } }
// OpenGL draw function func draw(window *glfw.Window) { gl.Clear(gl.COLOR_BUFFER_BIT) gl.Enable(gl.BLEND) gl.Enable(gl.POINT_SMOOTH) gl.Enable(gl.LINE_SMOOTH) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.LoadIdentity() gl.PushMatrix() gl.Disable(gl.LIGHTING) width, height := window.GetSize() x := float64(width) y := float64(height) h := 0 gl.Color4f(.1, .1, .1, .8) gl.LineWidth(1.0) // x方向 var x0, x1, y0, y1 float64 var deltaX, deltaY float64 d := width / 2 x0 = -x x1 = -x y0 = -y y1 = y deltaX = ((2 * x) / float64(d)) for i := 0; i < d; i++ { x0 = x0 + deltaX gl.Begin(gl.LINES) gl.Vertex3f(float32(x0), float32(y0), float32(h)) gl.Vertex3f(float32(x0), float32(y1), float32(h)) gl.End() } // y方向 x0 = -x x1 = x deltaY = ((2 * y) / float64(d)) for i := 0; i < d; i++ { y0 = y0 + deltaY gl.Begin(gl.LINES) gl.Vertex3f(float32(x0), float32(y0), float32(h)) gl.Vertex3f(float32(x1), float32(y0), float32(h)) gl.End() } gl.PopMatrix() // draw boxes for _, room := range rooms { gl.PushMatrix() rot := room.Box.Body.Angle() * chipmunk.DegreeConst gl.Rotatef(float32(rot), 0, 0, 1.0) x := roundm(float64(room.Box.Body.Position().X), 4.0) y := roundm(float64(room.Box.Body.Position().Y), 4.0) gl.Translated(x, y, 0.0) drawRoom(room) gl.PopMatrix() } }
func (c *Context) Disable(flag int) { gl.Disable(uint32(flag)) }
func (stash *Stash) GetGlyph(fnt *Font, codepoint int, isize int16) *Glyph { size := float64(isize) / 10 // Find code point and size. h := hashint(uint(codepoint)) & (HASH_LUT_SIZE - 1) for i := fnt.lut[h]; i != -1; i = fnt.glyphs[i].next { if fnt.glyphs[i].codepoint == codepoint && (fnt.fType == BMFONT || fnt.glyphs[i].size == isize) { return fnt.glyphs[i] } } // Could not find glyph. // For bitmap fonts: ignore this glyph. if fnt.fType == BMFONT { return nil } // For truetype fonts: create this glyph. scale := fnt.font.ScaleForPixelHeight(size) g := fnt.font.FindGlyphIndex(codepoint) if g == 0 { // glyph not found return nil } advance, _ := fnt.font.GetGlyphHMetrics(g) x0, y0, x1, y1 := fnt.font.GetGlyphBitmapBox(g, scale, scale) gw := x1 - x0 gh := y1 - y0 // Check if glyph is larger than maximum texture size if gw >= stash.tw || gh >= stash.th { return nil } // Find texture and row where the glyph can be fit. rh := (int16(gh) + 7) & ^7 var tt int texture := stash.ttTextures[tt] var br *Row for br == nil { for i := range texture.rows { if texture.rows[i].h == rh && int(texture.rows[i].x)+gw+1 <= stash.tw { br = texture.rows[i] } } // If no row is found, there are 3 possibilities: // - add new row // - try next texture // - create new texture if br == nil { var py int16 // Check that there is enough space. if len(texture.rows) > 0 { py = texture.rows[len(texture.rows)-1].y + texture.rows[len(texture.rows)-1].h + 1 if int(py+rh) > stash.th { if tt < len(stash.ttTextures)-1 { tt++ texture = stash.ttTextures[tt] } else { // Create new texture gl.Enable(gl.TEXTURE_2D) texture = &Texture{} gl.GenTextures(1, &texture.id) gl.BindTexture(gl.TEXTURE_2D, texture.id) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, int32(stash.tw), int32(stash.th), 0, gl.ALPHA, gl.UNSIGNED_BYTE, unsafe.Pointer(&stash.emptyData[0])) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.Disable(gl.TEXTURE_2D) stash.ttTextures = append(stash.ttTextures, texture) } continue } } // Init and add row br = &Row{ x: 0, y: py, h: rh, } texture.rows = append(texture.rows, br) } } // Init glyph. glyph := &Glyph{ codepoint: codepoint, size: isize, texture: texture, x0: int(br.x), y0: int(br.y), x1: int(br.x) + gw, y1: int(br.y) + gh, xadv: scale * float64(advance), xoff: float64(x0), yoff: float64(y0), next: 0, } fnt.glyphs = append(fnt.glyphs, glyph) // Advance row location. br.x += int16(gw) + 1 // Insert char to hash lookup. glyph.next = fnt.lut[h] fnt.lut[h] = len(fnt.glyphs) - 1 // Rasterize bmp := make([]byte, gw*gh) bmp = fnt.font.MakeGlyphBitmap(bmp, gw, gh, gw, scale, scale, g) if len(bmp) > 0 { gl.Enable(gl.TEXTURE_2D) // Update texture gl.BindTexture(gl.TEXTURE_2D, texture.id) gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1) gl.TexSubImage2D(gl.TEXTURE_2D, 0, int32(glyph.x0), int32(glyph.y0), int32(gw), int32(gh), gl.ALPHA, gl.UNSIGNED_BYTE, unsafe.Pointer(&bmp[0])) gl.Disable(gl.TEXTURE_2D) } return glyph }
// Disable disables various GL capabilities. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDisable.xhtml func Disable(cap Enum) { gl.Disable(uint32(cap)) }
// Printf draws the given string at the specified coordinates. // It expects the string to be a single line. Line breaks are not // handled as line breaks and are rendered as glyphs. // // In order to render multi-line text, it is up to the caller to split // the text up into individual lines of adequate length and then call // this method for each line seperately. func (f *Font) Printf(x, y float32, fs string, argv ...interface{}) error { indices := []rune(fmt.Sprintf(fs, argv...)) if len(indices) == 0 { return nil } // Runes form display list indices. // For this purpose, they need to be offset by -FontConfig.Low low := f.config.Low for i := range indices { indices[i] -= low } var vp [4]int32 gl.GetIntegerv(gl.VIEWPORT, &vp[0]) gl.PushAttrib(gl.TRANSFORM_BIT) gl.MatrixMode(gl.PROJECTION) gl.PushMatrix() gl.LoadIdentity() gl.Ortho(float64(vp[0]), float64(vp[2]), float64(vp[1]), float64(vp[3]), 0, 1) gl.PopAttrib() gl.PushAttrib(gl.LIST_BIT | gl.CURRENT_BIT | gl.ENABLE_BIT | gl.TRANSFORM_BIT) { gl.MatrixMode(gl.MODELVIEW) gl.Disable(gl.LIGHTING) gl.Disable(gl.DEPTH_TEST) gl.Enable(gl.BLEND) gl.Enable(gl.TEXTURE_2D) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.BindTexture(gl.TEXTURE_2D, f.texture) gl.ListBase(f.listbase) var mv [16]float32 gl.GetFloatv(gl.MODELVIEW_MATRIX, &mv[0]) gl.PushMatrix() { gl.LoadIdentity() mgw := float32(f.maxGlyphWidth) mgh := float32(f.maxGlyphHeight) switch f.config.Dir { case LeftToRight, TopToBottom: gl.Translatef(x, float32(vp[3])-y-mgh, 0) case RightToLeft: gl.Translatef(x-mgw, float32(vp[3])-y-mgh, 0) } gl.MultMatrixf(&mv[0]) gl.CallLists(int32(len(indices)), gl.UNSIGNED_INT, unsafe.Pointer(&indices[0])) } gl.PopMatrix() gl.BindTexture(gl.TEXTURE_2D, 0) } gl.PopAttrib() gl.PushAttrib(gl.TRANSFORM_BIT) gl.MatrixMode(gl.PROJECTION) gl.PopMatrix() gl.PopAttrib() return checkGLError() }