1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2025-04-20 07:26:45 +02: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 ^rec
] ]
{ #category : #accessing }
Diya2DNode >> color [
^ self style get: #color.
]
{ #category : #accessing }
Diya2DNode >> color: anObject [
style set:#color value: anObject
]
{ #category : #accessing } { #category : #accessing }
Diya2DNode >> draw [ Diya2DNode >> draw [
@ -83,12 +73,6 @@ Diya2DNode >> recFromBuffer [
^ Rectangle origin: minX@minY corner: maxX @ maxY ^ Rectangle origin: minX@minY corner: maxX @ maxY
] ]
{ #category : #initialization }
Diya2DNode >> setUpShader [
super setUpShader.
shader setUniform: #u_color value: self color asGL4FArray.
]
{ #category : #accessing } { #category : #accessing }
Diya2DNode >> updateTF [ Diya2DNode >> updateTF [
tf := Array2D identity:3. tf := Array2D identity:3.

View File

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

View File

@ -1,5 +1,54 @@
Class { Class {
#name : #DiyaButton, #name : #DiyaButton,
#superclass : #DiyaWidget, #superclass : #DiyaWidget,
#instVars : [
'label',
'rec'
],
#category : #'Diya-Widgets' #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: #fontFamily value: DiyaFontManager uniqueInstance defaultFamily.
self set: #fontStyle value: DiyaFontManager uniqueInstance defaultStyle. self set: #fontStyle value: DiyaFontManager uniqueInstance defaultStyle.
self set: #borderColor value: (Color r: 0.051 g: 0.051 b: 0.051). 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 } { #category : #accessing }
DiyaExampleApp >> setup [ DiyaExampleApp >> setup [
|node node1 ell label icon| |node node1 ell label icon button|
label := root addNode: (DiyaLabel new) at: 10@30. label := root addNode: (DiyaLabel new) at: 10@40.
label extent: 250@30. label extent: 250@30.
label color: Color orange. label color: Color orange.
label icon: 16rF254. label icon: 16rF254.
@ -34,15 +34,20 @@ DiyaExampleApp >> setup [
"node borderWidth: 3.0." "node borderWidth: 3.0."
node extent:200@200. 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 extent: 240@320.
node wordWrap: true. node wordWrap: true.
node fontSize: 16.
node align: #center."
node := root addNode: (DiyaLine from: 10@620 to: 200@635). node := root addNode: (DiyaLine from: 10@620 to: 200@635).
node color: (Color red). node color: (Color red).
node borderWidth: 2.0. 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 borderColor: Color red.
ell color: Color white. ell color: Color white.
ell rotation: Float pi / 6.0. ell rotation: Float pi / 6.0.
@ -58,8 +63,13 @@ DiyaExampleApp >> setup [
node textureNamed: 'mrsang.png'. node textureNamed: 'mrsang.png'.
node borderWidth: 3.0. 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 fontSize: 24.
icon color: (Color r: 209/255 g: 66/255 b:245/255 ). 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 ^ root
] ]

View File

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

View File

@ -8,6 +8,20 @@ Class {
#category : #'Diya-Widgets' #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 } { #category : #accessing }
DiyaLabel >> icon [ DiyaLabel >> icon [
^ icon ^ icon
@ -16,19 +30,43 @@ DiyaLabel >> icon [
{ #category : #accessing } { #category : #accessing }
DiyaLabel >> icon: anObject [ DiyaLabel >> icon: anObject [
icon := nil. 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)]. anObject isString ifTrue: [ icon := self addNode: (DiyaImageView from: anObject)].
icon ifNil: [ ^ DiyaCoreAPIError signal: 'Invalid icon identification']. icon ifNil: [ ^ DiyaCoreAPIError signal: 'Invalid icon identification'].
dirty := true. 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 } { #category : #initialization }
DiyaLabel >> initialize [ DiyaLabel >> initialize [
super initialize. super initialize.
txt := self addNode:(DiyaText data: ''). txt := self addNode:(DiyaText data: '').
icon := nil. icon := nil.
self extent: 0@0. self extent: 0@0.
"style := DiyaDefaultStyle uniqueInstance."
] ]
{ #category : #accessing } { #category : #accessing }
@ -46,12 +84,14 @@ DiyaLabel >> txt: anObject [
DiyaLabel >> updateLayout [ DiyaLabel >> updateLayout [
|offset isize| |offset isize|
offset := 0. offset := 0.
isize := style get: #fontSize.
icon ifNotNil: [ icon ifNotNil: [
isize := icon fontSize.
offset := isize + (isize >> 1). offset := isize + (isize >> 1).
icon position: 0 @ (extent y - isize) icon extent:offset @ (extent y).
]. ].
txt extent: (extent x - 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 } { #category : #initialization }
DiyaRectangle >> drawLines [ DiyaRectangle >> drawLines [
self drawLineAt: 0. OpenGL drawArrays: GL_LINE_LOOP first:0 count: (vbuffer size >> 2).
self drawLineAt: 1.
self drawLineAt: 3.
self drawLineAt: 4.
] ]
@ -34,8 +31,9 @@ DiyaRectangle >> initialize [
super initialize. super initialize.
self extent:10@10. self extent:10@10.
translation := nil. translation := nil.
vbuffer := FFIExternalArray externalNewType: GLfloat size:24. vbuffer := FFIExternalArray externalNewType: GLfloat size:16.
vbuffer autoRelease. vbuffer autoRelease.
type := GL_QUADS.
] ]
{ #category : #accessing } { #category : #accessing }
@ -46,10 +44,7 @@ DiyaRectangle >> update [
0.0. extent y. 0.0. 0.0. 0.0. extent y. 0.0. 0.0.
0. 0. 0.0. 1.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. 0.0. 1.0. 1.0.
extent x. extent y. 1.0. 0.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]. } doWithIndex: [:e :i| vbuffer at: i put: e].
^true ^true
] ]

View File

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

View File

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