@@ -7,12 +7,9 @@ import android.graphics.Paint
77import android.graphics.drawable.Drawable
88import android.text.Editable
99import android.text.Spannable
10- import android.text.style.DynamicDrawableSpan
1110import android.text.style.ImageSpan
12- import android.text.style.ReplacementSpan
1311import androidx.core.content.res.ResourcesCompat
1412import io.github.karino2.kotlitex.view.MathExpressionSpan
15- import java.lang.ref.WeakReference
1613import org.json.JSONObject
1714import org.oppia.android.util.R
1815import org.oppia.android.util.logging.ConsoleLogger
@@ -154,44 +151,56 @@ class MathTagHandler(
154151
155152/* * An [ImageSpan] that vertically centers a LaTeX drawable within the surrounding text. */
156153private class LatexImageSpan (
157- private val drawable : Drawable ,
158- private val isInline : Boolean
159- ) : ReplacementSpan() {
154+ imageDrawable : Drawable ? ,
155+ private val isInlineMode : Boolean
156+ ) : ImageSpan(imageDrawable ? : createEmptyDrawable()) {
157+
160158 companion object {
161- private const val INLINE_SHIFT_FACTOR = 0.9f // Adjust this value (0.2-0.4) as needed
159+ private const val INLINE_VERTICAL_SHIFT_RATIO = 0.9f
160+
161+ private fun createEmptyDrawable (): Drawable {
162+ return object : Drawable () {
163+ override fun draw (canvas : Canvas ) {}
164+ override fun setAlpha (alpha : Int ) {}
165+ override fun setColorFilter (colorFilter : android.graphics.ColorFilter ? ) {}
166+ override fun getOpacity (): Int = android.graphics.PixelFormat .TRANSPARENT
167+
168+ init {
169+ setBounds(0 , 0 , 1 , 1 )
170+ }
171+ }
172+ }
162173 }
163174
164175 override fun getSize (
165176 paint : Paint ,
166177 text : CharSequence ,
167178 start : Int ,
168179 end : Int ,
169- fm : Paint .FontMetricsInt ?
180+ fontMetrics : Paint .FontMetricsInt ?
170181 ): Int {
171- val bounds = drawable.bounds
172- val imageHeight = bounds.height()
173- val paintMetrics = paint.fontMetricsInt
174- val textHeight = paintMetrics.descent - paintMetrics.ascent
175-
176- fm?.let { metrics ->
177- if (isInline) {
178- // Reserve space for inline shift
182+ val drawableBounds = drawable.bounds
183+ val imageHeight = drawableBounds.height()
184+ val textMetrics = paint.fontMetricsInt
185+ val textHeight = textMetrics.descent - textMetrics.ascent
186+
187+ fontMetrics?.let { metrics ->
188+ if (isInlineMode) {
179189 val verticalShift = (imageHeight - textHeight) / 2 +
180- (paintMetrics .descent * INLINE_SHIFT_FACTOR ).toInt()
181- metrics.ascent = paintMetrics .ascent - verticalShift
190+ (textMetrics .descent * INLINE_VERTICAL_SHIFT_RATIO ).toInt()
191+ metrics.ascent = textMetrics .ascent - verticalShift
182192 metrics.top = metrics.ascent
183- metrics.descent = paintMetrics .descent + verticalShift
193+ metrics.descent = textMetrics .descent + verticalShift
184194 metrics.bottom = metrics.descent
185195 } else {
186- // Block mode calculations remain unchanged
187196 val totalHeight = (imageHeight * 1.2 ).toInt()
188197 metrics.ascent = - totalHeight / 2
189198 metrics.top = metrics.ascent
190199 metrics.descent = totalHeight / 2
191200 metrics.bottom = metrics.descent
192201 }
193202 }
194- return bounds .right
203+ return drawableBounds .right
195204 }
196205
197206 override fun draw (
@@ -208,20 +217,17 @@ private class LatexImageSpan(
208217 canvas.save()
209218
210219 val imageHeight = drawable.bounds.height()
211- val yPosition = when {
212- isInline -> {
213- // Apply downward shift for inline equations
214- val textMidline = baseline - (paint.fontMetrics.descent - paint.fontMetrics.ascent) / 2
215- val shiftOffset = (paint.fontMetricsInt.descent * INLINE_SHIFT_FACTOR ).toInt()
216- textMidline - (imageHeight / 2 ) + shiftOffset
217- }
218- else -> {
219- // Block mode remains centered
220- lineTop + (lineBottom - lineTop - imageHeight) / 2
221- }
220+ val yOffset = if (isInlineMode) {
221+ val metrics = paint.fontMetricsInt
222+ val ascent = metrics.ascent.toFloat()
223+ val descent = metrics.descent.toFloat()
224+ val expectedCenterY = baseline.toFloat() + (ascent + descent) / 2f
225+ expectedCenterY - (imageHeight / 2f )
226+ } else {
227+ lineTop.toFloat() + (lineBottom - lineTop - imageHeight) / 2f
222228 }
223229
224- canvas.translate(x, yPosition.toFloat() )
230+ canvas.translate(x, yOffset )
225231 drawable.draw(canvas)
226232 canvas.restore()
227233 }
0 commit comments