1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2024-12-26 11:28:22 +01:00

wip: rework on text rendering (performance is still degraded)

This commit is contained in:
Dany LE 2022-03-24 22:48:41 +01:00
parent d70df41681
commit 5058d62876
10 changed files with 277 additions and 100 deletions

View File

@ -19,16 +19,6 @@ Diya2DNode >> boundingBox [
^rec
]
{ #category : #accessing }
Diya2DNode >> color [
^ self style get: #color.
]
{ #category : #accessing }
Diya2DNode >> color: anObject [
style set:#color value: anObject
]
{ #category : #accessing }
Diya2DNode >> draw [
@ -83,12 +73,6 @@ Diya2DNode >> recFromBuffer [
^ Rectangle origin: minX@minY corner: maxX @ maxY
]
{ #category : #initialization }
Diya2DNode >> setUpShader [
super setUpShader.
shader setUniform: #u_color value: self color asGL4FArray.
]
{ #category : #accessing }
Diya2DNode >> updateTF [
tf := Array2D identity:3.

View File

@ -34,6 +34,18 @@ Diya2DPrimShape >> boundingBox [
^ bbox applyTf: self tf.
]
{ #category : #accessing }
Diya2DPrimShape >> color [
self texture ifNotNil: [ ^ self style get: #color. ].
^ self style get: #bgcolor.
]
{ #category : #accessing }
Diya2DPrimShape >> color: value [
self texture ifNotNil: [ ^ self style set: #color value: value. ].
^ self style set: #bgcolor value: value.
]
{ #category : #initialization }
Diya2DPrimShape >> draw [
vbuffer ifNil: [ ^self ].
@ -98,6 +110,7 @@ Diya2DPrimShape >> inner: aPoint [
Diya2DPrimShape >> setUpShader [
super setUpShader.
self shader
setUniform: #u_color value: self color asGL4FArray;
setUniform: #u_texture_type value:
(self texture ifNil: [ 0 ] ifNotNil:[self texture format]).
]

View File

@ -1,5 +1,54 @@
Class {
#name : #DiyaButton,
#superclass : #DiyaWidget,
#instVars : [
'label',
'rec'
],
#category : #'Diya-Widgets'
}
{ #category : #accessing }
DiyaButton class >> text: string [
^ self new text: string; yourself
]
{ #category : #accessing }
DiyaButton >> icon: id [
label icon: id.
label updateLayout.
]
{ #category : #accessing }
DiyaButton >> iconSize: size [
label iconSize: size.
]
{ #category : #initialization }
DiyaButton >> initialize [
super initialize.
style
set:#textAlign value: #center;
set:#textVAlign value: #middle.
rec := self addNode: (DiyaRectangle new).
label := self addNode: (DiyaLabel new).
label txt
wordWrap: false.
]
{ #category : #accessing }
DiyaButton >> label [
^ label
]
{ #category : #accessing }
DiyaButton >> text: string [
label txt: string.
]
{ #category : #accessing }
DiyaButton >> updateLayout [
rec extent: self extent.
label position: 0@(self extent y).
label extent: self extent.
]

View File

@ -14,5 +14,7 @@ DiyaDefaultStyle >> initialize [
self set: #fontFamily value: DiyaFontManager uniqueInstance defaultFamily.
self set: #fontStyle value: DiyaFontManager uniqueInstance defaultStyle.
self set: #borderColor value: (Color r: 0.051 g: 0.051 b: 0.051).
self set: #bgcolor2 value: (Color r: 0.1529 g: 0.1529 b: 0.1529)
self set: #bgcolor2 value: (Color r: 0.1529 g: 0.1529 b: 0.1529).
self set: #textAlign value: #left.
self set: #textVAlign value: #top
]

View File

@ -16,8 +16,8 @@ DiyaExampleApp >> main [
{ #category : #accessing }
DiyaExampleApp >> setup [
|node node1 ell label icon|
label := root addNode: (DiyaLabel new) at: 10@30.
|node node1 ell label icon button|
label := root addNode: (DiyaLabel new) at: 10@40.
label extent: 250@30.
label color: Color orange.
label icon: 16rF254.
@ -34,15 +34,20 @@ DiyaExampleApp >> setup [
"node borderWidth: 3.0."
node extent:200@200.
node := root addNode: (DiyaText data: String loremIpsum) at: 10@400.
node := root addNode: (DiyaRectangle new) at: 10@80.
node extent: 240@320.
"node := root addNode: (DiyaText data: String loremIpsum) at: 10@400.
node extent: 240@320.
node wordWrap: true.
node fontSize: 16.
node align: #center."
node := root addNode: (DiyaLine from: 10@620 to: 200@635).
node color: (Color red).
node borderWidth: 2.0.
ell := root addNode: (DiyaEllipse rx:150 ry: 100) at: 320@300.
ell := root addNode: (DiyaEllipse rx:100 ry: 70) at: 340@300.
ell borderColor: Color red.
ell color: Color white.
ell rotation: Float pi / 6.0.
@ -58,8 +63,13 @@ DiyaExampleApp >> setup [
node textureNamed: 'mrsang.png'.
node borderWidth: 3.0.
icon := root addNode: (DiyaFontIcon data: #(16rF101 16rF155 16rF185 16rF21B 16rF298 16rF254)) at: 10@10.
icon := root addNode: (DiyaFontIcon data: #(16rF101 16rF155 16rF185 16rF21B 16rF298 16rF254)) at: 10@24.
icon fontSize: 24.
icon color: (Color r: 209/255 g: 66/255 b:245/255 ).
button := root addNode: (DiyaButton text: 'Click me !') at: 160@10.
button extent: 200@40.
button icon:16rF185.
button iconSize: 24.
^ root
]

View File

@ -15,12 +15,13 @@ DiyaFontIcon >> data: code [
{ #category : #initialization }
DiyaFontIcon >> drawText [
|index offset tex|
|index offset tex glyph |
index := 1.
tex := self texture.
offset := 0@(self fontSize).
1 to: data size do: [ :i|
(self getCharsVerticesAt:i offset: offset on: tex) do: [
offset := (self alignLine: self fontSize)@(self valignText: self fontSize).
data do: [ :c|
glyph := tex getGlyph: c asInteger.
(self getCharsVerticesFrom: glyph offset: offset cellh: tex cellh) do: [
:e| vbuffer at: index put:e.
index := index + 1
].

View File

@ -8,6 +8,20 @@ Class {
#category : #'Diya-Widgets'
}
{ #category : #accessing }
DiyaLabel >> fontSize [
^txt fontSize.
]
{ #category : #accessing }
DiyaLabel >> fontSize: value [
txt fontSize: value.
icon ifNotNil: [ icon fontSize: value ].
"dirty := true."
]
{ #category : #accessing }
DiyaLabel >> icon [
^ icon
@ -16,19 +30,43 @@ DiyaLabel >> icon [
{ #category : #accessing }
DiyaLabel >> icon: anObject [
icon := nil.
anObject isNumber ifTrue: [ icon := self addNode: (DiyaFontIcon data: anObject) ].
anObject isNumber ifTrue: [
icon := self addNode: (DiyaFontIcon data: anObject).
icon align: #left].
anObject isString ifTrue: [ icon := self addNode: (DiyaImageView from: anObject)].
icon ifNil: [ ^ DiyaCoreAPIError signal: 'Invalid icon identification'].
dirty := true.
]
{ #category : #accessing }
DiyaLabel >> iconPosition: offset [
|xpos|
txt splitLines.
txt lines ifEmpty: [ ^0@0 ].
xpos := txt alignLine: txt lines first key.
^xpos@0
]
{ #category : #accessing }
DiyaLabel >> iconSize [
icon ifNil: [ ^0 ].
^icon fontSize.
]
{ #category : #accessing }
DiyaLabel >> iconSize: v [
icon ifNil: [ ^self ].
icon fontSize: v.
]
{ #category : #initialization }
DiyaLabel >> initialize [
super initialize.
txt := self addNode:(DiyaText data: '').
icon := nil.
self extent: 0@0.
"style := DiyaDefaultStyle uniqueInstance."
]
{ #category : #accessing }
@ -46,12 +84,14 @@ DiyaLabel >> txt: anObject [
DiyaLabel >> updateLayout [
|offset isize|
offset := 0.
isize := style get: #fontSize.
icon ifNotNil: [
isize := icon fontSize.
offset := isize + (isize >> 1).
icon position: 0 @ (extent y - isize)
icon extent:offset @ (extent y).
].
txt extent: (extent x - offset) @ (extent y).
txt position: offset @ (extent y)
txt position: offset @ 0.
icon ifNil: [ ^self ].
icon position: (self iconPosition: offset).
]

View File

@ -16,10 +16,7 @@ DiyaRectangle class >> size: size shader:s [
{ #category : #initialization }
DiyaRectangle >> drawLines [
self drawLineAt: 0.
self drawLineAt: 1.
self drawLineAt: 3.
self drawLineAt: 4.
OpenGL drawArrays: GL_LINE_LOOP first:0 count: (vbuffer size >> 2).
]
@ -34,8 +31,9 @@ DiyaRectangle >> initialize [
super initialize.
self extent:10@10.
translation := nil.
vbuffer := FFIExternalArray externalNewType: GLfloat size:24.
vbuffer := FFIExternalArray externalNewType: GLfloat size:16.
vbuffer autoRelease.
type := GL_QUADS.
]
{ #category : #accessing }
@ -46,10 +44,7 @@ DiyaRectangle >> update [
0.0. extent y. 0.0. 0.0.
0. 0. 0.0. 1.0.
extent x. 0.0. 1.0. 1.0.
extent x. 0.0. 1.0. 1.0.
extent x. extent y. 1.0. 0.0.
0.0. extent y. 0.0. 0.0.
} doWithIndex: [:e :i| vbuffer at: i put: e].
^true
]

View File

@ -5,7 +5,8 @@ Class {
'data',
'wrap',
'texheight',
'font'
'font',
'lines'
],
#pools : [
'FT2Types'
@ -23,6 +24,35 @@ DiyaText class >> data: string shader: s [
^ (self with:s) data: string; yourself
]
{ #category : #'menu messages' }
DiyaText >> align [
^ self style get: #textAlign
]
{ #category : #'menu messages' }
DiyaText >> align: v [
self style set: #textAlign value: v.
self formatText
]
{ #category : #accessing }
DiyaText >> alignLine:w [
self align = #center ifTrue:[^ 0 max:((self extent x - w) / 2.0 ) asFloat].
self align = #right ifTrue:[^ 0 max: self extent x - w].
^0
]
{ #category : #initialization }
DiyaText >> allocMemory [
vbuffer ifNotNil: [
vbuffer size >= data size
ifTrue: [^self]
ifFalse:[vbuffer free]
].
vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 16.
vbuffer autoRelease.
]
{ #category : #accessing }
DiyaText >> data [
^ data
@ -46,23 +76,8 @@ DiyaText >> drawLines [
{ #category : #accessing }
DiyaText >> drawText [
|vertices index tex2D offset lbdelta|
index := 1.
offset := 0@0.
tex2D := self texture.
lbdelta := self getLinebreakIndices: (self extent x / tex2D meanww) asInteger.
1 to: data size do: [ :i|
vertices := self getCharsVerticesAt:i offset: offset on: tex2D.
vertices do: [
:e| vbuffer at: index put:e.
index := index + 1.
].
(offset x > self extent x and: wrap not) ifTrue: [ ^self ].
((lbdelta includes: i + 1) and: wrap) ifTrue: [
offset setX: 0.0 setY: (offset y )- (tex2D linespace).
(offset y negated > self extent y) ifTrue: [ ^self ].
].
].
self splitLines.
self formatText .
]
{ #category : #accessing }
@ -81,8 +96,8 @@ DiyaText >> fontName: name style: face size: size [
name ifNotNil: [style set:#fontFamily value: name].
face ifNotNil: [style set: #fontStyle value:face].
style set: #fontSize value: size.
font := nil.
dirty := true.
self initTexture
]
{ #category : #accessing }
@ -101,16 +116,31 @@ DiyaText >> fontStyle [
]
{ #category : #accessing }
DiyaText >> getCharsVerticesAt:i offset: offset on: tex2D [
|x y w h glyph gsize c texcoord|
c := (data at:i) asInteger.
glyph := tex2D getGlyph: c.
gsize := glyph extent.
((offset x > self extent x) and: (gsize x > 0)) ifTrue:[
wrap ifFalse: [ ^ { } ].
DiyaText >> formatText [
|offset index line|
lines ifNil: [^self].
offset := 0@(self valignText: (texture linespace) * (lines size)).
index := 1.
lines do:[:assoc|
line := assoc value.
offset setX: (self alignLine: assoc key) setY: offset y.
line do:[:g|
(self getCharsVerticesFrom: g offset: offset cellh: texture cellh) do:[:v|
vbuffer at: index put:v.
index := index + 1.
]
].
offset setX: 0.0 setY: (offset y )- (texture linespace)
].
]
{ #category : #accessing }
DiyaText >> getCharsVerticesFrom:glyph offset: offset cellh: cellh [
|x y w h gsize texcoord|
gsize := glyph extent.
x := offset x + (glyph bearing x).
y := offset y - (tex2D cellh).
y := offset y - cellh.
w := (gsize x).
h := (gsize y).
texcoord := glyph texcoord.
@ -118,23 +148,35 @@ DiyaText >> getCharsVerticesAt:i offset: offset on: tex2D [
^{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. 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. }.
]
{ #category : #accessing }
DiyaText >> getLinebreakIndices: delta [
|indices idx|
indices := Set new.
idx := delta + 1.
[
idx < data size
] whileTrue: [
indices add: (self lastSeparatorFrom: idx) + 1.
idx := idx + delta.
].
^indices
DiyaText >> getLineAt: index to: line with: tex2D [
| glyph ret w |
w := 0.
index to: data size do:[ :i|
glyph := tex2D getGlyph: (data at:i) asInteger.
(w + (glyph advance x)) >= (self extent x) ifTrue:[
wrap ifFalse: [ ^ i @ w].
ret := self lastSeparatorFrom: i.
ret to: i - 1 do:[:j|
w := w - (line removeLast advance x)].
^ (ret+1)@w
] ifFalse:[
w := w + (glyph advance x).
line add: glyph.
].
].
^ (data size + 1) @ w
]
{ #category : #initialization }
DiyaText >> initTexture [
font:= DiyaFontManager uniqueInstance style: self fontStyle from: self fontName.
texture := font textureOf: self fontSize.
]
{ #category : #initialization }
@ -143,7 +185,8 @@ DiyaText >> initialize [
data := nil.
wrap := false.
texheight := 0.
style set: #border value: 0
style set: #border value: 0.
type := GL_QUADS.
]
{ #category : #'as yet unclassified' }
@ -154,29 +197,66 @@ DiyaText >> lastSeparatorFrom: index [
^ 0
]
{ #category : #accessing }
DiyaText >> lines [
^ lines
]
{ #category : #accessing }
DiyaText >> splitLines [
|line ret tex2D|
ret := 1@0.
tex2D := self texture.
lines := OrderedCollection new.
[
line := OrderedCollection new.
ret := self getLineAt: ret x to: line with: tex2D.
lines add: ((ret y) -> line).
(ret x < data size) and: wrap
] whileTrue.
]
{ #category : #accessing }
DiyaText >> texture [
| tex|
font:= font ifNil: [ DiyaFontManager uniqueInstance style: self fontStyle from: self fontName ].
tex := font textureOf: self fontSize.
texheight = tex height ifFalse: [
texheight := tex height.
texture ifNil: [ self initTexture ].
texheight = texture height ifFalse: [
texheight := texture height.
self update.
dirty := false.
].
^tex
^texture
]
{ #category : #initialization }
DiyaText >> update [
bbox ifNil: [ ^false ].
bbox ifNil: [ ^true ].
data ifNil:[^true].
data ifEmpty:[^true].
vbuffer ifNotNil: [vbuffer free].
vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 24.
vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 16.
vbuffer autoRelease.
self drawText.
^true
]
{ #category : #'menu messages' }
DiyaText >> valign [
^ self style get: #textVAlign
]
{ #category : #'menu messages' }
DiyaText >> valign: v [
self style set: #textVAlign value: v.
self formatText.
]
{ #category : #accessing }
DiyaText >> valignText:h [
self valign = #middle ifTrue:[^ (0 max:((self extent y - h) / 2 ) asFloat) negated].
self valign = #bottom ifTrue:[^ (0 max:(self extent y - h )) negated].
^0
]
{ #category : #initialization }
DiyaText >> wordWrap: aBool [
wrap := aBool.

View File

@ -12,6 +12,21 @@ DiyaWidget class >> fromStyle: aStyle [
^self new style: aStyle; yourself
]
{ #category : #accessing }
DiyaWidget >> color [
^style get: #color
]
{ #category : #accessing }
DiyaWidget >> color: value [
style set: #color value: value
]
{ #category : #geometry }
DiyaWidget >> extent [
^extent
]
{ #category : #geometry }
DiyaWidget >> extent: size [
extent := size.
@ -21,18 +36,6 @@ DiyaWidget >> extent: size [
{ #category : #initialization }
DiyaWidget >> initialize [
super initialize.
self style: DiyaDefaultStyle new.
]
{ #category : #accessing }
DiyaWidget >> style [
^ style
]
{ #category : #accessing }
DiyaWidget >> style: anObject [
style := anObject.
dirty := true
]
{ #category : #accessing }