2018-01-04 19:52:25 +01:00
|
|
|
package jp.juggler.subwaytooter.span
|
|
|
|
|
|
|
|
import android.content.Context
|
2018-04-21 01:16:44 +02:00
|
|
|
import android.graphics.*
|
2018-01-04 19:52:25 +01:00
|
|
|
import android.graphics.drawable.Drawable
|
2019-02-15 02:51:22 +01:00
|
|
|
import androidx.annotation.IntRange
|
|
|
|
import androidx.core.content.ContextCompat
|
2018-01-04 19:52:25 +01:00
|
|
|
import android.text.style.ReplacementSpan
|
|
|
|
|
|
|
|
import java.lang.ref.WeakReference
|
|
|
|
|
2018-04-21 01:16:44 +02:00
|
|
|
class EmojiImageSpan(
|
|
|
|
context : Context,
|
|
|
|
private val res_id : Int,
|
2018-10-28 14:08:10 +01:00
|
|
|
private val useColorShader : Boolean = false,
|
|
|
|
private val color : Int? = null
|
2018-04-21 01:16:44 +02:00
|
|
|
) : ReplacementSpan() {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
companion object {
|
|
|
|
|
2018-01-28 20:03:04 +01:00
|
|
|
// private static final LogCategory warning = new LogCategory( "EmojiImageSpan" );
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
// static DynamicDrawableSpan x = null;
|
|
|
|
|
|
|
|
private const val scale_ratio = 1.14f
|
|
|
|
private const val descent_ratio = 0.211f
|
2018-04-23 13:59:18 +02:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private val context : Context
|
|
|
|
private var mDrawableRef : WeakReference<Drawable>? = null
|
|
|
|
|
|
|
|
private val cachedDrawable : Drawable?
|
|
|
|
get() {
|
|
|
|
var d = mDrawableRef?.get()
|
|
|
|
if(d == null) {
|
|
|
|
d = ContextCompat.getDrawable(context, res_id) ?: return null
|
|
|
|
mDrawableRef = WeakReference(d)
|
|
|
|
}
|
|
|
|
return d
|
|
|
|
}
|
|
|
|
|
|
|
|
init {
|
|
|
|
this.context = context.applicationContext
|
|
|
|
}
|
|
|
|
|
2018-04-23 13:59:18 +02:00
|
|
|
private fun getImageSize(paint : Paint) = (0.5f + scale_ratio * paint.textSize).toInt()
|
2018-01-18 19:34:14 +01:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
override fun getSize(
|
2018-01-18 19:34:14 +01:00
|
|
|
paint : Paint,
|
|
|
|
text : CharSequence,
|
|
|
|
@IntRange(from = 0) start : Int,
|
|
|
|
@IntRange(from = 0) end : Int,
|
|
|
|
fm : Paint.FontMetricsInt?
|
2018-01-04 19:52:25 +01:00
|
|
|
) : Int {
|
2018-01-18 19:34:14 +01:00
|
|
|
val size = getImageSize(paint)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
if(fm != null) {
|
|
|
|
val c_descent = (0.5f + size * descent_ratio).toInt()
|
|
|
|
val c_ascent = c_descent - size
|
|
|
|
if(fm.ascent > c_ascent) fm.ascent = c_ascent
|
|
|
|
if(fm.top > c_ascent) fm.top = c_ascent
|
|
|
|
if(fm.descent < c_descent) fm.descent = c_descent
|
|
|
|
if(fm.bottom < c_descent) fm.bottom = c_descent
|
|
|
|
}
|
|
|
|
return size
|
|
|
|
}
|
|
|
|
|
2018-04-23 13:59:18 +02:00
|
|
|
private var lastColor : Int? = null
|
|
|
|
private var lastColorFilter : PorterDuffColorFilter? = null
|
2018-04-21 01:16:44 +02:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
override fun draw(
|
2018-01-18 19:34:14 +01:00
|
|
|
canvas : Canvas,
|
|
|
|
text : CharSequence,
|
|
|
|
start : Int,
|
|
|
|
end : Int,
|
|
|
|
x : Float,
|
|
|
|
top : Int,
|
|
|
|
baseline : Int,
|
|
|
|
bottom : Int,
|
|
|
|
paint : Paint
|
2018-01-04 19:52:25 +01:00
|
|
|
) {
|
2018-01-18 19:34:14 +01:00
|
|
|
val d = cachedDrawable ?: return
|
2018-04-23 13:59:18 +02:00
|
|
|
|
2018-01-18 19:34:14 +01:00
|
|
|
val size = getImageSize(paint)
|
2018-01-04 19:52:25 +01:00
|
|
|
val c_descent = (0.5f + size * descent_ratio).toInt()
|
|
|
|
val transY = baseline - size + c_descent
|
|
|
|
|
|
|
|
canvas.save()
|
|
|
|
canvas.translate(x, transY.toFloat())
|
|
|
|
d.setBounds(0, 0, size, size)
|
2018-04-21 01:16:44 +02:00
|
|
|
|
2018-04-23 13:59:18 +02:00
|
|
|
if(useColorShader) {
|
2018-10-28 14:08:10 +01:00
|
|
|
val pc:Int
|
|
|
|
val pa:Int
|
|
|
|
if( color ==null) {
|
|
|
|
pc = paint.color
|
|
|
|
pa = paint.alpha
|
|
|
|
}else{
|
|
|
|
pc = color or Color.BLACK
|
|
|
|
pa = color ushr 24
|
|
|
|
}
|
2018-04-23 13:59:18 +02:00
|
|
|
// Log.d("EmojiImageSpan",String.format("paint c=0x%x a=0x%x",pc,pa))
|
|
|
|
if(pc != lastColor || lastColorFilter == null) {
|
|
|
|
lastColor = pc
|
|
|
|
lastColorFilter = PorterDuffColorFilter( pc or Color.BLACK , PorterDuff.Mode.SRC_ATOP)
|
2018-04-21 01:16:44 +02:00
|
|
|
}
|
|
|
|
val saveColorFilter = d.colorFilter
|
2018-04-23 13:59:18 +02:00
|
|
|
val saveAlpha = d.alpha
|
2018-04-21 01:16:44 +02:00
|
|
|
d.colorFilter = lastColorFilter
|
2018-04-23 13:59:18 +02:00
|
|
|
d.alpha = pa
|
2018-04-21 01:16:44 +02:00
|
|
|
d.draw(canvas)
|
|
|
|
d.colorFilter = saveColorFilter
|
2018-04-23 13:59:18 +02:00
|
|
|
d.alpha = saveAlpha
|
|
|
|
} else {
|
2018-04-21 01:16:44 +02:00
|
|
|
d.draw(canvas)
|
|
|
|
}
|
2018-01-04 19:52:25 +01:00
|
|
|
canvas.restore()
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|