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