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

Commit 8203adb3 authored by John Hoford's avatar John Hoford Committed by Android (Google) Code Review
Browse files

Merge "add RemoteCompose float math, text, and animation operations Test:...

Merge "add RemoteCompose float math, text, and animation operations Test: RemoteCompose CTS test Bug: 339721781" into main
parents 48459cba e92e30cf
Loading
Loading
Loading
Loading
+100 −49
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ public class CoreDocument {

    ArrayList<Operation> mOperations;
    RemoteComposeState mRemoteComposeState = new RemoteComposeState();

    TimeVariables mTimeVariables = new TimeVariables();
    // Semantic version of the document
    Version mVersion = new Version(0, 1, 0);

@@ -70,6 +70,7 @@ public class CoreDocument {

    public void setWidth(int width) {
        this.mWidth = width;
        mRemoteComposeState.setWindowWidth(width);
    }

    public int getHeight() {
@@ -78,6 +79,8 @@ public class CoreDocument {

    public void setHeight(int height) {
        this.mHeight = height;
        mRemoteComposeState.setWindowHeight(height);

    }

    public RemoteComposeBuffer getBuffer() {
@@ -154,37 +157,43 @@ public class CoreDocument {
                    float scale = Math.min(1f, Math.min(scaleX, scaleY));
                    contentScaleX = scale;
                    contentScaleY = scale;
                } break;
                }
                break;
                case RootContentBehavior.SCALE_FIT: {
                    float scaleX = w / mWidth;
                    float scaleY = h / mHeight;
                    float scale = Math.min(scaleX, scaleY);
                    contentScaleX = scale;
                    contentScaleY = scale;
                } break;
                }
                break;
                case RootContentBehavior.SCALE_FILL_WIDTH: {
                    float scale = w / mWidth;
                    contentScaleX = scale;
                    contentScaleY = scale;
                } break;
                }
                break;
                case RootContentBehavior.SCALE_FILL_HEIGHT: {
                    float scale = h / mHeight;
                    contentScaleX = scale;
                    contentScaleY = scale;
                } break;
                }
                break;
                case RootContentBehavior.SCALE_CROP: {
                    float scaleX = w / mWidth;
                    float scaleY = h / mHeight;
                    float scale = Math.max(scaleX, scaleY);
                    contentScaleX = scale;
                    contentScaleY = scale;
                } break;
                }
                break;
                case RootContentBehavior.SCALE_FILL_BOUNDS: {
                    float scaleX = w / mWidth;
                    float scaleY = h / mHeight;
                    contentScaleX = scaleX;
                    contentScaleY = scaleY;
                } break;
                }
                break;
                default:
                    // nothing
            }
@@ -215,26 +224,32 @@ public class CoreDocument {
        switch (horizontalContentAlignment) {
            case RootContentBehavior.ALIGNMENT_START: {
                // nothing
            } break;
            }
            break;
            case RootContentBehavior.ALIGNMENT_HORIZONTAL_CENTER: {
                translateX = (w - contentWidth) / 2f;
            } break;
            }
            break;
            case RootContentBehavior.ALIGNMENT_END: {
                translateX = w - contentWidth;
            } break;
            }
            break;
            default:
                // nothing (same as alignment_start)
        }
        switch (verticalContentAlignment) {
            case RootContentBehavior.ALIGNMENT_TOP: {
                // nothing
            } break;
            }
            break;
            case RootContentBehavior.ALIGNMENT_VERTICAL_CENTER: {
                translateY = (h - contentHeight) / 2f;
            } break;
            }
            break;
            case RootContentBehavior.ALIGNMENT_BOTTOM: {
                translateY = h - contentHeight;
            } break;
            }
            break;
            default:
                // nothing (same as alignment_top)
        }
