mirror of
https://github.com/lxsang/Diya-API.git
synced 2025-03-12 18:42:48 +01:00
improve font rendering in OpenGL, optimise memory usage
This commit is contained in:
parent
f215eb054f
commit
e2a8bc046c
@ -74,7 +74,7 @@ DiyaBoot >> createWindow [
|
|||||||
|
|
||||||
{ #category : #events }
|
{ #category : #events }
|
||||||
DiyaBoot >> exampleNodes [
|
DiyaBoot >> exampleNodes [
|
||||||
|root node style tex|
|
|root node tex|
|
||||||
root := DiyaRootNode new.
|
root := DiyaRootNode new.
|
||||||
tex := (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png').
|
tex := (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png').
|
||||||
node := root addNode: (DiyaRectangle size: 200@200) at: 250 @ 430.
|
node := root addNode: (DiyaRectangle size: 200@200) at: 250 @ 430.
|
||||||
@ -83,13 +83,14 @@ DiyaBoot >> exampleNodes [
|
|||||||
node borderColor: Color red.
|
node borderColor: Color red.
|
||||||
node borderWidth: 3.0.
|
node borderWidth: 3.0.
|
||||||
|
|
||||||
style := DiyaFontManager uniqueInstance style: 'Bold' from:'Ubuntu'.
|
"style := DiyaFontManager uniqueInstance style: 'Regular' from:'Ubuntu'.
|
||||||
"style := DiyaFontManager uniqueInstance style: 'Regular' from: 'bootstrap-icons'."
|
tex1 := (style textureOf: 18).
|
||||||
node := root addNode: (DiyaRectangle size: 208@288) at: 250 @ 50.
|
style := DiyaFontManager uniqueInstance style: 'Regular' from: 'bootstrap-icons'.
|
||||||
|
node := root addNode: (DiyaRectangle size: tex1 extent) at: 250 @ 300.
|
||||||
node color: (Color orange).
|
node color: (Color orange).
|
||||||
node texture: (style textureOf: 48).
|
node texture: tex1.
|
||||||
node borderColor: Color red.
|
node borderColor: Color red.
|
||||||
node borderWidth: 3.0.
|
node borderWidth: 3.0."
|
||||||
|
|
||||||
node := root addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 20 @ 400.
|
node := root addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 20 @ 400.
|
||||||
node rotation: (Float pi / -8.0).
|
node rotation: (Float pi / -8.0).
|
||||||
@ -104,7 +105,7 @@ DiyaBoot >> exampleNodes [
|
|||||||
node borderWidth: 2.0.
|
node borderWidth: 2.0.
|
||||||
|
|
||||||
|
|
||||||
node := root addNode: (DiyaCircle r: 100) at: 200@200.
|
node := root addNode: (DiyaCircle r: 100) at: 320@300.
|
||||||
node borderColor: Color red.
|
node borderColor: Color red.
|
||||||
node color: Color white.
|
node color: Color white.
|
||||||
node borderWidth: 3.0.
|
node borderWidth: 3.0.
|
||||||
|
@ -4,7 +4,7 @@ Class {
|
|||||||
#instVars : [
|
#instVars : [
|
||||||
'advance',
|
'advance',
|
||||||
'bearing',
|
'bearing',
|
||||||
'texcoord'
|
'tex'
|
||||||
],
|
],
|
||||||
#pools : [
|
#pools : [
|
||||||
'OpenGLConstants',
|
'OpenGLConstants',
|
||||||
@ -34,11 +34,16 @@ DiyaFontGlyph >> bearing: anObject [
|
|||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
DiyaFontGlyph >> texcoord [
|
DiyaFontGlyph >> tex [
|
||||||
^ texcoord
|
^ tex
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
DiyaFontGlyph >> texcoord: anObject [
|
DiyaFontGlyph >> tex: anObject [
|
||||||
texcoord := anObject
|
tex := anObject
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
DiyaFontGlyph >> texcoord [
|
||||||
|
^ (Rectangle origin: (self origin/ (tex extent) ) asFloatPoint corner: ((self corner) / (tex extent)) asFloatPoint ).
|
||||||
]
|
]
|
||||||
|
@ -109,7 +109,7 @@ DiyaText >> fontStyle [
|
|||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
DiyaText >> getCharsVerticesAt:i offset: offset on: tex2D [
|
DiyaText >> getCharsVerticesAt:i offset: offset on: tex2D [
|
||||||
|x y w h glyph gsize c |
|
|x y w h glyph gsize c texcoord|
|
||||||
c := (data at:i) asciiValue.
|
c := (data at:i) asciiValue.
|
||||||
c = (Character space asciiValue) ifTrue:[
|
c = (Character space asciiValue) ifTrue:[
|
||||||
offset setX: (offset x + (tex2D spacing ) ) setY: offset y.
|
offset setX: (offset x + (tex2D spacing ) ) setY: offset y.
|
||||||
@ -130,13 +130,14 @@ DiyaText >> getCharsVerticesAt:i offset: offset on: tex2D [
|
|||||||
y := offset y - (tex2D cellh).
|
y := offset y - (tex2D cellh).
|
||||||
w := (gsize x).
|
w := (gsize x).
|
||||||
h := (gsize y).
|
h := (gsize y).
|
||||||
|
texcoord := glyph texcoord.
|
||||||
offset setX: (offset x + (glyph advance x)) setY: offset y.
|
offset setX: (offset x + (glyph advance x)) setY: offset y.
|
||||||
^{x. y + h. glyph texcoord origin x. glyph texcoord origin y.
|
^{x. y + h. texcoord origin x. texcoord origin y.
|
||||||
x. y. glyph texcoord origin x. glyph texcoord corner y.
|
x. y. texcoord origin x. texcoord corner y.
|
||||||
x + w. y. glyph texcoord corner x. glyph texcoord corner y.
|
x + w. y. texcoord corner x. texcoord corner y.
|
||||||
x. y + h. glyph texcoord origin x. glyph texcoord origin y.
|
x. y + h. texcoord origin x. texcoord origin y.
|
||||||
x + w. y. glyph texcoord corner x. glyph texcoord corner y.
|
x + w. y. texcoord corner x. texcoord corner y.
|
||||||
x + w. y + h. glyph texcoord corner x. glyph texcoord origin y. }.
|
x + w. y + h. texcoord corner x. texcoord origin y. }.
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #initialization }
|
{ #category : #initialization }
|
||||||
|
@ -6,7 +6,12 @@ Class {
|
|||||||
'cellw',
|
'cellw',
|
||||||
'cellh',
|
'cellh',
|
||||||
'spacing',
|
'spacing',
|
||||||
'fontSize'
|
'fontSize',
|
||||||
|
'colp',
|
||||||
|
'rowp',
|
||||||
|
'face',
|
||||||
|
'maxbearing',
|
||||||
|
'maxrows'
|
||||||
],
|
],
|
||||||
#pools : [
|
#pools : [
|
||||||
'OpenGLConstants',
|
'OpenGLConstants',
|
||||||
@ -26,7 +31,6 @@ OpenGLFontTex >> blitPixel8: bitmap at: offset size: size [
|
|||||||
0 to: size y - 1 do: [ :i|
|
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
|
LibC memCopy: (bitmap getHandle + (i* (size x))) to:(data getHandle + ((i + offset y) * width + (offset x) )) size: size x
|
||||||
].
|
].
|
||||||
bitmap free.
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
@ -44,39 +48,6 @@ OpenGLFontTex >> charmap [
|
|||||||
^ charmap
|
^ charmap
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'instance creation' }
|
|
||||||
OpenGLFontTex >> createBitmapFontFrom: glyphs maxBearing: maxbearing [
|
|
||||||
|bmp metric offset nrows index element|
|
|
||||||
data ifNotNil: [data free ].
|
|
||||||
charmap := Dictionary new.
|
|
||||||
nrows := glyphs size >> 5.
|
|
||||||
(glyphs size % 32) = 0 ifFalse:[nrows := nrows + 1].
|
|
||||||
data := FFIExternalArray externalNewType: GLubyte size:cellw * cellh * (nrows << 5).
|
|
||||||
LibC memset: data getHandle value: 0 size: data size.
|
|
||||||
data autoRelease.
|
|
||||||
index := 1.
|
|
||||||
offset := 0@0.
|
|
||||||
width := cellw * 32.
|
|
||||||
height := cellh * nrows.
|
|
||||||
0 to: nrows - 1 do: [ :row|
|
|
||||||
0 to: 31 do: [ :col| |glyph|
|
|
||||||
element := glyphs at: index.
|
|
||||||
metric := element at: 3.
|
|
||||||
bmp := element at:2.
|
|
||||||
offset := (col * cellw) @ (row*cellh).
|
|
||||||
glyph := (DiyaFontGlyph origin: offset extent: ((metric first x asInteger) @ cellh)).
|
|
||||||
glyph
|
|
||||||
bearing: (metric at: 2) asFloatPoint;
|
|
||||||
advance: (metric at: 3) asFloatPoint;
|
|
||||||
texcoord: (Rectangle origin: (glyph origin/ (self extent) ) asFloatPoint corner: ((glyph corner) / (self extent)) asFloatPoint ).
|
|
||||||
charmap at: element first put:glyph.
|
|
||||||
self blitPixel8: bmp at: (offset x) @ ((offset y) + maxbearing - (metric last) ) size: metric first.
|
|
||||||
index := index + 1.
|
|
||||||
index > glyphs size ifTrue:[^self].
|
|
||||||
]
|
|
||||||
].
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
OpenGLFontTex >> drop [
|
OpenGLFontTex >> drop [
|
||||||
OpenGL
|
OpenGL
|
||||||
@ -91,50 +62,67 @@ OpenGLFontTex >> fontSize [
|
|||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'instance creation' }
|
{ #category : #'instance creation' }
|
||||||
OpenGLFontTex >> fromFace: face ofSize: size [
|
OpenGLFontTex >> fromFace: aFace ofSize: size [
|
||||||
|minhang maxbearing rec glyphs iptr charcode w|
|
|minhang rec iptr charcode w|
|
||||||
fontSize := size.
|
fontSize := size.
|
||||||
face setPixelWidth:0 height: size.
|
face := aFace.
|
||||||
glyphs := OrderedCollection new.
|
charmap := Dictionary new.
|
||||||
cellw := 0.
|
face setPixelWidth:0 height: self fontSize.
|
||||||
cellh := 0.
|
cellw := cellh := minhang := maxbearing := 0.
|
||||||
minhang := 0.
|
|
||||||
maxbearing := 0.
|
|
||||||
iptr := FFIExternalArray externalNewType: GLuint size:1.
|
iptr := FFIExternalArray externalNewType: GLuint size:1.
|
||||||
iptr at:1 put: 0.
|
iptr at:1 put: 0.
|
||||||
rec := (FTFaceRec fromHandle: face getHandle).
|
rec := (FTFaceRec fromHandle: face getHandle).
|
||||||
charcode := face getFirstChar: iptr getHandle.
|
charcode := face getFirstChar: iptr getHandle.
|
||||||
[ (iptr at: 1) = 0 ] whileFalse: [
|
[ (iptr at: 1) = 0 ] whileFalse: [
|
||||||
|bmp bmpsize metric|
|
|
||||||
face loadCharacter: charcode flags: (1 << 2).
|
face loadCharacter: charcode flags: (1 << 2).
|
||||||
w := ((rec glyph metrics width) >> 6).
|
w := ((rec glyph metrics width) >> 6).
|
||||||
(w > (size << 1)) ifFalse:[
|
(w > (size << 1)) ifFalse:[
|
||||||
metric := {
|
|
||||||
(((rec glyph metrics width) >> 6)@ ((rec glyph metrics height) >> 6)).
|
|
||||||
(face glyph hBearing).
|
|
||||||
(face glyph advance).
|
|
||||||
((rec glyph metrics horiBearingY) >> 6)
|
|
||||||
}.
|
|
||||||
maxbearing := maxbearing max: ((rec glyph metrics horiBearingY) >> 6).
|
maxbearing := maxbearing max: ((rec glyph metrics horiBearingY) >> 6).
|
||||||
cellw := cellw max: w.
|
cellw := cellw max: w.
|
||||||
minhang := minhang min: ((( rec glyph metrics horiBearingY) - (rec glyph metrics height)) >> 6).
|
minhang := minhang min: ((( rec glyph metrics horiBearingY) - (rec glyph metrics height)) >> 6).
|
||||||
"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.
|
|
||||||
glyphs add: {charcode. bmp. metric}.
|
|
||||||
].
|
].
|
||||||
charcode := face getNextChar: charcode iptr: iptr getHandle.
|
charcode := face getNextChar: charcode iptr: iptr getHandle.
|
||||||
].
|
].
|
||||||
cellh := maxbearing - minhang.
|
cellh := maxbearing - minhang.
|
||||||
spacing := (size >> 2) asInteger.
|
spacing := (cellw >> 2) asInteger.
|
||||||
self createBitmapFontFrom: glyphs maxBearing: maxbearing.
|
maxrows := 8.
|
||||||
|
data := FFIExternalArray externalNewType: GLubyte size:cellw * cellh * (maxrows << 5).
|
||||||
|
LibC memset: data getHandle value: 0 size: data size.
|
||||||
|
width := cellw << 5.
|
||||||
|
height := cellh.
|
||||||
|
data autoRelease.
|
||||||
iptr free.
|
iptr free.
|
||||||
]
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
OpenGLFontTex >> genGlyph:c [
|
||||||
|
|rec offset glyph gsize|
|
||||||
|
face setPixelWidth:0 height: self fontSize.
|
||||||
|
face loadCharacter: c flags: (1 << 2).
|
||||||
|
rec := (FTFaceRec fromHandle: face getHandle).
|
||||||
|
gsize := ((rec glyph metrics width) >> 6)@((rec glyph metrics height) >> 6).
|
||||||
|
offset := (colp * cellw) @ (rowp*cellh).
|
||||||
|
glyph := (DiyaFontGlyph origin: offset extent: ((gsize x) @ cellh)).
|
||||||
|
glyph
|
||||||
|
bearing: face glyph hBearing asFloatPoint;
|
||||||
|
advance: face glyph advance;
|
||||||
|
tex: self.
|
||||||
|
self blitPixel8: rec glyph bitmap buffer at: (offset x) @ ((offset y) + maxbearing - ((rec glyph metrics horiBearingY) >> 6) ) size: gsize.
|
||||||
|
colp := (colp + 1) % 32.
|
||||||
|
colp = 0 ifTrue:[
|
||||||
|
rowp := rowp + 1.
|
||||||
|
height := height + cellh.
|
||||||
|
rowp >= maxrows ifTrue:[
|
||||||
|
self reallocateBuffer.
|
||||||
|
].
|
||||||
|
].
|
||||||
|
^glyph
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
OpenGLFontTex >> getGlyph: c [
|
OpenGLFontTex >> getGlyph: c [
|
||||||
^(self charmap at: c ifAbsent:[^nil])
|
^(self charmap at: c ifAbsentPut:[self genGlyph:c])
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #initialization }
|
{ #category : #initialization }
|
||||||
@ -148,6 +136,8 @@ OpenGLFontTex >> initialize [
|
|||||||
internalFormat := GL_ALPHA.
|
internalFormat := GL_ALPHA.
|
||||||
type := GL_UNSIGNED_BYTE.
|
type := GL_UNSIGNED_BYTE.
|
||||||
target := GL_TEXTURE_2D.
|
target := GL_TEXTURE_2D.
|
||||||
|
colp := 0.
|
||||||
|
rowp := 0.
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
@ -155,6 +145,19 @@ OpenGLFontTex >> linespace [
|
|||||||
^ cellh
|
^ cellh
|
||||||
]
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
OpenGLFontTex >> reallocateBuffer [
|
||||||
|
|newbuffer|
|
||||||
|
maxrows := maxrows + 4.
|
||||||
|
newbuffer := FFIExternalArray externalNewType: GLubyte size:cellw * cellh * (maxrows << 5).
|
||||||
|
LibC memset: newbuffer getHandle value: 0 size: newbuffer size.
|
||||||
|
LibC memCopy: data getHandle to: newbuffer getHandle size: data size.
|
||||||
|
newbuffer autoRelease.
|
||||||
|
data free.
|
||||||
|
data := newbuffer
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
OpenGLFontTex >> setup [
|
OpenGLFontTex >> setup [
|
||||||
OpenGL
|
OpenGL
|
||||||
|
Loading…
x
Reference in New Issue
Block a user