Revision control
Copy as Markdown
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
package org.mozilla.focus.home
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Paint
import android.net.Uri
import androidx.core.content.ContextCompat
import android.util.TypedValue
import org.mozilla.focus.R
import org.mozilla.focus.utils.UrlUtils
class HomeTilePlaceholderGenerator {
companion object {
private val TEXT_SIZE_DP = 22f
private val DEFAULT_ICON_CHAR = '?'
fun generate(context: Context, url: String?): Bitmap {
val startingChar = getRepresentativeCharacter(url)
val dimen = context.resources.getDimensionPixelSize(R.dimen.home_tile_placeholder_icon_size)
val bitmap = Bitmap.createBitmap(dimen, dimen, Bitmap.Config.ARGB_8888)
bitmap.eraseColor(ContextCompat.getColor(context, R.color.tv_ink))
return drawCharacterOnBitmap(context, startingChar, bitmap)
}
private fun drawCharacterOnBitmap(context: Context, character: Char, bitmap: Bitmap): Bitmap {
val desiredTextSize = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, TEXT_SIZE_DP, context.resources.displayMetrics)
val paint = Paint().apply {
color = ContextCompat.getColor(context, R.color.tv_white)
textAlign = Paint.Align.CENTER
textSize = desiredTextSize
isAntiAlias = true
}
val canvas = Canvas(bitmap)
canvas.drawText(character.toString(),
canvas.width / 2.0f,
canvas.height / 2.0f - (paint.descent() + paint.ascent()) / 2.0f,
paint)
return bitmap
}
/**
* Get a representative character for the given URL.
*
*/
@JvmStatic
fun getRepresentativeCharacter(url: String?): Char {
val firstChar = getRepresentativeSnippet(url)?.find { it.isLetterOrDigit() }?.toUpperCase()
return (firstChar ?: DEFAULT_ICON_CHAR)
}
/**
* Get the representative part of the URL. Usually this is the host (without common prefixes).
*
* @return the representative snippet or null if one could not be found.
*/
private fun getRepresentativeSnippet(url: String?): String? {
if (url == null || url.isEmpty()) return null
val uri = Uri.parse(url)
val snippet = if (!uri.host.isNullOrEmpty()) {
uri.host // cached by Uri class.
} else if (!uri.path.isNullOrEmpty()) { // The uri may not have a host for e.g. file:// uri
uri.path // cached by Uri class.
} else {
return null
}
// Strip common prefixes that we do not want to use to determine the representative characters
return UrlUtils.stripCommonSubdomains(snippet)
}
}
}