From b9b9feaa139841287b6253dd023a20efea1e15ba Mon Sep 17 00:00:00 2001 From: manas-yu Date: Fri, 24 Jan 2025 02:23:06 +0530 Subject: [PATCH] inline shift approach --- .../util/parser/html/MathTagHandler.kt | 82 ++++++++++++------- 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/utility/src/main/java/org/oppia/android/util/parser/html/MathTagHandler.kt b/utility/src/main/java/org/oppia/android/util/parser/html/MathTagHandler.kt index 7b71ac6d699..7f17e61c27c 100644 --- a/utility/src/main/java/org/oppia/android/util/parser/html/MathTagHandler.kt +++ b/utility/src/main/java/org/oppia/android/util/parser/html/MathTagHandler.kt @@ -7,9 +7,12 @@ import android.graphics.Paint import android.graphics.drawable.Drawable import android.text.Editable import android.text.Spannable +import android.text.style.DynamicDrawableSpan import android.text.style.ImageSpan +import android.text.style.ReplacementSpan import androidx.core.content.res.ResourcesCompat import io.github.karino2.kotlitex.view.MathExpressionSpan +import java.lang.ref.WeakReference import org.json.JSONObject import org.oppia.android.util.R import org.oppia.android.util.logging.ConsoleLogger @@ -68,7 +71,8 @@ class MathTagHandler( content.rawLatex, lineHeight, type = if (useInlineRendering) INLINE_TEXT_IMAGE else BLOCK_IMAGE - ) + ), + useInlineRendering ) } else { MathExpressionSpan( @@ -149,32 +153,45 @@ class MathTagHandler( } /** An [ImageSpan] that vertically centers a LaTeX drawable within the surrounding text. */ -private class LatexImageSpan(drawable: Drawable) : ImageSpan(drawable) { +private class LatexImageSpan( + private val drawable: Drawable, + private val isInline: Boolean +) : ReplacementSpan() { + companion object { + private const val INLINE_SHIFT_FACTOR = 0.9f // Adjust this value (0.2-0.4) as needed + } override fun getSize( paint: Paint, text: CharSequence, start: Int, end: Int, - fontMetricsInt: Paint.FontMetricsInt? + fm: Paint.FontMetricsInt? ): Int { - val drawable = drawable - val rect = drawable.bounds - - fontMetricsInt?.let { fm -> - val paintMetrics = paint.fontMetricsInt - val fontHeight = paintMetrics.descent - paintMetrics.ascent - val drawableHeight = rect.bottom - rect.top - val centerY = paintMetrics.ascent + fontHeight / 2 - - // Adjust font metrics to center the drawable vertically - fm.ascent = centerY - drawableHeight / 2 - fm.top = fm.ascent - fm.bottom = centerY + drawableHeight / 2 - fm.descent = fm.bottom + val bounds = drawable.bounds + val imageHeight = bounds.height() + val paintMetrics = paint.fontMetricsInt + val textHeight = paintMetrics.descent - paintMetrics.ascent + + fm?.let { metrics -> + if (isInline) { + // Reserve space for inline shift + val verticalShift = (imageHeight - textHeight) / 2 + + (paintMetrics.descent * INLINE_SHIFT_FACTOR).toInt() + metrics.ascent = paintMetrics.ascent - verticalShift + metrics.top = metrics.ascent + metrics.descent = paintMetrics.descent + verticalShift + metrics.bottom = metrics.descent + } else { + // Block mode calculations remain unchanged + val totalHeight = (imageHeight * 1.2).toInt() + metrics.ascent = -totalHeight / 2 + metrics.top = metrics.ascent + metrics.descent = totalHeight / 2 + metrics.bottom = metrics.descent + } } - - return rect.right + return bounds.right } override fun draw( @@ -183,21 +200,28 @@ private class LatexImageSpan(drawable: Drawable) : ImageSpan(drawable) { start: Int, end: Int, x: Float, - top: Int, - y: Int, - bottom: Int, + lineTop: Int, + baseline: Int, + lineBottom: Int, paint: Paint ) { - val drawable = drawable canvas.save() - // Calculate vertical centering - val paintMetrics = paint.fontMetricsInt - val fontHeight = paintMetrics.descent - paintMetrics.ascent - val centerY = y + paintMetrics.descent - fontHeight / 2 - val transY = centerY - (drawable.bounds.bottom - drawable.bounds.top) / 2 + val imageHeight = drawable.bounds.height() + val yPosition = when { + isInline -> { + // Apply downward shift for inline equations + val textMidline = baseline - (paint.fontMetrics.descent - paint.fontMetrics.ascent) / 2 + val shiftOffset = (paint.fontMetricsInt.descent * INLINE_SHIFT_FACTOR).toInt() + textMidline - (imageHeight / 2) + shiftOffset + } + else -> { + // Block mode remains centered + lineTop + (lineBottom - lineTop - imageHeight) / 2 + } + } - canvas.translate(x, transY.toFloat()) + canvas.translate(x, yPosition.toFloat()) drawable.draw(canvas) canvas.restore() }