1acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck/* 2acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Copyright (C) 2014 The Android Open Source Project 3acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * 4acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 5d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck * you mPrimitiveFields.may not use this file except in compliance with the License. 6d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck * You mPrimitiveFields.may obtain a copy of the License at 7acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * 8acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * http://www.apache.org/licenses/LICENSE-2.0 9acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * 10acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Unless required by applicable law or agreed to in writing, software 11acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * distributed under the License is distributed on an "AS IS" BASIS, 12acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * See the License for the specific language governing permissions and 14acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * limitations under the License. 15acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck */ 16d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 17acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include "RenderProperties.h" 18acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 19d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck#include <utils/Trace.h> 20d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 2125fbb3fa1138675379102a44405852555cefccbdJohn Reck#include <SkColorFilter.h> 22acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include <SkMatrix.h> 238c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik#include <SkPath.h> 248c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik#include <SkPathOps.h> 25acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 26acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include "Matrix.h" 27dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "hwui/Canvas.h" 28e0bb87d4bdbd3b08ab6a8569c8e564ed59b8a5a7Chris Craik#include "utils/MathUtils.h" 29f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck 30acb6f07623b7df3d4179f70ae03ade574616ffa6John Recknamespace android { 31acb6f07623b7df3d4179f70ae03ade574616ffa6John Recknamespace uirenderer { 32acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 33182952f5eeefc2a21d76d4664ada0e2d78c1105cChris CraikLayerProperties::LayerProperties() { 3425fbb3fa1138675379102a44405852555cefccbdJohn Reck reset(); 3525fbb3fa1138675379102a44405852555cefccbdJohn Reck} 3625fbb3fa1138675379102a44405852555cefccbdJohn Reck 3725fbb3fa1138675379102a44405852555cefccbdJohn ReckLayerProperties::~LayerProperties() { 38182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik setType(LayerType::None); 3925fbb3fa1138675379102a44405852555cefccbdJohn Reck} 4025fbb3fa1138675379102a44405852555cefccbdJohn Reck 4125fbb3fa1138675379102a44405852555cefccbdJohn Reckvoid LayerProperties::reset() { 4225fbb3fa1138675379102a44405852555cefccbdJohn Reck mOpaque = false; 43d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik setFromPaint(nullptr); 4425fbb3fa1138675379102a44405852555cefccbdJohn Reck} 4525fbb3fa1138675379102a44405852555cefccbdJohn Reck 4625fbb3fa1138675379102a44405852555cefccbdJohn Reckbool LayerProperties::setColorFilter(SkColorFilter* filter) { 4725fbb3fa1138675379102a44405852555cefccbdJohn Reck if (mColorFilter == filter) return false; 4825fbb3fa1138675379102a44405852555cefccbdJohn Reck SkRefCnt_SafeAssign(mColorFilter, filter); 4925fbb3fa1138675379102a44405852555cefccbdJohn Reck return true; 5025fbb3fa1138675379102a44405852555cefccbdJohn Reck} 5125fbb3fa1138675379102a44405852555cefccbdJohn Reck 5225fbb3fa1138675379102a44405852555cefccbdJohn Reckbool LayerProperties::setFromPaint(const SkPaint* paint) { 5325fbb3fa1138675379102a44405852555cefccbdJohn Reck bool changed = false; 54bf6f0f260886a04a1680c7f9917124a751322ca4Chris Craik changed |= setAlpha(static_cast<uint8_t>(PaintUtils::getAlphaDirect(paint))); 55260ab726486317496bc12a57d599ea96dcde3284Mike Reed changed |= setXferMode(PaintUtils::getBlendModeDirect(paint)); 56d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik changed |= setColorFilter(paint ? paint->getColorFilter() : nullptr); 5725fbb3fa1138675379102a44405852555cefccbdJohn Reck return changed; 5825fbb3fa1138675379102a44405852555cefccbdJohn Reck} 5925fbb3fa1138675379102a44405852555cefccbdJohn Reck 6025fbb3fa1138675379102a44405852555cefccbdJohn ReckLayerProperties& LayerProperties::operator=(const LayerProperties& other) { 6125fbb3fa1138675379102a44405852555cefccbdJohn Reck setType(other.type()); 6225fbb3fa1138675379102a44405852555cefccbdJohn Reck setOpaque(other.opaque()); 6325fbb3fa1138675379102a44405852555cefccbdJohn Reck setAlpha(other.alpha()); 6425fbb3fa1138675379102a44405852555cefccbdJohn Reck setXferMode(other.xferMode()); 6525fbb3fa1138675379102a44405852555cefccbdJohn Reck setColorFilter(other.colorFilter()); 6625fbb3fa1138675379102a44405852555cefccbdJohn Reck return *this; 6725fbb3fa1138675379102a44405852555cefccbdJohn Reck} 6825fbb3fa1138675379102a44405852555cefccbdJohn Reck 69d0a0b2a3140bfb1819a116413ce9d81886697a07John ReckRenderProperties::ComputedFields::ComputedFields() 70d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik : mTransformMatrix(nullptr) { 71d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck} 72d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 73d0a0b2a3140bfb1819a116413ce9d81886697a07John ReckRenderProperties::ComputedFields::~ComputedFields() { 74acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck delete mTransformMatrix; 75d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck} 76d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 77d0a0b2a3140bfb1819a116413ce9d81886697a07John ReckRenderProperties::RenderProperties() 78d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik : mStaticMatrix(nullptr) 79d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik , mAnimationMatrix(nullptr) { 80d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck} 81d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 82d0a0b2a3140bfb1819a116413ce9d81886697a07John ReckRenderProperties::~RenderProperties() { 83acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck delete mStaticMatrix; 84acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck delete mAnimationMatrix; 85acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} 86acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 87d0a0b2a3140bfb1819a116413ce9d81886697a07John ReckRenderProperties& RenderProperties::operator=(const RenderProperties& other) { 88d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck if (this != &other) { 89d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck mPrimitiveFields = other.mPrimitiveFields; 90d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck setStaticMatrix(other.getStaticMatrix()); 91d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck setAnimationMatrix(other.getAnimationMatrix()); 92d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck setCameraDistance(other.getCameraDistance()); 9325fbb3fa1138675379102a44405852555cefccbdJohn Reck mLayerProperties = other.layerProperties(); 94d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 9549e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik // Force recalculation of the matrix, since other's dirty bit may be clear 96f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mPrimitiveFields.mMatrixOrPivotDirty = true; 9749e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik updateMatrix(); 98d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 99d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck return *this; 100acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} 101acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 102c3849aa786db65dbda254b90b7db3b13efd98e65sergeyvstatic void dumpMatrix(std::ostream& output, std::string& indent, 103c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv const char* label, SkMatrix* matrix) { 104c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv if (matrix) { 105c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << indent << "(" << label << " " << matrix << ": "; 106c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << std::fixed << std::setprecision(2); 107c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << "[" << matrix->get(0) << " "<< matrix->get(1) << " " << matrix->get(2) << "]"; 108c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << " [" << matrix->get(3) << " "<< matrix->get(4) << " " << matrix->get(5) << "]"; 109c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << " [" << matrix->get(6) << " "<< matrix->get(7) << " " << matrix->get(8) << "]"; 110c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << ")" << std::endl; 111d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 112c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv} 113c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv 114c3849aa786db65dbda254b90b7db3b13efd98e65sergeyvvoid RenderProperties::debugOutputProperties(std::ostream& output, const int level) const { 115c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv auto indent = std::string(level * 2, ' '); 116c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv if (mPrimitiveFields.mLeft != 0 || mPrimitiveFields.mTop != 0) { 117c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << indent << "(Translate (left, top) " << mPrimitiveFields.mLeft 118c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << ", " << mPrimitiveFields.mTop << ")" << std::endl; 119d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 120c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv dumpMatrix(output, indent, "ConcatMatrix (static)", mStaticMatrix); 121c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv dumpMatrix(output, indent, "ConcatMatrix (animation)", mAnimationMatrix); 122c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv 123c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << std::fixed << std::setprecision(2); 124f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck if (hasTransformMatrix()) { 125f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck if (isTransformTranslateOnly()) { 126c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << indent << "(Translate " << getTranslationX() << ", " << getTranslationY() 127c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << ", " << getZ() << ")" << std::endl; 128d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } else { 129c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv dumpMatrix(output, indent, "ConcatMatrix ", mComputedFields.mTransformMatrix); 130d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 131d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 132d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 133856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik const bool isLayer = effectiveLayerType() != LayerType::None; 134a753f4c6cb8558795e673df1896532cd148781e2Chris Craik int clipFlags = getClippingFlags(); 13543a1d31a2837406a437937b340db85c1a05ed1edChris Craik if (mPrimitiveFields.mAlpha < 1 13643a1d31a2837406a437937b340db85c1a05ed1edChris Craik && !MathUtils::isZero(mPrimitiveFields.mAlpha)) { 137a753f4c6cb8558795e673df1896532cd148781e2Chris Craik if (isLayer) { 138a753f4c6cb8558795e673df1896532cd148781e2Chris Craik clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer 139d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 1408df5ffa9ae0667d9e0241adf4675753156fcef84Chris Craik 1414e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik if (CC_LIKELY(isLayer || !getHasOverlappingRendering())) { 1424e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik // simply scale rendering content's alpha 143c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << indent << "(ScaleAlpha " << mPrimitiveFields.mAlpha << ")" << std::endl; 1444e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik } else { 1454e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik // savelayeralpha to create an offscreen buffer to apply alpha 1464e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik Rect layerBounds(0, 0, getWidth(), getHeight()); 1474e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik if (clipFlags) { 1484e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik getClippingRectForFlags(clipFlags, &layerBounds); 1494e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik clipFlags = 0; // all clipping done by savelayer 1504e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik } 151c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << indent << "(SaveLayerAlpha " 152c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << (int)layerBounds.left << ", " << (int)layerBounds.top << ", " 153c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << (int)layerBounds.right << ", " << (int)layerBounds.bottom << ", " 154c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << (int)(mPrimitiveFields.mAlpha * 255) << ", 0x" << std::hex 155c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << (SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer) << ")" << std::dec 156c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << std::endl; 1574e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik } 158d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 15991eff22b5d7f8fe551bae01331948858ce932a96Chris Craik 160a753f4c6cb8558795e673df1896532cd148781e2Chris Craik if (clipFlags) { 161a753f4c6cb8558795e673df1896532cd148781e2Chris Craik Rect clipRect; 162a753f4c6cb8558795e673df1896532cd148781e2Chris Craik getClippingRectForFlags(clipFlags, &clipRect); 163c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << indent << "(ClipRect " 164c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << (int)clipRect.left << ", " << (int)clipRect.top << ", " 165c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << (int)clipRect.right << ", " << (int)clipRect.bottom << ")" << std::endl; 166d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 167136d1af1cc67f51e8523189260a7c4a22cc02768Chris Craik 168136d1af1cc67f51e8523189260a7c4a22cc02768Chris Craik if (getRevealClip().willClip()) { 169136d1af1cc67f51e8523189260a7c4a22cc02768Chris Craik Rect bounds; 170136d1af1cc67f51e8523189260a7c4a22cc02768Chris Craik getRevealClip().getBounds(&bounds); 171c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << indent << "(Clip to reveal clip with bounds " 172c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << bounds.left << ", " << bounds.top << ", " 173c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << bounds.right << ", " << bounds.bottom << ")" << std::endl; 174136d1af1cc67f51e8523189260a7c4a22cc02768Chris Craik } 175136d1af1cc67f51e8523189260a7c4a22cc02768Chris Craik 176136d1af1cc67f51e8523189260a7c4a22cc02768Chris Craik auto& outline = mPrimitiveFields.mOutline; 177136d1af1cc67f51e8523189260a7c4a22cc02768Chris Craik if (outline.getShouldClip()) { 178136d1af1cc67f51e8523189260a7c4a22cc02768Chris Craik if (outline.isEmpty()) { 179c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << indent << "(Clip to empty outline)"; 180136d1af1cc67f51e8523189260a7c4a22cc02768Chris Craik } else if (outline.willClip()) { 181c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv const Rect& bounds = outline.getBounds(); 182c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv output << indent << "(Clip to outline with bounds " 183c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << bounds.left << ", " << bounds.top << ", " 184c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv << bounds.right << ", " << bounds.bottom << ")" << std::endl; 185136d1af1cc67f51e8523189260a7c4a22cc02768Chris Craik } 186136d1af1cc67f51e8523189260a7c4a22cc02768Chris Craik } 187acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} 188acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 189acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckvoid RenderProperties::updateMatrix() { 190f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck if (mPrimitiveFields.mMatrixOrPivotDirty) { 191f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck if (!mComputedFields.mTransformMatrix) { 192f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck // only allocate a mPrimitiveFields.matrix if we have a complex transform 193f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformMatrix = new SkMatrix(); 194f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck } 195f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck if (!mPrimitiveFields.mPivotExplicitlySet) { 196f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mPrimitiveFields.mPivotX = mPrimitiveFields.mWidth / 2.0f; 197f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mPrimitiveFields.mPivotY = mPrimitiveFields.mHeight / 2.0f; 198f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck } 199f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck SkMatrix* transform = mComputedFields.mTransformMatrix; 200f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform->reset(); 201e0bb87d4bdbd3b08ab6a8569c8e564ed59b8a5a7Chris Craik if (MathUtils::isZero(getRotationX()) && MathUtils::isZero(getRotationY())) { 202f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform->setTranslate(getTranslationX(), getTranslationY()); 203f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform->preRotate(getRotation(), getPivotX(), getPivotY()); 204f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform->preScale(getScaleX(), getScaleY(), getPivotX(), getPivotY()); 205f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck } else { 206f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck SkMatrix transform3D; 207f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformCamera.save(); 208f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform->preScale(getScaleX(), getScaleY(), getPivotX(), getPivotY()); 209f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformCamera.rotateX(mPrimitiveFields.mRotationX); 210f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformCamera.rotateY(mPrimitiveFields.mRotationY); 211f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformCamera.rotateZ(-mPrimitiveFields.mRotation); 212f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformCamera.getMatrix(&transform3D); 213f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform3D.preTranslate(-getPivotX(), -getPivotY()); 214f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform3D.postTranslate(getPivotX() + getTranslationX(), 215f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck getPivotY() + getTranslationY()); 216f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform->postConcat(transform3D); 217f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformCamera.restore(); 218acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck } 219f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mPrimitiveFields.mMatrixOrPivotDirty = false; 220acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck } 221acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} 222acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 223acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} /* namespace uirenderer */ 224acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} /* namespace android */ 225