SampleText.cpp revision 3af2b8def636eb36b69b1b334013320646dc7465
1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "SampleCode.h"
9#include "SkView.h"
10#include "SkCanvas.h"
11#include "Sk64.h"
12#include "SkFlattenableBuffers.h"
13#include "SkGradientShader.h"
14#include "SkGraphics.h"
15#include "SkImageDecoder.h"
16#include "SkKernel33MaskFilter.h"
17#include "SkPath.h"
18#include "SkRandom.h"
19#include "SkRegion.h"
20#include "SkShader.h"
21#include "SkUtils.h"
22#include "SkColorPriv.h"
23#include "SkColorFilter.h"
24#include "SkTime.h"
25#include "SkTypeface.h"
26#include "SkXfermode.h"
27
28#include "SkStream.h"
29#include "SkXMLParser.h"
30
31class ReduceNoise : public SkKernel33ProcMaskFilter {
32public:
33    ReduceNoise(int percent256) : SkKernel33ProcMaskFilter(percent256) {}
34    virtual uint8_t computeValue(uint8_t* const* srcRows) const {
35        int c = srcRows[1][1];
36        int min = 255, max = 0;
37        for (int i = 0; i < 3; i++)
38            for (int j = 0; j < 3; j++)
39                if (i != 1 || j != 1)
40                {
41                    int v = srcRows[i][j];
42                    if (max < v)
43                        max = v;
44                    if  (min > v)
45                        min = v;
46                }
47        if (c > max) c = max;
48    //    if (c < min) c = min;
49        return c;
50    }
51    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(ReduceNoise)
52
53private:
54    ReduceNoise(SkFlattenableReadBuffer& rb) : SkKernel33ProcMaskFilter(rb) {}
55};
56
57class Darken : public SkKernel33ProcMaskFilter {
58public:
59    Darken(int percent256) : SkKernel33ProcMaskFilter(percent256) {}
60    virtual uint8_t computeValue(uint8_t* const* srcRows) const {
61        int c = srcRows[1][1];
62        float f = c / 255.f;
63
64        if (c >= 0) {
65            f = sqrtf(f);
66        } else {
67            f *= f;
68        }
69        SkASSERT(f >= 0 && f <= 1);
70        return (int)(f * 255);
71    }
72    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Darken)
73
74private:
75    Darken(SkFlattenableReadBuffer& rb) : SkKernel33ProcMaskFilter(rb) {}
76};
77
78static SkMaskFilter* makemf() { return new Darken(0x30); }
79
80static void test_breakText() {
81    SkPaint paint;
82    const char* text = "sdfkljAKLDFJKEWkldfjlk#$%&sdfs.dsj";
83    size_t length = strlen(text);
84    SkScalar width = paint.measureText(text, length);
85
86    SkScalar mm = 0;
87    SkScalar nn = 0;
88    for (SkScalar w = 0; w <= width; w += SK_Scalar1) {
89        SkScalar m;
90        size_t n = paint.breakText(text, length, w, &m,
91                                    SkPaint::kBackward_TextBufferDirection);
92
93        SkASSERT(n <= length);
94        SkASSERT(m <= width);
95
96        if (n == 0) {
97            SkASSERT(m == 0);
98        } else {
99            // now assert that we're monotonic
100            if (n == nn) {
101                SkASSERT(m == mm);
102            } else {
103                SkASSERT(n > nn);
104                SkASSERT(m > mm);
105            }
106        }
107        nn = SkIntToScalar((unsigned int)n);
108        mm = m;
109    }
110
111    SkDEBUGCODE(size_t length2 =) paint.breakText(text, length, width, &mm);
112    SkASSERT(length2 == length);
113    SkASSERT(mm == width);
114}
115
116static SkRandom gRand;
117
118class SkPowerMode : public SkXfermode {
119public:
120    SkPowerMode(SkScalar exponent) { this->init(exponent); }
121
122    virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
123                        const SkAlpha aa[]) const SK_OVERRIDE;
124
125    typedef SkFlattenable* (*Factory)(SkFlattenableReadBuffer&);
126
127    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPowerMode)
128
129private:
130    SkScalar fExp;          // user's value
131    uint8_t fTable[256];    // cache
132
133    void init(SkScalar exponent);
134    SkPowerMode(SkFlattenableReadBuffer& b) : INHERITED(b) {
135        // read the exponent
136        this->init(SkFixedToScalar(b.readFixed()));
137    }
138    virtual void flatten(SkFlattenableWriteBuffer& b) const SK_OVERRIDE {
139        this->INHERITED::flatten(b);
140        b.writeFixed(SkScalarToFixed(fExp));
141    }
142
143    typedef SkXfermode INHERITED;
144};
145
146void SkPowerMode::init(SkScalar e) {
147    fExp = e;
148    float ee = SkScalarToFloat(e);
149
150    printf("------ %g\n", ee);
151    for (int i = 0; i < 256; i++) {
152        float x = i / 255.f;
153     //   printf(" %d %g", i, x);
154        x = powf(x, ee);
155     //   printf(" %g", x);
156        int xx = SkScalarRound(SkFloatToScalar(x * 255));
157     //   printf(" %d\n", xx);
158        fTable[i] = SkToU8(xx);
159    }
160}
161
162void SkPowerMode::xfer16(uint16_t dst[], const SkPMColor src[], int count,
163                         const SkAlpha aa[]) const {
164    for (int i = 0; i < count; i++) {
165        SkPMColor c = src[i];
166        int r = SkGetPackedR32(c);
167        int g = SkGetPackedG32(c);
168        int b = SkGetPackedB32(c);
169        r = fTable[r];
170        g = fTable[g];
171        b = fTable[b];
172        dst[i] = SkPack888ToRGB16(r, g, b);
173    }
174}
175
176static const struct {
177    const char* fName;
178    uint32_t    fFlags;
179    bool        fFlushCache;
180} gHints[] = {
181    { "Linear", SkPaint::kLinearText_Flag,     false },
182    { "Normal",   0,                           true },
183    { "Subpixel", SkPaint::kSubpixelText_Flag, true }
184};
185
186static void DrawTheText(SkCanvas* canvas, const char text[], size_t length,
187                        SkScalar x, SkScalar y, const SkPaint& paint,
188                        SkScalar clickX, SkMaskFilter* mf) {
189    SkPaint p(paint);
190
191#if 0
192    canvas->drawText(text, length, x, y, paint);
193#else
194    {
195        SkPoint pts[1000];
196        SkScalar xpos = x;
197        SkASSERT(length <= SK_ARRAY_COUNT(pts));
198        for (size_t i = 0; i < length; i++) {
199            pts[i].set(xpos, y), xpos += paint.getTextSize();
200        }
201        canvas->drawPosText(text, length, pts, paint);
202    }
203#endif
204
205    p.setSubpixelText(true);
206    x += SkIntToScalar(180);
207    canvas->drawText(text, length, x, y, p);
208
209#ifdef SK_DEBUG
210    if (true) {
211    //    p.setMaskFilter(mf);
212        p.setSubpixelText(false);
213        p.setLinearText(true);
214        x += SkIntToScalar(180);
215        canvas->drawText(text, length, x, y, p);
216    }
217#endif
218}
219
220class TextSpeedView : public SampleView {
221public:
222    TextSpeedView() {
223        fMF = makemf();
224
225        fHints = 0;
226        fClickX = 0;
227
228        test_breakText();
229    }
230
231    virtual ~TextSpeedView() {
232        SkSafeUnref(fMF);
233    }
234
235protected:
236    // overrides from SkEventSink
237    virtual bool onQuery(SkEvent* evt) {
238        if (SampleCode::TitleQ(*evt)) {
239            SampleCode::TitleR(evt, "Text");
240            return true;
241        }
242        return this->INHERITED::onQuery(evt);
243    }
244
245    static void make_textstrip(SkBitmap* bm) {
246        bm->setConfig(SkBitmap::kRGB_565_Config, 200, 18);
247        bm->allocPixels();
248        bm->eraseColor(SK_ColorWHITE);
249
250        SkCanvas    canvas(*bm);
251        SkPaint     paint;
252        const char* s = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit";
253
254        paint.setFlags(paint.getFlags() | SkPaint::kAntiAlias_Flag
255                                        | SkPaint::kDevKernText_Flag);
256        paint.setTextSize(SkIntToScalar(14));
257        canvas.drawText(s, strlen(s), SkIntToScalar(8), SkIntToScalar(14), paint);
258    }
259
260    static void fill_pts(SkPoint pts[], size_t n, SkRandom* rand) {
261        for (size_t i = 0; i < n; i++)
262            pts[i].set(rand->nextUScalar1() * 640, rand->nextUScalar1() * 480);
263    }
264
265    virtual void onDrawContent(SkCanvas* canvas) {
266        SkAutoCanvasRestore restore(canvas, false);
267        {
268            SkRect r;
269            r.set(0, 0, SkIntToScalar(1000), SkIntToScalar(20));
270       //     canvas->saveLayer(&r, NULL, SkCanvas::kHasAlphaLayer_SaveFlag);
271        }
272
273        SkPaint paint;
274//        const uint16_t glyphs[] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 };
275        int         index = fHints % SK_ARRAY_COUNT(gHints);
276        index = 1;
277//        const char* style = gHints[index].fName;
278
279//        canvas->translate(0, SkIntToScalar(50));
280
281  //      canvas->drawText(style, strlen(style), SkIntToScalar(20), SkIntToScalar(20), paint);
282
283        SkSafeUnref(paint.setTypeface(SkTypeface::CreateFromFile("/skimages/samplefont.ttf")));
284        paint.setAntiAlias(true);
285        paint.setFlags(paint.getFlags() | gHints[index].fFlags);
286
287        SkRect clip;
288        clip.set(SkIntToScalar(25), SkIntToScalar(34), SkIntToScalar(88), SkIntToScalar(155));
289
290        const char* text = "Hamburgefons";
291        size_t length = strlen(text);
292
293        SkScalar y = SkIntToScalar(0);
294        for (int i = 9; i <= 24; i++) {
295            paint.setTextSize(SkIntToScalar(i) /*+ (gRand.nextU() & 0xFFFF)*/);
296            for (SkScalar dx = 0; dx <= SkIntToScalar(3)/4;
297                                            dx += SkIntToScalar(1) /* /4 */) {
298                y += paint.getFontSpacing();
299                DrawTheText(canvas, text, length, SkIntToScalar(20) + dx, y,
300                            paint, fClickX, fMF);
301            }
302        }
303        if (gHints[index].fFlushCache) {
304//                SkGraphics::SetFontCacheUsed(0);
305        }
306    }
307
308    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
309        fClickX = x;
310        this->inval(NULL);
311        return this->INHERITED::onFindClickHandler(x, y);
312    }
313
314    virtual bool onClick(Click* click) {
315        return this->INHERITED::onClick(click);
316    }
317
318private:
319    int fHints;
320    SkScalar fClickX;
321    SkMaskFilter* fMF;
322
323    typedef SampleView INHERITED;
324};
325
326//////////////////////////////////////////////////////////////////////////////
327
328static SkView* MyFactory() { return new TextSpeedView; }
329static SkViewRegister reg(MyFactory);
330
331