// 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. This is only relevant for the phone tab
 * switcher.
 */
public class TitleBitmapFactory {
    private static final String TAG = "TitleBitmapFactory";

    private static final float TITLE_WIDTH_PERCENTAGE = 1.f;

    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 = res.getColor(incognito ? R.color.compositor_tab_title_bar_text_incognito
                        : R.color.compositor_tab_title_bar_text);
        int shadowColor = res.getColor(incognito ? R.color.compositor_tab_title_bar_shadow_incognito
                        : R.color.compositor_tab_title_bar_shadow);
        int shadowXOffset = res.getDimensionPixelOffset(incognito
                        ? R.dimen.compositor_tab_title_bar_shadow_x_offset_incognito
                        : R.dimen.compositor_tab_title_bar_shadow_x_offset);
        int shadowYOffset = res.getDimensionPixelOffset(incognito
                        ? R.dimen.compositor_tab_title_bar_shadow_y_offset_incognito
                        : R.dimen.compositor_tab_title_bar_shadow_y_offset);
        float textSize = res.getDimensionPixelSize(R.dimen.compositor_tab_title_text_size);
        float adjustedTextSize = textSize * res.getConfiguration().fontScale;

        boolean fakeBoldText = res.getBoolean(R.bool.compositor_tab_title_fake_bold_text);

        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(textColor);
        if (shadowXOffset != 0 && shadowYOffset != 0) {
            mTextPaint.setShadowLayer(0.001f, shadowXOffset, shadowYOffset, shadowColor);
        }
        mTextPaint.setTextSize(adjustedTextSize);
        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 != null && 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, 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;
    }
}

@@ -816,61 +816,8 @@
 aps.
- This is only relevant for the phone tab%0A * switcher.
 %0A */

Update comments for TitleBitmapFactory