1#include "SampleCode.h"
2#include "SkView.h"
3#include "SkCanvas.h"
4#include "SkGradientShader.h"
5#include "SkGraphics.h"
6#include "SkImageDecoder.h"
7#include "SkPackBits.h"
8#include "SkPath.h"
9#include "SkPathMeasure.h"
10#include "SkRandom.h"
11#include "SkRegion.h"
12#include "SkShader.h"
13#include "SkUtils.h"
14#include "SkColorPriv.h"
15#include "SkColorFilter.h"
16#include "SkTypeface.h"
17#include "SkAvoidXfermode.h"
18
19#define REPEAT_COUNT    0
20
21static const char gText[] = "Hamburgefons";
22
23static bool gDevKern;
24
25static void rand_text(char text[], SkRandom& rand, size_t count) {
26    for (size_t i = 0; i < count; i++) {
27        text[i] = rand.nextU() & 0x7F;
28    }
29}
30
31static SkScalar sum_widths(const SkScalar widths[], int count) {
32    SkScalar w = 0;
33    for (int i = 0; i < count; i++) {
34        w += widths[i];
35    }
36    return w;
37}
38
39static void test_measure(const SkPaint& paint) {
40    char        text[256];
41    SkScalar    widths[256];
42    SkRect      rects[256];
43    SkRect      bounds;
44    int         count = 256;
45
46    SkRandom rand;
47
48    for (int i = 0; i < 100; i++) {
49        rand_text(text, rand, 256);
50        paint.getTextWidths(text, count, widths, NULL);
51        SkDEBUGCODE(SkScalar tw0 = sum_widths(widths, count);)
52        paint.getTextWidths(text, count, widths, rects);
53        SkDEBUGCODE(SkScalar tw1 = sum_widths(widths, count);)
54        SkASSERT(tw0 == tw1);
55
56        SkDEBUGCODE(SkScalar w0 = paint.measureText(text, count, NULL);)
57        SkDEBUGCODE(SkScalar w1 = paint.measureText(text, count, &bounds);)
58        SkASSERT(w0 == w1);
59        SkASSERT(w0 == tw0);
60
61        SkRect r = rects[0];
62        SkScalar x = 0;
63        for (int j = 1; j < count; j++) {
64            x += widths[j-1];
65            rects[j].offset(x, 0);
66            r.join(rects[j]);
67        }
68        SkASSERT(r == bounds);
69
70        if (r != bounds) {
71            printf("flags=%x i=%d [%g %g %g %g] [%g %g %g %g]\n",
72                   paint.getFlags(), i,
73                   SkScalarToFloat(r.fLeft),
74                   SkScalarToFloat(r.fTop),
75                   SkScalarToFloat(r.fRight),
76                   SkScalarToFloat(r.fBottom),
77                   SkScalarToFloat(bounds.fLeft),
78                   SkScalarToFloat(bounds.fTop),
79                   SkScalarToFloat(bounds.fRight),
80                   SkScalarToFloat(bounds.fBottom));
81        }
82    }
83}
84
85static void test_measure() {
86    SkPaint paint;
87
88    for (int i = 0; i <= SkPaint::kAllFlags; i++) {
89        paint.setFlags(i);
90        test_measure(paint);
91    }
92}
93
94//////////////////////////////////////////////////////////////////////////////
95
96static void test_textBounds(SkCanvas* canvas) {
97//    canvas->scale(SK_Scalar1/2, SK_Scalar1/2);
98
99//    canvas->rotate(SkIntToScalar(30));
100
101    gDevKern = !gDevKern;
102
103    SkScalar x = SkIntToScalar(50);
104    SkScalar y = SkIntToScalar(150);
105    SkScalar w[100];
106    SkRect   r[100], bounds;
107
108    SkPaint paint;
109    paint.setTextSize(SkIntToScalar(64));
110    paint.setAntiAlias(true);
111    paint.setDevKernText(gDevKern);
112
113    (void)paint.measureText(gText, strlen(gText), &bounds, NULL);
114    paint.setColor(SK_ColorGREEN);
115    bounds.offset(x, y);
116    canvas->drawRect(bounds, paint);
117
118    int count = paint.getTextWidths(gText, strlen(gText), w, r);
119
120    paint.setColor(SK_ColorRED);
121    for (int i = 0; i < count; i++) {
122        r[i].offset(x, y);
123        canvas->drawRect(r[i], paint);
124        x += w[i];
125    }
126    x = SkIntToScalar(50);
127    paint.setColor(gDevKern ? SK_ColorDKGRAY : SK_ColorBLACK);
128    canvas->drawText(gText, strlen(gText), x, y, paint);
129}
130
131static void create_src(SkBitmap* bitmap, SkBitmap::Config config) {
132    bitmap->setConfig(config, 100, 100);
133    bitmap->allocPixels();
134    bitmap->eraseColor(0);
135
136    SkCanvas    canvas(*bitmap);
137    SkPaint     paint;
138
139    paint.setAntiAlias(true);
140    canvas.drawCircle(SkIntToScalar(50), SkIntToScalar(50),
141                      SkIntToScalar(50), paint);
142}
143
144static void blur(SkBitmap* dst, const SkBitmap& src, SkScalar radius) {
145    *dst = src;
146}
147
148static void test_bitmap_blur(SkCanvas* canvas) {
149    SkBitmap    src, dst;
150
151    create_src(&src, SkBitmap::kARGB_8888_Config);
152    blur(&dst, src, SkIntToScalar(4));
153
154    SkPaint paint;
155
156    paint.setColor(SK_ColorRED);
157
158    canvas->drawBitmap(dst, SkIntToScalar(30), SkIntToScalar(60), &paint);
159}
160
161static SkScalar getpathlen(const SkPath& path) {
162    SkPathMeasure   meas(path, false);
163    return meas.getLength();
164}
165
166static void test_textpathmatrix(SkCanvas* canvas) {
167    SkPaint paint;
168    SkPath  path;
169    SkMatrix matrix;
170
171    path.moveTo(SkIntToScalar(200), SkIntToScalar(300));
172    path.quadTo(SkIntToScalar(400), SkIntToScalar(100),
173                SkIntToScalar(600), SkIntToScalar(300));
174
175    paint.setAntiAlias(true);
176
177    paint.setStyle(SkPaint::kStroke_Style);
178 //   canvas->drawPath(path, paint);
179    paint.setStyle(SkPaint::kFill_Style);
180    paint.setTextSize(SkIntToScalar(48));
181    paint.setTextAlign(SkPaint::kRight_Align);
182
183    const char* text = "Reflection";
184    size_t      len = strlen(text);
185    SkScalar    pathLen = getpathlen(path);
186
187    canvas->drawTextOnPath(text, len, path, NULL, paint);
188
189    paint.setColor(SK_ColorRED);
190    matrix.setScale(-SK_Scalar1, SK_Scalar1);
191    matrix.postTranslate(pathLen, 0);
192    canvas->drawTextOnPath(text, len, path, &matrix, paint);
193
194    paint.setColor(SK_ColorBLUE);
195    matrix.setScale(SK_Scalar1, -SK_Scalar1);
196    canvas->drawTextOnPath(text, len, path, &matrix, paint);
197
198    paint.setColor(SK_ColorGREEN);
199    matrix.setScale(-SK_Scalar1, -SK_Scalar1);
200    matrix.postTranslate(pathLen, 0);
201    canvas->drawTextOnPath(text, len, path, &matrix, paint);
202}
203
204class TextOnPathView : public SampleView {
205public:
206    SkPath      fPath;
207    SkScalar    fHOffset;
208
209	TextOnPathView() {
210        SkRect r;
211        r.set(SkIntToScalar(100), SkIntToScalar(100),
212              SkIntToScalar(300), SkIntToScalar(300));
213        fPath.addOval(r);
214        fPath.offset(SkIntToScalar(200), 0);
215
216        fHOffset = SkIntToScalar(50);
217    }
218
219protected:
220    // overrides from SkEventSink
221    virtual bool onQuery(SkEvent* evt) {
222        if (SampleCode::TitleQ(*evt)) {
223            SampleCode::TitleR(evt, "Text On Path");
224            return true;
225        }
226        return this->INHERITED::onQuery(evt);
227    }
228
229    virtual void onDrawContent(SkCanvas* canvas) {
230        SkPaint paint;
231
232        paint.setAntiAlias(true);
233        paint.setTextSize(SkIntToScalar(50));
234
235        for (int j = 0; j < REPEAT_COUNT; j++) {
236            SkScalar x = fHOffset;
237
238            paint.setColor(SK_ColorBLACK);
239            canvas->drawTextOnPathHV(gText, sizeof(gText)-1, fPath,
240                                     x, paint.getTextSize()/2, paint);
241
242            paint.setColor(SK_ColorRED);
243            canvas->drawTextOnPathHV(gText, sizeof(gText)-1, fPath,
244                                     x + SkIntToScalar(50), 0, paint);
245
246            paint.setColor(SK_ColorBLUE);
247            canvas->drawTextOnPathHV(gText, sizeof(gText)-1, fPath,
248                         x + SkIntToScalar(100), -paint.getTextSize()/2, paint);
249        }
250
251        paint.setColor(SK_ColorGREEN);
252        paint.setStyle(SkPaint::kStroke_Style);
253//        canvas->drawPath(fPath, paint);
254
255        canvas->translate(0, SkIntToScalar(100));
256        test_textpathmatrix(canvas);
257
258        if (REPEAT_COUNT > 1)
259            this->inval(NULL);
260    }
261
262    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
263        fHints += 1;
264        this->inval(NULL);
265        return this->INHERITED::onFindClickHandler(x, y);
266    }
267
268    virtual bool onClick(Click* click) {
269        return this->INHERITED::onClick(click);
270    }
271
272private:
273    int fHints;
274    typedef SampleView INHERITED;
275};
276
277//////////////////////////////////////////////////////////////////////////////
278
279static SkView* MyFactory() {
280    return new TextOnPathView;
281}
282
283static SkViewRegister reg(MyFactory);
284
285