use of android.view.DisplayListCanvas in project platform_frameworks_base by android.
the class LockPatternView method onDraw.
@Override
protected void onDraw(Canvas canvas) {
final ArrayList<Cell> pattern = mPattern;
final int count = pattern.size();
final boolean[][] drawLookup = mPatternDrawLookup;
if (mPatternDisplayMode == DisplayMode.Animate) {
// figure out which circles to draw
// + 1 so we pause on complete pattern
final int oneCycle = (count + 1) * MILLIS_PER_CIRCLE_ANIMATING;
final int spotInCycle = (int) (SystemClock.elapsedRealtime() - mAnimatingPeriodStart) % oneCycle;
final int numCircles = spotInCycle / MILLIS_PER_CIRCLE_ANIMATING;
clearPatternDrawLookup();
for (int i = 0; i < numCircles; i++) {
final Cell cell = pattern.get(i);
drawLookup[cell.getRow()][cell.getColumn()] = true;
}
// figure out in progress portion of ghosting line
final boolean needToUpdateInProgressPoint = numCircles > 0 && numCircles < count;
if (needToUpdateInProgressPoint) {
final float percentageOfNextCircle = ((float) (spotInCycle % MILLIS_PER_CIRCLE_ANIMATING)) / MILLIS_PER_CIRCLE_ANIMATING;
final Cell currentCell = pattern.get(numCircles - 1);
final float centerX = getCenterXForColumn(currentCell.column);
final float centerY = getCenterYForRow(currentCell.row);
final Cell nextCell = pattern.get(numCircles);
final float dx = percentageOfNextCircle * (getCenterXForColumn(nextCell.column) - centerX);
final float dy = percentageOfNextCircle * (getCenterYForRow(nextCell.row) - centerY);
mInProgressX = centerX + dx;
mInProgressY = centerY + dy;
}
// TODO: Infinite loop here...
invalidate();
}
final Path currentPath = mCurrentPath;
currentPath.rewind();
// draw the circles
for (int i = 0; i < 3; i++) {
float centerY = getCenterYForRow(i);
for (int j = 0; j < 3; j++) {
CellState cellState = mCellStates[i][j];
float centerX = getCenterXForColumn(j);
float translationY = cellState.translationY;
if (isHardwareAccelerated() && cellState.hwAnimating) {
DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
displayListCanvas.drawCircle(cellState.hwCenterX, cellState.hwCenterY, cellState.hwRadius, cellState.hwPaint);
} else {
drawCircle(canvas, (int) centerX, (int) centerY + translationY, cellState.radius, drawLookup[i][j], cellState.alpha);
}
}
}
// TODO: the path should be created and cached every time we hit-detect a cell
// only the last segment of the path should be computed here
// draw the path of the pattern (unless we are in stealth mode)
final boolean drawPath = !mInStealthMode;
if (drawPath) {
mPathPaint.setColor(getCurrentColor(true));
boolean anyCircles = false;
float lastX = 0f;
float lastY = 0f;
for (int i = 0; i < count; i++) {
Cell cell = pattern.get(i);
// of animation).
if (!drawLookup[cell.row][cell.column]) {
break;
}
anyCircles = true;
float centerX = getCenterXForColumn(cell.column);
float centerY = getCenterYForRow(cell.row);
if (i != 0) {
CellState state = mCellStates[cell.row][cell.column];
currentPath.rewind();
currentPath.moveTo(lastX, lastY);
if (state.lineEndX != Float.MIN_VALUE && state.lineEndY != Float.MIN_VALUE) {
currentPath.lineTo(state.lineEndX, state.lineEndY);
} else {
currentPath.lineTo(centerX, centerY);
}
canvas.drawPath(currentPath, mPathPaint);
}
lastX = centerX;
lastY = centerY;
}
// draw last in progress section
if ((mPatternInProgress || mPatternDisplayMode == DisplayMode.Animate) && anyCircles) {
currentPath.rewind();
currentPath.moveTo(lastX, lastY);
currentPath.lineTo(mInProgressX, mInProgressY);
mPathPaint.setAlpha((int) (calculateLastSegmentAlpha(mInProgressX, mInProgressY, lastX, lastY) * 255f));
canvas.drawPath(currentPath, mPathPaint);
}
}
}
use of android.view.DisplayListCanvas in project platform_frameworks_base by android.
the class Editor method drawHardwareAccelerated.
private void drawHardwareAccelerated(Canvas canvas, Layout layout, Path highlight, Paint highlightPaint, int cursorOffsetVertical) {
final long lineRange = layout.getLineRangeForDraw(canvas);
int firstLine = TextUtils.unpackRangeStartFromLong(lineRange);
int lastLine = TextUtils.unpackRangeEndFromLong(lineRange);
if (lastLine < 0)
return;
layout.drawBackground(canvas, highlight, highlightPaint, cursorOffsetVertical, firstLine, lastLine);
if (layout instanceof DynamicLayout) {
if (mTextRenderNodes == null) {
mTextRenderNodes = ArrayUtils.emptyArray(TextRenderNode.class);
}
DynamicLayout dynamicLayout = (DynamicLayout) layout;
int[] blockEndLines = dynamicLayout.getBlockEndLines();
int[] blockIndices = dynamicLayout.getBlockIndices();
final int numberOfBlocks = dynamicLayout.getNumberOfBlocks();
final int indexFirstChangedBlock = dynamicLayout.getIndexFirstChangedBlock();
int endOfPreviousBlock = -1;
int searchStartIndex = 0;
for (int i = 0; i < numberOfBlocks; i++) {
int blockEndLine = blockEndLines[i];
int blockIndex = blockIndices[i];
final boolean blockIsInvalid = blockIndex == DynamicLayout.INVALID_BLOCK_INDEX;
if (blockIsInvalid) {
blockIndex = getAvailableDisplayListIndex(blockIndices, numberOfBlocks, searchStartIndex);
// Note how dynamic layout's internal block indices get updated from Editor
blockIndices[i] = blockIndex;
if (mTextRenderNodes[blockIndex] != null) {
mTextRenderNodes[blockIndex].isDirty = true;
}
searchStartIndex = blockIndex + 1;
}
if (mTextRenderNodes[blockIndex] == null) {
mTextRenderNodes[blockIndex] = new TextRenderNode("Text " + blockIndex);
}
final boolean blockDisplayListIsInvalid = mTextRenderNodes[blockIndex].needsRecord();
RenderNode blockDisplayList = mTextRenderNodes[blockIndex].renderNode;
if (i >= indexFirstChangedBlock || blockDisplayListIsInvalid) {
final int blockBeginLine = endOfPreviousBlock + 1;
final int top = layout.getLineTop(blockBeginLine);
final int bottom = layout.getLineBottom(blockEndLine);
int left = 0;
int right = mTextView.getWidth();
if (mTextView.getHorizontallyScrolling()) {
float min = Float.MAX_VALUE;
float max = Float.MIN_VALUE;
for (int line = blockBeginLine; line <= blockEndLine; line++) {
min = Math.min(min, layout.getLineLeft(line));
max = Math.max(max, layout.getLineRight(line));
}
left = (int) min;
right = (int) (max + 0.5f);
}
// Rebuild display list if it is invalid
if (blockDisplayListIsInvalid) {
final DisplayListCanvas displayListCanvas = blockDisplayList.start(right - left, bottom - top);
try {
// drawText is always relative to TextView's origin, this translation
// brings this range of text back to the top left corner of the viewport
displayListCanvas.translate(-left, -top);
layout.drawText(displayListCanvas, blockBeginLine, blockEndLine);
mTextRenderNodes[blockIndex].isDirty = false;
// No need to untranslate, previous context is popped after
// drawDisplayList
} finally {
blockDisplayList.end(displayListCanvas);
// Same as drawDisplayList below, handled by our TextView's parent
blockDisplayList.setClipToBounds(false);
}
}
// Valid disply list whose index is >= indexFirstChangedBlock
// only needs to update its drawing location.
blockDisplayList.setLeftTopRightBottom(left, top, right, bottom);
}
((DisplayListCanvas) canvas).drawRenderNode(blockDisplayList);
endOfPreviousBlock = blockEndLine;
}
dynamicLayout.setIndexFirstChangedBlock(numberOfBlocks);
} else {
// Boring layout is used for empty and hint text
layout.drawText(canvas, firstLine, lastLine);
}
}
use of android.view.DisplayListCanvas in project platform_frameworks_base by android.
the class BackdropFrameRenderer method drawColorViews.
private void drawColorViews(int left, int top, int width, int height, boolean fullscreen, Rect systemInsets, Rect stableInsets) {
if (mSystemBarBackgroundNode == null) {
return;
}
DisplayListCanvas canvas = mSystemBarBackgroundNode.start(width, height);
mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
final int topInset = DecorView.getColorViewTopInset(mStableInsets.top, mSystemInsets.top);
final int bottomInset = DecorView.getColorViewBottomInset(stableInsets.bottom, systemInsets.bottom);
final int rightInset = DecorView.getColorViewRightInset(stableInsets.right, systemInsets.right);
final int leftInset = DecorView.getColorViewLeftInset(stableInsets.left, systemInsets.left);
if (mStatusBarColor != null) {
mStatusBarColor.setBounds(0, 0, left + width, topInset);
mStatusBarColor.draw(canvas);
}
// However, we need it for the transitions into/out of docked mode.
if (mNavigationBarColor != null && fullscreen) {
final int size = DecorView.getNavBarSize(bottomInset, rightInset, leftInset);
if (DecorView.isNavBarToRightEdge(bottomInset, rightInset)) {
mNavigationBarColor.setBounds(width - size, 0, width, height);
} else if (DecorView.isNavBarToLeftEdge(bottomInset, leftInset)) {
mNavigationBarColor.setBounds(0, 0, size, height);
} else {
mNavigationBarColor.setBounds(0, height - size, width, height);
}
mNavigationBarColor.draw(canvas);
}
mSystemBarBackgroundNode.end(canvas);
mRenderer.drawRenderNode(mSystemBarBackgroundNode);
}
use of android.view.DisplayListCanvas in project platform_frameworks_base by android.
the class RippleComponent method draw.
/**
* Draws the ripple to the canvas, inheriting the paint's color and alpha
* properties.
*
* @param c the canvas to which the ripple should be drawn
* @param p the paint used to draw the ripple
* @return {@code true} if something was drawn, {@code false} otherwise
*/
public boolean draw(Canvas c, Paint p) {
final boolean hasDisplayListCanvas = !mForceSoftware && c.isHardwareAccelerated() && c instanceof DisplayListCanvas;
if (mHasDisplayListCanvas != hasDisplayListCanvas) {
mHasDisplayListCanvas = hasDisplayListCanvas;
if (!hasDisplayListCanvas) {
// We've switched from hardware to non-hardware mode. Panic.
endHardwareAnimations();
}
}
if (hasDisplayListCanvas) {
final DisplayListCanvas hw = (DisplayListCanvas) c;
startPendingAnimation(hw, p);
if (mHardwareAnimator != null) {
return drawHardware(hw);
}
}
return drawSoftware(c, p);
}
use of android.view.DisplayListCanvas in project android_frameworks_base by DirtyUnicorns.
the class LockPatternView method onDraw.
@Override
protected void onDraw(Canvas canvas) {
final ArrayList<Cell> pattern = mPattern;
final int count = pattern.size();
final boolean[][] drawLookup = mPatternDrawLookup;
if (mPatternDisplayMode == DisplayMode.Animate) {
// figure out which circles to draw
// + 1 so we pause on complete pattern
final int oneCycle = (count + 1) * MILLIS_PER_CIRCLE_ANIMATING;
final int spotInCycle = (int) (SystemClock.elapsedRealtime() - mAnimatingPeriodStart) % oneCycle;
final int numCircles = spotInCycle / MILLIS_PER_CIRCLE_ANIMATING;
clearPatternDrawLookup();
for (int i = 0; i < numCircles; i++) {
final Cell cell = pattern.get(i);
drawLookup[cell.getRow()][cell.getColumn()] = true;
}
// figure out in progress portion of ghosting line
final boolean needToUpdateInProgressPoint = numCircles > 0 && numCircles < count;
if (needToUpdateInProgressPoint) {
final float percentageOfNextCircle = ((float) (spotInCycle % MILLIS_PER_CIRCLE_ANIMATING)) / MILLIS_PER_CIRCLE_ANIMATING;
final Cell currentCell = pattern.get(numCircles - 1);
final float centerX = getCenterXForColumn(currentCell.column);
final float centerY = getCenterYForRow(currentCell.row);
final Cell nextCell = pattern.get(numCircles);
final float dx = percentageOfNextCircle * (getCenterXForColumn(nextCell.column) - centerX);
final float dy = percentageOfNextCircle * (getCenterYForRow(nextCell.row) - centerY);
mInProgressX = centerX + dx;
mInProgressY = centerY + dy;
}
// TODO: Infinite loop here...
invalidate();
}
final Path currentPath = mCurrentPath;
currentPath.rewind();
// draw the circles
for (int i = 0; i < 3; i++) {
float centerY = getCenterYForRow(i);
for (int j = 0; j < 3; j++) {
CellState cellState = mCellStates[i][j];
float centerX = getCenterXForColumn(j);
float translationY = cellState.translationY;
if (mUseLockPatternDrawable) {
drawCellDrawable(canvas, i, j, cellState.radius, drawLookup[i][j]);
} else {
if (isHardwareAccelerated() && cellState.hwAnimating) {
DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
displayListCanvas.drawCircle(cellState.hwCenterX, cellState.hwCenterY, cellState.hwRadius, cellState.hwPaint);
} else {
drawCircle(canvas, (int) centerX, (int) centerY + translationY, cellState.radius, drawLookup[i][j], cellState.alpha);
}
}
}
}
// TODO: the path should be created and cached every time we hit-detect a cell
// only the last segment of the path should be computed here
// draw the path of the pattern (unless we are in stealth mode)
final boolean drawPath = !mInStealthMode;
if (drawPath) {
mPathPaint.setColor(getCurrentColor(true));
boolean anyCircles = false;
float lastX = 0f;
float lastY = 0f;
for (int i = 0; i < count; i++) {
Cell cell = pattern.get(i);
// of animation).
if (!drawLookup[cell.row][cell.column]) {
break;
}
anyCircles = true;
float centerX = getCenterXForColumn(cell.column);
float centerY = getCenterYForRow(cell.row);
if (i != 0) {
CellState state = mCellStates[cell.row][cell.column];
currentPath.rewind();
currentPath.moveTo(lastX, lastY);
if (state.lineEndX != Float.MIN_VALUE && state.lineEndY != Float.MIN_VALUE) {
currentPath.lineTo(state.lineEndX, state.lineEndY);
} else {
currentPath.lineTo(centerX, centerY);
}
canvas.drawPath(currentPath, mPathPaint);
}
lastX = centerX;
lastY = centerY;
}
// draw last in progress section
if ((mPatternInProgress || mPatternDisplayMode == DisplayMode.Animate) && anyCircles) {
currentPath.rewind();
currentPath.moveTo(lastX, lastY);
currentPath.lineTo(mInProgressX, mInProgressY);
mPathPaint.setAlpha((int) (calculateLastSegmentAlpha(mInProgressX, mInProgressY, lastX, lastY) * 255f));
canvas.drawPath(currentPath, mPathPaint);
}
}
}
Aggregations