Search in sources :

Example 1 with DisplayListCanvas

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);
        }
    }
}
Also used : Path(android.graphics.Path) DisplayListCanvas(android.view.DisplayListCanvas) Paint(android.graphics.Paint)

Example 2 with DisplayListCanvas

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);
    }
}
Also used : RenderNode(android.view.RenderNode) DisplayListCanvas(android.view.DisplayListCanvas) DynamicLayout(android.text.DynamicLayout) Paint(android.graphics.Paint)

Example 3 with DisplayListCanvas

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);
}
Also used : DisplayListCanvas(android.view.DisplayListCanvas)

Example 4 with DisplayListCanvas

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);
}
Also used : DisplayListCanvas(android.view.DisplayListCanvas)

Example 5 with DisplayListCanvas

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);
        }
    }
}
Also used : Path(android.graphics.Path) DisplayListCanvas(android.view.DisplayListCanvas) Paint(android.graphics.Paint)

Aggregations

DisplayListCanvas (android.view.DisplayListCanvas)30 Paint (android.graphics.Paint)10 Path (android.graphics.Path)5 ColorDrawable (android.graphics.drawable.ColorDrawable)5 Drawable (android.graphics.drawable.Drawable)5 DynamicLayout (android.text.DynamicLayout)5 RenderNode (android.view.RenderNode)5