diff --git a/AndroidMath.iml b/AndroidMath.iml
deleted file mode 100644
index 4e2a15d..0000000
--- a/AndroidMath.iml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index dcd9d11..3e28720 100644
--- a/build.gradle
+++ b/build.gradle
@@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.5.2'
+ classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' // Add this line
diff --git a/mathdisplaylib/mathdisplaylib.iml b/mathdisplaylib/mathdisplaylib.iml
deleted file mode 100644
index 585934b..0000000
--- a/mathdisplaylib/mathdisplaylib.iml
+++ /dev/null
@@ -1,158 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- generateDebugSources
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/mathdisplaylib/src/main/java/com/agog/mathdisplay/MTMathGenerator.kt b/mathdisplaylib/src/main/java/com/agog/mathdisplay/MTMathGenerator.kt
index 383bafb..9e39949 100644
--- a/mathdisplaylib/src/main/java/com/agog/mathdisplay/MTMathGenerator.kt
+++ b/mathdisplaylib/src/main/java/com/agog/mathdisplay/MTMathGenerator.kt
@@ -2,7 +2,7 @@ package com.agog.mathdisplay
import android.graphics.Bitmap
import android.graphics.Canvas
-import android.graphics.Color
+import android.util.Log
import com.agog.mathdisplay.parse.MTLineStyle
import com.agog.mathdisplay.parse.MTMathListBuilder
import com.agog.mathdisplay.render.MTFont
@@ -11,28 +11,30 @@ import com.agog.mathdisplay.render.trim
object MTMathGenerator {
+ private const val TAG = "MTMathGenerator"
private const val defaultWidth = 640
private const val defaultHeight = 480
private const val defaultMargin = 20
private const val defaultFontSize = 20f
var defaultFont: MTFont? = null
+ var isDebugOn: Boolean = false
@JvmStatic
- fun createBitmap(latexString: String): Bitmap? {
+ fun createBitmap(latexString: String, isDebugOn: Boolean = false): Bitmap? {
if (defaultFont == null) initializeDefaultFont()
- return createBitmap(latexString, defaultFont, defaultWidth, defaultHeight, defaultMargin)
+ return createBitmap(latexString, defaultFont, defaultWidth, defaultHeight, defaultMargin, isDebugOn)
}
@JvmStatic
- fun createBitmap(latexString: String, fontColor: Int): Bitmap? {
+ fun createBitmap(latexString: String, fontColor: Int, isDebugOn: Boolean = false): Bitmap? {
defaultFont?.color = fontColor
- return createBitmap(latexString, defaultFont, defaultWidth, defaultHeight, defaultMargin)
+ return createBitmap(latexString, defaultFont, defaultWidth, defaultHeight, defaultMargin, isDebugOn)
}
@JvmStatic
- fun createBitmap(latexString: String, font: MTFont): Bitmap? {
- return createBitmap(latexString, font, defaultWidth, defaultHeight, defaultMargin)
+ fun createBitmap(latexString: String, font: MTFont, isDebugOn: Boolean = false): Bitmap? {
+ return createBitmap(latexString, font, defaultWidth, defaultHeight, defaultMargin, isDebugOn)
}
@JvmStatic
@@ -41,15 +43,19 @@ object MTMathGenerator {
fontParam: MTFont? = defaultFont,
bitmapWidth: Int = defaultWidth,
bitmapHeight: Int = defaultHeight,
- bitmapMargin: Int = defaultMargin
+ bitmapMargin: Int = defaultMargin,
+ isDebugOn: Boolean = false
): Bitmap? {
+ this.isDebugOn = isDebugOn
+ if (!passScreening(latexString)) return null
+
var font = fontParam
if (defaultFont == null) {
initializeDefaultFont()
if (font == null) font = defaultFont
}
- val mathList = MTMathListBuilder.buildFromString(latexString)
+ val mathList = MTMathListBuilder.buildFromString(sanitize(latexString))
if (mathList != null && font != null) {
val bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888)
@@ -68,9 +74,60 @@ object MTMathGenerator {
return null
}
+ private fun passScreening(latexString: String): Boolean {
+ val str = latexString.toLowerCase()
+
+ if (str.contains("\\color")) {
+ log("[filter] denied \\color syntax on: $str")
+ return false
+ }
+
+ if (str.contains("{array}")) {
+ log("[filter] denied {array} syntax on: $str")
+ return false
+ }
+
+ if (str.contains("matrix}")) {
+ log("[filter] denied *matrix} syntax on: $str")
+ return false
+ }
+
+ if (str.contains("\\cancel}")) {
+ log("[filter] denied \\cancel syntax on: $str")
+ return false
+ }
+
+ return true
+ }
+
+ private fun log(message: String) {
+ if (isDebugOn) {
+ Log.i(TAG, message)
+ }
+ }
+
private fun initializeDefaultFont() {
if (defaultFont == null) {
defaultFont = MTFontManager.latinModernFontWithSize(defaultFontSize)
}
}
+
+ private fun sanitize(str: String): String {
+ var sanitizedStr = str
+ log("[sanitize] before : $sanitizedStr")
+
+ // convert to single line
+ sanitizedStr = sanitizedStr.replace("\n", "")
+ sanitizedStr = sanitizedStr.replace("\r", "")
+
+ // fix long minus sign
+ sanitizedStr = sanitizedStr.replace("−", "-")
+
+ // fix align
+ sanitizedStr = sanitizedStr.replace("{align}", "{aligned}")
+ sanitizedStr = sanitizedStr.replace("{align*}", "{aligned}")
+
+ log("[sanitize] after : $sanitizedStr")
+ return sanitizedStr
+ }
}
diff --git a/sampleapp/build.gradle b/sampleapp/build.gradle
index b3845d0..5b96bba 100644
--- a/sampleapp/build.gradle
+++ b/sampleapp/build.gradle
@@ -3,12 +3,10 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
-
android {
compileSdkVersion 27
-
defaultConfig {
applicationId "com.agog.latexmathsample"
minSdkVersion 23
@@ -39,4 +37,3 @@ dependencies {
androidTestImplementation 'com.android.support.test:runner:1.0.1'
implementation project(':mathdisplaylib')
}
-
diff --git a/sampleapp/sampleapp.iml b/sampleapp/sampleapp.iml
deleted file mode 100644
index 46b422e..0000000
--- a/sampleapp/sampleapp.iml
+++ /dev/null
@@ -1,164 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- generateDebugSources
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/sampleapp/src/main/AndroidManifest.xml b/sampleapp/src/main/AndroidManifest.xml
index a8c62f5..9497db6 100644
--- a/sampleapp/src/main/AndroidManifest.xml
+++ b/sampleapp/src/main/AndroidManifest.xml
@@ -9,8 +9,9 @@
android:roundIcon="@mipmap/icon"
android:supportsRtl="true"
android:theme="@style/AppTheme">
+
diff --git a/sampleapp/src/main/java/com/agog/latexmathsample/CheckActivity.kt b/sampleapp/src/main/java/com/agog/latexmathsample/CheckActivity.kt
new file mode 100644
index 0000000..1885511
--- /dev/null
+++ b/sampleapp/src/main/java/com/agog/latexmathsample/CheckActivity.kt
@@ -0,0 +1,145 @@
+package com.agog.latexmathsample
+
+import android.content.Context
+import android.content.Intent
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.graphics.Matrix
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.Drawable
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import com.agog.mathdisplay.MTMathGenerator
+import kotlinx.android.synthetic.main.activity_check.*
+
+
+class CheckActivity : AppCompatActivity() {
+
+ companion object {
+ fun createIntent(context: Context): Intent {
+ return Intent(context, CheckActivity::class.java)
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_check)
+
+ checkLatexCompatibility()
+ }
+
+ private fun bitmapToDrawable(bitmap: Bitmap): Drawable {
+ val drawable = BitmapDrawable(resources, bitmap)
+ drawable.setBounds(0, 0, bitmap.width, bitmap.height)
+
+ return drawable
+ }
+
+ private fun checkLatexCompatibility() {
+ val layoutPad = 16
+ val layoutParams = LinearLayout.LayoutParams(0, 0)
+ layoutParams.setMargins(layoutPad, layoutPad, layoutPad, layoutPad)
+
+ val inputStream = resources.openRawResource(R.raw.checklatex)
+ val lineList = mutableListOf()
+
+ inputStream.bufferedReader().useLines { lines -> lines.forEach { lineList.add(it) } }
+
+ // create test(s) from checklatex.txt file
+ lineList.forEach {
+ if (it.isNotBlank()) {
+ if (it[0] == '#') {
+ val tv = TextView(this)
+ tv.text = it.trim()
+ tv.setTextColor(Color.DKGRAY)
+ println("textSize ${tv.textSize}")
+ checkLatexLayout.addView(tv)
+ } else {
+ createLatexImageView(it)
+
+ }
+ }
+ }
+
+ runMultilineTest()
+ }
+
+ private fun createLatexImageView(strLatex: String) {
+ val latexBitmap: Bitmap? = MTMathGenerator.createBitmap(strLatex, isDebugOn = true)
+
+ if (latexBitmap != null) {
+ val latexImageView = createImageView(latexBitmap)
+ checkLatexLayout.addView(latexImageView)
+ } else {
+ val errorRenderTV = TextView(this)
+ errorRenderTV.text = "error rendering: $strLatex"
+ errorRenderTV.setTextColor(Color.RED)
+ checkLatexLayout.addView(errorRenderTV)
+ }
+ }
+
+ private fun runMultilineTest() {
+ val multilineStr = "\\left|\\begin{matrix}\n" +
+ "6 & 1 & 3\\\\ \n" +
+ "2 & 3 & 2\\\\ \n" +
+ "1 & 1 & 0\\end{matrix}\\right|\n" +
+ "=\n" +
+ "\\left|\\begin{matrix}\n" +
+ "\\require{cancel}\\cancel{6} & \\require{cancel}\\cancel{1} & \\require{cancel}\\cancel{3}\\\\ \n" +
+ "\\require{cancel}\\cancel{2} & \\require{cancel}\\cancel{3} & \\require{cancel}\\cancel{2}\\\\ \n" +
+ "\\require{cancel}\\cancel{1} & \\require{cancel}\\cancel{1} & \\require{cancel}\\cancel{0}\\end{matrix}\\right|\n" +
+ "\\begin{matrix}\\require{cancel}\\cancel{6} & \\require{cancel}\\cancel{1}\\\\ \n" +
+ "\\require{cancel}\\cancel{2} & \\require{cancel}\\cancel{3} \\\\ \n" +
+ "\\require{cancel}\\cancel{1} & \\require{cancel}\\cancel{1}\\end{matrix} "
+
+ createLatexImageView(multilineStr)
+ }
+
+ // from this: https://stackoverflow.com/questions/8232608/fit-image-into-imageview-keep-aspect-ratio-and-then-resize-imageview-to-image-d
+ // change it to have bitmap as param and return new ImageView instead
+ @Throws(NoSuchElementException::class)
+ private fun createImageView(bitmap: Bitmap): ImageView { // Get bitmap from the the ImageView.
+ val imageView = ImageView(this)
+ imageView.setImageBitmap(bitmap)
+
+ val drawing = imageView.drawable
+ val viewBitmap = (drawing as BitmapDrawable).bitmap
+
+ // Get current dimensions AND the desired bounding box
+ var width = viewBitmap.width
+ var height = viewBitmap.height
+ val bounding = dpToPx(120)
+ val xScale = bounding.toFloat() / width
+ val yScale = bounding.toFloat() / height
+ val scale = if (xScale <= yScale) xScale else yScale
+
+ // Create a matrix for the scaling and add the scaling data
+ val matrix = Matrix()
+ matrix.postScale(scale, scale)
+
+ // Create a new bitmap and convert it to a format understood by the ImageView
+ val scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true)
+ width = scaledBitmap.width // re-use
+ height = scaledBitmap.height // re-use
+ val result = BitmapDrawable(scaledBitmap)
+
+ // Apply the scaled bitmap
+ imageView.setImageDrawable(result)
+
+ // Now change ImageView's dimensions to match the scaled image
+ val params = LinearLayout.LayoutParams(0, 0)
+ params.width = width
+ params.height = height
+ imageView.layoutParams = params
+
+ return imageView
+ }
+
+ private fun dpToPx(dp: Int): Int {
+ val density = applicationContext.resources.displayMetrics.density
+ return Math.round(dp.toFloat() * density)
+ }
+}
diff --git a/sampleapp/src/main/java/com/agog/latexmathsample/MainActivity.kt b/sampleapp/src/main/java/com/agog/latexmathsample/MainActivity.kt
index f870a2c..023ff45 100644
--- a/sampleapp/src/main/java/com/agog/latexmathsample/MainActivity.kt
+++ b/sampleapp/src/main/java/com/agog/latexmathsample/MainActivity.kt
@@ -8,6 +8,7 @@ import android.view.MenuItem
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
+import android.widget.Toast
import com.agog.mathdisplay.MTFontManager
import com.agog.mathdisplay.MTMathGenerator
import com.agog.mathdisplay.MTMathView
@@ -199,6 +200,11 @@ class MainActivity : AppCompatActivity() {
}
return true
}
+ R.id.checkMenu -> {
+ val checkActivityIntent = CheckActivity.createIntent(this)
+ startActivity(checkActivityIntent)
+ return true
+ }
else -> super.onOptionsItemSelected(item)
diff --git a/sampleapp/src/main/res/layout/activity_check.xml b/sampleapp/src/main/res/layout/activity_check.xml
new file mode 100644
index 0000000..86ffde7
--- /dev/null
+++ b/sampleapp/src/main/res/layout/activity_check.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sampleapp/src/main/res/menu/menu_main.xml b/sampleapp/src/main/res/menu/menu_main.xml
index 41d936d..a45f42b 100644
--- a/sampleapp/src/main/res/menu/menu_main.xml
+++ b/sampleapp/src/main/res/menu/menu_main.xml
@@ -4,8 +4,8 @@
tools:context="com.agog.latexmathsample.com.agog.latexmath.MainActivity">
-
-
-
diff --git a/sampleapp/src/main/res/raw/checklatex.txt b/sampleapp/src/main/res/raw/checklatex.txt
new file mode 100644
index 0000000..ccf3a7a
--- /dev/null
+++ b/sampleapp/src/main/res/raw/checklatex.txt
@@ -0,0 +1,7 @@
+# -- Require Cancel Command --
+
+# cancel command?
+
+\cancel{1}
+
+# cancel not supported