TestUtils.cpp revision dccca44ffda4836b56a21da95a046c9708ffd49c
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
19d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik#include "DeferredLayerUpdater.h"
20d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik#include "LayerRenderer.h"
21d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
2216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Recknamespace android {
2316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Recknamespace uirenderer {
2416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
2516c9d6a92e1b86d448c00c52a1630f3e71e6df76John ReckSkColor TestUtils::interpolateColor(float fraction, SkColor start, SkColor end) {
2616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int startA = (start >> 24) & 0xff;
2716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int startR = (start >> 16) & 0xff;
2816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int startG = (start >> 8) & 0xff;
2916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int startB = start & 0xff;
3016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
3116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int endA = (end >> 24) & 0xff;
3216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int endR = (end >> 16) & 0xff;
3316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int endG = (end >> 8) & 0xff;
3416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int endB = end & 0xff;
3516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
3616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    return (int)((startA + (int)(fraction * (endA - startA))) << 24)
3716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            | (int)((startR + (int)(fraction * (endR - startR))) << 16)
3816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            | (int)((startG + (int)(fraction * (endG - startG))) << 8)
3916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            | (int)((startB + (int)(fraction * (endB - startB))));
4016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck}
4116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
42d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craiksp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater(
43d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        renderthread::RenderThread& renderThread, uint32_t width, uint32_t height,
44d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        std::function<void(Matrix4*)> transformSetupCallback) {
45d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    bool isOpaque = true;
46d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    bool forceFilter = true;
47d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    GLenum renderTarget = GL_TEXTURE_EXTERNAL_OES;
48d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
49d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    Layer* layer = LayerRenderer::createTextureLayer(renderThread.renderState());
50d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, forceFilter,
51d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            renderTarget, Matrix4::identity().data);
52d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    transformSetupCallback(&(layer->getTransform()));
53d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
54d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    sp<DeferredLayerUpdater> layerUpdater = new DeferredLayerUpdater(layer);
55d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    return layerUpdater;
56d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik}
57d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
58e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craikvoid TestUtils::layoutTextUnscaled(const SkPaint& paint, const char* text,
59e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik        std::vector<glyph_t>* outGlyphs, std::vector<float>* outPositions,
60e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik        float* outTotalAdvance, Rect* outBounds) {
61e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    Rect bounds;
62e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    float totalAdvance = 0;
6342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
64d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    SkAutoGlyphCacheNoGamma autoCache(paint, &surfaceProps, &SkMatrix::I());
6542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    while (*text != '\0') {
6642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        SkUnichar unichar = SkUTF8_NextUnichar(&text);
6742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        glyph_t glyph = autoCache.getCache()->unicharToGlyph(unichar);
6842a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        autoCache.getCache()->unicharToGlyph(unichar);
69a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
7042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        // push glyph and its relative position
71e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik        outGlyphs->push_back(glyph);
72e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik        outPositions->push_back(totalAdvance);
73e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik        outPositions->push_back(0);
74a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
7542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        // compute bounds
7642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        SkGlyph skGlyph = autoCache.getCache()->getUnicharMetrics(unichar);
7742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        Rect glyphBounds(skGlyph.fWidth, skGlyph.fHeight);
7842a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        glyphBounds.translate(totalAdvance + skGlyph.fLeft, skGlyph.fTop);
7942a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        bounds.unionWith(glyphBounds);
80a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
8142a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        // advance next character
8242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        SkScalar skWidth;
8342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        paint.getTextWidths(&glyph, sizeof(glyph), &skWidth, NULL);
8442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        totalAdvance += skWidth;
8542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    }
86e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    *outBounds = bounds;
87e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    *outTotalAdvance = totalAdvance;
88e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik}
89e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik
90dccca44ffda4836b56a21da95a046c9708ffd49csergeyvvoid TestUtils::drawUtf8ToCanvas(TestCanvas* canvas, const char* text,
91e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik        const SkPaint& paint, float x, float y) {
92e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    // drawing text requires GlyphID TextEncoding (which JNI layer would have done)
93e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    LOG_ALWAYS_FATAL_IF(paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding,
94e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            "must use glyph encoding");
95e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
96e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    SkAutoGlyphCacheNoGamma autoCache(paint, &surfaceProps, &SkMatrix::I());
97e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik
98e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    std::vector<glyph_t> glyphs;
99e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    std::vector<float> positions;
100e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    float totalAdvance;
101e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    Rect bounds;
102e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    layoutTextUnscaled(paint, text, &glyphs, &positions, &totalAdvance, &bounds);
10342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik
10442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    // apply alignment via x parameter (which JNI layer would have done)
10542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    if (paint.getTextAlign() == SkPaint::kCenter_Align) {
10642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        x -= totalAdvance / 2;
10742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
10842a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        x -= totalAdvance;
10942a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    }
11042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik
11142a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    bounds.translate(x, y);
11242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik
11342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    // Force left alignment, since alignment offset is already baked in
11442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    SkPaint alignPaintCopy(paint);
11542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    alignPaintCopy.setTextAlign(SkPaint::kLeft_Align);
116dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    canvas->drawGlyphs(glyphs.data(), positions.data(), glyphs.size(), alignPaintCopy, x, y,
11742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik                bounds.left, bounds.top, bounds.right, bounds.bottom, totalAdvance);
118a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik}
119a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
120dccca44ffda4836b56a21da95a046c9708ffd49csergeyvvoid TestUtils::drawUtf8ToCanvas(TestCanvas* canvas, const char* text,
121d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        const SkPaint& paint, const SkPath& path) {
122d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    // drawing text requires GlyphID TextEncoding (which JNI layer would have done)
123d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    LOG_ALWAYS_FATAL_IF(paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding,
124d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            "must use glyph encoding");
125d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
126d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    SkAutoGlyphCacheNoGamma autoCache(paint, &surfaceProps, &SkMatrix::I());
127d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik
128d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    std::vector<glyph_t> glyphs;
129d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    while (*text != '\0') {
130d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        SkUnichar unichar = SkUTF8_NextUnichar(&text);
131d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        glyphs.push_back(autoCache.getCache()->unicharToGlyph(unichar));
132d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    }
133dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    canvas->drawGlyphsOnPath(glyphs.data(), glyphs.size(), path, 0, 0, paint);
134d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik}
135d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik
136e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reckvoid TestUtils::TestTask::run() {
137e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    // RenderState only valid once RenderThread is running, so queried here
138e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    RenderState& renderState = renderthread::RenderThread::getInstance().renderState();
139e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
140e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    renderState.onGLContextCreated();
141e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    rtCallback(renderthread::RenderThread::getInstance());
1421bc4ee4506b0a113d447d54909e1f8f5c1205563Chris Craik    renderState.flush(Caches::FlushMode::Full);
143e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    renderState.onGLContextDestroyed();
144e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck}
145e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
146dccca44ffda4836b56a21da95a046c9708ffd49csergeyvstd::unique_ptr<uint16_t[]> TestUtils::utf8ToUtf16(const char* str) {
147dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    const size_t strLen = strlen(str);
148dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    const ssize_t utf16Len = utf8_to_utf16_length((uint8_t*) str, strLen);
149dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    std::unique_ptr<uint16_t[]> dst(new uint16_t[utf16Len + 1]);
150dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    utf8_to_utf16((uint8_t*) str, strLen, (char16_t*) dst.get());
151dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    return dst;
152dccca44ffda4836b56a21da95a046c9708ffd49csergeyv}
153dccca44ffda4836b56a21da95a046c9708ffd49csergeyv
15416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck} /* namespace uirenderer */
15516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck} /* namespace android */
156