/*
* Copyright (C) 2012 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 com.google.android.apps.markers;
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Region.Op;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import org.dsandler.apps.markers.R;
public class Slate extends View {
static final boolean DEBUG = false;
static final String TAG = "Slate";
public static final boolean HWLAYER = true;
public static final boolean SWLAYER = false;
public static final boolean FANCY_INVALIDATES = false; // doesn't work
public static final boolean INVALIDATE_ALL_THE_THINGS = true; // invalidate() every frame
public static final int FLAG_DEBUG_STROKES = 1;
public static final int FLAG_DEBUG_PRESSURE = 1 << 1;
public static final int FLAG_DEBUG_INVALIDATES = 1 << 2;
public static final int FLAG_DEBUG_TILES = 1 << 3;
public static final int FLAG_DEBUG_EVERYTHING = ~0;
public static final int MAX_POINTERS = 10;
static final int DENSITY = 1;
private static final int SMOOTHING_FILTER_WLEN = 6;
private static final float SMOOTHING_FILTER_POS_DECAY = 0.65f;
private static final float SMOOTHING_FILTER_PRESSURE_DECAY = 0.9f;
private static final int FIXED_DIMENSION = 0; // 1024;
private static final float INVALIDATE_PADDING = 4.0f;
public static final boolean ASSUME_STYLUS_CALIBRATED = true;
// keep these in sync with penType in values/attrs.xml
public static final int TYPE_WHITEBOARD = 0;
public static final int TYPE_FELTTIP = 1;
public static final int TYPE_AIRBRUSH = 2;
public static final int TYPE_FOUNTAIN_PEN = 3;
public static final int SHAPE_CIRCLE = 0;
public static final int SHAPE_SQUARE = 1;
// public static final int SHAPE_BITMAP_CIRCLE = 2;
public static final int SHAPE_BITMAP_AIRBRUSH = 3;
public static final int SHAPE_FOUNTAIN_PEN = 4;
private float mPressureExponent = 2.0f;
private float mRadiusMin;
private float mRadiusMax;
int mDebugFlags = 0;
private TiledBitmapCanvas mTiledCanvas;
private final Paint mDebugPaints[] = new Paint[10];
private Bitmap mPendingPaintBitmap;
// private Bitmap mCircleBits;
// private Rect mCircleBitsFrame;
private Bitmap mAirbrushBits;
private Rect mAirbrushBitsFrame;
private Bitmap mFountainPenBits;
private Rect mFountainPenBitsFrame;
private PressureCooker mPressureCooker;
private boolean mZoomMode;
private boolean mEmpty;
private Region mDirtyRegion = new Region();
private Paint mBlitPaint;
private Paint mWorkspacePaint;
private Matrix mZoomMatrix = new Matrix();
private Matrix mZoomMatrixInv = new Matrix();
private float mPanX = 0f, mPanY = 0f;
private int mMemClass;
private boolean mLowMem;
public interface SlateListener {
void strokeStarted();
void strokeEnded();
}
private class MarkersPlotter implements SpotFilter.Plotter {
// Plotter receives pointer coordinates and draws them.
// It implements the necessary interface to receive filtered Spots from the SpotFilter.
// It hands off the drawing command to the renderer.
private SpotFilter mCoordBuffer;
private SmoothStroker mRenderer;
private float mLastPressure = -1f;
private int mLastTool = 0;
final float[] mTmpPoint = new float[2];
public MarkersPlotter() {
mCoordBuffer = new SpotFilter(SMOOTHING_FILTER_WLEN, SMOOTHING_FILTER_POS_DECAY, SMOOTHING_FILTER_PRESSURE_DECAY, this);
mRenderer = new SmoothStroker();
}
// final Rect tmpDirtyRect = new Rect();
@Override
public void plot(Spot s) {
final float pressureNorm;
if (ASSUME_STYLUS_CALIBRATED && s.tool == MotionEvent.TOOL_TYPE_STYLUS) {
pressureNorm = s.pressure;
} else {
pressureNorm = mPressureCooker.getAdjustedPressure(s.pressure);
}
final float radius = lerp(mRadiusMin, mRadiusMax,
(float) Math.pow(pressureNorm, mPressureExponent));
mTmpPoint[0] = s.x - mPanX;
mTmpPoint[1] = s.y - mPanY;
mZoomMatrixInv.mapPoints(mTmpPoint);
final RectF dirtyF = mRenderer.strokeTo(mTiledCanvas,
mTmpPoint[0],
mTmpPoint[1], radius);
dirty(dirtyF);
// dirtyF.roundOut(tmpDirtyRect);
// tmpDirtyRect.inset((int)-INVALIDATE_PADDING,(int)-INVALIDATE_PADDING);
// invalidate(tmpDirtyRect);
}
public void setPenColor(int color) {
mRenderer.setPenColor(color);
}
public void finish(long time) {
mLastPressure = -1f;
mCoordBuffer.finish();
mRenderer.reset();
}
// public void addCoords(MotionEvent.PointerCoords pt, long time) {
// mCoordBuffer.add(pt, time);
// mLastPressure = pt.pressure;
// }
public void add(Spot s) {
mCoordBuffer.add(s);
mLastPressure = s.pressure;
mLastTool = s.tool;
}
// public float getRadius() {
// return mRenderer.getRadius();
// }
public float getLastPressure() {
return mLastPressure;
}
public int getLastTool() {
return mLastTool;
}
public void setPenType(int shape) {
mRenderer.setPenType(shape);
}
}
private class SmoothStroker {
// The renderer. Given a stream of filtered points, converts it into draw calls.
private float mLastX = 0, mLastY = 0, mLastLen = 0, mLastR = -1;
private float mTan[] = new float[2];
private int mPenColor;
private int mPenType;
private int mShape = SHAPE_CIRCLE; // SHAPE_BITMAP_AIRBRUSH;
private Path mWorkPath = new Path();
private PathMeasure mWorkPathMeasure = new PathMeasure();
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
int mInkDensity = 0xff; // set to 0x20 or so for a felt-tip look, 0xff for traditional Markers
public SmoothStroker() {
- 1
- 2
- 3
- 4
前往页