diff options
Diffstat (limited to 'third_party/freetype-py/examples/subpixel-positioning.py')
-rw-r--r-- | third_party/freetype-py/examples/subpixel-positioning.py | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/third_party/freetype-py/examples/subpixel-positioning.py b/third_party/freetype-py/examples/subpixel-positioning.py new file mode 100644 index 0000000..6483517 --- /dev/null +++ b/third_party/freetype-py/examples/subpixel-positioning.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------- +# +# FreeType high-level python API - Copyright 2011 Nicolas P. Rougier +# Distributed under the terms of the new BSD license. +# +# ----------------------------------------------------------------------------- +''' +Subpixel rendering AND positioning using OpenGL and shaders. + +''' +import numpy as np +import OpenGL.GL as gl +import OpenGL.GLUT as glut +from texture_font import TextureFont, TextureAtlas +from shader import Shader + + +vert=''' +uniform sampler2D texture; +uniform vec2 pixel; +attribute float modulo; +varying float m; +void main() { + gl_FrontColor = gl_Color; + gl_TexCoord[0].xy = gl_MultiTexCoord0.xy; + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + m = modulo; +} +''' + +frag=''' +uniform sampler2D texture; +uniform vec2 pixel; +varying float m; +void main() { + float gamma = 1.0; + + vec2 uv = gl_TexCoord[0].xy; + vec4 current = texture2D(texture, uv); + vec4 previous= texture2D(texture, uv+vec2(-1,0)*pixel); + + current = pow(current, vec4(1.0/gamma)); + previous = pow(previous, vec4(1.0/gamma)); + + float r = current.r; + float g = current.g; + float b = current.b; + float a = current.a; + if( m <= 0.333 ) + { + float z = m/0.333; + r = mix(current.r, previous.b, z); + g = mix(current.g, current.r, z); + b = mix(current.b, current.g, z); + } + else if( m <= 0.666 ) + { + float z = (m-0.33)/0.333; + r = mix(previous.b, previous.g, z); + g = mix(current.r, previous.b, z); + b = mix(current.g, current.r, z); + } + else if( m < 1.0 ) + { + float z = (m-0.66)/0.334; + r = mix(previous.g, previous.r, z); + g = mix(previous.b, previous.g, z); + b = mix(current.r, previous.b, z); + } + + float t = max(max(r,g),b); + vec4 color = vec4(0.,0.,0., (r+g+b)/2.); + color = t*color + (1.-t)*vec4(r,g,b, min(min(r,g),b)); + gl_FragColor = vec4( color.rgb, color.a); +} +''' + + + + + +class Label: + def __init__(self, text, font, color=(1.0, 1.0, 1.0, 0.0), x=0, y=0, + width=None, height=None, anchor_x='left', anchor_y='baseline'): + self.text = text + self.vertices = np.zeros((len(text)*4,3), dtype=np.float32) + self.indices = np.zeros((len(text)*6, ), dtype=np.uint) + self.colors = np.zeros((len(text)*4,4), dtype=np.float32) + self.texcoords= np.zeros((len(text)*4,2), dtype=np.float32) + self.attrib = np.zeros((len(text)*4,1), dtype=np.float32) + pen = [x,y] + prev = None + + for i,charcode in enumerate(text): + glyph = font[charcode] + kerning = glyph.get_kerning(prev) + x0 = pen[0] + glyph.offset[0] + kerning + dx = x0-int(x0) + x0 = int(x0) + y0 = pen[1] + glyph.offset[1] + x1 = x0 + glyph.size[0] + y1 = y0 - glyph.size[1] + u0 = glyph.texcoords[0] + v0 = glyph.texcoords[1] + u1 = glyph.texcoords[2] + v1 = glyph.texcoords[3] + + index = i*4 + indices = [index, index+1, index+2, index, index+2, index+3] + vertices = [[x0,y0,1],[x0,y1,1],[x1,y1,1], [x1,y0,1]] + texcoords = [[u0,v0],[u0,v1],[u1,v1], [u1,v0]] + colors = [color,]*4 + + self.vertices[i*4:i*4+4] = vertices + self.indices[i*6:i*6+6] = indices + self.texcoords[i*4:i*4+4] = texcoords + self.colors[i*4:i*4+4] = colors + self.attrib[i*4:i*4+4] = dx + pen[0] = pen[0]+glyph.advance[0]/64.0 + kerning + pen[1] = pen[1]+glyph.advance[1]/64.0 + prev = charcode + + width = pen[0]-glyph.advance[0]/64.0+glyph.size[0] + + if anchor_y == 'top': + dy = -round(font.ascender) + elif anchor_y == 'center': + dy = +round(-font.height/2-font.descender) + elif anchor_y == 'bottom': + dy = -round(font.descender) + else: + dy = 0 + + if anchor_x == 'right': + dx = -width/1.0 + elif anchor_x == 'center': + dx = -width/2.0 + else: + dx = 0 + self.vertices += (round(dx), round(dy), 0) + + + def draw(self): + gl.glEnable( gl.GL_TEXTURE_2D ) + gl.glDisable( gl.GL_DEPTH_TEST ) + + gl.glEnableClientState(gl.GL_VERTEX_ARRAY) + gl.glEnableClientState(gl.GL_COLOR_ARRAY) + gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY) + gl.glEnableClientState(gl.GL_VERTEX_ARRAY) + + gl.glVertexPointer(3, gl.GL_FLOAT, 0, self.vertices) + gl.glColorPointer(4, gl.GL_FLOAT, 0, self.colors) + gl.glTexCoordPointer(2, gl.GL_FLOAT, 0, self.texcoords) + + r,g,b = 0,0,0 + gl.glColor( 1, 1, 1, 1 ) + gl.glEnable( gl.GL_BLEND ) + #gl.glBlendFunc( gl.GL_CONSTANT_COLOR_EXT, gl.GL_ONE_MINUS_SRC_COLOR ) + #gl.glBlendColor(r,g,b,1) + gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA ) + gl.glBlendColor( 1, 1, 1, 1 ) + + gl.glEnableVertexAttribArray( 1 ); + gl.glVertexAttribPointer( 1, 1, gl.GL_FLOAT, gl.GL_FALSE, 0, self.attrib) + shader.bind() + shader.uniformi('texture', 0) + shader.uniformf('pixel', 1.0/512, 1.0/512) + gl.glDrawElements(gl.GL_TRIANGLES, len(self.indices), + gl.GL_UNSIGNED_INT, self.indices) + shader.unbind() + gl.glDisableVertexAttribArray( 1 ); + gl.glDisableClientState(gl.GL_VERTEX_ARRAY) + gl.glDisableClientState(gl.GL_COLOR_ARRAY) + gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY) + gl.glDisable( gl.GL_TEXTURE_2D ) + gl.glDisable( gl.GL_BLEND ) + + + + +if __name__ == '__main__': + import sys + + atlas = TextureAtlas(512,512,3) + + def on_display( ): + #gl.glClearColor(0,0,0,1) + gl.glClearColor(1,1,1,1) + gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) + gl.glBindTexture( gl.GL_TEXTURE_2D, atlas.texid ) + for label in labels: + label.draw() + + gl.glColor(0,0,0,1) + gl.glBegin(gl.GL_LINES) + gl.glVertex2i(15,0) + gl.glVertex2i(15, 330) + gl.glVertex2i(225, 0) + gl.glVertex2i(225, 330) + gl.glEnd() + glut.glutSwapBuffers( ) + + def on_reshape( width, height ): + gl.glViewport( 0, 0, width, height ) + gl.glMatrixMode( gl.GL_PROJECTION ) + gl.glLoadIdentity( ) + gl.glOrtho( 0, width, 0, height, -1, 1 ) + gl.glMatrixMode( gl.GL_MODELVIEW ) + gl.glLoadIdentity( ) + + def on_keyboard( key, x, y ): + if key == '\033': + sys.exit( ) + + glut.glutInit( sys.argv ) + glut.glutInitDisplayMode( glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH ) + glut.glutCreateWindow( "Freetype OpenGL" ) + glut.glutReshapeWindow( 240, 330 ) + glut.glutDisplayFunc( on_display ) + glut.glutReshapeFunc( on_reshape ) + glut.glutKeyboardFunc( on_keyboard ) + + font = TextureFont(atlas, './Arial.ttf', 9) + text = "|... A Quick Brown Fox Jumps Over The Lazy Dog" + labels = [] + x,y = 20,310 + for i in range(30): + labels.append(Label(text=text, font=font, x=x, y=y)) + x += 0.1000000000001 + y -= 10 + atlas.upload() + shader = Shader(vert,frag) + glut.glutMainLoop( ) |