Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c54b3fad authored by Shu Chen's avatar Shu Chen Committed by Android (Google) Code Review
Browse files

Merge "Supports dynamic height for the new magnifier."

parents 08cfc5f3 d931a476
Loading
Loading
Loading
Loading
+38 −6
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.ActionMode;
import android.view.ActionMode.Callback;
import android.view.ContextMenu;
@@ -394,6 +395,19 @@ public class Editor {
    // Specifies whether the new magnifier (with fish-eye effect) is enabled.
    private final boolean mNewMagnifierEnabled;

    // Line height range in DP for the new magnifier.
    static private final int MIN_LINE_HEIGHT_FOR_MAGNIFIER = 20;
    static private final int MAX_LINE_HEIGHT_FOR_MAGNIFIER = 32;
    // Line height range in pixels for the new magnifier.
    //  - If the line height is bigger than the max, magnifier should be dismissed.
    //  - If the line height is smaller than the min, magnifier should apply a bigger zoom factor
    //    to make sure the text can be seen clearly.
    private int mMinLineHeightForMagnifier;
    private int mMaxLineHeightForMagnifier;
    // The zoom factor initially configured.
    // The actual zoom value may changes based on this initial zoom value.
    private float mInitialZoom = 1f;

    Editor(TextView textView) {
        mTextView = textView;
        // Synchronize the filter list, which places the undo input filter at the end.
@@ -440,8 +454,6 @@ public class Editor {
    private Magnifier.Builder createBuilderWithInlineMagnifierDefaults() {
        final Magnifier.Builder params = new Magnifier.Builder(mTextView);

        // TODO: supports changing the height/width dynamically because the text height can be
        // dynamically changed.
        float zoom = AppGlobals.getFloatCoreSetting(
                WidgetFlags.KEY_MAGNIFIER_ZOOM_FACTOR, 1.5f);
        float aspectRatio = AppGlobals.getFloatCoreSetting(
@@ -454,13 +466,20 @@ public class Editor {
            aspectRatio = 5.5f;
        }

        mInitialZoom = zoom;
        mMinLineHeightForMagnifier = (int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, MIN_LINE_HEIGHT_FOR_MAGNIFIER,
                mTextView.getContext().getResources().getDisplayMetrics());
        mMaxLineHeightForMagnifier = (int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, MAX_LINE_HEIGHT_FOR_MAGNIFIER,
                mTextView.getContext().getResources().getDisplayMetrics());

        final Layout layout = mTextView.getLayout();
        final int line = layout.getLineForOffset(mTextView.getSelectionStart());
        final int sourceHeight =
            layout.getLineBottomWithoutSpacing(line) - layout.getLineTop(line);
        // Slightly increase the height to avoid tooLargeTextForMagnifier() returns true.
        int height = (int)(sourceHeight * zoom) + 2;
        int width = (int)(aspectRatio * height);
        final int height = (int)(sourceHeight * zoom);
        final int width = (int)(aspectRatio * Math.max(sourceHeight, mMinLineHeightForMagnifier));

        params.setFishEyeStyle()
                .setSize(width, height)
@@ -4902,6 +4921,12 @@ public class Editor {
        }

        private boolean tooLargeTextForMagnifier() {
            if (mNewMagnifierEnabled) {
                Layout layout = mTextView.getLayout();
                final int line = layout.getLineForOffset(getCurrentCursorOffset());
                return layout.getLineBottomWithoutSpacing(line) - layout.getLineTop(line)
                        >= mMaxLineHeightForMagnifier;
            }
            final float magnifierContentHeight = Math.round(
                    mMagnifierAnimator.mMagnifier.getHeight()
                            / mMagnifierAnimator.mMagnifier.getZoom());
@@ -5111,6 +5136,13 @@ public class Editor {
                    int lineRight = (int) layout.getLineRight(line);
                    lineRight += mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
                    mMagnifierAnimator.mMagnifier.setSourceHorizontalBounds(lineLeft, lineRight);
                    final int lineHeight =
                            layout.getLineBottomWithoutSpacing(line) - layout.getLineTop(line);
                    float zoom = mInitialZoom;
                    if (lineHeight < mMinLineHeightForMagnifier) {
                        zoom = zoom * mMinLineHeightForMagnifier / lineHeight;
                    }
                    mMagnifierAnimator.mMagnifier.updateSourceFactors(lineHeight, zoom);
                    mMagnifierAnimator.mMagnifier.show(showPosInView.x, showPosInView.y);
                } else {
                    mMagnifierAnimator.show(showPosInView.x, showPosInView.y);
+75 −8
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ public final class Magnifier {
    // The width of the window containing the magnifier.
    private final int mWindowWidth;
    // The height of the window containing the magnifier.
    private final int mWindowHeight;
    private int mWindowHeight;
    // The zoom applied to the view region copied to the magnifier view.
    private float mZoom;
    // The width of the content that will be copied to the magnifier.
@@ -484,6 +484,21 @@ public final class Magnifier {
        mDirtyState = true;
    }

    /**
     * Updates the factors of source which may impact the magnifier's size.
     * This can be called while the magnifier is showing and moving.
     * @param sourceHeight the new source height.
     * @param zoom the new zoom factor.
     */
    void updateSourceFactors(final int sourceHeight, final float zoom) {
        mZoom = zoom;
        mSourceHeight = sourceHeight;
        mWindowHeight = (int) (sourceHeight * zoom);
        if (mWindow != null) {
            mWindow.updateContentFactors(mWindowHeight, zoom);
        }
    }

    /**
     * Returns the zoom to be applied to the magnified view region copied to the magnifier.
     * If the zoom is x and the magnifier window size is (width, height), the original size
@@ -904,7 +919,7 @@ public final class Magnifier {
        private final Display mDisplay;
        // The size of the content of the magnifier.
        private final int mContentWidth;
        private final int mContentHeight;
        private int mContentHeight;
        // The insets of the content inside the allocated surface.
        private final int mOffsetX;
        private final int mOffsetY;
@@ -947,7 +962,7 @@ public final class Magnifier {
        // The current content of the magnifier. It is mBitmap + mOverlay, only used for testing.
        private Bitmap mCurrentContent;

        private final float mZoom;
        private float mZoom;
        // The width of the ramp region in pixels on the left & right sides of the fish-eye effect.
        private final int mRamp;
        // Whether is in the new magnifier style.
@@ -1009,11 +1024,11 @@ public final class Magnifier {

            final RecordingCanvas canvas = mRenderer.getRootNode().beginRecording(width, height);
            try {
                canvas.insertReorderBarrier();
                canvas.enableZ();
                canvas.drawRenderNode(mBitmapRenderNode);
                canvas.insertInorderBarrier();
                canvas.disableZ();
                canvas.drawRenderNode(mOverlayRenderNode);
                canvas.insertInorderBarrier();
                canvas.disableZ();
            } finally {
                mRenderer.getRootNode().endRecording();
            }
@@ -1034,15 +1049,66 @@ public final class Magnifier {
            }
        }

        /**
         * Updates the factors of content which may resize the window.
         * @param contentHeight the new height of content.
         * @param zoom the new zoom factor.
         */
        private void updateContentFactors(final int contentHeight, final float zoom) {
            if (mContentHeight == contentHeight && mZoom == zoom) {
              return;
            }
            if (mContentHeight < contentHeight) {
                // Grows the surface height as necessary.
                new SurfaceControl.Transaction().setBufferSize(
                        mSurfaceControl, mContentWidth, contentHeight).apply();
                mSurface.copyFrom(mSurfaceControl);
                mRenderer.setSurface(mSurface);

                final Outline outline = new Outline();
                outline.setRoundRect(0, 0, mContentWidth, contentHeight, 0);
                outline.setAlpha(1.0f);

                mBitmapRenderNode.setLeftTopRightBottom(mOffsetX, mOffsetY,
                        mOffsetX + mContentWidth, mOffsetY + contentHeight);
                mBitmapRenderNode.setOutline(outline);

                mOverlayRenderNode.setLeftTopRightBottom(mOffsetX, mOffsetY,
                        mOffsetX + mContentWidth, mOffsetY + contentHeight);
                mOverlayRenderNode.setOutline(outline);

                final RecordingCanvas canvas =
                        mRenderer.getRootNode().beginRecording(mContentWidth, contentHeight);
                try {
                    canvas.enableZ();
                    canvas.drawRenderNode(mBitmapRenderNode);
                    canvas.disableZ();
                    canvas.drawRenderNode(mOverlayRenderNode);
                    canvas.disableZ();
                } finally {
                    mRenderer.getRootNode().endRecording();
                }
            }
            mContentHeight = contentHeight;
            mZoom = zoom;
            fillMeshMatrix();
        }

        private void createMeshMatrixForFishEyeEffect() {
            mMeshWidth = 1;
            mMeshHeight = 6;
            mMeshLeft = new float[2 * (mMeshWidth + 1) * (mMeshHeight + 1)];
            mMeshRight = new float[2 * (mMeshWidth + 1) * (mMeshHeight + 1)];
            fillMeshMatrix();
        }

        private void fillMeshMatrix() {
            mMeshWidth = 1;
            mMeshHeight = 6;
            final float w = mContentWidth;
            final float h = mContentHeight;
            final float h0 = h / mZoom;
            final float dh = h - h0;
            mMeshLeft = new float[2 * (mMeshWidth + 1) * (mMeshHeight + 1)];
            mMeshRight = new float[2 * (mMeshWidth + 1) * (mMeshHeight + 1)];
            for (int i = 0; i < 2 * (mMeshWidth + 1) * (mMeshHeight + 1); i += 2) {
                // Calculates X value.
                final int colIndex = i % (2 * (mMeshWidth + 1)) / 2;
@@ -1197,6 +1263,7 @@ public final class Magnifier {
            if (mBitmap != null) {
                mBitmap.recycle();
            }
            mOverlay.setCallback(null);
        }

        private void doDraw() {