TestUtils.cpp revision ee708facf127f2e8bed5970d5c05fa823fcfc1ce
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "TestUtils.h" 18 19#include "hwui/Paint.h" 20#include "DeferredLayerUpdater.h" 21 22#include <renderthread/EglManager.h> 23#include <renderthread/OpenGLPipeline.h> 24#include <utils/Unicode.h> 25#include <SkClipStack.h> 26 27#include <SkGlyphCache.h> 28 29namespace android { 30namespace uirenderer { 31 32SkColor TestUtils::interpolateColor(float fraction, SkColor start, SkColor end) { 33 int startA = (start >> 24) & 0xff; 34 int startR = (start >> 16) & 0xff; 35 int startG = (start >> 8) & 0xff; 36 int startB = start & 0xff; 37 38 int endA = (end >> 24) & 0xff; 39 int endR = (end >> 16) & 0xff; 40 int endG = (end >> 8) & 0xff; 41 int endB = end & 0xff; 42 43 return (int)((startA + (int)(fraction * (endA - startA))) << 24) 44 | (int)((startR + (int)(fraction * (endR - startR))) << 16) 45 | (int)((startG + (int)(fraction * (endG - startG))) << 8) 46 | (int)((startB + (int)(fraction * (endB - startB)))); 47} 48 49sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater( 50 renderthread::RenderThread& renderThread, uint32_t width, uint32_t height, 51 const SkMatrix& transform) { 52 renderthread::OpenGLPipeline pipeline(renderThread); 53 sp<DeferredLayerUpdater> layerUpdater = pipeline.createTextureLayer(); 54 layerUpdater->backingLayer()->getTransform().load(transform); 55 layerUpdater->setSize(width, height); 56 layerUpdater->setTransform(&transform); 57 58 // updateLayer so it's ready to draw 59 layerUpdater->updateLayer(true, GL_TEXTURE_EXTERNAL_OES, Matrix4::identity().data); 60 return layerUpdater; 61} 62 63void TestUtils::layoutTextUnscaled(const SkPaint& paint, const char* text, 64 std::vector<glyph_t>* outGlyphs, std::vector<float>* outPositions, 65 float* outTotalAdvance, Rect* outBounds) { 66 Rect bounds; 67 float totalAdvance = 0; 68 SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry); 69 SkAutoGlyphCacheNoGamma autoCache(paint, &surfaceProps, &SkMatrix::I()); 70 while (*text != '\0') { 71 size_t nextIndex = 0; 72 int32_t unichar = utf32_from_utf8_at(text, 4, 0, &nextIndex); 73 text += nextIndex; 74 75 glyph_t glyph = autoCache.getCache()->unicharToGlyph(unichar); 76 autoCache.getCache()->unicharToGlyph(unichar); 77 78 // push glyph and its relative position 79 outGlyphs->push_back(glyph); 80 outPositions->push_back(totalAdvance); 81 outPositions->push_back(0); 82 83 // compute bounds 84 SkGlyph skGlyph = autoCache.getCache()->getUnicharMetrics(unichar); 85 Rect glyphBounds(skGlyph.fWidth, skGlyph.fHeight); 86 glyphBounds.translate(totalAdvance + skGlyph.fLeft, skGlyph.fTop); 87 bounds.unionWith(glyphBounds); 88 89 // advance next character 90 SkScalar skWidth; 91 paint.getTextWidths(&glyph, sizeof(glyph), &skWidth, NULL); 92 totalAdvance += skWidth; 93 } 94 *outBounds = bounds; 95 *outTotalAdvance = totalAdvance; 96} 97 98 99void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, 100 const SkPaint& paint, float x, float y) { 101 auto utf16 = asciiToUtf16(text); 102 canvas->drawText(utf16.get(), 0, strlen(text), strlen(text), x, y, 0, paint, nullptr); 103} 104 105void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, 106 const SkPaint& paint, const SkPath& path) { 107 auto utf16 = asciiToUtf16(text); 108 canvas->drawTextOnPath(utf16.get(), strlen(text), 0, path, 0, 0, paint, nullptr); 109} 110 111void TestUtils::TestTask::run() { 112 // RenderState only valid once RenderThread is running, so queried here 113 renderthread::RenderThread& renderThread = renderthread::RenderThread::getInstance(); 114 renderThread.eglManager().initialize(); 115 116 rtCallback(renderThread); 117 118 renderThread.renderState().flush(Caches::FlushMode::Full); 119 renderThread.eglManager().destroy(); 120} 121 122std::unique_ptr<uint16_t[]> TestUtils::asciiToUtf16(const char* str) { 123 const int length = strlen(str); 124 std::unique_ptr<uint16_t[]> utf16(new uint16_t[length]); 125 for (int i = 0; i < length; i++) { 126 utf16.get()[i] = str[i]; 127 } 128 return utf16; 129} 130 131SkColor TestUtils::getColor(const sk_sp<SkSurface>& surface, int x, int y) { 132 SkPixmap pixmap; 133 if (!surface->peekPixels(&pixmap)) { 134 return 0; 135 } 136 switch (pixmap.colorType()) { 137 case kGray_8_SkColorType: { 138 const uint8_t* addr = pixmap.addr8(x, y); 139 return SkColorSetRGB(*addr, *addr, *addr); 140 } 141 case kAlpha_8_SkColorType: { 142 const uint8_t* addr = pixmap.addr8(x, y); 143 return SkColorSetA(0, addr[0]); 144 } 145 case kRGB_565_SkColorType: { 146 const uint16_t* addr = pixmap.addr16(x, y); 147 return SkPixel16ToColor(addr[0]); 148 } 149 case kARGB_4444_SkColorType: { 150 const uint16_t* addr = pixmap.addr16(x, y); 151 SkPMColor c = SkPixel4444ToPixel32(addr[0]); 152 return SkUnPreMultiply::PMColorToColor(c); 153 } 154 case kBGRA_8888_SkColorType: { 155 const uint32_t* addr = pixmap.addr32(x, y); 156 SkPMColor c = SkSwizzle_BGRA_to_PMColor(addr[0]); 157 return SkUnPreMultiply::PMColorToColor(c); 158 } 159 case kRGBA_8888_SkColorType: { 160 const uint32_t* addr = pixmap.addr32(x, y); 161 SkPMColor c = SkSwizzle_RGBA_to_PMColor(addr[0]); 162 return SkUnPreMultiply::PMColorToColor(c); 163 } 164 default: 165 return 0; 166 } 167 return 0; 168} 169 170SkRect TestUtils::getClipBounds(const SkCanvas* canvas) { 171 SkClipStack::BoundsType boundType; 172 SkRect clipBounds; 173 canvas->getClipStack()->getBounds(&clipBounds, &boundType); 174 return clipBounds; 175} 176 177SkRect TestUtils::getLocalClipBounds(const SkCanvas* canvas) { 178 SkMatrix invertedTotalMatrix; 179 if (!canvas->getTotalMatrix().invert(&invertedTotalMatrix)) { 180 return SkRect::MakeEmpty(); 181 } 182 SkRect outlineInDeviceCoord = TestUtils::getClipBounds(canvas); 183 SkRect outlineInLocalCoord; 184 invertedTotalMatrix.mapRect(&outlineInLocalCoord, outlineInDeviceCoord); 185 return outlineInLocalCoord; 186} 187 188} /* namespace uirenderer */ 189} /* namespace android */ 190