/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jackpal.androidterm.emulatorview;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
abstract class BaseTextRenderer implements TextRenderer {
protected boolean mReverseVideo;
protected int[] mPalette;
protected static final int[] sXterm256Paint = {
// 16 original colors
// First 8 are dim
0xff000000, // black
0xffcd0000, // dim red
0xff00cd00, // dim green
0xffcdcd00, // dim yellow
0xff0000ee, // dim blue
0xffcd00cd, // dim magenta
0xff00cdcd, // dim cyan
0xffe5e5e5, // dim white
// second 8 are bright
0xff7f7f7f, // medium grey
0xffff0000, // bright red
0xff00ff00, // bright green
0xffffff00, // bright yellow
0xff5c5cff, // light blue
0xffff00ff, // bright magenta
0xff00ffff, // bright cyan
0xffffffff, // bright white
// 216 color cube, six shades of each color
0xff000000,
0xff00005f,
0xff000087,
0xff0000af,
0xff0000d7,
0xff0000ff,
0xff005f00,
0xff005f5f,
0xff005f87,
0xff005faf,
0xff005fd7,
0xff005fff,
0xff008700,
0xff00875f,
0xff008787,
0xff0087af,
0xff0087d7,
0xff0087ff,
0xff00af00,
0xff00af5f,
0xff00af87,
0xff00afaf,
0xff00afd7,
0xff00afff,
0xff00d700,
0xff00d75f,
0xff00d787,
0xff00d7af,
0xff00d7d7,
0xff00d7ff,
0xff00ff00,
0xff00ff5f,
0xff00ff87,
0xff00ffaf,
0xff00ffd7,
0xff00ffff,
0xff5f0000,
0xff5f005f,
0xff5f0087,
0xff5f00af,
0xff5f00d7,
0xff5f00ff,
0xff5f5f00,
0xff5f5f5f,
0xff5f5f87,
0xff5f5faf,
0xff5f5fd7,
0xff5f5fff,
0xff5f8700,
0xff5f875f,
0xff5f8787,
0xff5f87af,
0xff5f87d7,
0xff5f87ff,
0xff5faf00,
0xff5faf5f,
0xff5faf87,
0xff5fafaf,
0xff5fafd7,
0xff5fafff,
0xff5fd700,
0xff5fd75f,
0xff5fd787,
0xff5fd7af,
0xff5fd7d7,
0xff5fd7ff,
0xff5fff00,
0xff5fff5f,
0xff5fff87,
0xff5fffaf,
0xff5fffd7,
0xff5fffff,
0xff870000,
0xff87005f,
0xff870087,
0xff8700af,
0xff8700d7,
0xff8700ff,
0xff875f00,
0xff875f5f,
0xff875f87,
0xff875faf,
0xff875fd7,
0xff875fff,
0xff878700,
0xff87875f,
0xff878787,
0xff8787af,
0xff8787d7,
0xff8787ff,
0xff87af00,
0xff87af5f,
0xff87af87,
0xff87afaf,
0xff87afd7,
0xff87afff,
0xff87d700,
0xff87d75f,
0xff87d787,
0xff87d7af,
0xff87d7d7,
0xff87d7ff,
0xff87ff00,
0xff87ff5f,
0xff87ff87,
0xff87ffaf,
0xff87ffd7,
0xff87ffff,
0xffaf0000,
0xffaf005f,
0xffaf0087,
0xffaf00af,
0xffaf00d7,
0xffaf00ff,
0xffaf5f00,
0xffaf5f5f,
0xffaf5f87,
0xffaf5faf,
0xffaf5fd7,
0xffaf5fff,
0xffaf8700,
0xffaf875f,
0xffaf8787,
0xffaf87af,
0xffaf87d7,
0xffaf87ff,
0xffafaf00,
0xffafaf5f,
0xffafaf87,
0xffafafaf,
0xffafafd7,
0xffafafff,
0xffafd700,
0xffafd75f,
0xffafd787,
0xffafd7af,
0xffafd7d7,
0xffafd7ff,
0xffafff00,
0xffafff5f,
0xffafff87,
0xffafffaf,
0xffafffd7,
0xffafffff,
0xffd70000,
0xffd7005f,
0xffd70087,
0xffd700af,
0xffd700d7,
0xffd700ff,
0xffd75f00,
0xffd75f5f,
0xffd75f87,
0xffd75faf,
0xffd75fd7,
0xffd75fff,
0xffd78700,
0xffd7875f,
0xffd78787,
0xffd787af,
0xffd787d7,
0xffd787ff,
0xffd7af00,
0xffd7af5f,
0xffd7af87,
0xffd7afaf,
0xffd7afd7,
0xffd7afff,
0xffd7d700,
0xffd7d75f,
0xffd7d787,
0xffd7d7af,
0xffd7d7d7,
0xffd7d7ff,
0xffd7ff00,
0xffd7ff5f,
0xffd7ff87,
0xffd7ffaf,
0xffd7ffd7,
0xffd7ffff,
0xffff0000,
0xffff005f,
0xffff0087,
0xffff00af,
0xffff00d7,
0xffff00ff,
0xffff5f00,
0xffff5f5f,
0xffff5f87,
0xffff5faf,
0xffff5fd7,
0xffff5fff,
0xffff8700,
0xffff875f,
0xffff8787,
0xffff87af,
0xffff87d7,
0xffff87ff,
0xffffaf00,
0xffffaf5f,
0xffffaf87,
0xffffafaf,
0xffffafd7,
0xffffafff,
0xffffd700,
0xffffd75f,
0xffffd787,
0xffffd7af,
0xffffd7d7,
0xffffd7ff,
0xffffff00,
0xffffff5f,
0xffffff87,
0xffffffaf,
0xffffffd7,
0xffffffff,
// 24 grey scale ramp
0xff080808,
0xff121212,
0xff1c1c1c,
0xff262626,
0xff303030,
0xff3a3a3a,
0xff444444,
0xff4e4e4e,
0xff585858,
0xff626262,
0xff6c6c6c,
0xff767676,
0xff808080,
0xff8a8a8a,
0xff949494,
0xff9e9e9e,
0xffa8a8a8,
0xffb2b2b2,
0xffbcbcbc,
0xffc6c6c6,
0xffd0d0d0,
0xffdadada,
0xffe4e4e4,
0xffeeeeee
};
static final ColorScheme defaultColorScheme =
new ColorScheme(0xffcccccc, 0xff000000);
private final Paint mCursorScreenPaint;
private final Paint mCopyRedToAlphaPaint;
private final Paint mCursorPaint;
private final Paint mCursorStrokePaint;
private final Path mShiftCursor;
private final Path mAltCursor;
private final Path mCtrlCursor;
private final Path mFnCursor;
private RectF mTempSrc;
private RectF mTempDst;
private Matrix mScaleMatrix;
private float mLastCharWidth;
private float mLastCharHeight;
private static final Matrix.ScaleToFit mScaleType = Matrix.ScaleToFit.FILL;
private Bitmap mCursorBitmap;
private Bitmap mWorkBitmap;
private int mCursorBitmapCursorMode = -1;
public BaseTextRenderer(ColorScheme scheme) {
if (scheme == null) {
scheme = defaultColorScheme;
}
setDefaultColors(scheme);
mCursorScreenPaint = new Paint();
mCursorScreenPaint.setColor(scheme.getCursorBackColor());
// Cursor paint and cursor stroke paint are used to draw a grayscale mask that's converted
// to an alpha8 texture. Only the red channel's value matters.
mCursorPaint = new Paint();
mCursorPaint.setColor(0xff909090); // Opaque lightgray
mCursorPaint.setAntiAlias(true);
mCursorStrokePaint = new Paint(mCursorPaint);
mCursorStrokePaint.setStrokeWidth(0.1f);
mCursorStrokePaint.setStyle(Paint.Style.STROKE);
mCopyRedToAlphaPaint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.set(new float[] {
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
1, 0, 0, 0, 0 });
mCopyRedToAlphaPaint.setColorFilter(new ColorMatrixColorFilter(cm));
mShiftCursor = new Path();
mShiftCursor.lineTo(0.5f, 0.33f);
mShiftCursor.lineTo(1.0f, 0.0f);
mAltCursor = new Path();
mAltCursor.moveTo(0.0f, 1.0f);
mAltCursor.lineTo(0.5f, 0.66f);
mAltCursor.lineTo(1.0f, 1.0f);
mCtrlCursor = new Path();
mCtrlCursor.moveTo(0.0f, 0.25f);
mCtrlCursor.lineTo(1.0f, 0.5f);
mCtrlCursor.lineTo(0.0f, 0.75f);
mFnCursor = new Path();
mFnCursor.moveTo(1.0f, 0.25f);
mFnCursor.lineTo(0.0f, 0.5f);
mFnCursor.lineTo(1.0f, 0.75f);
// For creating the transform when the terminal resizes
mTempSrc = new RectF();
mTempSrc.set(0.0f, 0.0f, 1.0f, 1.0f);
mTempDst = new RectF();
mScaleMatrix = new Matrix();
}
public void setReverseVideo(boolean reverseVideo) {
mReverseVideo = reverseVideo;
}
private void setDefaultColors(ColorScheme scheme) {
mPalette = cloneDefaultColors();
mPalette[TextStyle.ciForeground] = scheme.getForeColor();
mPalette[TextStyle.ciBackground] = scheme.getBackColor();
mPalette[TextStyle.ciCursorForeground] = scheme.getCursorForeColor();
mPalette[TextStyle.ciCursorBackground] = scheme.getCursorBackColor();
}
private static int[] cloneDefaultColors() {
int length = sXterm256Paint.length;
int[] clone = new int[TextStyle.ciColorLength];
System.arraycopy(sXterm256Paint, 0, clone, 0, length);
return clone;
}
protected void drawCursorImp(Canvas canvas, float x, float y, float charWidth, float charHeight,
int cursorMode) {
if (cursorMode == 0) {
canvas.drawRect(x, y - charHeight, x + charWidth, y, mCursorScreenPaint);
return;
}
// Fancy cursor. Draw an offscreen cursor shape, then blit it on screen.
// Has the character size changed?
if (charWidth != mLastCharWidth || charHeight != mLastCharHeight) {
mLastCharWidth = charWidth;
mLastCharHeight = charHeight;
mTempDst.set(0.0f, 0.0f, charWidth, charHeight);
mScaleMatrix.setRectToRect(mTempSrc, mTempDst, mScaleType);
mCursorBitmap = Bitmap.createBitmap((int) charWidth, (int) charHeight,
Bitmap.Config.ALPHA_8);
mWorkBitmap = Bitmap.createBitmap((int) charWidth, (int) charHeight,
Bitmap.Config.ARGB_8888);
mCursorBitmapCursorMode = -1;
}
// Has the cursor mode changed ?
if (cursorMode != mCursorBitmapCursorMode) {
mCursorBitmapCursorMode = cursorMode;
mWorkBitmap.eraseColor(0xffffffff);
Canvas workCanvas = new Canvas(mWorkBitmap);
workCanvas.concat(mScaleMatrix);
drawCursorHelper(workCanvas, mShiftCursor, cursorMode, MODE_SHIFT_SHIFT);
drawCursorHelper(workCanvas, mAltCursor, cursorMode, MODE_ALT_SHIFT);
drawCursorHelper(workCanvas, mCtrlCursor, cursorMode, MODE_CTRL_SHIFT);
drawCursorHelper(workCanvas, mFnCursor, cursorMode, MODE_FN_SHIFT);
mCursorBitmap.eraseColor(0);
Canvas bitmapCanvas = new Canvas(mCursorBitmap);
bitmapCanvas.drawBitmap(mWorkBitmap, 0, 0, mCopyRedToAlphaPaint);
}
canvas.drawBitmap(mCursorBitmap, x, y - charHeight, mCursorScreenPaint);
}
private void drawCursorHelper(Canvas canvas, Path path, int mode, int shift) {
switch ((mode >> shift) & MODE_MASK) {
case MODE_ON:
canvas.drawPath(path, mCursorStrokePaint);
break;
case MODE_LOCKED:
canvas.drawPath(path, mCursorPaint);
break;
}
}
}