@@ -291,6 +306,12 @@ public class CoreDocument {
            this.mMetadata = metadata;
        }

        /**
         * Returns true if x,y coordinate is within bounds
         * @param x x-coordinate
         * @param y y-coordinate
         * @return x,y coordinate is within bounds
         */
        public boolean contains(float x, float y) {
            return x >= mLeft && x < mRight
                    && y >= mTop && y < mBottom;
@@ -341,16 +362,22 @@ public class CoreDocument {
    public void initializeContext(RemoteContext context) {
        mRemoteComposeState.reset();
        mClickAreas.clear();

        mRemoteComposeState.setNextId(RemoteComposeState.START_ID);
        context.mDocument = this;
        context.mRemoteComposeState = mRemoteComposeState;

        // mark context to be in DATA mode, which will skip the painting ops.
        context.mMode = RemoteContext.ContextMode.DATA;
        mTimeVariables.updateTime(context);

        for (Operation op : mOperations) {
            if (op instanceof VariableSupport) {
                ((VariableSupport) op).updateVariables(context);
                ((VariableSupport) op).registerListening(context);
            }
            op.apply(context);
        }
        context.mMode = RemoteContext.ContextMode.UNSET;

    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
@@ -446,12 +473,31 @@ public class CoreDocument {
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        for (Operation op : mOperations) {
            builder.append(op.toString());
            builder.append("\n");
        }
        return builder.toString();
    }

    //////////////////////////////////////////////////////////////////////////
    // Painting
    ///////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////

    private final float[] mScaleOutput = new float[2];
    private final float[] mTranslateOutput = new float[2];
    private int mRepaintNext = -1; // delay to next repaint -1 = don't 1 = asap

    /**
     * Returns > 0 if it needs to repaint
     * @return
     */
    public int needsRepaint() {
        return mRepaintNext;
    }

    /**
     * Paint the document
@@ -475,6 +521,11 @@ public class CoreDocument {
            context.mPaintContext.translate(mTranslateOutput[0], mTranslateOutput[1]);
            context.mPaintContext.scale(mScaleOutput[0], mScaleOutput[1]);
        }
        mTimeVariables.updateTime(context);
        context.loadFloat(RemoteContext.ID_WINDOW_WIDTH, getWidth());
        context.loadFloat(RemoteContext.ID_WINDOW_HEIGHT, getHeight());
        mRepaintNext = context.updateOps();

        for (Operation op : mOperations) {
            // operations will only be executed if no theme is set (ie UNSPECIFIED)
            // or the theme is equal as the one passed in argument to paint.
+24 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import com.android.internal.widget.remotecompose.core.operations.BitmapData;
import com.android.internal.widget.remotecompose.core.operations.ClickArea;
import com.android.internal.widget.remotecompose.core.operations.ClipPath;
import com.android.internal.widget.remotecompose.core.operations.ClipRect;
import com.android.internal.widget.remotecompose.core.operations.ColorExpression;
import com.android.internal.widget.remotecompose.core.operations.DrawArc;
import com.android.internal.widget.remotecompose.core.operations.DrawBitmap;
import com.android.internal.widget.remotecompose.core.operations.DrawBitmapInt;
@@ -28,9 +29,12 @@ import com.android.internal.widget.remotecompose.core.operations.DrawOval;
import com.android.internal.widget.remotecompose.core.operations.DrawPath;
import com.android.internal.widget.remotecompose.core.operations.DrawRect;
import com.android.internal.widget.remotecompose.core.operations.DrawRoundRect;
import com.android.internal.widget.remotecompose.core.operations.DrawText;
import com.android.internal.widget.remotecompose.core.operations.DrawTextAnchored;
import com.android.internal.widget.remotecompose.core.operations.DrawTextOnPath;
import com.android.internal.widget.remotecompose.core.operations.DrawTextRun;
import com.android.internal.widget.remotecompose.core.operations.DrawTweenPath;
import com.android.internal.widget.remotecompose.core.operations.FloatConstant;
import com.android.internal.widget.remotecompose.core.operations.FloatExpression;
import com.android.internal.widget.remotecompose.core.operations.Header;
import com.android.internal.widget.remotecompose.core.operations.MatrixRestore;
import com.android.internal.widget.remotecompose.core.operations.MatrixRotate;
@@ -42,7 +46,10 @@ import com.android.internal.widget.remotecompose.core.operations.PaintData;
import com.android.internal.widget.remotecompose.core.operations.PathData;
import com.android.internal.widget.remotecompose.core.operations.RootContentBehavior;
import com.android.internal.widget.remotecompose.core.operations.RootContentDescription;
import com.android.internal.widget.remotecompose.core.operations.ShaderData;
import com.android.internal.widget.remotecompose.core.operations.TextData;
import com.android.internal.widget.remotecompose.core.operations.TextFromFloat;
import com.android.internal.widget.remotecompose.core.operations.TextMerge;
import com.android.internal.widget.remotecompose.core.operations.Theme;
import com.android.internal.widget.remotecompose.core.operations.utilities.IntMap;

@@ -67,6 +74,7 @@ public class Operations {
    public static final int DRAW_BITMAP = 44;
    public static final int DRAW_BITMAP_INT = 66;
    public static final int DATA_BITMAP = 101;
    public static final int DATA_SHADER = 45;
    public static final int DATA_TEXT = 102;

    /////////////////////////////=====================
@@ -91,6 +99,12 @@ public class Operations {
    public static final int MATRIX_SAVE = 130;
    public static final int MATRIX_RESTORE = 131;
    public static final int MATRIX_SET = 132;
    public static final int DATA_FLOAT = 80;
    public static final int ANIMATED_FLOAT = 81;
    public static final int DRAW_TEXT_ANCHOR = 133;
    public static final int COLOR_EXPRESSIONS = 134;
    public static final int TEXT_FROM_FLOAT = 135;
    public static final int TEXT_MERGE = 136;

    /////////////////////////////////////////======================
    public static IntMap<CompanionOperation> map = new IntMap<>();
@@ -114,7 +128,7 @@ public class Operations {
        map.put(DRAW_RECT, DrawRect.COMPANION);
        map.put(DRAW_ROUND_RECT, DrawRoundRect.COMPANION);
        map.put(DRAW_TEXT_ON_PATH, DrawTextOnPath.COMPANION);
        map.put(DRAW_TEXT_RUN, DrawTextRun.COMPANION);
        map.put(DRAW_TEXT_RUN, DrawText.COMPANION);
        map.put(DRAW_TWEEN_PATH, DrawTweenPath.COMPANION);
        map.put(DATA_PATH, PathData.COMPANION);
        map.put(PAINT_VALUES, PaintData.COMPANION);
@@ -126,6 +140,13 @@ public class Operations {
        map.put(MATRIX_TRANSLATE, MatrixTranslate.COMPANION);
        map.put(CLIP_PATH, ClipPath.COMPANION);
        map.put(CLIP_RECT, ClipRect.COMPANION);
        map.put(DATA_SHADER, ShaderData.COMPANION);
        map.put(DATA_FLOAT, FloatConstant.COMPANION);
        map.put(ANIMATED_FLOAT, FloatExpression.COMPANION);
        map.put(DRAW_TEXT_ANCHOR, DrawTextAnchored.COMPANION);
        map.put(COLOR_EXPRESSIONS, ColorExpression.COMPANION);
        map.put(TEXT_FROM_FLOAT, TextFromFloat.COMPANION);
        map.put(TEXT_MERGE, TextMerge.COMPANION);

    }

+88 −3
Original line number Diff line number Diff line
@@ -68,7 +68,35 @@ public abstract class PaintContext {

    public abstract void drawTextOnPath(int textId, int pathId, float hOffset, float vOffset);

    public abstract void drawTextRun(int textID,
    /**
     * Return the dimensions (left, top, right, bottom).
     * Relative to a drawTextRun x=0, y=0;
     *
     * @param textId
     * @param start
     * @param end    if end is -1 it means the whole string
     * @param monospace measure with better support for monospace
     * @param bounds the bounds (left, top, right, bottom)
     */
    public abstract void getTextBounds(int textId,
                                       int start,
                                       int end,
                                       boolean monospace,
                                       float[]bounds);

    /**
     * Draw a text starting ast x,y
     *
     * @param textId reference to the text
     * @param start
     * @param end
     * @param contextStart
     * @param contextEnd
     * @param x
     * @param y
     * @param rtl
     */
    public abstract void drawTextRun(int textId,
                                     int start,
                                     int end,
                                     int contextStart,
@@ -77,6 +105,14 @@ public abstract class PaintContext {
                                     float y,
                                     boolean rtl);

    /**
     * Draw an interpolation between two paths
     * @param path1Id
     * @param path2Id
     * @param tween  0.0 = is path1 1.0 is path2
     * @param start
     * @param stop
     */
    public abstract void drawTweenPath(int path1Id,
                                       int path2Id,
                                       float tween,
@@ -85,21 +121,70 @@ public abstract class PaintContext {

    public abstract void applyPaint(PaintBundle mPaintData);

    public abstract void mtrixScale(float scaleX, float scaleY, float centerX, float centerY);
    /**
     * Scale the rendering by scaleX and saleY (1.0 = no scale).
     * Scaling is done about centerX,centerY.
     *
     * @param scaleX
     * @param scaleY
     * @param centerX
     * @param centerY
     */
    public abstract void matrixScale(float scaleX, float scaleY, float centerX, float centerY);

    /**
     * Translate the rendering
     * @param translateX
     * @param translateY
     */
    public abstract void matrixTranslate(float translateX, float translateY);

    /**
     * Skew the rendering
     * @param skewX
     * @param skewY
     */
    public abstract void matrixSkew(float skewX, float skewY);

    /**
     * Rotate the rendering.
     * Note rotates are cumulative.
     * @param rotate angle to rotate
     * @param pivotX x-coordinate about which to rotate
     * @param pivotY y-coordinate about which to rotate
     */
    public abstract void matrixRotate(float rotate, float pivotX, float pivotY);

    /**
     * Save the current state of the transform
     */
    public abstract void matrixSave();

    /**
     * Restore the previously saved state of the transform
     */
    public abstract void matrixRestore();

    /**
     * Set the clip to a rectangle.
     * Drawing outside the current clip region will have no effect
     * @param left
     * @param top
     * @param right
     * @param bottom
     */
    public abstract void clipRect(float left, float top, float right, float bottom);

    /**
     * Clip based on a path.
     * @param pathId
     * @param regionOp
     */
    public abstract void clipPath(int pathId, int regionOp);

    /**
     * Reset the paint
     */
    public abstract void reset();
}
+341 −8

File changed.

Preview size limit exceeded, changes collapsed.

+164 −10
Original line number Diff line number Diff line
@@ -15,25 +15,52 @@
 */
package com.android.internal.widget.remotecompose.core;

import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_CONTINUOUS_SEC;
import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_TIME_IN_MIN;
import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_TIME_IN_SEC;
import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_WINDOW_HEIGHT;
import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_WINDOW_WIDTH;

import com.android.internal.widget.remotecompose.core.operations.utilities.IntMap;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * Represents runtime state for a RemoteCompose document
 * State includes things like the value of variables
 */
public class RemoteComposeState {

    public static final int START_ID = 42;
    private static final int MAX_FLOATS = 500;
    private final IntMap<Object> mIntDataMap = new IntMap<>();
    private final IntMap<Boolean> mIntWrittenMap = new IntMap<>();
    private final HashMap<Object, Integer> mDataIntMap = new HashMap();
    private final float[] mFloatMap = new float[MAX_FLOATS]; // efficient cache
    private final int[] mColorMap = new int[MAX_FLOATS]; // efficient cache
    private int mNextId = START_ID;

    private static int sNextId = 42;
    {
        for (int i = 0; i < mFloatMap.length; i++) {
            mFloatMap[i] = Float.NaN;
        }
    }

    /**
     * Get Object based on id. The system will cache things like bitmaps
     * Paths etc. They can be accessed with this command
     * @param id
     * @return
     */
    public Object getFromId(int id) {
        return mIntDataMap.get(id);
    }

    /**
     * true if the cache contain this id
     * @param id
     * @return
     */
    public boolean containsId(int id) {
        return mIntDataMap.get(id) != null;
    }
@@ -68,6 +95,65 @@ public class RemoteComposeState {
        mIntDataMap.put(id, item);
    }

    /**
     * Insert an item in the cache
     */
    public void update(int id, Object item) {
        mDataIntMap.remove(mIntDataMap.get(id));
        mDataIntMap.put(item, id);
        mIntDataMap.put(id, item);
    }

    /**
     * Insert an item in the cache
     */
    public int cacheFloat(float item) {
        int id = nextId();
        mFloatMap[id] = item;
        return id;
    }

    /**
     * Insert an item in the cache
     */
    public void cacheFloat(int id, float item) {
        mFloatMap[id] = item;
    }

    /**
     * Insert an item in the cache
     */
    public void updateFloat(int id, float item) {
        mFloatMap[id] = item;
    }

    /**
     * get float
     */
    public float getFloat(int id) {
        return mFloatMap[id];
    }

    /**
     * Get the float value
     *
     * @param id
     * @return
     */
    public int getColor(int id) {
        return mColorMap[id];
    }

    /**
     * Modify the color at id.
     * @param id
     * @param color
     */
    public void updateColor(int id, int color) {
        mColorMap[id] = color;
    }


    /**
     * Method to determine if a cached value has been written to the documents WireBuffer based on
     * its id.
@@ -90,11 +176,79 @@ public class RemoteComposeState {
        mIntWrittenMap.clear();
    }

    public static int nextId() {
        return sNextId++;
    /**
     * Get the next available id
     * @return
     */
    public int nextId() {
        return mNextId++;
    }

    /**
     * Set the next id
     * @param id
     */
    public void setNextId(int id) {
        mNextId = id;
    }

    IntMap<ArrayList<VariableSupport>> mVarListeners = new IntMap<>();
    ArrayList<VariableSupport> mAllVarListeners = new ArrayList<>();

    private void add(int id, VariableSupport variableSupport) {
        ArrayList<VariableSupport> v = mVarListeners.get(id);
        if (v == null) {
            v = new ArrayList<VariableSupport>();
            mVarListeners.put(id, v);
        }
        v.add(variableSupport);
        mAllVarListeners.add(variableSupport);
    }

    /**
     * Commands that listen to variables add themselves.
     * @param id
     * @param variableSupport
     */
    public void listenToVar(int id, VariableSupport variableSupport) {
        add(id, variableSupport);
    }

    /**
     * List of Commands that need to be updated
     * @param context
     * @return
     */
    public int getOpsToUpdate(RemoteContext context) {
        for (VariableSupport vs : mAllVarListeners) {
            vs.updateVariables(context);
        }
        if (mVarListeners.get(ID_CONTINUOUS_SEC) != null) {
            return 1;
        }
        if (mVarListeners.get(ID_TIME_IN_SEC) != null) {
            return 1000;
        }
        if (mVarListeners.get(ID_TIME_IN_MIN) != null) {
            return 1000 * 60;
        }
    public static void setNextId(int id) {
        sNextId = id;
        return -1;
    }

    /**
     * Set the width of the overall document on screen.
     * @param width
     */
    public void setWindowWidth(float width) {
        updateFloat(ID_WINDOW_WIDTH, width);
    }

    /**
     * Set the width of the overall document on screen.
     * @param height
     */
    public void setWindowHeight(float height) {
        updateFloat(ID_WINDOW_HEIGHT, height);
    }

}
Loading