auto import from //depot/cupcake/@135843
diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp
new file mode 100644
index 0000000..bec7a64
--- /dev/null
+++ b/libs/surfaceflinger/Transform.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ui/Region.h>
+
+#include <private/pixelflinger/ggl_fixed.h>
+
+#include "Transform.h"
+
+// ---------------------------------------------------------------------------
+
+#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
+#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+Transform::Transform()
+ : mType(0)
+{
+ mTransform.reset();
+}
+
+Transform::Transform(const Transform& other)
+ : mTransform(other.mTransform), mType(other.mType)
+{
+}
+
+Transform::~Transform() {
+}
+
+Transform Transform::operator * (const Transform& rhs) const
+{
+ if (LIKELY(mType == 0))
+ return rhs;
+
+ Transform r(*this);
+ r.mTransform.preConcat(rhs.mTransform);
+ r.mType |= rhs.mType;
+ return r;
+}
+
+float Transform::operator [] (int i) const
+{
+ float r = 0;
+ switch(i) {
+ case 0: r = SkScalarToFloat( mTransform[SkMatrix::kMScaleX] ); break;
+ case 1: r = SkScalarToFloat( mTransform[SkMatrix::kMSkewX] ); break;
+ case 2: r = SkScalarToFloat( mTransform[SkMatrix::kMSkewY] ); break;
+ case 3: r = SkScalarToFloat( mTransform[SkMatrix::kMScaleY] ); break;
+ }
+ return r;
+}
+
+uint8_t Transform::type() const
+{
+ if (UNLIKELY(mType & 0x80000000)) {
+ mType = mTransform.getType();
+ }
+ return uint8_t(mType & 0xFF);
+}
+
+bool Transform::transformed() const {
+ return type() > SkMatrix::kTranslate_Mask;
+}
+
+int Transform::tx() const {
+ return SkScalarRound( mTransform[SkMatrix::kMTransX] );
+}
+
+int Transform::ty() const {
+ return SkScalarRound( mTransform[SkMatrix::kMTransY] );
+}
+
+void Transform::reset() {
+ mTransform.reset();
+ mType = 0;
+}
+
+void Transform::set( float xx, float xy,
+ float yx, float yy)
+{
+ mTransform.set(SkMatrix::kMScaleX, SkFloatToScalar(xx));
+ mTransform.set(SkMatrix::kMSkewX, SkFloatToScalar(xy));
+ mTransform.set(SkMatrix::kMSkewY, SkFloatToScalar(yx));
+ mTransform.set(SkMatrix::kMScaleY, SkFloatToScalar(yy));
+ mType |= 0x80000000;
+}
+
+void Transform::set(int tx, int ty)
+{
+ if (tx | ty) {
+ mTransform.set(SkMatrix::kMTransX, SkIntToScalar(tx));
+ mTransform.set(SkMatrix::kMTransY, SkIntToScalar(ty));
+ mType |= SkMatrix::kTranslate_Mask;
+ } else {
+ mTransform.set(SkMatrix::kMTransX, 0);
+ mTransform.set(SkMatrix::kMTransY, 0);
+ mType &= ~SkMatrix::kTranslate_Mask;
+ }
+}
+
+void Transform::transform(GLfixed* point, int x, int y) const
+{
+ SkPoint s;
+ mTransform.mapXY(SkIntToScalar(x), SkIntToScalar(y), &s);
+ point[0] = SkScalarToFixed(s.fX);
+ point[1] = SkScalarToFixed(s.fY);
+}
+
+Rect Transform::makeBounds(int w, int h) const
+{
+ Rect r;
+ SkRect d, s;
+ s.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
+ mTransform.mapRect(&d, s);
+ r.left = SkScalarRound( d.fLeft );
+ r.top = SkScalarRound( d.fTop );
+ r.right = SkScalarRound( d.fRight );
+ r.bottom = SkScalarRound( d.fBottom );
+ return r;
+}
+
+Rect Transform::transform(const Rect& bounds) const
+{
+ Rect r;
+ SkRect d, s;
+ s.set( SkIntToScalar( bounds.left ),
+ SkIntToScalar( bounds.top ),
+ SkIntToScalar( bounds.right ),
+ SkIntToScalar( bounds.bottom ));
+ mTransform.mapRect(&d, s);
+ r.left = SkScalarRound( d.fLeft );
+ r.top = SkScalarRound( d.fTop );
+ r.right = SkScalarRound( d.fRight );
+ r.bottom = SkScalarRound( d.fBottom );
+ return r;
+}
+
+Region Transform::transform(const Region& reg) const
+{
+ Region out;
+ if (UNLIKELY(transformed())) {
+ if (LIKELY(preserveRects())) {
+ Rect r;
+ Region::iterator iterator(reg);
+ while (iterator.iterate(&r)) {
+ out.orSelf(transform(r));
+ }
+ } else {
+ out.set(transform(reg.bounds()));
+ }
+ } else {
+ out = reg.translate(tx(), ty());
+ }
+ return out;
+}
+
+int32_t Transform::getOrientation() const
+{
+ uint32_t flags = 0;
+ if (UNLIKELY(transformed())) {
+ SkScalar a = mTransform[SkMatrix::kMScaleX];
+ SkScalar b = mTransform[SkMatrix::kMSkewX];
+ SkScalar c = mTransform[SkMatrix::kMSkewY];
+ SkScalar d = mTransform[SkMatrix::kMScaleY];
+ if (b==0 && c==0 && a && d) {
+ if (a<0) flags |= FLIP_H;
+ if (d<0) flags |= FLIP_V;
+ } else if (b && c && a==0 && d==0) {
+ flags |= ROT_90;
+ if (b>0) flags |= FLIP_H;
+ if (c<0) flags |= FLIP_V;
+ } else {
+ flags = 0x80000000;
+ }
+ }
+ return flags;
+}
+
+bool Transform::preserveRects() const
+{
+ return mTransform.rectStaysRect();
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android