/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.flat;
import java.util.Arrays;
import android.util.SparseIntArray;
/**
* {@link DrawCommandManager} with horizontal clipping (The view scrolls left and right).
*/
/* package */ final class HorizontalDrawCommandManager extends ClippingDrawCommandManager {
/* package */ HorizontalDrawCommandManager(
FlatViewGroup flatViewGroup,
DrawCommand[] drawCommands) {
super(flatViewGroup, drawCommands);
}
@Override
int commandStartIndex() {
int start = Arrays.binarySearch(mCommandMaxBottom, mClippingRect.left);
// We don't care whether we matched or not, but positive indices are helpful. The binary search
// returns ~index in the case that it isn't a match, so reverse that here.
return start < 0 ? ~start : start;
}
@Override
int commandStopIndex(int start) {
int stop = Arrays.binarySearch(
mCommandMinTop,
start,
mCommandMinTop.length,
mClippingRect.right);
// We don't care whether we matched or not, but positive indices are helpful. The binary search
// returns ~index in the case that it isn't a match, so reverse that here.
return stop < 0 ? ~stop : stop;
}
@Override
int regionStopIndex(float touchX, float touchY) {
int stop = Arrays.binarySearch(mRegionMinTop, touchX + 0.0001f);
// We don't care whether we matched or not, but positive indices are helpful. The binary search
// returns ~index in the case that it isn't a match, so reverse that here.
return stop < 0 ? ~stop : stop;
}
@Override
boolean regionAboveTouch(int index, float touchX, float touchY) {
return mRegionMaxBottom[index] < touchX;
}
/**
* Populates the max and min arrays for a given set of node regions.
*
* This should never be called from the UI thread, as the reason it exists is to do work off the
* UI thread.
*
* @param regions The regions that will eventually be mounted.
* @param maxRight At each index i, the maximum right value of all regions at or below i.
* @param minLeft At each index i, the minimum left value of all regions at or below i.
*/
public static void fillMaxMinArrays(NodeRegion[] regions, float[] maxRight, float[] minLeft) {
float last = 0;
for (int i = 0; i < regions.length; i++) {
last = Math.max(last, regions[i].getTouchableRight());
maxRight[i] = last;
}
for (int i = regions.length - 1; i >= 0; i--) {
last = Math.min(last, regions[i].getTouchableLeft());
minLeft[i] = last;
}
}
/**
* Populates the max and min arrays for a given set of draw commands. Also populates a mapping of
* react tags to their index position in the command array.
*
* This should never be called from the UI thread, as the reason it exists is to do work off the
* UI thread.
*
* @param commands The draw commands that will eventually be mounted.
* @param maxRight At each index i, the maximum right value of all draw commands at or below i.
* @param minLeft At each index i, the minimum left value of all draw commands at or below i.
* @param drawViewIndexMap Mapping of ids to index position within the draw command array.
*/
public static void fillMaxMinArrays(
DrawCommand[] commands,
float[] maxRight,
float[] minLeft,
SparseIntArray drawViewIndexMap) {
float last = 0;
// Loop through the DrawCommands, keeping track of the maximum we've seen if we only iterated
// through items up to this position.
for (int i = 0; i < commands.length; i++) {
if (commands[i] instanceof DrawView) {
DrawView drawView = (DrawView) commands[i];
// These will generally be roughly sorted by id, so try to insert at the end if possible.
drawViewIndexMap.append(drawView.reactTag, i);
last = Math.max(last, drawView.mLogicalRight);
} else {
last = Math.max(last, commands[i].getRight());
}
maxRight[i] = last;
}
// Intentionally leave last as it was, since it's at the maximum bottom position we've seen so
// far, we can use it again.
// Loop through backwards, keeping track of the minimum we've seen at this position.
for (int i = commands.length - 1; i >= 0; i--) {
if (commands[i] instanceof DrawView) {
last = Math.min(last, ((DrawView) commands[i]).mLogicalLeft);
} else {
last = Math.min(last, commands[i].getLeft());
}
minLeft[i] = last;
}
}
}