From 16269e40c321cd36929bcef65fbaf2265d6c30c9 Mon Sep 17 00:00:00 2001 From: DanyLE Date: Wed, 16 Mar 2022 21:33:35 +0100 Subject: [PATCH] fix conflict --- Diya/Diya2DNode.class.st | 3 +- Diya/Diya2DPrimShape.class.st | 2 +- Diya/Diya2DShader.class.st | 3 +- Diya/DiyaBoot.class.st | 39 +++++---- Diya/DiyaConvexPolygon.class.st | 48 +++++++++++ Diya/DiyaEllipse.class.st | 77 ++++++++--------- Diya/DiyaEllipseShader.class.st | 146 ++++++++++++++++++++++++++++++++ Diya/DiyaLine.class.st | 8 +- Diya/DiyaPolygon.class.st | 62 ++++++++++++++ Diya/DiyaText.class.st | 4 +- Diya/FT2Face.extension.st | 11 +++ Diya/OpenGLFontTex.class.st | 105 +++++++++++++---------- 12 files changed, 396 insertions(+), 112 deletions(-) create mode 100644 Diya/DiyaConvexPolygon.class.st create mode 100644 Diya/DiyaEllipseShader.class.st create mode 100644 Diya/FT2Face.extension.st diff --git a/Diya/Diya2DNode.class.st b/Diya/Diya2DNode.class.st index 607db27..b8aeddb 100644 --- a/Diya/Diya2DNode.class.st +++ b/Diya/Diya2DNode.class.st @@ -49,7 +49,8 @@ Diya2DNode >> initialize [ { #category : #'as yet unclassified' } Diya2DNode >> recFromBuffer [ |maxX maxY minX minY x y| - maxX := maxY := minX := minY := 0. + maxX := minX := vbuffer at: 1. + maxY := minY := vbuffer at: 2. 1 to: vbuffer size by: 4 do: [ :i| x := vbuffer at: i. y := vbuffer at: i + 1. diff --git a/Diya/Diya2DPrimShape.class.st b/Diya/Diya2DPrimShape.class.st index c2b6ad4..4578c8c 100644 --- a/Diya/Diya2DPrimShape.class.st +++ b/Diya/Diya2DPrimShape.class.st @@ -69,7 +69,7 @@ Diya2DPrimShape >> initialize [ children := nil. type := GL_TRIANGLES. border := 0. - bcolor := Color white + bcolor := Color white. ] { #category : #initialization } diff --git a/Diya/Diya2DShader.class.st b/Diya/Diya2DShader.class.st index a67aa60..11b010b 100644 --- a/Diya/Diya2DShader.class.st +++ b/Diya/Diya2DShader.class.st @@ -17,7 +17,6 @@ uniform float u_time; // 2D uniforms uniform int u_texture_type; uniform vec4 u_color; -uniform vec4 u_border_color; uniform sampler2D u_texture; varying vec2 texcoord; void main(void) { @@ -57,5 +56,5 @@ Diya2DShader >> setUpUniforms [ self addUniform: #u_texture_type of: Uniform1i. self addUniform: #u_color of: Uniform4F. self addUniform: #u_border_color of: Uniform4F. - self addUniform: #u_border of: Uniform1i. + self addUniform: #u_border of: Uniform1F. ] diff --git a/Diya/DiyaBoot.class.st b/Diya/DiyaBoot.class.st index 22a955e..7496a98 100644 --- a/Diya/DiyaBoot.class.st +++ b/Diya/DiyaBoot.class.st @@ -74,18 +74,19 @@ DiyaBoot >> createWindow [ { #category : #events } DiyaBoot >> exampleNodes [ - |root node style| + |root node style tex| root := DiyaRootNode new. + tex := (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png'). node := root addNode: (DiyaRectangle size: 200@200) at: 250 @ 430. - node texture: (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png'). + node texture: tex. node color: (Color r: 1.0 g:1.0 b:1.0 alpha:1.0 ). node borderColor: Color red. node borderWidth: 3.0. - style := DiyaFontManager uniqueInstance style: 'Bold' from:'Ubuntu'. + style := DiyaFontManager uniqueInstance style: 'Regular' from:'Ubuntu'. node := root addNode: (DiyaRectangle size: 208@288) at: 250 @ 50. node color: (Color orange). - node texture: (style textureOf: 20). + node texture: (style textureOf: 16). node borderColor: Color red. node borderWidth: 3.0. @@ -94,7 +95,7 @@ DiyaBoot >> exampleNodes [ node scale: 1.5@1.5. node := root addNode: (DiyaText data: String loremIpsum) at: 10@340. - node extent: 230@320. + node extent: 250@320. node wordWrap: true. node := root addNode: (DiyaLine from: 10@620 to: 200@635). @@ -104,8 +105,16 @@ DiyaBoot >> exampleNodes [ node := root addNode: (DiyaCircle r: 100) at: 200@200. node borderColor: Color red. - node borderWidth: 2.0. - "node rotation:(Float pi / 4.0)." + node color: Color white. + node borderWidth: 3.0. + node texture: tex. + "node rotation:(Float pi / 4.0)". + + node := root addNode: (DiyaConvexPolygon points:{250@100. 400@250. 450@80. 350@60}). + node color: Color green. + node borderColor: Color red. + node texture: tex. + node borderWidth: 3.0. ^ root ] @@ -156,24 +165,20 @@ DiyaBoot >> randomColorChannel [ { #category : #events } DiyaBoot >> render [ - |event root text delta fps maxfps minfps| + |event root text delta fps| event := SDL_Event new. root := self exampleNodes. DiyaRenderer uniqueInstance root: root. - text := root addNode:(DiyaText data: 'tick') at: (display w - 250)@40. - text extent: 250@40. - text fontSize: 20. + text := root addNode:(DiyaText data: 'tick') at: (display w - 80)@40. + text extent: 80@40. + text fontSize: 18. text color: Color red. DiyaRendererContext uniqueInstance. self GLinit. - fps := maxfps := 0. - minfps := self class maxFPS. [ running ] whileTrue: [ delta := DiyaClock uniqueInstance delta asMilliSeconds. fps := ((1000/delta) asInteger). - maxfps := maxfps max: fps. - minfps := minfps min: fps. - text data: ('FPS:', fps asString, '(Min ', minfps asString, ', max ', maxfps asString, ')'). + text data: ('FPS:', fps asString). DiyaClock uniqueInstance tick. [(SDL2 pollEvent: event) > 0] whileTrue: [ self processEvent: event @@ -182,7 +187,7 @@ DiyaBoot >> render [ SDL2 glSwapWindow: window. delta := DiyaClock uniqueInstance delta asMilliSeconds. - SDL2 delay: (0 max: (1000/ self class maxFPS) asInteger - delta). "60 fps" + SDL2 delay: (0 max: (1000/ self class maxFPS) asInteger - delta). ]. ] diff --git a/Diya/DiyaConvexPolygon.class.st b/Diya/DiyaConvexPolygon.class.st new file mode 100644 index 0000000..1f547c1 --- /dev/null +++ b/Diya/DiyaConvexPolygon.class.st @@ -0,0 +1,48 @@ +Class { + #name : #DiyaConvexPolygon, + #superclass : #DiyaPolygon, + #category : #'Diya-Graphics' +} + +{ #category : #accessing } +DiyaConvexPolygon >> calculateVertices [ + |size index p texcoord| + size := (points size + 1) << 2. + vbuffer ifNotNil: [ vbuffer free ]. + vbuffer := FFIExternalArray externalNewType: GLfloat size:size. + vbuffer autoRelease. + points sort:[:a :b| a angle < b angle]. + index := 1. + points do:[:point| + texcoord := self texcoordOf: point. + vbuffer + at: index put: point x; + at: index + 1 put: point y; + at: index + 2 put: texcoord x; + at: index + 3 put: 1.0 - texcoord y. + index := index + 4. + ]. + p := points at: 2. + texcoord := self texcoordOf: p. + vbuffer + at: index put: p x; + at: index + 1 put: p y; + at: index + 2 put: texcoord x; + at: index + 3 put: 1.0 - texcoord y. +] + +{ #category : #initialization } +DiyaConvexPolygon >> drawLines [ + OpenGL drawArrays: GL_LINE_LOOP first:0 count: (vbuffer size >> 2) - 1. +] + +{ #category : #initialization } +DiyaConvexPolygon >> initialize [ + super initialize. + type := GL_TRIANGLE_FAN +] + +{ #category : #accessing } +DiyaConvexPolygon >> texcoordOf: point [ + ^ (point / (self extent )) asFloatPoint +] diff --git a/Diya/DiyaEllipse.class.st b/Diya/DiyaEllipse.class.st index 6241f05..790f00b 100644 --- a/Diya/DiyaEllipse.class.st +++ b/Diya/DiyaEllipse.class.st @@ -3,8 +3,7 @@ Class { #superclass : #Diya2DPrimShape, #instVars : [ 'rx', - 'ry', - 'delta' + 'ry' ], #category : #'Diya-Graphics' } @@ -24,29 +23,28 @@ DiyaEllipse class >> rx: rx ry: ry shader: s [ yourself ] -{ #category : #accessing } -DiyaEllipse >> delta [ - ^ delta -] - -{ #category : #accessing } -DiyaEllipse >> delta: anObject [ - delta := anObject +{ #category : #initialization } +DiyaEllipse >> draw [ + OpenGL + enable: GL_BLEND; + blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA. + super draw. + OpenGL + disable: GL_BLEND ] { #category : #initialization } -DiyaEllipse >> drawLines [ - 0 to: (vbuffer size >> 2) by: 3 do:[: i| - self drawLineAt: i - ]. +DiyaEllipse >> drawBorder [ + "do nothing" ] { #category : #initialization } DiyaEllipse >> initialize [ super initialize. translation := nil. - vbuffer := FFIExternalArray externalNewType: GLfloat size:4332. + vbuffer := FFIExternalArray externalNewType: GLfloat size: 24. vbuffer autoRelease. + shader := DiyaEllipseShader uniqueInstance. ] { #category : #accessing } @@ -71,36 +69,27 @@ DiyaEllipse >> ry: anObject [ dirty := true ] +{ #category : #initialization } +DiyaEllipse >> setUpShader [ + super setUpShader. + self shader + setUniform: #u_border value: border; + setUniform: #u_border_color value: bcolor asGL4FArray; + setUniform: #u_rx value: rx; + setUniform: #u_ry value: ry. +] + { #category : #accessing } DiyaEllipse >> update [ - |theta c s x y index t| - bbox := Rectangle origin: ((rx negated) @ (ry negated)) / 2.0 corner: (rx @ ry) / 2.0. - theta := 2.0 * (Float pi) / 360.0. - c := theta cos. - s := theta sin. - x := 1. - y := 0. - index := 1. - 0 to: 360 do:[:a| - vbuffer - at: index + 4 put: x * rx; - at: index + 5 put: y * ry; - at: index + 6 put: 0.0; - at: index + 7 put: 0.0. - t := x. - x := (c * x) - (s * y). - y := (s * t) + (c * y). - vbuffer - at: index put: x*rx; - at: index + 1 put: y*ry; - at: index + 2 put: 0.0; - at: index + 3 put: 0.0; - - at: index + 8 put: 0.0; - at: index + 9 put: 0.0; - at: index + 10 put: 0.0; - at: index + 11 put: 0.0. - index := index + 12. - ]. + bbox := Rectangle origin: ((rx negated) @ (ry negated)) corner: (rx @ ry). + { + bbox origin x. bbox corner y. 0.0. 0.0. + bbox origin x. bbox origin y. 0.0. 1.0. + bbox corner x. bbox origin y. 1.0. 1.0. + + bbox corner x. bbox origin y. 1.0. 1.0. + bbox corner x. bbox corner y. 1.0. 0.0. + bbox origin x. bbox corner y. 0.0. 0.0. + } doWithIndex: [:e :i| vbuffer at: i put: e]. ^true ] diff --git a/Diya/DiyaEllipseShader.class.st b/Diya/DiyaEllipseShader.class.st new file mode 100644 index 0000000..5c6b49a --- /dev/null +++ b/Diya/DiyaEllipseShader.class.st @@ -0,0 +1,146 @@ +Class { + #name : #DiyaEllipseShader, + #superclass : #Diya2DShader, + #category : #'Diya-Shaders' +} + +{ #category : #accessing } +DiyaEllipseShader class >> fragmentShader [ + ^' +#ifdef GL_ES + precision highp float; +#endif + +uniform vec2 u_resolution; +uniform vec2 u_mouse; +uniform float u_time; +// 2D uniforms +uniform int u_texture_type; +uniform vec4 u_color; +uniform vec4 u_border_color; +uniform sampler2D u_texture; +uniform float u_border; +uniform float u_rx; +uniform float u_ry; +varying float rotation; +varying vec2 middle; +varying vec2 texcoord; +struct Ellipse +{ + vec2 c; + float minor; + float major; + float f; +}; +float get_foci(float major, float minor) +{ + return sqrt((major*major)-(minor*minor)); +} +Ellipse create_ellipse(vec2 c, float mi, float ma) +{ + Ellipse e; + e.c = c; + e.major = max(mi,ma); + e.minor = min(mi,ma); + e.f = get_foci(e.major, e.minor); + return e; +} +bool is_inside_ellipse(vec2 p, Ellipse e) +{ + float first = ((p.x-e.c.x)*(p.x-e.c.x)) / (e.major*e.major); + float second = ((p.y-e.c.y)*(p.y-e.c.y)) / (e.minor*e.minor); + return first+second <= 1.0; +} + +bool is_inside_border(vec2 p, Ellipse e, float w) +{ + float first = ((p.x-e.c.x)*(p.x-e.c.x)) / ((e.major-w)*(e.major-w)); + float second = ((p.y-e.c.y)*(p.y-e.c.y)) / ((e.minor-w)*(e.minor-w)); + float sum = first + second; + return sum<= 1.0; +} + +void draw_ellipse(inout vec4 c, vec2 p, Ellipse e, float border) +{ + c = vec4(0); + if (is_inside_border(p,e, border)) + { + vec4 texcolor = vec4(1); + // vec2 uv = (p - (e.c - vec2(e.major , e.minor))) / vec2(e.major*2.0, e.minor*2.0); + // alpha + if(u_texture_type == 0x1906) { + texcolor = vec4(1, 1, 1, texture2D(u_texture, texcoord).a); + } + // rgba + else if (u_texture_type == 0x1908){ + texcolor = texture2D(u_texture, texcoord); + } + c = texcolor * u_color; + } + else + { + if (is_inside_ellipse(p, e)) + { + c = u_border_color; + } + } + +} + +vec2 rotate_point(vec2 center, vec2 p,float angle) +{ + float s = sin(angle); + float c = cos(angle); + + // translate point back to origin: + p.x -= center.x; + p.y -= center.y; + + // rotate point + float xnew = p.x * c - p.y * s; + float ynew = p.x * s + p.y * c; + + // translate point back: + p.x = xnew + center.x; + p.y = ynew + center.y; + return p; +} + +void main() { + vec4 color = vec4(0); + //defining ellipse + Ellipse e = create_ellipse(middle, u_ry, u_rx); + draw_ellipse(color, rotate_point(middle, gl_FragCoord.xy, rotation), e, u_border); + // Output to screen + gl_FragColor = color; +} +' +] + +{ #category : #accessing } +DiyaEllipseShader class >> vertexShader [ + ^' +#ifdef GL_ES +precision mediump float; +#endif +uniform mat4 u_projection; +uniform mat3 u_transform; +varying float rotation; +varying vec2 middle; +varying vec2 texcoord; +void main() +{ + vec3 coord_global = u_transform * vec3(gl_Vertex.xy, 1.0); + gl_Position = u_projection * vec4(coord_global.xy, 0, 1.0); + rotation = atan(u_transform[1][0], u_transform[0][0]); + middle = (u_transform * vec3(0.0,0.0,1.0)).xy; + texcoord = gl_Vertex.zw; +}' +] + +{ #category : #initialization } +DiyaEllipseShader >> setUpUniforms [ + super setUpUniforms. + self addUniform: #u_rx of: Uniform1F. + self addUniform: #u_ry of: Uniform1F. +] diff --git a/Diya/DiyaLine.class.st b/Diya/DiyaLine.class.st index f989608..8c2cd65 100644 --- a/Diya/DiyaLine.class.st +++ b/Diya/DiyaLine.class.st @@ -90,9 +90,13 @@ DiyaLine >> to: anObject [ { #category : #accessing } DiyaLine >> update [ |extent| - translation = from ifFalse:[self position: from]. - bbox := (Rectangle origin: 0@0 corner: to - from ). + bbox := (Rectangle origin: from corner: to ). + bbox origin = translation ifFalse:[self position: bbox origin]. + from := from - bbox origin. + to := to - bbox origin. extent := bbox extent. + bbox := (Rectangle origin: 0@0 corner: extent ). + { 0.0. 0.0. 0.0. 0.0. extent x. extent y. 0.0. 0.0. diff --git a/Diya/DiyaPolygon.class.st b/Diya/DiyaPolygon.class.st index 9e44aca..d48192d 100644 --- a/Diya/DiyaPolygon.class.st +++ b/Diya/DiyaPolygon.class.st @@ -1,5 +1,67 @@ Class { #name : #DiyaPolygon, #superclass : #Diya2DPrimShape, + #instVars : [ + 'points' + ], #category : #'Diya-Graphics' } + +{ #category : #'as yet unclassified' } +DiyaPolygon class >> points: points [ + ^self new points: points; yourself +] + +{ #category : #'as yet unclassified' } +DiyaPolygon class >> points: points shader:s [ + ^self new points: points; shader:s; yourself +] + +{ #category : #accessing } +DiyaPolygon >> calculateVertices [ + ^self subclassResponsibility +] + +{ #category : #initialization } +DiyaPolygon >> initialize [ + super initialize. + points := {}. + vbuffer := nil. +] + +{ #category : #accessing } +DiyaPolygon >> points [ + ^ points +] + +{ #category : #accessing } +DiyaPolygon >> points: anObject [ + points := anObject. + dirty := true +] + +{ #category : #accessing } +DiyaPolygon >> recFromPoints [ + |maxX maxY minX minY x y| + maxX := minX := (points at: 1) x. + maxY := minY := (points at: 1) y. + points do: [ :p| + x := p x. + y := p y. + maxX := maxX max: x. + maxY := maxY max: y. + minX := minX min: x. + minY := minY min: y. + ]. + ^ Rectangle origin: minX@minY corner: maxX @ maxY +] + +{ #category : #accessing } +DiyaPolygon >> update [ + bbox := self recFromPoints. + translation = bbox origin ifFalse:[ self position: bbox origin]. + points := points collect:[:e | e - bbox origin]. + bbox := self recFromPoints. + self calculateVertices. + ^true +] diff --git a/Diya/DiyaText.class.st b/Diya/DiyaText.class.st index 49b666d..a7d806a 100644 --- a/Diya/DiyaText.class.st +++ b/Diya/DiyaText.class.st @@ -74,7 +74,7 @@ DiyaText >> drawText [ { #category : #accessing } DiyaText >> extent: v [ - bbox := Rectangle origin: 0@0 corner: v. + bbox := Rectangle origin: 0@0 corner: (v x) @ (v y negated ). dirty := true ] @@ -114,7 +114,7 @@ DiyaText >> getCharsVerticesAt:i offset: offset on: tex2D [ c = (Character space asciiValue) ifTrue:[ offset setX: (offset x + (tex2D spacing ) ) setY: offset y. wrap ifTrue: [ - (offset x + ((self nextSpaceFrom: i + 1) * (tex2D spacing))) > (self extent x) ifTrue: [ + (offset x + ((self nextSpaceFrom: i + 1) * (tex2D fontSize))) > (self extent x) ifTrue: [ offset setX: 0.0 setY: (offset y )- (tex2D linespace)]. ]. ^ {}. diff --git a/Diya/FT2Face.extension.st b/Diya/FT2Face.extension.st new file mode 100644 index 0000000..68497ce --- /dev/null +++ b/Diya/FT2Face.extension.st @@ -0,0 +1,11 @@ +Extension { #name : #FT2Face } + +{ #category : #'*Diya' } +FT2Face >> getFirstChar: gindex [ + ^self ffiCall: #(FT_ULong FT_Get_First_Char(self,FT_UInt *gindex)). +] + +{ #category : #'*Diya' } +FT2Face >> getNextChar: charcode iptr: gindex [ + ^self ffiCall: #( FT_ULong FT_Get_Next_Char(self,FT_ULong charcode,FT_UInt *gindex )). +] diff --git a/Diya/OpenGLFontTex.class.st b/Diya/OpenGLFontTex.class.st index 0f191dc..d4c8b76 100644 --- a/Diya/OpenGLFontTex.class.st +++ b/Diya/OpenGLFontTex.class.st @@ -5,7 +5,8 @@ Class { 'charmap', 'cellw', 'cellh', - 'spacing' + 'spacing', + 'fontSize' ], #pools : [ 'OpenGLConstants', @@ -24,7 +25,8 @@ OpenGLFontTex >> blitPixel8: bitmap at: offset size: size [ size = (0@0) ifTrue:[^self]. 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 - ] + ]. + bitmap free. ] { #category : #accessing } @@ -43,28 +45,34 @@ OpenGLFontTex >> charmap [ ] { #category : #'instance creation' } -OpenGLFontTex >> createBitmapFontFrom: bitmaps metrics: metrics maxBearing: maxbearing [ - |currChar offset| +OpenGLFontTex >> createBitmapFontFrom: glyphs maxBearing: maxbearing [ + |bmp metric offset nrows index element| data ifNotNil: [data free ]. - charmap := OrderedCollection new. - data := FFIExternalArray externalNewType: GLubyte size:cellw * cellh * 256. + 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. - currChar := 1. + index := 1. offset := 0@0. - width := cellw * 16. - height := cellh * 16. - 0 to: 15 do: [ :row| - 0 to: 15 do: [ :col| |glyph| + 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: (((metrics at: currChar) first x asInteger) @ cellh)). + glyph := (DiyaFontGlyph origin: offset extent: ((metric first x asInteger) @ cellh)). glyph - bearing: ((metrics at: currChar) at: 2) asFloatPoint; - advance: ((metrics at: currChar) at: 3) asFloatPoint; + 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 add:glyph. - self blitPixel8: (bitmaps at: currChar) at: (offset x) @ ((offset y) + maxbearing - ((metrics at: currChar) last) ) size: (metrics at: currChar) first. - currChar := currChar + 1. + 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]. ] ]. ] @@ -77,51 +85,62 @@ OpenGLFontTex >> drop [ disable: GL_BLEND. ] +{ #category : #accessing } +OpenGLFontTex >> fontSize [ + ^ fontSize +] + { #category : #'instance creation' } OpenGLFontTex >> fromFace: face ofSize: size [ - |minhang maxbearing rec metrics bitmaps | + |minhang maxbearing rec glyphs iptr charcode w| + fontSize := size. face setPixelWidth:0 height: size. - "set up a buffer for 256 characters" - bitmaps := OrderedCollection new. - metrics := OrderedCollection new. + glyphs := OrderedCollection new. cellw := 0. cellh := 0. minhang := 0. maxbearing := 0. + iptr := FFIExternalArray externalNewType: GLuint size:1. + iptr at:1 put: 0. rec := (FTFaceRec fromHandle: face getHandle). - 0 to: 255 do: [ :c | - |bmp bmpsize| - face loadCharacter: c flags: (1 << 2). - metrics add: { - (((rec glyph metrics width) /64)@ ((rec glyph metrics height) /64)). - (face glyph hBearing). - (face glyph advance). - ((rec glyph metrics horiBearingY) / 64) - }. - maxbearing := maxbearing max: ((rec glyph metrics horiBearingY) / 64). - cellw := cellw max: ((rec glyph metrics width) / 64). - minhang := minhang min: ((( rec glyph metrics horiBearingY) - (rec glyph metrics height )) / 64). - "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. - bitmaps add: bmp. + charcode := face getFirstChar: iptr getHandle. + [ (iptr at: 1) = 0 ] whileFalse: [ + |bmp bmpsize metric| + face loadCharacter: charcode flags: (1 << 2). + w := ((rec glyph metrics width) >> 6). + (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). + cellw := cellw max: w. + 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. ]. cellh := maxbearing - minhang. - spacing := (cellw / 2) asInteger. - self createBitmapFontFrom: bitmaps metrics: metrics maxBearing: maxbearing. - bitmaps do:[:p| p free]. + spacing := (size >> 2) asInteger. + self createBitmapFontFrom: glyphs maxBearing: maxbearing. + iptr free. ] { #category : #accessing } OpenGLFontTex >> getGlyph: c [ - ^(self charmap at: c + 1) + ^(self charmap at: c ifAbsent:[^nil]) ] { #category : #initialization } OpenGLFontTex >> initialize [ super initialize. - charmap := OrderedCollection new. + charmap := Dictionary new. data := nil. level := 0. border := 0.