@@ -29,6 +29,7 @@ import java.nio.FloatBuffer
2929import kotlin.math.cos
3030import kotlin.math.roundToInt
3131import kotlin.math.sin
32+ import kotlin.math.sqrt
3233import kotlin.math.tan
3334
3435private val LOGGER = LogManager .getLogger(" PolyUI/GLRenderer" )
@@ -101,18 +102,17 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
101102 private var count = 0
102103 private var curTex = 0
103104 private var transformDepth = 0
104- private var curScissor = 0
105+ private var scissorDepth = 0
105106 private var transform = IDENTITY .copyOf()
106107 private var viewportWidth = 0f
107108 private var viewportHeight = 0f
108109 private var pixelRatio = 1f
109110 private var alphaCap = 1f
110111 private var popFlushNeeded = false
111112
113+ // atlas data
112114 private var slotX = 0
113115 private var slotY = 0
114-
115- /* * current max height of the currently active row in the atlas. */
116116 private var atlasRowHeight = 0
117117
118118 private val FRAG = """
@@ -149,24 +149,24 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
149149 float rRight = mix(r.z, r.y, py); // bottom-right / top-right
150150 float radius = mix(rLeft, rRight, px);
151151
152- vec2 q = abs(p) - (b - vec2( radius) );
152+ vec2 q = abs(p) - (b - radius);
153153 return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;
154154 }
155155
156156 float hollowRoundedBoxSDF(vec2 p, vec2 b, vec4 r, float thickness) {
157- float outer = roundedBoxSDF(p, b + vec2( 0.2) , r);
158- float inner = roundedBoxSDF(p, b - vec2( thickness) , max(r - vec4( thickness) , 0.0));
157+ float outer = roundedBoxSDF(p, b + 0.2, r + 0.2 );
158+ float inner = roundedBoxSDF(p, b - thickness, max(r - thickness, 0.0));
159159 return max(outer, -inner);
160160 }
161161
162162 float roundBoxSDF(vec2 p, vec2 halfSize, float radius) {
163- vec2 q = abs(p) - (halfSize - vec2( radius) );
163+ vec2 q = abs(p) - (halfSize - radius);
164164 return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;
165165 }
166166
167167 void main() {
168- vec2 center = vRect.xy + 0.5 * vRect.zw;
169168 vec2 halfSize = 0.5 * vRect.zw;
169+ vec2 center = vRect.xy + halfSize;
170170 vec2 p = vPos - center;
171171
172172 float d = (vThickness > 0.0) ? hollowRoundedBoxSDF(p, halfSize, vRadii, vThickness) : roundedBoxSDF(p, halfSize, vRadii);
@@ -193,6 +193,10 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
193193 float t = clamp((dist + vUV.y * 0.5) / vUV.y, 0.0, 1.0);
194194 col = mix(vColor0, vColor1, t);
195195 }
196+ else if (vThickness == -5.0) { // drop shadow, vUV.x as spread and vUV.y as blur
197+ float dShadow = roundBoxSDF(p, halfSize + vUV.x, vRadii.x);
198+ col = vec4(vColor0.rgb, vColor0.a * (1.0 - smoothstep(-vUV.y, vUV.y, dShadow)));
199+ }
196200
197201 // Proper antialiasing based on distance field
198202 float f = fwidth(d);
@@ -404,11 +408,12 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
404408 }
405409
406410 override fun beginFrame (width : Float , height : Float , pixelRatio : Float ) {
407- curScissor = 0
411+ scissorDepth = 0
408412 alphaCap = 1f
409413 count = 0
410414 buffer.clear()
411415 transform.set(IDENTITY )
416+ popFlushNeeded = false
412417 transformDepth = 0
413418 val prevProg = glGetInteger(GL_CURRENT_PROGRAM )
414419 glUseProgram(program)
@@ -608,6 +613,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
608613
609614 override fun text (font : Font , x : Float , y : Float , text : String , color : Color , fontSize : Float ) {
610615 val fAtlas = getFontAtlas(font, fontSize)
616+ val s = transformScale()
617+ val fAtlasForRendering = if (s == 1f ) fAtlas else getFontAtlas(font, fontSize * s)
611618 if (count >= MAX_BATCH ) flush()
612619 if (count > 0 && curTex != atlas) flush()
613620 curTex = atlas
@@ -631,7 +638,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
631638 buffer.put(EMPTY_ROW ) // zero radii
632639 buffer.put(r).put(g).put(b).put(a)
633640 buffer.put(EMPTY_ROW ) // color1 unused
634- buffer.put(glyph, 0 , 4 )
641+ buffer.put(if (s == 1f ) glyph else fAtlasForRendering.get(c) , 0 , 4 )
635642 buffer.put(- 1f ) // thickness = -1 for text
636643 penX + = glyph.xAdvance * scaleFactor
637644 count + = 1
@@ -656,7 +663,14 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
656663 spread : Float ,
657664 radius : Float
658665 ) {
659- // rect(x, y, width, height, )
666+ if (count >= MAX_BATCH ) flush()
667+ buffer.put(x).put(y).put(width).put(height)
668+ buffer.put(EMPTY_ROW ) // zero radii
669+ buffer.put(0f ).put(0f ).put(0f ).put(alphaCap) // black, alpha to alphaCap
670+ buffer.put(EMPTY_ROW ) // color1 unused
671+ buffer.put(spread).put(blur).put(0f ).put(0f )
672+ buffer.put(- 5f ) // thickness = -5 for drop shadow
673+ count + = 1
660674 }
661675
662676 override fun pushScissor (x : Float , y : Float , width : Float , height : Float ) {
@@ -665,24 +679,24 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
665679 val ny = (viewportHeight - (y + height) * pixelRatio).roundToInt()
666680 val nw = (width * pixelRatio).roundToInt()
667681 val nh = (height * pixelRatio).roundToInt()
668- scissorStack[curScissor ++ ] = nx
669- scissorStack[curScissor ++ ] = ny
670- scissorStack[curScissor ++ ] = nw
671- scissorStack[curScissor ++ ] = nh
682+ scissorStack[scissorDepth ++ ] = nx
683+ scissorStack[scissorDepth ++ ] = ny
684+ scissorStack[scissorDepth ++ ] = nw
685+ scissorStack[scissorDepth ++ ] = nh
672686 glEnable(GL_SCISSOR_TEST )
673687 glScissor(nx, ny, nw, nh)
674688 }
675689
676690 override fun pushScissorIntersecting (x : Float , y : Float , width : Float , height : Float ) {
677- if (curScissor < 4 ) {
691+ if (scissorDepth < 4 ) {
678692 pushScissor(x, y, width, height)
679693 return
680694 }
681695 flush()
682- val px = scissorStack[curScissor - 4 ]
683- val py = scissorStack[curScissor - 3 ]
684- val pw = scissorStack[curScissor - 2 ]
685- val ph = scissorStack[curScissor - 1 ]
696+ val px = scissorStack[scissorDepth - 4 ]
697+ val py = scissorStack[scissorDepth - 3 ]
698+ val pw = scissorStack[scissorDepth - 2 ]
699+ val ph = scissorStack[scissorDepth - 1 ]
686700 val nx = (x * pixelRatio).roundToInt()
687701 val ny = (viewportHeight - (y + height) * pixelRatio).roundToInt()
688702
@@ -691,27 +705,27 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
691705 val iw = maxOf(0 , minOf(nx + (width * pixelRatio).roundToInt(), px + pw) - ix)
692706 val ih = maxOf(0 , minOf(ny + (height * pixelRatio).roundToInt(), py + ph) - iy)
693707
694- scissorStack[curScissor ++ ] = ix
695- scissorStack[curScissor ++ ] = iy
696- scissorStack[curScissor ++ ] = iw
697- scissorStack[curScissor ++ ] = ih
708+ scissorStack[scissorDepth ++ ] = ix
709+ scissorStack[scissorDepth ++ ] = iy
710+ scissorStack[scissorDepth ++ ] = iw
711+ scissorStack[scissorDepth ++ ] = ih
698712
699713 glEnable(GL_SCISSOR_TEST )
700714 glScissor(ix, iy, iw, ih)
701715 }
702716
703717 override fun popScissor () {
704718 flush()
705- if (curScissor <= 4 ) {
706- curScissor = 0
719+ if (scissorDepth <= 4 ) {
720+ scissorDepth = 0
707721 glDisable(GL_SCISSOR_TEST )
708722 return
709723 }
710- curScissor - = 4
711- val x = scissorStack[curScissor - 4 ]
712- val y = scissorStack[curScissor - 3 ]
713- val width = scissorStack[curScissor - 2 ]
714- val height = scissorStack[curScissor - 1 ]
724+ scissorDepth - = 4
725+ val x = scissorStack[scissorDepth - 4 ]
726+ val y = scissorStack[scissorDepth - 3 ]
727+ val width = scissorStack[scissorDepth - 2 ]
728+ val height = scissorStack[scissorDepth - 1 ]
715729 glEnable(GL_SCISSOR_TEST )
716730 glScissor(x, y, width, height)
717731 }
@@ -740,6 +754,12 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
740754 popFlushNeeded = true
741755 }
742756
757+ private fun transformScale (): Float {
758+ val sx = sqrt(transform[0 ] * transform[0 ] + transform[3 ] * transform[3 ])
759+ val sy = sqrt(transform[1 ] * transform[1 ] + transform[4 ] * transform[4 ])
760+ return (sx + sy) * 0.5f
761+ }
762+
743763 override fun translate (x : Float , y : Float ) {
744764 flush()
745765 transform[6 ] + = transform[0 ] * x + transform[3 ] * y
0 commit comments