1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2014 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gm.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "sk_tool_utils.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPoint.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTextBlob.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTDArray.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotnamespace  {
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotenum Pos {
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kDefault_Pos = 0,
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kScalar_Pos  = 1,
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kPoint_Pos   = 2,
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst struct BlobCfg {
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    unsigned count;
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Pos      pos;
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar scale;
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} blobConfigs[][3][3] = {
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    {
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 1024, kDefault_Pos, 1 }, { 0, kDefault_Pos, 0 }, { 0, kDefault_Pos, 0 } },
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 1024,  kScalar_Pos, 1 }, { 0,  kScalar_Pos, 0 }, { 0,  kScalar_Pos, 0 } },
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 1024,   kPoint_Pos, 1 }, { 0,   kPoint_Pos, 0 }, { 0,   kPoint_Pos, 0 } },
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    },
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    {
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4, kDefault_Pos, 1 },     { 4, kDefault_Pos, 1 },  { 4, kDefault_Pos, 1 } },
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4,  kScalar_Pos, 1 },     { 4,  kScalar_Pos, 1 },  { 4,  kScalar_Pos, 1 } },
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4,   kPoint_Pos, 1 },     { 4,   kPoint_Pos, 1 },  { 4,   kPoint_Pos, 1 } },
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    },
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    {
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4, kDefault_Pos, 1 },     { 4, kDefault_Pos, 1 },  { 4,  kScalar_Pos, 1 } },
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4,  kScalar_Pos, 1 },     { 4,  kScalar_Pos, 1 },  { 4,   kPoint_Pos, 1 } },
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4,   kPoint_Pos, 1 },     { 4,   kPoint_Pos, 1 },  { 4, kDefault_Pos, 1 } },
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    },
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    {
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4, kDefault_Pos, 1 },     { 4,  kScalar_Pos, 1 },  { 4,   kPoint_Pos, 1 } },
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4,  kScalar_Pos, 1 },     { 4,   kPoint_Pos, 1 },  { 4, kDefault_Pos, 1 } },
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4,   kPoint_Pos, 1 },     { 4, kDefault_Pos, 1 },  { 4,  kScalar_Pos, 1 } },
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    },
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    {
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4, kDefault_Pos, .75f },     { 4, kDefault_Pos, 1 },  { 4,  kScalar_Pos, 1.25f } },
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4,  kScalar_Pos, .75f },     { 4,  kScalar_Pos, 1 },  { 4,   kPoint_Pos, 1.25f } },
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4,   kPoint_Pos, .75f },     { 4,   kPoint_Pos, 1 },  { 4, kDefault_Pos, 1.25f } },
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    },
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    {
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4, kDefault_Pos, 1 },     { 4,  kScalar_Pos, .75f },  { 4,   kPoint_Pos, 1.25f } },
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4,  kScalar_Pos, 1 },     { 4,   kPoint_Pos, .75f },  { 4, kDefault_Pos, 1.25f } },
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { { 4,   kPoint_Pos, 1 },     { 4, kDefault_Pos, .75f },  { 4,  kScalar_Pos, 1.25f } },
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    },
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkScalar kFontSize = 16;
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass TextBlobGM : public skiagm::GM {
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextBlobGM(const char* txt)
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : fText(txt) {
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onOnceBeforeDraw() override {
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fTypeface = sk_tool_utils::create_portable_typeface("serif", SkFontStyle());
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint p;
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p.setTypeface(fTypeface);
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        size_t txtLen = strlen(fText);
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int glyphCount = p.textToGlyphs(fText, txtLen, nullptr);
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fGlyphs.append(glyphCount);
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p.textToGlyphs(fText, txtLen, fGlyphs.begin());
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString onShortName() override {
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkString("textblob");
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkISize onISize() override {
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkISize::Make(640, 480);
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onDraw(SkCanvas* canvas) override {
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (unsigned b = 0; b < SK_ARRAY_COUNT(blobConfigs); ++b) {
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_sp<SkTextBlob> blob(this->makeBlob(b));
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkPaint p;
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkPoint offset = SkPoint::Make(SkIntToScalar(10 + 300 * (b % 2)),
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           SkIntToScalar(20 + 150 * (b / 2)));
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawTextBlob(blob, offset.x(), offset.y(), p);
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p.setColor(SK_ColorBLUE);
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p.setStyle(SkPaint::kStroke_Style);
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkRect box = blob->bounds();
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            box.offset(offset);
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawRect(box, p);
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkTextBlob> makeBlob(unsigned blobIndex) {
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkTextBlobBuilder builder;
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint font;
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setAntiAlias(true);
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setSubpixelText(true);
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setTypeface(fTypeface);
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (unsigned l = 0; l < SK_ARRAY_COUNT(blobConfigs[blobIndex]); ++l) {
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            unsigned currentGlyph = 0;
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (unsigned c = 0; c < SK_ARRAY_COUNT(blobConfigs[blobIndex][l]); ++c) {
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const BlobCfg* cfg = &blobConfigs[blobIndex][l][c];
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                unsigned count = cfg->count;
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (count > fGlyphs.count() - currentGlyph) {
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    count = fGlyphs.count() - currentGlyph;
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (0 == count) {
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                font.setTextSize(kFontSize * cfg->scale);
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const SkScalar advanceX = font.getTextSize() * 0.85f;
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const SkScalar advanceY = font.getTextSize() * 1.5f;
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkPoint offset = SkPoint::Make(currentGlyph * advanceX + c * advanceX,
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               advanceY * l);
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                switch (cfg->pos) {
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case kDefault_Pos: {
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    const SkTextBlobBuilder::RunBuffer& buf = builder.allocRun(font, count,
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                               offset.x(),
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                               offset.y());
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } break;
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case kScalar_Pos: {
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPosH(font, count,
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                                   offset.y());
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkTDArray<SkScalar> pos;
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    for (unsigned i = 0; i < count; ++i) {
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        *pos.append() = offset.x() + i * advanceX;
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar));
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } break;
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case kPoint_Pos: {
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPos(font, count);
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkTDArray<SkScalar> pos;
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    for (unsigned i = 0; i < count; ++i) {
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        *pos.append() = offset.x() + i * advanceX;
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        *pos.append() = offset.y() + i * (advanceY / count);
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar) * 2);
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } break;
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                default:
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SK_ABORT("unhandled pos value");
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                currentGlyph += count;
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return builder.make();
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTDArray<uint16_t> fGlyphs;
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkTypeface>   fTypeface;
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char*         fText;
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef skiagm::GM INHERITED;
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_GM(return new TextBlobGM("hamburgefons");)
191