Skip to content

Commit d48ca08

Browse files
committed
cr 1
1 parent ab5c43e commit d48ca08

File tree

3 files changed

+138
-16
lines changed

3 files changed

+138
-16
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.omega_r.libs.omegatypes
2+
3+
import android.graphics.Typeface
4+
import android.os.Parcel
5+
import android.os.Process
6+
import java.util.ArrayList
7+
8+
object LeakyTypefaceStorageCompat {
9+
10+
private val lock = Any()
11+
12+
private val storage = ArrayList<Typeface>()
13+
14+
/**
15+
* Write typeface to parcel.
16+
*
17+
* You can't transfer Typeface to a different process. [readTypefaceFromParcel] will
18+
* return `null` if the [readTypefaceFromParcel] is called in a different process.
19+
*
20+
* @param typeface A [Typeface] to be written.
21+
* @param parcel A [Parcel] object.
22+
*/
23+
fun writeTypefaceToParcel(typeface: Typeface, parcel: Parcel) {
24+
parcel.writeInt(Process.myPid())
25+
synchronized(lock) {
26+
val id: Int
27+
val i = storage.indexOf(typeface)
28+
if (i != -1) {
29+
id = i
30+
} else {
31+
id = storage.size
32+
storage.add(typeface)
33+
}
34+
parcel.writeInt(id)
35+
}
36+
}
37+
38+
/**
39+
* Read typeface from parcel.
40+
*
41+
* If the [Typeface] was created in another process, this method returns null.
42+
*
43+
* @param parcel A [Parcel] object
44+
* @return A [Typeface] object.
45+
*/
46+
fun readTypefaceFromParcel(parcel: Parcel): Typeface? {
47+
val pid = parcel.readInt()
48+
val typefaceId = parcel.readInt()
49+
if (pid != Process.myPid()) {
50+
return null // The Typeface was created and written in another process.
51+
}
52+
synchronized(lock) {
53+
return storage[typefaceId]
54+
}
55+
}
56+
}

omegatypes/src/main/java/com/omega_r/libs/omegatypes/TextStyle.kt

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ abstract class TextStyle : Serializable {
4242
fun strikethrough(): TextStyle = strikethroughTextStyle
4343

4444
@JvmStatic
45-
fun font(fontName: Text): TextStyle = FontTextStyle(fontNameText = fontName)
45+
fun font(fontName: Text): TextStyle = NameFontTextStyle(fontNameText = fontName)
4646

4747
@JvmStatic
48-
fun font(fontName: String): TextStyle = FontTextStyle(fontNameText = fontName.toText())
48+
fun font(fontName: String): TextStyle = NameFontTextStyle(fontNameText = fontName.toText())
4949

5050
@JvmStatic
51-
fun font(typeface: Typeface): TextStyle = FontTextStyle(fontTypeface = typeface)
51+
fun font(typeface: Typeface): TextStyle = TypefaceFontTextStyle(fontTypeface = typeface)
5252

5353
@JvmStatic
5454
fun size(size: Size): TextStyle = SizeTextStyle(size)
@@ -118,23 +118,20 @@ abstract class TextStyle : Serializable {
118118
}
119119
}
120120

121-
private class FontTextStyle(
122-
private val fontNameText: Text? = null,
123-
private val fontTypeface: Typeface? = null
124-
) : TextStyle() {
121+
private class NameFontTextStyle(private val fontNameText: Text) : TextStyle() {
125122

126123
override fun SpannableString.applyStyle(context: Context) {
127-
setSpan(createSpan(context), 0, length, 0)
124+
fontNameText.getString(context)?.let {
125+
setSpan(TypefaceSpan(it), 0, length, 0)
126+
}
128127
}
129128

130-
private fun createSpan(context: Context): Any {
131-
if (fontTypeface != null) {
132-
return StyleSpan(fontTypeface.style)
133-
}
134-
fontNameText?.getString(context)?.let {
135-
return TypefaceSpan(it)
136-
}
137-
throw IllegalStateException()
129+
}
130+
131+
private class TypefaceFontTextStyle(private val fontTypeface: Typeface) : TextStyle() {
132+
133+
override fun SpannableString.applyStyle(context: Context) {
134+
setSpan(TypefaceSpanCompat(typeface = fontTypeface), 0, length, 0)
138135
}
139136

140137
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.omega_r.libs.omegatypes
2+
3+
import android.graphics.Paint
4+
import android.graphics.Typeface
5+
import android.os.Parcel
6+
import android.text.ParcelableSpan
7+
import android.text.TextPaint
8+
import android.text.style.MetricAffectingSpan
9+
import android.text.style.TypefaceSpan
10+
11+
class TypefaceSpanCompat(
12+
var family: String? = null,
13+
var typeface: Typeface? = null) : MetricAffectingSpan(), ParcelableSpan {
14+
15+
companion object {
16+
private const val SPAN_TYPE_ID = 13
17+
}
18+
19+
/**
20+
* Constructs a [TypefaceSpan] from a parcel.
21+
*/
22+
constructor(src: Parcel) : this(family = src.readString(), typeface = LeakyTypefaceStorageCompat.readTypefaceFromParcel(src))
23+
24+
override fun getSpanTypeId(): Int {
25+
return SPAN_TYPE_ID
26+
}
27+
28+
override fun describeContents(): Int {
29+
return 0
30+
}
31+
32+
override fun writeToParcel(dest: Parcel, flags: Int) {
33+
dest.writeString(family)
34+
typeface?.let { LeakyTypefaceStorageCompat.writeTypefaceToParcel(it, dest) }
35+
}
36+
37+
override fun updateDrawState(ds: TextPaint) {
38+
updateTypeface(ds)
39+
}
40+
41+
override fun updateMeasureState(paint: TextPaint) {
42+
updateTypeface(paint)
43+
}
44+
45+
private fun updateTypeface(paint: Paint) {
46+
if (typeface != null) {
47+
paint.typeface = typeface
48+
} else if (family != null) {
49+
applyFontFamily(paint, family!!)
50+
}
51+
}
52+
53+
private fun applyFontFamily(paint: Paint, family: String) {
54+
val style: Int
55+
val old = paint.typeface
56+
style = old?.style ?: Typeface.NORMAL
57+
val styledTypeface = Typeface.create(family, style)
58+
val fake = style and styledTypeface.style.inv()
59+
60+
if (fake and Typeface.BOLD != 0) {
61+
paint.isFakeBoldText = true
62+
}
63+
64+
if (fake and Typeface.ITALIC != 0) {
65+
paint.textSkewX = -0.25f
66+
}
67+
paint.typeface = styledTypeface
68+
}
69+
}

0 commit comments

Comments
 (0)