changeset 328:c1fad3d93861

Add getKerning to freetype module and use it in sample
author Michael Pavone <pavone@retrodev.com>
date Wed, 25 Mar 2015 00:16:37 -0700
parents 860075fdc2d3
children eef8a5cea812
files modules/freetype.tp samples/freetype.tp
diffstat 2 files changed, 63 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/modules/freetype.tp	Tue Mar 24 23:13:13 2015 -0700
+++ b/modules/freetype.tp	Wed Mar 25 00:16:37 2015 -0700
@@ -232,6 +232,45 @@
 				u16ret
 			}
 			
+			llMessage: hasKerning? withVars: {
+				ret <- object ptr
+			} andCode: {
+				if: (FT_HAS_KERNING: face) {
+					true
+				} else {
+					false
+				}
+			}
+			
+			llMessage: getKerning:mode withVars: {
+				oleft <- object ptr
+				oright <- object ptr
+				omode <- object ptr
+				left <- obj_uint32 ptr
+				right <- obj_uint32 ptr
+				mode <- obj_uint32 ptr
+				x <- obj_int32 ptr
+				y <- obj_int32 ptr
+				ret <- object ptr
+				kernVec <- FT_Vector
+				err <- int
+			} andCode: :oleft oright :omode {
+				left <- (mcall: uint32 1 oleft) castTo: (obj_uint32 ptr)
+				right <- (mcall: uint32 1 oright) castTo: (obj_uint32 ptr)
+				mode <- (mcall: uint32 1 omode) castTo: (obj_uint32 ptr)
+				err <- FT_Get_Kerning: face (left num) (right num) (mode num) (addr_of: kernVec)
+				if: err != 0 {
+					mcall: none 1 option
+				} else: {
+					x <- make_object: (addr_of: obj_int32_meta) NULL 0
+					y <- make_object: (addr_of: obj_int32_meta) NULL 0
+					x num!: ((addr_of: kernVec) x)
+					y num!: ((addr_of: kernVec) y)
+					ret <- mcall: x:y 3 vec x y
+					mcall: value 2 option ret
+				}
+			}
+			
 			firstChar <- {
 				_helper getFirstChar: faceOpaque _makeChar
 			}
@@ -280,6 +319,12 @@
 		_constant: color FT_LOAD_COLOR
 	}
 	
+	_kerning <- #{
+		_constant: default FT_KERNING_DEFAULT
+		_constant: unfitted FT_KERNING_UNFITTED
+		_constant: unscaled FT_KERNING_UNSCALED
+	}
+	
 	#{
 		init <- {
 			
@@ -319,5 +364,6 @@
 		}
 		
 		loadFlags <- { _loadFlags }
+		kerning <- { _kerning }
 	}
 }
\ No newline at end of file
--- a/samples/freetype.tp	Tue Mar 24 23:13:13 2015 -0700
+++ b/samples/freetype.tp	Wed Mar 25 00:16:37 2015 -0700
@@ -28,8 +28,8 @@
 		glyphs <- #[]
 		//TODO: Use a bytearray once that has an append method
 		pixels <- #[]
-		foreach: (face charmap) :char glyphIndex {
-			face loadGlyph: glyphIndex flags: (render or linearDesign)
+		foreach: (face charmap) :char glyphIdx {
+			face loadGlyph: glyphIdx flags: (render or linearDesign)
 			pixelStart <- pixels length
 			_width <- slot bitmapWidth
 			_height <- slot bitmapRows
@@ -58,6 +58,7 @@
 				leftOffset <- (slot bitmapLeft)
 				topOffset <- (slot bitmapTop)
 				charCode <- char
+				glyphIndex <- glyphIdx
 				
 				atlasX <- -1
 				atlasY <- -1
@@ -264,10 +265,12 @@
 					width <- aWidth
 					height <- aHeight
 					glyphs <- glyphDict
-					drawString:at <- :str :x y {
+					drawString:at:useKerning? <- :str :xPos yPos :kern? {
 						//pixels to font units
-						designPosition <- (x f64) * _pixelFactor
+						designPosition <- (xPos f64) * _pixelFactor
 						charIdx <- 0
+						last <- 0u32
+						useKerning? <- kern? && (face hasKerning?)
 						
 						while: { charIdx < (str byte_length) } do: {
 							//TODO: UTF-8
@@ -275,11 +278,17 @@
 							glyph <- glyphs get: char else: {
 								glyphs get: 0u32 else: { false }
 							}
-							texture copyRect: (glyph atlasRect) To: (glyph destRect: x y)
+							texture copyRect: (glyph atlasRect) To: (glyph destRect: xPos yPos)
 							
 							designPosition <- designPosition + ((glyph hAdvance) f64)
-							x <- (designPosition / _pixelFactor + 0.5) truncInt32
+							if: charIdx > 0 && useKerning? {
+								(face getKerning: last (glyph glyphIndex) mode: ((freetype kerning) unscaled)) value: :kern {
+									designPosition <- designPosition + ((kern x) f64)
+								} none: {}
+							}
+							xPos <- (designPosition / _pixelFactor + 0.5) truncInt32
 							
+							last <- glyph glyphIndex
 							charIdx <- charIdx + 1
 						}
 					}
@@ -360,7 +369,8 @@
 							while: { continue? } do: {
 								renderer clear
 								if: (str length) > 0 {
-									atlas drawString: str at: 0 windowHeight / 2
+									atlas drawString: str at: 0 windowHeight / 3 useKerning?: true
+									atlas drawString: str at: 0 windowHeight * 2 / 3 useKerning?: false
 								} else: {
 									y <- 0
 									x <- 0