aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:21 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:21 -0800
commit03202c9c3dfbf8c4feb0a1ee9b3680817e633f58 (patch)
tree1d0ba7cbf3e77c239527697ac455312b216c434e /src/utils
parent37df15a82319228ae28fe5d99c010b288aad7091 (diff)
downloadexternal_skia-03202c9c3dfbf8c4feb0a1ee9b3680817e633f58.zip
external_skia-03202c9c3dfbf8c4feb0a1ee9b3680817e633f58.tar.gz
external_skia-03202c9c3dfbf8c4feb0a1ee9b3680817e633f58.tar.bz2
auto import from //branches/cupcake/...@125939
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/SkCamera.cpp449
-rw-r--r--src/utils/SkColorMatrix.cpp165
-rw-r--r--src/utils/SkCullPoints.cpp168
-rw-r--r--src/utils/SkDumpCanvas.cpp398
-rw-r--r--src/utils/SkInterpolator.cpp339
-rw-r--r--src/utils/SkNinePatch.cpp287
-rw-r--r--src/utils/SkProxyCanvas.cpp162
-rw-r--r--src/utils/SkUnitMappers.cpp80
-rw-r--r--src/utils/mac/SkBitmap_Mac.cpp142
-rw-r--r--src/utils/mac/SkCreateCGImageRef.cpp67
-rw-r--r--src/utils/mac/SkOSWindow_Mac.cpp450
11 files changed, 2707 insertions, 0 deletions
diff --git a/src/utils/SkCamera.cpp b/src/utils/SkCamera.cpp
new file mode 100644
index 0000000..b02499f
--- /dev/null
+++ b/src/utils/SkCamera.cpp
@@ -0,0 +1,449 @@
+/* libs/graphics/effects/SkCamera.cpp
+**
+** Copyright 2006, 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 "SkCamera.h"
+
+static SkScalar SkScalarDotDiv(int count, const SkScalar a[], int step_a,
+ const SkScalar b[], int step_b,
+ SkScalar denom)
+{
+#ifdef SK_SCALAR_IS_FLOAT
+ float prod = 0;
+ for (int i = 0; i < count; i++)
+ {
+ prod += a[0] * b[0];
+ a += step_a;
+ b += step_b;
+ }
+ return prod / denom;
+#else
+ Sk64 prod, tmp;
+
+ prod.set(0);
+ for (int i = 0; i < count; i++)
+ {
+ tmp.setMul(a[0], b[0]);
+ prod.add(tmp);
+ a += step_a;
+ b += step_b;
+ }
+ prod.div(denom, Sk64::kRound_DivOption);
+ return prod.get32();
+#endif
+}
+
+static SkScalar SkScalarDot(int count, const SkScalar a[], int step_a,
+ const SkScalar b[], int step_b)
+{
+#ifdef SK_SCALAR_IS_FLOAT
+ float prod = 0;
+ for (int i = 0; i < count; i++)
+ {
+ prod += a[0] * b[0];
+ a += step_a;
+ b += step_b;
+ }
+ return prod;
+#else
+ Sk64 prod, tmp;
+
+ prod.set(0);
+ for (int i = 0; i < count; i++)
+ {
+ tmp.setMul(a[0], b[0]);
+ prod.add(tmp);
+ a += step_a;
+ b += step_b;
+ }
+ return prod.getFixed();
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+SkUnitScalar SkPoint3D::normalize(SkUnit3D* unit) const
+{
+#ifdef SK_SCALAR_IS_FLOAT
+ float mag = sk_float_sqrt(fX*fX + fY*fY + fZ*fZ);
+ if (mag)
+ {
+ float scale = 1.0f / mag;
+ unit->fX = fX * scale;
+ unit->fY = fY * scale;
+ unit->fZ = fZ * scale;
+ }
+#else
+ Sk64 tmp1, tmp2;
+
+ tmp1.setMul(fX, fX);
+ tmp2.setMul(fY, fY);
+ tmp1.add(tmp2);
+ tmp2.setMul(fZ, fZ);
+ tmp1.add(tmp2);
+
+ SkFixed mag = tmp1.getSqrt();
+ if (mag)
+ {
+ // what if mag < SK_Fixed1 ??? we will underflow the fixdiv
+ SkFixed scale = SkFixedDiv(SK_Fract1, mag);
+ unit->fX = SkFixedMul(fX, scale);
+ unit->fY = SkFixedMul(fY, scale);
+ unit->fZ = SkFixedMul(fZ, scale);
+ }
+#endif
+ return mag;
+}
+
+SkUnitScalar SkUnit3D::Dot(const SkUnit3D& a, const SkUnit3D& b)
+{
+ return SkUnitScalarMul(a.fX, b.fX) +
+ SkUnitScalarMul(a.fY, b.fY) +
+ SkUnitScalarMul(a.fZ, b.fZ);
+}
+
+void SkUnit3D::Cross(const SkUnit3D& a, const SkUnit3D& b, SkUnit3D* cross)
+{
+ SkASSERT(cross);
+
+ // use x,y,z, in case &a == cross or &b == cross
+
+
+ SkScalar x = SkUnitScalarMul(a.fY, b.fZ) - SkUnitScalarMul(a.fZ, b.fY);
+ SkScalar y = SkUnitScalarMul(a.fZ, b.fX) - SkUnitScalarMul(a.fX, b.fY);
+ SkScalar z = SkUnitScalarMul(a.fX, b.fY) - SkUnitScalarMul(a.fY, b.fX);
+
+ cross->set(x, y, z);
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+SkPatch3D::SkPatch3D()
+{
+ this->reset();
+}
+
+void SkPatch3D::reset()
+{
+ fOrigin.set(0, 0, 0);
+ fU.set(SK_Scalar1, 0, 0);
+ fV.set(0, -SK_Scalar1, 0);
+}
+
+void SkPatch3D::transform(const SkMatrix3D& m, SkPatch3D* dst) const
+{
+ if (dst == NULL)
+ dst = (SkPatch3D*)this;
+
+ m.mapVector(fU, &dst->fU);
+ m.mapVector(fV, &dst->fV);
+ m.mapPoint(fOrigin, &dst->fOrigin);
+}
+
+SkScalar SkPatch3D::dotWith(SkScalar dx, SkScalar dy, SkScalar dz) const
+{
+ SkScalar cx = SkScalarMul(fU.fY, fV.fZ) - SkScalarMul(fU.fZ, fV.fY);
+ SkScalar cy = SkScalarMul(fU.fZ, fV.fX) - SkScalarMul(fU.fX, fV.fY);
+ SkScalar cz = SkScalarMul(fU.fX, fV.fY) - SkScalarMul(fU.fY, fV.fX);
+
+ return SkScalarMul(cx, dx) + SkScalarMul(cy, dy) + SkScalarMul(cz, dz);
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+void SkMatrix3D::reset()
+{
+ memset(fMat, 0, sizeof(fMat));
+ fMat[0][0] = fMat[1][1] = fMat[2][2] = SK_Scalar1;
+}
+
+void SkMatrix3D::setTranslate(SkScalar x, SkScalar y, SkScalar z)
+{
+ memset(fMat, 0, sizeof(fMat));
+ fMat[0][0] = x;
+ fMat[1][1] = y;
+ fMat[2][2] = z;
+}
+
+void SkMatrix3D::setRotateX(SkScalar degX)
+{
+ SkScalar s, c;
+
+ s = SkScalarSinCos(SkDegreesToRadians(degX), &c);
+ this->setRow(0, SK_Scalar1, 0, 0);
+ this->setRow(1, 0, c, -s);
+ this->setRow(2, 0, s, c);
+}
+
+void SkMatrix3D::setRotateY(SkScalar degY)
+{
+ SkScalar s, c;
+
+ s = SkScalarSinCos(SkDegreesToRadians(degY), &c);
+ this->setRow(0, c, 0, -s);
+ this->setRow(1, 0, SK_Scalar1, 0);
+ this->setRow(2, s, 0, c);
+}
+
+void SkMatrix3D::setRotateZ(SkScalar degZ)
+{
+ SkScalar s, c;
+
+ s = SkScalarSinCos(SkDegreesToRadians(degZ), &c);
+ this->setRow(0, c, -s, 0);
+ this->setRow(1, s, c, 0);
+ this->setRow(2, 0, 0, SK_Scalar1);
+}
+
+void SkMatrix3D::preTranslate(SkScalar x, SkScalar y, SkScalar z)
+{
+ SkScalar col[3] = { x, y, z};
+
+ for (int i = 0; i < 3; i++)
+ fMat[i][3] += SkScalarDot(3, &fMat[i][0], 1, col, 1);
+}
+
+void SkMatrix3D::preRotateX(SkScalar degX)
+{
+ SkMatrix3D m;
+ m.setRotateX(degX);
+ this->setConcat(*this, m);
+}
+
+void SkMatrix3D::preRotateY(SkScalar degY)
+{
+ SkMatrix3D m;
+ m.setRotateY(degY);
+ this->setConcat(*this, m);
+}
+
+void SkMatrix3D::preRotateZ(SkScalar degZ)
+{
+ SkMatrix3D m;
+ m.setRotateZ(degZ);
+ this->setConcat(*this, m);
+}
+
+void SkMatrix3D::setConcat(const SkMatrix3D& a, const SkMatrix3D& b)
+{
+ SkMatrix3D tmp;
+ SkMatrix3D* c = this;
+
+ if (this == &a || this == &b)
+ c = &tmp;
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++)
+ c->fMat[i][j] = SkScalarDot(3, &a.fMat[i][0], 1, &b.fMat[0][j], 4);
+ c->fMat[i][3] = SkScalarDot(3, &a.fMat[i][0], 1, &b.fMat[0][3], 4) + a.fMat[i][3];
+ }
+
+ if (c == &tmp)
+ *this = tmp;
+}
+
+void SkMatrix3D::mapPoint(const SkPoint3D& src, SkPoint3D* dst) const
+{
+ SkScalar x = SkScalarDot(3, &fMat[0][0], 1, &src.fX, 1) + fMat[0][3];
+ SkScalar y = SkScalarDot(3, &fMat[1][0], 1, &src.fX, 1) + fMat[1][3];
+ SkScalar z = SkScalarDot(3, &fMat[2][0], 1, &src.fX, 1) + fMat[2][3];
+ dst->set(x, y, z);
+}
+
+void SkMatrix3D::mapVector(const SkVector3D& src, SkVector3D* dst) const
+{
+ SkScalar x = SkScalarDot(3, &fMat[0][0], 1, &src.fX, 1);
+ SkScalar y = SkScalarDot(3, &fMat[1][0], 1, &src.fX, 1);
+ SkScalar z = SkScalarDot(3, &fMat[2][0], 1, &src.fX, 1);
+ dst->set(x, y, z);
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+SkCamera3D::SkCamera3D()
+{
+ this->reset();
+}
+
+void SkCamera3D::reset()
+{
+ fLocation.set(0, 0, -SkIntToScalar(576)); // 8 inches backward
+ fAxis.set(0, 0, SK_Scalar1); // forward
+ fZenith.set(0, -SK_Scalar1, 0); // up
+
+ fObserver.set(0, 0, fLocation.fZ);
+
+ fNeedToUpdate = true;
+}
+
+void SkCamera3D::update()
+{
+ fNeedToUpdate = true;
+}
+
+void SkCamera3D::doUpdate() const
+{
+ SkUnit3D axis, zenith, cross;
+
+ fAxis.normalize(&axis);
+
+ {
+ SkScalar dot = SkUnit3D::Dot(*(const SkUnit3D*)(const void*)&fZenith, axis);
+
+ zenith.fX = fZenith.fX - SkUnitScalarMul(dot, axis.fX);
+ zenith.fY = fZenith.fY - SkUnitScalarMul(dot, axis.fY);
+ zenith.fZ = fZenith.fZ - SkUnitScalarMul(dot, axis.fZ);
+
+ (void)((SkPoint3D*)(void*)&zenith)->normalize(&zenith);
+ }
+
+ SkUnit3D::Cross(axis, zenith, &cross);
+
+ {
+ SkMatrix* orien = &fOrientation;
+ SkScalar x = fObserver.fX;
+ SkScalar y = fObserver.fY;
+ SkScalar z = fObserver.fZ;
+
+ orien->set(SkMatrix::kMScaleX, SkUnitScalarMul(x, axis.fX) - SkUnitScalarMul(z, cross.fX));
+ orien->set(SkMatrix::kMSkewX, SkUnitScalarMul(x, axis.fY) - SkUnitScalarMul(z, cross.fY));
+ orien->set(SkMatrix::kMTransX, SkUnitScalarMul(x, axis.fZ) - SkUnitScalarMul(z, cross.fZ));
+ orien->set(SkMatrix::kMSkewY, SkUnitScalarMul(y, axis.fX) - SkUnitScalarMul(z, zenith.fX));
+ orien->set(SkMatrix::kMScaleY, SkUnitScalarMul(y, axis.fY) - SkUnitScalarMul(z, zenith.fY));
+ orien->set(SkMatrix::kMTransY, SkUnitScalarMul(y, axis.fZ) - SkUnitScalarMul(z, zenith.fZ));
+ orien->set(SkMatrix::kMPersp0, axis.fX);
+ orien->set(SkMatrix::kMPersp1, axis.fY);
+ orien->set(SkMatrix::kMPersp2, axis.fZ);
+ }
+}
+
+void SkCamera3D::patchToMatrix(const SkPatch3D& quilt, SkMatrix* matrix) const
+{
+ if (fNeedToUpdate)
+ {
+ this->doUpdate();
+ fNeedToUpdate = false;
+ }
+
+ const SkScalar* mapPtr = (const SkScalar*)(const void*)&fOrientation;
+ const SkScalar* patchPtr;
+ SkPoint3D diff;
+ SkScalar dot;
+
+ diff.fX = quilt.fOrigin.fX - fLocation.fX;
+ diff.fY = quilt.fOrigin.fY - fLocation.fY;
+ diff.fZ = quilt.fOrigin.fZ - fLocation.fZ;
+
+ dot = SkUnit3D::Dot(*(const SkUnit3D*)(const void*)&diff,
+ *(const SkUnit3D*)(((const SkScalar*)(const void*)&fOrientation) + 6));
+
+ patchPtr = (const SkScalar*)&quilt;
+ matrix->set(SkMatrix::kMScaleX, SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot));
+ matrix->set(SkMatrix::kMSkewY, SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot));
+ matrix->set(SkMatrix::kMPersp0, SkScalarDotDiv(3, patchPtr, 1, mapPtr+6, 1, dot));
+
+ patchPtr += 3;
+ matrix->set(SkMatrix::kMSkewX, SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot));
+ matrix->set(SkMatrix::kMScaleY, SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot));
+ matrix->set(SkMatrix::kMPersp1, SkScalarDotDiv(3, patchPtr, 1, mapPtr+6, 1, dot));
+
+ patchPtr = (const SkScalar*)(const void*)&diff;
+ matrix->set(SkMatrix::kMTransX, SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot));
+ matrix->set(SkMatrix::kMTransY, SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot));
+ matrix->set(SkMatrix::kMPersp2, SK_UnitScalar1);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+Sk3DView::Sk3DView()
+{
+ fInitialRec.fMatrix.reset();
+ fRec = &fInitialRec;
+}
+
+Sk3DView::~Sk3DView()
+{
+ Rec* rec = fRec;
+ while (rec != &fInitialRec) {
+ Rec* next = rec->fNext;
+ SkDELETE(rec);
+ rec = next;
+ }
+}
+
+void Sk3DView::save()
+{
+ Rec* rec = SkNEW(Rec);
+ rec->fNext = fRec;
+ rec->fMatrix = fRec->fMatrix;
+ fRec = rec;
+}
+
+void Sk3DView::restore()
+{
+ SkASSERT(fRec != &fInitialRec);
+ Rec* next = fRec->fNext;
+ SkDELETE(fRec);
+ fRec = next;
+}
+
+void Sk3DView::translate(SkScalar x, SkScalar y, SkScalar z)
+{
+ fRec->fMatrix.preTranslate(x, y, z);
+}
+
+void Sk3DView::rotateX(SkScalar deg)
+{
+ fRec->fMatrix.preRotateX(deg);
+}
+
+void Sk3DView::rotateY(SkScalar deg)
+{
+ fRec->fMatrix.preRotateY(deg);
+}
+
+void Sk3DView::rotateZ(SkScalar deg)
+{
+ fRec->fMatrix.preRotateZ(deg);
+}
+
+SkScalar Sk3DView::dotWithNormal(SkScalar x, SkScalar y, SkScalar z) const
+{
+ SkPatch3D patch;
+ patch.transform(fRec->fMatrix);
+ return patch.dotWith(x, y, z);
+}
+
+void Sk3DView::getMatrix(SkMatrix* matrix) const
+{
+ if (matrix != NULL)
+ {
+ SkPatch3D patch;
+ patch.transform(fRec->fMatrix);
+ fCamera.patchToMatrix(patch, matrix);
+ }
+}
+
+#include "SkCanvas.h"
+
+void Sk3DView::applyToCanvas(SkCanvas* canvas) const
+{
+ SkMatrix matrix;
+
+ this->getMatrix(&matrix);
+ canvas->concat(matrix);
+}
+
diff --git a/src/utils/SkColorMatrix.cpp b/src/utils/SkColorMatrix.cpp
new file mode 100644
index 0000000..0a20990
--- /dev/null
+++ b/src/utils/SkColorMatrix.cpp
@@ -0,0 +1,165 @@
+#include "SkColorMatrix.h"
+
+#define kRScale 0
+#define kGScale 6
+#define kBScale 12
+#define kAScale 18
+
+void SkColorMatrix::setIdentity()
+{
+ memset(fMat, 0, sizeof(fMat));
+ fMat[kRScale] = fMat[kGScale] = fMat[kBScale] = fMat[kAScale] = SK_Scalar1;
+}
+
+void SkColorMatrix::setScale(SkScalar rScale, SkScalar gScale, SkScalar bScale,
+ SkScalar aScale)
+{
+ memset(fMat, 0, sizeof(fMat));
+ fMat[kRScale] = rScale;
+ fMat[kGScale] = gScale;
+ fMat[kBScale] = bScale;
+ fMat[kAScale] = aScale;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SkColorMatrix::setRotate(Axis axis, SkScalar degrees)
+{
+ SkScalar S, C;
+
+ S = SkScalarSinCos(SkDegreesToRadians(degrees), &C);
+
+ this->setSinCos(axis, S, C);
+}
+
+void SkColorMatrix::setSinCos(Axis axis, SkScalar sine, SkScalar cosine)
+{
+ SkASSERT((unsigned)axis < 3);
+
+ static const uint8_t gRotateIndex[] = {
+ 6, 7, 11, 12,
+ 0, 2, 15, 17,
+ 0, 1, 5, 6,
+ };
+ const uint8_t* index = gRotateIndex + axis * 4;
+
+ this->setIdentity();
+ fMat[index[0]] = cosine;
+ fMat[index[1]] = sine;
+ fMat[index[2]] = -sine;
+ fMat[index[3]] = cosine;
+}
+
+void SkColorMatrix::preRotate(Axis axis, SkScalar degrees)
+{
+ SkColorMatrix tmp;
+ tmp.setRotate(axis, degrees);
+ this->preConcat(tmp);
+}
+
+void SkColorMatrix::postRotate(Axis axis, SkScalar degrees)
+{
+ SkColorMatrix tmp;
+ tmp.setRotate(axis, degrees);
+ this->postConcat(tmp);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SkColorMatrix::setConcat(const SkColorMatrix& matA,
+ const SkColorMatrix& matB)
+{
+ SkScalar tmp[20];
+ SkScalar* result = fMat;
+
+ if (&matA == this || &matB == this)
+ result = tmp;
+
+ const SkScalar* a = matA.fMat;
+ const SkScalar* b = matB.fMat;
+
+ int index = 0;
+ for (int j = 0; j < 20; j += 5)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ result[index++] = SkScalarMul(a[j + 0], b[i + 0]) +
+ SkScalarMul(a[j + 1], b[i + 5]) +
+ SkScalarMul(a[j + 2], b[i + 10]) +
+ SkScalarMul(a[j + 3], b[i + 15]);
+ }
+ result[index++] = SkScalarMul(a[j + 0], b[4]) +
+ SkScalarMul(a[j + 1], b[9]) +
+ SkScalarMul(a[j + 2], b[14]) +
+ SkScalarMul(a[j + 3], b[19]) +
+ a[j + 4];
+ }
+
+ if (fMat != result)
+ memcpy(fMat, result, sizeof(fMat));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void setrow(SkScalar row[], SkScalar r, SkScalar g, SkScalar b)
+{
+ row[0] = r;
+ row[1] = g;
+ row[2] = b;
+}
+
+static const SkScalar kHueR = SkFloatToScalar(0.213f);
+static const SkScalar kHueG = SkFloatToScalar(0.715f);
+static const SkScalar kHueB = SkFloatToScalar(0.072f);
+
+void SkColorMatrix::setSaturation(SkScalar sat)
+{
+ memset(fMat, 0, sizeof(fMat));
+
+ const SkScalar R = SkScalarMul(kHueR, SK_Scalar1 - sat);
+ const SkScalar G = SkScalarMul(kHueG, SK_Scalar1 - sat);
+ const SkScalar B = SkScalarMul(kHueB, SK_Scalar1 - sat);
+
+ setrow(fMat + 0, R + sat, G, B);
+ setrow(fMat + 5, R, G + sat, B);
+ setrow(fMat + 10, R, G, B + sat);
+ fMat[18] = SK_Scalar1;
+}
+
+static const SkScalar kR2Y = SkFloatToScalar(0.299f);
+static const SkScalar kG2Y = SkFloatToScalar(0.587f);
+static const SkScalar kB2Y = SkFloatToScalar(0.114f);
+
+static const SkScalar kR2U = SkFloatToScalar(-0.16874f);
+static const SkScalar kG2U = SkFloatToScalar(-0.33126f);
+static const SkScalar kB2U = SkFloatToScalar(0.5f);
+
+static const SkScalar kR2V = SkFloatToScalar(0.5f);
+static const SkScalar kG2V = SkFloatToScalar(-0.41869f);
+static const SkScalar kB2V = SkFloatToScalar(-0.08131f);
+
+void SkColorMatrix::setRGB2YUV()
+{
+ memset(fMat, 0, sizeof(fMat));
+
+ setrow(fMat + 0, kR2Y, kG2Y, kB2Y);
+ setrow(fMat + 5, kR2U, kG2U, kB2U);
+ setrow(fMat + 10, kR2V, kG2V, kB2V);
+ fMat[18] = SK_Scalar1;
+}
+
+static const SkScalar kV2R = SkFloatToScalar(1.402f);
+static const SkScalar kU2G = SkFloatToScalar(-0.34414f);
+static const SkScalar kV2G = SkFloatToScalar(-0.71414f);
+static const SkScalar kU2B = SkFloatToScalar(1.772f);
+
+void SkColorMatrix::setYUV2RGB()
+{
+ memset(fMat, 0, sizeof(fMat));
+
+ setrow(fMat + 0, SK_Scalar1, 0, kV2R);
+ setrow(fMat + 5, SK_Scalar1, kU2G, kV2G);
+ setrow(fMat + 10, SK_Scalar1, kU2B, 0);
+ fMat[18] = SK_Scalar1;
+}
+
diff --git a/src/utils/SkCullPoints.cpp b/src/utils/SkCullPoints.cpp
new file mode 100644
index 0000000..23d00b6
--- /dev/null
+++ b/src/utils/SkCullPoints.cpp
@@ -0,0 +1,168 @@
+/* libs/graphics/effects/SkCullPoints.cpp
+**
+** Copyright 2006, 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 "SkCullPoints.h"
+#include "Sk64.h"
+
+static bool cross_product_is_neg(const SkIPoint& v, int dx, int dy)
+{
+#if 0
+ return v.fX * dy - v.fY * dx < 0;
+#else
+ Sk64 tmp0, tmp1;
+
+ tmp0.setMul(v.fX, dy);
+ tmp1.setMul(dx, v.fY);
+ tmp0.sub(tmp1);
+ return tmp0.isNeg();
+#endif
+}
+
+bool SkCullPoints::sect_test(int x0, int y0, int x1, int y1) const
+{
+ const SkIRect& r = fR;
+
+ if (x0 < r.fLeft && x1 < r.fLeft ||
+ x0 > r.fRight && x1 > r.fRight ||
+ y0 < r.fTop && y1 < r.fTop ||
+ y0 > r.fBottom && y1 > r.fBottom)
+ return false;
+
+ // since the crossprod test is a little expensive, check for easy-in cases first
+ if (r.contains(x0, y0) || r.contains(x1, y1))
+ return true;
+
+ // At this point we're not sure, so we do a crossprod test
+ SkIPoint vec;
+ const SkIPoint* rAsQuad = fAsQuad;
+
+ vec.set(x1 - x0, y1 - y0);
+ bool isNeg = cross_product_is_neg(vec, x0 - rAsQuad[0].fX, y0 - rAsQuad[0].fY);
+ for (int i = 1; i < 4; i++) {
+ if (cross_product_is_neg(vec, x0 - rAsQuad[i].fX, y0 - rAsQuad[i].fY) != isNeg)
+ {
+ return true;
+ }
+ }
+ return false; // we didn't intersect
+}
+
+static void toQuad(const SkIRect& r, SkIPoint quad[4])
+{
+ SkASSERT(quad);
+
+ quad[0].set(r.fLeft, r.fTop);
+ quad[1].set(r.fRight, r.fTop);
+ quad[2].set(r.fRight, r.fBottom);
+ quad[3].set(r.fLeft, r.fBottom);
+}
+
+SkCullPoints::SkCullPoints()
+{
+ SkIRect r;
+ r.setEmpty();
+ this->reset(r);
+}
+
+SkCullPoints::SkCullPoints(const SkIRect& r)
+{
+ this->reset(r);
+}
+
+void SkCullPoints::reset(const SkIRect& r)
+{
+ fR = r;
+ toQuad(fR, fAsQuad);
+ fPrevPt.set(0, 0);
+ fPrevResult = kNo_Result;
+}
+
+void SkCullPoints::moveTo(int x, int y)
+{
+ fPrevPt.set(x, y);
+ fPrevResult = kNo_Result; // so we trigger a movetolineto later
+}
+
+SkCullPoints::LineToResult SkCullPoints::lineTo(int x, int y, SkIPoint line[])
+{
+ SkASSERT(line != NULL);
+
+ LineToResult result = kNo_Result;
+ int x0 = fPrevPt.fX;
+ int y0 = fPrevPt.fY;
+
+ // need to upgrade sect_test to chop the result
+ // and to correctly return kLineTo_Result when the result is connected
+ // to the previous call-out
+ if (this->sect_test(x0, y0, x, y))
+ {
+ line[0].set(x0, y0);
+ line[1].set(x, y);
+
+ if (fPrevResult != kNo_Result && fPrevPt.equals(x0, y0))
+ result = kLineTo_Result;
+ else
+ result = kMoveToLineTo_Result;
+ }
+
+ fPrevPt.set(x, y);
+ fPrevResult = result;
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "SkPath.h"
+
+SkCullPointsPath::SkCullPointsPath()
+ : fCP(), fPath(NULL)
+{
+}
+
+SkCullPointsPath::SkCullPointsPath(const SkIRect& r, SkPath* dst)
+ : fCP(r), fPath(dst)
+{
+}
+
+void SkCullPointsPath::reset(const SkIRect& r, SkPath* dst)
+{
+ fCP.reset(r);
+ fPath = dst;
+}
+
+void SkCullPointsPath::moveTo(int x, int y)
+{
+ fCP.moveTo(x, y);
+}
+
+void SkCullPointsPath::lineTo(int x, int y)
+{
+ SkIPoint pts[2];
+
+ switch (fCP.lineTo(x, y, pts)) {
+ case SkCullPoints::kMoveToLineTo_Result:
+ fPath->moveTo(SkIntToScalar(pts[0].fX), SkIntToScalar(pts[0].fY));
+ // fall through to the lineto case
+ case SkCullPoints::kLineTo_Result:
+ fPath->lineTo(SkIntToScalar(pts[1].fX), SkIntToScalar(pts[1].fY));
+ break;
+ default:
+ break;
+ }
+}
+
diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp
new file mode 100644
index 0000000..fb203ef
--- /dev/null
+++ b/src/utils/SkDumpCanvas.cpp
@@ -0,0 +1,398 @@
+#include "SkDumpCanvas.h"
+#include "SkPixelRef.h"
+#include "SkString.h"
+#include <stdarg.h>
+
+// needed just to know that these are all subclassed from SkFlattenable
+#include "SkShader.h"
+#include "SkPathEffect.h"
+#include "SkXfermode.h"
+#include "SkColorFilter.h"
+#include "SkPathEffect.h"
+#include "SkMaskFilter.h"
+
+static void toString(const SkRect& r, SkString* str) {
+ str->printf("[(%g %g) %g %g]",
+ SkScalarToFloat(r.fLeft), SkScalarToFloat(r.fTop),
+ SkScalarToFloat(r.width()), SkScalarToFloat(r.height()));
+}
+
+static void toString(const SkIRect& r, SkString* str) {
+ str->printf("[(%d %d) %d %d]", r.fLeft, r.fTop, r.width(), r.height());
+}
+
+static void toString(const SkPath& path, SkString* str) {
+ if (path.isEmpty()) {
+ str->set("path:empty");
+ } else {
+ SkRect bounds;
+ path.computeBounds(&bounds, SkPath::kFast_BoundsType);
+ toString(bounds, str);
+ str->append("]");
+ str->prepend("path:[");
+ }
+}
+
+static const char* toString(SkRegion::Op op) {
+ static const char* gOpNames[] = {
+ "DIFF", "SECT", "UNION", "XOR", "RDIFF", "REPLACE"
+ };
+ return gOpNames[op];
+}
+
+static void toString(const SkRegion& rgn, SkString* str) {
+ toString(rgn.getBounds(), str);
+ str->prepend("Region:[");
+ str->append("]");
+ if (rgn.isComplex()) {
+ str->append(".complex");
+ }
+}
+
+static const char* toString(SkCanvas::VertexMode vm) {
+ static const char* gVMNames[] = {
+ "TRIANGLES", "STRIP", "FAN"
+ };
+ return gVMNames[vm];
+}
+
+static const char* toString(SkCanvas::PointMode pm) {
+ static const char* gPMNames[] = {
+ "POINTS", "LINES", "POLYGON"
+ };
+ return gPMNames[pm];
+}
+
+static const char* toString(SkBitmap::Config config) {
+ static const char* gConfigNames[] = {
+ "NONE", "A1", "A8", "INDEX8", "565", "4444", "8888", "RLE"
+ };
+ return gConfigNames[config];
+}
+
+static void toString(const SkBitmap& bm, SkString* str) {
+ str->printf("bitmap:[%d %d] %s", bm.width(), bm.height(),
+ toString(bm.config()));
+
+ SkPixelRef* pr = bm.pixelRef();
+ if (NULL == pr) {
+ // show null or the explicit pixel address (rare)
+ str->appendf(" pixels:%p", bm.getPixels());
+ } else {
+ const char* uri = pr->getURI();
+ if (uri) {
+ str->appendf(" uri:\"%s\"", uri);
+ } else {
+ str->appendf(" pixelref:%p", pr);
+ }
+ }
+}
+
+static void toString(const void* text, size_t len, SkPaint::TextEncoding enc,
+ SkString* str) {
+ switch (enc) {
+ case SkPaint::kUTF8_TextEncoding:
+ str->printf("\"%.*s\"%s", SkMax32(len, 32), text,
+ len > 32 ? "..." : "");
+ break;
+ case SkPaint::kUTF16_TextEncoding:
+ str->printf("\"%.*S\"%s", SkMax32(len, 32), text,
+ len > 64 ? "..." : "");
+ break;
+ case SkPaint::kGlyphID_TextEncoding:
+ str->set("<glyphs>");
+ break;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkDumpCanvas::SkDumpCanvas(Dumper* dumper) {
+ dumper->safeRef();
+ fDumper = dumper;
+
+ static const int WIDE_OPEN = 16384;
+ SkBitmap emptyBitmap;
+
+ emptyBitmap.setConfig(SkBitmap::kNo_Config, WIDE_OPEN, WIDE_OPEN);
+ this->setBitmapDevice(emptyBitmap);
+}
+
+SkDumpCanvas::~SkDumpCanvas() {
+ fDumper->safeUnref();
+}
+
+void SkDumpCanvas::dump(Verb verb, const SkPaint* paint,
+ const char format[], ...) {
+ static const size_t BUFFER_SIZE = 1024;
+
+ char buffer[BUFFER_SIZE];
+ va_list args;
+ va_start(args, format);
+ vsnprintf(buffer, BUFFER_SIZE, format, args);
+ va_end(args);
+
+ if (fDumper) {
+ fDumper->dump(this, verb, buffer, paint);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+int SkDumpCanvas::save(SaveFlags flags) {
+ this->dump(kSave_Verb, NULL, "save(0x%X)", flags);
+ return this->INHERITED::save(flags);
+}
+
+int SkDumpCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) {
+ this->dump(kSave_Verb, paint, "saveLayer(0x%X)", flags);
+ return this->INHERITED::saveLayer(bounds, paint, flags);
+}
+
+void SkDumpCanvas::restore() {
+ this->INHERITED::restore();
+ this->dump(kRestore_Verb, NULL, "restore");
+}
+
+bool SkDumpCanvas::translate(SkScalar dx, SkScalar dy) {
+ this->dump(kMatrix_Verb, NULL, "translate(%g %g)",
+ SkScalarToFloat(dx), SkScalarToFloat(dy));
+ return this->INHERITED::translate(dx, dy);
+}
+
+bool SkDumpCanvas::scale(SkScalar sx, SkScalar sy) {
+ this->dump(kMatrix_Verb, NULL, "scale(%g %g)",
+ SkScalarToFloat(sx), SkScalarToFloat(sy));
+ return this->INHERITED::scale(sx, sy);
+}
+
+bool SkDumpCanvas::rotate(SkScalar degrees) {
+ this->dump(kMatrix_Verb, NULL, "rotate(%g)", SkScalarToFloat(degrees));
+ return this->INHERITED::rotate(degrees);
+}
+
+bool SkDumpCanvas::skew(SkScalar sx, SkScalar sy) {
+ this->dump(kMatrix_Verb, NULL, "skew(%g %g)",
+ SkScalarToFloat(sx), SkScalarToFloat(sy));
+ return this->INHERITED::skew(sx, sy);
+}
+
+bool SkDumpCanvas::concat(const SkMatrix& matrix) {
+ SkString str;
+ matrix.toDumpString(&str);
+ this->dump(kMatrix_Verb, NULL, "concat(%s)", str.c_str());
+ return this->INHERITED::concat(matrix);
+}
+
+void SkDumpCanvas::setMatrix(const SkMatrix& matrix) {
+ SkString str;
+ matrix.toDumpString(&str);
+ this->dump(kMatrix_Verb, NULL, "setMatrix(%s)", str.c_str());
+ this->INHERITED::setMatrix(matrix);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool SkDumpCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
+ SkString str;
+ toString(rect, &str);
+ this->dump(kClip_Verb, NULL, "clipRect(%s %s)", str.c_str(), toString(op));
+ return this->INHERITED::clipRect(rect, op);
+}
+
+bool SkDumpCanvas::clipPath(const SkPath& path, SkRegion::Op op) {
+ SkString str;
+ toString(path, &str);
+ this->dump(kClip_Verb, NULL, "clipPath(%s %s)", str.c_str(), toString(op));
+ return this->INHERITED::clipPath(path, op);
+}
+
+bool SkDumpCanvas::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
+ SkString str;
+ toString(deviceRgn, &str);
+ this->dump(kClip_Verb, NULL, "clipRegion(%s %s)", str.c_str(),
+ toString(op));
+ return this->INHERITED::clipRegion(deviceRgn, op);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SkDumpCanvas::drawPaint(const SkPaint& paint) {
+ this->dump(kDrawPaint_Verb, &paint, "drawPaint()");
+}
+
+void SkDumpCanvas::drawPoints(PointMode mode, size_t count,
+ const SkPoint pts[], const SkPaint& paint) {
+ this->dump(kDrawPoints_Verb, &paint, "drawPoints(%s, %d)", toString(mode),
+ count);
+}
+
+void SkDumpCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
+ SkString str;
+ toString(rect, &str);
+ this->dump(kDrawRect_Verb, &paint, "drawRect(%s)", str.c_str());
+}
+
+void SkDumpCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
+ SkString str;
+ toString(path, &str);
+ this->dump(kDrawPath_Verb, &paint, "drawPath(%s)", str.c_str());
+}
+
+void SkDumpCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
+ const SkPaint* paint) {
+ SkString str;
+ toString(bitmap, &str);
+ this->dump(kDrawBitmap_Verb, paint, "drawBitmap(%s (%g %g))", str.c_str(),
+ SkScalarToFloat(x), SkScalarToFloat(y));
+}
+
+void SkDumpCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+ const SkRect& dst, const SkPaint* paint) {
+ SkString bs, rs;
+ toString(bitmap, &bs);
+ toString(dst, &rs);
+ // show the src-rect only if its not everything
+ if (src && (src->fLeft > 0 || src->fTop > 0 ||
+ src->fRight < bitmap.width() ||
+ src->fBottom < bitmap.height())) {
+ SkString ss;
+ toString(*src, &ss);
+ rs.prependf("%s ", ss.c_str());
+ }
+
+ this->dump(kDrawBitmap_Verb, paint, "drawBitmapRect(%s %s)",
+ bs.c_str(), rs.c_str());
+}
+
+void SkDumpCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+ const SkPaint* paint) {
+ SkString bs, ms;
+ toString(bitmap, &bs);
+ m.toDumpString(&ms);
+ this->dump(kDrawBitmap_Verb, paint, "drawBitmapMatrix(%s %s)",
+ bs.c_str(), ms.c_str());
+}
+
+void SkDumpCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
+ const SkPaint* paint) {
+ SkString str;
+ toString(bitmap, &str);
+ this->dump(kDrawBitmap_Verb, paint, "drawSprite(%s (%d %d))", str.c_str(),
+ x, y);
+}
+
+void SkDumpCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint) {
+ SkString str;
+ toString(text, byteLength, paint.getTextEncoding(), &str);
+ this->dump(kDrawText_Verb, &paint, "drawText(%s [%d] (%g %g))", str.c_str(),
+ byteLength, SkScalarToFloat(x), SkScalarToFloat(y));
+}
+
+void SkDumpCanvas::drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint) {
+ SkString str;
+ toString(text, byteLength, paint.getTextEncoding(), &str);
+ this->dump(kDrawText_Verb, &paint, "drawPosText(%s [%d] (%g %g ...))",
+ str.c_str(), byteLength, SkScalarToFloat(pos[0].fX),
+ SkScalarToFloat(pos[0].fY));
+}
+
+void SkDumpCanvas::drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint) {
+ SkString str;
+ toString(text, byteLength, paint.getTextEncoding(), &str);
+ this->dump(kDrawText_Verb, &paint, "drawPosTextH(%s [%d] (%g %g ...))",
+ str.c_str(), byteLength, SkScalarToFloat(xpos[0]),
+ SkScalarToFloat(constY));
+}
+
+void SkDumpCanvas::drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) {
+ SkString str;
+ toString(text, byteLength, paint.getTextEncoding(), &str);
+ this->dump(kDrawText_Verb, &paint, "drawTextOnPath(%s [%d])",
+ str.c_str(), byteLength);
+}
+
+void SkDumpCanvas::drawPicture(SkPicture& picture) {
+ this->dump(kDrawPicture_Verb, NULL, "drawPicture(%p)", &picture);
+}
+
+void SkDumpCanvas::drawVertices(VertexMode vmode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) {
+ this->dump(kDrawVertices_Verb, &paint, "drawVertices(%s [%d] [%g %g ...]",
+ toString(vmode), vertexCount, SkScalarToFloat(vertices[0].fX),
+ SkScalarToFloat(vertices[0].fY));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+SkFormatDumper::SkFormatDumper(void (*proc)(const char*, void*), void* refcon) {
+ fProc = proc;
+ fRefcon = refcon;
+}
+
+static void appendPtr(SkString* str, const void* ptr, const char name[]) {
+ if (ptr) {
+ str->appendf(" %s:%p", name, ptr);
+ }
+}
+
+static void appendFlattenable(SkString* str, const SkFlattenable* ptr,
+ const char name[]) {
+ if (ptr) {
+ SkString info;
+ if (ptr->toDumpString(&info)) {
+ str->appendf(" %s", info.c_str());
+ } else {
+ str->appendf(" %s:%p", name, ptr);
+ }
+ }
+}
+
+void SkFormatDumper::dump(SkDumpCanvas* canvas, SkDumpCanvas::Verb verb,
+ const char str[], const SkPaint* p) {
+ SkString msg, tab;
+ const int level = canvas->getSaveCount() - 1;
+ SkASSERT(level >= 0);
+ for (int i = 0; i < level; i++) {
+ tab.append("\t");
+ }
+ msg.printf("%s%s", tab.c_str(), str);
+
+ if (p) {
+ msg.appendf(" color:0x%08X flags:%X", p->getColor(), p->getFlags());
+ appendFlattenable(&msg, p->getShader(), "shader");
+ appendFlattenable(&msg, p->getXfermode(), "xfermode");
+ appendFlattenable(&msg, p->getPathEffect(), "pathEffect");
+ appendFlattenable(&msg, p->getMaskFilter(), "maskFilter");
+ appendFlattenable(&msg, p->getPathEffect(), "pathEffect");
+ appendFlattenable(&msg, p->getColorFilter(), "filter");
+
+ if (SkDumpCanvas::kDrawText_Verb == verb) {
+ msg.appendf(" textSize:%g", SkScalarToFloat(p->getTextSize()));
+ appendPtr(&msg, p->getTypeface(), "typeface");
+ }
+ }
+
+ fProc(msg.c_str(), fRefcon);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void dumpToDebugf(const char text[], void*) {
+ SkDebugf("%s\n", text);
+}
+
+SkDebugfDumper::SkDebugfDumper() : INHERITED(dumpToDebugf, NULL) {}
+
+
diff --git a/src/utils/SkInterpolator.cpp b/src/utils/SkInterpolator.cpp
new file mode 100644
index 0000000..e4ecd95
--- /dev/null
+++ b/src/utils/SkInterpolator.cpp
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2006-2008 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 "SkInterpolator.h"
+#include "SkMath.h"
+#include "SkTSearch.h"
+
+SkInterpolatorBase::SkInterpolatorBase() {
+ fStorage = NULL;
+ fTimes = NULL;
+ SkDEBUGCODE(fTimesArray = NULL;)
+}
+
+SkInterpolatorBase::~SkInterpolatorBase() {
+ if (fStorage) {
+ sk_free(fStorage);
+ }
+}
+
+void SkInterpolatorBase::reset(int elemCount, int frameCount) {
+ fFlags = 0;
+ fElemCount = SkToU8(elemCount);
+ fFrameCount = SkToS16(frameCount);
+ fRepeat = SK_Scalar1;
+ if (fStorage) {
+ sk_free(fStorage);
+ fStorage = NULL;
+ fTimes = NULL;
+ SkDEBUGCODE(fTimesArray = NULL);
+ }
+}
+
+/* Each value[] run is formated as:
+ <time (in msec)>
+ <blend>
+ <data[fElemCount]>
+
+ Totaling fElemCount+2 entries per keyframe
+*/
+
+bool SkInterpolatorBase::getDuration(SkMSec* startTime, SkMSec* endTime) const {
+ if (fFrameCount == 0) {
+ return false;
+ }
+
+ if (startTime) {
+ *startTime = fTimes[0].fTime;
+ }
+ if (endTime) {
+ *endTime = fTimes[fFrameCount - 1].fTime;
+ }
+ return true;
+}
+
+SkScalar SkInterpolatorBase::ComputeRelativeT(SkMSec time, SkMSec prevTime,
+ SkMSec nextTime, const SkScalar blend[4]) {
+ SkASSERT(time > prevTime && time < nextTime);
+
+ SkScalar t = SkScalarDiv((SkScalar)(time - prevTime),
+ (SkScalar)(nextTime - prevTime));
+ return blend ?
+ SkUnitCubicInterp(t, blend[0], blend[1], blend[2], blend[3]) : t;
+}
+
+SkInterpolatorBase::Result SkInterpolatorBase::timeToT(SkMSec time, SkScalar* T,
+ int* indexPtr, SkBool* exactPtr) const {
+ SkASSERT(fFrameCount > 0);
+ Result result = kNormal_Result;
+ if (fRepeat != SK_Scalar1) {
+ SkMSec startTime, endTime;
+ this->getDuration(&startTime, &endTime);
+ SkMSec totalTime = endTime - startTime;
+ SkMSec offsetTime = time - startTime;
+ endTime = SkScalarMulFloor(fRepeat, totalTime);
+ if (offsetTime >= endTime) {
+ SkScalar fraction = SkScalarFraction(fRepeat);
+ offsetTime = fraction == 0 && fRepeat > 0 ? totalTime :
+ SkScalarMulFloor(fraction, totalTime);
+ result = kFreezeEnd_Result;
+ } else {
+ int mirror = fFlags & kMirror;
+ offsetTime = offsetTime % (totalTime << mirror);
+ if (offsetTime > totalTime) { // can only be true if fMirror is true
+ offsetTime = (totalTime << 1) - offsetTime;
+ }
+ }
+ time = offsetTime + startTime;
+ }
+
+ int index = SkTSearch<SkMSec>(&fTimes[0].fTime, fFrameCount, time,
+ sizeof(SkTimeCode));
+
+ bool exact = true;
+
+ if (index < 0) {
+ index = ~index;
+ if (index == 0) {
+ result = kFreezeStart_Result;
+ } else if (index == fFrameCount) {
+ if (fFlags & kReset) {
+ index = 0;
+ } else {
+ index -= 1;
+ }
+ result = kFreezeEnd_Result;
+ } else {
+ exact = false;
+ }
+ }
+ SkASSERT(index < fFrameCount);
+ const SkTimeCode* nextTime = &fTimes[index];
+ SkMSec nextT = nextTime[0].fTime;
+ if (exact) {
+ *T = 0;
+ } else {
+ SkMSec prevT = nextTime[-1].fTime;
+ *T = ComputeRelativeT(time, prevT, nextT, nextTime[-1].fBlend);
+ }
+ *indexPtr = index;
+ *exactPtr = exact;
+ return result;
+}
+
+
+SkInterpolator::SkInterpolator() {
+ INHERITED::reset(0, 0);
+ fValues = NULL;
+ SkDEBUGCODE(fScalarsArray = NULL;)
+}
+
+SkInterpolator::SkInterpolator(int elemCount, int frameCount) {
+ SkASSERT(elemCount > 0);
+ this->reset(elemCount, frameCount);
+}
+
+void SkInterpolator::reset(int elemCount, int frameCount) {
+ INHERITED::reset(elemCount, frameCount);
+ fStorage = sk_malloc_throw((sizeof(SkScalar) * elemCount +
+ sizeof(SkTimeCode)) * frameCount);
+ fTimes = (SkTimeCode*) fStorage;
+ fValues = (SkScalar*) ((char*) fStorage + sizeof(SkTimeCode) * frameCount);
+#ifdef SK_DEBUG
+ fTimesArray = (SkTimeCode(*)[10]) fTimes;
+ fScalarsArray = (SkScalar(*)[10]) fValues;
+#endif
+}
+
+#define SK_Fixed1Third (SK_Fixed1/3)
+#define SK_Fixed2Third (SK_Fixed1*2/3)
+
+static const SkScalar gIdentityBlend[4] = {
+#ifdef SK_SCALAR_IS_FLOAT
+ 0.33333333f, 0.33333333f, 0.66666667f, 0.66666667f
+#else
+ SK_Fixed1Third, SK_Fixed1Third, SK_Fixed2Third, SK_Fixed2Third
+#endif
+};
+
+bool SkInterpolator::setKeyFrame(int index, SkMSec time,
+ const SkScalar values[], const SkScalar blend[4]) {
+ SkASSERT(values != NULL);
+
+ if (blend == NULL) {
+ blend = gIdentityBlend;
+ }
+
+ bool success = ~index == SkTSearch<SkMSec>(&fTimes->fTime, index, time,
+ sizeof(SkTimeCode));
+ SkASSERT(success);
+ if (success) {
+ SkTimeCode* timeCode = &fTimes[index];
+ timeCode->fTime = time;
+ memcpy(timeCode->fBlend, blend, sizeof(timeCode->fBlend));
+ SkScalar* dst = &fValues[fElemCount * index];
+ memcpy(dst, values, fElemCount * sizeof(SkScalar));
+ }
+ return success;
+}
+
+SkInterpolator::Result SkInterpolator::timeToValues(SkMSec time,
+ SkScalar values[]) const {
+ SkScalar T;
+ int index;
+ SkBool exact;
+ Result result = timeToT(time, &T, &index, &exact);
+ if (values) {
+ const SkScalar* nextSrc = &fValues[index * fElemCount];
+
+ if (exact) {
+ memcpy(values, nextSrc, fElemCount * sizeof(SkScalar));
+ } else {
+ SkASSERT(index > 0);
+
+ const SkScalar* prevSrc = nextSrc - fElemCount;
+
+ for (int i = fElemCount - 1; i >= 0; --i) {
+ values[i] = SkScalarInterp(prevSrc[i], nextSrc[i], T);
+ }
+ }
+ }
+ return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef int Dot14;
+#define Dot14_ONE (1 << 14)
+#define Dot14_HALF (1 << 13)
+
+#define Dot14ToFloat(x) ((x) / 16384.f)
+
+static inline Dot14 Dot14Mul(Dot14 a, Dot14 b) {
+ return (a * b + Dot14_HALF) >> 14;
+}
+
+static inline Dot14 eval_cubic(Dot14 t, Dot14 A, Dot14 B, Dot14 C) {
+ return Dot14Mul(Dot14Mul(Dot14Mul(C, t) + B, t) + A, t);
+}
+
+static inline Dot14 pin_and_convert(SkScalar x) {
+ if (x <= 0) {
+ return 0;
+ }
+ if (x >= SK_Scalar1) {
+ return Dot14_ONE;
+ }
+ return SkScalarToFixed(x) >> 2;
+}
+
+SkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by,
+ SkScalar cx, SkScalar cy) {
+ // pin to the unit-square, and convert to 2.14
+ Dot14 x = pin_and_convert(value);
+
+ if (x == 0) return 0;
+ if (x == Dot14_ONE) return SK_Scalar1;
+
+ Dot14 b = pin_and_convert(bx);
+ Dot14 c = pin_and_convert(cx);
+
+ // Now compute our coefficients from the control points
+ // t -> 3b
+ // t^2 -> 3c - 6b
+ // t^3 -> 3b - 3c + 1
+ Dot14 A = 3*b;
+ Dot14 B = 3*(c - 2*b);
+ Dot14 C = 3*(b - c) + Dot14_ONE;
+
+ // Now search for a t value given x
+ Dot14 t = Dot14_HALF;
+ Dot14 dt = Dot14_HALF;
+ for (int i = 0; i < 13; i++) {
+ dt >>= 1;
+ Dot14 guess = eval_cubic(t, A, B, C);
+ if (x < guess) {
+ t -= dt;
+ } else {
+ t += dt;
+ }
+ }
+
+ // Now we have t, so compute the coeff for Y and evaluate
+ b = pin_and_convert(by);
+ c = pin_and_convert(cy);
+ A = 3*b;
+ B = 3*(c - 2*b);
+ C = 3*(b - c) + Dot14_ONE;
+ return SkFixedToScalar(eval_cubic(t, A, B, C) << 2);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef SK_DEBUG
+
+#ifdef SK_SUPPORT_UNITTEST
+ static SkScalar* iset(SkScalar array[3], int a, int b, int c) {
+ array[0] = SkIntToScalar(a);
+ array[1] = SkIntToScalar(b);
+ array[2] = SkIntToScalar(c);
+ return array;
+ }
+#endif
+
+void SkInterpolator::UnitTest() {
+#ifdef SK_SUPPORT_UNITTEST
+ SkInterpolator inter(3, 2);
+ SkScalar v1[3], v2[3], v[3], vv[3];
+ Result result;
+
+ inter.setKeyFrame(0, 100, iset(v1, 10, 20, 30), 0);
+ inter.setKeyFrame(1, 200, iset(v2, 110, 220, 330));
+
+ result = inter.timeToValues(0, v);
+ SkASSERT(result == kFreezeStart_Result);
+ SkASSERT(memcmp(v, v1, sizeof(v)) == 0);
+
+ result = inter.timeToValues(99, v);
+ SkASSERT(result == kFreezeStart_Result);
+ SkASSERT(memcmp(v, v1, sizeof(v)) == 0);
+
+ result = inter.timeToValues(100, v);
+ SkASSERT(result == kNormal_Result);
+ SkASSERT(memcmp(v, v1, sizeof(v)) == 0);
+
+ result = inter.timeToValues(200, v);
+ SkASSERT(result == kNormal_Result);
+ SkASSERT(memcmp(v, v2, sizeof(v)) == 0);
+
+ result = inter.timeToValues(201, v);
+ SkASSERT(result == kFreezeEnd_Result);
+ SkASSERT(memcmp(v, v2, sizeof(v)) == 0);
+
+ result = inter.timeToValues(150, v);
+ SkASSERT(result == kNormal_Result);
+ SkASSERT(memcmp(v, iset(vv, 60, 120, 180), sizeof(v)) == 0);
+
+ result = inter.timeToValues(125, v);
+ SkASSERT(result == kNormal_Result);
+ result = inter.timeToValues(175, v);
+ SkASSERT(result == kNormal_Result);
+#endif
+}
+
+#endif
+
diff --git a/src/utils/SkNinePatch.cpp b/src/utils/SkNinePatch.cpp
new file mode 100644
index 0000000..b8e11fb
--- /dev/null
+++ b/src/utils/SkNinePatch.cpp
@@ -0,0 +1,287 @@
+/*
+** Copyright 2006, 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 "SkNinePatch.h"
+#include "SkCanvas.h"
+#include "SkShader.h"
+
+static const uint16_t g3x3Indices[] = {
+ 0, 5, 1, 0, 4, 5,
+ 1, 6, 2, 1, 5, 6,
+ 2, 7, 3, 2, 6, 7,
+
+ 4, 9, 5, 4, 8, 9,
+ 5, 10, 6, 5, 9, 10,
+ 6, 11, 7, 6, 10, 11,
+
+ 8, 13, 9, 8, 12, 13,
+ 9, 14, 10, 9, 13, 14,
+ 10, 15, 11, 10, 14, 15
+};
+
+static int fillIndices(uint16_t indices[], int xCount, int yCount) {
+ uint16_t* startIndices = indices;
+
+ int n = 0;
+ for (int y = 0; y < yCount; y++) {
+ for (int x = 0; x < xCount; x++) {
+ *indices++ = n;
+ *indices++ = n + xCount + 2;
+ *indices++ = n + 1;
+
+ *indices++ = n;
+ *indices++ = n + xCount + 1;
+ *indices++ = n + xCount + 2;
+
+ n += 1;
+ }
+ n += 1;
+ }
+ return indices - startIndices;
+}
+
+static void fillRow(SkPoint verts[], SkPoint texs[],
+ const SkScalar vy, const SkScalar ty,
+ const SkRect& bounds, const int32_t xDivs[], int numXDivs,
+ const SkScalar stretchX, int width) {
+ SkScalar vx = bounds.fLeft;
+ verts->set(vx, vy); verts++;
+ texs->set(0, ty); texs++;
+ for (int x = 0; x < numXDivs; x++) {
+ SkScalar tx = SkIntToScalar(xDivs[x]);
+ if (x & 1) {
+ vx += stretchX;
+ } else {
+ vx += tx;
+ }
+ verts->set(vx, vy); verts++;
+ texs->set(tx, ty); texs++;
+ }
+ verts->set(bounds.fRight, vy); verts++;
+ texs->set(SkIntToScalar(width), ty); texs++;
+}
+
+struct Mesh {
+ const SkPoint* fVerts;
+ const SkPoint* fTexs;
+ const SkColor* fColors;
+ const uint16_t* fIndices;
+};
+
+void SkNinePatch::DrawMesh(SkCanvas* canvas, const SkRect& bounds,
+ const SkBitmap& bitmap,
+ const int32_t xDivs[], int numXDivs,
+ const int32_t yDivs[], int numYDivs,
+ const SkPaint* paint) {
+ if (bounds.isEmpty() || bitmap.width() == 0 || bitmap.height() == 0) {
+ return;
+ }
+
+ // should try a quick-reject test before calling lockPixels
+ SkAutoLockPixels alp(bitmap);
+ // after the lock, it is valid to check
+ if (!bitmap.readyToDraw()) {
+ return;
+ }
+
+ // check for degenerate divs (just an optimization, not required)
+ {
+ int i;
+ int zeros = 0;
+ for (i = 0; i < numYDivs && yDivs[i] == 0; i++) {
+ zeros += 1;
+ }
+ numYDivs -= zeros;
+ yDivs += zeros;
+ for (i = numYDivs - 1; i >= 0 && yDivs[i] == bitmap.height(); --i) {
+ numYDivs -= 1;
+ }
+ }
+
+ Mesh mesh;
+
+ const int numXStretch = (numXDivs + 1) >> 1;
+ const int numYStretch = (numYDivs + 1) >> 1;
+
+ if (numXStretch < 1 && numYStretch < 1) {
+ BITMAP_RECT:
+// SkDebugf("------ drawasamesh revert to bitmaprect\n");
+ canvas->drawBitmapRect(bitmap, NULL, bounds, paint);
+ return;
+ }
+
+ if (false) {
+ int i;
+ for (i = 0; i < numXDivs; i++) {
+ SkDebugf("--- xdivs[%d] %d\n", i, xDivs[i]);
+ }
+ for (i = 0; i < numYDivs; i++) {
+ SkDebugf("--- ydivs[%d] %d\n", i, yDivs[i]);
+ }
+ }
+
+ SkScalar stretchX = 0, stretchY = 0;
+
+ if (numXStretch > 0) {
+ int stretchSize = 0;
+ for (int i = 1; i < numXDivs; i += 2) {
+ stretchSize += xDivs[i] - xDivs[i-1];
+ }
+ int fixed = bitmap.width() - stretchSize;
+ stretchX = (bounds.width() - SkIntToScalar(fixed)) / numXStretch;
+ if (stretchX < 0) {
+ goto BITMAP_RECT;
+ }
+ }
+
+ if (numYStretch > 0) {
+ int stretchSize = 0;
+ for (int i = 1; i < numYDivs; i += 2) {
+ stretchSize += yDivs[i] - yDivs[i-1];
+ }
+ int fixed = bitmap.height() - stretchSize;
+ stretchY = (bounds.height() - SkIntToScalar(fixed)) / numYStretch;
+ if (stretchY < 0) {
+ goto BITMAP_RECT;
+ }
+ }
+
+#if 0
+ SkDebugf("---- drawasamesh [%d %d] -> [%g %g] <%d %d> (%g %g)\n",
+ bitmap.width(), bitmap.height(),
+ SkScalarToFloat(bounds.width()), SkScalarToFloat(bounds.height()),
+ numXDivs + 1, numYDivs + 1,
+ SkScalarToFloat(stretchX), SkScalarToFloat(stretchY));
+#endif
+
+ const int vCount = (numXDivs + 2) * (numYDivs + 2);
+ // number of celss * 2 (tris per cell) * 3 (verts per tri)
+ const int indexCount = (numXDivs + 1) * (numYDivs + 1) * 2 * 3;
+ // allocate 2 times, one for verts, one for texs, plus indices
+ SkAutoMalloc storage(vCount * sizeof(SkPoint) * 2 +
+ indexCount * sizeof(uint16_t));
+ SkPoint* verts = (SkPoint*)storage.get();
+ SkPoint* texs = verts + vCount;
+ uint16_t* indices = (uint16_t*)(texs + vCount);
+
+ mesh.fVerts = verts;
+ mesh.fTexs = texs;
+ mesh.fColors = NULL;
+ mesh.fIndices = NULL;
+
+ // we use <= for YDivs, since the prebuild indices work for 3x2 and 3x1 too
+ if (numXDivs == 2 && numYDivs <= 2) {
+ mesh.fIndices = g3x3Indices;
+ } else {
+ int n = fillIndices(indices, numXDivs + 1, numYDivs + 1);
+ SkASSERT(n == indexCount);
+ mesh.fIndices = indices;
+ }
+
+ SkScalar vy = bounds.fTop;
+ fillRow(verts, texs, vy, 0, bounds, xDivs, numXDivs,
+ stretchX, bitmap.width());
+ verts += numXDivs + 2;
+ texs += numXDivs + 2;
+ for (int y = 0; y < numYDivs; y++) {
+ const SkScalar ty = SkIntToScalar(yDivs[y]);
+ if (y & 1) {
+ vy += stretchY;
+ } else {
+ vy += ty;
+ }
+ fillRow(verts, texs, vy, ty, bounds, xDivs, numXDivs,
+ stretchX, bitmap.width());
+ verts += numXDivs + 2;
+ texs += numXDivs + 2;
+ }
+ fillRow(verts, texs, bounds.fBottom, SkIntToScalar(bitmap.height()),
+ bounds, xDivs, numXDivs, stretchX, bitmap.width());
+
+ SkShader* shader = SkShader::CreateBitmapShader(bitmap,
+ SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode);
+ SkPaint p;
+ if (paint) {
+ p = *paint;
+ }
+ p.setShader(shader)->unref();
+ canvas->drawVertices(SkCanvas::kTriangles_VertexMode, vCount,
+ mesh.fVerts, mesh.fTexs, mesh.fColors, NULL,
+ mesh.fIndices, indexCount, p);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void drawNineViaRects(SkCanvas* canvas, const SkRect& dst,
+ const SkBitmap& bitmap, const SkIRect& margins,
+ const SkPaint* paint) {
+ const int32_t srcX[4] = {
+ 0, margins.fLeft, bitmap.width() - margins.fRight, bitmap.width()
+ };
+ const int32_t srcY[4] = {
+ 0, margins.fTop, bitmap.height() - margins.fBottom, bitmap.height()
+ };
+ const SkScalar dstX[4] = {
+ dst.fLeft, dst.fLeft + SkIntToScalar(margins.fLeft),
+ dst.fRight - SkIntToScalar(margins.fRight), dst.fRight
+ };
+ const SkScalar dstY[4] = {
+ dst.fTop, dst.fTop + SkIntToScalar(margins.fTop),
+ dst.fBottom - SkIntToScalar(margins.fBottom), dst.fBottom
+ };
+
+ SkIRect s;
+ SkRect d;
+ for (int y = 0; y < 3; y++) {
+ s.fTop = srcY[y];
+ s.fBottom = srcY[y+1];
+ d.fTop = dstY[y];
+ d.fBottom = dstY[y+1];
+ for (int x = 0; x < 3; x++) {
+ s.fLeft = srcX[x];
+ s.fRight = srcX[x+1];
+ d.fLeft = dstX[x];
+ d.fRight = dstX[x+1];
+ canvas->drawBitmapRect(bitmap, &s, d, paint);
+ }
+ }
+}
+
+void SkNinePatch::DrawNine(SkCanvas* canvas, const SkRect& bounds,
+ const SkBitmap& bitmap, const SkIRect& margins,
+ const SkPaint* paint) {
+ /** Our vertices code has numerical precision problems if the transformed
+ coordinates land directly on a 1/2 pixel boundary. To work around that
+ for now, we only take the vertices case if we are in opengl. Also,
+ when not in GL, the vertices impl is slower (more math) than calling
+ the viaRects code.
+ */
+ if (canvas->getViewport(NULL)) { // returns true for OpenGL
+ int32_t xDivs[2];
+ int32_t yDivs[2];
+
+ xDivs[0] = margins.fLeft;
+ xDivs[1] = bitmap.width() - margins.fRight;
+ yDivs[0] = margins.fTop;
+ yDivs[1] = bitmap.height() - margins.fBottom;
+
+ SkNinePatch::DrawMesh(canvas, bounds, bitmap,
+ xDivs, 2, yDivs, 2, paint);
+ } else {
+ drawNineViaRects(canvas, bounds, bitmap, margins, paint);
+ }
+}
diff --git a/src/utils/SkProxyCanvas.cpp b/src/utils/SkProxyCanvas.cpp
new file mode 100644
index 0000000..2a02b45
--- /dev/null
+++ b/src/utils/SkProxyCanvas.cpp
@@ -0,0 +1,162 @@
+#include "SkProxyCanvas.h"
+
+SkProxyCanvas::SkProxyCanvas(SkCanvas* proxy) : fProxy(proxy) {
+ fProxy->safeRef();
+}
+
+SkProxyCanvas::~SkProxyCanvas() {
+ fProxy->safeUnref();
+}
+
+void SkProxyCanvas::setProxy(SkCanvas* proxy) {
+ SkRefCnt_SafeAssign(fProxy, proxy);
+}
+
+///////////////////////////////// Overrides ///////////
+
+bool SkProxyCanvas::getViewport(SkIPoint* size) const {
+ return fProxy->getViewport(size);
+}
+
+bool SkProxyCanvas::setViewport(int x, int y) {
+ return fProxy->setViewport(x, y);
+}
+
+SkDevice* SkProxyCanvas::setBitmapDevice(const SkBitmap& bitmap) {
+ return fProxy->setBitmapDevice(bitmap);
+}
+
+int SkProxyCanvas::save(SaveFlags flags) {
+ return fProxy->save(flags);
+}
+
+int SkProxyCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) {
+ return fProxy->saveLayer(bounds, paint, flags);
+}
+
+void SkProxyCanvas::restore() {
+ fProxy->restore();
+}
+
+bool SkProxyCanvas::translate(SkScalar dx, SkScalar dy) {
+ return fProxy->translate(dx, dy);
+}
+
+bool SkProxyCanvas::scale(SkScalar sx, SkScalar sy) {
+ return fProxy->scale(sx, sy);
+}
+
+bool SkProxyCanvas::rotate(SkScalar degrees) {
+ return fProxy->rotate(degrees);
+}
+
+bool SkProxyCanvas::skew(SkScalar sx, SkScalar sy) {
+ return fProxy->skew(sx, sy);
+}
+
+bool SkProxyCanvas::concat(const SkMatrix& matrix) {
+ return fProxy->concat(matrix);
+}
+
+void SkProxyCanvas::setMatrix(const SkMatrix& matrix) {
+ fProxy->setMatrix(matrix);
+}
+
+bool SkProxyCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
+ return fProxy->clipRect(rect, op);
+}
+
+bool SkProxyCanvas::clipPath(const SkPath& path, SkRegion::Op op) {
+ return fProxy->clipPath(path, op);
+}
+
+bool SkProxyCanvas::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
+ return fProxy->clipRegion(deviceRgn, op);
+}
+
+void SkProxyCanvas::drawPaint(const SkPaint& paint) {
+ fProxy->drawPaint(paint);
+}
+
+void SkProxyCanvas::drawPoints(PointMode mode, size_t count,
+ const SkPoint pts[], const SkPaint& paint) {
+ fProxy->drawPoints(mode, count, pts, paint);
+}
+
+void SkProxyCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
+ fProxy->drawRect(rect, paint);
+}
+
+void SkProxyCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
+ fProxy->drawPath(path, paint);
+}
+
+void SkProxyCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
+ const SkPaint* paint) {
+ fProxy->drawBitmap(bitmap, x, y, paint);
+}
+
+void SkProxyCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+ const SkRect& dst, const SkPaint* paint) {
+ fProxy->drawBitmapRect(bitmap, src, dst, paint);
+}
+
+void SkProxyCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+ const SkPaint* paint) {
+ fProxy->drawBitmapMatrix(bitmap, m, paint);
+}
+
+void SkProxyCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
+ const SkPaint* paint) {
+ fProxy->drawSprite(bitmap, x, y, paint);
+}
+
+void SkProxyCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint) {
+ fProxy->drawText(text, byteLength, x, y, paint);
+}
+
+void SkProxyCanvas::drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint) {
+ fProxy->drawPosText(text, byteLength, pos, paint);
+}
+
+void SkProxyCanvas::drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint) {
+ fProxy->drawPosTextH(text, byteLength, xpos, constY, paint);
+}
+
+void SkProxyCanvas::drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) {
+ fProxy->drawTextOnPath(text, byteLength, path, matrix, paint);
+}
+
+void SkProxyCanvas::drawPicture(SkPicture& picture) {
+ fProxy->drawPicture(picture);
+}
+
+void SkProxyCanvas::drawVertices(VertexMode vmode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) {
+ fProxy->drawVertices(vmode, vertexCount, vertices, texs, colors,
+ xmode, indices, indexCount, paint);
+}
+
+SkBounder* SkProxyCanvas::setBounder(SkBounder* bounder) {
+ return fProxy->setBounder(bounder);
+}
+
+SkDrawFilter* SkProxyCanvas::setDrawFilter(SkDrawFilter* filter) {
+ return fProxy->setDrawFilter(filter);
+}
+
+SkDevice* SkProxyCanvas::createDevice(SkBitmap::Config config, int width,
+ int height, bool isOpaque, bool isForLayer) {
+ return fProxy->createDevice(config, width, height, isOpaque, isForLayer);
+}
+
diff --git a/src/utils/SkUnitMappers.cpp b/src/utils/SkUnitMappers.cpp
new file mode 100644
index 0000000..0363a2b
--- /dev/null
+++ b/src/utils/SkUnitMappers.cpp
@@ -0,0 +1,80 @@
+#include "SkUnitMappers.h"
+
+SkDiscreteMapper::SkDiscreteMapper(int segments)
+{
+ if (segments < 2)
+ {
+ fSegments = 0;
+ fScale = 0;
+ }
+ else
+ {
+ if (segments > 0xFFFF)
+ segments = 0xFFFF;
+ fSegments = segments;
+ fScale = SK_Fract1 / (segments - 1);
+ }
+}
+
+uint16_t SkDiscreteMapper::mapUnit16(uint16_t input)
+{
+ SkFixed x = input * fSegments >> 16;
+ x = x * fScale >> 14;
+ x += x << 15 >> 31; // map 0x10000 to 0xFFFF
+ return SkToU16(x);
+}
+
+SkDiscreteMapper::SkDiscreteMapper(SkFlattenableReadBuffer& rb)
+ : SkUnitMapper(rb)
+{
+ fSegments = rb.readU32();
+ fScale = rb.readU32();
+}
+
+SkFlattenable::Factory SkDiscreteMapper::getFactory()
+{
+ return Create;
+}
+
+SkFlattenable* SkDiscreteMapper::Create(SkFlattenableReadBuffer& rb)
+{
+ return SkNEW_ARGS(SkDiscreteMapper, (rb));
+}
+
+void SkDiscreteMapper::flatten(SkFlattenableWriteBuffer& wb)
+{
+ this->INHERITED::flatten(wb);
+
+ wb.write32(fSegments);
+ wb.write32(fScale);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+uint16_t SkCosineMapper::mapUnit16(uint16_t input)
+{
+ /* we want to call cosine(input * pi/2) treating input as [0...1)
+ however, the straight multitply would overflow 32bits since input is
+ 16bits and pi/2 is 17bits, so we shift down our pi const before we mul
+ */
+ SkFixed rads = (unsigned)(input * (SK_FixedPI >> 2)) >> 15;
+ SkFixed x = SkFixedCos(rads);
+ x += x << 15 >> 31; // map 0x10000 to 0xFFFF
+ return SkToU16(x);
+}
+
+SkCosineMapper::SkCosineMapper(SkFlattenableReadBuffer& rb)
+ : SkUnitMapper(rb)
+{
+}
+
+SkFlattenable::Factory SkCosineMapper::getFactory()
+{
+ return Create;
+}
+
+SkFlattenable* SkCosineMapper::Create(SkFlattenableReadBuffer& rb)
+{
+ return SkNEW_ARGS(SkCosineMapper, (rb));
+}
+
diff --git a/src/utils/mac/SkBitmap_Mac.cpp b/src/utils/mac/SkBitmap_Mac.cpp
new file mode 100644
index 0000000..06c2b27
--- /dev/null
+++ b/src/utils/mac/SkBitmap_Mac.cpp
@@ -0,0 +1,142 @@
+#include "SkBitmap.h"
+#include "SkColorPriv.h"
+#include "SkMath.h"
+
+#if defined(SK_BUILD_FOR_MAC) && !defined(SK_USE_WXWIDGETS)
+
+#include <ApplicationServices/ApplicationServices.h>
+
+#ifndef __ppc__
+ #define SWAP_16BIT
+#endif
+
+static void convertGL32_to_Mac32(uint32_t dst[], const SkBitmap& bm) {
+ memcpy(dst, bm.getPixels(), bm.getSize());
+ return;
+
+ uint32_t* stop = dst + (bm.getSize() >> 2);
+ const uint8_t* src = (const uint8_t*)bm.getPixels();
+ while (dst < stop) {
+ *dst++ = src[2] << 24 | src[1] << 16 | src[0] << 8 | src[3] << 0;
+ src += sizeof(uint32_t);
+ }
+}
+
+static void convert565_to_32(uint32_t dst[], const SkBitmap& bm) {
+ for (int y = 0; y < bm.height(); y++) {
+ const uint16_t* src = bm.getAddr16(0, y);
+ const uint16_t* stop = src + bm.width();
+ while (src < stop) {
+ unsigned c = *src++;
+ unsigned r = SkPacked16ToR32(c);
+ unsigned g = SkPacked16ToG32(c);
+ unsigned b = SkPacked16ToB32(c);
+
+ *dst++ = (b << 24) | (g << 16) | (r << 8) | 0xFF;
+ }
+ }
+}
+
+static void convert4444_to_555(uint16_t dst[], const uint16_t src[], int count)
+{
+ const uint16_t* stop = src + count;
+
+ while (src < stop)
+ {
+ unsigned c = *src++;
+
+ unsigned r = SkGetPackedR4444(c);
+ unsigned g = SkGetPackedG4444(c);
+ unsigned b = SkGetPackedB4444(c);
+ // convert to 5 bits
+ r = (r << 1) | (r >> 3);
+ g = (g << 1) | (g >> 3);
+ b = (b << 1) | (b >> 3);
+ // build the 555
+ c = (r << 10) | (g << 5) | b;
+
+#ifdef SWAP_16BIT
+ c = (c >> 8) | (c << 8);
+#endif
+ *dst++ = c;
+ }
+}
+
+#include "SkTemplates.h"
+
+static CGImageRef bitmap2imageref(const SkBitmap& bm) {
+ size_t bitsPerComp;
+ size_t bitsPerPixel;
+ CGBitmapInfo info;
+ CGColorSpaceRef cs = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ CGDataProviderRef data = CGDataProviderCreateWithData(NULL,
+ bm.getPixels(),
+ bm.getSize(),
+ NULL);
+ SkAutoTCallVProc<CGDataProvider, CGDataProviderRelease> acp(data);
+ SkAutoTCallVProc<CGColorSpace, CGColorSpaceRelease> acp2(cs);
+
+ switch (bm.config()) {
+ case SkBitmap::kARGB_8888_Config:
+ bitsPerComp = 8;
+ bitsPerPixel = 32;
+ info = kCGImageAlphaPremultipliedLast;
+ break;
+ case SkBitmap::kARGB_4444_Config:
+ bitsPerComp = 4;
+ bitsPerPixel = 16;
+ info = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder16Little;
+ break;
+#if 0 // not supported by quartz !!!
+ case SkBitmap::kRGB_565_Config:
+ bitsPerComp = 5;
+ bitsPerPixel = 16;
+ info = kCGImageAlphaNone | kCGBitmapByteOrder16Little;
+ break;
+#endif
+ default:
+ return NULL;
+ }
+
+ return CGImageCreate(bm.width(), bm.height(), bitsPerComp, bitsPerPixel,
+ bm.rowBytes(), cs, info, data,
+ NULL, false, kCGRenderingIntentDefault);
+}
+
+void SkBitmap::drawToPort(WindowRef wind, CGContextRef cg) const {
+ if (fPixels == NULL || fWidth == 0 || fHeight == 0) {
+ return;
+ }
+
+ bool useQD = false;
+ if (NULL == cg) {
+ SetPortWindowPort(wind);
+ QDBeginCGContext(GetWindowPort(wind), &cg);
+ useQD = true;
+ }
+
+ SkBitmap bm;
+ if (this->config() == kRGB_565_Config) {
+ this->copyTo(&bm, kARGB_8888_Config);
+ } else {
+ bm = *this;
+ }
+ bm.lockPixels();
+
+ CGImageRef image = bitmap2imageref(bm);
+ if (image) {
+ CGRect rect;
+ rect.origin.x = rect.origin.y = 0;
+ rect.size.width = bm.width();
+ rect.size.height = bm.height();
+
+ CGContextDrawImage(cg, rect, image);
+ CGImageRelease(image);
+ }
+
+ if (useQD) {
+ QDEndCGContext(GetWindowPort(wind), &cg);
+ }
+}
+
+#endif
diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp
new file mode 100644
index 0000000..6c9415e
--- /dev/null
+++ b/src/utils/mac/SkCreateCGImageRef.cpp
@@ -0,0 +1,67 @@
+#include "SkCGUtils.h"
+#include "SkBitmap.h"
+
+extern CGImageRef SkCreateCGImageRef(const SkBitmap&);
+
+static void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info);
+ delete bitmap;
+}
+
+static SkBitmap* prepareForImageRef(const SkBitmap& bm,
+ size_t* bitsPerComponent,
+ CGBitmapInfo* info) {
+ switch (bm.config()) {
+ case SkBitmap::kARGB_8888_Config:
+ *bitsPerComponent = 8;
+ // try to match our argb ordering in SkColorPriv
+ *info = kCGBitmapByteOrder32Big |
+ kCGImageAlphaPremultipliedLast;
+ break;
+ case SkBitmap::kRGB_565_Config:
+ // doesn't see quite right. Are they thinking 1555?
+ *bitsPerComponent = 5;
+ *info = kCGBitmapByteOrder16Little;
+ break;
+ case SkBitmap::kARGB_4444_Config:
+ *bitsPerComponent = 4;
+ *info = kCGBitmapByteOrder16Little | kCGImageAlphaPremultipliedLast;
+ break;
+ default:
+ return NULL;
+ }
+
+ return new SkBitmap(bm);
+}
+
+CGImageRef SkCreateCGImageRef(const SkBitmap& bm) {
+ size_t bitsPerComponent;
+ CGBitmapInfo info;
+
+ SkBitmap* bitmap = prepareForImageRef(bm, &bitsPerComponent, &info);
+ if (NULL == bitmap) {
+ return NULL;
+ }
+
+ const int w = bitmap->width();
+ const int h = bitmap->height();
+ const size_t s = bitmap->getSize();
+
+ // our provider "owns" the bitmap*, and will take care of deleting it
+ // we initially lock it, so we can access the pixels. The bitmap will be deleted in the release
+ // proc, which will in turn unlock the pixels
+ bitmap->lockPixels();
+ CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s,
+ SkBitmap_ReleaseInfo);
+
+ CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ CGImageRef ref = CGImageCreate(w, h, bitsPerComponent,
+ bitmap->bytesPerPixel() * 8,
+ bitmap->rowBytes(), space, info, dataRef,
+ NULL, false, kCGRenderingIntentDefault);
+ CGColorSpaceRelease(space);
+ CGDataProviderRelease(dataRef);
+ return ref;
+}
+
+
diff --git a/src/utils/mac/SkOSWindow_Mac.cpp b/src/utils/mac/SkOSWindow_Mac.cpp
new file mode 100644
index 0000000..40ed57c
--- /dev/null
+++ b/src/utils/mac/SkOSWindow_Mac.cpp
@@ -0,0 +1,450 @@
+#include "SkTypes.h"
+
+#if defined(SK_BUILD_FOR_MAC) && !defined(SK_USE_WXWIDGETS)
+
+#include <Carbon/Carbon.h>
+#include "SkCGUtils.h"
+
+#include "SkWindow.h"
+#include "SkCanvas.h"
+#include "SkOSMenu.h"
+#include "SkTime.h"
+
+#include "SkGraphics.h"
+#include <new.h>
+
+static void (*gPrevNewHandler)();
+
+extern "C" {
+ static void sk_new_handler()
+ {
+ if (SkGraphics::SetFontCacheUsed(0))
+ return;
+ if (gPrevNewHandler)
+ gPrevNewHandler();
+ else
+ sk_throw();
+ }
+}
+
+static SkOSWindow* gCurrOSWin;
+static EventTargetRef gEventTarget;
+static EventQueueRef gCurrEventQ;
+
+static OSStatus MyDrawEventHandler(EventHandlerCallRef myHandler,
+ EventRef event, void *userData) {
+ // NOTE: GState is save/restored by the HIView system doing the callback,
+ // so the draw handler doesn't need to do it
+
+ OSStatus status = noErr;
+ CGContextRef context;
+ HIRect bounds;
+
+ // Get the CGContextRef
+ status = GetEventParameter (event, kEventParamCGContextRef,
+ typeCGContextRef, NULL,
+ sizeof (CGContextRef),
+ NULL,
+ &context);
+
+ if (status != noErr) {
+ SkDebugf("Got error %d getting the context!\n", status);
+ return status;
+ }
+
+ // Get the bounding rectangle
+ HIViewGetBounds ((HIViewRef) userData, &bounds);
+
+ gCurrOSWin->doPaint(context);
+ return status;
+}
+
+#define SK_MacEventClass FOUR_CHAR_CODE('SKec')
+#define SK_MacEventKind FOUR_CHAR_CODE('SKek')
+#define SK_MacEventParamName FOUR_CHAR_CODE('SKev')
+#define SK_MacEventSinkIDParamName FOUR_CHAR_CODE('SKes')
+
+static void set_bindingside(HISideBinding* side, HIViewRef parent, HIBindingKind kind) {
+ side->toView = parent;
+ side->kind = kind;
+ side->offset = 0;
+}
+
+static void set_axisscale(HIAxisScale* axis, HIViewRef parent) {
+ axis->toView = parent;
+ axis->kind = kHILayoutScaleAbsolute;
+ axis->ratio = 1;
+}
+
+static void set_axisposition(HIAxisPosition* pos, HIViewRef parent, HIPositionKind kind) {
+ pos->toView = parent;
+ pos->kind = kind;
+ pos->offset = 0;
+}
+
+SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd)
+{
+ OSStatus result;
+ WindowRef wr = (WindowRef)hWnd;
+
+ HIViewRef imageView, parent;
+ HIViewRef rootView = HIViewGetRoot(wr);
+ HIViewFindByID(rootView, kHIViewWindowContentID, &parent);
+ result = HIImageViewCreate(NULL, &imageView);
+ SkASSERT(result == noErr);
+
+ result = HIViewAddSubview(parent, imageView);
+ SkASSERT(result == noErr);
+
+ fHVIEW = imageView;
+
+ HIViewSetVisible(imageView, true);
+ HIViewPlaceInSuperviewAt(imageView, 0, 0);
+
+ if (true) {
+ HILayoutInfo layout;
+ layout.version = kHILayoutInfoVersionZero;
+ set_bindingside(&layout.binding.left, parent, kHILayoutBindLeft);
+ set_bindingside(&layout.binding.top, parent, kHILayoutBindTop);
+ set_bindingside(&layout.binding.right, parent, kHILayoutBindRight);
+ set_bindingside(&layout.binding.bottom, parent, kHILayoutBindBottom);
+ set_axisscale(&layout.scale.x, parent);
+ set_axisscale(&layout.scale.y, parent);
+ set_axisposition(&layout.position.x, parent, kHILayoutPositionLeft);
+ set_axisposition(&layout.position.y, rootView, kHILayoutPositionTop);
+ HIViewSetLayoutInfo(imageView, &layout);
+ }
+
+ HIImageViewSetOpaque(imageView, true);
+ HIImageViewSetScaleToFit(imageView, false);
+
+ static const EventTypeSpec gTypes[] = {
+ { kEventClassKeyboard, kEventRawKeyDown },
+ { kEventClassKeyboard, kEventRawKeyUp },
+ { kEventClassMouse, kEventMouseDown },
+ { kEventClassMouse, kEventMouseDragged },
+ { kEventClassMouse, kEventMouseUp },
+ { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
+ { kEventClassWindow, kEventWindowBoundsChanged },
+// { kEventClassWindow, kEventWindowDrawContent },
+ { SK_MacEventClass, SK_MacEventKind }
+ };
+
+ EventHandlerUPP handlerUPP = NewEventHandlerUPP(SkOSWindow::EventHandler);
+ int count = SK_ARRAY_COUNT(gTypes);
+
+ result = InstallEventHandler(GetWindowEventTarget(wr), handlerUPP,
+ count, gTypes, this, nil);
+ SkASSERT(result == noErr);
+
+ gCurrOSWin = this;
+ gCurrEventQ = GetCurrentEventQueue();
+ gEventTarget = GetWindowEventTarget(wr);
+
+ static bool gOnce = true;
+ if (gOnce) {
+ gOnce = false;
+ gPrevNewHandler = set_new_handler(sk_new_handler);
+ }
+}
+
+void SkOSWindow::doPaint(void* ctx)
+{
+#if 0
+ this->update(NULL);
+
+ const SkBitmap& bm = this->getBitmap();
+ CGImageRef img = SkCreateCGImageRef(bm);
+
+ if (img) {
+ CGRect r = CGRectMake(0, 0, bm.width(), bm.height());
+
+ CGContextRef cg = reinterpret_cast<CGContextRef>(ctx);
+
+ CGContextSaveGState(cg);
+ CGContextTranslateCTM(cg, 0, r.size.height);
+ CGContextScaleCTM(cg, 1, -1);
+
+ CGContextDrawImage(cg, r, img);
+
+ CGContextRestoreGState(cg);
+
+ CGImageRelease(img);
+ }
+#endif
+}
+
+void SkOSWindow::updateSize()
+{
+ Rect r;
+
+ GetWindowBounds((WindowRef)fHWND, kWindowContentRgn, &r);
+ this->resize(r.right - r.left, r.bottom - r.top);
+
+#if 0
+ HIRect frame;
+ HIViewRef imageView = (HIViewRef)getHVIEW();
+ HIViewRef parent = HIViewGetSuperview(imageView);
+
+ HIViewGetBounds(imageView, &frame);
+ SkDebugf("------ %d bounds %g %g %g %g\n", r.right - r.left,
+ frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
+#endif
+}
+
+void SkOSWindow::onHandleInval(const SkIRect& r)
+{
+ SkEvent* evt = new SkEvent("inval-imageview");
+ evt->post(this->getSinkID());
+}
+
+bool SkOSWindow::onEvent(const SkEvent& evt) {
+ if (evt.isType("inval-imageview")) {
+ this->update(NULL);
+
+ const SkBitmap& bm = this->getBitmap();
+
+ CGImageRef img = SkCreateCGImageRef(bm);
+ HIImageViewSetImage((HIViewRef)getHVIEW(), img);
+ CGImageRelease(img);
+ return true;
+ }
+ return INHERITED::onEvent(evt);
+}
+
+void SkOSWindow::onSetTitle(const char title[])
+{
+ CFStringRef str = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8);
+ SetWindowTitleWithCFString((WindowRef)fHWND, str);
+ CFRelease(str);
+}
+
+void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
+{
+}
+
+static void getparam(EventRef inEvent, OSType name, OSType type, UInt32 size, void* data)
+{
+ EventParamType actualType;
+ UInt32 actualSize;
+ OSStatus status;
+
+ status = GetEventParameter(inEvent, name, type, &actualType, size, &actualSize, data);
+ SkASSERT(status == noErr);
+ SkASSERT(actualType == type);
+ SkASSERT(actualSize == size);
+}
+
+enum {
+ SK_MacReturnKey = 36,
+ SK_MacDeleteKey = 51,
+ SK_MacEndKey = 119,
+ SK_MacLeftKey = 123,
+ SK_MacRightKey = 124,
+ SK_MacDownKey = 125,
+ SK_MacUpKey = 126,
+
+ SK_Mac0Key = 0x52,
+ SK_Mac1Key = 0x53,
+ SK_Mac2Key = 0x54,
+ SK_Mac3Key = 0x55,
+ SK_Mac4Key = 0x56,
+ SK_Mac5Key = 0x57,
+ SK_Mac6Key = 0x58,
+ SK_Mac7Key = 0x59,
+ SK_Mac8Key = 0x5b,
+ SK_Mac9Key = 0x5c
+};
+
+static SkKey raw2key(UInt32 raw)
+{
+ static const struct {
+ UInt32 fRaw;
+ SkKey fKey;
+ } gKeys[] = {
+ { SK_MacUpKey, kUp_SkKey },
+ { SK_MacDownKey, kDown_SkKey },
+ { SK_MacLeftKey, kLeft_SkKey },
+ { SK_MacRightKey, kRight_SkKey },
+ { SK_MacReturnKey, kOK_SkKey },
+ { SK_MacDeleteKey, kBack_SkKey },
+ { SK_MacEndKey, kEnd_SkKey },
+ { SK_Mac0Key, k0_SkKey },
+ { SK_Mac1Key, k1_SkKey },
+ { SK_Mac2Key, k2_SkKey },
+ { SK_Mac3Key, k3_SkKey },
+ { SK_Mac4Key, k4_SkKey },
+ { SK_Mac5Key, k5_SkKey },
+ { SK_Mac6Key, k6_SkKey },
+ { SK_Mac7Key, k7_SkKey },
+ { SK_Mac8Key, k8_SkKey },
+ { SK_Mac9Key, k9_SkKey }
+ };
+
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
+ if (gKeys[i].fRaw == raw)
+ return gKeys[i].fKey;
+ return kNONE_SkKey;
+}
+
+static void post_skmacevent()
+{
+ EventRef ref;
+ OSStatus status = CreateEvent(nil, SK_MacEventClass, SK_MacEventKind, 0, 0, &ref);
+ SkASSERT(status == noErr);
+
+#if 0
+ status = SetEventParameter(ref, SK_MacEventParamName, SK_MacEventParamName, sizeof(evt), &evt);
+ SkASSERT(status == noErr);
+ status = SetEventParameter(ref, SK_MacEventSinkIDParamName, SK_MacEventSinkIDParamName, sizeof(sinkID), &sinkID);
+ SkASSERT(status == noErr);
+#endif
+
+ EventTargetRef target = gEventTarget;
+ SetEventParameter(ref, kEventParamPostTarget, typeEventTargetRef, sizeof(target), &target);
+ SkASSERT(status == noErr);
+
+ status = PostEventToQueue(gCurrEventQ, ref, kEventPriorityStandard);
+ SkASSERT(status == noErr);
+
+ ReleaseEvent(ref);
+}
+
+pascal OSStatus SkOSWindow::EventHandler( EventHandlerCallRef inHandler, EventRef inEvent, void* userData )
+{
+ SkOSWindow* win = (SkOSWindow*)userData;
+ OSStatus result = eventNotHandledErr;
+ UInt32 wClass = GetEventClass(inEvent);
+ UInt32 wKind = GetEventKind(inEvent);
+
+ gCurrOSWin = win; // will need to be in TLS. Set this so PostEvent will work
+
+ switch (wClass) {
+ case kEventClassMouse: {
+ Point pt;
+ getparam(inEvent, kEventParamMouseLocation, typeQDPoint, sizeof(pt), &pt);
+ SetPortWindowPort((WindowRef)win->getHWND());
+ GlobalToLocal(&pt);
+
+ switch (wKind) {
+ case kEventMouseDown:
+ (void)win->handleClick(pt.h, pt.v, Click::kDown_State);
+ break;
+ case kEventMouseDragged:
+ (void)win->handleClick(pt.h, pt.v, Click::kMoved_State);
+ break;
+ case kEventMouseUp:
+ (void)win->handleClick(pt.h, pt.v, Click::kUp_State);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case kEventClassKeyboard:
+ if (wKind == kEventRawKeyDown) {
+ UInt32 raw;
+ getparam(inEvent, kEventParamKeyCode, typeUInt32, sizeof(raw), &raw);
+ SkKey key = raw2key(raw);
+ if (key != kNONE_SkKey)
+ (void)win->handleKey(key);
+ } else if (wKind == kEventRawKeyUp) {
+ UInt32 raw;
+ getparam(inEvent, kEventParamKeyCode, typeUInt32, sizeof(raw), &raw);
+ SkKey key = raw2key(raw);
+ if (key != kNONE_SkKey)
+ (void)win->handleKeyUp(key);
+ }
+ break;
+ case kEventClassTextInput:
+ if (wKind == kEventTextInputUnicodeForKeyEvent) {
+ UInt16 uni;
+ getparam(inEvent, kEventParamTextInputSendText, typeUnicodeText, sizeof(uni), &uni);
+ win->handleChar(uni);
+ }
+ break;
+ case kEventClassWindow:
+ switch (wKind) {
+ case kEventWindowBoundsChanged:
+ win->updateSize();
+ break;
+ case kEventWindowDrawContent: {
+ CGContextRef cg;
+ result = GetEventParameter(inEvent,
+ kEventParamCGContextRef,
+ typeCGContextRef,
+ NULL,
+ sizeof (CGContextRef),
+ NULL,
+ &cg);
+ if (result != 0) {
+ cg = NULL;
+ }
+ win->doPaint(cg);
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+ case SK_MacEventClass: {
+ SkASSERT(wKind == SK_MacEventKind);
+ if (SkEvent::ProcessEvent()) {
+ post_skmacevent();
+ }
+ #if 0
+ SkEvent* evt;
+ SkEventSinkID sinkID;
+ getparam(inEvent, SK_MacEventParamName, SK_MacEventParamName, sizeof(evt), &evt);
+ getparam(inEvent, SK_MacEventSinkIDParamName, SK_MacEventSinkIDParamName, sizeof(sinkID), &sinkID);
+ #endif
+ result = noErr;
+ break;
+ }
+ default:
+ break;
+ }
+ if (result == eventNotHandledErr) {
+ result = CallNextEventHandler(inHandler, inEvent);
+ }
+ return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+void SkEvent::SignalNonEmptyQueue()
+{
+ post_skmacevent();
+// SkDebugf("signal nonempty\n");
+}
+
+static TMTask gTMTaskRec;
+static TMTask* gTMTaskPtr;
+
+static void sk_timer_proc(TMTask* rec)
+{
+ SkEvent::ServiceQueueTimer();
+// SkDebugf("timer task fired\n");
+}
+
+void SkEvent::SignalQueueTimer(SkMSec delay)
+{
+ if (gTMTaskPtr)
+ {
+ RemoveTimeTask((QElem*)gTMTaskPtr);
+ DisposeTimerUPP(gTMTaskPtr->tmAddr);
+ gTMTaskPtr = nil;
+ }
+ if (delay)
+ {
+ gTMTaskPtr = &gTMTaskRec;
+ memset(gTMTaskPtr, 0, sizeof(gTMTaskRec));
+ gTMTaskPtr->tmAddr = NewTimerUPP(sk_timer_proc);
+ OSErr err = InstallTimeTask((QElem*)gTMTaskPtr);
+// SkDebugf("installtimetask of %d returned %d\n", delay, err);
+ PrimeTimeTask((QElem*)gTMTaskPtr, delay);
+ }
+}
+
+#endif
+