mirror of
https://github.com/lxsang/Diya-API.git
synced 2025-02-20 18:12:48 +01:00
FreeType face now is cached as bitmap font
This commit is contained in:
parent
7fa21d524b
commit
b8897a6351
@ -27,6 +27,12 @@ DiyaBoot class >> startx [
|
||||
self uniqueInstance run
|
||||
]
|
||||
|
||||
{ #category : #events }
|
||||
DiyaBoot >> GLinit. [
|
||||
OpenGL viewportX: 0 Y:0 W: display w H: display h.
|
||||
OpenGL enable: GL_TEXTURE_2D.
|
||||
]
|
||||
|
||||
{ #category : #events }
|
||||
DiyaBoot >> createGLContext [
|
||||
context := SDL2 glCreateContext: window.
|
||||
@ -107,9 +113,10 @@ DiyaBoot >> render [
|
||||
rec := root addNode: (DiyaRectangle size: 50@50 shader: GLSimpleShader uniqueInstance) at: 250 @ 500.
|
||||
rec rotation: (Float pi / -8.0).
|
||||
rec scale: 1.5@1.5.
|
||||
text := root addNode: (DiyaText data: String loremIpsum shader: TotoShader uniqueInstance) at: 20@320.
|
||||
text := root addNode: (DiyaText data: String loremIpsum shader: TotoShader uniqueInstance) at: 20@320.
|
||||
text extent: 200@320.
|
||||
"text rotation:(Float pi / 4.0)."
|
||||
self GLinit.
|
||||
OpenGL viewportX: 0 Y:0 W: display w H: display h.
|
||||
"TODO: maybe give node to customize this"
|
||||
[ running ] whileTrue: [
|
||||
@ -118,7 +125,6 @@ DiyaBoot >> render [
|
||||
].
|
||||
DiyaRenderer uniqueInstance render.
|
||||
SDL2 glSwapWindow: window.
|
||||
"SDL2 delay: 50. "
|
||||
].
|
||||
]
|
||||
|
||||
|
@ -2,9 +2,9 @@ Class {
|
||||
#name : #DiyaFontStyle,
|
||||
#superclass : #DiyaBaseObject,
|
||||
#instVars : [
|
||||
'texmap',
|
||||
'face',
|
||||
'name',
|
||||
'charmap'
|
||||
'name'
|
||||
],
|
||||
#category : #'Diya-Fonts'
|
||||
}
|
||||
@ -21,27 +21,13 @@ DiyaFontStyle >> face [
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaFontStyle >> face: anObject [
|
||||
face := anObject.
|
||||
name := anObject styleName
|
||||
face := anObject
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaFontStyle >> initialize [
|
||||
super initialize.
|
||||
charmap := Dictionary new.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaFontStyle >> loadChar: charCode size: size [
|
||||
|tex dic|
|
||||
"lookup in the char map"
|
||||
dic := charmap at: charCode ifAbsentPut: Dictionary new.
|
||||
tex := dic at: size ifAbsentPut: [
|
||||
face setPixelWidth:0 height: size.
|
||||
face loadCharacter: charCode flags: (1 << 2).
|
||||
OpenGLFontTex fromFace: face
|
||||
].
|
||||
^tex
|
||||
texmap := Dictionary new.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@ -53,3 +39,18 @@ DiyaFontStyle >> name [
|
||||
DiyaFontStyle >> name: anObject [
|
||||
name := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaFontStyle >> texmap [
|
||||
^ texmap
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaFontStyle >> textureOf: size [
|
||||
|tex|
|
||||
tex := texmap at: size ifAbsentPut: [
|
||||
""
|
||||
OpenGLFontTex fromFace: face ofSize: size
|
||||
].
|
||||
^tex
|
||||
]
|
||||
|
@ -14,16 +14,15 @@ DiyaRectangle >> draw [
|
||||
} doWithIndex: [:e :i| context buffer at: i put: e].
|
||||
shader use.
|
||||
shader setUniform: #u_time value: DiyaClock uniqueInstance elapsedTime asFloat.
|
||||
shader setUniform: #u_transform value: {GL_TRUE. self tf asGLBuffer}.
|
||||
shader setUniform: #u_projection value: {GL_FALSE. context projection buffer}.
|
||||
shader setUniform: #u_resolution value: { context resolution x. context resolution y }.
|
||||
shader setUniform: #u_transform value: {GL_TRUE. self tf asGLBuffer}.
|
||||
context mouse ifNotNil: [
|
||||
"in shader, window origin is bottom left conor of the window
|
||||
the mouse position should be transformed to this coodinate"
|
||||
shader setUniform: #u_mouse value: { context mouse x. context resolution y - context mouse y }.
|
||||
].
|
||||
context vao enableAttribute: 0.
|
||||
context vbo bind: GL_ARRAY_BUFFER.
|
||||
OpenGLVertexArray vertexAttributePointerIndex: 0 size:3 type: GL_FLOAT normalized: GL_FALSE stride: 0 pointer: nil.
|
||||
context vbo subData: GL_ARRAY_BUFFER offset:0 data: context buffer.
|
||||
OpenGL drawArrays: GL_QUADS first:0 count: 4.
|
||||
|
@ -8,6 +8,7 @@ Class {
|
||||
DiyaRootNode >> draw [
|
||||
OpenGL clearColorR: 1.0 G: 0.0 B: 1.0 A:0.
|
||||
OpenGL clear: GL_COLOR_BUFFER_BIT.
|
||||
context vbo bind: GL_ARRAY_BUFFER.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
|
@ -36,12 +36,11 @@ DiyaText >> data: anObject [
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> draw [
|
||||
| offset|
|
||||
| offset tex2D|
|
||||
data ifNil: [ ^self ].
|
||||
offset := 0.0@0.0.
|
||||
OpenGL enable: GL_CULL_FACE.
|
||||
OpenGL enable: GL_BLEND.
|
||||
OpenGL enable: GL_TEXTURE_2D.
|
||||
OpenGL blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA.
|
||||
self shader use.
|
||||
shader setUniform: #u_time value: DiyaClock uniqueInstance elapsedTime asFloat.
|
||||
@ -53,9 +52,15 @@ DiyaText >> draw [
|
||||
OpenGL pixelstorei: GL_UNPACK_ALIGNMENT param: 1.
|
||||
"configure vao vbo for texture QUAD"
|
||||
context texture0 active.
|
||||
tex2D := style textureOf: self fontSize.
|
||||
context texture0 setImage2D: tex2D.
|
||||
OpenGLTexture parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_WRAP_S param: GL_CLAMP_TO_EDGE.
|
||||
OpenGLTexture parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_WRAP_T param: GL_CLAMP_TO_EDGE.
|
||||
OpenGLTexture parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_MIN_FILTER param: GL_LINEAR.
|
||||
OpenGLTexture parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_MAG_FILTER param: GL_LINEAR.
|
||||
context vao enableAttribute: 0.
|
||||
OpenGLVertexArray vertexAttributePointerIndex: 0 size:4 type: GL_FLOAT normalized: GL_FALSE stride: 16 pointer: nil .
|
||||
data do:[:c | self drawCharacter: c at: offset].
|
||||
data do:[:c | self drawCharacter: c asciiValue at: offset withTexture:tex2D. ].
|
||||
context vao disableAttribute: 0.
|
||||
"reset value"
|
||||
OpenGL pixelstorei: GL_UNPACK_ALIGNMENT param: 4.
|
||||
@ -65,36 +70,56 @@ DiyaText >> draw [
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> drawCharacter: c at: offset [
|
||||
|tex2D|
|
||||
tex2D := style loadChar: c asciiValue size: self fontSize.
|
||||
context texture0 setImage2D: tex2D.
|
||||
OpenGLTexture parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_WRAP_S param: GL_CLAMP_TO_EDGE.
|
||||
OpenGLTexture parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_WRAP_T param: GL_CLAMP_TO_EDGE.
|
||||
OpenGLTexture parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_MIN_FILTER param: GL_LINEAR.
|
||||
OpenGLTexture parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_MAG_FILTER param: GL_LINEAR.
|
||||
"fill the buffer"
|
||||
((offset x > extent x) and: (tex2D width > 0)) ifTrue:[
|
||||
DiyaText >> drawCharacter: c at: offset withTexture: tex2D [
|
||||
|x y w h charsize texcoord|
|
||||
c = (Character space asciiValue) ifTrue:[
|
||||
^offset setX: (offset x + ((tex2D spacing )* (self scale x)) ) setY: offset y.
|
||||
].
|
||||
charsize := tex2D charSize: c.
|
||||
((offset x > extent x) and: (charsize x > 0)) ifTrue:[
|
||||
offset setX: 0.0 setY: (offset y )- (tex2D linespace * (self scale y)).].
|
||||
self fillVerticesBuffer: context buffer at: offset tex: tex2D.
|
||||
charsize := tex2D charSize: c.
|
||||
texcoord := tex2D texCoordOf: c.
|
||||
x := offset x "+ ((tex bearing x )*(self scale x))".
|
||||
y := offset y - ((tex2D cellh) * (self scale y)) "(((tex height) - (tex bearing y))*(self scale y))".
|
||||
w := (charsize x)*(self scale x).
|
||||
h := (charsize y)*(self scale y).
|
||||
{x. y + h. texcoord origin x. texcoord origin y.
|
||||
x. y. texcoord origin x. texcoord corner y.
|
||||
x + w. y. texcoord corner x. texcoord corner y.
|
||||
x. y + h. texcoord origin x. texcoord origin y.
|
||||
x + w. y. texcoord corner x. texcoord corner y.
|
||||
x + w. y + h. texcoord corner x. texcoord origin y. } withIndexDo: [ :e :i| context buffer at:i put: e ].
|
||||
context vbo subData: GL_ARRAY_BUFFER offset: 0 data: context buffer.
|
||||
OpenGL drawArrays: GL_TRIANGLES first:0 count:6.
|
||||
offset setX: (offset x + ((tex2D advance x )* (self scale x)) ) setY: offset y.
|
||||
offset setX: (offset x + ((charsize x )* (self scale x)) ) setY: offset y.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> fillVerticesBuffer: buffer at: offset tex: tex [
|
||||
|x y w h|
|
||||
x := offset x + ((tex bearing x )*(self scale x)).
|
||||
"x := offset x + ((tex bearing x )*(self scale x)).
|
||||
y := offset y - (((tex height) - (tex bearing y))*(self scale y)).
|
||||
w := (tex width)*(self scale x).
|
||||
h := (tex height)*(self scale y).
|
||||
h := (tex height)*(self scale y)."
|
||||
x := 0.
|
||||
y := 0.
|
||||
w := tex width.
|
||||
h := tex height.
|
||||
{x. y + h. 0.0. 0.0.
|
||||
x. y. 0.0. 1.0.
|
||||
x + w. y. 1.0. 1.0.
|
||||
x. y + h. 0.0. 0.0.
|
||||
x + w. y. 1.0. 1.0.
|
||||
x + w. y + h. 1.0. 0.0. } withIndexDo: [ :e :i| buffer at:i put: e ]
|
||||
|
||||
|
||||
"{x. y + h. 0.0. 0.0.
|
||||
x. y. 0.0. 1.0.
|
||||
x + w. y. 1.0. 1.0.
|
||||
x. y + h. 0.0. 0.0.
|
||||
x + w. y. 1.0. 1.0.
|
||||
x + w. y + h. 1.0. 0.0. }"
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
|
12
Diya/LibC.extension.st
Normal file
12
Diya/LibC.extension.st
Normal file
@ -0,0 +1,12 @@
|
||||
Extension { #name : #LibC }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
LibC >> memset:pointer value: value size: size [
|
||||
^self ffiCall: #(void *memset(void *pointer, int value, size_t size))
|
||||
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
LibC class >> memset:pointer value: value size: size [
|
||||
^self uniqueInstance memset: pointer value: value size: size
|
||||
]
|
@ -2,9 +2,9 @@ Class {
|
||||
#name : #OpenGLFontTex,
|
||||
#superclass : #OpenGLTexImage2D,
|
||||
#instVars : [
|
||||
'bearing',
|
||||
'advance',
|
||||
'linespace'
|
||||
'charmap',
|
||||
'cellw',
|
||||
'cellh'
|
||||
],
|
||||
#pools : [
|
||||
'OpenGLConstants',
|
||||
@ -14,58 +14,117 @@ Class {
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
OpenGLFontTex class >> fromFace: face [
|
||||
^self new fromFace: face; yourself
|
||||
OpenGLFontTex class >> fromFace: face ofSize: size [
|
||||
^self new fromFace: face ofSize: size; yourself
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
OpenGLFontTex >> blitPixel8: bitmap at: offset size: size [
|
||||
size = (0@0) ifTrue:[^self].
|
||||
0 to: size y - 1 do: [ :i|
|
||||
LibC memCopy: (bitmap getHandle + (i* (size x))) to:(data getHandle + ((i + offset y) * width + (offset x) )) size: size x
|
||||
]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> advance [
|
||||
^ advance
|
||||
OpenGLFontTex >> cellh [
|
||||
^ cellh
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> advance: anObject [
|
||||
advance := anObject
|
||||
OpenGLFontTex >> cellw [
|
||||
^ cellw
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> bearing [
|
||||
^ bearing
|
||||
OpenGLFontTex >> charSize: c [
|
||||
^(self charmap at: c + 1) extent
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> bearing: anObject [
|
||||
bearing := anObject
|
||||
OpenGLFontTex >> charmap [
|
||||
^ charmap
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> fromFace: aFTFace [
|
||||
|size glyph rec|
|
||||
glyph := aFTFace glyph.
|
||||
size := glyph width * glyph height.
|
||||
data := FFIExternalArray externalNewType: #uint8 size:size.
|
||||
rec := (FTFaceRec fromHandle: aFTFace getHandle).
|
||||
{ #category : #'instance creation' }
|
||||
OpenGLFontTex >> createBitmapFontFrom: bitmaps metrics: metrics maxBearing: maxbearing [
|
||||
|currChar offset|
|
||||
data ifNotNil: [data free ].
|
||||
charmap := OrderedCollection new.
|
||||
data := FFIExternalArray externalNewType: GLubyte size:cellw * cellh * 256.
|
||||
LibC memset: data getHandle value: 0 size: data size.
|
||||
data autoRelease.
|
||||
LibC memCopy: (rec glyph bitmap buffer) to:data getHandle size: size.
|
||||
currChar := 1.
|
||||
offset := 0@0.
|
||||
width := cellw * 16.
|
||||
height := cellh * 16.
|
||||
"linespace := (rec size metrics height / 64) asInteger."
|
||||
0 to: 15 do: [ :row|
|
||||
0 to: 15 do: [ :col|
|
||||
offset := (col * cellw) @ (row*cellh).
|
||||
charmap add: (Rectangle origin: offset extent: (((metrics at: currChar) first x) @ cellh)).
|
||||
self blitPixel8: (bitmaps at: currChar) at: (offset x) @ ((offset y) + maxbearing - ((metrics at: currChar) last) ) size: (metrics at: currChar) first.
|
||||
currChar := currChar + 1.
|
||||
]
|
||||
].
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
OpenGLFontTex >> fromFace: face ofSize: size [
|
||||
|minhang maxbearing rec metrics bitmaps |
|
||||
face setPixelWidth:0 height: size.
|
||||
"set up a buffer for 256 characters"
|
||||
bitmaps := OrderedCollection new.
|
||||
metrics := OrderedCollection new.
|
||||
cellw := 0.
|
||||
cellh := 0.
|
||||
minhang := 0.
|
||||
maxbearing := 0.
|
||||
rec := (FTFaceRec fromHandle: face getHandle).
|
||||
0 to: 255 do: [ :c |
|
||||
|bmp bmpsize|
|
||||
face loadCharacter: c flags: (1 << 2).
|
||||
metrics add: { ((rec glyph metrics width) /64)@ ((rec glyph metrics height) /64). (rec glyph metrics horiBearingY) / 64}.
|
||||
maxbearing := maxbearing max: ((rec glyph metrics horiBearingY) / 64).
|
||||
cellw := cellw max: ((rec glyph metrics width) / 64).
|
||||
minhang := minhang min: ((( rec glyph metrics horiBearingY) - (rec glyph metrics height )) / 64).
|
||||
"copy buffer"
|
||||
bmpsize := (rec glyph bitmap width)*(rec glyph bitmap rows).
|
||||
bmp := FFIExternalArray externalNewType: GLubyte size:bmpsize.
|
||||
LibC memCopy: rec glyph bitmap buffer to: bmp getHandle size: bmpsize.
|
||||
bitmaps add: bmp.
|
||||
].
|
||||
cellh := maxbearing - minhang.
|
||||
self createBitmapFontFrom: bitmaps metrics: metrics maxBearing: maxbearing.
|
||||
bitmaps do:[:p| p free].
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
OpenGLFontTex >> initialize [
|
||||
super initialize.
|
||||
charmap := OrderedCollection new.
|
||||
data := nil.
|
||||
level := 0.
|
||||
internalFormat := GL_ALPHA.
|
||||
width := glyph width.
|
||||
height := glyph height.
|
||||
linespace := (rec size metrics height / 64) asInteger.
|
||||
border := 0.
|
||||
format := GL_ALPHA.
|
||||
internalFormat := GL_ALPHA.
|
||||
type := GL_UNSIGNED_BYTE.
|
||||
target := GL_TEXTURE_2D.
|
||||
bearing := (glyph hBearingX )@ (glyph hBearingY).
|
||||
advance := (glyph advanceX )@ (glyph advanceY).
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> linespace [
|
||||
^ linespace
|
||||
^ cellh
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> linespace: anObject [
|
||||
linespace := anObject
|
||||
OpenGLFontTex >> spacing [
|
||||
^ cellw / 2
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> texCoordOf: c [
|
||||
|rec|
|
||||
rec := self charmap at: c + 1.
|
||||
^ Rectangle origin: ((rec origin )/ (self extent) ) asFloatPoint corner: ((rec corner) / (self extent)) asFloatPoint
|
||||
]
|
||||
|
@ -52,6 +52,11 @@ OpenGLTexImage2D >> debug [
|
||||
stdlog: 'internalformat :',internalFormat hex
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLTexImage2D >> extent [
|
||||
^ width @ height
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLTexImage2D >> format [
|
||||
^ format
|
||||
|
@ -76,7 +76,6 @@ OpenGLTexture >> bind: target [
|
||||
{ #category : #initialization }
|
||||
OpenGLTexture >> delete [
|
||||
self class delete: 1 pointer: textureID getHandle.
|
||||
textureID free.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
|
Loading…
x
Reference in New Issue
Block a user