From 35934cccabf72879603ef37222da2195445f027e Mon Sep 17 00:00:00 2001 From: Derek Sollenberger Date: Wed, 23 Mar 2016 14:59:10 -0400 Subject: [PATCH] Compute text bounds on a per glyph basis when drawing from an SkPicture. bug: 27665826 Change-Id: I031c08a348b2488c85f74e708ee90019b24d707f --- libs/hwui/Android.mk | 3 +- libs/hwui/SkiaCanvasProxy.cpp | 15 ++++-- libs/hwui/tests/unit/SkiaCanvasTests.cpp | 60 ++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 libs/hwui/tests/unit/SkiaCanvasTests.cpp diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 516591b2f0996..01f9cde823c7d 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -266,7 +266,8 @@ ifeq (true, $(HWUI_NEW_OPS)) tests/unit/FrameBuilderTests.cpp \ tests/unit/LeakCheckTests.cpp \ tests/unit/OpDumperTests.cpp \ - tests/unit/RecordingCanvasTests.cpp + tests/unit/RecordingCanvasTests.cpp \ + tests/unit/SkiaCanvasTests.cpp endif include $(LOCAL_PATH)/hwui_static_deps.mk diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp index c6124803eb6a0..9df32b28bf3b9 100644 --- a/libs/hwui/SkiaCanvasProxy.cpp +++ b/libs/hwui/SkiaCanvasProxy.cpp @@ -318,12 +318,17 @@ void SkiaCanvasProxy::onDrawPosText(const void* text, size_t byteLength, const S posArray = pointStorage.get(); } - // compute conservative bounds - // NOTE: We could call the faster paint.getFontBounds for a less accurate, - // but even more conservative bounds if this is too slow. + // Compute conservative bounds. If the content has already been processed + // by Minikin then it had already computed these bounds. Unfortunately, + // there is no way to capture those bounds as part of the Skia drawPosText + // API so we need to do that computation again here. SkRect bounds; - glyphs.paint.measureText(glyphs.glyphIDs, glyphs.count << 1, &bounds); - bounds.offset(x, y); + for (int i = 0; i < glyphs.count; i++) { + SkRect glyphBounds; + glyphs.paint.measureText(&glyphs.glyphIDs[i], sizeof(uint16_t), &glyphBounds); + glyphBounds.offset(pos[i].fX, pos[i].fY); + bounds.join(glyphBounds); + } static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats"); mCanvas->drawGlyphs(glyphs.glyphIDs, &posArray[0].fX, glyphs.count, glyphs.paint, x, y, diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp new file mode 100644 index 0000000000000..d6279b4a29744 --- /dev/null +++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tests/common/TestUtils.h" + +#include +#include +#include +#include + +using namespace android; +using namespace android::uirenderer; + +/** + * Verify that we get the same culling bounds for text for (1) drawing glyphs + * directly to a Canvas or (2) going through a SkPicture as an intermediate step. + */ +TEST(SkiaCanvasProxy, drawGlyphsViaPicture) { + auto dl = TestUtils::createDisplayList(200, 200, [](RecordingCanvas& canvas) { + // setup test variables + SkPaint paint; + paint.setAntiAlias(true); + paint.setTextSize(20); + static const char* text = "testing text bounds"; + + // draw text directly into Recording canvas + TestUtils::drawUtf8ToCanvas(&canvas, text, paint, 25, 25); + + // record the same text draw into a SkPicture and replay it into a Recording canvas + SkPictureRecorder recorder; + SkCanvas* skCanvas = recorder.beginRecording(200, 200, NULL, 0); + std::unique_ptr pictCanvas(Canvas::create_canvas(skCanvas)); + TestUtils::drawUtf8ToCanvas(pictCanvas.get(), text, paint, 25, 25); + SkAutoTUnref picture(recorder.endRecording()); + + canvas.asSkCanvas()->drawPicture(picture); + }); + + // verify that the text bounds and matrices match + ASSERT_EQ(2U, dl->getOps().size()); + auto directOp = dl->getOps()[0]; + auto pictureOp = dl->getOps()[1]; + ASSERT_EQ(RecordedOpId::TextOp, directOp->opId); + EXPECT_EQ(directOp->opId, pictureOp->opId); + EXPECT_EQ(directOp->unmappedBounds, pictureOp->unmappedBounds); + EXPECT_EQ(directOp->localMatrix, pictureOp->localMatrix); +}