Home | History | Annotate | Download | only in unit
      1 /*
      2  * Copyright (C) 2016 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 "tests/common/TestUtils.h"
     18 
     19 #include <RecordingCanvas.h>
     20 #include <SkBlurDrawLooper.h>
     21 #include <SkCanvasStateUtils.h>
     22 #include <SkPicture.h>
     23 #include <SkPictureRecorder.h>
     24 #include <gtest/gtest.h>
     25 
     26 using namespace android;
     27 using namespace android::uirenderer;
     28 
     29 /**
     30  * Verify that we get the same culling bounds for text for (1) drawing glyphs
     31  * directly to a Canvas or (2) going through a SkPicture as an intermediate step.
     32  */
     33 OPENGL_PIPELINE_TEST(SkiaCanvasProxy, drawGlyphsViaPicture) {
     34     auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
     35         // setup test variables
     36         SkPaint paint;
     37         paint.setAntiAlias(true);
     38         paint.setTextSize(20);
     39         static const char* text = "testing text bounds";
     40 
     41         // draw text directly into Recording canvas
     42         TestUtils::drawUtf8ToCanvas(&canvas, text, paint, 25, 25);
     43 
     44         // record the same text draw into a SkPicture and replay it into a Recording canvas
     45         SkPictureRecorder recorder;
     46         SkCanvas* skCanvas = recorder.beginRecording(200, 200, NULL, 0);
     47         std::unique_ptr<Canvas> pictCanvas(Canvas::create_canvas(skCanvas));
     48         TestUtils::drawUtf8ToCanvas(pictCanvas.get(), text, paint, 25, 25);
     49         sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
     50 
     51         canvas.asSkCanvas()->drawPicture(picture);
     52     });
     53 
     54     // verify that the text bounds and matrices match
     55     ASSERT_EQ(2U, dl->getOps().size());
     56     auto directOp = dl->getOps()[0];
     57     auto pictureOp = dl->getOps()[1];
     58     ASSERT_EQ(RecordedOpId::TextOp, directOp->opId);
     59     EXPECT_EQ(directOp->opId, pictureOp->opId);
     60     EXPECT_EQ(directOp->unmappedBounds, pictureOp->unmappedBounds);
     61     EXPECT_EQ(directOp->localMatrix, pictureOp->localMatrix);
     62 }
     63 
     64 TEST(SkiaCanvas, drawShadowLayer) {
     65     auto surface = SkSurface::MakeRasterN32Premul(10, 10);
     66     SkiaCanvas canvas(surface->getCanvas());
     67 
     68     // clear to white
     69     canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrc);
     70 
     71     SkPaint paint;
     72     // it is transparent to ensure that we still draw the rect since it has a looper
     73     paint.setColor(SK_ColorTRANSPARENT);
     74     // this is how view's shadow layers are implemented
     75     paint.setLooper(SkBlurDrawLooper::Make(0xF0000000, 6.0f, 0, 10));
     76     canvas.drawRect(3, 3, 7, 7, paint);
     77 
     78     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
     79     ASSERT_NE(TestUtils::getColor(surface, 5, 5), SK_ColorWHITE);
     80 }
     81 
     82 TEST(SkiaCanvas, colorSpaceXform) {
     83     sk_sp<SkColorSpace> adobe = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
     84                                                       SkColorSpace::kAdobeRGB_Gamut);
     85 
     86     SkImageInfo adobeInfo = SkImageInfo::Make(1, 1, kN32_SkColorType, kOpaque_SkAlphaType, adobe);
     87     sk_sp<Bitmap> adobeBitmap = Bitmap::allocateHeapBitmap(adobeInfo);
     88     SkBitmap adobeSkBitmap;
     89     adobeBitmap->getSkBitmap(&adobeSkBitmap);
     90     *adobeSkBitmap.getAddr32(0, 0) = 0xFF0000F0;  // Opaque, almost fully-red
     91 
     92     SkImageInfo info = adobeInfo.makeColorSpace(nullptr);
     93     sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info);
     94     SkBitmap skBitmap;
     95     bitmap->getSkBitmap(&skBitmap);
     96 
     97     // Create a software canvas.
     98     SkiaCanvas canvas(skBitmap);
     99     canvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
    100     // The result should be fully red, since we convert to sRGB at draw time.
    101     ASSERT_EQ(0xFF0000FF, *skBitmap.getAddr32(0, 0));
    102 
    103     // Create a software canvas with an Adobe color space.
    104     SkiaCanvas adobeSkCanvas(adobeSkBitmap);
    105     adobeSkCanvas.drawBitmap(*bitmap, 0, 0, nullptr);
    106     // The result should be less than fully red, since we convert to Adobe RGB at draw time.
    107     ASSERT_EQ(0xFF0000DC, *adobeSkBitmap.getAddr32(0, 0));
    108 
    109     // Test picture recording.
    110     SkPictureRecorder recorder;
    111     SkCanvas* skPicCanvas = recorder.beginRecording(1, 1, NULL, 0);
    112     SkiaCanvas picCanvas(skPicCanvas);
    113     picCanvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
    114     sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
    115 
    116     // Playback to an software canvas.  The result should be fully red.
    117     canvas.asSkCanvas()->drawPicture(picture);
    118     ASSERT_EQ(0xFF0000FF, *skBitmap.getAddr32(0, 0));
    119 }
    120 
    121 TEST(SkiaCanvas, captureCanvasState) {
    122     // Create a software canvas.
    123     SkImageInfo info = SkImageInfo::Make(1, 1, kN32_SkColorType, kOpaque_SkAlphaType);
    124     sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info);
    125     SkBitmap skBitmap;
    126     bitmap->getSkBitmap(&skBitmap);
    127     skBitmap.eraseColor(0);
    128     SkiaCanvas canvas(skBitmap);
    129 
    130     // Translate, then capture and verify the CanvasState.
    131     canvas.translate(1.0f, 1.0f);
    132     SkCanvasState* state = canvas.captureCanvasState();
    133     ASSERT_NE(state, nullptr);
    134     std::unique_ptr<SkCanvas> newCanvas = SkCanvasStateUtils::MakeFromCanvasState(state);
    135     ASSERT_NE(newCanvas.get(), nullptr);
    136     newCanvas->translate(-1.0f, -1.0f);
    137     ASSERT_TRUE(newCanvas->getTotalMatrix().isIdentity());
    138     SkCanvasStateUtils::ReleaseCanvasState(state);
    139 
    140     // Create a picture canvas.
    141     SkPictureRecorder recorder;
    142     SkCanvas* skPicCanvas = recorder.beginRecording(1, 1, NULL, 0);
    143     SkiaCanvas picCanvas(skPicCanvas);
    144     state = picCanvas.captureCanvasState();
    145 
    146     // Verify that we cannot get the CanvasState.
    147     ASSERT_EQ(state, nullptr);
    148 }
    149