1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SampleCode.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkView.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGradientShader.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRegion.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "Sk1DPathEffect.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCornerPathEffect.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPathMeasure.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRandom.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h"
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDither.h"
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void draw_sweep(SkCanvas* c, int width, int height, SkScalar angle) {
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint p;
27ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    p.setAntiAlias(true);
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//    p.setDither(true);
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    p.setStrokeWidth(SkIntToScalar(width/10));
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    p.setStyle(SkPaint::kStroke_Style);
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
34ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    //    SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN, SK_ColorCYAN };
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkColor colors[] = { 0x4c737373, 0x4c737373, 0xffffd300 };
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader* s = SkGradientShader::CreateSweep(r.centerX(), r.centerY(),
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                colors, NULL, SK_ARRAY_COUNT(colors));
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    p.setShader(s)->unref();
40ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoCanvasRestore acr(c, true);
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    c->translate(r.centerX(), r.centerY());
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    c->rotate(angle);
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    c->translate(-r.centerX(), -r.centerY());
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect bounds = r;
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.inset(p.getStrokeWidth(), p.getStrokeWidth());
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect innerBounds = r;
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (true) {
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        c->drawOval(r, p);
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar x = r.centerX();
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar y = r.centerY();
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar radius = r.width() / 2;
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar thickness = p.getStrokeWidth();
584b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org        SkScalar sweep = 360.0f;
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath path;
60ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.moveTo(x + radius, y);
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // outer top
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.lineTo(x + radius + thickness, y);
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // outer arc
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(bounds, 0, sweep, false);
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // inner arc
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(innerBounds, sweep, -sweep, false);
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.close();
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
72961ddb04a0a7aba843032d829ab867518e52559ereed@google.comstatic void make_bm(SkBitmap* bm) {
73a8c183125f2861067daf432cada06d431a795cd0commit-bot@chromium.org    bm->allocN32Pixels(100, 100);
74dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com    bm->eraseColor(SK_ColorTRANSPARENT);
75ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
76ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com    SkCanvas c(*bm);
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    draw_sweep(&c, bm->width(), bm->height(), 0);
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
80261b8e2ca1cf22303ad95267f0bdc6e87e1bbe70reed@google.comstatic void pre_dither(const SkBitmap& bm) {
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoLockPixels alp(bm);
82ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
83261b8e2ca1cf22303ad95267f0bdc6e87e1bbe70reed@google.com    for (int y = 0; y < bm.height(); y++) {
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DITHER_4444_SCAN(y);
85ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor* p = bm.getAddr32(0, y);
87261b8e2ca1cf22303ad95267f0bdc6e87e1bbe70reed@google.com        for (int x = 0; x < bm.width(); x++) {
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = *p;
89ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned a = SkGetPackedA32(c);
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned r = SkGetPackedR32(c);
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned g = SkGetPackedG32(c);
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned b = SkGetPackedB32(c);
94ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned d = DITHER_VALUE(x);
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            a = SkDITHER_A32To4444(a, d);
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            r = SkDITHER_R32To4444(r, d);
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            g = SkDITHER_G32To4444(g, d);
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            b = SkDITHER_B32To4444(b, d);
101ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            a = SkA4444ToA32(a);
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            r = SkR4444ToR32(r);
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            g = SkG4444ToG32(g);
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            b = SkB4444ToB32(b);
106ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *p++ = SkPackARGB32(a, r, g, b);
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
112961ddb04a0a7aba843032d829ab867518e52559ereed@google.comclass DitherView : public SampleView {
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBitmap    fBM, fBMPreDither, fBM16;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar fAngle;
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
117ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com    DitherView() {
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        make_bm(&fBM);
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        make_bm(&fBMPreDither);
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        pre_dither(fBMPreDither);
1218a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        fBM.copyTo(&fBM16, kARGB_4444_SkColorType);
122ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fAngle = 0;
124ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
125961ddb04a0a7aba843032d829ab867518e52559ereed@google.com        this->setBGColor(0xFF181818);
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // overrides from SkEventSink
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual bool onQuery(SkEvent* evt) {
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (SampleCode::TitleQ(*evt)) {
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SampleCode::TitleR(evt, "Dither");
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->INHERITED::onQuery(evt);
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
137ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
138961ddb04a0a7aba843032d829ab867518e52559ereed@google.com    virtual void onDrawContent(SkCanvas* canvas) {
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint paint;
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar x = SkIntToScalar(10);
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar y = SkIntToScalar(10);
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkScalar DX = SkIntToScalar(fBM.width() + 10);
143ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint.setAntiAlias(true);
145ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (true) {
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            canvas->drawBitmap(fBM, x, y, &paint);
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += DX;
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            paint.setDither(true);
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            canvas->drawBitmap(fBM, x, y, &paint);
151ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += DX;
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            paint.setDither(false);
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            canvas->drawBitmap(fBMPreDither, x, y, &paint);
155ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += DX;
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            canvas->drawBitmap(fBM16, x, y, &paint);
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
159ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->translate(DX, DX*2);
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        draw_sweep(canvas, fBM.width(), fBM.height(), fAngle);
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->translate(DX, 0);
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        draw_sweep(canvas, fBM.width()>>1, fBM.height()>>1, fAngle);
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->translate(DX, 0);
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        draw_sweep(canvas, fBM.width()>>2, fBM.height()>>2, fAngle);
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fAngle += SK_Scalar1/2;
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->inval(NULL);
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
172961ddb04a0a7aba843032d829ab867518e52559ereed@google.com    typedef SampleView INHERITED;
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkView* MyFactory() { return new DitherView; }
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkViewRegister reg(MyFactory);
179