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

Commit 09637d60 authored by John Hoford's avatar John Hoford
Browse files

add animation and float variables

Test: RemoteCompose CTS test
Bug: 339721781

Change-Id: Ie7c8e732324d8e64d0cdb2badcf36f4e56e2dacf
parent 98ab960b
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