Skip to content

Commit

Permalink
Fabric: Transform type and <View transform/> prop
Browse files Browse the repository at this point in the history
Summary: The matrix magic and parsing approach are mixins between current iOS and Android implementation.

Reviewed By: fkgozali

Differential Revision: D8344054

fbshipit-source-id: 524b48c5ab61959ce740373534d0d435eb37b647
  • Loading branch information
shergin authored and facebook-github-bot committed Jun 15, 2018
1 parent 3c8c017 commit 8df7d51
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 0 deletions.
1 change: 1 addition & 0 deletions ReactCommon/fabric/view/ViewProps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ ViewProps::ViewProps(const ViewProps &sourceProps, const RawProps &rawProps):
shadowOffset(convertRawProp(rawProps, "shadowOffset", sourceProps.shadowOffset)),
shadowOpacity(convertRawProp(rawProps, "shadowOpacity", sourceProps.shadowOpacity)),
shadowRadius(convertRawProp(rawProps, "shadowRadius", sourceProps.shadowRadius)),
transform(convertRawProp(rawProps, "transform", sourceProps.transform)),
backfaceVisibility(convertRawProp(rawProps, "backfaceVisibility", sourceProps.backfaceVisibility)),
shouldRasterize(convertRawProp(rawProps, "shouldRasterize", sourceProps.shouldRasterize)),
zIndex(convertRawProp(rawProps, "zIndex", sourceProps.zIndex)),
Expand Down
1 change: 1 addition & 0 deletions ReactCommon/fabric/view/ViewProps.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class ViewProps:
const Float shadowRadius {};

// Transform
const Transform transform {};
const bool backfaceVisibility {false};
const bool shouldRasterize {false};
const int zIndex {0};
Expand Down
48 changes: 48 additions & 0 deletions ReactCommon/fabric/view/conversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,54 @@ inline void fromDynamic(const folly::dynamic &value, YGFloatOptional &result) {
abort();
}

inline void fromDynamic(const folly::dynamic &value, Transform &result) {
assert(value.isArray());
Transform transformMatrix;
for (auto &&tranformConfiguration : value) {
assert(tranformConfiguration.isObject());
auto pair = *tranformConfiguration.items().begin();
auto &&operation = pair.first.asString();
auto &&parameters = pair.second;

if (operation == "matrix") {
assert(parameters.isArray());
assert(parameters.size() == transformMatrix.matrix.size());
int i = 0;
for (auto item : parameters) {
transformMatrix.matrix[i++] = (Float)item.asDouble();
}
} else if (operation == "perspective") {
transformMatrix = transformMatrix * Transform::Perspective((Float)parameters.asDouble());
} else if (operation == "rotateX") {
transformMatrix = transformMatrix * Transform::Rotate((Float)parameters.asDouble(), 0, 0);
} else if (operation == "rotateY") {
transformMatrix = transformMatrix * Transform::Rotate(0, (Float)parameters.asDouble(), 0);
} else if (operation == "rotateZ") {
transformMatrix = transformMatrix * Transform::Rotate(0, 0, (Float)parameters.asDouble());
} else if (operation == "scale") {
transformMatrix = transformMatrix * Transform::Scale((Float)parameters.asDouble(), (Float)parameters.asDouble(), (Float)parameters.asDouble());
} else if (operation == "scaleX") {
transformMatrix = transformMatrix * Transform::Scale((Float)parameters.asDouble(), 0, 0);
} else if (operation == "scaleY") {
transformMatrix = transformMatrix * Transform::Scale(0, (Float)parameters.asDouble(), 0);
} else if (operation == "scaleZ") {
transformMatrix = transformMatrix * Transform::Scale(0, 0, (Float)parameters.asDouble());
} else if (operation == "translate") {
transformMatrix = transformMatrix * Transform::Translate(parameters[0].asDouble(), parameters[1].asDouble(), 0);
} else if (operation == "translateX") {
transformMatrix = transformMatrix * Transform::Translate(parameters[0].asDouble(), 0, 0);
} else if (operation == "translateY") {
transformMatrix = transformMatrix * Transform::Translate(0, parameters[0].asDouble(), 0);
} else if (operation == "skewX") {
transformMatrix = transformMatrix * Transform::Skew(parameters.asDouble(), 0);
} else if (operation == "skewY") {
transformMatrix = transformMatrix * Transform::Skew(0, parameters.asDouble());
}
}

result = transformMatrix;
}

