1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2025-03-12 10:32:48 +01:00

improve font rendering in OpenGL, optimise memory usage

This commit is contained in:
Dany LE 2022-03-17 00:32:19 +01:00
parent f215eb054f
commit e2a8bc046c
4 changed files with 87 additions and 77 deletions

View File

@ -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.

View File

@ -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 ).
] ]

View File

@ -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 }

View File

@ -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