105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary/* 205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary * Copyright 2015 Google Inc. 305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary * 405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary * Use of this source code is governed by a BSD-style license that can be 505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary * found in the LICENSE file. 605b48e2a24ae78312c80ed94195f0b705fdb0547halcanary */ 705b48e2a24ae78312c80ed94195f0b705fdb0547halcanary 805b48e2a24ae78312c80ed94195f0b705fdb0547halcanary#include "gm.h" 933d2055e594177b27360f84e0631b26d74a55a9bMike Klein#include "sk_tool_utils.h" 1005b48e2a24ae78312c80ed94195f0b705fdb0547halcanary#include "SkImage.h" 1105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary#include "SkRRect.h" 1205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary 1305b48e2a24ae78312c80ed94195f0b705fdb0547halcanarystatic void rotated_checkerboard_shader(SkPaint* paint, 1405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkColor c1, 1505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkColor c2, 1605b48e2a24ae78312c80ed94195f0b705fdb0547halcanary int size) { 1705b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkBitmap bm; 1805b48e2a24ae78312c80ed94195f0b705fdb0547halcanary bm.allocN32Pixels(2 * size, 2 * size); 1905b48e2a24ae78312c80ed94195f0b705fdb0547halcanary bm.eraseColor(c1); 2005b48e2a24ae78312c80ed94195f0b705fdb0547halcanary bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2); 2105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2); 2205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkMatrix matrix; 2305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary matrix.setScale(0.75f, 0.75f); 2405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary matrix.preRotate(30.0f); 251a9b9640843a64af8d9d90337ec3b3fea663196areed paint->setShader( 261a9b9640843a64af8d9d90337ec3b3fea663196areed SkShader::MakeBitmapShader(bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, 271a9b9640843a64af8d9d90337ec3b3fea663196areed &matrix)); 2805b48e2a24ae78312c80ed94195f0b705fdb0547halcanary} 2905b48e2a24ae78312c80ed94195f0b705fdb0547halcanary 3005b48e2a24ae78312c80ed94195f0b705fdb0547halcanarystatic void exercise_draw_pos_text(SkCanvas* canvas, 3105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary const char* text, 3205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkScalar x, SkScalar y, 3305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary const SkPaint& paint) { 3405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary size_t textLen = strlen(text); 3505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary int count = paint.countText(text, textLen); 3605b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkAutoTArray<SkScalar> widths(count); 3705b48e2a24ae78312c80ed94195f0b705fdb0547halcanary paint.getTextWidths(text, textLen, &widths[0]); 3805b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkAutoTArray<SkPoint> pos(count); 3905b48e2a24ae78312c80ed94195f0b705fdb0547halcanary for (int i = 0; i < count; ++i) { 4005b48e2a24ae78312c80ed94195f0b705fdb0547halcanary pos[i].set(x, y); 4105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary x += widths[i]; 4205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary } 4305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->drawPosText(text, textLen, &pos[0], paint); 4405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary} 4505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary 4605b48e2a24ae78312c80ed94195f0b705fdb0547halcanarystatic void exercise_draw_pos_text_h(SkCanvas* canvas, 4705b48e2a24ae78312c80ed94195f0b705fdb0547halcanary const char* text, 4805b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkScalar x, SkScalar y, 4905b48e2a24ae78312c80ed94195f0b705fdb0547halcanary const SkPaint& paint) { 5005b48e2a24ae78312c80ed94195f0b705fdb0547halcanary size_t textLen = strlen(text); 5105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary int count = paint.countText(text, textLen); 5205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkAutoTArray<SkScalar> widths(count); 5305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary paint.getTextWidths(text, textLen, &widths[0]); 5405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkAutoTArray<SkScalar> pos(count); 5505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary for (int i = 0; i < count; ++i) { 5605b48e2a24ae78312c80ed94195f0b705fdb0547halcanary pos[i] = x; 5705b48e2a24ae78312c80ed94195f0b705fdb0547halcanary x += widths[i]; 5805b48e2a24ae78312c80ed94195f0b705fdb0547halcanary } 5905b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->drawPosTextH(text, textLen, &pos[0], y, paint); 6005b48e2a24ae78312c80ed94195f0b705fdb0547halcanary} 6105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary 6205b48e2a24ae78312c80ed94195f0b705fdb0547halcanarystatic void test_text(SkCanvas* canvas, SkScalar size, 6305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkColor color, SkScalar Y) { 6405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkPaint type; 6505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary type.setTextSize(24); 6605b48e2a24ae78312c80ed94195f0b705fdb0547halcanary sk_tool_utils::set_portable_typeface(&type); 6705b48e2a24ae78312c80ed94195f0b705fdb0547halcanary type.setColor(color); 6805b48e2a24ae78312c80ed94195f0b705fdb0547halcanary const char text[] = "HELLO WORLD"; 6905b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->drawText(text, strlen(text), 32, size / 2 + Y, type); 7005b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkScalar lineSpacing = type.getFontSpacing(); 7105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary exercise_draw_pos_text(canvas, text, 32, size / 2 + Y + lineSpacing, type); 7205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary exercise_draw_pos_text_h(canvas, text, 32, 7305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary size / 2 + Y + 2 * lineSpacing, type); 7405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary} 7505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary 7605b48e2a24ae78312c80ed94195f0b705fdb0547halcanary// If this GM works correctly, the cyan layer should be lined up with 7705b48e2a24ae78312c80ed94195f0b705fdb0547halcanary// the objects below it. 7805b48e2a24ae78312c80ed94195f0b705fdb0547halcanaryDEF_SIMPLE_GM(skbug_257, canvas, 512, 512) { 7905b48e2a24ae78312c80ed94195f0b705fdb0547halcanary const SkScalar size = 256; 8005b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkAutoCanvasRestore autoCanvasRestore0(canvas, true); 8105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary const SkScalar scale = 1.00168f; 8205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->scale(scale, scale); 8305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary { 8405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkPaint checker; 8505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary rotated_checkerboard_shader(&checker, SK_ColorWHITE, SK_ColorBLACK, 16); 8605b48e2a24ae78312c80ed94195f0b705fdb0547halcanary checker.setAntiAlias(true); 8705b48e2a24ae78312c80ed94195f0b705fdb0547halcanary 8805b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkAutoCanvasRestore autoCanvasRestore(canvas, true); 8905b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->clear(0xFFCECFCE); 9005b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkScalar translate = 225364.0f; 9105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->translate(0, -translate); 9205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary 9305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary // Test rects 9405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkRect rect = SkRect::MakeLTRB(8, 8 + translate, size - 8, 9505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary size - 8 + translate); 9605b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->drawRect(rect, checker); 9705b48e2a24ae78312c80ed94195f0b705fdb0547halcanary 9805b48e2a24ae78312c80ed94195f0b705fdb0547halcanary // Test Paths 9905b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->translate(size, 0); 10005b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkRRect rrect; 10105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkVector radii[4] = {{40, 40}, {40, 40}, {40, 40}, {40, 40}}; 10205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary rrect.setRectRadii(rect, radii); 10305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->drawRRect(rrect, checker); 10405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary 10505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary // Test Points 10605b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->translate(-size, size); 10705b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkScalar delta = 1.0 / 64.0; 10805b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkPoint points[8] = {{size / 2, 8 + translate}, 10905b48e2a24ae78312c80ed94195f0b705fdb0547halcanary {size / 2, 8 + translate + delta}, 11005b48e2a24ae78312c80ed94195f0b705fdb0547halcanary {8, size / 2 + translate}, 11105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary {8, size / 2 + translate + delta}, 11205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary {size / 2, size - 8 + translate}, 11305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary {size / 2, size - 8 + translate + delta}, 11405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary {size - 8, size / 2 + translate}, 11505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary {size - 8, size / 2 + translate + delta}}; 11605b48e2a24ae78312c80ed94195f0b705fdb0547halcanary checker.setStyle(SkPaint::kStroke_Style); 11705b48e2a24ae78312c80ed94195f0b705fdb0547halcanary checker.setStrokeWidth(8); 11805b48e2a24ae78312c80ed94195f0b705fdb0547halcanary checker.setStrokeCap(SkPaint::kRound_Cap); 11905b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->drawPoints(SkCanvas::kLines_PointMode, 8, points, checker); 12005b48e2a24ae78312c80ed94195f0b705fdb0547halcanary 12105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary // Test Text 12205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->translate(size, 0); 12305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary test_text(canvas, size, SK_ColorBLACK, translate); 12405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary } 12505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary // reference points (without the huge translations). 12605b48e2a24ae78312c80ed94195f0b705fdb0547halcanary SkPaint stroke; 12705b48e2a24ae78312c80ed94195f0b705fdb0547halcanary stroke.setStyle(SkPaint::kStroke_Style); 12805b48e2a24ae78312c80ed94195f0b705fdb0547halcanary stroke.setStrokeWidth(5); 12905b48e2a24ae78312c80ed94195f0b705fdb0547halcanary stroke.setColor(SK_ColorCYAN); 13005b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->drawCircle(size / 2, size / 2, size / 2 - 10, stroke); 13105b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->drawCircle(3 * size / 2, size / 2, size / 2 - 10, stroke); 13205b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->drawCircle(size / 2, 384, size / 2 - 10, stroke); 13305b48e2a24ae78312c80ed94195f0b705fdb0547halcanary canvas->translate(size, size); 13405b48e2a24ae78312c80ed94195f0b705fdb0547halcanary test_text(canvas, size, SK_ColorCYAN, 0.0f); 13505b48e2a24ae78312c80ed94195f0b705fdb0547halcanary} 136