halcanary | 05b48e2 | 2015-11-16 10:51:21 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2015 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #include "gm.h" |
Mike Klein | 33d2055 | 2017-03-22 13:47:51 -0400 | [diff] [blame] | 9 | #include "sk_tool_utils.h" |
halcanary | 05b48e2 | 2015-11-16 10:51:21 -0800 | [diff] [blame] | 10 | #include "SkImage.h" |
| 11 | #include "SkRRect.h" |
Mike Reed | 088b74e | 2018-12-24 14:52:46 -0500 | [diff] [blame] | 12 | #include "SkTextBlob.h" |
halcanary | 05b48e2 | 2015-11-16 10:51:21 -0800 | [diff] [blame] | 13 | |
| 14 | static void rotated_checkerboard_shader(SkPaint* paint, |
| 15 | SkColor c1, |
| 16 | SkColor c2, |
| 17 | int size) { |
| 18 | SkBitmap bm; |
| 19 | bm.allocN32Pixels(2 * size, 2 * size); |
| 20 | bm.eraseColor(c1); |
| 21 | bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2); |
| 22 | bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2); |
| 23 | SkMatrix matrix; |
| 24 | matrix.setScale(0.75f, 0.75f); |
| 25 | matrix.preRotate(30.0f); |
reed | 1a9b964 | 2016-03-13 14:13:58 -0700 | [diff] [blame] | 26 | paint->setShader( |
| 27 | SkShader::MakeBitmapShader(bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, |
| 28 | &matrix)); |
halcanary | 05b48e2 | 2015-11-16 10:51:21 -0800 | [diff] [blame] | 29 | } |
| 30 | |
| 31 | static void exercise_draw_pos_text(SkCanvas* canvas, |
| 32 | const char* text, |
| 33 | SkScalar x, SkScalar y, |
Mike Reed | 088b74e | 2018-12-24 14:52:46 -0500 | [diff] [blame] | 34 | const SkFont& font, const SkPaint& paint) { |
| 35 | const int count = font.countText(text, strlen(text), kUTF8_SkTextEncoding); |
| 36 | SkTextBlobBuilder builder; |
| 37 | auto rec = builder.allocRunPos(font, count); |
| 38 | font.textToGlyphs(text, strlen(text), kUTF8_SkTextEncoding, rec.glyphs, count); |
| 39 | font.getPos(rec.glyphs, count, (SkPoint*)rec.pos, {x, y}); |
| 40 | canvas->drawTextBlob(builder.make(), 0, 0, paint); |
halcanary | 05b48e2 | 2015-11-16 10:51:21 -0800 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | static void exercise_draw_pos_text_h(SkCanvas* canvas, |
| 44 | const char* text, |
| 45 | SkScalar x, SkScalar y, |
Mike Reed | 088b74e | 2018-12-24 14:52:46 -0500 | [diff] [blame] | 46 | const SkFont& font, const SkPaint& paint) { |
| 47 | const int count = font.countText(text, strlen(text), kUTF8_SkTextEncoding); |
| 48 | SkTextBlobBuilder builder; |
| 49 | auto rec = builder.allocRunPosH(font, count, 0); |
| 50 | font.textToGlyphs(text, strlen(text), kUTF8_SkTextEncoding, rec.glyphs, count); |
| 51 | font.getXPos(rec.glyphs, count, rec.pos); |
| 52 | canvas->drawTextBlob(builder.make(), x, y, paint); |
halcanary | 05b48e2 | 2015-11-16 10:51:21 -0800 | [diff] [blame] | 53 | } |
| 54 | |
| 55 | static void test_text(SkCanvas* canvas, SkScalar size, |
| 56 | SkColor color, SkScalar Y) { |
Mike Reed | 088b74e | 2018-12-24 14:52:46 -0500 | [diff] [blame] | 57 | SkFont font(sk_tool_utils::create_portable_typeface(), 24); |
| 58 | font.setEdging(SkFont::Edging::kAlias); |
halcanary | 05b48e2 | 2015-11-16 10:51:21 -0800 | [diff] [blame] | 59 | SkPaint type; |
halcanary | 05b48e2 | 2015-11-16 10:51:21 -0800 | [diff] [blame] | 60 | type.setColor(color); |
| 61 | const char text[] = "HELLO WORLD"; |
Mike Reed | 088b74e | 2018-12-24 14:52:46 -0500 | [diff] [blame] | 62 | canvas->drawSimpleText(text, strlen(text), kUTF8_SkTextEncoding, 32, size / 2 + Y, |
| 63 | font, type); |
| 64 | SkScalar lineSpacing = font.getSpacing(); |
| 65 | exercise_draw_pos_text(canvas, text, 32, size / 2 + Y + lineSpacing, font, type); |
halcanary | 05b48e2 | 2015-11-16 10:51:21 -0800 | [diff] [blame] | 66 | exercise_draw_pos_text_h(canvas, text, 32, |
Mike Reed | 088b74e | 2018-12-24 14:52:46 -0500 | [diff] [blame] | 67 | size / 2 + Y + 2 * lineSpacing, font, type); |
halcanary | 05b48e2 | 2015-11-16 10:51:21 -0800 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | // If this GM works correctly, the cyan layer should be lined up with |
| 71 | // the objects below it. |
| 72 | DEF_SIMPLE_GM(skbug_257, canvas, 512, 512) { |
| 73 | const SkScalar size = 256; |
| 74 | SkAutoCanvasRestore autoCanvasRestore0(canvas, true); |
| 75 | const SkScalar scale = 1.00168f; |
| 76 | canvas->scale(scale, scale); |
| 77 | { |
| 78 | SkPaint checker; |
| 79 | rotated_checkerboard_shader(&checker, SK_ColorWHITE, SK_ColorBLACK, 16); |
| 80 | checker.setAntiAlias(true); |
| 81 | |
| 82 | SkAutoCanvasRestore autoCanvasRestore(canvas, true); |
| 83 | canvas->clear(0xFFCECFCE); |
| 84 | SkScalar translate = 225364.0f; |
| 85 | canvas->translate(0, -translate); |
| 86 | |
| 87 | // Test rects |
| 88 | SkRect rect = SkRect::MakeLTRB(8, 8 + translate, size - 8, |
| 89 | size - 8 + translate); |
| 90 | canvas->drawRect(rect, checker); |
| 91 | |
| 92 | // Test Paths |
| 93 | canvas->translate(size, 0); |
| 94 | SkRRect rrect; |
| 95 | SkVector radii[4] = {{40, 40}, {40, 40}, {40, 40}, {40, 40}}; |
| 96 | rrect.setRectRadii(rect, radii); |
| 97 | canvas->drawRRect(rrect, checker); |
| 98 | |
| 99 | // Test Points |
| 100 | canvas->translate(-size, size); |
| 101 | SkScalar delta = 1.0 / 64.0; |
| 102 | SkPoint points[8] = {{size / 2, 8 + translate}, |
| 103 | {size / 2, 8 + translate + delta}, |
| 104 | {8, size / 2 + translate}, |
| 105 | {8, size / 2 + translate + delta}, |
| 106 | {size / 2, size - 8 + translate}, |
| 107 | {size / 2, size - 8 + translate + delta}, |
| 108 | {size - 8, size / 2 + translate}, |
| 109 | {size - 8, size / 2 + translate + delta}}; |
| 110 | checker.setStyle(SkPaint::kStroke_Style); |
| 111 | checker.setStrokeWidth(8); |
| 112 | checker.setStrokeCap(SkPaint::kRound_Cap); |
| 113 | canvas->drawPoints(SkCanvas::kLines_PointMode, 8, points, checker); |
| 114 | |
| 115 | // Test Text |
| 116 | canvas->translate(size, 0); |
| 117 | test_text(canvas, size, SK_ColorBLACK, translate); |
| 118 | } |
| 119 | // reference points (without the huge translations). |
| 120 | SkPaint stroke; |
| 121 | stroke.setStyle(SkPaint::kStroke_Style); |
| 122 | stroke.setStrokeWidth(5); |
| 123 | stroke.setColor(SK_ColorCYAN); |
| 124 | canvas->drawCircle(size / 2, size / 2, size / 2 - 10, stroke); |
| 125 | canvas->drawCircle(3 * size / 2, size / 2, size / 2 - 10, stroke); |
| 126 | canvas->drawCircle(size / 2, 384, size / 2 - 10, stroke); |
| 127 | canvas->translate(size, size); |
| 128 | test_text(canvas, size, SK_ColorCYAN, 0.0f); |
| 129 | } |