// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.compositor.layouts.content;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.Log;
import android.view.InflateException;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R;
/**
* A factory that creates text and favicon bitmaps.
*/
public class TitleBitmapFactory {
private static final String TAG = "TitleBitmapFactory";
private static final float TITLE_WIDTH_PERCENTAGE = 1.f;
// Canvas#drawText() seems to fail when trying to draw 4100 or more characters.
// See https://crbug.com/524390/ for more details.
private static final int MAX_NUM_TITLE_CHAR = 1000;
private final int mMaxWidth;
private final int mNullFaviconResourceId;
private final TextPaint mTextPaint;
private int mFaviconDimension;
private final int mViewHeight;
private final float mTextHeight;
private final float mTextYOffset;
/**
* @param context The current Android's context.
* @param incognito Whether the title are for incognito mode.
* @param nullFaviconResourceId A drawable resource id of a default favicon.
*/
public TitleBitmapFactory(Context context, boolean incognito, int nullFaviconResourceId) {
mNullFaviconResourceId = nullFaviconResourceId;
Resources res = context.getResources();
int textColor = ApiCompatibilityUtils.getColor(res, incognito
? R.color.compositor_tab_title_bar_text_incognito
: R.color.compositor_tab_title_bar_text);
float textSize = res.getDimension(R.dimen.compositor_tab_title_text_size);
boolean fakeBoldText = res.getBoolean(R.bool.compositor_tab_title_fake_bold_text);
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(textColor);
mTextPaint.setTextSize(textSize);
mTextPaint.setFakeBoldText(fakeBoldText);
mTextPaint.density = res.getDisplayMetrics().density;
FontMetrics textFontMetrics = mTextPaint.getFontMetrics();
mTextHeight = (float) Math.ceil(textFontMetrics.bottom - textFontMetrics.top);
mTextYOffset = -textFontMetrics.top;
mFaviconDimension = res.getDimensionPixelSize(R.dimen.compositor_tab_title_favicon_size);
mViewHeight = (int) Math.max(mFaviconDimension, mTextHeight);
int width = res.getDisplayMetrics().widthPixels;
int height = res.getDisplayMetrics().heightPixels;
mMaxWidth = (int) (TITLE_WIDTH_PERCENTAGE * Math.max(width, height));
// Set the favicon dimension here.
mFaviconDimension = Math.min(mMaxWidth, mFaviconDimension);
}
/**
* Generates the favicon bitmap.
*
* @param context Android's UI context.
* @param favicon The favicon of the tab.
* @return The Bitmap with the favicon.
*/
public Bitmap getFaviconBitmap(Context context, Bitmap favicon) {
try {
Bitmap b = Bitmap.createBitmap(
mFaviconDimension, mFaviconDimension, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
if (favicon == null) {
Drawable drawable = ApiCompatibilityUtils.getDrawable(
context.getResources(), mNullFaviconResourceId);
if (drawable instanceof BitmapDrawable) {
favicon = ((BitmapDrawable) drawable).getBitmap();
}
}
if (favicon != null) {
c.drawBitmap(favicon, Math.round((mFaviconDimension - favicon.getWidth()) / 2.0f),
Math.round((mFaviconDimension - favicon.getHeight()) / 2.0f), null);
}
return b;
} catch (OutOfMemoryError ex) {
Log.w(TAG, "OutOfMemoryError while building favicon texture.");
} catch (InflateException ex) {
Log.w(TAG, "InflateException while building favicon texture.");
}
return null;
}
/**
* Generates the title bitmap.
*
* @param context Android's UI context.
* @param title The title of the tab.
* @return The Bitmap with the title.
*/
public Bitmap getTitleBitmap(Context context, String title) {
try {
boolean drawText = !TextUtils.isEmpty(title);
int textWidth =
drawText ? (int) Math.ceil(Layout.getDesiredWidth(title, mTextPaint)) : 0;
// Minimum 1 width bitmap to avoid createBitmap function's IllegalArgumentException,
// when textWidth == 0.
Bitmap b = Bitmap.createBitmap(Math.max(Math.min(mMaxWidth, textWidth), 1), mViewHeight,
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
if (drawText) {
c.drawText(title, 0, Math.min(MAX_NUM_TITLE_CHAR, title.length()), 0,
Math.round((mViewHeight - mTextHeight) / 2.0f + mTextYOffset), mTextPaint);
}
return b;
} catch (OutOfMemoryError ex) {
Log.w(TAG, "OutOfMemoryError while building title texture.");
} catch (InflateException ex) {
Log.w(TAG, "InflateException while building title texture.");
}
return null;
}
}