116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck/* 216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Copyright (C) 2015 The Android Open Source Project 316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * 416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * you may not use this file except in compliance with the License. 616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * You may obtain a copy of the License at 716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * 816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * http://www.apache.org/licenses/LICENSE-2.0 916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * 1016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Unless required by applicable law or agreed to in writing, software 1116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * distributed under the License is distributed on an "AS IS" BASIS, 1216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * See the License for the specific language governing permissions and 1416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * limitations under the License. 1516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck */ 1616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 1716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include "TestUtils.h" 1816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 1979abbf22d4f672208327546661e694d837f564a9Derek Sollenberger#include "hwui/Paint.h" 20d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik#include "DeferredLayerUpdater.h" 21d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 227dc370bfe3223dfbcb368e0006c688dfd668ab01sergeyv#include <renderthread/EglManager.h> 2356ad6ec42f814e9e61030ff819cac4e5d31def8bDerek Sollenberger#include <renderthread/OpenGLPipeline.h> 2498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel#include <pipeline/skia/SkiaOpenGLPipeline.h> 2598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel#include <pipeline/skia/SkiaVulkanPipeline.h> 2698c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel#include <renderthread/VulkanManager.h> 27f4cf5d3b019fa60e96219578a4c6ad1a90c7b665Ben Wagner#include <utils/Unicode.h> 2852771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include <SkClipStack.h> 29f4cf5d3b019fa60e96219578a4c6ad1a90c7b665Ben Wagner 30ee708facf127f2e8bed5970d5c05fa823fcfc1ceLeon Scroggins III#include <SkGlyphCache.h> 31ee708facf127f2e8bed5970d5c05fa823fcfc1ceLeon Scroggins III 3216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Recknamespace android { 3316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Recknamespace uirenderer { 3416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 3516c9d6a92e1b86d448c00c52a1630f3e71e6df76John ReckSkColor TestUtils::interpolateColor(float fraction, SkColor start, SkColor end) { 3616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck int startA = (start >> 24) & 0xff; 3716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck int startR = (start >> 16) & 0xff; 3816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck int startG = (start >> 8) & 0xff; 3916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck int startB = start & 0xff; 4016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 4116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck int endA = (end >> 24) & 0xff; 4216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck int endR = (end >> 16) & 0xff; 4316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck int endG = (end >> 8) & 0xff; 4416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck int endB = end & 0xff; 4516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 4616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck return (int)((startA + (int)(fraction * (endA - startA))) << 24) 4716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck | (int)((startR + (int)(fraction * (endR - startR))) << 16) 4816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck | (int)((startG + (int)(fraction * (endG - startG))) << 8) 4916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck | (int)((startB + (int)(fraction * (endB - startB)))); 5016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck} 5116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 52d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craiksp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater( 5398c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel renderthread::RenderThread& renderThread) { 5498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel android::uirenderer::renderthread::IRenderPipeline* pipeline; 5598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel if (Properties::getRenderPipelineType() == RenderPipelineType::OpenGL) { 5698c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel pipeline = new renderthread::OpenGLPipeline(renderThread); 5798c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel } else if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) { 5898c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel pipeline = new skiapipeline::SkiaOpenGLPipeline(renderThread); 5998c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel } else { 6098c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel pipeline = new skiapipeline::SkiaVulkanPipeline(renderThread); 6198c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel } 6298c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel sp<DeferredLayerUpdater> layerUpdater = pipeline->createTextureLayer(); 633e9999bd866fac71c72e6b484a9836c87c328a08sergeyv layerUpdater->apply(); 6498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel delete pipeline; 6598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel return layerUpdater; 6698c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel} 6798c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel 6898c78dad1969e2321cfee2085faa55d95bba7e29Greg Danielsp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater( 69d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik renderthread::RenderThread& renderThread, uint32_t width, uint32_t height, 70243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik const SkMatrix& transform) { 7198c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel sp<DeferredLayerUpdater> layerUpdater = createTextureLayerUpdater(renderThread); 7256ad6ec42f814e9e61030ff819cac4e5d31def8bDerek Sollenberger layerUpdater->backingLayer()->getTransform().load(transform); 73243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik layerUpdater->setSize(width, height); 74243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik layerUpdater->setTransform(&transform); 75243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik 76243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik // updateLayer so it's ready to draw 7709df887c9078a34f2bda32c83734b7f75c0a60ffChris Craik layerUpdater->updateLayer(true, Matrix4::identity().data); 7809df887c9078a34f2bda32c83734b7f75c0a60ffChris Craik if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) { 7909df887c9078a34f2bda32c83734b7f75c0a60ffChris Craik static_cast<GlLayer*>(layerUpdater->backingLayer())->setRenderTarget( 8009df887c9078a34f2bda32c83734b7f75c0a60ffChris Craik GL_TEXTURE_EXTERNAL_OES); 8109df887c9078a34f2bda32c83734b7f75c0a60ffChris Craik } 82d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik return layerUpdater; 83d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik} 84d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 85e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craikvoid TestUtils::layoutTextUnscaled(const SkPaint& paint, const char* text, 86e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik std::vector<glyph_t>* outGlyphs, std::vector<float>* outPositions, 87e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik float* outTotalAdvance, Rect* outBounds) { 88e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik Rect bounds; 89e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik float totalAdvance = 0; 9042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry); 91d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik SkAutoGlyphCacheNoGamma autoCache(paint, &surfaceProps, &SkMatrix::I()); 9242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik while (*text != '\0') { 93f4cf5d3b019fa60e96219578a4c6ad1a90c7b665Ben Wagner size_t nextIndex = 0; 94f4cf5d3b019fa60e96219578a4c6ad1a90c7b665Ben Wagner int32_t unichar = utf32_from_utf8_at(text, 4, 0, &nextIndex); 95f4cf5d3b019fa60e96219578a4c6ad1a90c7b665Ben Wagner text += nextIndex; 96f4cf5d3b019fa60e96219578a4c6ad1a90c7b665Ben Wagner 9742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik glyph_t glyph = autoCache.getCache()->unicharToGlyph(unichar); 9842a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik autoCache.getCache()->unicharToGlyph(unichar); 99a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 10042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik // push glyph and its relative position 101e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik outGlyphs->push_back(glyph); 102e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik outPositions->push_back(totalAdvance); 103e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik outPositions->push_back(0); 104a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 10542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik // compute bounds 10642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik SkGlyph skGlyph = autoCache.getCache()->getUnicharMetrics(unichar); 10742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik Rect glyphBounds(skGlyph.fWidth, skGlyph.fHeight); 10842a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik glyphBounds.translate(totalAdvance + skGlyph.fLeft, skGlyph.fTop); 10942a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik bounds.unionWith(glyphBounds); 110a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 11142a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik // advance next character 11242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik SkScalar skWidth; 11342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik paint.getTextWidths(&glyph, sizeof(glyph), &skWidth, NULL); 11442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik totalAdvance += skWidth; 11542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik } 116e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik *outBounds = bounds; 117e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik *outTotalAdvance = totalAdvance; 118e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik} 119e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik 12042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik 12179abbf22d4f672208327546661e694d837f564a9Derek Sollenbergervoid TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, 12279abbf22d4f672208327546661e694d837f564a9Derek Sollenberger const SkPaint& paint, float x, float y) { 12379abbf22d4f672208327546661e694d837f564a9Derek Sollenberger auto utf16 = asciiToUtf16(text); 12479abbf22d4f672208327546661e694d837f564a9Derek Sollenberger canvas->drawText(utf16.get(), 0, strlen(text), strlen(text), x, y, 0, paint, nullptr); 125a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik} 126a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 12779abbf22d4f672208327546661e694d837f564a9Derek Sollenbergervoid TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, 128d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik const SkPaint& paint, const SkPath& path) { 12979abbf22d4f672208327546661e694d837f564a9Derek Sollenberger auto utf16 = asciiToUtf16(text); 13079abbf22d4f672208327546661e694d837f564a9Derek Sollenberger canvas->drawTextOnPath(utf16.get(), strlen(text), 0, path, 0, 0, paint, nullptr); 131d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik} 132d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 133e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reckvoid TestUtils::TestTask::run() { 134e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck // RenderState only valid once RenderThread is running, so queried here 1357dc370bfe3223dfbcb368e0006c688dfd668ab01sergeyv renderthread::RenderThread& renderThread = renderthread::RenderThread::getInstance(); 13698c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { 13798c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel renderThread.vulkanManager().initialize(); 13898c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel } else { 13998c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel renderThread.eglManager().initialize(); 14098c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel } 141e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck 1427dc370bfe3223dfbcb368e0006c688dfd668ab01sergeyv rtCallback(renderThread); 14356ad6ec42f814e9e61030ff819cac4e5d31def8bDerek Sollenberger 14498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { 14598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel renderThread.vulkanManager().destroy(); 14698c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel } else { 14798c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel renderThread.renderState().flush(Caches::FlushMode::Full); 14898c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel renderThread.eglManager().destroy(); 14998c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel } 150e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck} 151e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck 15279abbf22d4f672208327546661e694d837f564a9Derek Sollenbergerstd::unique_ptr<uint16_t[]> TestUtils::asciiToUtf16(const char* str) { 15379abbf22d4f672208327546661e694d837f564a9Derek Sollenberger const int length = strlen(str); 15479abbf22d4f672208327546661e694d837f564a9Derek Sollenberger std::unique_ptr<uint16_t[]> utf16(new uint16_t[length]); 15579abbf22d4f672208327546661e694d837f564a9Derek Sollenberger for (int i = 0; i < length; i++) { 15679abbf22d4f672208327546661e694d837f564a9Derek Sollenberger utf16.get()[i] = str[i]; 15779abbf22d4f672208327546661e694d837f564a9Derek Sollenberger } 15879abbf22d4f672208327546661e694d837f564a9Derek Sollenberger return utf16; 159dccca44ffda4836b56a21da95a046c9708ffd49csergeyv} 160dccca44ffda4836b56a21da95a046c9708ffd49csergeyv 161021693b967a2c5556dddd183eb0247df4079e1adStan IlievSkColor TestUtils::getColor(const sk_sp<SkSurface>& surface, int x, int y) { 162021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPixmap pixmap; 163021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (!surface->peekPixels(&pixmap)) { 164021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return 0; 165021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 166021693b967a2c5556dddd183eb0247df4079e1adStan Iliev switch (pixmap.colorType()) { 167021693b967a2c5556dddd183eb0247df4079e1adStan Iliev case kGray_8_SkColorType: { 168021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const uint8_t* addr = pixmap.addr8(x, y); 169021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return SkColorSetRGB(*addr, *addr, *addr); 170021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 171021693b967a2c5556dddd183eb0247df4079e1adStan Iliev case kAlpha_8_SkColorType: { 172021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const uint8_t* addr = pixmap.addr8(x, y); 173021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return SkColorSetA(0, addr[0]); 174021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 175021693b967a2c5556dddd183eb0247df4079e1adStan Iliev case kRGB_565_SkColorType: { 176021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const uint16_t* addr = pixmap.addr16(x, y); 177021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return SkPixel16ToColor(addr[0]); 178021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 179021693b967a2c5556dddd183eb0247df4079e1adStan Iliev case kARGB_4444_SkColorType: { 180021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const uint16_t* addr = pixmap.addr16(x, y); 181021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPMColor c = SkPixel4444ToPixel32(addr[0]); 182021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return SkUnPreMultiply::PMColorToColor(c); 183021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 184021693b967a2c5556dddd183eb0247df4079e1adStan Iliev case kBGRA_8888_SkColorType: { 185021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const uint32_t* addr = pixmap.addr32(x, y); 186021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPMColor c = SkSwizzle_BGRA_to_PMColor(addr[0]); 187021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return SkUnPreMultiply::PMColorToColor(c); 188021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 189021693b967a2c5556dddd183eb0247df4079e1adStan Iliev case kRGBA_8888_SkColorType: { 190021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const uint32_t* addr = pixmap.addr32(x, y); 191021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPMColor c = SkSwizzle_RGBA_to_PMColor(addr[0]); 192021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return SkUnPreMultiply::PMColorToColor(c); 193021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 194021693b967a2c5556dddd183eb0247df4079e1adStan Iliev default: 195021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return 0; 196021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 197021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return 0; 198021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 199021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 20052771272f4f018f4fc6846224bf047497e784af1Stan IlievSkRect TestUtils::getClipBounds(const SkCanvas* canvas) { 2015e4389823191aafff7422561f134dbdb391e0a2dMike Reed return SkRect::Make(canvas->getDeviceClipBounds()); 20252771272f4f018f4fc6846224bf047497e784af1Stan Iliev} 20352771272f4f018f4fc6846224bf047497e784af1Stan Iliev 20452771272f4f018f4fc6846224bf047497e784af1Stan IlievSkRect TestUtils::getLocalClipBounds(const SkCanvas* canvas) { 20552771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkMatrix invertedTotalMatrix; 20652771272f4f018f4fc6846224bf047497e784af1Stan Iliev if (!canvas->getTotalMatrix().invert(&invertedTotalMatrix)) { 20752771272f4f018f4fc6846224bf047497e784af1Stan Iliev return SkRect::MakeEmpty(); 20852771272f4f018f4fc6846224bf047497e784af1Stan Iliev } 20952771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkRect outlineInDeviceCoord = TestUtils::getClipBounds(canvas); 21052771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkRect outlineInLocalCoord; 21152771272f4f018f4fc6846224bf047497e784af1Stan Iliev invertedTotalMatrix.mapRect(&outlineInLocalCoord, outlineInDeviceCoord); 21252771272f4f018f4fc6846224bf047497e784af1Stan Iliev return outlineInLocalCoord; 21352771272f4f018f4fc6846224bf047497e784af1Stan Iliev} 21452771272f4f018f4fc6846224bf047497e784af1Stan Iliev 21516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck} /* namespace uirenderer */ 21616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck} /* namespace android */ 217