1/*
2 * Copyright 2011 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 "SampleCode.h"
9#include "SkView.h"
10#include "SkCanvas.h"
11#include "SkReadBuffer.h"
12#include "SkWriteBuffer.h"
13#include "SkGradientShader.h"
14#include "SkGraphics.h"
15#include "SkImageDecoder.h"
16#include "SkPath.h"
17#include "SkRandom.h"
18#include "SkRegion.h"
19#include "SkShader.h"
20#include "SkUtils.h"
21#include "SkColorPriv.h"
22#include "SkColorFilter.h"
23#include "SkTime.h"
24#include "SkTypeface.h"
25#include "SkXfermode.h"
26
27#include "SkStream.h"
28#include "SkXMLParser.h"
29
30static void test_breakText() {
31    SkPaint paint;
32    const char* text = "sdfkljAKLDFJKEWkldfjlk#$%&sdfs.dsj";
33    size_t length = strlen(text);
34    SkScalar width = paint.measureText(text, length);
35
36    SkScalar mm = 0;
37    SkScalar nn = 0;
38    for (SkScalar w = 0; w <= width; w += SK_Scalar1) {
39        SkScalar m;
40        size_t n = paint.breakText(text, length, w, &m);
41
42        SkASSERT(n <= length);
43        SkASSERT(m <= width);
44
45        if (n == 0) {
46            SkASSERT(m == 0);
47        } else {
48            // now assert that we're monotonic
49            if (n == nn) {
50                SkASSERT(m == mm);
51            } else {
52                SkASSERT(n > nn);
53                SkASSERT(m > mm);
54            }
55        }
56        nn = SkIntToScalar((unsigned int)n);
57        mm = m;
58    }
59
60    SkDEBUGCODE(size_t length2 =) paint.breakText(text, length, width, &mm);
61    SkASSERT(length2 == length);
62    SkASSERT(mm == width);
63}
64
65static const struct {
66    const char* fName;
67    uint32_t    fFlags;
68    bool        fFlushCache;
69} gHints[] = {
70    { "Linear", SkPaint::kLinearText_Flag,     false },
71    { "Normal",   0,                           true },
72    { "Subpixel", SkPaint::kSubpixelText_Flag, true }
73};
74
75static void DrawTheText(SkCanvas* canvas, const char text[], size_t length, SkScalar x, SkScalar y,
76                        const SkPaint& paint, SkScalar clickX) {
77    SkPaint p(paint);
78
79#if 0
80    canvas->drawText(text, length, x, y, paint);
81#else
82    {
83        SkPoint pts[1000];
84        SkScalar xpos = x;
85        SkASSERT(length <= SK_ARRAY_COUNT(pts));
86        for (size_t i = 0; i < length; i++) {
87            pts[i].set(xpos, y), xpos += paint.getTextSize();
88        }
89        canvas->drawPosText(text, length, pts, paint);
90    }
91#endif
92
93    p.setSubpixelText(true);
94    x += SkIntToScalar(180);
95    canvas->drawText(text, length, x, y, p);
96
97#ifdef SK_DEBUG
98    if (true) {
99        p.setSubpixelText(false);
100        p.setLinearText(true);
101        x += SkIntToScalar(180);
102        canvas->drawText(text, length, x, y, p);
103    }
104#endif
105}
106
107class TextSpeedView : public SampleView {
108public:
109    TextSpeedView() {
110        fHints = 0;
111        fClickX = 0;
112
113        test_breakText();
114    }
115
116protected:
117    // overrides from SkEventSink
118    bool onQuery(SkEvent* evt) override {
119        if (SampleCode::TitleQ(*evt)) {
120            SampleCode::TitleR(evt, "Text");
121            return true;
122        }
123        return this->INHERITED::onQuery(evt);
124    }
125
126    static void make_textstrip(SkBitmap* bm) {
127        bm->allocPixels(SkImageInfo::Make(200, 18, kRGB_565_SkColorType,
128                                          kOpaque_SkAlphaType));
129        bm->eraseColor(SK_ColorWHITE);
130
131        SkCanvas    canvas(*bm);
132        SkPaint     paint;
133        const char* s = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit";
134
135        paint.setFlags(paint.getFlags() | SkPaint::kAntiAlias_Flag
136                                        | SkPaint::kDevKernText_Flag);
137        paint.setTextSize(SkIntToScalar(14));
138        canvas.drawText(s, strlen(s), SkIntToScalar(8), SkIntToScalar(14), paint);
139    }
140
141    static void fill_pts(SkPoint pts[], size_t n, SkRandom* rand) {
142        for (size_t i = 0; i < n; i++)
143            pts[i].set(rand->nextUScalar1() * 640, rand->nextUScalar1() * 480);
144    }
145
146    void onDrawContent(SkCanvas* canvas) override {
147        SkAutoCanvasRestore restore(canvas, false);
148        {
149            SkRect r;
150            r.set(0, 0, SkIntToScalar(1000), SkIntToScalar(20));
151       //     canvas->saveLayer(&r, NULL, SkCanvas::kHasAlphaLayer_SaveFlag);
152        }
153
154        SkPaint paint;
155//        const uint16_t glyphs[] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 };
156        int         index = fHints % SK_ARRAY_COUNT(gHints);
157        index = 1;
158//        const char* style = gHints[index].fName;
159
160//        canvas->translate(0, SkIntToScalar(50));
161
162  //      canvas->drawText(style, strlen(style), SkIntToScalar(20), SkIntToScalar(20), paint);
163
164        SkSafeUnref(paint.setTypeface(SkTypeface::CreateFromFile("/skimages/samplefont.ttf")));
165        paint.setAntiAlias(true);
166        paint.setFlags(paint.getFlags() | gHints[index].fFlags);
167
168        SkRect clip;
169        clip.set(SkIntToScalar(25), SkIntToScalar(34), SkIntToScalar(88), SkIntToScalar(155));
170
171        const char* text = "Hamburgefons";
172        size_t length = strlen(text);
173
174        SkScalar y = SkIntToScalar(0);
175        for (int i = 9; i <= 24; i++) {
176            paint.setTextSize(SkIntToScalar(i) /*+ (gRand.nextU() & 0xFFFF)*/);
177            for (SkScalar dx = 0; dx <= SkIntToScalar(3)/4;
178                                            dx += SkIntToScalar(1) /* /4 */) {
179                y += paint.getFontSpacing();
180                DrawTheText(canvas, text, length, SkIntToScalar(20) + dx, y, paint, fClickX);
181            }
182        }
183        if (gHints[index].fFlushCache) {
184//                SkGraphics::SetFontCacheUsed(0);
185        }
186    }
187
188    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
189                                              unsigned modi) override {
190        fClickX = x;
191        this->inval(NULL);
192        return this->INHERITED::onFindClickHandler(x, y, modi);
193    }
194
195    bool onClick(Click* click) override {
196        return this->INHERITED::onClick(click);
197    }
198
199private:
200    int fHints;
201    SkScalar fClickX;
202
203    typedef SampleView INHERITED;
204};
205
206//////////////////////////////////////////////////////////////////////////////
207
208static SkView* MyFactory() { return new TextSpeedView; }
209static SkViewRegister reg(MyFactory);
210