summaryrefslogtreecommitdiff
path: root/third_party/freetype-py/examples/subpixel-positioning.py
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/freetype-py/examples/subpixel-positioning.py')
-rw-r--r--third_party/freetype-py/examples/subpixel-positioning.py236
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( )