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" |
| 12 | |
| 13 | static void rotated_checkerboard_shader(SkPaint* paint, |
| 14 | SkColor c1, |
| 15 | SkColor c2, |
| 16 | int size) { |
| 17 | SkBitmap bm; |
| 18 | bm.allocN32Pixels(2 * size, 2 * size); |
| 19 | bm.eraseColor(c1); |
| 20 | bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2); |
| 21 | bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2); |
| 22 | SkMatrix matrix; |
| 23 | matrix.setScale(0.75f, 0.75f); |
| 24 | matrix.preRotate(30.0f); |
reed | 1a9b964 | 2016-03-13 14:13:58 -0700 | [diff] [blame] | 25 | paint->setShader( |
| 26 | SkShader::MakeBitmapShader(bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, |
| 27 | &matrix)); |
halcanary | 05b48e2 | 2015-11-16 10:51:21 -0800 | [diff] [blame] | 28 | } |
| 29 | |
| 30 | static void exercise_draw_pos_text(SkCanvas* canvas, |
| 31 | const char* text, |
| 32 | SkScalar x, SkScalar y, |
| 33 | const SkPaint& paint) { |
| 34 | size_t textLen = strlen(text); |
| 35 | int count = paint.countText(text, textLen); |
| 36 | SkAutoTArray<SkScalar> widths(count); |
| 37 | paint.getTextWidths(text, textLen, &widths[0]); |
| 38 | SkAutoTArray<SkPoint> pos(count); |
| 39 | for (int i = 0; i < count; ++i) { |
| 40 | pos[i].set(x, y); |
| 41 | x += widths[i]; |
| 42 | } |
| 43 | canvas->drawPosText(text, textLen, &pos[0], paint); |
| 44 | } |
| 45 | |
| 46 | static void exercise_draw_pos_text_h(SkCanvas* canvas, |
| 47 | const char* text, |
| 48 | SkScalar x, SkScalar y, |
| 49 | const SkPaint& paint) { |
| 50 | size_t textLen = strlen(text); |
| 51 | int count = paint.countText(text, textLen); |
| 52 | SkAutoTArray<SkScalar> widths(count); |
| 53 | paint.getTextWidths(text, textLen, &widths[0]); |
| 54 | SkAutoTArray<SkScalar> pos(count); |
| 55 | for (int i = 0; i < count; ++i) { |
| 56 | pos[i] = x; |
| 57 | x += widths[i]; |
| 58 | } |
| 59 | canvas->drawPosTextH(text, textLen, &pos[0], y, paint); |
| 60 | } |
| 61 | |
| 62 | static void test_text(SkCanvas* canvas, SkScalar size, |
| 63 | SkColor color, SkScalar Y) { |
| 64 | SkPaint type; |
| 65 | type.setTextSize(24); |
| 66 | sk_tool_utils::set_portable_typeface(&type); |
| 67 | type.setColor(color); |
| 68 | const char text[] = "HELLO WORLD"; |
Cary Clark | 2a475ea | 2017-04-28 15:35:12 -0400 | [diff] [blame] | 69 | canvas->drawString(text, 32, size / 2 + Y, type); |
halcanary | 05b48e2 | 2015-11-16 10:51:21 -0800 | [diff] [blame] | 70 | SkScalar lineSpacing = type.getFontSpacing(); |
| 71 | exercise_draw_pos_text(canvas, text, 32, size / 2 + Y + lineSpacing, type); |
| 72 | exercise_draw_pos_text_h(canvas, text, 32, |
| 73 | size / 2 + Y + 2 * lineSpacing, type); |
| 74 | } |
| 75 | |
| 76 | // If this GM works correctly, the cyan layer should be lined up with |
| 77 | // the objects below it. |
| 78 | DEF_SIMPLE_GM(skbug_257, canvas, 512, 512) { |
| 79 | const SkScalar size = 256; |
| 80 | SkAutoCanvasRestore autoCanvasRestore0(canvas, true); |
| 81 | const SkScalar scale = 1.00168f; |
| 82 | canvas->scale(scale, scale); |
| 83 | { |
| 84 | SkPaint checker; |
| 85 | rotated_checkerboard_shader(&checker, SK_ColorWHITE, SK_ColorBLACK, 16); |
| 86 | checker.setAntiAlias(true); |
| 87 | |
| 88 | SkAutoCanvasRestore autoCanvasRestore(canvas, true); |
| 89 | canvas->clear(0xFFCECFCE); |
| 90 | SkScalar translate = 225364.0f; |
| 91 | canvas->translate(0, -translate); |
| 92 | |
| 93 | // Test rects |
| 94 | SkRect rect = SkRect::MakeLTRB(8, 8 + translate, size - 8, |
| 95 | size - 8 + translate); |
| 96 | canvas->drawRect(rect, checker); |
| 97 | |
| 98 | // Test Paths |
| 99 | canvas->translate(size, 0); |
| 100 | SkRRect rrect; |
| 101 | SkVector radii[4] = {{40, 40}, {40, 40}, {40, 40}, {40, 40}}; |
| 102 | rrect.setRectRadii(rect, radii); |
| 103 | canvas->drawRRect(rrect, checker); |
| 104 | |
| 105 | // Test Points |
| 106 | canvas->translate(-size, size); |
| 107 | SkScalar delta = 1.0 / 64.0; |
| 108 | SkPoint points[8] = {{size / 2, 8 + translate}, |
| 109 | {size / 2, 8 + translate + delta}, |
| 110 | {8, size / 2 + translate}, |
| 111 | {8, size / 2 + translate + delta}, |
| 112 | {size / 2, size - 8 + translate}, |
| 113 | {size / 2, size - 8 + translate + delta}, |
| 114 | {size - 8, size / 2 + translate}, |
| 115 | {size - 8, size / 2 + translate + delta}}; |
| 116 | checker.setStyle(SkPaint::kStroke_Style); |
| 117 | checker.setStrokeWidth(8); |
| 118 | checker.setStrokeCap(SkPaint::kRound_Cap); |
| 119 | canvas->drawPoints(SkCanvas::kLines_PointMode, 8, points, checker); |
| 120 | |
| 121 | // Test Text |
| 122 | canvas->translate(size, 0); |
| 123 | test_text(canvas, size, SK_ColorBLACK, translate); |
| 124 | } |
| 125 | // reference points (without the huge translations). |
| 126 | SkPaint stroke; |
| 127 | stroke.setStyle(SkPaint::kStroke_Style); |
| 128 | stroke.setStrokeWidth(5); |
| 129 | stroke.setColor(SK_ColorCYAN); |
| 130 | canvas->drawCircle(size / 2, size / 2, size / 2 - 10, stroke); |
| 131 | canvas->drawCircle(3 * size / 2, size / 2, size / 2 - 10, stroke); |
| 132 | canvas->drawCircle(size / 2, 384, size / 2 - 10, stroke); |
| 133 | canvas->translate(size, size); |
| 134 | test_text(canvas, size, SK_ColorCYAN, 0.0f); |
| 135 | } |