inline void fromDynamic(const folly::dynamic &value, PointerEventsMode &result) {
assert(value.isString());
auto stringValue = value.asString();
Expand Down
131 changes: 131 additions & 0 deletions ReactCommon/fabric/view/primitives.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,137 @@
namespace facebook {
namespace react {

struct Transform {
std::array<Float, 16> matrix {{
0, 0, 0, 0,

This comment has been minimized.

Copy link
@janicduplessis

janicduplessis Jun 17, 2018

Contributor

@shergin Shouldn't that row be 1, 0, 0, 0?

This comment has been minimized.

Copy link
@shergin

shergin Jun 17, 2018

Author Contributor

@janicduplessis ¯\_(ツ)_/¯ I am not sure. Should it be?

This comment has been minimized.

Copy link
@janicduplessis

janicduplessis Jun 18, 2018

Contributor

I think so since we’re using this as the identity matrix.

This comment has been minimized.

Copy link
@fkgozali

fkgozali Jun 19, 2018

Contributor

good catch @janicduplessis!

This comment has been minimized.

Copy link
@shergin

shergin Jun 19, 2018

Author Contributor

9a59428

Thanks!!1

0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
}};

static Transform Identity() {
Transform transform;
return transform;
}

static Transform Perspective(const Float &perspective) {
Transform transform;
transform.matrix[11] = -1.0 / perspective;
return transform;
}

static Transform Scale(const Float &factorX, const Float &factorY, const Float &factorZ) {
Transform transform;
transform.matrix[0] = factorX;
transform.matrix[5] = factorY;
transform.matrix[10] = factorZ;
return transform;
}

static Transform Translate(const Float &x, const Float &y, const Float &z) {
Transform transform;
transform.matrix[12] = x;
transform.matrix[13] = y;
transform.matrix[14] = z;
return transform;
}

static Transform Skew(const Float &x, const Float &y) {
Transform transform;
transform.matrix[4] = std::tan(x);
transform.matrix[1] = std::tan(y);
return transform;
}

static Transform RotateX(const Float &radians) {
Transform transform;
transform.matrix[5] = std::cos(radians);
transform.matrix[6] = std::sin(radians);
transform.matrix[9] = -std::sin(radians);
transform.matrix[10] = std::cos(radians);
return transform;
}

static Transform RotateY(const Float &radians) {
Transform transform;
transform.matrix[0] = std::cos(radians);
transform.matrix[2] = -std::sin(radians);
transform.matrix[8] = std::sin(radians);
transform.matrix[10] = std::cos(radians);
return transform;
}

static Transform RotateZ(const Float &radians) {
Transform transform;
transform.matrix[0] = std::cos(radians);
transform.matrix[1] = std::sin(radians);
transform.matrix[4] = -std::sin(radians);
transform.matrix[5] = std::cos(radians);
return transform;
}

static Transform Rotate(const Float &x, const Float &y, const Float &z) {
Transform transform;
if (x != 0) { transform = transform * Transform::RotateX(x); }
if (y != 0) { transform = transform * Transform::RotateY(y); }
if (z != 0) { transform = transform * Transform::RotateZ(z); }
return transform;
}

bool operator ==(const Transform& rhs) const {
for (int i = 0; i < 16; i++) {
if (matrix[i] != rhs.matrix[i]) {
return false;
}
}
return true;
}

bool operator !=(const Transform& rhs) const {
return !(*this == rhs);
}

Transform operator *(const Transform& rhs) const {
if (*this == Transform::Identity()) {
return rhs;
}

const Transform &lhs = *this;
Transform result;

Float lhs00 = lhs.matrix[0], lhs01 = lhs.matrix[1], lhs02 = lhs.matrix[2], lhs03 = lhs.matrix[3],
lhs10 = lhs.matrix[4], lhs11 = lhs.matrix[5], lhs12 = lhs.matrix[6], lhs13 = lhs.matrix[7],
lhs20 = lhs.matrix[8], lhs21 = lhs.matrix[9], lhs22 = lhs.matrix[10], lhs23 = lhs.matrix[11],
lhs30 = lhs.matrix[12], lhs31 = lhs.matrix[13], lhs32 = lhs.matrix[14], lhs33 = lhs.matrix[15];

Float rhs0 = rhs.matrix[0], rhs1 = rhs.matrix[1], rhs2 = rhs.matrix[2], rhs3 = rhs.matrix[3];
result.matrix[0] = rhs0 * lhs00 + rhs1 * lhs10 + rhs2 * lhs20 + rhs3 * lhs30;
result.matrix[1] = rhs0 * lhs01 + rhs1 * lhs11 + rhs2 * lhs21 + rhs3 * lhs31;
result.matrix[2] = rhs0 * lhs02 + rhs1 * lhs12 + rhs2 * lhs22 + rhs3 * lhs32;
result.matrix[3] = rhs0 * lhs03 + rhs1 * lhs13 + rhs2 * lhs23 + rhs3 * lhs33;

rhs0 = rhs.matrix[4]; rhs1 = rhs.matrix[5]; rhs2 = rhs.matrix[6]; rhs3 = rhs.matrix[7];
result.matrix[4] = rhs0 * lhs00 + rhs1 * lhs10 + rhs2 * lhs20 + rhs3 * lhs30;
result.matrix[5] = rhs0 * lhs01 + rhs1 * lhs11 + rhs2 * lhs21 + rhs3 * lhs31;
result.matrix[6] = rhs0 * lhs02 + rhs1 * lhs12 + rhs2 * lhs22 + rhs3 * lhs32;
result.matrix[7] = rhs0 * lhs03 + rhs1 * lhs13 + rhs2 * lhs23 + rhs3 * lhs33;

rhs0 = rhs.matrix[8]; rhs1 = rhs.matrix[9]; rhs2 = rhs.matrix[10]; rhs3 = rhs.matrix[11];
result.matrix[8] = rhs0 * lhs00 + rhs1 * lhs10 + rhs2 * lhs20 + rhs3 * lhs30;
result.matrix[9] = rhs0 * lhs01 + rhs1 * lhs11 + rhs2 * lhs21 + rhs3 * lhs31;
result.matrix[10] = rhs0 * lhs02 + rhs1 * lhs12 + rhs2 * lhs22 + rhs3 * lhs32;
result.matrix[11] = rhs0 * lhs03 + rhs1 * lhs13 + rhs2 * lhs23 + rhs3 * lhs33;

rhs0 = rhs.matrix[12]; rhs1 = rhs.matrix[13]; rhs2 = rhs.matrix[14]; rhs3 = rhs.matrix[15];
result.matrix[12] = rhs0 * lhs00 + rhs1 * lhs10 + rhs2 * lhs20 + rhs3 * lhs30;
result.matrix[13] = rhs0 * lhs01 + rhs1 * lhs11 + rhs2 * lhs21 + rhs3 * lhs31;
result.matrix[14] = rhs0 * lhs02 + rhs1 * lhs12 + rhs2 * lhs22 + rhs3 * lhs32;
result.matrix[15] = rhs0 * lhs03 + rhs1 * lhs13 + rhs2 * lhs23 + rhs3 * lhs33;

return result;
}
};

enum class PointerEventsMode {
Auto,
None,
Expand Down

0 comments on commit 8df7d51

Please sign in to comment.