mirror of
				https://github.com/lxsang/Diya-API.git
				synced 2025-10-31 10:15:34 +01:00 
			
		
		
		
	improve font rendering in OpenGL, optimise memory usage
This commit is contained in:
		| @@ -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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user