1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/* 3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project 4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */ 8685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkCamera.h" 11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic SkScalar SkScalarDotDiv(int count, const SkScalar a[], int step_a, 13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkScalar b[], int step_b, 1418ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com SkScalar denom) { 15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_SCALAR_IS_FLOAT 16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com float prod = 0; 1718ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com for (int i = 0; i < count; i++) { 18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prod += a[0] * b[0]; 19bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a += step_a; 20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b += step_b; 21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 22bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return prod / denom; 23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else 24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk64 prod, tmp; 25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prod.set(0); 2718ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com for (int i = 0; i < count; i++) { 28bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.setMul(a[0], b[0]); 29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prod.add(tmp); 30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a += step_a; 31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b += step_b; 32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prod.div(denom, Sk64::kRound_DivOption); 34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return prod.get32(); 35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic SkScalar SkScalarDot(int count, const SkScalar a[], int step_a, 3918ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com const SkScalar b[], int step_b) { 40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_SCALAR_IS_FLOAT 41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com float prod = 0; 4218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com for (int i = 0; i < count; i++) { 43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prod += a[0] * b[0]; 44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a += step_a; 45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b += step_b; 46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return prod; 48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else 49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk64 prod, tmp; 50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prod.set(0); 5218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com for (int i = 0; i < count; i++) { 53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.setMul(a[0], b[0]); 54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prod.add(tmp); 55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a += step_a; 56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b += step_b; 57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return prod.getFixed(); 59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 6218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com/////////////////////////////////////////////////////////////////////////////// 63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 6418ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comSkUnitScalar SkPoint3D::normalize(SkUnit3D* unit) const { 65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_SCALAR_IS_FLOAT 66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com float mag = sk_float_sqrt(fX*fX + fY*fY + fZ*fZ); 6718ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com if (mag) { 68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com float scale = 1.0f / mag; 69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unit->fX = fX * scale; 70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unit->fY = fY * scale; 71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unit->fZ = fZ * scale; 7218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com } else { 7318ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com unit->fX = unit->fY = unit->fZ = 0; 74bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else 76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk64 tmp1, tmp2; 77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp1.setMul(fX, fX); 79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp2.setMul(fY, fY); 80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp1.add(tmp2); 81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp2.setMul(fZ, fZ); 82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp1.add(tmp2); 83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed mag = tmp1.getSqrt(); 8518ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com if (mag) { 86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // what if mag < SK_Fixed1 ??? we will underflow the fixdiv 87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed scale = SkFixedDiv(SK_Fract1, mag); 88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unit->fX = SkFixedMul(fX, scale); 89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unit->fY = SkFixedMul(fY, scale); 90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unit->fZ = SkFixedMul(fZ, scale); 9118ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com } else { 9218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com unit->fX = unit->fY = unit->fZ = 0; 93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return mag; 96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 9818ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comSkUnitScalar SkUnit3D::Dot(const SkUnit3D& a, const SkUnit3D& b) { 99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkUnitScalarMul(a.fX, b.fX) + 100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkUnitScalarMul(a.fY, b.fY) + 101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkUnitScalarMul(a.fZ, b.fZ); 102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 10418ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkUnit3D::Cross(const SkUnit3D& a, const SkUnit3D& b, SkUnit3D* cross) { 105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(cross); 106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // use x,y,z, in case &a == cross or &b == cross 108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar x = SkUnitScalarMul(a.fY, b.fZ) - SkUnitScalarMul(a.fZ, b.fY); 110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar y = SkUnitScalarMul(a.fZ, b.fX) - SkUnitScalarMul(a.fX, b.fY); 111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar z = SkUnitScalarMul(a.fX, b.fY) - SkUnitScalarMul(a.fY, b.fX); 112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cross->set(x, y, z); 114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 11618ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com/////////////////////////////////////////////////////////////////////////////// 117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 11818ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comSkPatch3D::SkPatch3D() { 119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->reset(); 120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 12218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkPatch3D::reset() { 123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fOrigin.set(0, 0, 0); 124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fU.set(SK_Scalar1, 0, 0); 125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fV.set(0, -SK_Scalar1, 0); 126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 12818ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkPatch3D::transform(const SkMatrix3D& m, SkPatch3D* dst) const { 12918ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com if (dst == NULL) { 130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst = (SkPatch3D*)this; 13118ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com } 132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com m.mapVector(fU, &dst->fU); 133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com m.mapVector(fV, &dst->fV); 134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com m.mapPoint(fOrigin, &dst->fOrigin); 135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 13718ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comSkScalar SkPatch3D::dotWith(SkScalar dx, SkScalar dy, SkScalar dz) const { 138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar cx = SkScalarMul(fU.fY, fV.fZ) - SkScalarMul(fU.fZ, fV.fY); 139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar cy = SkScalarMul(fU.fZ, fV.fX) - SkScalarMul(fU.fX, fV.fY); 140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar cz = SkScalarMul(fU.fX, fV.fY) - SkScalarMul(fU.fY, fV.fX); 141bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkScalarMul(cx, dx) + SkScalarMul(cy, dy) + SkScalarMul(cz, dz); 143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 14518ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com/////////////////////////////////////////////////////////////////////////////// 146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 14718ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkMatrix3D::reset() { 148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com memset(fMat, 0, sizeof(fMat)); 149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMat[0][0] = fMat[1][1] = fMat[2][2] = SK_Scalar1; 150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 15218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkMatrix3D::setTranslate(SkScalar x, SkScalar y, SkScalar z) { 153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com memset(fMat, 0, sizeof(fMat)); 154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMat[0][0] = x; 155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMat[1][1] = y; 156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMat[2][2] = z; 157bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 15918ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkMatrix3D::setRotateX(SkScalar degX) { 160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar s, c; 161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com s = SkScalarSinCos(SkDegreesToRadians(degX), &c); 163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setRow(0, SK_Scalar1, 0, 0); 164bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setRow(1, 0, c, -s); 165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setRow(2, 0, s, c); 166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 16818ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkMatrix3D::setRotateY(SkScalar degY) { 169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar s, c; 170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 171bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com s = SkScalarSinCos(SkDegreesToRadians(degY), &c); 172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setRow(0, c, 0, -s); 173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setRow(1, 0, SK_Scalar1, 0); 174bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setRow(2, s, 0, c); 175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 176bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 17718ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkMatrix3D::setRotateZ(SkScalar degZ) { 178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar s, c; 179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com s = SkScalarSinCos(SkDegreesToRadians(degZ), &c); 181bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setRow(0, c, -s, 0); 182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setRow(1, s, c, 0); 183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setRow(2, 0, 0, SK_Scalar1); 184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 18618ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkMatrix3D::preTranslate(SkScalar x, SkScalar y, SkScalar z) { 187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar col[3] = { x, y, z}; 188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 18918ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com for (int i = 0; i < 3; i++) { 190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMat[i][3] += SkScalarDot(3, &fMat[i][0], 1, col, 1); 19118ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com } 192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 19418ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkMatrix3D::preRotateX(SkScalar degX) { 19518ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com SkMatrix3D m; 196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com m.setRotateX(degX); 197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setConcat(*this, m); 198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 20018ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkMatrix3D::preRotateY(SkScalar degY) { 20118ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com SkMatrix3D m; 202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com m.setRotateY(degY); 203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setConcat(*this, m); 204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 20618ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkMatrix3D::preRotateZ(SkScalar degZ) { 20718ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com SkMatrix3D m; 208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com m.setRotateZ(degZ); 209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setConcat(*this, m); 210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 21218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkMatrix3D::setConcat(const SkMatrix3D& a, const SkMatrix3D& b) { 213bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkMatrix3D tmp; 214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkMatrix3D* c = this; 215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 21618ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com if (this == &a || this == &b) { 217bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c = &tmp; 21818ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com } 219bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com for (int i = 0; i < 3; i++) { 22018ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com for (int j = 0; j < 3; j++) { 221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c->fMat[i][j] = SkScalarDot(3, &a.fMat[i][0], 1, &b.fMat[0][j], 4); 22218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com } 22318ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com c->fMat[i][3] = SkScalarDot(3, &a.fMat[i][0], 1, 22418ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com &b.fMat[0][3], 4) + a.fMat[i][3]; 225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 22718ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com if (c == &tmp) { 228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *this = tmp; 22918ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com } 230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 23218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkMatrix3D::mapPoint(const SkPoint3D& src, SkPoint3D* dst) const { 233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar x = SkScalarDot(3, &fMat[0][0], 1, &src.fX, 1) + fMat[0][3]; 234bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar y = SkScalarDot(3, &fMat[1][0], 1, &src.fX, 1) + fMat[1][3]; 235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar z = SkScalarDot(3, &fMat[2][0], 1, &src.fX, 1) + fMat[2][3]; 236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->set(x, y, z); 237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 238bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 23918ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkMatrix3D::mapVector(const SkVector3D& src, SkVector3D* dst) const { 240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar x = SkScalarDot(3, &fMat[0][0], 1, &src.fX, 1); 241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar y = SkScalarDot(3, &fMat[1][0], 1, &src.fX, 1); 242bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar z = SkScalarDot(3, &fMat[2][0], 1, &src.fX, 1); 243bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->set(x, y, z); 244bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 24618ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com/////////////////////////////////////////////////////////////////////////////// 247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 24818ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comSkCamera3D::SkCamera3D() { 249bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->reset(); 250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 251bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 25218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkCamera3D::reset() { 253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fLocation.set(0, 0, -SkIntToScalar(576)); // 8 inches backward 254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fAxis.set(0, 0, SK_Scalar1); // forward 255bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fZenith.set(0, -SK_Scalar1, 0); // up 256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fObserver.set(0, 0, fLocation.fZ); 258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fNeedToUpdate = true; 260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 26218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkCamera3D::update() { 263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fNeedToUpdate = true; 264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 26618ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkCamera3D::doUpdate() const { 267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkUnit3D axis, zenith, cross; 268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fAxis.normalize(&axis); 270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 272f79344ff5cde387bce386eac805a3899f4e255b9bsalomon@google.com SkScalar dot = SkUnit3D::Dot(*SkTCast<const SkUnit3D*>(&fZenith), axis); 273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com zenith.fX = fZenith.fX - SkUnitScalarMul(dot, axis.fX); 275bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com zenith.fY = fZenith.fY - SkUnitScalarMul(dot, axis.fY); 276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com zenith.fZ = fZenith.fZ - SkUnitScalarMul(dot, axis.fZ); 277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 278f79344ff5cde387bce386eac805a3899f4e255b9bsalomon@google.com SkTCast<SkPoint3D*>(&zenith)->normalize(&zenith); 279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 281bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkUnit3D::Cross(axis, zenith, &cross); 282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkMatrix* orien = &fOrientation; 285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar x = fObserver.fX; 286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar y = fObserver.fY; 287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar z = fObserver.fZ; 288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com orien->set(SkMatrix::kMScaleX, SkUnitScalarMul(x, axis.fX) - SkUnitScalarMul(z, cross.fX)); 290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com orien->set(SkMatrix::kMSkewX, SkUnitScalarMul(x, axis.fY) - SkUnitScalarMul(z, cross.fY)); 291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com orien->set(SkMatrix::kMTransX, SkUnitScalarMul(x, axis.fZ) - SkUnitScalarMul(z, cross.fZ)); 292bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com orien->set(SkMatrix::kMSkewY, SkUnitScalarMul(y, axis.fX) - SkUnitScalarMul(z, zenith.fX)); 293bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com orien->set(SkMatrix::kMScaleY, SkUnitScalarMul(y, axis.fY) - SkUnitScalarMul(z, zenith.fY)); 294bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com orien->set(SkMatrix::kMTransY, SkUnitScalarMul(y, axis.fZ) - SkUnitScalarMul(z, zenith.fZ)); 295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com orien->set(SkMatrix::kMPersp0, axis.fX); 296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com orien->set(SkMatrix::kMPersp1, axis.fY); 297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com orien->set(SkMatrix::kMPersp2, axis.fZ); 298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 30118ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid SkCamera3D::patchToMatrix(const SkPatch3D& quilt, SkMatrix* matrix) const { 30218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com if (fNeedToUpdate) { 303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->doUpdate(); 304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fNeedToUpdate = false; 305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 306bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkScalar* mapPtr = (const SkScalar*)(const void*)&fOrientation; 308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkScalar* patchPtr; 309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPoint3D diff; 310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar dot; 311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com diff.fX = quilt.fOrigin.fX - fLocation.fX; 313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com diff.fY = quilt.fOrigin.fY - fLocation.fY; 314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com diff.fZ = quilt.fOrigin.fZ - fLocation.fZ; 315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 316f79344ff5cde387bce386eac805a3899f4e255b9bsalomon@google.com dot = SkUnit3D::Dot(*SkTCast<const SkUnit3D*>(&diff), 317f79344ff5cde387bce386eac805a3899f4e255b9bsalomon@google.com *SkTCast<const SkUnit3D*>(SkTCast<const SkScalar*>(&fOrientation) + 6)); 318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com patchPtr = (const SkScalar*)&quilt; 320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix->set(SkMatrix::kMScaleX, SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot)); 321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix->set(SkMatrix::kMSkewY, SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot)); 322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix->set(SkMatrix::kMPersp0, SkScalarDotDiv(3, patchPtr, 1, mapPtr+6, 1, dot)); 323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com patchPtr += 3; 325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix->set(SkMatrix::kMSkewX, SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot)); 326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix->set(SkMatrix::kMScaleY, SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot)); 327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix->set(SkMatrix::kMPersp1, SkScalarDotDiv(3, patchPtr, 1, mapPtr+6, 1, dot)); 328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com patchPtr = (const SkScalar*)(const void*)&diff; 330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix->set(SkMatrix::kMTransX, SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot)); 331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix->set(SkMatrix::kMTransY, SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot)); 332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix->set(SkMatrix::kMPersp2, SK_UnitScalar1); 333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 33518ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com/////////////////////////////////////////////////////////////////////////////// 336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 33718ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comSk3DView::Sk3DView() { 338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fInitialRec.fMatrix.reset(); 339bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRec = &fInitialRec; 340bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 34218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comSk3DView::~Sk3DView() { 343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Rec* rec = fRec; 344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (rec != &fInitialRec) { 345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Rec* next = rec->fNext; 346bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDELETE(rec); 347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec = next; 348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 35118ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid Sk3DView::save() { 352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Rec* rec = SkNEW(Rec); 353bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fNext = fRec; 354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fMatrix = fRec->fMatrix; 355bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRec = rec; 356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 35818ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid Sk3DView::restore() { 359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(fRec != &fInitialRec); 360bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Rec* next = fRec->fNext; 361bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDELETE(fRec); 362bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRec = next; 363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 365f3a882d015181a30388e98b9a04e76d04d11b667djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID 36618ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid Sk3DView::setCameraLocation(SkScalar x, SkScalar y, SkScalar z) { 367d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com // the camera location is passed in inches, set in pt 368dfc928cc9afc242d1125e8d5ae48e8bca66c4834commit-bot@chromium.org SkScalar lz = z * 72.0f; 369dfc928cc9afc242d1125e8d5ae48e8bca66c4834commit-bot@chromium.org fCamera.fLocation.set(x * 72.0f, y * 72.0f, lz); 370d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com fCamera.fObserver.set(0, 0, lz); 371d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com fCamera.update(); 372dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com 373d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com} 3747174ec8c620d98bbbc2048b7036a1e45383629d2djsollen@google.com 3757174ec8c620d98bbbc2048b7036a1e45383629d2djsollen@google.comSkScalar Sk3DView::getCameraLocationX() { 376dfc928cc9afc242d1125e8d5ae48e8bca66c4834commit-bot@chromium.org return fCamera.fLocation.fX / 72.0f; 3777174ec8c620d98bbbc2048b7036a1e45383629d2djsollen@google.com} 3787174ec8c620d98bbbc2048b7036a1e45383629d2djsollen@google.com 3797174ec8c620d98bbbc2048b7036a1e45383629d2djsollen@google.comSkScalar Sk3DView::getCameraLocationY() { 380dfc928cc9afc242d1125e8d5ae48e8bca66c4834commit-bot@chromium.org return fCamera.fLocation.fY / 72.0f; 3817174ec8c620d98bbbc2048b7036a1e45383629d2djsollen@google.com} 3827174ec8c620d98bbbc2048b7036a1e45383629d2djsollen@google.com 3837174ec8c620d98bbbc2048b7036a1e45383629d2djsollen@google.comSkScalar Sk3DView::getCameraLocationZ() { 384dfc928cc9afc242d1125e8d5ae48e8bca66c4834commit-bot@chromium.org return fCamera.fLocation.fZ / 72.0f; 3857174ec8c620d98bbbc2048b7036a1e45383629d2djsollen@google.com} 386d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com#endif 387d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com 38818ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid Sk3DView::translate(SkScalar x, SkScalar y, SkScalar z) { 389bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRec->fMatrix.preTranslate(x, y, z); 390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 39218ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid Sk3DView::rotateX(SkScalar deg) { 393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRec->fMatrix.preRotateX(deg); 394bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 395bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 39618ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid Sk3DView::rotateY(SkScalar deg) { 397bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRec->fMatrix.preRotateY(deg); 398bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 399bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 40018ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid Sk3DView::rotateZ(SkScalar deg) { 401bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRec->fMatrix.preRotateZ(deg); 402bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 403bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 40418ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comSkScalar Sk3DView::dotWithNormal(SkScalar x, SkScalar y, SkScalar z) const { 405bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPatch3D patch; 406bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com patch.transform(fRec->fMatrix); 407bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return patch.dotWith(x, y, z); 408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 409bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 41018ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid Sk3DView::getMatrix(SkMatrix* matrix) const { 41118ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.com if (matrix != NULL) { 412bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPatch3D patch; 413bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com patch.transform(fRec->fMatrix); 414bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fCamera.patchToMatrix(patch, matrix); 415bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 416bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 417bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 418bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkCanvas.h" 419bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 42018ec3a8b541abddf77938667e5b4e842625ca7f8reed@google.comvoid Sk3DView::applyToCanvas(SkCanvas* canvas) const { 421bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkMatrix matrix; 422dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com 423bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->getMatrix(&matrix); 424bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com canvas->concat(matrix); 425bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 426