1fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
2fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com/*
3fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com * Copyright 2011 Google Inc.
4fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com *
5fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
6fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com * found in the LICENSE file.
7fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com */
8fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com#include "gm.h"
9fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com#include "SkCanvas.h"
10fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com#include "SkPaint.h"
112880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkPath.h"
12fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com#include "SkRandom.h"
13fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
14fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comnamespace skiagm {
15fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
16fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comclass EmptyPathGM : public GM {
17fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.compublic:
18fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    EmptyPathGM() {}
19fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
20fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comprotected:
21fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    SkString onShortName() {
22fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        return SkString("emptypath");
23fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
24ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
25f539318f0d3dba743ec1886d5d9df0fb1be628a1tfarina    SkISize onISize() { return SkISize::Make(600, 280); }
26fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
27fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    void drawEmpty(SkCanvas* canvas,
28fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                    SkColor color,
29fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                    const SkRect& clip,
30fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                    SkPaint::Style style,
31fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                    SkPath::FillType fill) {
32fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        SkPath path;
33fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        path.setFillType(fill);
34fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        SkPaint paint;
35fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        paint.setColor(color);
36fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        paint.setStyle(style);
37fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        canvas->save();
38fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        canvas->clipRect(clip);
39fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        canvas->drawPath(path, paint);
40fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        canvas->restore();
41fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
42ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
43fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    virtual void onDraw(SkCanvas* canvas) {
44fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        struct FillAndName {
45fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            SkPath::FillType fFill;
46fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            const char*      fName;
47fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        };
48fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        static const FillAndName gFills[] = {
49fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            {SkPath::kWinding_FillType, "Winding"},
50fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            {SkPath::kEvenOdd_FillType, "Even / Odd"},
51fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            {SkPath::kInverseWinding_FillType, "Inverse Winding"},
52fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
53fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        };
54fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        struct StyleAndName {
55fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            SkPaint::Style fStyle;
56fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            const char*    fName;
57fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        };
58fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        static const StyleAndName gStyles[] = {
59fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            {SkPaint::kFill_Style, "Fill"},
60fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            {SkPaint::kStroke_Style, "Stroke"},
61fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
62fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        };
63fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
64fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        SkPaint titlePaint;
65fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        titlePaint.setColor(SK_ColorBLACK);
66fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        titlePaint.setAntiAlias(true);
672880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        sk_tool_utils::set_portable_typeface(&titlePaint);
68fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        titlePaint.setTextSize(15 * SK_Scalar1);
69fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        const char title[] = "Empty Paths Drawn Into Rectangle Clips With "
70fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                             "Indicated Style and Fill";
71fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        canvas->drawText(title, strlen(title),
72fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                            20 * SK_Scalar1,
73fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                            20 * SK_Scalar1,
74fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                            titlePaint);
75fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
76f9d610179d7d4198b57b12d06f8d1ca09f580df3scroggo        SkRandom rand;
77fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
78fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        int i = 0;
79fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        canvas->save();
80fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        canvas->translate(10 * SK_Scalar1, 0);
81fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        canvas->save();
82f12449b5d2867ca653aa53ac58fc1148e7f0b636bsalomon@google.com        for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
83f12449b5d2867ca653aa53ac58fc1148e7f0b636bsalomon@google.com            for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
84fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                if (0 == i % 4) {
85fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                    canvas->restore();
86fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                    canvas->translate(0, rect.height() + 40 * SK_Scalar1);
87fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                    canvas->save();
88fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                } else {
89fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                    canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
90fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                }
91fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                ++i;
92fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
93fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
94fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                SkColor color = rand.nextU();
95d85093c28fe360650c46971b00a39c6dbf991a6bcaryclark                color = 0xff000000 | color; // force solid
9665cdba6ba78aaec0c0a4596bb5941020c789482bcaryclark                color = sk_tool_utils::color_to_565(color);
97fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                this->drawEmpty(canvas, color, rect,
98fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                                gStyles[style].fStyle, gFills[fill].fFill);
99fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
100fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                SkPaint rectPaint;
101fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                rectPaint.setColor(SK_ColorBLACK);
102fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                rectPaint.setStyle(SkPaint::kStroke_Style);
103fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                rectPaint.setStrokeWidth(-1);
104fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                rectPaint.setAntiAlias(true);
105fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                canvas->drawRect(rect, rectPaint);
106fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
107fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                SkPaint labelPaint;
108fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                labelPaint.setColor(color);
109fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                labelPaint.setAntiAlias(true);
1102880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                sk_tool_utils::set_portable_typeface(&labelPaint);
111fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                labelPaint.setTextSize(12 * SK_Scalar1);
112fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                canvas->drawText(gStyles[style].fName,
113fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                                 strlen(gStyles[style].fName),
114fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                                 0, rect.height() + 15 * SK_Scalar1,
115fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                                 labelPaint);
116fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                canvas->drawText(gFills[fill].fName,
117fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                                 strlen(gFills[fill].fName),
118fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                                 0, rect.height() + 28 * SK_Scalar1,
119fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com                                 labelPaint);
120fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            }
121fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
122fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        canvas->restore();
123fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        canvas->restore();
124fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
125ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
126fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comprivate:
127fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    typedef GM INHERITED;
128fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com};
1292880df2609eba09b555ca37be04b6ad89290c765Tom HudsonDEF_GM( return new EmptyPathGM; )
130fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
131fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com//////////////////////////////////////////////////////////////////////////////
132fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1332880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonstatic void make_path_move(SkPath* path, const SkPoint pts[3]) {
1342880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    for (int i = 0; i < 3; ++i) {
1352880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        path->moveTo(pts[i]);
1362880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
1372880df2609eba09b555ca37be04b6ad89290c765Tom Hudson}
1382880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1392880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonstatic void make_path_move_close(SkPath* path, const SkPoint pts[3]) {
1402880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    for (int i = 0; i < 3; ++i) {
1412880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        path->moveTo(pts[i]);
1422880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        path->close();
1432880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
1442880df2609eba09b555ca37be04b6ad89290c765Tom Hudson}
1452880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1462880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonstatic void make_path_move_line(SkPath* path, const SkPoint pts[3]) {
1472880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    for (int i = 0; i < 3; ++i) {
1482880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        path->moveTo(pts[i]);
1492880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        path->lineTo(pts[i]);
1502880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
1512880df2609eba09b555ca37be04b6ad89290c765Tom Hudson}
1522880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1532880df2609eba09b555ca37be04b6ad89290c765Tom Hudsontypedef void (*MakePathProc)(SkPath*, const SkPoint pts[3]);
1542880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1552880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonstatic void make_path_move_mix(SkPath* path, const SkPoint pts[3]) {
1562880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    path->moveTo(pts[0]);
1572880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    path->moveTo(pts[1]); path->close();
1582880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    path->moveTo(pts[2]); path->lineTo(pts[2]);
1592880df2609eba09b555ca37be04b6ad89290c765Tom Hudson}
1602880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1612880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonclass EmptyStrokeGM : public GM {
1622880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    SkPoint fPts[3];
1632880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1642880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonpublic:
1652880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    EmptyStrokeGM() {
1662880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        fPts[0].set(40, 40);
1672880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        fPts[1].set(80, 40);
1682880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        fPts[2].set(120, 40);
1692880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
1702880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1712880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonprotected:
1722880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    SkString onShortName() override {
1732880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        return SkString("emptystroke");
1742880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
1752880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1762880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    SkISize onISize() override { return SkISize::Make(200, 240); }
1772880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1782880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    void onDraw(SkCanvas* canvas) override {
1792880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        const MakePathProc procs[] = {
1802880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            make_path_move,             // expect red red red
1812880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            make_path_move_close,       // expect black black black
1822880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            make_path_move_line,        // expect black black black
1832880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            make_path_move_mix,         // expect red black black,
1842880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        };
1852880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1862880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkPaint strokePaint;
1872880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        strokePaint.setStyle(SkPaint::kStroke_Style);
1882880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        strokePaint.setStrokeWidth(21);
1892880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        strokePaint.setStrokeCap(SkPaint::kSquare_Cap);
1902880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1912880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkPaint dotPaint;
1922880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        dotPaint.setColor(SK_ColorRED);
1932880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        strokePaint.setStyle(SkPaint::kStroke_Style);
1942880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        dotPaint.setStrokeWidth(7);
1952880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1962880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) {
1972880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            SkPath path;
1982880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            procs[i](&path, fPts);
1992880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, fPts, dotPaint);
2002880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            canvas->drawPath(path, strokePaint);
2012880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            canvas->translate(0, 40);
2022880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        }
2032880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
2042880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
2052880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonprivate:
2062880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    typedef GM INHERITED;
2072880df2609eba09b555ca37be04b6ad89290c765Tom Hudson};
2082880df2609eba09b555ca37be04b6ad89290c765Tom HudsonDEF_GM( return new EmptyStrokeGM; )
209fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
210fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
211