aboutsummaryrefslogtreecommitdiffhomepage
path: root/gm/skbug_257.cpp
blob: 91c0a1665ef38253f95270e3556a2e8f397b1cbd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "sk_tool_utils.h"
#include "SkImage.h"
#include "SkRRect.h"

static void rotated_checkerboard_shader(SkPaint* paint,
                                        SkColor c1,
                                        SkColor c2,
                                        int size) {
    SkBitmap bm;
    bm.allocN32Pixels(2 * size, 2 * size);
    bm.eraseColor(c1);
    bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2);
    bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2);
    SkMatrix matrix;
    matrix.setScale(0.75f, 0.75f);
    matrix.preRotate(30.0f);
    paint->setShader(
            SkShader::MakeBitmapShader(bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode,
                                       &matrix));
}

static void exercise_draw_pos_text(SkCanvas* canvas,
                                   const char* text,
                                   SkScalar x, SkScalar y,
                                   const SkPaint& paint) {
    size_t textLen = strlen(text);
    int count = paint.countText(text, textLen);
    SkAutoTArray<SkScalar> widths(count);
    paint.getTextWidths(text, textLen, &widths[0]);
    SkAutoTArray<SkPoint> pos(count);
    for (int i = 0; i < count; ++i) {
        pos[i].set(x, y);
        x += widths[i];
    }
    canvas->drawPosText(text, textLen, &pos[0], paint);
}

static void exercise_draw_pos_text_h(SkCanvas* canvas,
                                     const char* text,
                                     SkScalar x, SkScalar y,
                                     const SkPaint& paint) {
    size_t textLen = strlen(text);
    int count = paint.countText(text, textLen);
    SkAutoTArray<SkScalar> widths(count);
    paint.getTextWidths(text, textLen, &widths[0]);
    SkAutoTArray<SkScalar> pos(count);
    for (int i = 0; i < count; ++i) {
        pos[i] = x;
        x += widths[i];
    }
    canvas->drawPosTextH(text, textLen, &pos[0], y, paint);
}

static void test_text(SkCanvas* canvas, SkScalar size,
                      SkColor color, SkScalar Y) {
    SkPaint type;
    type.setTextSize(24);
    sk_tool_utils::set_portable_typeface(&type);
    type.setColor(color);
    const char text[] = "HELLO WORLD";
    canvas->drawString(text, 32, size / 2 + Y, type);
    SkScalar lineSpacing = type.getFontSpacing();
    exercise_draw_pos_text(canvas, text, 32, size / 2 + Y + lineSpacing, type);
    exercise_draw_pos_text_h(canvas, text, 32,
                             size / 2 + Y + 2 * lineSpacing, type);
}

// If this GM works correctly, the cyan layer should be lined up with
// the objects below it.
DEF_SIMPLE_GM(skbug_257, canvas, 512, 512) {
    const SkScalar size = 256;
    SkAutoCanvasRestore autoCanvasRestore0(canvas, true);
    const SkScalar scale = 1.00168f;
    canvas->scale(scale, scale);
    {
        SkPaint checker;
        rotated_checkerboard_shader(&checker, SK_ColorWHITE, SK_ColorBLACK, 16);
        checker.setAntiAlias(true);

        SkAutoCanvasRestore autoCanvasRestore(canvas, true);
        canvas->clear(0xFFCECFCE);
        SkScalar translate = 225364.0f;
        canvas->translate(0, -translate);

        // Test rects
        SkRect rect = SkRect::MakeLTRB(8, 8 + translate, size - 8,
                                       size - 8 + translate);
        canvas->drawRect(rect, checker);

        // Test Paths
        canvas->translate(size, 0);
        SkRRect rrect;
        SkVector radii[4] = {{40, 40}, {40, 40}, {40, 40}, {40, 40}};
        rrect.setRectRadii(rect, radii);
        canvas->drawRRect(rrect, checker);

        // Test Points
        canvas->translate(-size, size);
        SkScalar delta = 1.0 / 64.0;
        SkPoint points[8] = {{size / 2, 8 + translate},
                             {size / 2, 8 + translate + delta},
                             {8, size / 2 + translate},
                             {8, size / 2 + translate + delta},
                             {size / 2, size - 8 + translate},
                             {size / 2, size - 8 + translate + delta},
                             {size - 8, size / 2 + translate},
                             {size - 8, size / 2 + translate + delta}};
        checker.setStyle(SkPaint::kStroke_Style);
        checker.setStrokeWidth(8);
        checker.setStrokeCap(SkPaint::kRound_Cap);
        canvas->drawPoints(SkCanvas::kLines_PointMode, 8, points, checker);

        // Test Text
        canvas->translate(size, 0);
        test_text(canvas, size, SK_ColorBLACK, translate);
    }
    // reference points (without the huge translations).
    SkPaint stroke;
    stroke.setStyle(SkPaint::kStroke_Style);
    stroke.setStrokeWidth(5);
    stroke.setColor(SK_ColorCYAN);
    canvas->drawCircle(size / 2, size / 2, size / 2 - 10, stroke);
    canvas->drawCircle(3 * size / 2, size / 2, size / 2 - 10, stroke);
    canvas->drawCircle(size / 2, 384, size / 2 - 10, stroke);
    canvas->translate(size, size);
    test_text(canvas, size, SK_ColorCYAN, 0.0f);
}