aboutsummaryrefslogtreecommitdiffstats
path: root/samplecode
diff options
context:
space:
mode:
Diffstat (limited to 'samplecode')
-rw-r--r--samplecode/SampleAll.cpp791
-rw-r--r--samplecode/SampleApp.cpp607
-rw-r--r--samplecode/SampleArc.cpp187
-rw-r--r--samplecode/SampleBitmapRect.cpp110
-rw-r--r--samplecode/SampleCamera.cpp106
-rw-r--r--samplecode/SampleCircle.cpp137
-rw-r--r--samplecode/SampleCode.h38
-rw-r--r--samplecode/SampleCull.cpp230
-rw-r--r--samplecode/SampleDither.cpp197
-rw-r--r--samplecode/SampleDrawLooper.cpp103
-rw-r--r--samplecode/SampleEmboss.cpp77
-rw-r--r--samplecode/SampleEncode.cpp253
-rw-r--r--samplecode/SampleFillType.cpp101
-rw-r--r--samplecode/SampleFilter.cpp163
-rw-r--r--samplecode/SampleFilter2.cpp123
-rw-r--r--samplecode/SampleFontCache.cpp171
-rw-r--r--samplecode/SampleGL.cpp206
-rw-r--r--samplecode/SampleImage.cpp158
-rw-r--r--samplecode/SampleImageDir.cpp319
-rw-r--r--samplecode/SampleLayers.cpp258
-rw-r--r--samplecode/SampleLines.cpp146
-rw-r--r--samplecode/SampleMeasure.cpp138
-rw-r--r--samplecode/SampleNinePatch.cpp56
-rw-r--r--samplecode/SampleOverflow.cpp106
-rw-r--r--samplecode/SamplePageFlip.cpp173
-rw-r--r--samplecode/SamplePatch.cpp417
-rw-r--r--samplecode/SamplePath.cpp163
-rw-r--r--samplecode/SamplePathEffects.cpp282
-rw-r--r--samplecode/SamplePicture.cpp157
-rw-r--r--samplecode/SamplePoints.cpp121
-rw-r--r--samplecode/SamplePolyToPoly.cpp165
-rw-r--r--samplecode/SampleRegion.cpp307
-rw-r--r--samplecode/SampleShaders.cpp157
-rw-r--r--samplecode/SampleStrokeText.cpp147
-rw-r--r--samplecode/SampleTests.cpp99
-rw-r--r--samplecode/SampleText.cpp791
-rw-r--r--samplecode/SampleTextAlpha.cpp122
-rw-r--r--samplecode/SampleTextEffects.cpp466
-rw-r--r--samplecode/SampleTextOnPath.cpp442
-rw-r--r--samplecode/SampleTiling.cpp170
-rw-r--r--samplecode/SampleTypeface.cpp91
-rw-r--r--samplecode/SampleVertices.cpp278
-rw-r--r--samplecode/SampleXfermodes.cpp265
-rw-r--r--samplecode/vertexdump.cpp88
44 files changed, 9682 insertions, 0 deletions
diff --git a/samplecode/SampleAll.cpp b/samplecode/SampleAll.cpp
new file mode 100644
index 0000000..968263b
--- /dev/null
+++ b/samplecode/SampleAll.cpp
@@ -0,0 +1,791 @@
+#include "SampleCode.h"
+#include "SkCanvas.h"
+#include "SkView.h"
+#include "Sk1DPathEffect.h"
+#include "Sk2DPathEffect.h"
+#include "SkAvoidXfermode.h"
+#include "SkBlurMaskFilter.h"
+#include "SkColorFilter.h"
+#include "SkColorPriv.h"
+#include "SkCornerPathEffect.h"
+#include "SkDashPathEffect.h"
+#include "SkDiscretePathEffect.h"
+#include "SkEmbossMaskFilter.h"
+#include "SkGradientShader.h"
+#include "SkImageDecoder.h"
+#include "SkLayerRasterizer.h"
+#include "SkMath.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkShaderExtras.h"
+#include "SkCornerPathEffect.h"
+#include "SkPathMeasure.h"
+#include "SkPicture.h"
+#include "SkRandom.h"
+#include "SkTransparentShader.h"
+#include "SkTypeface.h"
+#include "SkUnitMappers.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+
+#include <math.h>
+
+extern void Dump();
+
+static inline SkPMColor rgb2gray(SkPMColor c)
+{
+ unsigned r = SkGetPackedR32(c);
+ unsigned g = SkGetPackedG32(c);
+ unsigned b = SkGetPackedB32(c);
+
+ unsigned x = r * 5 + g * 7 + b * 4 >> 4;
+
+ return SkPackARGB32(0, x, x, x) | (c & (SK_A32_MASK << SK_A32_SHIFT));
+}
+
+class SkGrayScaleColorFilter : public SkColorFilter {
+public:
+ virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[])
+ {
+ for (int i = 0; i < count; i++)
+ result[i] = rgb2gray(src[i]);
+ }
+};
+
+class SkChannelMaskColorFilter : public SkColorFilter {
+public:
+ SkChannelMaskColorFilter(U8CPU redMask, U8CPU greenMask, U8CPU blueMask)
+ {
+ fMask = SkPackARGB32(0xFF, redMask, greenMask, blueMask);
+ }
+
+ virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[])
+ {
+ SkPMColor mask = fMask;
+ for (int i = 0; i < count; i++)
+ result[i] = src[i] & mask;
+ }
+
+private:
+ SkPMColor fMask;
+};
+
+///////////////////////////////////////////////////////////
+
+static void r0(SkLayerRasterizer* rast, SkPaint& p)
+{
+ p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
+ SkBlurMaskFilter::kNormal_BlurStyle))->unref();
+ rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
+
+ p.setMaskFilter(NULL);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1);
+ rast->addLayer(p);
+
+ p.setAlpha(0x11);
+ p.setStyle(SkPaint::kFill_Style);
+ p.setPorterDuffXfermode(SkPorterDuff::kSrc_Mode);
+ rast->addLayer(p);
+}
+
+static void r1(SkLayerRasterizer* rast, SkPaint& p)
+{
+ rast->addLayer(p);
+
+ p.setAlpha(0x40);
+ p.setPorterDuffXfermode(SkPorterDuff::kSrc_Mode);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1*2);
+ rast->addLayer(p);
+}
+
+static void r2(SkLayerRasterizer* rast, SkPaint& p)
+{
+ p.setStyle(SkPaint::kStrokeAndFill_Style);
+ p.setStrokeWidth(SK_Scalar1*4);
+ rast->addLayer(p);
+
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1*3/2);
+ p.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ rast->addLayer(p);
+}
+
+static void r3(SkLayerRasterizer* rast, SkPaint& p)
+{
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1*3);
+ rast->addLayer(p);
+
+ p.setAlpha(0x20);
+ p.setStyle(SkPaint::kFill_Style);
+ p.setPorterDuffXfermode(SkPorterDuff::kSrc_Mode);
+ rast->addLayer(p);
+}
+
+static void r4(SkLayerRasterizer* rast, SkPaint& p)
+{
+ p.setAlpha(0x60);
+ rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
+
+ p.setAlpha(0xFF);
+ p.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
+
+ p.setXfermode(NULL);
+ rast->addLayer(p);
+}
+
+static void r5(SkLayerRasterizer* rast, SkPaint& p)
+{
+ rast->addLayer(p);
+
+ p.setPathEffect(new SkDiscretePathEffect(SK_Scalar1*4, SK_Scalar1*3))->unref();
+ p.setPorterDuffXfermode(SkPorterDuff::kSrcOut_Mode);
+ rast->addLayer(p);
+}
+
+static void r6(SkLayerRasterizer* rast, SkPaint& p)
+{
+ rast->addLayer(p);
+
+ p.setAntiAlias(false);
+ SkLayerRasterizer* rast2 = new SkLayerRasterizer;
+ r5(rast2, p);
+ p.setRasterizer(rast2)->unref();
+ p.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ rast->addLayer(p);
+}
+
+class Dot2DPathEffect : public Sk2DPathEffect {
+public:
+ Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix)
+ : Sk2DPathEffect(matrix), fRadius(radius) {}
+
+ virtual void flatten(SkFlattenableWriteBuffer& buffer)
+ {
+ this->INHERITED::flatten(buffer);
+
+ buffer.writeScalar(fRadius);
+ }
+ virtual Factory getFactory() { return CreateProc; }
+
+protected:
+ virtual void next(const SkPoint& loc, int u, int v, SkPath* dst)
+ {
+ dst->addCircle(loc.fX, loc.fY, fRadius);
+ }
+
+ Dot2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer)
+ {
+ fRadius = buffer.readScalar();
+ }
+private:
+ SkScalar fRadius;
+
+ static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer)
+ {
+ return new Dot2DPathEffect(buffer);
+ }
+
+ typedef Sk2DPathEffect INHERITED;
+};
+
+static void r7(SkLayerRasterizer* rast, SkPaint& p)
+{
+ SkMatrix lattice;
+ lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
+ lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
+ p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*4, lattice))->unref();
+ rast->addLayer(p);
+}
+
+static void r8(SkLayerRasterizer* rast, SkPaint& p)
+{
+ rast->addLayer(p);
+
+ SkMatrix lattice;
+ lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
+ lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
+ p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*2, lattice))->unref();
+ p.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ rast->addLayer(p);
+
+ p.setPathEffect(NULL);
+ p.setXfermode(NULL);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1);
+ rast->addLayer(p);
+}
+
+class Line2DPathEffect : public Sk2DPathEffect {
+public:
+ Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
+ : Sk2DPathEffect(matrix), fWidth(width) {}
+
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width)
+ {
+ if (this->INHERITED::filterPath(dst, src, width))
+ {
+ *width = fWidth;
+ return true;
+ }
+ return false;
+ }
+
+ virtual Factory getFactory() { return CreateProc; }
+ virtual void flatten(SkFlattenableWriteBuffer& buffer)
+ {
+ this->INHERITED::flatten(buffer);
+ buffer.writeScalar(fWidth);
+ }
+protected:
+ virtual void nextSpan(int u, int v, int ucount, SkPath* dst)
+ {
+ if (ucount > 1)
+ {
+ SkPoint src[2], dstP[2];
+
+ src[0].set(SkIntToScalar(u) + SK_ScalarHalf,
+ SkIntToScalar(v) + SK_ScalarHalf);
+ src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf,
+ SkIntToScalar(v) + SK_ScalarHalf);
+ this->getMatrix().mapPoints(dstP, src, 2);
+
+ dst->moveTo(dstP[0]);
+ dst->lineTo(dstP[1]);
+ }
+ }
+
+ Line2DPathEffect::Line2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer)
+ {
+ fWidth = buffer.readScalar();
+ }
+
+private:
+ SkScalar fWidth;
+
+ static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { return new Line2DPathEffect(buffer); }
+
+ typedef Sk2DPathEffect INHERITED;
+};
+
+static void r9(SkLayerRasterizer* rast, SkPaint& p)
+{
+ rast->addLayer(p);
+
+ SkMatrix lattice;
+ lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
+ lattice.postRotate(SkIntToScalar(30), 0, 0);
+ p.setPathEffect(new Line2DPathEffect(SK_Scalar1*2, lattice))->unref();
+ p.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ rast->addLayer(p);
+
+ p.setPathEffect(NULL);
+ p.setXfermode(NULL);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1);
+ rast->addLayer(p);
+}
+
+typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
+
+static const raster_proc gRastProcs[] = {
+ r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
+};
+
+static const struct {
+ SkColor fMul, fAdd;
+} gLightingColors[] = {
+ { 0x808080, 0x800000 }, // general case
+ { 0x707070, 0x707070 }, // no-pin case
+ { 0xFFFFFF, 0x800000 }, // just-add case
+ { 0x808080, 0x000000 }, // just-mul case
+ { 0xFFFFFF, 0x000000 } // identity case
+};
+
+static unsigned color_dist16(uint16_t a, uint16_t b)
+{
+ unsigned dr = SkAbs32(SkPacked16ToR32(a) - SkPacked16ToR32(b));
+ unsigned dg = SkAbs32(SkPacked16ToG32(a) - SkPacked16ToG32(b));
+ unsigned db = SkAbs32(SkPacked16ToB32(a) - SkPacked16ToB32(b));
+
+ return SkMax32(dr, SkMax32(dg, db));
+}
+
+static unsigned scale_dist(unsigned dist, unsigned scale)
+{
+ dist >>= 6;
+ dist = (dist << 2) | dist;
+ dist = (dist << 4) | dist;
+ return dist;
+
+// return SkAlphaMul(dist, scale);
+}
+
+static void apply_shader(SkPaint* paint, int index)
+{
+ raster_proc proc = gRastProcs[index];
+ if (proc)
+ {
+ SkPaint p;
+ SkLayerRasterizer* rast = new SkLayerRasterizer;
+
+ p.setAntiAlias(true);
+ proc(rast, p);
+ paint->setRasterizer(rast)->unref();
+ }
+
+#if 1
+ SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
+ paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir, SK_Scalar1/4, SkIntToScalar(4), SkIntToScalar(3)))->unref();
+ paint->setColor(SK_ColorBLUE);
+#endif
+}
+
+static void test_math()
+{
+ float x;
+ const float PI = 3.141593;
+
+ for (x = 0; x < 1; x += 0.05f)
+ printf("atan(%g) = %g\n", x, atanf(x) * 180/PI);
+ for (x = 1; x < 10000000; x *= 2)
+ printf("atan(%g) = %g\n", x, atanf(x) * 180/PI);
+}
+
+class DemoView : public SkView {
+public:
+ DemoView()
+ {
+ test_math();
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Demo");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ return this->INHERITED::onClick(click);
+ }
+
+ void makePath(SkPath& path)
+ {
+ path.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(20),
+ SkPath::kCCW_Direction);
+ for (int index = 0; index < 10; index++) {
+ SkScalar x = SkFloatToScalar(cos(index / 10.0f * 2 * 3.1415925358f));
+ SkScalar y = SkFloatToScalar(sin(index / 10.0f * 2 * 3.1415925358f));
+ x *= index & 1 ? 7 : 14;
+ y *= index & 1 ? 7 : 14;
+ x += SkIntToScalar(20);
+ y += SkIntToScalar(20);
+ if (index == 0)
+ path.moveTo(x, y);
+ else
+ path.lineTo(x, y);
+ }
+ path.close();
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ canvas->drawColor(SK_ColorWHITE);
+ canvas->save();
+ drawPicture(canvas, 0);
+ canvas->restore();
+
+ {
+ SkPicture picture;
+ SkCanvas* record = picture.beginRecording(320, 480);
+ drawPicture(record, 120);
+ canvas->translate(0, SkIntToScalar(120));
+
+ SkRect clip;
+ clip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
+ do {
+ canvas->save();
+ canvas->clipRect(clip);
+ picture.draw(canvas);
+ canvas->restore();
+ if (clip.fRight < SkIntToScalar(320))
+ clip.offset(SkIntToScalar(160), 0);
+ else if (clip.fBottom < SkIntToScalar(480))
+ clip.offset(-SkIntToScalar(320), SkIntToScalar(160));
+ else
+ break;
+ } while (true);
+ }
+ Dump();
+ }
+
+ void drawPicture(SkCanvas* canvas, int spriteOffset)
+ {
+ SkMatrix matrix; matrix.reset();
+ SkPaint paint;
+ SkPath path;
+ SkPoint start = {0, 0};
+ SkPoint stop = { SkIntToScalar(40), SkIntToScalar(40) };
+ SkRect rect = {0, 0, SkIntToScalar(40), SkIntToScalar(40) };
+ SkRect rect2 = {0, 0, SkIntToScalar(65), SkIntToScalar(20) };
+ SkScalar left = 0, top = 0, x = 0, y = 0;
+ int index;
+
+ char ascii[] = "ascii...";
+ size_t asciiLength = sizeof(ascii) - 1;
+ char utf8[] = "utf8" "\xe2\x80\xa6";
+ short utf16[] = {'u', 't', 'f', '1', '6', 0x2026 };
+ short utf16simple[] = {'u', 't', 'f', '1', '6', '!' };
+
+ makePath(path);
+ SkTDArray<SkPoint>(pos);
+ pos.setCount(asciiLength);
+ for (index = 0; index < asciiLength; index++)
+ pos[index].set(SkIntToScalar(index * 10), SkIntToScalar(index * 2));
+ SkTDArray<SkPoint>(pos2);
+ pos2.setCount(asciiLength);
+ for (index = 0; index < asciiLength; index++)
+ pos2[index].set(SkIntToScalar(index * 10), SkIntToScalar(20));
+
+ // shaders
+ SkPoint linearPoints[] = { 0, 0, SkIntToScalar(40), SkIntToScalar(40) };
+ SkColor linearColors[] = { SK_ColorRED, SK_ColorBLUE };
+ SkScalar* linearPos = NULL;
+ int linearCount = 2;
+ SkShader::TileMode linearMode = SkShader::kMirror_TileMode;
+ SkUnitMapper* linearMapper = new SkDiscreteMapper(3);
+ SkAutoUnref unmapLinearMapper(linearMapper);
+ SkShader* linear = SkGradientShader::CreateLinear(linearPoints,
+ linearColors, linearPos, linearCount, linearMode, linearMapper);
+
+ SkPoint radialCenter = { SkIntToScalar(25), SkIntToScalar(25) };
+ SkScalar radialRadius = SkIntToScalar(25);
+ SkColor radialColors[] = { SK_ColorGREEN, SK_ColorGRAY, SK_ColorRED };
+ SkScalar radialPos[] = { 0, SkIntToScalar(3) / 5, SkIntToScalar(1)};
+ int radialCount = 3;
+ SkShader::TileMode radialMode = SkShader::kRepeat_TileMode;
+ SkUnitMapper* radialMapper = new SkCosineMapper();
+ SkAutoUnref unmapRadialMapper(radialMapper);
+ SkShader* radial = SkGradientShader::CreateRadial(radialCenter,
+ radialRadius, radialColors, radialPos, radialCount,
+ radialMode, radialMapper);
+
+ SkTransparentShader* transparentShader = new SkTransparentShader();
+ SkEmbossMaskFilter::Light light;
+ light.fDirection[0] = SK_Scalar1/2;
+ light.fDirection[1] = SK_Scalar1/2;
+ light.fDirection[2] = SK_Scalar1/3;
+ light.fAmbient = 0x48;
+ light.fSpecular = 0x80;
+ SkScalar radius = SkIntToScalar(12)/5;
+ SkEmbossMaskFilter* embossFilter = new SkEmbossMaskFilter(light,
+ radius);
+
+ SkXfermode* xfermode = SkPorterDuff::CreateXfermode(SkPorterDuff::kXor_Mode);
+ SkColorFilter* lightingFilter = SkColorFilter::CreateLightingFilter(
+ 0xff89bc45, 0xff112233);
+
+ canvas->save();
+ canvas->translate(SkIntToScalar(0), SkIntToScalar(5));
+ paint.setFlags(SkPaint::kAntiAlias_Flag | SkPaint::kFilterBitmap_Flag);
+ // !!! draw through a clip
+ paint.setColor(SK_ColorLTGRAY);
+ paint.setStyle(SkPaint::kFill_Style);
+ SkRect clip = {0, 0, SkIntToScalar(320), SkIntToScalar(120)};
+ canvas->clipRect(clip);
+ paint.setShader(SkShader::CreateBitmapShader(fTx,
+ SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode))->unref();
+ canvas->drawPaint(paint);
+ canvas->save();
+
+ // line (exercises xfermode, colorShader, colorFilter, filterShader)
+ paint.setColor(SK_ColorGREEN);
+ paint.setStrokeWidth(SkIntToScalar(10));
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setXfermode(xfermode)->unref();
+ paint.setColorFilter(lightingFilter)->unref();
+ canvas->drawLine(start.fX, start.fY, stop.fX, stop.fY, paint); // should not be green
+ paint.setXfermode(NULL);
+ paint.setColorFilter(NULL);
+
+ // rectangle
+ paint.setStyle(SkPaint::kFill_Style);
+ canvas->translate(SkIntToScalar(50), 0);
+ paint.setColor(SK_ColorYELLOW);
+ paint.setShader(linear)->unref();
+ paint.setPathEffect(pathEffectTest())->unref();
+ canvas->drawRect(rect, paint);
+ paint.setPathEffect(NULL);
+
+ // circle w/ emboss & transparent (exercises 3dshader)
+ canvas->translate(SkIntToScalar(50), 0);
+ paint.setMaskFilter(embossFilter)->unref();
+ canvas->drawOval(rect, paint);
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
+ paint.setShader(transparentShader)->unref();
+ canvas->drawOval(rect, paint);
+ canvas->translate(0, SkIntToScalar(-10));
+
+ // path
+ canvas->translate(SkIntToScalar(50), 0);
+ paint.setColor(SK_ColorRED);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(5));
+ paint.setShader(radial)->unref();
+ paint.setMaskFilter(NULL);
+ canvas->drawPath(path, paint);
+
+ paint.setShader(NULL);
+ // bitmap, sprite
+ canvas->translate(SkIntToScalar(50), 0);
+ paint.setStyle(SkPaint::kFill_Style);
+ canvas->drawBitmap(fBug, left, top, &paint);
+ canvas->translate(SkIntToScalar(30), 0);
+ canvas->drawSprite(fTb,
+ SkScalarRound(canvas->getTotalMatrix().getTranslateX()),
+ spriteOffset + 10, &paint);
+
+ canvas->translate(-SkIntToScalar(30), SkIntToScalar(30));
+ paint.setShader(shaderTest())->unref(); // test compose shader
+ canvas->drawRect(rect2, paint);
+ paint.setShader(NULL);
+
+ canvas->restore();
+ // text
+ canvas->translate(0, SkIntToScalar(60));
+ canvas->save();
+ paint.setColor(SK_ColorGRAY);
+ canvas->drawPosText(ascii, asciiLength, pos.begin(), paint);
+ canvas->drawPosText(ascii, asciiLength, pos2.begin(), paint);
+
+ canvas->translate(SkIntToScalar(50), 0);
+ paint.setColor(SK_ColorCYAN);
+ canvas->drawText(utf8, sizeof(utf8) - 1, x, y, paint);
+
+ canvas->translate(SkIntToScalar(30), 0);
+ paint.setColor(SK_ColorMAGENTA);
+ paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+ matrix.setTranslate(SkIntToScalar(10), SkIntToScalar(10));
+ canvas->drawTextOnPath((void*) utf16, sizeof(utf16), path, &matrix, paint);
+ canvas->translate(0, SkIntToScalar(20));
+ canvas->drawTextOnPath((void*) utf16simple, sizeof(utf16simple), path, &matrix, paint);
+ canvas->restore();
+
+ canvas->translate(0, SkIntToScalar(60));
+ paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
+ canvas->restore();
+ }
+
+ /*
+./SkColorFilter.h:25:class SkColorFilter : public SkFlattenable { -- abstract
+ static SkColorFilter* CreatXfermodeFilter() *** untested ***
+ static SkColorFilter* CreatePorterDuffFilter() *** untested ***
+ static SkColorFilter* CreateLightingFilter() -- tested
+./SkDrawLooper.h:9:class SkDrawLooper : public SkFlattenable { -- virtually abstract
+ ./SkBlurDrawLooper.h:9:class SkBlurDrawLooper : public SkDrawLooper { *** untested ***
+./SkMaskFilter.h:41:class SkMaskFilter : public SkFlattenable { -- abstract chmod +w .h
+ ./SkEmbossMaskFilter.h:27:class SkEmbossMaskFilter : public SkMaskFilter { -- tested
+./SkPathEffect.h:33:class SkPathEffect : public SkFlattenable { -- abstract
+ ./Sk1DPathEffect.h:27:class Sk1DPathEffect : public SkPathEffect { -- abstract
+ ./Sk1DPathEffect.h:48:class SkPath1DPathEffect : public Sk1DPathEffect { -- tested
+ ./Sk2DPathEffect.h:25:class Sk2DPathEffect : public SkPathEffect { *** untested ***
+ ./SkCornerPathEffect.h:28:class SkCornerPathEffect : public SkPathEffect { *** untested ***
+ ./SkDashPathEffect.h:27:class SkDashPathEffect : public SkPathEffect {
+ ./SkDiscretePathEffect.h:27:class SkDiscretePathEffect : public SkPathEffect {
+ ./SkPaint.h:760:class SkStrokePathEffect : public SkPathEffect {
+ ./SkPathEffect.h:58:class SkPairPathEffect : public SkPathEffect {
+ ./SkPathEffect.h:78:class SkComposePathEffect : public SkPairPathEffect {
+ ./SkPathEffect.h:114:class SkSumPathEffect : public SkPairPathEffect {
+./SkRasterizer.h:29:class SkRasterizer : public SkFlattenable {
+ ./SkLayerRasterizer.h:27:class SkLayerRasterizer : public SkRasterizer {
+./SkShader.h:36:class SkShader : public SkFlattenable {
+ ./SkColorFilter.h:59:class SkFilterShader : public SkShader {
+ ./SkColorShader.h:26:class SkColorShader : public SkShader {
+ ./SkShaderExtras.h:31:class SkComposeShader : public SkShader {
+ ./SkTransparentShader.h:23:class SkTransparentShader : public SkShader {
+./SkUnitMapper.h:24:class SkUnitMapper : public SkFlattenable {
+ ./SkUnitMapper.h:33:class SkDiscreteMapper : public SkUnitMapper {
+ ./SkUnitMapper.h:51:class SkFlipCosineMapper : public SkUnitMapper {
+./SkXfermode.h:32:class SkXfermode : public SkFlattenable {
+ ./SkAvoidXfermode.h:28:class SkAvoidXfermode : public SkXfermode { *** not done *** chmod +w .h .cpp
+ ./SkXfermode.h:54:class SkProcXfermode : public SkXfermode {
+ */
+
+ /*
+./SkBlurMaskFilter.h:25:class SkBlurMaskFilter {
+ chmod +w SkBlurMaskFilter.cpp
+./SkGradientShader.h:30:class SkGradientShader {
+ */
+ // save layer, bounder, looper
+ // matrix
+ // clip /path/region
+ // bitmap proc shader ?
+
+/* untested:
+SkCornerPathEffect.h:28:class SkCornerPathEffect : public SkPathEffect {
+*/
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ fClickPt.set(x, y);
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ SkPathEffect* pathEffectTest()
+ {
+ static const int gXY[] = { 1, 0, 0, -1, 2, -1, 3, 0, 2, 1, 0, 1 };
+ SkScalar gPhase = 0;
+ SkPath path;
+ path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
+ for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
+ path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
+ path.close();
+ path.offset(SkIntToScalar(-6), 0);
+ SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12),
+ gPhase, SkPath1DPathEffect::kRotate_Style);
+ SkPathEffect* inner = new SkDiscretePathEffect(SkIntToScalar(2),
+ SkIntToScalar(1)/10); // SkCornerPathEffect(SkIntToScalar(2));
+ SkPathEffect* result = new SkComposePathEffect(outer, inner);
+ outer->unref();
+ inner->unref();
+ return result;
+ }
+
+ SkPathEffect* pathEffectTest2() // unsure this works (has no visible effect)
+ {
+ SkPathEffect* outer = new SkStrokePathEffect(SkIntToScalar(4),
+ SkPaint::kStroke_Style, SkPaint::kMiter_Join, SkPaint::kButt_Cap);
+ static const SkScalar intervals[] = {SkIntToScalar(1), SkIntToScalar(2),
+ SkIntToScalar(2), SkIntToScalar(1)};
+ SkPathEffect* inner = new SkDashPathEffect(intervals,
+ sizeof(intervals) / sizeof(intervals[0]), 0);
+ SkPathEffect* result = new SkSumPathEffect(outer, inner);
+ outer->unref();
+ inner->unref();
+ return result;
+ }
+
+ SkShader* shaderTest()
+ {
+ SkPoint pts[] = {0, 0, SkIntToScalar(100), 0 };
+ SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
+ SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, NULL,
+ 2, SkShader::kClamp_TileMode);
+ pts[1].set(0, SkIntToScalar(100));
+ SkColor colors2[] = {SK_ColorBLACK, SkColorSetARGB(0x80, 0, 0, 0)};
+ SkShader* shaderB = SkGradientShader::CreateLinear(pts, colors2, NULL,
+ 2, SkShader::kClamp_TileMode);
+ SkXfermode* mode = SkPorterDuff::CreateXfermode(SkPorterDuff::kDstIn_Mode);
+ SkShader* result = new SkComposeShader(shaderA, shaderB, mode);
+ shaderA->unref();
+ shaderB->unref();
+ mode->unref();
+ return result;
+ }
+
+ virtual void startTest() {
+ SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/bugcirc.gif", &fBug);
+ SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/tbcirc.gif", &fTb);
+ SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/05psp04.gif", &fTx);
+ }
+
+ void drawRaster(SkCanvas* canvas)
+ {
+ for (int index = 0; index < SK_ARRAY_COUNT(gRastProcs); index++)
+ drawOneRaster(canvas);
+ }
+
+ void drawOneRaster(SkCanvas* canvas)
+ {
+ canvas->save();
+// canvas->scale(SK_Scalar1*2, SK_Scalar1*2, 0, 0);
+
+ SkScalar x = SkIntToScalar(20);
+ SkScalar y = SkIntToScalar(40);
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setTextSize(SkIntToScalar(48));
+ paint.setTypeface(SkTypeface::Create("sans-serif", SkTypeface::kBold));
+
+ SkString str("GOOGLE");
+
+ for (int i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++)
+ {
+ apply_shader(&paint, i);
+
+ // paint.setMaskFilter(NULL);
+ // paint.setColor(SK_ColorBLACK);
+
+#if 01
+ int index = i % SK_ARRAY_COUNT(gLightingColors);
+ paint.setColorFilter(SkColorFilter::CreateLightingFilter(
+ gLightingColors[index].fMul,
+ gLightingColors[index].fAdd))->unref();
+#endif
+
+ canvas->drawText(str.c_str(), str.size(), x, y, paint);
+ SkRect oval = { x, y - SkIntToScalar(40), x + SkIntToScalar(40), y };
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawOval(oval, paint);
+ paint.setStyle(SkPaint::kFill_Style);
+ if (0)
+ {
+ SkPath path;
+ paint.getTextPath(str.c_str(), str.size(), x + SkIntToScalar(260), y, &path);
+ canvas->drawPath(path, paint);
+ }
+
+ y += paint.getFontSpacing();
+ }
+
+ canvas->restore();
+
+ if (0)
+ {
+ SkPoint pts[] = { 0, 0, 0, SkIntToScalar(150) };
+ SkColor colors[] = { 0xFFE6E6E6, 0xFFFFFFFF };
+ SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode);
+
+ paint.reset();
+ paint.setShader(s)->unref();
+ canvas->drawRectCoords(0, 0, SkIntToScalar(120), SkIntToScalar(150), paint);
+ }
+
+ if (1)
+ {
+ SkAvoidXfermode mode(SK_ColorWHITE, 0xFF,
+ SkAvoidXfermode::kTargetColor_Mode);
+ SkPaint paint;
+ x += SkIntToScalar(20);
+ SkRect r = { x, 0, x + SkIntToScalar(360), SkIntToScalar(700) };
+ paint.setXfermode(&mode);
+ paint.setColor(SK_ColorGREEN);
+ paint.setAntiAlias(true);
+ canvas->drawOval(r, paint);
+ }
+ }
+
+private:
+ SkPoint fClickPt;
+ SkBitmap fBug, fTb, fTx;
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new DemoView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
new file mode 100644
index 0000000..0d2bbbc
--- /dev/null
+++ b/samplecode/SampleApp.cpp
@@ -0,0 +1,607 @@
+#include "SkCanvas.h"
+#include "SkDevice.h"
+#include "SkGLCanvas.h"
+#include "SkGraphics.h"
+#include "SkImageEncoder.h"
+#include "SkPaint.h"
+#include "SkPicture.h"
+#include "SkStream.h"
+#include "SkWindow.h"
+
+#include "SampleCode.h"
+
+//#define SK_SUPPORT_GL
+
+#ifdef SK_SUPPORT_GL
+#include <AGL/agl.h>
+#include <OpenGL/gl.h>
+#endif
+
+#define ANIMATING_EVENTTYPE "nextSample"
+#define ANIMATING_DELAY 750
+
+#define USE_OFFSCREEN
+
+SkViewRegister* SkViewRegister::gHead;
+SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) {
+ static bool gOnce;
+ if (!gOnce) {
+ gHead = NULL;
+ gOnce = true;
+ }
+
+ fChain = gHead;
+ gHead = this;
+}
+
+#ifdef SK_SUPPORT_GL
+static AGLContext gAGLContext;
+
+static void init_gl(WindowRef wref) {
+ GLint major, minor;
+
+ aglGetVersion(&major, &minor);
+ SkDebugf("---- agl version %d %d\n", major, minor);
+
+ const GLint pixelAttrs[] = {
+ AGL_RGBA,
+ AGL_DEPTH_SIZE, 32,
+ AGL_OFFSCREEN,
+ AGL_NONE
+ };
+
+ AGLPixelFormat format = aglCreatePixelFormat(pixelAttrs);
+ SkDebugf("----- agl format %p\n", format);
+ gAGLContext = aglCreateContext(format, NULL);
+ SkDebugf("----- agl context %p\n", gAGLContext);
+ aglDestroyPixelFormat(format);
+
+ aglEnable(gAGLContext, GL_BLEND);
+ aglEnable(gAGLContext, GL_LINE_SMOOTH);
+ aglEnable(gAGLContext, GL_POINT_SMOOTH);
+ aglEnable(gAGLContext, GL_POLYGON_SMOOTH);
+
+ aglSetCurrentContext(gAGLContext);
+}
+
+static void setup_offscreen_gl(const SkBitmap& offscreen, WindowRef wref) {
+ GLboolean success = true;
+
+#ifdef USE_OFFSCREEN
+ success = aglSetOffScreen(gAGLContext,
+ offscreen.width(),
+ offscreen.height(),
+ offscreen.rowBytes(),
+ offscreen.getPixels());
+#else
+ success = aglSetWindowRef(gAGLContext, wref);
+#endif
+
+ GLenum err = aglGetError();
+ if (err) {
+ SkDebugf("---- setoffscreen %d %d %s [%d %d]\n", success, err,
+ aglErrorString(err), offscreen.width(), offscreen.height());
+ }
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
+ glEnable(GL_TEXTURE_2D);
+
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+
+static const char gTitleEvtName[] = "SampleCode_Title_Event";
+static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event";
+
+bool SampleCode::TitleQ(const SkEvent& evt) {
+ return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1);
+}
+
+void SampleCode::TitleR(SkEvent* evt, const char title[]) {
+ SkASSERT(evt && TitleQ(*evt));
+ evt->setString(gTitleEvtName, title);
+}
+
+bool SampleCode::PrefSizeQ(const SkEvent& evt) {
+ return evt.isType(gPrefSizeEvtName, sizeof(gPrefSizeEvtName) - 1);
+}
+
+void SampleCode::PrefSizeR(SkEvent* evt, SkScalar width, SkScalar height) {
+ SkASSERT(evt && PrefSizeQ(*evt));
+ SkScalar size[2];
+ size[0] = width;
+ size[1] = height;
+ evt->setScalars(gPrefSizeEvtName, 2, size);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class SampleWindow : public SkOSWindow {
+public:
+ SampleWindow(void* hwnd);
+ virtual ~SampleWindow();
+
+protected:
+ virtual void onDraw(SkCanvas* canvas);
+ virtual bool onHandleKey(SkKey key);
+ virtual bool onHandleChar(SkUnichar);
+ virtual void onSizeChange();
+
+ virtual SkCanvas* beforeChildren(SkCanvas*);
+ virtual void afterChildren(SkCanvas*);
+
+ virtual bool onEvent(const SkEvent& evt);
+
+#if 0
+ virtual bool handleChar(SkUnichar uni);
+ virtual bool handleEvent(const SkEvent& evt);
+ virtual bool handleKey(SkKey key);
+ virtual bool handleKeyUp(SkKey key);
+
+ virtual bool onClick(Click* click);
+ virtual Click* onFindClickHandler(SkScalar x, SkScalar y);
+ virtual bool onHandleKeyUp(SkKey key);
+#endif
+private:
+ const SkViewRegister* fCurr;
+
+ SkPicture* fPicture;
+ SkGLCanvas* fGLCanvas;
+ SkPath fClipPath;
+
+ enum CanvasType {
+ kRaster_CanvasType,
+ kPicture_CanvasType,
+ kOpenGL_CanvasType
+ };
+ CanvasType fCanvasType;
+
+ bool fUseClip;
+ bool fRepeatDrawing;
+ bool fAnimating;
+
+ int fScrollTestX, fScrollTestY;
+
+ void loadView(SkView*);
+ void updateTitle();
+ bool nextSample();
+
+ void postAnimatingEvent() {
+ if (fAnimating) {
+ SkEvent* evt = new SkEvent(ANIMATING_EVENTTYPE);
+ evt->post(this->getSinkID(), ANIMATING_DELAY);
+ }
+ }
+
+
+ static CanvasType cycle_canvastype(CanvasType);
+
+ typedef SkOSWindow INHERITED;
+};
+
+SampleWindow::CanvasType SampleWindow::cycle_canvastype(CanvasType ct) {
+ static const CanvasType gCT[] = {
+ kPicture_CanvasType,
+ kOpenGL_CanvasType,
+ kRaster_CanvasType
+ };
+ return gCT[ct];
+}
+
+SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) {
+#ifdef SK_SUPPORT_GL
+ init_gl((WindowRef)hwnd);
+#endif
+
+ fPicture = NULL;
+ fGLCanvas = NULL;
+
+ fCanvasType = kRaster_CanvasType;
+ fUseClip = false;
+ fRepeatDrawing = false;
+ fAnimating = false;
+
+ fScrollTestX = fScrollTestY = 0;
+
+// this->setConfig(SkBitmap::kRGB_565_Config);
+ this->setConfig(SkBitmap::kARGB_8888_Config);
+ this->setVisibleP(true);
+
+ fCurr = SkViewRegister::Head();
+ this->loadView(fCurr->factory()());
+}
+
+SampleWindow::~SampleWindow() {
+ delete fPicture;
+ delete fGLCanvas;
+}
+
+void SampleWindow::onDraw(SkCanvas* canvas) {
+ if (fRepeatDrawing) {
+ this->inval(NULL);
+ }
+}
+
+#include "SkColorPriv.h"
+
+static void reverseRedAndBlue(const SkBitmap& bm) {
+ SkASSERT(bm.config() == SkBitmap::kARGB_8888_Config);
+ uint8_t* p = (uint8_t*)bm.getPixels();
+ uint8_t* stop = p + bm.getSize();
+ while (p < stop) {
+ // swap red/blue (to go from ARGB(int) to RGBA(memory) and premultiply
+ unsigned scale = SkAlpha255To256(p[3]);
+ unsigned r = p[2];
+ unsigned b = p[0];
+ p[0] = SkAlphaMul(r, scale);
+ p[1] = SkAlphaMul(p[1], scale);
+ p[2] = SkAlphaMul(b, scale);
+ p += 4;
+ }
+}
+
+SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
+#ifdef SK_SUPPORT_GL
+#ifndef USE_OFFSCREEN
+ aglSetWindowRef(gAGLContext, NULL);
+#endif
+#endif
+ switch (fCanvasType) {
+ case kRaster_CanvasType:
+ canvas = this->INHERITED::beforeChildren(canvas);
+ break;
+ case kPicture_CanvasType:
+ fPicture = new SkPicture;
+ canvas = fPicture->beginRecording(9999, 9999);
+ break;
+#ifdef SK_SUPPORT_GL
+ case kOpenGL_CanvasType: {
+ //SkGLCanvas::DeleteAllTextures(); // just for testing
+ SkDevice* device = canvas->getDevice();
+ const SkBitmap& bitmap = device->accessBitmap(true);
+ // first clear the raster bitmap, so we don't see any leftover bits
+ bitmap.eraseColor(0);
+ // now setup our glcanvas
+ setup_offscreen_gl(bitmap, (WindowRef)this->getHWND());
+ fGLCanvas = new SkGLCanvas;
+ fGLCanvas->setViewport(bitmap.width(), bitmap.height());
+ canvas = fGLCanvas;
+ break;
+ }
+#endif
+ }
+
+ if (fUseClip) {
+ canvas->drawColor(0xFFFF88FF);
+ canvas->clipPath(fClipPath);
+ }
+
+ return canvas;
+}
+
+static void paint_rgn(const SkBitmap& bm, const SkIRect& r,
+ const SkRegion& rgn) {
+ SkCanvas canvas(bm);
+ SkRegion inval(rgn);
+
+ inval.translate(r.fLeft, r.fTop);
+ canvas.clipRegion(inval);
+ canvas.drawColor(0xFFFF8080);
+}
+
+void SampleWindow::afterChildren(SkCanvas* orig) {
+ switch (fCanvasType) {
+ case kRaster_CanvasType:
+ break;
+ case kPicture_CanvasType:
+ if (false) {
+ SkPicture* pict = new SkPicture(*fPicture);
+ fPicture->unref();
+ orig->drawPicture(*pict);
+ pict->unref();
+ } if (true) {
+ SkDynamicMemoryWStream ostream;
+ fPicture->serialize(&ostream);
+ fPicture->unref();
+
+ SkMemoryStream istream(ostream.getStream(), ostream.getOffset());
+ SkPicture pict(&istream);
+ orig->drawPicture(pict);
+ } else {
+ fPicture->draw(orig);
+ fPicture->unref();
+ }
+ fPicture = NULL;
+ break;
+#ifdef SK_SUPPORT_GL
+ case kOpenGL_CanvasType:
+ glFlush();
+ delete fGLCanvas;
+ fGLCanvas = NULL;
+#ifdef USE_OFFSCREEN
+ reverseRedAndBlue(orig->getDevice()->accessBitmap(true));
+#endif
+ break;
+#endif
+ }
+
+// if ((fScrollTestX | fScrollTestY) != 0)
+ {
+ const SkBitmap& bm = orig->getDevice()->accessBitmap(true);
+ int dx = fScrollTestX * 7;
+ int dy = fScrollTestY * 7;
+ SkIRect r;
+ SkRegion inval;
+
+ r.set(50, 50, 50+100, 50+100);
+ bm.scrollRect(&r, dx, dy, &inval);
+ paint_rgn(bm, r, inval);
+ }
+}
+
+static SkBitmap::Config gConfigCycle[] = {
+ SkBitmap::kNo_Config, // none -> none
+ SkBitmap::kNo_Config, // a1 -> none
+ SkBitmap::kNo_Config, // a8 -> none
+ SkBitmap::kNo_Config, // index8 -> none
+ SkBitmap::kARGB_4444_Config, // 565 -> 4444
+ SkBitmap::kARGB_8888_Config, // 4444 -> 8888
+ SkBitmap::kRGB_565_Config // 8888 -> 565
+};
+
+static SkBitmap::Config cycle_configs(SkBitmap::Config c) {
+ return gConfigCycle[c];
+}
+
+bool SampleWindow::nextSample() {
+ if (fCurr) {
+ fCurr = fCurr->next();
+ if (NULL == fCurr) {
+ fCurr = SkViewRegister::Head();
+ }
+ this->loadView(fCurr->factory()());
+ return true;
+ }
+ return false;
+}
+
+bool SampleWindow::onEvent(const SkEvent& evt) {
+ if (evt.isType(ANIMATING_EVENTTYPE)) {
+ if (fAnimating) {
+ this->nextSample();
+ this->postAnimatingEvent();
+ }
+ return true;
+ }
+ return this->INHERITED::onEvent(evt);
+}
+
+static void cleanup_for_filename(SkString* name) {
+ char* str = name->writable_str();
+ for (int i = 0; i < name->size(); i++) {
+ switch (str[i]) {
+ case ':': str[i] = '-'; break;
+ case '/': str[i] = '-'; break;
+ case ' ': str[i] = '_'; break;
+ default: break;
+ }
+ }
+}
+
+bool SampleWindow::onHandleChar(SkUnichar uni) {
+ int dx = 0xFF;
+ int dy = 0xFF;
+
+ switch (uni) {
+ case '5': dx = 0; dy = 0; break;
+ case '8': dx = 0; dy = -1; break;
+ case '6': dx = 1; dy = 0; break;
+ case '2': dx = 0; dy = 1; break;
+ case '4': dx = -1; dy = 0; break;
+ case '7': dx = -1; dy = -1; break;
+ case '9': dx = 1; dy = -1; break;
+ case '3': dx = 1; dy = 1; break;
+ case '1': dx = -1; dy = 1; break;
+
+ default:
+ break;
+ }
+
+ if (0xFF != dx && 0xFF != dy) {
+ if ((dx | dy) == 0) {
+ fScrollTestX = fScrollTestY = 0;
+ } else {
+ fScrollTestX += dx;
+ fScrollTestY += dy;
+ }
+ this->inval(NULL);
+ return true;
+ }
+
+ switch (uni) {
+ case 'a':
+ fAnimating = !fAnimating;
+ this->postAnimatingEvent();
+ this->updateTitle();
+ return true;
+ case 'f': {
+ const char* title = this->getTitle();
+ if (title[0] == 0) {
+ title = "sampleapp";
+ }
+ SkString name(title);
+ cleanup_for_filename(&name);
+ name.append(".png");
+ if (SkImageEncoder::EncodeFile(name.c_str(), this->getBitmap(),
+ SkImageEncoder::kPNG_Type, 100)) {
+ SkDebugf("Created %s\n", name.c_str());
+ }
+ return true;
+ }
+ default:
+ break;
+ }
+
+ return this->INHERITED::onHandleChar(uni);
+}
+
+#include "SkDumpCanvas.h"
+
+bool SampleWindow::onHandleKey(SkKey key) {
+ switch (key) {
+ case kRight_SkKey:
+ if (this->nextSample()) {
+ return true;
+ }
+ break;
+ case kLeft_SkKey:
+ fCanvasType = cycle_canvastype(fCanvasType);
+ this->updateTitle();
+ this->inval(NULL);
+ return true;
+ case kUp_SkKey:
+ fUseClip = !fUseClip;
+ this->updateTitle();
+ this->inval(NULL);
+ return true;
+ case kDown_SkKey:
+ this->setConfig(cycle_configs(this->getBitmap().config()));
+ this->updateTitle();
+ return true;
+ case kOK_SkKey:
+ if (true) {
+ SkDebugfDumper dumper;
+ SkDumpCanvas dc(&dumper);
+ this->draw(&dc);
+ } else {
+ fRepeatDrawing = !fRepeatDrawing;
+ if (fRepeatDrawing) {
+ this->inval(NULL);
+ }
+ }
+ return true;
+ default:
+ break;
+ }
+ return this->INHERITED::onHandleKey(key);
+}
+
+void SampleWindow::loadView(SkView* view) {
+ SkView::F2BIter iter(this);
+ SkView* prev = iter.next();
+ if (prev) {
+ prev->detachFromParent();
+ }
+ view->setVisibleP(true);
+ this->attachChildToFront(view)->unref();
+ view->setSize(this->width(), this->height());
+
+ this->updateTitle();
+}
+
+static const char* gConfigNames[] = {
+ "unknown config",
+ "A1",
+ "A8",
+ "Index8",
+ "565",
+ "4444",
+ "8888"
+};
+
+static const char* configToString(SkBitmap::Config c) {
+ return gConfigNames[c];
+}
+
+static const char* gCanvasTypePrefix[] = {
+ "raster: ",
+ "picture: ",
+ "opengl: "
+};
+
+void SampleWindow::updateTitle() {
+ SkString title;
+
+ SkView::F2BIter iter(this);
+ SkView* view = iter.next();
+ SkEvent evt(gTitleEvtName);
+ if (view->doQuery(&evt)) {
+ title.set(evt.findString(gTitleEvtName));
+ }
+ if (title.size() == 0) {
+ title.set("<unknown>");
+ }
+
+ title.prepend(gCanvasTypePrefix[fCanvasType]);
+
+ title.prepend(" ");
+ title.prepend(configToString(this->getBitmap().config()));
+
+ if (fAnimating) {
+ title.prepend("<A> ");
+ }
+
+ this->setTitle(title.c_str());
+}
+
+void SampleWindow::onSizeChange() {
+ this->INHERITED::onSizeChange();
+
+ SkView::F2BIter iter(this);
+ SkView* view = iter.next();
+ view->setSize(this->width(), this->height());
+
+ // rebuild our clippath
+ {
+ const SkScalar W = this->width();
+ const SkScalar H = this->height();
+
+ fClipPath.reset();
+#if 0
+ for (SkScalar y = SK_Scalar1; y < H; y += SkIntToScalar(32)) {
+ SkRect r;
+ r.set(SK_Scalar1, y, SkIntToScalar(30), y + SkIntToScalar(30));
+ for (; r.fLeft < W; r.offset(SkIntToScalar(32), 0))
+ fClipPath.addRect(r);
+ }
+#else
+ SkRect r;
+ r.set(0, 0, W, H);
+ fClipPath.addRect(r, SkPath::kCCW_Direction);
+ r.set(W/4, H/4, W*3/4, H*3/4);
+ fClipPath.addRect(r, SkPath::kCW_Direction);
+#endif
+ }
+
+ this->updateTitle(); // to refresh our config
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkOSWindow* create_sk_window(void* hwnd) {
+ return new SampleWindow(hwnd);
+}
+
+void get_preferred_size(int* x, int* y, int* width, int* height) {
+ *x = 10;
+ *y = 50;
+ *width = 640;
+ *height = 480;
+}
+
+void application_init() {
+// setenv("ANDROID_ROOT", "../../../data", 0);
+ setenv("ANDROID_ROOT", "/android/device/data", 0);
+ SkGraphics::Init(true);
+ SkEvent::Init();
+}
+
+void application_term() {
+ SkEvent::Term();
+ SkGraphics::Term();
+}
diff --git a/samplecode/SampleArc.cpp b/samplecode/SampleArc.cpp
new file mode 100644
index 0000000..ada1d0a
--- /dev/null
+++ b/samplecode/SampleArc.cpp
@@ -0,0 +1,187 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkComposeShader.h"
+#include "Sk1DPathEffect.h"
+#include "SkCornerPathEffect.h"
+#include "SkPathMeasure.h"
+#include "SkRandom.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkPorterDuff.h"
+#include "SkLayerRasterizer.h"
+
+class ArcsView : public SkView {
+public:
+ ArcsView()
+ {
+ fSweep = SkIntToScalar(100);
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Arcs");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+ canvas->drawColor(0xFFDDDDDD);
+ }
+
+ static void drawRectWithLines(SkCanvas* canvas, const SkRect& r, const SkPaint& p)
+ {
+ canvas->drawRect(r, p);
+ canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, p);
+ canvas->drawLine(r.fLeft, r.fBottom, r.fRight, r.fTop, p);
+ canvas->drawLine(r.fLeft, r.centerY(), r.fRight, r.centerY(), p);
+ canvas->drawLine(r.centerX(), r.fTop, r.centerX(), r.fBottom, p);
+ }
+
+ static void draw_label(SkCanvas* canvas, const SkRect& rect,
+ int start, int sweep)
+ {
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setTextAlign(SkPaint::kCenter_Align);
+
+ SkString str;
+
+ str.appendS32(start);
+ str.append(", ");
+ str.appendS32(sweep);
+ canvas->drawText(str.c_str(), str.size(), rect.centerX(),
+ rect.fBottom + paint.getTextSize() * 5/4, paint);
+ }
+
+ static void drawArcs(SkCanvas* canvas)
+ {
+ SkPaint paint;
+ SkRect r;
+ SkScalar w = SkIntToScalar(75);
+ SkScalar h = SkIntToScalar(50);
+
+ r.set(0, 0, w, h);
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+
+ canvas->save();
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(300));
+
+ paint.setStrokeWidth(SkIntToScalar(1));
+
+ static const int gAngles[] = {
+ 0, 360,
+ 0, 45,
+ 0, -45,
+ 720, 135,
+ -90, 269,
+ -90, 270,
+ -90, 271,
+ -180, -270,
+ 225, 90
+ };
+
+ for (int i = 0; i < SK_ARRAY_COUNT(gAngles); i += 2)
+ {
+ paint.setColor(SK_ColorBLACK);
+ drawRectWithLines(canvas, r, paint);
+
+ paint.setColor(SK_ColorRED);
+ canvas->drawArc(r, SkIntToScalar(gAngles[i]),
+ SkIntToScalar(gAngles[i+1]), false, paint);
+
+ draw_label(canvas, r, gAngles[i], gAngles[i+1]);
+
+ canvas->translate(w * 8 / 7, 0);
+ }
+
+ canvas->restore();
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ SkRect r;
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setStrokeWidth(SkIntToScalar(2));
+ paint.setStyle(SkPaint::kStroke_Style);
+
+ r.set(0, 0, SkIntToScalar(200), SkIntToScalar(200));
+ r.offset(SkIntToScalar(20), SkIntToScalar(20));
+
+ if (false) {
+ const SkScalar d = SkIntToScalar(3);
+ const SkScalar rad[] = { d, d, d, d, d, d, d, d };
+ SkPath path;
+ path.addRoundRect(r, rad);
+ canvas->drawPath(path, paint);
+ return;
+ }
+
+ drawRectWithLines(canvas, r, paint);
+
+ // printf("----- sweep %g %X\n", SkScalarToFloat(fSweep), SkDegreesToRadians(fSweep));
+
+
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor(0x800000FF);
+ canvas->drawArc(r, 0, fSweep, true, paint);
+
+ paint.setColor(0x800FF000);
+ canvas->drawArc(r, 0, fSweep, false, paint);
+
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setColor(SK_ColorRED);
+ canvas->drawArc(r, 0, fSweep, true, paint);
+
+ paint.setStrokeWidth(0);
+ paint.setColor(SK_ColorBLUE);
+ canvas->drawArc(r, 0, fSweep, false, paint);
+
+ fSweep += SK_Scalar1/4;
+ if (fSweep > SkIntToScalar(360))
+ fSweep = 0;
+
+ drawArcs(canvas);
+ this->inval(NULL);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ // fSweep += SK_Scalar1;
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ SkScalar fSweep;
+
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new ArcsView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleBitmapRect.cpp b/samplecode/SampleBitmapRect.cpp
new file mode 100644
index 0000000..f164e06
--- /dev/null
+++ b/samplecode/SampleBitmapRect.cpp
@@ -0,0 +1,110 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkPath.h"
+#include "SkPorterDuff.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+
+#include "SkImageRef.h"
+#include "SkOSFile.h"
+#include "SkStream.h"
+
+#define SPECIFIC_IMAGE "/skimages/main.gif"
+
+class BitmapRectView : public SkView {
+public:
+ SkBitmap fBitmap;
+ int fCurrX, fCurrY;
+
+ BitmapRectView() {
+ SkImageDecoder::DecodeFile(SPECIFIC_IMAGE, &fBitmap);
+ fCurrX = fCurrY = 0;
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SkString str("BitmapRect: ");
+ str.append(SPECIFIC_IMAGE);
+ SampleCode::TitleR(evt, str.c_str());
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+ canvas->drawColor(SK_ColorGRAY);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ canvas->drawBitmap(fBitmap, 0, 0, NULL);
+
+ SkIRect subset;
+ const int SRC_WIDTH = 16;
+ const int SRC_HEIGHT = 16;
+
+ subset.set(0, 0, SRC_WIDTH, SRC_HEIGHT);
+ subset.offset(fCurrX, fCurrY);
+
+ SkDebugf("---- src x=%d y=%d\n", subset.fLeft, subset.fTop);
+
+ SkRect dst0, dst1;
+ SkScalar y = SkIntToScalar(fBitmap.height() + 16);
+
+ dst0.set(SkIntToScalar(50), y,
+ SkIntToScalar(50+SRC_WIDTH),
+ y + SkIntToScalar(SRC_HEIGHT));
+ dst1 = dst0;
+ dst1.offset(SkIntToScalar(200), 0);
+ dst1.fRight = dst1.fLeft + 8 * dst0.width();
+ dst1.fBottom = dst1.fTop + 8 * dst0.height();
+
+ canvas->drawBitmapRect(fBitmap, &subset, dst0, NULL);
+ canvas->drawBitmapRect(fBitmap, &subset, dst1, NULL);
+
+ SkPaint paint;
+ paint.setColor(0x88FF0000);
+ canvas->drawRect(dst0, paint);
+ paint.setColor(0x880000FF);
+ canvas->drawRect(dst1, paint);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ return new Click(this);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ fCurrX = click->fICurr.fX;
+ fCurrY = click->fICurr.fY;
+ this->inval(NULL);
+ return true;
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new BitmapRectView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleCamera.cpp b/samplecode/SampleCamera.cpp
new file mode 100644
index 0000000..9a8d1ef
--- /dev/null
+++ b/samplecode/SampleCamera.cpp
@@ -0,0 +1,106 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkCamera.h"
+#include "SkEmbossMaskFilter.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkRandom.h"
+
+class CameraView : public SkView {
+public:
+ CameraView()
+ {
+ fRX = fRY = fRZ = 0;
+ }
+
+ virtual ~CameraView()
+ {
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Camera");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+ canvas->drawColor(0xFFDDDDDD);
+// canvas->drawColor(0, SkPorterDuff::kClear_Mode);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ canvas->translate(this->width()/2, this->height()/2);
+
+ Sk3DView view;
+ view.rotateX(SkIntToScalar(fRX));
+ view.rotateY(SkIntToScalar(fRY));
+ view.applyToCanvas(canvas);
+
+ SkPaint paint;
+ SkScalar rad = SkIntToScalar(50);
+ SkScalar dim = rad*2;
+
+ if (view.dotWithNormal(0, 0, SK_Scalar1) < 0) {
+ paint.setColor(SK_ColorRED);
+ }
+
+ paint.setAntiAlias(true);
+
+#if 0
+ SkEmbossMaskFilter::Light light;
+ light.fDirection[0] = SK_Scalar1;
+ light.fDirection[1] = SK_Scalar1;
+ light.fDirection[2] = SK_Scalar1;
+ light.fAmbient = 180;
+ light.fSpecular = 16 * 2;
+ paint.setMaskFilter(new SkEmbossMaskFilter(light, SkIntToScalar(4)));
+#endif
+
+ canvas->drawCircle(0, 0, rad, paint);
+ canvas->drawCircle(-dim, -dim, rad, paint);
+ canvas->drawCircle(-dim, dim, rad, paint);
+ canvas->drawCircle( dim, -dim, rad, paint);
+ canvas->drawCircle( dim, dim, rad, paint);
+
+ fRY += 1;
+ if (fRY >= 360)
+ fRY = 0;
+ this->inval(NULL);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ SkScalar angle = SkScalarDiv(this->height()/2 - y, this->height());
+ fRX = SkScalarRound(angle * 180);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ int fRX, fRY, fRZ;
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new CameraView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleCircle.cpp b/samplecode/SampleCircle.cpp
new file mode 100644
index 0000000..bfb92d4
--- /dev/null
+++ b/samplecode/SampleCircle.cpp
@@ -0,0 +1,137 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkDevice.h"
+#include "SkPaint.h"
+
+// ensure that we don't accidentally screw up the bounds when the oval is
+// fractional, and the impl computes the center and radii, and uses them to
+// reconstruct the edges of the circle.
+// see bug# 1504910
+static void test_circlebounds(SkCanvas* canvas) {
+#ifdef SK_SCALAR_IS_FLOAT
+ SkRect r = { 1.39999998, 1, 21.3999996, 21 };
+ SkPath p;
+ p.addOval(r);
+ SkRect r2;
+ p.computeBounds(&r2, SkPath::kFast_BoundsType);
+ SkASSERT(r == r2);
+#endif
+}
+
+class CircleView : public SkView {
+public:
+ static const SkScalar ANIM_DX = SK_Scalar1 / 67;
+ static const SkScalar ANIM_DY = SK_Scalar1 / 29;
+ static const SkScalar ANIM_RAD = SK_Scalar1 / 19;
+ SkScalar fDX, fDY, fRAD;
+
+ CircleView() {
+ fDX = fDY = fRAD = 0;
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Circles");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorWHITE);
+ }
+
+ void circle(SkCanvas* canvas, int width, bool aa) {
+ SkPaint paint;
+
+ paint.setAntiAlias(aa);
+ if (width < 0) {
+ paint.setStyle(SkPaint::kFill_Style);
+ } else {
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(width));
+ }
+ canvas->drawCircle(0, 0, SkIntToScalar(9) + fRAD, paint);
+ }
+
+ void drawSix(SkCanvas* canvas, SkScalar dx, SkScalar dy) {
+ for (int width = -1; width <= 1; width++) {
+ canvas->save();
+ circle(canvas, width, false);
+ canvas->translate(0, dy);
+ circle(canvas, width, true);
+ canvas->restore();
+ canvas->translate(dx, 0);
+ }
+ }
+
+ static void blowup(SkCanvas* canvas, const SkIRect& src, const SkRect& dst) {
+ SkDevice* device = canvas->getDevice();
+ const SkBitmap& bm = device->accessBitmap(false);
+ canvas->drawBitmapRect(bm, &src, dst, NULL);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ test_circlebounds(canvas);
+
+ if (false) {
+ // canvas->translate(SK_ScalarHalf, SK_ScalarHalf);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawCircle(SkIntToScalar(10), SkIntToScalar(10), SkIntToScalar(2), paint);
+
+ SkIRect r;
+ r.set(7, 7, 13, 13);
+ SkRect dst;
+ dst.set(SkIntToScalar(100), SkIntToScalar(10), SkIntToScalar(200), SkIntToScalar(110));
+ blowup(canvas, r, dst);
+ return;
+ }
+
+ // test that degenerate rects do nothing
+ if (true) {
+ SkScalar x = SkIntToScalar(30);
+ SkRect r;
+ r.set(x, x, x, x);
+ SkPaint p;
+ canvas->drawRect(r, p);
+ p.setAntiAlias(true);
+ canvas->drawRect(r, p);
+ }
+
+ SkScalar dx = SkIntToScalar(32);
+ SkScalar dy = SkIntToScalar(32);
+
+ canvas->translate(dx + fDX, dy + fDY);
+ drawSix(canvas, dx, dy);
+
+ canvas->translate(dx, 0);
+ canvas->translate(SK_ScalarHalf, SK_ScalarHalf);
+ drawSix(canvas, dx, dy);
+
+ fDX += ANIM_DX;
+ fDY += ANIM_DY;
+ fRAD += ANIM_RAD;
+ this->inval(NULL);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+const SkScalar CircleView::ANIM_DX;
+const SkScalar CircleView::ANIM_DY;
+const SkScalar CircleView::ANIM_RAD;
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new CircleView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleCode.h b/samplecode/SampleCode.h
new file mode 100644
index 0000000..ff660f2
--- /dev/null
+++ b/samplecode/SampleCode.h
@@ -0,0 +1,38 @@
+#ifndef SampleCode_DEFINED
+#define SampleCode_DEFINED
+
+#include "SkEvent.h"
+
+class SampleCode {
+public:
+ static bool TitleQ(const SkEvent&);
+ static void TitleR(SkEvent*, const char title[]);
+
+ static bool PrefSizeQ(const SkEvent&);
+ static void PrefSizeR(SkEvent*, SkScalar width, SkScalar height);
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+class SkView;
+
+typedef SkView* (*SkViewFactory)();
+
+class SkViewRegister : SkNoncopyable {
+public:
+ SkViewRegister(SkViewFactory);
+
+ static const SkViewRegister* Head() { return gHead; }
+
+ SkViewRegister* next() const { return fChain; }
+ SkViewFactory factory() const { return fFact; }
+
+private:
+ SkViewFactory fFact;
+ SkViewRegister* fChain;
+
+ static SkViewRegister* gHead;
+};
+
+#endif
+
diff --git a/samplecode/SampleCull.cpp b/samplecode/SampleCull.cpp
new file mode 100644
index 0000000..ea1bb77
--- /dev/null
+++ b/samplecode/SampleCull.cpp
@@ -0,0 +1,230 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkCornerPathEffect.h"
+#include "SkCullPoints.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkRandom.h"
+
+static void addbump(SkPath* path, const SkPoint pts[2], SkScalar bump)
+{
+ SkVector tang;
+
+ tang.setLength(pts[1].fX - pts[0].fX, pts[1].fY - pts[0].fY, bump);
+
+ path->lineTo(SkScalarHalf(pts[0].fX + pts[1].fX) - tang.fY,
+ SkScalarHalf(pts[0].fY + pts[1].fY) + tang.fX);
+ path->lineTo(pts[1]);
+}
+
+static void subdivide(SkPath* path, SkScalar bump)
+{
+ SkPath::Iter iter(*path, false);
+ SkPoint pts[4];
+ SkPath tmp;
+
+ for (;;)
+ switch (iter.next(pts)) {
+ case SkPath::kMove_Verb:
+ tmp.moveTo(pts[0]);
+ break;
+ case SkPath::kLine_Verb:
+ addbump(&tmp, pts, bump);
+ bump = -bump;
+ break;
+ case SkPath::kDone_Verb:
+ goto FINISH;
+ default:
+ break;
+ }
+
+FINISH:
+ path->swap(tmp);
+}
+
+static SkIPoint* getpts(const SkPath& path, int* count)
+{
+ SkPoint pts[4];
+ int n = 1;
+ SkIPoint* array;
+
+ {
+ SkPath::Iter iter(path, false);
+ for (;;)
+ switch (iter.next(pts)) {
+ case SkPath::kLine_Verb:
+ n += 1;
+ break;
+ case SkPath::kDone_Verb:
+ goto FINISHED;
+ default:
+ break;
+ }
+ }
+
+FINISHED:
+ array = new SkIPoint[n];
+ n = 0;
+
+ {
+ SkPath::Iter iter(path, false);
+ for (;;)
+ switch (iter.next(pts)) {
+ case SkPath::kMove_Verb:
+ array[n++].set(SkScalarRound(pts[0].fX), SkScalarRound(pts[0].fY));
+ break;
+ case SkPath::kLine_Verb:
+ array[n++].set(SkScalarRound(pts[1].fX), SkScalarRound(pts[1].fY));
+ break;
+ case SkPath::kDone_Verb:
+ goto FINISHED2;
+ default:
+ break;
+ }
+ }
+
+FINISHED2:
+ *count = n;
+ return array;
+}
+
+static SkScalar nextScalarRange(SkRandom& rand, SkScalar min, SkScalar max)
+{
+ return min + SkScalarMul(rand.nextUScalar1(), max - min);
+}
+
+class CullView : public SkView {
+public:
+ CullView()
+ {
+ fClip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
+
+ SkRandom rand;
+
+ for (int i = 0; i < 50; i++) {
+ int x = nextScalarRange(rand, -fClip.width()*1, fClip.width()*2);
+ int y = nextScalarRange(rand, -fClip.height()*1, fClip.height()*2);
+ if (i == 0)
+ fPath.moveTo(x, y);
+ else
+ fPath.lineTo(x, y);
+ }
+
+ SkScalar bump = fClip.width()/8;
+ subdivide(&fPath, bump);
+ subdivide(&fPath, bump);
+ subdivide(&fPath, bump);
+ fPoints = getpts(fPath, &fPtCount);
+ }
+
+ virtual ~CullView()
+ {
+ delete[] fPoints;
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Culling");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+ canvas->drawColor(0xFFDDDDDD);
+
+ #if 0
+ SkPaint paint;
+
+ paint.setAntiAliasOn(true);
+ paint.setTextSize(SkIntToScalar(20));
+ paint.setTypeface(SkTypeface::Create("serif", SkTypeface::kBoldItalic))->unref();
+
+ uint16_t text[20];
+
+ text[0] = 'H';
+ text[1] = 'i';
+ text[2] = ' ';
+ for (int i = 3; i < 20; i++)
+ text[i] = 0x3040 + i;
+ canvas->drawText16(text, 20, SkIntToScalar(20), SkIntToScalar(20), paint);
+ #endif
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ SkAutoCanvasRestore ar(canvas, true);
+
+ canvas->translate( SkScalarHalf(this->width() - fClip.width()),
+ SkScalarHalf(this->height() - fClip.height()));
+
+ // canvas->scale(SK_Scalar1*3, SK_Scalar1*3, 0, 0);
+
+ SkPaint paint;
+
+ // paint.setAntiAliasOn(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+
+ canvas->drawRect(fClip, paint);
+
+#if 1
+ paint.setColor(0xFF555555);
+ paint.setStrokeWidth(SkIntToScalar(2));
+// paint.setPathEffect(new SkCornerPathEffect(SkIntToScalar(30)))->unref();
+ canvas->drawPath(fPath, paint);
+// paint.setPathEffect(NULL);
+#endif
+
+ SkPath tmp;
+ SkIRect iclip;
+ fClip.round(&iclip);
+
+ SkCullPointsPath cpp(iclip, &tmp);
+
+ cpp.moveTo(fPoints[0].fX, fPoints[0].fY);
+ for (int i = 0; i < fPtCount; i++)
+ cpp.lineTo(fPoints[i].fX, fPoints[i].fY);
+
+ paint.setColor(SK_ColorRED);
+ paint.setStrokeWidth(SkIntToScalar(3));
+ paint.setStrokeJoin(SkPaint::kRound_Join);
+ canvas->drawPath(tmp, paint);
+
+ this->inval(NULL);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ SkRect fClip;
+ SkIPoint* fPoints;
+ SkPath fPath;
+ int fPtCount;
+
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new CullView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleDither.cpp b/samplecode/SampleDither.cpp
new file mode 100644
index 0000000..64af007
--- /dev/null
+++ b/samplecode/SampleDither.cpp
@@ -0,0 +1,197 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "Sk1DPathEffect.h"
+#include "SkCornerPathEffect.h"
+#include "SkPathMeasure.h"
+#include "SkRandom.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkDither.h"
+
+static void draw_sweep(SkCanvas* c, int width, int height, SkScalar angle) {
+ SkRect r;
+ SkPaint p;
+
+ p.setAntiAlias(true);
+// p.setDither(true);
+ p.setStrokeWidth(SkIntToScalar(width/10));
+ p.setStyle(SkPaint::kStroke_Style);
+
+ r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
+
+ // SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN, SK_ColorCYAN };
+ SkColor colors[] = { 0x4c737373, 0x4c737373, 0xffffd300 };
+ SkShader* s = SkGradientShader::CreateSweep(r.centerX(), r.centerY(),
+ colors, NULL, SK_ARRAY_COUNT(colors));
+ p.setShader(s)->unref();
+
+ SkAutoCanvasRestore acr(c, true);
+
+ c->translate(r.centerX(), r.centerY());
+ c->rotate(angle);
+ c->translate(-r.centerX(), -r.centerY());
+
+ SkRect bounds = r;
+ r.inset(p.getStrokeWidth(), p.getStrokeWidth());
+ SkRect innerBounds = r;
+
+ if (true) {
+ c->drawOval(r, p);
+ } else {
+ SkScalar x = r.centerX();
+ SkScalar y = r.centerY();
+ SkScalar radius = r.width() / 2;
+ SkScalar thickness = p.getStrokeWidth();
+ SkScalar sweep = SkFloatToScalar(360.0f);
+ SkPath path;
+
+ path.moveTo(x + radius, y);
+ // outer top
+ path.lineTo(x + radius + thickness, y);
+ // outer arc
+ path.arcTo(bounds, 0, sweep, false);
+ // inner arc
+ path.arcTo(innerBounds, sweep, -sweep, false);
+ path.close();
+ }
+}
+
+static void make_bm(SkBitmap* bm)
+{
+ bm->setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
+ bm->allocPixels();
+#if 0
+ bm->eraseColor(SK_ColorBLUE);
+ return;
+#else
+ bm->eraseColor(0);
+#endif
+
+ SkCanvas c(*bm);
+ draw_sweep(&c, bm->width(), bm->height(), 0);
+}
+
+static void pre_dither(const SkBitmap& bm)
+{
+ SkAutoLockPixels alp(bm);
+
+ for (unsigned y = 0; y < bm.height(); y++) {
+ DITHER_4444_SCAN(y);
+
+ SkPMColor* p = bm.getAddr32(0, y);
+ for (unsigned x = 0; x < bm.width(); x++) {
+ SkPMColor c = *p;
+
+ unsigned a = SkGetPackedA32(c);
+ unsigned r = SkGetPackedR32(c);
+ unsigned g = SkGetPackedG32(c);
+ unsigned b = SkGetPackedB32(c);
+
+ unsigned d = DITHER_VALUE(x);
+
+ a = SkDITHER_A32To4444(a, d);
+ r = SkDITHER_R32To4444(r, d);
+ g = SkDITHER_G32To4444(g, d);
+ b = SkDITHER_B32To4444(b, d);
+
+ a = SkA4444ToA32(a);
+ r = SkR4444ToR32(r);
+ g = SkG4444ToG32(g);
+ b = SkB4444ToB32(b);
+
+ *p++ = SkPackARGB32(a, r, g, b);
+ }
+ }
+}
+
+class DitherView : public SkView {
+public:
+ SkBitmap fBM, fBMPreDither, fBM16;
+ SkScalar fAngle;
+
+ DitherView() {
+ make_bm(&fBM);
+ make_bm(&fBMPreDither);
+ pre_dither(fBMPreDither);
+ fBM.copyTo(&fBM16, SkBitmap::kARGB_4444_Config);
+
+ fAngle = 0;
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Dither");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+// canvas->drawColor(0xFFDDDDDD);
+ canvas->drawColor(0xFF181818);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ SkPaint paint;
+ SkScalar x = SkIntToScalar(10);
+ SkScalar y = SkIntToScalar(10);
+ const SkScalar DX = SkIntToScalar(fBM.width() + 10);
+
+ paint.setAntiAlias(true);
+
+ if (true) {
+ canvas->drawBitmap(fBM, x, y, &paint);
+ x += DX;
+ paint.setDither(true);
+ canvas->drawBitmap(fBM, x, y, &paint);
+
+ x += DX;
+ paint.setDither(false);
+ canvas->drawBitmap(fBMPreDither, x, y, &paint);
+
+ x += DX;
+ canvas->drawBitmap(fBM16, x, y, &paint);
+ }
+
+ canvas->translate(DX, DX*2);
+ draw_sweep(canvas, fBM.width(), fBM.height(), fAngle);
+ canvas->translate(DX, 0);
+ draw_sweep(canvas, fBM.width()>>1, fBM.height()>>1, fAngle);
+ canvas->translate(DX, 0);
+ draw_sweep(canvas, fBM.width()>>2, fBM.height()>>2, fAngle);
+
+ fAngle += SK_Scalar1/2;
+ this->inval(NULL);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ // fSweep += SK_Scalar1;
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new DitherView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleDrawLooper.cpp b/samplecode/SampleDrawLooper.cpp
new file mode 100644
index 0000000..1a7a870
--- /dev/null
+++ b/samplecode/SampleDrawLooper.cpp
@@ -0,0 +1,103 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGraphics.h"
+#include "SkRandom.h"
+#include "SkLayerDrawLooper.h"
+#include "SkBlurMaskFilter.h"
+
+#include <pthread.h>
+
+#define WIDTH 200
+#define HEIGHT 200
+
+class LooperView : public SkView {
+public:
+
+ SkLayerDrawLooper* fLooper;
+
+ LooperView() {
+ static const struct {
+ SkColor fColor;
+ SkPaint::Style fStyle;
+ SkScalar fWidth;
+ SkScalar fOffset;
+ int fBlur;
+ } gParams[] = {
+ { SK_ColorWHITE, SkPaint::kStroke_Style, SkIntToScalar(1)*3/4, 0, 0 },
+ { SK_ColorRED, SkPaint::kStroke_Style, SkIntToScalar(4), 0, 0 },
+ { SK_ColorBLUE, SkPaint::kFill_Style, 0, 0, 0 },
+ { 0x88000000, SkPaint::kFill_Style, 0, SkIntToScalar(10), 3 }
+ };
+
+ fLooper = new SkLayerDrawLooper;
+
+ for (int i = 0; i < SK_ARRAY_COUNT(gParams); i++) {
+ SkPaint* paint = fLooper->addLayer(gParams[i].fOffset,
+ gParams[i].fOffset);
+ paint->setAntiAlias(true);
+ paint->setColor(gParams[i].fColor);
+ paint->setStyle(gParams[i].fStyle);
+ paint->setStrokeWidth(gParams[i].fWidth);
+ paint->setTextSize(SkIntToScalar(72));
+ if (gParams[i].fBlur > 0) {
+ SkMaskFilter* mf = SkBlurMaskFilter::Create(SkIntToScalar(gParams[i].fBlur),
+ SkBlurMaskFilter::kNormal_BlurStyle);
+ paint->setMaskFilter(mf)->unref();
+ }
+ }
+ }
+
+ virtual ~LooperView() {
+ fLooper->safeUnref();
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "DrawLooper");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(0xFFDDDDDD);
+// canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ SkPaint paint;
+ paint.setLooper(fLooper);
+
+ canvas->drawCircle(SkIntToScalar(50), SkIntToScalar(50),
+ SkIntToScalar(30), paint);
+
+ canvas->drawRectCoords(SkIntToScalar(150), SkIntToScalar(50),
+ SkIntToScalar(200), SkIntToScalar(100), paint);
+
+ canvas->drawText("Looper", 6, SkIntToScalar(230), SkIntToScalar(100),
+ paint);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click) {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new LooperView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleEmboss.cpp b/samplecode/SampleEmboss.cpp
new file mode 100644
index 0000000..d12074f
--- /dev/null
+++ b/samplecode/SampleEmboss.cpp
@@ -0,0 +1,77 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "Sk64.h"
+#include "SkColorShader.h"
+#include "SkEmbossMaskFilter.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkKernel33MaskFilter.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+#include "SkXfermode.h"
+
+class EmbossView : public SkView {
+ SkEmbossMaskFilter::Light fLight;
+public:
+ EmbossView()
+ {
+ fLight.fDirection[0] = SK_Scalar1;
+ fLight.fDirection[1] = SK_Scalar1;
+ fLight.fDirection[2] = SK_Scalar1;
+ fLight.fAmbient = 128;
+ fLight.fSpecular = 16*2;
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Emboss");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+ canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(10));
+ paint.setMaskFilter(new SkEmbossMaskFilter(fLight, SkIntToScalar(4)))->unref();
+ paint.setShader(new SkColorShader(SK_ColorBLUE))->unref();
+ paint.setDither(true);
+
+ canvas->drawCircle(SkIntToScalar(50), SkIntToScalar(50),
+ SkIntToScalar(30), paint);
+ }
+
+private:
+
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new EmbossView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleEncode.cpp b/samplecode/SampleEncode.cpp
new file mode 100644
index 0000000..e4197bf
--- /dev/null
+++ b/samplecode/SampleEncode.cpp
@@ -0,0 +1,253 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageEncoder.h"
+#include "SkPath.h"
+#include "SkPorterDuff.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+
+#include "SkImageRef.h"
+#include "SkStream.h"
+
+static void make_image(SkBitmap* bm, SkBitmap::Config config, int configIndex) {
+ const int width = 98;
+ const int height = 100;
+ SkBitmap device;
+
+ device.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ device.allocPixels();
+
+ SkCanvas canvas(device);
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ canvas.drawColor(SK_ColorRED);
+ paint.setColor(SK_ColorBLUE);
+ canvas.drawCircle(SkIntToScalar(width)/2, SkIntToScalar(height)/2,
+ SkIntToScalar(width)/2, paint);
+
+ bm->setConfig(config, width, height);
+ switch (config) {
+ case SkBitmap::kARGB_8888_Config:
+ bm->swap(device);
+ break;
+ case SkBitmap::kRGB_565_Config: {
+ bm->allocPixels();
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ *bm->getAddr16(x, y) = SkPixel32ToPixel16(*device.getAddr32(x, y));
+ }
+ }
+ break;
+ }
+ case SkBitmap::kIndex8_Config: {
+ SkPMColor colors[256];
+ for (int i = 0; i < 256; i++) {
+ if (configIndex & 1) {
+ colors[i] = SkPackARGB32(255-i, 0, 0, 255-i);
+ } else {
+ colors[i] = SkPackARGB32(0xFF, i, 0, 255-i);
+ }
+ }
+ SkColorTable* ctable = new SkColorTable(colors, 256);
+ bm->allocPixels(ctable);
+ ctable->unref();
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ *bm->getAddr8(x, y) = SkGetPackedR32(*device.getAddr32(x, y));
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+// configs to build the original bitmap in. Can be at most these 3
+static const SkBitmap::Config gConfigs[] = {
+ SkBitmap::kARGB_8888_Config,
+ SkBitmap::kRGB_565_Config,
+ SkBitmap::kIndex8_Config, // opaque
+ SkBitmap::kIndex8_Config // alpha
+};
+
+static const char* const gConfigLabels[] = {
+ "8888", "565", "Index8", "Index8 alpha"
+};
+
+// types to encode into. Can be at most these 3. Must match up with gExt[]
+static const SkImageEncoder::Type gTypes[] = {
+ SkImageEncoder::kJPEG_Type,
+ SkImageEncoder::kPNG_Type
+};
+
+// must match up with gTypes[]
+static const char* const gExt[] = {
+ ".jpg", ".png"
+};
+
+static const char* gPath = "/encoded/";
+
+static void make_name(SkString* name, int config, int ext) {
+ name->set(gPath);
+ name->append(gConfigLabels[config]);
+ name->append(gExt[ext]);
+}
+
+#include <sys/stat.h>
+
+class EncodeView : public SkView {
+public:
+ SkBitmap* fBitmaps;
+ size_t fBitmapCount;
+
+ EncodeView() {
+ #if 1
+ (void)mkdir(gPath, S_IRWXU | S_IRWXG | S_IRWXO);
+
+ fBitmapCount = SK_ARRAY_COUNT(gConfigs);
+ fBitmaps = new SkBitmap[fBitmapCount];
+ for (size_t i = 0; i < fBitmapCount; i++) {
+ make_image(&fBitmaps[i], gConfigs[i], i);
+
+ for (size_t j = 0; j < SK_ARRAY_COUNT(gExt); j++) {
+ SkString path;
+ make_name(&path, i, j);
+
+ // remove any previous run of this file
+ remove(path.c_str());
+
+ SkImageEncoder* codec = SkImageEncoder::Create(gTypes[j]);
+ if (!codec->encodeFile(path.c_str(), fBitmaps[i], 100)) {
+ SkDebugf("------ failed to encode %s\n", path.c_str());
+ remove(path.c_str()); // remove any partial file
+ }
+ delete codec;
+ }
+ }
+ #else
+ fBitmaps = NULL;
+ fBitmapCount = 0;
+ #endif
+ }
+
+ virtual ~EncodeView() {
+ delete[] fBitmaps;
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "ImageEncoder");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(0xFFDDDDDD);
+// canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ if (fBitmapCount == 0) {
+ return;
+ }
+
+ SkPaint paint;
+ if (false) {
+// SkColor colors[] = { 0xFE000000, SK_ColorWHITE };
+ SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
+ SkShader* shader = SkGradientShader::CreateSweep(SkIntToScalar(50), SkIntToScalar(50),
+ colors, NULL, 2);
+ paint.setShader(shader)->unref();
+
+ SkRect r;
+ r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
+ canvas->drawRect(r, paint);
+
+ canvas->translate(SkIntToScalar(200), SkIntToScalar(200));
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(10));
+ canvas->drawOval(r, paint);
+ return;
+ }
+
+ paint.setAntiAlias(true);
+ paint.setTextAlign(SkPaint::kCenter_Align);
+
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
+
+ SkScalar x = 0, y = 0, maxX = 0;
+ const int SPACER = 10;
+
+ for (size_t i = 0; i < fBitmapCount; i++) {
+ canvas->drawText(gConfigLabels[i], strlen(gConfigLabels[i]),
+ x + SkIntToScalar(fBitmaps[i].width()) / 2, 0,
+ paint);
+ y = paint.getTextSize();
+
+ canvas->drawBitmap(fBitmaps[i], x, y);
+
+ SkScalar yy = y;
+ for (size_t j = 0; j < SK_ARRAY_COUNT(gExt); j++) {
+ yy += SkIntToScalar(fBitmaps[i].height() + 10);
+
+ SkBitmap bm;
+ SkString name;
+
+ make_name(&name, i, j);
+
+ SkImageDecoder::DecodeFile(name.c_str(), &bm);
+ canvas->drawBitmap(bm, x, yy);
+ }
+
+ x += SkIntToScalar(fBitmaps[i].width() + SPACER);
+ if (x > maxX) {
+ maxX = x;
+ }
+ }
+
+ y = (paint.getTextSize() + SkIntToScalar(fBitmaps[0].height())) * 3 / 2;
+ x = maxX + SkIntToScalar(10);
+ paint.setTextAlign(SkPaint::kLeft_Align);
+
+ for (size_t j = 0; j < SK_ARRAY_COUNT(gExt); j++) {
+ canvas->drawText(gExt[j], strlen(gExt[j]), x, y, paint);
+ y += SkIntToScalar(fBitmaps[0].height() + SPACER);
+ }
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click) {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new EncodeView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleFillType.cpp b/samplecode/SampleFillType.cpp
new file mode 100644
index 0000000..bb268cd
--- /dev/null
+++ b/samplecode/SampleFillType.cpp
@@ -0,0 +1,101 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkCornerPathEffect.h"
+#include "SkCullPoints.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+
+class FillTypeView : public SkView {
+ SkPath fPath;
+public:
+ FillTypeView() {
+ const SkScalar radius = SkIntToScalar(45);
+ fPath.addCircle(SkIntToScalar(50), SkIntToScalar(50), radius);
+ fPath.addCircle(SkIntToScalar(100), SkIntToScalar(100), radius);
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "FillType");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(0xFFDDDDDD);
+ }
+
+ void showPath(SkCanvas* canvas, int x, int y, SkPath::FillType ft,
+ SkScalar scale, const SkPaint& paint) {
+
+ const SkRect r = { 0, 0, SkIntToScalar(150), SkIntToScalar(150) };
+
+ canvas->save();
+ canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
+ canvas->clipRect(r);
+ canvas->drawColor(SK_ColorWHITE);
+ fPath.setFillType(ft);
+ canvas->translate(r.centerX(), r.centerY());
+ canvas->scale(scale, scale);
+ canvas->translate(-r.centerX(), -r.centerY());
+ canvas->drawPath(fPath, paint);
+ canvas->restore();
+ }
+
+ void showFour(SkCanvas* canvas, SkScalar scale, const SkPaint& paint) {
+ showPath(canvas, 0, 0, SkPath::kWinding_FillType,
+ scale, paint);
+ showPath(canvas, 200, 0, SkPath::kEvenOdd_FillType,
+ scale, paint);
+ showPath(canvas, 00, 200, SkPath::kInverseWinding_FillType,
+ scale, paint);
+ showPath(canvas, 200, 200, SkPath::kInverseEvenOdd_FillType,
+ scale, paint);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ drawBG(canvas);
+
+ canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
+
+ SkPaint paint;
+ const SkScalar scale = SkIntToScalar(5)/4;
+
+ paint.setAntiAlias(false);
+
+ showFour(canvas, SK_Scalar1, paint);
+ canvas->translate(SkIntToScalar(450), 0);
+ showFour(canvas, scale, paint);
+
+ paint.setAntiAlias(true);
+
+ canvas->translate(SkIntToScalar(-450), SkIntToScalar(450));
+ showFour(canvas, SK_Scalar1, paint);
+ canvas->translate(SkIntToScalar(450), 0);
+ showFour(canvas, scale, paint);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click) {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new FillTypeView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleFilter.cpp b/samplecode/SampleFilter.cpp
new file mode 100644
index 0000000..49d9c48
--- /dev/null
+++ b/samplecode/SampleFilter.cpp
@@ -0,0 +1,163 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "Sk1DPathEffect.h"
+#include "SkCornerPathEffect.h"
+#include "SkPathMeasure.h"
+#include "SkRandom.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkDither.h"
+
+static void make_bm(SkBitmap* bm)
+{
+ const SkColor colors[] = {
+ SK_ColorRED, SK_ColorGREEN,
+ SK_ColorBLUE, SK_ColorWHITE
+ };
+ SkColorTable* ctable = new SkColorTable(colors, 4);
+ bm->setConfig(SkBitmap::kIndex8_Config, 2, 2);
+ bm->allocPixels(ctable);
+ ctable->unref();
+
+ *bm->getAddr8(0, 0) = 0;
+ *bm->getAddr8(1, 0) = 1;
+ *bm->getAddr8(0, 1) = 2;
+ *bm->getAddr8(1, 1) = 3;
+}
+
+static SkScalar draw_bm(SkCanvas* canvas, const SkBitmap& bm,
+ SkScalar x, SkScalar y, SkPaint* paint)
+{
+#if 1
+ canvas->drawBitmap(bm, x, y, paint);
+ return SkIntToScalar(bm.width()) * 5/4;
+#else
+ SkRect r;
+
+ r.set(x, y,
+ x + SkIntToScalar(bm.width() * 2),
+ y + SkIntToScalar(bm.height() * 2));
+ SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode);
+ paint->setShader(s)->unref();
+ canvas->drawRect(r, *paint);
+ paint->setShader(NULL);
+ return r.width() * 5/4;
+#endif
+}
+
+static SkScalar draw_set(SkCanvas* c, const SkBitmap& bm, SkScalar x, SkPaint* p)
+{
+ x += draw_bm(c, bm, x, 0, p);
+ p->setFilterBitmap(true);
+ x += draw_bm(c, bm, x, 0, p);
+ p->setDither(true);
+ return x + draw_bm(c, bm, x, 0, p);
+}
+
+static const char* gConfigNames[] = {
+ "unknown config",
+ "A1",
+ "A8",
+ "Index8",
+ "565",
+ "4444",
+ "8888"
+};
+
+static SkScalar draw_row(SkCanvas* canvas, const SkBitmap& bm)
+{
+ SkAutoCanvasRestore acr(canvas, true);
+
+ SkPaint paint;
+ SkScalar x = 0;
+ const int scale = 32;
+
+ paint.setAntiAlias(true);
+ const char* name = gConfigNames[bm.config()];
+ canvas->drawText(name, strlen(name), x, SkIntToScalar(bm.height())*scale*5/8,
+ paint);
+ canvas->translate(SkIntToScalar(48), 0);
+
+ canvas->scale(SkIntToScalar(scale), SkIntToScalar(scale));
+
+ x += draw_set(canvas, bm, 0, &paint);
+ paint.reset();
+ paint.setAlpha(0x80);
+ draw_set(canvas, bm, x, &paint);
+ return x * scale / 3;
+}
+
+class FilterView : public SkView {
+public:
+ SkBitmap fBM8, fBM4444, fBM16, fBM32;
+
+ FilterView()
+ {
+ make_bm(&fBM8);
+ fBM8.copyTo(&fBM4444, SkBitmap::kARGB_4444_Config);
+ fBM8.copyTo(&fBM16, SkBitmap::kRGB_565_Config);
+ fBM8.copyTo(&fBM32, SkBitmap::kARGB_8888_Config);
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Filter");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+ canvas->drawColor(0xFFDDDDDD);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ SkScalar x = SkIntToScalar(10);
+ SkScalar y = SkIntToScalar(10);
+
+ canvas->translate(x, y);
+ y = draw_row(canvas, fBM8);
+ canvas->translate(0, y);
+ y = draw_row(canvas, fBM4444);
+ canvas->translate(0, y);
+ y = draw_row(canvas, fBM16);
+ canvas->translate(0, y);
+ draw_row(canvas, fBM32);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ // fSweep += SK_Scalar1;
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new FilterView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleFilter2.cpp b/samplecode/SampleFilter2.cpp
new file mode 100644
index 0000000..1800eb9
--- /dev/null
+++ b/samplecode/SampleFilter2.cpp
@@ -0,0 +1,123 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkPath.h"
+#include "SkPorterDuff.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+
+static const char* gNames[] = {
+ "/skimages/background_01.png"
+};
+
+class Filter2View : public SkView {
+public:
+ SkBitmap* fBitmaps;
+ int fBitmapCount;
+ int fCurrIndex;
+
+ Filter2View() {
+ fBitmapCount = SK_ARRAY_COUNT(gNames)*2;
+ fBitmaps = new SkBitmap[fBitmapCount];
+
+ for (int i = 0; i < fBitmapCount/2; i++) {
+ SkImageDecoder::DecodeFile(gNames[i], &fBitmaps[i],
+ SkBitmap::kARGB_8888_Config,
+ SkImageDecoder::kDecodePixels_Mode);
+ }
+ for (int i = fBitmapCount/2; i < fBitmapCount; i++) {
+ SkImageDecoder::DecodeFile(gNames[i-fBitmapCount/2], &fBitmaps[i],
+ SkBitmap::kRGB_565_Config,
+ SkImageDecoder::kDecodePixels_Mode);
+ }
+ fCurrIndex = 0;
+ }
+
+ virtual ~Filter2View() {
+ delete[] fBitmaps;
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SkString str("Filter/Dither ");
+ str.append(gNames[fCurrIndex]);
+ SampleCode::TitleR(evt, str.c_str());
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+// canvas->drawColor(0xFFDDDDDD);
+ canvas->drawColor(SK_ColorGRAY);
+// canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(50));
+
+ const SkScalar W = SkIntToScalar(fBitmaps[0].width() + 1);
+ const SkScalar H = SkIntToScalar(fBitmaps[0].height() + 1);
+ SkPaint paint;
+
+ const SkScalar scale = SkFloatToScalar(0.897917f);
+ canvas->scale(SK_Scalar1, scale);
+
+ for (int k = 0; k < 2; k++) {
+ paint.setFilterBitmap(k == 1);
+ for (int j = 0; j < 2; j++) {
+ paint.setDither(j == 1);
+ for (int i = 0; i < fBitmapCount; i++) {
+ SkScalar x = (k * fBitmapCount + j) * W;
+ SkScalar y = i * H;
+ x = SkIntToScalar(SkScalarRound(x));
+ y = SkIntToScalar(SkScalarRound(y));
+ canvas->drawBitmap(fBitmaps[i], x, y, &paint);
+ if (i == 0) {
+ SkPaint p;
+ p.setAntiAlias(true);
+ p.setTextAlign(SkPaint::kCenter_Align);
+ p.setTextSize(SkIntToScalar(18));
+ SkString s("dither=");
+ s.appendS32(paint.isDither());
+ s.append(" filter=");
+ s.appendS32(paint.isFilterBitmap());
+ canvas->drawText(s.c_str(), s.size(), x + W/2,
+ y - p.getTextSize(), p);
+ }
+ if (k+j == 2) {
+ SkPaint p;
+ p.setAntiAlias(true);
+ p.setTextSize(SkIntToScalar(18));
+ SkString s;
+ s.append(" depth=");
+ s.appendS32(fBitmaps[i].config() == SkBitmap::kRGB_565_Config ? 16 : 32);
+ canvas->drawText(s.c_str(), s.size(), x + W + SkIntToScalar(4),
+ y + H/2, p);
+ }
+ }
+ }
+ }
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new Filter2View; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleFontCache.cpp b/samplecode/SampleFontCache.cpp
new file mode 100644
index 0000000..fb63f71
--- /dev/null
+++ b/samplecode/SampleFontCache.cpp
@@ -0,0 +1,171 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGraphics.h"
+#include "SkRandom.h"
+
+#include <pthread.h>
+
+static void call_measure()
+{
+ SkPaint paint;
+ uint16_t text[32];
+ SkRandom rand;
+
+ paint.setAntiAlias(true);
+ paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+ for (int j = 0; j < SK_ARRAY_COUNT(text); j++)
+ text[j] = (uint16_t)((rand.nextU() & 0xFF) + 32);
+
+ for (int i = 9; i < 36; i++)
+ {
+ SkPaint::FontMetrics m;
+
+ paint.setTextSize(SkIntToScalar(i));
+ paint.getFontMetrics(&m);
+ paint.measureText(text, sizeof(text));
+ }
+}
+
+static void call_draw(SkCanvas* canvas)
+{
+ SkPaint paint;
+ uint16_t text[32];
+ SkRandom rand;
+
+ paint.setAntiAlias(true);
+ paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+ for (int j = 0; j < SK_ARRAY_COUNT(text); j++)
+ text[j] = (uint16_t)((rand.nextU() & 0xFF) + 32);
+
+ SkScalar x = SkIntToScalar(10);
+ SkScalar y = SkIntToScalar(20);
+
+ canvas->drawColor(SK_ColorWHITE);
+ for (int i = 9; i < 36; i++)
+ {
+ SkPaint::FontMetrics m;
+
+ paint.setTextSize(SkIntToScalar(i));
+ paint.getFontMetrics(&m);
+ canvas->drawText(text, sizeof(text), x, y, paint);
+ y += m.fDescent - m.fAscent;
+ }
+}
+
+static bool gDone;
+
+static void* measure_proc(void* context)
+{
+ while (!gDone)
+ {
+ call_measure();
+ }
+ return NULL;
+}
+
+static void* draw_proc(void* context)
+{
+ SkBitmap* bm = (SkBitmap*)context;
+ SkCanvas canvas(*bm);
+
+ while (!gDone)
+ {
+ call_draw(&canvas);
+ }
+ return NULL;
+}
+
+class FontCacheView : public SkView {
+public:
+ enum { N = 4 };
+
+ pthread_t fMThreads[N];
+ pthread_t fDThreads[N];
+ SkBitmap fBitmaps[N];
+
+ FontCacheView()
+ {
+ gDone = false;
+ for (int i = 0; i < N; i++)
+ {
+ int status;
+ pthread_attr_t attr;
+
+ status = pthread_attr_init(&attr);
+ SkASSERT(0 == status);
+ status = pthread_create(&fMThreads[i], &attr, measure_proc, NULL);
+ SkASSERT(0 == status);
+
+ fBitmaps[i].setConfig(SkBitmap::kRGB_565_Config, 320, 240);
+ fBitmaps[i].allocPixels();
+ status = pthread_create(&fDThreads[i], &attr, draw_proc, &fBitmaps[i]);
+ SkASSERT(0 == status);
+ }
+ }
+
+ virtual ~FontCacheView()
+ {
+ gDone = true;
+ for (int i = 0; i < N; i++)
+ {
+ void* ret;
+ int status = pthread_join(fMThreads[i], &ret);
+ SkASSERT(0 == status);
+ status = pthread_join(fDThreads[i], &ret);
+ SkASSERT(0 == status);
+ }
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "FontCache");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+ canvas->drawColor(0xFFDDDDDD);
+// canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ SkScalar x = 0;
+ SkScalar y = 0;
+ for (int i = 0; i < N; i++)
+ {
+ canvas->drawBitmap(fBitmaps[i], x, y);
+ x += SkIntToScalar(fBitmaps[i].width());
+ }
+ this->inval(NULL);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new FontCacheView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleGL.cpp b/samplecode/SampleGL.cpp
new file mode 100644
index 0000000..d020b0e
--- /dev/null
+++ b/samplecode/SampleGL.cpp
@@ -0,0 +1,206 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "Sk64.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkKernel33MaskFilter.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+#include "SkXfermode.h"
+
+// effects
+#include "SkGradientShader.h"
+#include "SkShaderExtras.h"
+#include "SkUnitMappers.h"
+
+#include "SkStream.h"
+#include "SkXMLParser.h"
+
+#include "SkGLCanvas.h"
+
+#include <AGL/agl.h>
+#include <OpenGL/gl.h>
+
+extern void* gSampleWind;
+
+static void makebm(SkBitmap* bm, SkBitmap::Config config, int w, int h)
+{
+ bm->setConfig(config, w, h);
+ bm->allocPixels();
+ bm->eraseColor(0);
+
+ SkCanvas canvas(*bm);
+ SkPoint pts[] = { 0, 0, SkIntToScalar(w), SkIntToScalar(h) };
+ SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
+ SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
+ SkPaint paint;
+
+ SkUnitMapper* um = NULL;
+
+// um = new SkCosineMapper;
+ // um = new SkDiscreteMapper(12);
+
+ SkAutoUnref au(um);
+
+ paint.setAntiAlias(true);
+ paint.setShader(SkGradientShader::CreateLinear(pts, colors, pos,
+ SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode, um))->unref();
+
+ SkRect r;
+ r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
+ canvas.drawOval(r, paint);
+}
+
+static void premulBitmap(const SkBitmap& bm) {
+ for (int y = 0; y < bm.height(); y++) {
+ SkPMColor* p = bm.getAddr32(0, y);
+ for (int x = 0; x < bm.width(); x++) {
+ SkPMColor c = *p;
+ unsigned a = SkGetPackedA32(c);
+ unsigned r = SkGetPackedR32(c);
+ unsigned g = SkGetPackedG32(c);
+ unsigned b = SkGetPackedB32(c);
+
+ unsigned scale = SkAlpha255To256(a);
+ r = SkAlphaMul(r, scale);
+ g = SkAlphaMul(g, scale);
+ b = SkAlphaMul(b, scale);
+ *p++ = SkPackARGB32(a, r, g, b);
+ }
+ }
+}
+
+class GLView : public SkView {
+public:
+ AGLContext fCtx;
+ SkBitmap fOffscreen;
+ SkBitmap fTexture[3];
+
+ GLView() {
+ makebm(&fTexture[0], SkBitmap::kARGB_8888_Config, 64, 100);
+ makebm(&fTexture[1], SkBitmap::kRGB_565_Config, 64, 100);
+ makebm(&fTexture[2], SkBitmap::kARGB_4444_Config, 64, 100);
+
+ GLint major, minor;
+
+ aglGetVersion(&major, &minor);
+ SkDebugf("---- version %d %d\n", major, minor);
+
+ GLint attr[] = {
+ AGL_RGBA,
+ AGL_DEPTH_SIZE, 32,
+ AGL_OFFSCREEN,
+ AGL_NONE
+ };
+
+ SkDebugf("------ attr %p %d\n", attr, sizeof(attr));
+ AGLPixelFormat format = aglCreatePixelFormat(attr);
+ SkDebugf("----- format %p\n", format);
+ fCtx = aglCreateContext(format, 0);
+ SkDebugf("----- context %p\n", fCtx);
+ GLboolean success; //= aglSetWindowRef(fCtx, (WindowRef)gSampleWind);
+// SkDebugf("----- aglSetWindowRef %d\n", success);
+
+ aglEnable(fCtx, GL_BLEND);
+ aglEnable(fCtx, GL_LINE_SMOOTH);
+ aglEnable(fCtx, GL_POINT_SMOOTH);
+ aglEnable(fCtx, GL_POLYGON_SMOOTH);
+
+ fOffscreen.setConfig(SkBitmap::kARGB_8888_Config, 300, 300);
+ fOffscreen.allocPixels();
+
+ success = aglSetOffScreen(fCtx,
+ fOffscreen.width(),
+ fOffscreen.height(),
+ fOffscreen.rowBytes(),
+ fOffscreen.getPixels());
+ GLenum err = aglGetError();
+ SkDebugf("---- setoffscreen %d %d %s\n", success, err, aglErrorString(err));
+
+ aglSetCurrentContext(fCtx);
+ glOrtho(0, fOffscreen.width(),
+ fOffscreen.height(), 0,
+ -1, 1);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
+
+ glEnable(GL_TEXTURE_2D);
+}
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "GL");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(0xFFDDDDDD);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ SkGLCanvas c(fOffscreen.width(), fOffscreen.height());
+
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ SkPaint p;
+
+ p.setAntiAlias(true);
+
+ c.drawColor(SK_ColorWHITE);
+
+ p.setColor(SK_ColorRED);
+ c.drawCircle(SkIntToScalar(40), SkIntToScalar(40), SkIntToScalar(20), p);
+
+ p.setColor(SK_ColorGREEN);
+ p.setStrokeWidth(SkIntToScalar(6));
+ p.setStrokeCap(SkPaint::kRound_Cap);
+ c.drawLine(SkIntToScalar(10), SkIntToScalar(10), SkIntToScalar(40), SkIntToScalar(50), p);
+
+ // c.scale(SkIntToScalar(3)/2, SkIntToScalar(3)/2);
+ p.setColor(0x880000FF);
+ c.drawCircle(SkIntToScalar(40), SkIntToScalar(40), SkIntToScalar(20), p);
+
+ for (int i = 0; i < SK_ARRAY_COUNT(fTexture); i++) {
+ c.drawBitmap(fTexture[i], SkIntToScalar(10), SkIntToScalar(100), NULL);
+ c.translate(SkIntToScalar(fTexture[i].width()), 0);
+ }
+ p.setColor(SK_ColorBLUE);
+ c.drawRectCoords(SkIntToScalar(10), SkIntToScalar(100),
+ SkIntToScalar(10+fTexture[0].width()),
+ SkIntToScalar(100+fTexture[0].height()),
+ p);
+
+ ////////
+ glFlush();
+ premulBitmap(fOffscreen);
+ canvas->drawBitmap(fOffscreen, SkIntToScalar(10), SkIntToScalar(10), NULL);
+ }
+
+private:
+
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new GLView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleImage.cpp b/samplecode/SampleImage.cpp
new file mode 100644
index 0000000..4cefd27
--- /dev/null
+++ b/samplecode/SampleImage.cpp
@@ -0,0 +1,158 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkPath.h"
+#include "SkPorterDuff.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+
+#include "SkImageRef_GlobalPool.h"
+#include "SkStream.h"
+
+static const char* gNames[] = {
+ "1.bmp", "1.gif", "1.jpg", "1.png",
+ "2.bmp", "2.gif", "2.jpg", "2.png"
+};
+
+// ownership of the stream is transferred
+static bool SetImageRef(SkBitmap* bitmap, SkStream* stream,
+ SkBitmap::Config pref, const char name[] = NULL)
+{
+ if (SkImageDecoder::DecodeStream(stream, bitmap, pref,
+ SkImageDecoder::kDecodeBounds_Mode)) {
+ SkASSERT(bitmap->config() != SkBitmap::kNo_Config);
+
+ SkImageRef* ref = new SkImageRef_GlobalPool(stream, bitmap->config());
+ ref->setURI(name);
+ bitmap->setPixelRef(ref)->unref();
+ return true;
+ } else {
+ delete stream;
+ return false;
+ }
+}
+
+class ImageView : public SkView {
+public:
+ SkBitmap* fBitmaps;
+ SkShader* fShader;
+
+ ImageView() {
+ SkImageRef_GlobalPool::SetRAMBudget(32 * 1024);
+
+ int i, N = SK_ARRAY_COUNT(gNames);
+ fBitmaps = new SkBitmap[N];
+
+ for (i = 0; i < N; i++) {
+ SkString str("/skimages/");
+ str.append(gNames[i]);
+ SkFILEStream* stream = new SkFILEStream(str.c_str());
+
+ SetImageRef(&fBitmaps[i], stream, SkBitmap::kNo_Config, gNames[i]);
+ if (i & 1)
+ fBitmaps[i].buildMipMap();
+ }
+
+ fShader = SkShader::CreateBitmapShader(fBitmaps[5],
+ SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode);
+
+ if (true) {
+ SkMatrix m;
+
+ m.setRotate(SkIntToScalar(30));
+ fShader->setLocalMatrix(m);
+ }
+
+#if 0
+ SkImageRef::DumpPool();
+ for (i = 0; i < N; i++) {
+ SkBitmap& bm = fBitmaps[i];
+
+ SkDebugf("<%s> addr=%p", gNames[i], bm.getPixels());
+ bool success = bm.lockPixels();
+ SkDebugf(" addr=%d", bm.getPixels());
+ if (success)
+ bm.unlockPixels();
+ SkDebugf(" addr=%p", bm.getPixels());
+ success = bm.lockPixels();
+ SkDebugf(" addr=%d", bm.getPixels());
+ if (success)
+ bm.unlockPixels();
+ SkDebugf("\n");
+ }
+ SkImageRef::DumpPool();
+#endif
+ }
+
+ virtual ~ImageView() {
+ delete[] fBitmaps;
+ delete fShader;
+
+ SkImageRef_GlobalPool::DumpPool();
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Image");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(0xFFDDDDDD);
+// canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
+
+ SkScalar x = 0, y = 0;
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); i++) {
+ canvas->drawBitmap(fBitmaps[i], x, y);
+ x += SkIntToScalar(fBitmaps[i].width() + 10);
+ }
+
+ canvas->translate(0, SkIntToScalar(120));
+
+ SkPaint paint;
+ paint.setShader(fShader);
+ paint.setFilterBitmap(true);
+ SkRect r = { 0, 0, SkIntToScalar(300), SkIntToScalar(100) };
+
+ canvas->drawRect(r, paint);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click) {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new ImageView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleImageDir.cpp b/samplecode/SampleImageDir.cpp
new file mode 100644
index 0000000..32a719b
--- /dev/null
+++ b/samplecode/SampleImageDir.cpp
@@ -0,0 +1,319 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkPath.h"
+#include "SkPorterDuff.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+#include "SkComposeShader.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+
+#include "SkImageRef_GlobalPool.h"
+#include "SkOSFile.h"
+#include "SkStream.h"
+
+#include "SkBlurDrawLooper.h"
+#include "SkColorMatrixFilter.h"
+
+static void drawmarshmallow(SkCanvas* canvas) {
+ SkBitmap bitmap;
+ SkPaint paint;
+ SkRect r;
+ SkMatrix m;
+
+ SkImageDecoder::DecodeFile("/Users/reed/Downloads/3elfs.jpg", &bitmap);
+ SkShader* s = SkShader::CreateBitmapShader(bitmap,
+ SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode);
+ paint.setShader(s)->unref();
+ m.setTranslate(SkIntToScalar(250), SkIntToScalar(134));
+ s->setLocalMatrix(m);
+
+ r.set(SkIntToScalar(250),
+ SkIntToScalar(134),
+ SkIntToScalar(250 + 449),
+ SkIntToScalar(134 + 701));
+ paint.setFlags(2);
+
+ canvas->drawRect(r, paint);
+}
+
+static void DrawRoundRect(SkCanvas& canvas) {
+ bool ret = false;
+ SkPaint paint;
+ SkBitmap bitmap;
+ SkMatrix matrix;
+ matrix.reset();
+
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1370, 812);
+ bitmap.allocPixels();
+#if 0
+ SkCanvas canvas;
+ canvas.setBitmapDevice(bitmap);
+#endif
+
+ // set up clipper
+ SkRect skclip;
+ skclip.set(SkIntToFixed(284), SkIntToFixed(40), SkIntToFixed(1370), SkIntToFixed(708));
+
+// ret = canvas.clipRect(skclip);
+// SkASSERT(ret);
+
+ matrix.set(SkMatrix::kMTransX, SkFloatToFixed(-1153.28));
+ matrix.set(SkMatrix::kMTransY, SkFloatToFixed(1180.50));
+
+ matrix.set(SkMatrix::kMScaleX, SkFloatToFixed(0.177171));
+ matrix.set(SkMatrix::kMScaleY, SkFloatToFixed(0.177043));
+
+ matrix.set(SkMatrix::kMSkewX, SkFloatToFixed(0.126968));
+ matrix.set(SkMatrix::kMSkewY, SkFloatToFixed(-0.126876));
+
+ matrix.set(SkMatrix::kMPersp0, SkFloatToFixed(0.0));
+ matrix.set(SkMatrix::kMPersp1, SkFloatToFixed(0.0));
+
+ ret = canvas.concat(matrix);
+
+ paint.setAntiAlias(true);
+ paint.setColor(0xb2202020);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkFloatToFixed(68.13));
+
+ SkRect r;
+ r.set(SkFloatToFixed(-313.714417), SkFloatToFixed(-4.826389), SkFloatToFixed(18014.447266), SkFloatToFixed(1858.154541));
+ canvas.drawRoundRect(r, SkFloatToFixed(91.756363), SkFloatToFixed(91.756363), paint);
+}
+
+// ownership of the stream is transferred
+static bool SetImageRef(SkBitmap* bitmap, SkStream* stream,
+ SkBitmap::Config pref, const char name[] = NULL) {
+#if 0
+ // test buffer streams
+ SkStream* str = new SkBufferStream(stream, 717);
+ stream->unref();
+ stream = str;
+#endif
+
+ SkImageRef* ref = new SkImageRef_GlobalPool(stream, pref, 1);
+ ref->setURI(name);
+ if (!ref->getInfo(bitmap)) {
+ delete ref;
+ return false;
+ }
+ bitmap->setPixelRef(ref)->unref();
+ return true;
+}
+
+//#define SPECIFIC_IMAGE "/skimages/72.jpg"
+#define SPECIFIC_IMAGE "/Users/reed/Downloads/3elfs.jpg"
+
+#define IMAGE_DIR "/skimages/"
+#define IMAGE_SUFFIX ".gif"
+
+class ImageDirView : public SkView {
+public:
+ SkBitmap* fBitmaps;
+ SkString* fStrings;
+ int fBitmapCount;
+ int fCurrIndex;
+ SkScalar fSaturation;
+ SkScalar fAngle;
+
+ ImageDirView() {
+ SkImageRef_GlobalPool::SetRAMBudget(320 * 1024);
+
+#ifdef SPECIFIC_IMAGE
+ fBitmaps = new SkBitmap[3];
+ fStrings = new SkString[3];
+ fBitmapCount = 3;
+ const SkBitmap::Config configs[] = {
+ SkBitmap::kARGB_8888_Config,
+ SkBitmap::kRGB_565_Config,
+ SkBitmap::kARGB_4444_Config
+ };
+ for (int i = 0; i < fBitmapCount; i++) {
+#if 1
+ SkStream* stream = new SkFILEStream(SPECIFIC_IMAGE);
+ SetImageRef(&fBitmaps[i], stream, configs[i], SPECIFIC_IMAGE);
+#else
+ SkImageDecoder::DecodeFile(SPECIFIC_IMAGE, &fBitmaps[i]);
+#endif
+ }
+#else
+ int i, N = 0;
+ SkOSFile::Iter iter(IMAGE_DIR, IMAGE_SUFFIX);
+ SkString name;
+ while (iter.next(&name)) {
+ N += 1;
+ }
+ fBitmaps = new SkBitmap[N];
+ fStrings = new SkString[N];
+ iter.reset(IMAGE_DIR, IMAGE_SUFFIX);
+ for (i = 0; i < N; i++) {
+ iter.next(&name);
+ SkString path(IMAGE_DIR);
+ path.append(name);
+ SkStream* stream = new SkFILEStream(path.c_str());
+
+ SetImageRef(&fBitmaps[i], stream, SkBitmap::kNo_Config,
+ name.c_str());
+ fStrings[i] = name;
+ }
+ fBitmapCount = N;
+#endif
+ fCurrIndex = 0;
+ fDX = fDY = 0;
+
+ fSaturation = SK_Scalar1;
+ fAngle = 0;
+
+ fScale = SK_Scalar1;
+ }
+
+ virtual ~ImageDirView() {
+ delete[] fBitmaps;
+ delete[] fStrings;
+
+ SkImageRef_GlobalPool::DumpPool();
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SkString str("ImageDir: ");
+#ifdef SPECIFIC_IMAGE
+ str.append(SPECIFIC_IMAGE);
+#else
+ str.append(IMAGE_DIR);
+#endif
+ SampleCode::TitleR(evt, str.c_str());
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+// canvas->drawColor(0xFFDDDDDD);
+ canvas->drawColor(SK_ColorGRAY);
+ canvas->drawColor(SK_ColorWHITE);
+ }
+
+ SkScalar fScale;
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ if (true) {
+ canvas->scale(SkIntToScalar(2), SkIntToScalar(2));
+ drawmarshmallow(canvas);
+ return;
+ }
+
+ if (false) {
+ SkPaint p;
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SkIntToScalar(4));
+ canvas->drawCircle(SkIntToScalar(100), SkIntToScalar(100), SkIntToScalar(50), p);
+ p.setAntiAlias(true);
+ canvas->drawCircle(SkIntToScalar(300), SkIntToScalar(100), SkIntToScalar(50), p);
+ }
+ if (false) {
+ SkScalar cx = this->width()/2;
+ SkScalar cy = this->height()/2;
+ canvas->translate(cx, cy);
+ canvas->scale(fScale, fScale);
+ canvas->translate(-cx, -cy);
+ DrawRoundRect(*canvas);
+ return;
+ }
+
+ SkScalar scale = SK_Scalar1 * 999/1000;
+// scale = SK_Scalar1/2;
+
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
+ // canvas->scale(scale, scale);
+
+ SkScalar x = SkIntToScalar(32), y = SkIntToScalar(32);
+ SkPaint paint;
+
+ // x += fDX;
+ // y += fDY;
+
+// paint.setLooper(new SkBlurDrawLooper(SkIntToScalar(12), 0, 0, 0xDD000000))->unref();
+
+#if 0
+ for (int i = 0; i < fBitmapCount; i++) {
+ SkPaint p;
+
+#if 1
+ const SkScalar cm[] = {
+ SkIntToScalar(2), 0, 0, 0, SkIntToScalar(-255),
+ 0, SkIntToScalar(2), 0, 0, SkIntToScalar(-255),
+ 0, 0, SkIntToScalar(2), 0, SkIntToScalar(-255),
+ 0, 0, 0, SkIntToScalar(1), 0
+ };
+ SkColorFilter* cf = new SkColorMatrixFilter(cm);
+ p.setColorFilter(cf)->unref();
+#endif
+
+ canvas->drawBitmap(fBitmaps[i], x, y, &p);
+ x += SkIntToScalar(fBitmaps[i].width() + 10);
+ }
+ return;
+#endif
+
+ canvas->drawBitmap(fBitmaps[fCurrIndex], x, y, &paint);
+#ifndef SPECIFIC_IMAGE
+ if (true) {
+ fCurrIndex += 1;
+ if (fCurrIndex >= fBitmapCount) {
+ fCurrIndex = 0;
+ }
+ this->inval(NULL);
+ }
+#endif
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ if (true) {
+ fCurrIndex += 1;
+ if (fCurrIndex >= fBitmapCount)
+ fCurrIndex = 0;
+ this->inval(NULL);
+ }
+ return new Click(this);
+ }
+
+ virtual bool onClick(Click* click) {
+ SkScalar center = this->width()/2;
+ fSaturation = SkScalarDiv(click->fCurr.fX - center, center/2);
+ center = this->height()/2;
+ fAngle = SkScalarDiv(click->fCurr.fY - center, center) * 180;
+
+ fDX += click->fCurr.fX - click->fPrev.fX;
+ fDY += click->fCurr.fY - click->fPrev.fY;
+
+ fScale = SkScalarDiv(click->fCurr.fX, this->width());
+
+ this->inval(NULL);
+ return true;
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ SkScalar fDX, fDY;
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new ImageDirView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleLayers.cpp b/samplecode/SampleLayers.cpp
new file mode 100644
index 0000000..8666745
--- /dev/null
+++ b/samplecode/SampleLayers.cpp
@@ -0,0 +1,258 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkBlurMaskFilter.h"
+#include "SkCamera.h"
+#include "SkColorFilter.h"
+#include "SkColorPriv.h"
+#include "SkDevice.h"
+#include "SkGradientShader.h"
+#include "SkImageDecoder.h"
+#include "SkInterpolator.h"
+#include "SkMaskFilter.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+#include "SkUtils.h"
+#include "SkKey.h"
+#include "SkPorterDuff.h"
+#include "SkXfermode.h"
+#include "SkDrawFilter.h"
+
+static void make_paint(SkPaint* paint) {
+ SkColor colors[] = { 0, SK_ColorWHITE };
+ SkPoint pts[] = { 0, 0, 0, SK_Scalar1*20 };
+ SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode);
+
+ paint->setShader(s)->unref();
+ paint->setXfermode(SkPorterDuff::CreateXfermode(SkPorterDuff::kDstIn_Mode))->unref();
+}
+
+static void dump_layers(const char label[], SkCanvas* canvas) {
+ SkDebugf("Dump Layers(%s)\n", label);
+
+ SkCanvas::LayerIter iter(canvas, true);
+ int index = 0;
+ while (!iter.done()) {
+ const SkBitmap& bm = iter.device()->accessBitmap(false);
+ const SkIRect& clip = iter.clip().getBounds();
+ SkDebugf("Layer[%d] bitmap [%d %d] X=%d Y=%d clip=[%d %d %d %d] alpha=%d\n", index++,
+ bm.width(), bm.height(), iter.x(), iter.y(),
+ clip.fLeft, clip.fTop, clip.fRight, clip.fBottom,
+ iter.paint().getAlpha());
+ iter.next();
+ }
+}
+
+// test drawing with strips of fading gradient above and below
+static void test_fade(SkCanvas* canvas) {
+ SkAutoCanvasRestore ar(canvas, true);
+
+ SkRect r;
+
+ SkPaint p;
+ p.setAlpha(0x88);
+
+ SkAutoCanvasRestore(canvas, false);
+
+ // create the layers
+
+ r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
+ canvas->clipRect(r);
+
+ r.fBottom = SkIntToScalar(20);
+ canvas->saveLayer(&r, NULL, (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag));
+
+ r.fTop = SkIntToScalar(80);
+ r.fBottom = SkIntToScalar(100);
+ canvas->saveLayer(&r, NULL, (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag));
+
+ // now draw the "content"
+
+ if (true) {
+ r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
+
+ canvas->saveLayerAlpha(&r, 0x80);
+
+ SkPaint p;
+ p.setColor(SK_ColorRED);
+ p.setAntiAlias(true);
+ canvas->drawOval(r, p);
+
+ dump_layers("inside layer alpha", canvas);
+
+ canvas->restore();
+ } else {
+ r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
+
+ SkPaint p;
+ p.setColor(SK_ColorRED);
+ p.setAntiAlias(true);
+ canvas->drawOval(r, p);
+ }
+
+// return;
+
+ dump_layers("outside layer alpha", canvas);
+
+ // now apply an effect
+
+ SkPaint paint;
+ make_paint(&paint);
+ r.set(0, 0, SkIntToScalar(100), SkIntToScalar(20));
+// SkDebugf("--------- draw top grad\n");
+ canvas->drawRect(r, paint);
+
+ SkMatrix m;
+ SkShader* s = paint.getShader();
+ m.setScale(SK_Scalar1, -SK_Scalar1);
+ m.postTranslate(0, SkIntToScalar(100));
+ s->setLocalMatrix(m);
+
+ r.fTop = SkIntToScalar(80);
+ r.fBottom = SkIntToScalar(100);
+// SkDebugf("--------- draw bot grad\n");
+ canvas->drawRect(r, paint);
+}
+
+class RedFilter : public SkDrawFilter {
+public:
+ virtual bool filter(SkCanvas*, SkPaint* p, SkDrawFilter::Type) {
+ fColor = p->getColor();
+ if (fColor == SK_ColorRED) {
+ p->setColor(SK_ColorGREEN);
+ }
+ return true;
+ }
+ virtual void restore(SkCanvas*, SkPaint* p, SkDrawFilter::Type) {
+ p->setColor(fColor);
+ }
+
+private:
+ SkColor fColor;
+};
+
+class LayersView : public SkView {
+public:
+ LayersView() {}
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Layers");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ if (false) {
+ SkRect r;
+ r.set(SkIntToScalar(0), SkIntToScalar(0),
+ SkIntToScalar(220), SkIntToScalar(120));
+ SkPaint p;
+ p.setAlpha(0x88);
+ p.setAntiAlias(true);
+
+ if (true) {
+ canvas->saveLayer(&r, &p);
+ p.setColor(0xFFFF0000);
+ canvas->drawOval(r, p);
+ canvas->restore();
+ }
+
+ p.setColor(0xFF0000FF);
+ r.offset(SkIntToScalar(20), SkIntToScalar(50));
+ canvas->drawOval(r, p);
+ }
+
+ if (false) {
+ SkPaint p;
+ p.setAlpha(0x88);
+ p.setAntiAlias(true);
+
+ canvas->translate(SkIntToScalar(300), 0);
+
+ SkRect r;
+ r.set(SkIntToScalar(0), SkIntToScalar(0),
+ SkIntToScalar(220), SkIntToScalar(60));
+
+ canvas->saveLayer(&r, &p, (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag));
+// canvas->clipRect(r, SkRegion::kDifference_Op);
+// canvas->clipRect(r, SkRegion::kIntersect_Op);
+
+ r.set(SkIntToScalar(0), SkIntToScalar(0),
+ SkIntToScalar(220), SkIntToScalar(120));
+ p.setColor(SK_ColorBLUE);
+ canvas->drawOval(r, p);
+ canvas->restore();
+ return;
+ }
+
+ //canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
+ test_fade(canvas);
+ return;
+
+ // canvas->setDrawFilter(new RedFilter)->unref();
+
+ SkRect r;
+ SkPaint p;
+
+ canvas->translate(SkIntToScalar(220), SkIntToScalar(20));
+
+ p.setAntiAlias(true);
+ r.set(SkIntToScalar(20), SkIntToScalar(20),
+ SkIntToScalar(220), SkIntToScalar(120));
+
+ p.setColor(SK_ColorBLUE);
+ // p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(8), SkBlurMaskFilter::kNormal_BlurStyle))->unref();
+ canvas->drawRect(r, p);
+ p.setMaskFilter(NULL);
+
+ SkRect bounds = r;
+ bounds.fBottom = bounds.centerY();
+ canvas->saveLayer(&bounds, NULL, SkCanvas::kARGB_NoClipLayer_SaveFlag);
+
+ p.setColor(SK_ColorRED);
+ canvas->drawOval(r, p);
+
+ p.setAlpha(0x80);
+ p.setPorterDuffXfermode(SkPorterDuff::kDstIn_Mode);
+ canvas->drawRect(bounds, p);
+
+ canvas->restore();
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ this->inval(NULL);
+
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click) {
+ return this->INHERITED::onClick(click);
+ }
+
+ virtual bool handleKey(SkKey key) {
+ this->inval(NULL);
+ return true;
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new LayersView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleLines.cpp b/samplecode/SampleLines.cpp
new file mode 100644
index 0000000..a0238b0
--- /dev/null
+++ b/samplecode/SampleLines.cpp
@@ -0,0 +1,146 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "Sk64.h"
+#include "SkCornerPathEffect.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkKernel33MaskFilter.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+#include "SkXfermode.h"
+
+#include "SkStream.h"
+#include "SkXMLParser.h"
+#include "SkColorPriv.h"
+#include "SkImageDecoder.h"
+
+class LinesView : public SkView {
+public:
+ LinesView()
+ {
+ unsigned r = 0x1F;
+ unsigned g = 0x3F;
+ for (unsigned a = 0; a <= 0xF; a++) {
+ unsigned scale = 16 - SkAlpha15To16(a);
+ unsigned sr = (a << 1) | (a >> 3);
+ unsigned dr = r * scale >> 4;
+ unsigned sg = (a << 2) | (a >> 2);
+ unsigned dg = g * scale >> 4;
+
+ unsigned ssg = sg & ~(~(a >> 3) & 1);
+
+ printf("4444 sa=%d sr=%d sg=%d da=%d dr=%d dg=%d total-r=%d total-g=%d %d\n",
+ a, sr, sg, scale, dr, dg, sr+dr, sg+dg, ssg+dg);
+ }
+
+ for (unsigned aa = 0; aa <= 0xFF; aa++) {
+ unsigned invScale = SkAlpha255To256(255 - aa);
+ unsigned dst = SkAlphaMul(0xFF, invScale);
+ printf("8888 sa=%02x dst=%02x sum=%d %s\n", aa, dst, aa+dst,
+ (aa+dst) > 0xFF ? "OVERFLOW" : "");
+ }
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Lines");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+// canvas->drawColor(0xFFDDDDDD);
+ canvas->drawColor(SK_ColorWHITE);
+ // canvas->drawColor(SK_ColorBLACK);
+ }
+
+ /*
+ 0x1F * x + 0x1F * (32 - x)
+ */
+ void drawRings(SkCanvas* canvas)
+ {
+ canvas->scale(SkIntToScalar(1)/2, SkIntToScalar(1)/2);
+
+ SkRect r;
+ SkScalar x = SkIntToScalar(10);
+ SkScalar y = SkIntToScalar(10);
+ r.set(x, y, x + SkIntToScalar(100), y + SkIntToScalar(100));
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkScalarHalf(SkIntToScalar(3)));
+ paint.setColor(0xFFFF8800);
+ paint.setColor(0xFFFFFFFF);
+ canvas->drawRect(r, paint);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ SkBitmap bm;
+ SkImageDecoder::DecodeFile("/kill.gif", &bm);
+ canvas->drawBitmap(bm, 0, 0, NULL);
+
+ this->drawRings(canvas);
+ return;
+
+ SkPaint paint;
+
+ // fAlpha = 0x80;
+ paint.setColor(SK_ColorWHITE);
+ paint.setAlpha(fAlpha & 0xFF);
+ SkRect r;
+
+ SkScalar x = SkIntToScalar(10);
+ SkScalar y = SkIntToScalar(10);
+ r.set(x, y, x + SkIntToScalar(100), y + SkIntToScalar(100));
+ canvas->drawRect(r, paint);
+ return;
+
+ paint.setColor(0xffffff00); // yellow
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(2));
+
+// y += SK_Scalar1/2;
+
+ canvas->drawLine(x, y, x + SkIntToScalar(90), y + SkIntToScalar(90), paint);
+
+ paint.setAntiAlias(true); // with anti-aliasing
+ y += SkIntToScalar(10);
+ canvas->drawLine(x, y, x + SkIntToScalar(90), y + SkIntToScalar(90), paint);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ fAlpha = SkScalarRound(y);
+ this->inval(NULL);
+ return NULL;
+ }
+private:
+
+ int fAlpha;
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new LinesView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleMeasure.cpp b/samplecode/SampleMeasure.cpp
new file mode 100644
index 0000000..70b8812
--- /dev/null
+++ b/samplecode/SampleMeasure.cpp
@@ -0,0 +1,138 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "Sk1DPathEffect.h"
+#include "SkCornerPathEffect.h"
+#include "SkPathMeasure.h"
+#include "SkRandom.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkDither.h"
+
+// exercise scale/linear/devkern
+struct Setting {
+ SkScalar fScale;
+ bool fLinearText;
+ bool fDevKernText;
+};
+
+static const SkScalar ONE = SkIntToScalar(9999)/10000;
+
+static const Setting gSettings[] = {
+ { 0, false, false },
+ { 0, false, true },
+ { 0, true, false },
+ { 0, true, true },
+ { ONE, false, false },
+ { ONE, false, true },
+ { ONE, true, false },
+ { ONE, true, true }
+};
+
+static void doMeasure(SkCanvas* canvas, const SkPaint& paint, const char text[])
+{
+ SkScalar dy = paint.getFontMetrics(NULL);
+
+ size_t len = strlen(text);
+ SkAutoTMalloc<SkScalar> autoWidths(len);
+ SkScalar* widths = autoWidths.get();
+ SkAutoTMalloc<SkRect> autoRects(len);
+ SkRect* rects = autoRects.get();
+ SkRect bounds;
+
+ SkPaint p(paint);
+ for (int i = 0; i < SK_ARRAY_COUNT(gSettings); i++) {
+ p.setLinearText(gSettings[i].fLinearText);
+ p.setDevKernText(gSettings[i].fDevKernText);
+ SkScalar scale = gSettings[i].fScale;
+
+ int n = p.getTextWidths(text, len, widths, rects);
+ SkScalar w = p.measureText(text, len, &bounds, scale);
+
+ p.setStyle(SkPaint::kFill_Style);
+ p.setColor(0x8888FF88);
+ canvas->drawRect(bounds, p);
+ p.setColor(0xFF000000);
+ canvas->drawText(text, len, 0, 0, p);
+
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(0);
+ p.setColor(0xFFFF0000);
+ SkScalar x = 0;
+ for (int j = 0; j < n; j++) {
+ SkRect r = rects[j];
+ r.offset(x, 0);
+ canvas->drawRect(r, p);
+ x += widths[j];
+ }
+
+ p.setColor(0xFF0000FF);
+ canvas->drawLine(0, 0, w, 0, p);
+ p.setStrokeWidth(SkIntToScalar(4));
+ canvas->drawPoint(x, 0, p);
+
+ canvas->translate(0, dy);
+ }
+}
+
+class MeasureView : public SkView {
+public:
+ SkPaint fPaint;
+
+ MeasureView()
+ {
+ fPaint.setAntiAlias(true);
+ fPaint.setTextSize(SkIntToScalar(64));
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Measure");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+ canvas->drawColor(0xFFDDDDDD);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ canvas->translate(fPaint.getTextSize(), fPaint.getTextSize());
+ doMeasure(canvas, fPaint, "Hamburgefons");
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ // fSweep += SK_Scalar1;
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new MeasureView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleNinePatch.cpp b/samplecode/SampleNinePatch.cpp
new file mode 100644
index 0000000..2fd60a2
--- /dev/null
+++ b/samplecode/SampleNinePatch.cpp
@@ -0,0 +1,56 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkImageDecoder.h"
+#include "SkNinePatch.h"
+#include "SkPaint.h"
+#include "SkUnPreMultiply.h"
+
+class NinePatchView : public SkView {
+public:
+ SkBitmap fBM;
+
+ NinePatchView() {
+ SkImageDecoder::DecodeFile("/skimages/folder_background.9.png", &fBM);
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "NinePatch");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorWHITE);
+
+ canvas->drawBitmap(fBM, 0, 0);
+
+ SkIRect margins;
+ SkRect dst;
+ int d = 25;
+
+ margins.set(d, d, d, d);
+ dst.set(0, 0, SkIntToScalar(200), SkIntToScalar(200));
+ dst.offset(SkIntToScalar(fBM.width()), 0);
+ dst.offset(SkIntToScalar(2), SkIntToScalar(2));
+
+ SkNinePatch::DrawNine(canvas, dst, fBM, margins);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new NinePatchView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleOverflow.cpp b/samplecode/SampleOverflow.cpp
new file mode 100644
index 0000000..229683f
--- /dev/null
+++ b/samplecode/SampleOverflow.cpp
@@ -0,0 +1,106 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkDevice.h"
+#include "SkPaint.h"
+
+static void DrawRoundRect() {
+#ifdef SK_SCALAR_IS_FIXED
+ bool ret = false;
+ SkPaint paint;
+ SkBitmap bitmap;
+ SkCanvas canvas;
+ SkMatrix matrix;
+ matrix.reset();
+
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1370, 812);
+ bitmap.allocPixels();
+ canvas.setBitmapDevice(bitmap);
+
+ // set up clipper
+ SkRect skclip;
+ skclip.set(SkIntToFixed(284), SkIntToFixed(40), SkIntToFixed(1370), SkIntToFixed(708));
+
+ ret = canvas.clipRect(skclip);
+ SkASSERT(ret);
+
+ matrix.set(SkMatrix::kMTransX, SkFloatToFixed(-1153.28));
+ matrix.set(SkMatrix::kMTransY, SkFloatToFixed(1180.50));
+
+ matrix.set(SkMatrix::kMScaleX, SkFloatToFixed(0.177171));
+ matrix.set(SkMatrix::kMScaleY, SkFloatToFixed(0.177043));
+
+ matrix.set(SkMatrix::kMSkewX, SkFloatToFixed(0.126968));
+ matrix.set(SkMatrix::kMSkewY, SkFloatToFixed(-0.126876));
+
+ matrix.set(SkMatrix::kMPersp0, SkFloatToFixed(0.0));
+ matrix.set(SkMatrix::kMPersp1, SkFloatToFixed(0.0));
+
+ ret = canvas.concat(matrix);
+
+ paint.setAntiAlias(true);
+ paint.setColor(0xb2202020);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkFloatToFixed(68.13));
+
+ SkRect r;
+ r.set(SkFloatToFixed(-313.714417), SkFloatToFixed(-4.826389), SkFloatToFixed(18014.447266), SkFloatToFixed(1858.154541));
+ canvas.drawRoundRect(r, SkFloatToFixed(91.756363), SkFloatToFixed(91.756363), paint);
+#endif
+}
+
+static bool HitTestPath(const SkPath& path, SkScalar x, SkScalar y) {
+ SkRegion rgn, clip;
+
+ int ix = SkScalarFloor(x);
+ int iy = SkScalarFloor(y);
+
+ clip.setRect(ix, iy, ix + 1, iy + 1);
+
+ bool contains = rgn.setPath(path, clip);
+ return contains;
+}
+
+static void TestOverflowHitTest() {
+ SkPath path;
+
+#ifdef SK_SCALAR_IS_FLOATx
+ path.addCircle(0, 0, 70000, SkPath::kCCW_Direction);
+ SkASSERT(HitTestPath(path, 40000, 40000));
+#endif
+}
+
+class OverflowView : public SkView {
+public:
+ OverflowView() {}
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Circles");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ DrawRoundRect();
+ TestOverflowHitTest();
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new OverflowView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SamplePageFlip.cpp b/samplecode/SamplePageFlip.cpp
new file mode 100644
index 0000000..6b1adfd
--- /dev/null
+++ b/samplecode/SamplePageFlip.cpp
@@ -0,0 +1,173 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGraphics.h"
+#include "SkRandom.h"
+#include "SkFlipPixelRef.h"
+#include "SkPageFlipper.h"
+
+#include <pthread.h>
+
+#define WIDTH 200
+#define HEIGHT 200
+
+static bool gDone;
+
+static void bounce(SkScalar* x, SkScalar* dx, const int max) {
+ *x += *dx;
+ if (*x < 0) {
+ *x = 0;
+ if (*dx < 0) {
+ *dx = -*dx;
+ }
+ } else if (*x > SkIntToScalar(max)) {
+ *x = SkIntToScalar(max);
+ if (*dx > 0) {
+ *dx = -*dx;
+ }
+ }
+}
+
+static void* draw_proc(void* context) {
+ const int OVALW = 32;
+ const int OVALH = 32;
+
+ const SkBitmap* bm = static_cast<const SkBitmap*>(context);
+ SkFlipPixelRef* ref = static_cast<SkFlipPixelRef*>(bm->pixelRef());
+
+ const int DSCALE = 1;
+ SkScalar dx = SkIntToScalar(7) / DSCALE;
+ SkScalar dy = SkIntToScalar(5) / DSCALE;
+ SkScalar x = 0;
+ SkScalar y = 0;
+
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setColor(reinterpret_cast<SkColor>(ref) | (0xFF << 24));
+
+ SkRect oval;
+ oval.setEmpty();
+
+ while (!gDone) {
+ ref->inval(oval, true);
+ oval.set(x, y, x + SkIntToScalar(OVALW), y + SkIntToScalar(OVALH));
+ ref->inval(oval, true);
+
+ SkAutoFlipUpdate update(ref);
+
+ if (!update.dirty().isEmpty()) {
+ // this must be local to the loop, since it needs to forget the pixels
+ // its writing to after each iteration, since we do the swap
+ SkCanvas canvas(update.bitmap());
+
+// SkDebugf("----- dirty [%d %d %d %d]\n", dirty.getBounds().fLeft, dirty.getBounds().fTop, dirty.getBounds().width(), dirty.getBounds().height());
+ canvas.clipRegion(update.dirty());
+
+ canvas.drawColor(0, SkPorterDuff::kClear_Mode);
+ canvas.drawOval(oval, paint);
+ }
+ bounce(&x, &dx, WIDTH-OVALW);
+ bounce(&y, &dy, HEIGHT-OVALH);
+
+#if 1
+ for (int i = 0; i < 1000; i++) {
+ for (int j = 0; j < 10000; j++) {
+ SkFixedMul(j, 10);
+ }
+ }
+#endif
+ }
+ return NULL;
+}
+
+static const SkBitmap::Config gConfigs[] = {
+ SkBitmap::kARGB_8888_Config,
+#if 1
+ SkBitmap::kRGB_565_Config,
+ SkBitmap::kARGB_4444_Config,
+ SkBitmap::kA8_Config
+#endif
+};
+
+class PageFlipView : public SkView {
+public:
+
+ enum { N = SK_ARRAY_COUNT(gConfigs) };
+
+ pthread_t fThreads[N];
+ SkBitmap fBitmaps[N];
+
+ PageFlipView() {
+ gDone = false;
+ for (int i = 0; i < N; i++) {
+ int status;
+ pthread_attr_t attr;
+
+ status = pthread_attr_init(&attr);
+ SkASSERT(0 == status);
+
+ fBitmaps[i].setConfig(gConfigs[i], WIDTH, HEIGHT);
+ SkFlipPixelRef* pr = new SkFlipPixelRef(gConfigs[i], WIDTH, HEIGHT);
+ fBitmaps[i].setPixelRef(pr)->unref();
+ fBitmaps[i].eraseColor(0);
+
+ status = pthread_create(&fThreads[i], &attr, draw_proc, &fBitmaps[i]);
+ SkASSERT(0 == status);
+ }
+ }
+
+ virtual ~PageFlipView() {
+ gDone = true;
+ for (int i = 0; i < N; i++) {
+ void* ret;
+ int status = pthread_join(fThreads[i], &ret);
+ SkASSERT(0 == status);
+ }
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "PageFlip");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(0xFFDDDDDD);
+// canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ SkScalar x = SkIntToScalar(10);
+ SkScalar y = SkIntToScalar(10);
+ for (int i = 0; i < N; i++) {
+ canvas->drawBitmap(fBitmaps[i], x, y);
+ x += SkIntToScalar(fBitmaps[i].width() + 20);
+ }
+ this->inval(NULL);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click) {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new PageFlipView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SamplePatch.cpp b/samplecode/SamplePatch.cpp
new file mode 100644
index 0000000..77bd332
--- /dev/null
+++ b/samplecode/SamplePatch.cpp
@@ -0,0 +1,417 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkPath.h"
+#include "SkPorterDuff.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+
+#include "SkImageRef.h"
+#include "SkOSFile.h"
+#include "SkStream.h"
+
+#include "SkGeometry.h" // private include :(
+
+static void drawtriangle(SkCanvas* canvas, const SkPaint& paint,
+ const SkPoint pts[3]) {
+ SkPath path;
+
+ path.moveTo(pts[0]);
+ path.lineTo(pts[1]);
+ path.lineTo(pts[2]);
+
+ canvas->drawPath(path, paint);
+}
+
+static SkShader* make_shader0(SkIPoint* size) {
+ SkBitmap bm;
+
+// SkImageDecoder::DecodeFile("/skimages/progressivejpg.jpg", &bm);
+ SkImageDecoder::DecodeFile("/skimages/beach.jpg", &bm);
+ size->set(bm.width(), bm.height());
+ return SkShader::CreateBitmapShader(bm, SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode);
+}
+
+static SkShader* make_shader1(const SkIPoint& size) {
+ SkPoint pts[] = { 0, 0, SkIntToScalar(size.fX), SkIntToScalar(size.fY) };
+ SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED };
+ return SkGradientShader::CreateLinear(pts, colors, NULL,
+ SK_ARRAY_COUNT(colors), SkShader::kMirror_TileMode, NULL);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class Patch {
+public:
+ Patch() { bzero(fPts, sizeof(fPts)); }
+ ~Patch() {}
+
+ void setPatch(const SkPoint pts[12]) {
+ memcpy(fPts, pts, 12 * sizeof(SkPoint));
+ fPts[12] = pts[0]; // the last shall be first
+ }
+ void setBounds(int w, int h) { fW = w; fH = h; }
+
+ void draw(SkCanvas*, const SkPaint&, int segsU, int segsV,
+ bool doTextures, bool doColors);
+
+private:
+ SkPoint fPts[13];
+ int fW, fH;
+};
+
+static void eval_patch_edge(const SkPoint cubic[], SkPoint samples[], int segs) {
+ SkScalar t = 0;
+ SkScalar dt = SK_Scalar1 / segs;
+
+ samples[0] = cubic[0];
+ for (int i = 1; i < segs; i++) {
+ t += dt;
+ SkEvalCubicAt(cubic, t, &samples[i], NULL, NULL);
+ }
+}
+
+static void eval_sheet(const SkPoint edge[], int nu, int nv, int iu, int iv,
+ SkPoint* pt) {
+ const int TL = 0;
+ const int TR = nu;
+ const int BR = TR + nv;
+ const int BL = BR + nu;
+
+ SkScalar u = SkIntToScalar(iu) / nu;
+ SkScalar v = SkIntToScalar(iv) / nv;
+
+ SkScalar uv = SkScalarMul(u, v);
+ SkScalar Uv = SkScalarMul(SK_Scalar1 - u, v);
+ SkScalar uV = SkScalarMul(u, SK_Scalar1 - v);
+ SkScalar UV = SkScalarMul(SK_Scalar1 - u, SK_Scalar1 - v);
+
+ SkScalar x0 = SkScalarMul(UV, edge[TL].fX) + SkScalarMul(uV, edge[TR].fX) +
+ SkScalarMul(Uv, edge[BL].fX) + SkScalarMul(uv, edge[BR].fX);
+ SkScalar y0 = SkScalarMul(UV, edge[TL].fY) + SkScalarMul(uV, edge[TR].fY) +
+ SkScalarMul(Uv, edge[BL].fY) + SkScalarMul(uv, edge[BR].fY);
+
+ SkScalar x = SkScalarMul(SK_Scalar1 - v, edge[TL+iu].fX) +
+ SkScalarMul(u, edge[TR+iv].fX) +
+ SkScalarMul(v, edge[BR+nu-iu].fX) +
+ SkScalarMul(SK_Scalar1 - u, edge[BL+nv-iv].fX) - x0;
+ SkScalar y = SkScalarMul(SK_Scalar1 - v, edge[TL+iu].fY) +
+ SkScalarMul(u, edge[TR+iv].fY) +
+ SkScalarMul(v, edge[BR+nu-iu].fY) +
+ SkScalarMul(SK_Scalar1 - u, edge[BL+nv-iv].fY) - y0;
+ pt->set(x, y);
+}
+
+static int ScalarTo255(SkScalar v) {
+ int scale = SkScalarToFixed(v) >> 8;
+ if (scale < 0) {
+ scale = 0;
+ } else if (scale > 255) {
+ scale = 255;
+ }
+ return scale;
+}
+
+static SkColor make_color(SkScalar s, SkScalar t) {
+ int cs = ScalarTo255(s);
+ int ct = ScalarTo255(t);
+ return SkColorSetARGB(0xFF, cs, 0, 0) + SkColorSetARGB(0, 0, ct, 0);
+}
+
+void Patch::draw(SkCanvas* canvas, const SkPaint& paint, int nu, int nv,
+ bool doTextures, bool doColors) {
+ if (nu < 1 || nv < 1) {
+ return;
+ }
+
+ int i, npts = (nu + nv) * 2;
+ SkAutoSTMalloc<16, SkPoint> storage(npts + 1);
+ SkPoint* edge0 = storage.get();
+ SkPoint* edge1 = edge0 + nu;
+ SkPoint* edge2 = edge1 + nv;
+ SkPoint* edge3 = edge2 + nu;
+
+ // evaluate the edge points
+ eval_patch_edge(fPts + 0, edge0, nu);
+ eval_patch_edge(fPts + 3, edge1, nv);
+ eval_patch_edge(fPts + 6, edge2, nu);
+ eval_patch_edge(fPts + 9, edge3, nv);
+ edge3[nv] = edge0[0]; // the last shall be first
+
+ for (i = 0; i < npts; i++) {
+// canvas->drawLine(edge0[i].fX, edge0[i].fY, edge0[i+1].fX, edge0[i+1].fY, paint);
+ }
+
+ int row, vertCount = (nu + 1) * (nv + 1);
+ SkAutoTMalloc<SkPoint> vertStorage(vertCount);
+ SkPoint* verts = vertStorage.get();
+
+ // first row
+ memcpy(verts, edge0, (nu + 1) * sizeof(SkPoint));
+ // rows
+ SkPoint* r = verts;
+ for (row = 1; row < nv; row++) {
+ r += nu + 1;
+ r[0] = edge3[nv - row];
+ for (int col = 1; col < nu; col++) {
+ eval_sheet(edge0, nu, nv, col, row, &r[col]);
+ }
+ r[nu] = edge1[row];
+ }
+ // last row
+ SkPoint* last = verts + nv * (nu + 1);
+ for (i = 0; i <= nu; i++) {
+ last[i] = edge2[nu - i];
+ }
+
+// canvas->drawPoints(verts, vertCount, paint);
+
+ int stripCount = (nu + 1) * 2;
+ SkAutoTMalloc<SkPoint> stripStorage(stripCount * 2);
+ SkAutoTMalloc<SkColor> colorStorage(stripCount);
+ SkPoint* strip = stripStorage.get();
+ SkPoint* tex = strip + stripCount;
+ SkColor* colors = colorStorage.get();
+ SkScalar t = 0;
+ const SkScalar ds = SK_Scalar1 * fW / nu;
+ const SkScalar dt = SK_Scalar1 * fH / nv;
+ r = verts;
+ for (row = 0; row < nv; row++) {
+ SkPoint* upper = r;
+ SkPoint* lower = r + nu + 1;
+ r = lower;
+ SkScalar s = 0;
+ for (i = 0; i <= nu; i++) {
+ strip[i*2 + 0] = *upper++;
+ strip[i*2 + 1] = *lower++;
+ tex[i*2 + 0].set(s, t);
+ tex[i*2 + 1].set(s, t + dt);
+ colors[i*2 + 0] = make_color(s/fW, t/fH);
+ colors[i*2 + 1] = make_color(s/fW, (t + dt)/fH);
+ s += ds;
+ }
+ t += dt;
+ canvas->drawVertices(SkCanvas::kTriangleStrip_VertexMode, stripCount,
+ strip, doTextures ? tex : NULL,
+ doColors ? colors : NULL, NULL,
+ NULL, 0, paint);
+ }
+}
+
+static void drawpatches(SkCanvas* canvas, const SkPaint& paint, int nu, int nv,
+ Patch* patch) {
+
+ SkAutoCanvasRestore ar(canvas, true);
+
+ patch->draw(canvas, paint, 10, 10, false, false);
+ canvas->translate(SkIntToScalar(300), 0);
+ patch->draw(canvas, paint, 10, 10, true, false);
+ canvas->translate(SkIntToScalar(300), 0);
+ patch->draw(canvas, paint, 10, 10, false, true);
+ canvas->translate(SkIntToScalar(300), 0);
+ patch->draw(canvas, paint, 10, 10, true, true);
+}
+
+class PatchView : public SkView {
+ SkShader* fShader0;
+ SkShader* fShader1;
+ SkIPoint fSize0, fSize1;
+ SkPoint fPts[12];
+
+public:
+ PatchView() {
+ fShader0 = make_shader0(&fSize0);
+ fSize1 = fSize0;
+ if (fSize0.fX == 0 || fSize0.fY == 0) {
+ fSize1.set(2, 2);
+ }
+ fShader1 = make_shader1(fSize1);
+
+ const SkScalar S = SkIntToScalar(90);
+ const SkScalar T = SkIntToScalar(64);
+ fPts[0].set(S*1, T);
+ fPts[1].set(S*2, T);
+ fPts[2].set(S*3, T);
+ fPts[3].set(S*4, T);
+ fPts[4].set(S*4, T*2);
+ fPts[5].set(S*4, T*3);
+ fPts[6].set(S*4, T*4);
+ fPts[7].set(S*3, T*4);
+ fPts[8].set(S*2, T*4);
+ fPts[9].set(S*1, T*4);
+ fPts[10].set(S*1, T*3);
+ fPts[11].set(S*1, T*2);
+ }
+
+ virtual ~PatchView() {
+ fShader0->safeUnref();
+ fShader1->safeUnref();
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SkString str("Patch");
+ SampleCode::TitleR(evt, str.c_str());
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorGRAY);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ SkPaint paint;
+ paint.setDither(true);
+ paint.setFilterBitmap(true);
+
+ if (false) {
+ SkPath p;
+ p.moveTo(0, 0);
+ p.lineTo(SkIntToScalar(30000), SkIntToScalar(30000));
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(4));
+ paint.setAntiAlias(true);
+ canvas->scale(SkIntToScalar(3), SkIntToScalar(3));
+ canvas->drawPath(p, paint);
+ return;
+ }
+
+ if (false) {
+ for (int dy = -1; dy <= 2; dy++) {
+ canvas->save();
+ if (dy == 2) {
+ canvas->translate(0, SK_Scalar1/2);
+ } else {
+ canvas->translate(0, SkIntToScalar(dy)/100);
+ }
+
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config, 20, 20);
+ bm.allocPixels();
+ SkCanvas c(bm);
+ SkRect r = { 0, 0, 20*SK_Scalar1, SK_Scalar1 };
+ for (int y = 0; y < 20; y++) {
+ SkPaint p;
+ p.setARGB(0xFF, y*5&0xFF, y*13&0xFF, y*29&0xFF);
+ c.drawRect(r, p);
+ r.offset(0, SK_Scalar1);
+ }
+ SkIRect src;
+ SkRect dst;
+
+ static const int srcPts[] = {
+ // 2, 0, 15, 2,
+ 2, 2, 15, 16,
+ 17, 2, 2, 16,
+ 19, 2, 1, 16,
+ // 2, 18, 15, 2
+ };
+ static const double dstPts[] = {
+ // 7, 262 15, 24.5,
+ 7, 286.5, 15, 16,
+ 22, 286.5, 5, 16,
+ 27, 286.5, 1, 16,
+ // 7, 302.5, 15, 24.5
+ };
+
+ SkPaint p;
+// p.setFilterBitmap(true);
+ const int* s = srcPts;
+ const double* d = dstPts;
+ for (int i = 0; i < 3; i++) {
+ src.set(s[0], s[1], s[0]+s[2], s[1]+s[3]);
+ dst.set(SkDoubleToScalar(d[0]),
+ SkDoubleToScalar(d[1]),
+ SkDoubleToScalar(d[0]+d[2]),
+ SkDoubleToScalar(d[1]+d[3]));
+ canvas->drawBitmapRect(bm, &src, dst, &p);
+ canvas->translate(SkDoubleToScalar(1), 0);
+ s += 4;
+ d += 4;
+ }
+ canvas->restore();
+ canvas->translate(SkIntToScalar(32), 0);
+ }
+ return;
+ }
+
+ Patch patch;
+
+ paint.setShader(fShader0);
+ if (fSize0.fX == 0) {
+ fSize0.fX = 1;
+ }
+ if (fSize0.fY == 0) {
+ fSize0.fY = 1;
+ }
+ patch.setBounds(fSize0.fX, fSize0.fY);
+
+ patch.setPatch(fPts);
+ drawpatches(canvas, paint, 10, 10, &patch);
+
+ paint.setShader(NULL);
+ paint.setAntiAlias(true);
+ paint.setStrokeWidth(SkIntToScalar(5));
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(fPts),
+ fPts, paint);
+
+ canvas->translate(0, SkIntToScalar(300));
+
+ paint.setAntiAlias(false);
+ paint.setShader(fShader1);
+ patch.setBounds(fSize1.fX, fSize1.fY);
+ drawpatches(canvas, paint, 10, 10, &patch);
+ }
+
+ class PtClick : public Click {
+ public:
+ int fIndex;
+ PtClick(SkView* view, int index) : Click(view), fIndex(index) {}
+ };
+
+ static bool hittest(const SkPoint& pt, SkScalar x, SkScalar y) {
+ return SkPoint::Length(pt.fX - x, pt.fY - y) < SkIntToScalar(5);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ for (int i = 0; i < SK_ARRAY_COUNT(fPts); i++) {
+ if (hittest(fPts[i], x, y)) {
+ return new PtClick(this, i);
+ }
+ }
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click) {
+ fPts[((PtClick*)click)->fIndex].set(click->fCurr.fX, click->fCurr.fY);
+ this->inval(NULL);
+ return true;
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new PatchView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SamplePath.cpp b/samplecode/SamplePath.cpp
new file mode 100644
index 0000000..98f1a5b
--- /dev/null
+++ b/samplecode/SamplePath.cpp
@@ -0,0 +1,163 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkPath.h"
+#include "SkPorterDuff.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+
+class PathView : public SkView {
+public:
+ int fDStroke, fStroke, fMinStroke, fMaxStroke;
+ SkPath fPath[6];
+ bool fShowHairline;
+
+ PathView()
+ {
+ fShowHairline = false;
+
+ fDStroke = 1;
+ fStroke = 10;
+ fMinStroke = 10;
+ fMaxStroke = 180;
+
+ const int V = 85;
+
+ fPath[0].moveTo(SkIntToScalar(40), SkIntToScalar(70));
+ fPath[0].lineTo(SkIntToScalar(70), SkIntToScalar(70) + SK_Scalar1/1);
+ fPath[0].lineTo(SkIntToScalar(110), SkIntToScalar(70));
+
+ fPath[1].moveTo(SkIntToScalar(40), SkIntToScalar(70));
+ fPath[1].lineTo(SkIntToScalar(70), SkIntToScalar(70) - SK_Scalar1/1);
+ fPath[1].lineTo(SkIntToScalar(110), SkIntToScalar(70));
+
+ fPath[2].moveTo(SkIntToScalar(V), SkIntToScalar(V));
+ fPath[2].lineTo(SkIntToScalar(50), SkIntToScalar(V));
+ fPath[2].lineTo(SkIntToScalar(50), SkIntToScalar(50));
+
+ fPath[3].moveTo(SkIntToScalar(50), SkIntToScalar(50));
+ fPath[3].lineTo(SkIntToScalar(50), SkIntToScalar(V));
+ fPath[3].lineTo(SkIntToScalar(V), SkIntToScalar(V));
+
+ fPath[4].moveTo(SkIntToScalar(50), SkIntToScalar(50));
+ fPath[4].lineTo(SkIntToScalar(50), SkIntToScalar(V));
+ fPath[4].lineTo(SkIntToScalar(52), SkIntToScalar(50));
+
+ fPath[5].moveTo(SkIntToScalar(52), SkIntToScalar(50));
+ fPath[5].lineTo(SkIntToScalar(50), SkIntToScalar(V));
+ fPath[5].lineTo(SkIntToScalar(50), SkIntToScalar(50));
+ }
+
+ virtual ~PathView()
+ {
+ }
+
+ void nextStroke()
+ {
+ fStroke += fDStroke;
+ if (fStroke > fMaxStroke || fStroke < fMinStroke)
+ fDStroke = -fDStroke;
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Paths");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+ canvas->drawColor(0xFFDDDDDD);
+// canvas->drawColor(SK_ColorWHITE);
+ }
+
+ void drawPath(SkCanvas* canvas, const SkPath& path, SkPaint::Join j)
+ {
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeJoin(j);
+ paint.setStrokeWidth(SkIntToScalar(fStroke));
+
+ if (fShowHairline)
+ {
+ SkPath fill;
+
+ paint.getFillPath(path, &fill);
+ paint.setStrokeWidth(0);
+ canvas->drawPath(fill, paint);
+ }
+ else
+ canvas->drawPath(path, paint);
+
+ paint.setColor(SK_ColorRED);
+ paint.setStrokeWidth(0);
+ canvas->drawPath(path, paint);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ canvas->translate(SkIntToScalar(50), SkIntToScalar(50));
+
+ static const SkPaint::Join gJoins[] = {
+ SkPaint::kBevel_Join,
+ SkPaint::kMiter_Join,
+ SkPaint::kRound_Join
+ };
+
+ for (int i = 0; i < SK_ARRAY_COUNT(gJoins); i++)
+ {
+ canvas->save();
+ for (int j = 0; j < SK_ARRAY_COUNT(fPath); j++)
+ {
+ this->drawPath(canvas, fPath[j], gJoins[i]);
+ canvas->translate(SkIntToScalar(200), 0);
+ }
+ canvas->restore();
+
+ canvas->translate(0, SkIntToScalar(200));
+ }
+
+ this->nextStroke();
+ this->inval(NULL);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ fShowHairline = !fShowHairline;
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new PathView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SamplePathEffects.cpp b/samplecode/SamplePathEffects.cpp
new file mode 100644
index 0000000..4e964d7
--- /dev/null
+++ b/samplecode/SamplePathEffects.cpp
@@ -0,0 +1,282 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "Sk1DPathEffect.h"
+#include "SkCornerPathEffect.h"
+#include "SkPathMeasure.h"
+#include "SkRandom.h"
+#include "SkColorPriv.h"
+#include "SkPixelXorXfermode.h"
+
+static void test_grow(SkPath* path)
+{
+ for (int i = 0; i < 100000; i++)
+ {
+ path->lineTo(i, i);
+ path->lineTo(i, i*2);
+ }
+}
+
+#define CORNER_RADIUS 12
+static SkScalar gPhase;
+
+static const int gXY[] = {
+ 4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4
+};
+
+static SkPathEffect* make_pe(int flags)
+{
+ if (flags == 1)
+ return new SkCornerPathEffect(SkIntToScalar(CORNER_RADIUS));
+
+ SkPath path;
+ path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
+ for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
+ path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
+ path.close();
+ path.offset(SkIntToScalar(-6), 0);
+
+ SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12), gPhase, SkPath1DPathEffect::kRotate_Style);
+
+ if (flags == 2)
+ return outer;
+
+ SkPathEffect* inner = new SkCornerPathEffect(SkIntToScalar(CORNER_RADIUS));
+
+ SkPathEffect* pe = new SkComposePathEffect(outer, inner);
+ outer->unref();
+ inner->unref();
+ return pe;
+}
+
+static SkPathEffect* make_warp_pe()
+{
+ SkPath path;
+ path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
+ for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
+ path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
+ path.close();
+ path.offset(SkIntToScalar(-6), 0);
+
+ SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12), gPhase, SkPath1DPathEffect::kMorph_Style);
+ SkPathEffect* inner = new SkCornerPathEffect(SkIntToScalar(CORNER_RADIUS));
+
+ SkPathEffect* pe = new SkComposePathEffect(outer, inner);
+ outer->unref();
+ inner->unref();
+ return pe;
+}
+
+///////////////////////////////////////////////////////////
+
+#include "SkColorFilter.h"
+#include "SkPorterDuff.h"
+#include "SkLayerRasterizer.h"
+
+class testrast : public SkLayerRasterizer {
+public:
+ testrast()
+ {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+#if 0
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SK_Scalar1*4);
+ this->addLayer(paint);
+
+ paint.setStrokeWidth(SK_Scalar1*1);
+ paint.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ this->addLayer(paint);
+#else
+ paint.setAlpha(0x66);
+ this->addLayer(paint, SkIntToScalar(4), SkIntToScalar(4));
+
+ paint.setAlpha(0xFF);
+ this->addLayer(paint);
+#endif
+ }
+};
+
+class PathEffectView : public SkView {
+ SkPath fPath;
+ SkPoint fClickPt;
+public:
+ PathEffectView()
+ {
+ SkRandom rand;
+ int steps = 20;
+ SkScalar dist = SkIntToScalar(500);
+ SkScalar x = SkIntToScalar(20);
+ SkScalar y = SkIntToScalar(50);
+
+ fPath.moveTo(x, y);
+ for (int i = 0; i < steps; i++)
+ {
+ x += dist/steps;
+ fPath.lineTo(x, y + SkIntToScalar(rand.nextS() % 25));
+ }
+
+ fClickPt.set(SkIntToScalar(200), SkIntToScalar(200));
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "PathEffects");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+ canvas->drawColor(0xFFDDDDDD);
+
+#if 0
+ SkPath path;
+ test_grow(&path);
+ SkPaint p;
+
+ p.setAntiAlias(true);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1);
+ canvas->drawPath(path, p);
+ path.close();
+#endif
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ if (true)
+ {
+ canvas->drawColor(SK_ColorWHITE);
+
+ SkPixelXorXfermode mode(SK_ColorWHITE);
+ SkPaint paint;
+
+ paint.setColor(SK_ColorRED);
+ paint.setXfermode(&mode);
+ paint.setStrokeWidth(SkIntToScalar(8));
+
+ canvas->drawLine(SkIntToScalar(100), SkIntToScalar(100),
+ SkIntToScalar(200), SkIntToScalar(200), paint);
+ canvas->drawLine(SkIntToScalar(100), SkIntToScalar(200),
+ SkIntToScalar(200), SkIntToScalar(100), paint);
+ // return;
+ }
+
+ if (false)
+ {
+ SkPath path;
+ SkPoint pts[] = { SkIntToScalar(100), SkIntToScalar(100),
+ SkIntToScalar(200), SkIntToScalar(100),
+ SkIntToScalar(100), SkIntToScalar(200)
+ };
+ SkPaint paint;
+
+ pts[2] = fClickPt;
+
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(5));
+
+ path.moveTo(pts[0]);
+ path.arcTo(pts[1], pts[2], SkIntToScalar(50));
+ canvas->drawPath(path, paint);
+
+ paint.setStrokeWidth(0);
+ paint.setColor(SK_ColorRED);
+ canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint);
+ canvas->drawLine(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, paint);
+ return;
+ }
+
+ gPhase -= SK_Scalar1;
+ this->inval(nil);
+
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(5));
+ canvas->drawPath(fPath, paint);
+ paint.setStrokeWidth(0);
+
+ paint.setColor(SK_ColorRED);
+ paint.setPathEffect(make_pe(1))->unref();
+ canvas->drawPath(fPath, paint);
+
+ canvas->translate(0, SkIntToScalar(50));
+
+ paint.setColor(SK_ColorBLUE);
+ paint.setPathEffect(make_pe(2))->unref();
+ canvas->drawPath(fPath, paint);
+
+ canvas->translate(0, SkIntToScalar(50));
+
+ paint.setARGB(0xFF, 0, 0xBB, 0);
+ paint.setPathEffect(make_pe(3))->unref();
+ canvas->drawPath(fPath, paint);
+
+ canvas->translate(0, SkIntToScalar(50));
+
+ paint.setARGB(0xFF, 0, 0, 0);
+ paint.setPathEffect(make_warp_pe())->unref();
+ paint.setRasterizer(new testrast)->unref();
+ canvas->drawPath(fPath, paint);
+
+ {
+ SkRect oval;
+
+ oval.set(SkIntToScalar(50), SkIntToScalar(100),
+ SkIntToScalar(150), SkIntToScalar(150));
+ canvas->drawRoundRect(oval, SkIntToScalar(8), SkIntToScalar(8), paint);
+ }
+
+ {
+ SkRect bounds;
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setAlpha(0x80);
+ paint.setColorFilter(
+ SkColorFilter::CreatePorterDuffFilter(
+ SkColorSetARGB(0x44, 0, 0xFF, 0), SkPorterDuff::kSrcATop_Mode))->unref();
+
+ bounds.set(SkIntToScalar(10), SkIntToScalar(10), SkIntToScalar(150), SkIntToScalar(70));
+ canvas->saveLayer(&bounds, &paint,
+ (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag));
+
+ paint.setColorFilter(NULL);
+ paint.setColor(SK_ColorRED);
+ canvas->drawOval(bounds, paint);
+
+ paint.setColor(SK_ColorBLUE);
+ paint.setAlpha(0x80);
+ bounds.inset(SkIntToScalar(10), SkIntToScalar(10));
+ canvas->drawOval(bounds, paint);
+
+ canvas->restore();
+ }
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new PathEffectView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SamplePicture.cpp b/samplecode/SamplePicture.cpp
new file mode 100644
index 0000000..dfc1555
--- /dev/null
+++ b/samplecode/SamplePicture.cpp
@@ -0,0 +1,157 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "Sk64.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkKernel33MaskFilter.h"
+#include "SkPath.h"
+#include "SkPicture.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+#include "SkXfermode.h"
+
+#include "SkStream.h"
+#include "SkXMLParser.h"
+
+static void drawCircle(SkCanvas* canvas, int r, SkColor color) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(color);
+
+ canvas->drawCircle(SkIntToScalar(r), SkIntToScalar(r), SkIntToScalar(r),
+ paint);
+}
+
+class PictureView : public SkView {
+public:
+ PictureView() {
+ fPicture = new SkPicture;
+ SkCanvas* canvas = fPicture->beginRecording(100, 100);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+ drawCircle(canvas, 50, SK_ColorBLACK);
+ fSubPicture = new SkPicture;
+ canvas->drawPicture(*fSubPicture);
+ canvas->translate(SkIntToScalar(50), 0);
+ canvas->drawPicture(*fSubPicture);
+ canvas->translate(0, SkIntToScalar(50));
+ canvas->drawPicture(*fSubPicture);
+ canvas->translate(SkIntToScalar(-50), 0);
+ canvas->drawPicture(*fSubPicture);
+ // fPicture now has (4) references to us. We can release ours, and just
+ // unref fPicture in our destructor, and it will in turn take care of
+ // the other references to fSubPicture
+ fSubPicture->unref();
+ }
+
+ virtual ~PictureView() {
+ fPicture->unref();
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Picture");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+// canvas->drawColor(0xFFDDDDDD);
+ canvas->drawColor(SK_ColorWHITE);
+ // canvas->drawColor(SK_ColorBLACK);
+ }
+
+ void drawSomething(SkCanvas* canvas) {
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+
+ paint.setColor(SK_ColorRED);
+ canvas->drawCircle(SkIntToScalar(50), SkIntToScalar(50),
+ SkIntToScalar(40), paint);
+ paint.setColor(SK_ColorBLACK);
+ paint.setTextSize(SkIntToScalar(40));
+ canvas->drawText("Picture", 7, SkIntToScalar(50), SkIntToScalar(62),
+ paint);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ drawSomething(canvas);
+
+ SkPicture* pict = new SkPicture;
+ SkAutoUnref aur(pict);
+
+ drawSomething(pict->beginRecording(100, 100));
+ pict->endRecording();
+
+ canvas->save();
+ canvas->translate(SkIntToScalar(300), SkIntToScalar(50));
+ canvas->scale(-SK_Scalar1, -SK_Scalar1);
+ canvas->translate(-SkIntToScalar(100), -SkIntToScalar(50));
+ canvas->drawPicture(*pict);
+ canvas->restore();
+
+ canvas->save();
+ canvas->translate(SkIntToScalar(200), SkIntToScalar(150));
+ canvas->scale(SK_Scalar1, -SK_Scalar1);
+ canvas->translate(0, -SkIntToScalar(50));
+ canvas->drawPicture(*pict);
+ canvas->restore();
+
+ canvas->save();
+ canvas->translate(SkIntToScalar(100), SkIntToScalar(100));
+ canvas->scale(-SK_Scalar1, SK_Scalar1);
+ canvas->translate(-SkIntToScalar(100), 0);
+ canvas->drawPicture(*pict);
+ canvas->restore();
+
+ // test that we can re-record a subpicture, and see the results
+
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(250));
+ drawCircle(fSubPicture->beginRecording(50, 50), 25,
+ fRand.nextU() | 0xFF000000);
+ canvas->drawPicture(*fPicture);
+ delayInval(500);
+ }
+
+private:
+ #define INVAL_ALL_TYPE "inval-all"
+
+ void delayInval(SkMSec delay) {
+ (new SkEvent(INVAL_ALL_TYPE))->post(this->getSinkID(), delay);
+ }
+
+ virtual bool onEvent(const SkEvent& evt) {
+ if (evt.isType(INVAL_ALL_TYPE)) {
+ this->inval(NULL);
+ return true;
+ }
+ return this->INHERITED::onEvent(evt);
+ }
+
+ SkPicture* fPicture;
+ SkPicture* fSubPicture;
+ SkRandom fRand;
+
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new PictureView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SamplePoints.cpp b/samplecode/SamplePoints.cpp
new file mode 100644
index 0000000..7dc98f3
--- /dev/null
+++ b/samplecode/SamplePoints.cpp
@@ -0,0 +1,121 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "Sk64.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkKernel33MaskFilter.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+#include "SkXfermode.h"
+
+#include "SkStream.h"
+#include "SkXMLParser.h"
+
+static SkRandom gRand;
+
+static const struct {
+ const char* fName;
+ uint32_t fFlags;
+ bool fFlushCache;
+} gHints[] = {
+ { "Linear", SkPaint::kLinearText_Flag, false },
+ { "Normal", 0, true },
+ { "Subpixel", SkPaint::kSubpixelText_Flag, true }
+};
+
+#ifdef SK_DEBUG
+ #define REPEAT_COUNT 1
+#else
+ #define REPEAT_COUNT 5000
+#endif
+
+class PointsView : public SkView {
+ bool fAA;
+public:
+ PointsView() : fAA(false) {}
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Points");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+// canvas->drawColor(0xFFDDDDDD);
+ canvas->drawColor(SK_ColorWHITE);
+ // canvas->drawColor(SK_ColorBLACK);
+ }
+
+ static void fill_pts(SkPoint pts[], size_t n, SkRandom* rand)
+ {
+ for (size_t i = 0; i < n; i++)
+ pts[i].set(rand->nextUScalar1() * 640, rand->nextUScalar1() * 480);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ canvas->translate(SK_Scalar1, SK_Scalar1);
+
+ SkRandom rand;
+ SkPaint p0, p1, p2, p3;
+ const size_t n = 99;
+ const int TIMES = 1;
+
+ p0.setColor(SK_ColorRED);
+ p1.setColor(SK_ColorGREEN);
+ p2.setColor(SK_ColorBLUE);
+ p3.setColor(SK_ColorWHITE);
+
+ // fAA = !fAA;
+
+ p0.setAntiAlias(fAA);
+ p1.setAntiAlias(fAA);
+ p2.setAntiAlias(fAA);
+ p3.setAntiAlias(fAA);
+
+ p0.setStrokeWidth(SkIntToScalar(4));
+ p2.setStrokeWidth(SkIntToScalar(6));
+
+ SkPoint* pts = new SkPoint[n];
+ fill_pts(pts, n, &rand);
+
+// SkMSec now = SkTime::GetMSecs();
+ for (int times = 0; times < TIMES; times++)
+ {
+ canvas->drawPoints(SkCanvas::kPolygon_PointMode, n, pts, p0);
+ canvas->drawPoints(SkCanvas::kLines_PointMode, n, pts, p1);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, n, pts, p2);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, n, pts, p3);
+ }
+ // printf("----- msecs %d\n", SkTime::GetMSecs() - now);
+ delete[] pts;
+ }
+
+private:
+
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new PointsView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SamplePolyToPoly.cpp b/samplecode/SamplePolyToPoly.cpp
new file mode 100644
index 0000000..98e4484
--- /dev/null
+++ b/samplecode/SamplePolyToPoly.cpp
@@ -0,0 +1,165 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGraphics.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+#include "SkTime.h"
+
+extern bool SkSetPoly3To3(SkMatrix* matrix, const SkPoint src[3], const SkPoint dst[3]);
+
+class PolyToPolyView : public SkView {
+public:
+ PolyToPolyView() {
+ // tests
+ {
+ SkPoint src[] = { 0, 0, SK_Scalar1, 0, 0, SK_Scalar1 };
+ SkPoint dst[] = { 0, 0, 2*SK_Scalar1, 0, 0, 2*SK_Scalar1 };
+ SkMatrix m1, m2;
+ bool success;
+
+ success = m1.setPolyToPoly(src, dst, 3);
+ SkDebugf("--- setPolyToPoly1 %d\n", success);
+
+ m2.reset();
+ m2.set(SkMatrix::kMScaleX, dst[1].fX - dst[0].fX);
+ m2.set(SkMatrix::kMSkewX, dst[2].fX - dst[0].fX);
+ m2.set(SkMatrix::kMTransX, dst[0].fX);
+ m2.set(SkMatrix::kMSkewY, dst[1].fY - dst[0].fY);
+ m2.set(SkMatrix::kMScaleY, dst[2].fY - dst[0].fY);
+ m2.set(SkMatrix::kMTransY, dst[0].fY);
+
+ m1.reset();
+
+ const SkScalar src1[] = {
+ 0, 0, 0, SkFloatToScalar(427), SkFloatToScalar(316), SkFloatToScalar(427), SkFloatToScalar(316), 0
+ };
+ const SkScalar dst1[] = {
+ SkFloatToScalar(158), SkFloatToScalar(177.5f), SkFloatToScalar(158), SkFloatToScalar(249.5f),
+ SkFloatToScalar(158), SkFloatToScalar(604.5f), SkFloatToScalar(158), SkFloatToScalar(-177.5f)
+ };
+
+ success = m2.setPolyToPoly((const SkPoint*)src1, (SkPoint*)dst1, 4);
+ SkDebugf("--- setPolyToPoly2 %d\n", success);
+
+ {
+ const SkPoint src[] = {
+ SkIntToScalar(1), SkIntToScalar(0),
+ SkIntToScalar(4), SkIntToScalar(7),
+ SkIntToScalar(10), SkIntToScalar(2)
+ };
+ const SkPoint dst[] = {
+ SkIntToScalar(4), SkIntToScalar(2),
+ SkIntToScalar(45), SkIntToScalar(26),
+ SkIntToScalar(32), SkIntToScalar(17)
+ };
+
+ SkMatrix m0, m1;
+ m0.setPolyToPoly(src, dst, 3);
+ SkSetPoly3To3(&m1, src, dst);
+ m0.dump();
+ m1.dump();
+ }
+ }
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SkString str("PolyToPolyView");
+ SampleCode::TitleR(evt, str.c_str());
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorWHITE);
+ }
+
+ static void doDraw(SkCanvas* canvas, SkPaint* paint, const int isrc[],
+ const int idst[], int count) {
+ SkMatrix matrix;
+ SkPoint src[4], dst[4];
+
+ for (int i = 0; i < count; i++) {
+ src[i].set(SkIntToScalar(isrc[2*i+0]), SkIntToScalar(isrc[2*i+1]));
+ dst[i].set(SkIntToScalar(idst[2*i+0]), SkIntToScalar(idst[2*i+1]));
+ }
+
+ canvas->save();
+ matrix.setPolyToPoly(src, dst, count);
+ canvas->concat(matrix);
+
+ paint->setColor(SK_ColorGRAY);
+ paint->setStyle(SkPaint::kStroke_Style);
+ const SkScalar D = SkIntToScalar(64);
+ canvas->drawRectCoords(0, 0, D, D, *paint);
+ canvas->drawLine(0, 0, D, D, *paint);
+ canvas->drawLine(0, D, D, 0, *paint);
+
+ SkPaint::FontMetrics fm;
+ paint->getFontMetrics(&fm);
+ paint->setColor(SK_ColorRED);
+ paint->setStyle(SkPaint::kFill_Style);
+ SkScalar x = D/2;
+ float y = D/2 - (fm.fAscent + fm.fDescent)/2;
+ SkString str;
+ str.appendS32(count);
+ canvas->drawText(str.c_str(), str.size(), x, y, *paint);
+
+ canvas->restore();
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStrokeWidth(SkIntToScalar(4));
+ paint.setTextSize(SkIntToScalar(40));
+ paint.setTextAlign(SkPaint::kCenter_Align);
+
+ canvas->save();
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
+ // translate (1 point)
+ const int src1[] = { 0, 0 };
+ const int dst1[] = { 5, 5 };
+ doDraw(canvas, &paint, src1, dst1, 1);
+ canvas->restore();
+
+ canvas->save();
+ canvas->translate(SkIntToScalar(160), SkIntToScalar(10));
+ // rotate/uniform-scale (2 points)
+ const int src2[] = { 32, 32, 64, 32 };
+ const int dst2[] = { 32, 32, 64, 48 };
+ doDraw(canvas, &paint, src2, dst2, 2);
+ canvas->restore();
+
+ canvas->save();
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(110));
+ // rotate/skew (3 points)
+ const int src3[] = { 0, 0, 64, 0, 0, 64 };
+ const int dst3[] = { 0, 0, 96, 0, 24, 64 };
+ doDraw(canvas, &paint, src3, dst3, 3);
+ canvas->restore();
+
+ canvas->save();
+ canvas->translate(SkIntToScalar(160), SkIntToScalar(110));
+ // perspective (4 points)
+ const int src4[] = { 0, 0, 64, 0, 64, 64, 0, 64 };
+ const int dst4[] = { 0, 0, 96, 0, 64, 96, 0, 64 };
+ doDraw(canvas, &paint, src4, dst4, 4);
+ canvas->restore();
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new PolyToPolyView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleRegion.cpp b/samplecode/SampleRegion.cpp
new file mode 100644
index 0000000..d3fe062
--- /dev/null
+++ b/samplecode/SampleRegion.cpp
@@ -0,0 +1,307 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkImageDecoder.h"
+
+#ifdef SK_DEBUG
+static void make_rgn(SkRegion* rgn, int left, int top, int right, int bottom,
+ size_t count, int32_t runs[]) {
+ SkIRect r;
+ r.set(left, top, right, bottom);
+
+ rgn->debugSetRuns(runs, count);
+ SkASSERT(rgn->getBounds() == r);
+}
+
+static void test_union_bug_1505668(SkRegion* ra, SkRegion* rb, SkRegion* rc) {
+ static int32_t dataA[] = {
+ 0x00000001, 0x000001dd,
+ 0x00000001, 0x0000000c, 0x0000000d, 0x00000025,
+ 0x7fffffff, 0x000001de, 0x00000001, 0x00000025,
+ 0x7fffffff, 0x000004b3, 0x00000001, 0x00000026,
+ 0x7fffffff, 0x000004b4, 0x0000000c, 0x00000026,
+ 0x7fffffff, 0x00000579, 0x00000000, 0x0000013a,
+ 0x7fffffff, 0x000005d8, 0x00000000, 0x0000013b,
+ 0x7fffffff, 0x7fffffff
+ };
+ make_rgn(ra, 0, 1, 315, 1496, SK_ARRAY_COUNT(dataA), dataA);
+
+ static int32_t dataB[] = {
+ 0x000000b6, 0x000000c4,
+ 0x000000a1, 0x000000f0, 0x7fffffff, 0x000000d6,
+ 0x7fffffff, 0x000000e4, 0x00000070, 0x00000079,
+ 0x000000a1, 0x000000b0, 0x7fffffff, 0x000000e6,
+ 0x7fffffff, 0x000000f4, 0x00000070, 0x00000079,
+ 0x000000a1, 0x000000b0, 0x7fffffff, 0x000000f6,
+ 0x7fffffff, 0x00000104, 0x000000a1, 0x000000b0,
+ 0x7fffffff, 0x7fffffff
+ };
+ make_rgn(rb, 112, 182, 240, 260, SK_ARRAY_COUNT(dataB), dataB);
+
+ rc->op(*ra, *rb, SkRegion::kUnion_Op);
+}
+#endif
+
+static void paint_rgn(SkCanvas* canvas, const SkRegion& rgn, const SkPaint& paint)
+{
+ SkRegion::Iterator iter(rgn);
+
+ for (; !iter.done(); iter.next())
+ {
+ SkRect r;
+ r.set(iter.rect());
+ canvas->drawRect(r, paint);
+ }
+}
+
+class RegionView : public SkView {
+public:
+ RegionView()
+ {
+ fBase.set(100, 100, 150, 150);
+ fRect = fBase;
+ fRect.inset(5, 5);
+ fRect.offset(25, 25);
+ }
+
+ void build_rgn(SkRegion* rgn, SkRegion::Op op)
+ {
+ rgn->setRect(fBase);
+ SkIRect r = fBase;
+ r.offset(75, 20);
+ rgn->op(r, SkRegion::kUnion_Op);
+ rgn->op(fRect, op);
+ }
+
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Regions");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawOrig(SkCanvas* canvas, bool bg)
+ {
+ SkRect r;
+ SkPaint paint;
+
+ paint.setStyle(SkPaint::kStroke_Style);
+ if (bg)
+ paint.setColor(0xFFBBBBBB);
+
+ r.set(fBase);
+ canvas->drawRect(r, paint);
+ r.set(fRect);
+ canvas->drawRect(r, paint);
+ }
+
+ void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color)
+ {
+ SkRegion rgn;
+
+ this->build_rgn(&rgn, op);
+
+ {
+ SkRegion tmp, tmp2(rgn);
+
+ tmp = tmp2;
+ tmp.translate(5, -3);
+
+ {
+ char buffer[1000];
+ size_t size = tmp.flatten(NULL);
+ SkASSERT(size <= sizeof(buffer));
+ size_t size2 = tmp.flatten(buffer);
+ SkASSERT(size == size2);
+
+ SkRegion tmp3;
+ size2 = tmp3.unflatten(buffer);
+ SkASSERT(size == size2);
+
+ SkASSERT(tmp3 == tmp);
+ }
+
+ rgn.translate(20, 30, &tmp);
+ SkASSERT(rgn.isEmpty() || tmp != rgn);
+ tmp.translate(-20, -30);
+ SkASSERT(tmp == rgn);
+ }
+
+ this->drawOrig(canvas, true);
+
+ SkPaint paint;
+ paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
+ paint_rgn(canvas, rgn, paint);
+
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setColor(color);
+ paint_rgn(canvas, rgn, paint);
+ }
+
+ void drawPathOped(SkCanvas* canvas, SkRegion::Op op, SkColor color)
+ {
+ SkRegion rgn;
+ SkPath path;
+
+ this->build_rgn(&rgn, op);
+ rgn.getBoundaryPath(&path);
+
+ this->drawOrig(canvas, true);
+
+ SkPaint paint;
+
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
+ canvas->drawPath(path, paint);
+ paint.setColor(color);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawPath(path, paint);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+ canvas->drawColor(0xFFDDDDDD);
+ return;
+
+#if 0
+ SkColorTable ct;
+ SkPMColor colors[] = { SK_ColorRED, SK_ColorBLUE };
+ ct.setColors(colors, 2);
+ ct.setFlags(ct.getFlags() | SkColorTable::kColorsAreOpaque_Flag);
+
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kIndex8_Config, 20, 20, 21);
+ bm.setColorTable(&ct);
+ bm.allocPixels();
+ sk_memset16((uint16_t*)bm.getAddr8(0, 0), 0x0001, bm.rowBytes() * bm.height() / 2);
+#endif
+#if 0
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kRGB_565_Config, 20, 20, 42);
+ bm.allocPixels();
+ sk_memset32((uint32_t*)bm.getAddr16(0, 0), 0x0000FFFF, bm.rowBytes() * bm.height() / 4);
+#endif
+#if 1
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config, 20, 20);
+ bm.allocPixels();
+ sk_memset32((uint32_t*)bm.getAddr32(0, 0), 0xFFDDDDDD, bm.rowBytes() * bm.height() / 4);
+#endif
+
+ SkPaint paint;
+
+// SkShader* shader = SkShader::CreateBitmapShader(bm, false, SkPaint::kBilinear_FilterType, SkShader::kRepeat_TileMode);
+ SkPoint pts[] = { 0, 0, SkIntToScalar(100), SkIntToScalar(0) };
+ SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE };
+ SkShader* shader = SkGradientShader::CreateLinear(pts, colors, nil, 2, SkShader::kMirror_TileMode);
+ paint.setShader(shader)->unref();
+
+ canvas->drawPaint(paint);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ if (true) {
+ SkRect r = { 0, 0, 1 << 30, 1 << 30 };
+ bool open = canvas->clipRect(r);
+ SkDebugf("---- giant clip is %d\n", open);
+ }
+ this->drawBG(canvas);
+
+#ifdef SK_DEBUG
+ if (true) {
+ SkRegion a, b, c;
+ test_union_bug_1505668(&a, &b, &c);
+
+ if (false) { // draw the result of the test
+ SkPaint paint;
+
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
+ paint.setColor(SK_ColorRED);
+ paint_rgn(canvas, a, paint);
+ paint.setColor(0x800000FF);
+ paint_rgn(canvas, b, paint);
+ paint.setColor(SK_ColorBLACK);
+ paint.setStyle(SkPaint::kStroke_Style);
+ // paint_rgn(canvas, c, paint);
+ return;
+ }
+ }
+#endif
+
+ static const struct {
+ SkColor fColor;
+ const char* fName;
+ SkRegion::Op fOp;
+ } gOps[] = {
+ { SK_ColorBLACK, "Difference", SkRegion::kDifference_Op },
+ { SK_ColorRED, "Intersect", SkRegion::kIntersect_Op },
+ { 0xFF008800, "Union", SkRegion::kUnion_Op },
+ { SK_ColorBLUE, "XOR", SkRegion::kXOR_Op }
+ };
+
+ SkPaint textPaint;
+ textPaint.setAntiAlias(true);
+ textPaint.setTextSize(SK_Scalar1*24);
+
+ this->drawOrig(canvas, false);
+ canvas->save();
+ canvas->translate(SkIntToScalar(200), 0);
+ this->drawRgnOped(canvas, SkRegion::kUnion_Op, SK_ColorBLACK);
+ canvas->restore();
+
+ canvas->translate(0, SkIntToScalar(200));
+
+ for (int op = 0; op < SK_ARRAY_COUNT(gOps); op++)
+ {
+ canvas->drawText(gOps[op].fName, strlen(gOps[op].fName), SkIntToScalar(75), SkIntToScalar(50), textPaint);
+
+ this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
+
+ if (true)
+ {
+ canvas->save();
+ canvas->translate(0, SkIntToScalar(200));
+ this->drawPathOped(canvas, gOps[op].fOp, gOps[op].fColor);
+ canvas->restore();
+ }
+
+ canvas->translate(SkIntToScalar(200), 0);
+ }
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ return fRect.contains(SkScalarRound(x), SkScalarRound(y)) ? new Click(this) : nil;
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ fRect.offset(click->fICurr.fX - click->fIPrev.fX,
+ click->fICurr.fY - click->fIPrev.fY);
+ this->inval(nil);
+ return true;
+ }
+
+private:
+ SkIRect fBase, fRect;
+
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new RegionView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleShaders.cpp b/samplecode/SampleShaders.cpp
new file mode 100644
index 0000000..f5ddca9
--- /dev/null
+++ b/samplecode/SampleShaders.cpp
@@ -0,0 +1,157 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkPath.h"
+#include "SkPorterDuff.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+#include "SkComposeShader.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTransparentShader.h"
+#include "SkTypeface.h"
+
+static SkShader* make_bitmapfade(const SkBitmap& bm)
+{
+ SkPoint pts[2];
+ SkColor colors[2];
+
+ pts[0].set(0, 0);
+ pts[1].set(0, SkIntToScalar(bm.height()));
+ colors[0] = SK_ColorBLACK;
+ colors[1] = SkColorSetARGB(0, 0, 0, 0);
+ SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode);
+
+ SkShader* shaderB = SkShader::CreateBitmapShader(bm,
+ SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
+
+ SkXfermode* mode = SkPorterDuff::CreateXfermode(SkPorterDuff::kDstIn_Mode);
+
+ SkShader* shader = new SkComposeShader(shaderB, shaderA, mode);
+ shaderA->unref();
+ shaderB->unref();
+ mode->unref();
+
+ return shader;
+}
+
+class ShaderView : public SkView {
+public:
+ SkShader* fShader;
+ SkBitmap fBitmap;
+
+ ShaderView()
+ {
+ SkImageDecoder::DecodeFile("/cover.png", &fBitmap);
+
+ SkPoint pts[2];
+ SkColor colors[2];
+
+ pts[0].set(0, 0);
+ pts[1].set(SkIntToScalar(100), 0);
+ colors[0] = SK_ColorRED;
+ colors[1] = SK_ColorBLUE;
+ SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode);
+
+ pts[0].set(0, 0);
+ pts[1].set(0, SkIntToScalar(100));
+ colors[0] = SK_ColorBLACK;
+ colors[1] = SkColorSetARGB(0x80, 0, 0, 0);
+ SkShader* shaderB = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode);
+
+ SkXfermode* mode = SkPorterDuff::CreateXfermode(SkPorterDuff::kDstIn_Mode);
+
+ fShader = new SkComposeShader(shaderA, shaderB, mode);
+ shaderA->unref();
+ shaderB->unref();
+ mode->unref();
+ }
+ virtual ~ShaderView()
+ {
+ fShader->safeUnref();
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Shaders");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+// canvas->drawColor(0xFFDDDDDD);
+ canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ canvas->drawBitmap(fBitmap, 0, 0);
+
+ {
+ SkIRect src;
+ SkRect dst;
+
+ src.set(20, 50, 120, 70);
+ dst.set(src);
+ dst.offset(SkIntToScalar(300), 0);
+
+ canvas->drawBitmapRect(fBitmap, &src, dst);
+ }
+
+ canvas->translate(SkIntToScalar(80), SkIntToScalar(80));
+
+ SkPaint paint;
+ SkRect r;
+
+ paint.setColor(SK_ColorGREEN);
+ canvas->drawRectCoords(0, 0, SkIntToScalar(100), SkIntToScalar(100), paint);
+ paint.setShader(fShader);
+ canvas->drawRectCoords(0, 0, SkIntToScalar(100), SkIntToScalar(100), paint);
+
+ canvas->translate(SkIntToScalar(110), 0);
+
+ r.set(0, 0, SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height()));
+
+ paint.setShader(NULL);
+ canvas->drawRect(r, paint);
+ paint.setShader(make_bitmapfade(fBitmap))->unref();
+ canvas->drawRect(r, paint);
+
+ paint.setShader(new SkTransparentShader)->unref();
+ canvas->drawRect(r, paint);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new ShaderView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleStrokeText.cpp b/samplecode/SampleStrokeText.cpp
new file mode 100644
index 0000000..0627d51
--- /dev/null
+++ b/samplecode/SampleStrokeText.cpp
@@ -0,0 +1,147 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "Sk64.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkKernel33MaskFilter.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+#include "SkXfermode.h"
+
+static void lettersToBitmap(SkBitmap* dst, const char chars[],
+ const SkPaint& original, SkBitmap::Config config) {
+ SkPath path;
+ SkScalar x = 0;
+ SkScalar width;
+ SkPath p;
+ for (int i = 0; i < strlen(chars); i++) {
+ original.getTextPath(&chars[i], 1, x, 0, &p);
+ path.addPath(p);
+ original.getTextWidths(&chars[i], 1, &width);
+ x += width;
+ }
+ SkRect bounds;
+ path.computeBounds(&bounds, SkPath::kExact_BoundsType);
+ SkScalar sw = -original.getStrokeWidth();
+ bounds.inset(sw, sw);
+ path.offset(-bounds.fLeft, -bounds.fTop);
+ bounds.offset(-bounds.fLeft, -bounds.fTop);
+
+ int w = SkScalarRound(bounds.width());
+ int h = SkScalarRound(bounds.height());
+ SkPaint paint(original);
+ SkBitmap src;
+ src.setConfig(config, w, h);
+ src.allocPixels();
+ src.eraseColor(0);
+ {
+ SkCanvas canvas(src);
+ paint.setAntiAlias(true);
+ paint.setColor(SK_ColorBLACK);
+ paint.setStyle(SkPaint::kFill_Style);
+ canvas.drawPath(path, paint);
+ }
+
+ dst->setConfig(config, w, h);
+ dst->allocPixels();
+ dst->eraseColor(SK_ColorWHITE);
+ {
+ SkCanvas canvas(*dst);
+ paint.setPorterDuffXfermode(SkPorterDuff::kDstATop_Mode);
+ canvas.drawBitmap(src, 0, 0, &paint);
+ paint.setColor(original.getColor());
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas.drawPath(path, paint);
+ }
+}
+
+static void lettersToBitmap2(SkBitmap* dst, const char chars[],
+ const SkPaint& original, SkBitmap::Config config) {
+ SkPath path;
+ SkScalar x = 0;
+ SkScalar width;
+ SkPath p;
+ for (int i = 0; i < strlen(chars); i++) {
+ original.getTextPath(&chars[i], 1, x, 0, &p);
+ path.addPath(p);
+ original.getTextWidths(&chars[i], 1, &width);
+ x += width;
+ }
+ SkRect bounds;
+ path.computeBounds(&bounds, SkPath::kExact_BoundsType);
+ SkScalar sw = -original.getStrokeWidth();
+ bounds.inset(sw, sw);
+ path.offset(-bounds.fLeft, -bounds.fTop);
+ bounds.offset(-bounds.fLeft, -bounds.fTop);
+
+ int w = SkScalarRound(bounds.width());
+ int h = SkScalarRound(bounds.height());
+ SkPaint paint(original);
+
+ paint.setAntiAlias(true);
+ paint.setPorterDuffXfermode(SkPorterDuff::kDstATop_Mode);
+ paint.setColor(original.getColor());
+ paint.setStyle(SkPaint::kStroke_Style);
+
+ dst->setConfig(config, w, h);
+ dst->allocPixels();
+ dst->eraseColor(SK_ColorWHITE);
+
+ SkCanvas canvas(*dst);
+ canvas.drawPath(path, paint);
+}
+
+class StrokeTextView : public SkView {
+ bool fAA;
+public:
+ StrokeTextView() : fAA(false) {}
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "StrokeText");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(0xFF333333);
+ canvas->drawColor(0xFFCC8844);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ SkBitmap bm;
+ SkPaint paint;
+
+ paint.setStrokeWidth(SkIntToScalar(6));
+ paint.setTextSize(SkIntToScalar(80));
+// paint.setTypeface(Typeface.DEFAULT_BOLD);
+
+ lettersToBitmap(&bm, "Test Case", paint, SkBitmap::kARGB_4444_Config);
+
+ canvas->drawBitmap(bm, 0, 0);
+ }
+
+private:
+
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new StrokeTextView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleTests.cpp b/samplecode/SampleTests.cpp
new file mode 100644
index 0000000..d021672
--- /dev/null
+++ b/samplecode/SampleTests.cpp
@@ -0,0 +1,99 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkBlurMaskFilter.h"
+#include "SkCamera.h"
+#include "SkColorFilter.h"
+#include "SkColorPriv.h"
+#include "SkDevice.h"
+#include "SkGradientShader.h"
+#include "SkImageDecoder.h"
+#include "SkInterpolator.h"
+#include "SkMaskFilter.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkShaderExtras.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+#include "SkUtils.h"
+#include "SkKey.h"
+#include "SkPorterDuff.h"
+#include "SkXfermode.h"
+#include "SkDrawFilter.h"
+
+#include "test.h"
+
+class TestsView : public SkView {
+public:
+ skia::Test::Iter fIter;
+
+ TestsView() {}
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Tests");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ skia::Test* test = fIter.next();
+ if (NULL == test) {
+ fIter.reset();
+ test = fIter.next();
+ }
+
+ SkIPoint size;
+ test->getSize(&size);
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.fX, size.fY);
+ bitmap.allocPixels();
+ bitmap.eraseColor(0);
+
+ SkCanvas c(bitmap);
+ test->draw(&c);
+
+ canvas->drawBitmap(bitmap, SkIntToScalar(10), SkIntToScalar(10), NULL);
+
+ SkString str;
+ test->getString(skia::Test::kTitle, &str);
+ SkDebugf("--- %s\n", str.c_str());
+ delete test;
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ this->inval(NULL);
+
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click) {
+ this->inval(NULL);
+ return this->INHERITED::onClick(click);
+ }
+
+ virtual bool handleKey(SkKey key) {
+ this->inval(NULL);
+ return true;
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new TestsView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleText.cpp b/samplecode/SampleText.cpp
new file mode 100644
index 0000000..60e015a
--- /dev/null
+++ b/samplecode/SampleText.cpp
@@ -0,0 +1,791 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "Sk64.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkKernel33MaskFilter.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+#include "SkXfermode.h"
+
+#include "SkStream.h"
+#include "SkXMLParser.h"
+
+static const int gKernel[3][3] = {
+// { -1, -2, -1 }, { -2, 12, -2 }, { -1, -2, -1 }
+ { 1, 2, 1 }, { 2, 64-12, 2 }, { 1, 2, 1 }
+};
+static const int gShift = 6;
+
+class ReduceNoise : public SkKernel33ProcMaskFilter {
+public:
+ ReduceNoise(int percent256) : SkKernel33ProcMaskFilter(percent256) {}
+ virtual uint8_t computeValue(uint8_t* const* srcRows)
+ {
+ int c = srcRows[1][1];
+ int min = 255, max = 0;
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ if (i != 1 || j != 1)
+ {
+ int v = srcRows[i][j];
+ if (max < v)
+ max = v;
+ if (min > v)
+ min = v;
+ }
+ if (c > max) c = max;
+ // if (c < min) c = min;
+ return c;
+ }
+ virtual Factory getFactory() { return Create; }
+private:
+ ReduceNoise(SkFlattenableReadBuffer& rb) : SkKernel33ProcMaskFilter(rb) {}
+ static SkFlattenable* Create(SkFlattenableReadBuffer& rb)
+ {
+ return new ReduceNoise(rb);
+ }
+};
+
+class Darken : public SkKernel33ProcMaskFilter {
+public:
+ Darken(int percent256) : SkKernel33ProcMaskFilter(percent256) {}
+ virtual uint8_t computeValue(uint8_t* const* srcRows)
+ {
+ int c = srcRows[1][1];
+ float f = c / 255.f;
+
+ if (c >= 0)
+ {
+ f = sqrtf(f);
+ }
+ else
+ {
+ f *= f;
+ }
+ SkASSERT(f >= 0 && f <= 1);
+ return (int)(f * 255);
+ }
+ virtual Factory getFactory() { return Create; }
+private:
+ Darken(SkFlattenableReadBuffer& rb) : SkKernel33ProcMaskFilter(rb) {}
+ static SkFlattenable* Create(SkFlattenableReadBuffer& rb)
+ {
+ return new Darken(rb);
+ }
+};
+
+static SkMaskFilter* makemf() { return new Darken(0x30); }
+
+//#ifdef TEST_CLICKX
+
+static void test_typefaceCache()
+{
+ SkTypeface* t0 = SkTypeface::Create("sans-serif", SkTypeface::kNormal);
+ SkTypeface* t1 = SkTypeface::Create(NULL, SkTypeface::kNormal);
+ SkTypeface* t2 = SkTypeface::Create("arial", SkTypeface::kNormal);
+ SkTypeface* t3 = SkTypeface::Create("helvetica", SkTypeface::kItalic);
+
+#ifndef SK_BUILD_FOR_MAC
+ SkASSERT(t0 == t1);
+ SkASSERT(t0 == t2);
+ SkASSERT(t0 == t3);
+#endif
+}
+
+static void test_breakText()
+{
+ SkPaint paint;
+ const char* text = "sdfkljAKLDFJKEWkldfjlk#$%&sdfs.dsj";
+ size_t length = strlen(text);
+ SkScalar width = paint.measureText(text, length);
+
+ SkScalar mm = 0;
+ SkScalar nn = 0;
+ for (SkScalar w = 0; w <= width; w += SK_Scalar1)
+ {
+ SkScalar m;
+ size_t n = paint.breakText(text, length, w, &m,
+ SkPaint::kBackward_TextBufferDirection);
+
+ SkASSERT(n <= length);
+ SkASSERT(m <= width);
+
+ if (n == 0)
+ SkASSERT(m == 0);
+ else
+ {
+ // now assert that we're monotonic
+ if (n == nn)
+ SkASSERT(m == mm);
+ else
+ {
+ SkASSERT(n > nn);
+ SkASSERT(m > mm);
+ }
+ }
+ nn = n;
+ mm = m;
+ }
+
+ nn = paint.breakText(text, length, width, &mm);
+ SkASSERT(nn == length);
+ SkASSERT(mm == width);
+}
+
+static SkRandom gRand;
+
+class SkPowerMode : public SkXfermode {
+public:
+ SkPowerMode(SkScalar exponent) { this->init(exponent); }
+
+ virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, const SkAlpha aa[]);
+
+ typedef SkFlattenable* (*Factory)(SkFlattenableReadBuffer&);
+
+ // overrides for SkFlattenable
+ virtual Factory getFactory() { return Create; }
+ virtual void flatten(SkFlattenableWriteBuffer& b)
+ {
+ // this->INHERITED::flatten(b); How can we know if this is legal????
+ b.write32(SkScalarToFixed(fExp));
+ }
+
+private:
+ SkScalar fExp; // user's value
+ uint8_t fTable[256]; // cache
+
+ void init(SkScalar exponent);
+ SkPowerMode(SkFlattenableReadBuffer& b) : SkXfermode(b)
+ {
+ // read the exponent
+ this->init(SkFixedToScalar(b.readS32()));
+ }
+ static SkFlattenable* Create(SkFlattenableReadBuffer& b)
+ {
+ return SkNEW_ARGS(SkPowerMode, (b));
+ }
+
+ typedef SkXfermode INHERITED;
+};
+
+void SkPowerMode::init(SkScalar e)
+{
+ fExp = e;
+ float ee = SkScalarToFloat(e);
+
+ printf("------ %g\n", ee);
+ for (int i = 0; i < 256; i++)
+ {
+ float x = i / 255.f;
+ // printf(" %d %g", i, x);
+ x = powf(x, ee);
+ // printf(" %g", x);
+ int xx = SkScalarRound(SkFloatToScalar(x * 255));
+ // printf(" %d\n", xx);
+ fTable[i] = SkToU8(xx);
+ }
+}
+
+void SkPowerMode::xfer16(uint16_t dst[], const SkPMColor src[], int count, const SkAlpha aa[])
+{
+ for (int i = 0; i < count; i++)
+ {
+ SkPMColor c = src[i];
+ int r = SkGetPackedR32(c);
+ int g = SkGetPackedG32(c);
+ int b = SkGetPackedB32(c);
+ r = fTable[r];
+ g = fTable[g];
+ b = fTable[b];
+ dst[i] = SkPack888ToRGB16(r, g, b);
+ }
+}
+
+static const struct {
+ const char* fName;
+ uint32_t fFlags;
+ bool fFlushCache;
+} gHints[] = {
+ { "Linear", SkPaint::kLinearText_Flag, false },
+ { "Normal", 0, true },
+ { "Subpixel", SkPaint::kSubpixelText_Flag, true }
+};
+
+#ifdef SK_DEBUG
+ #define REPEAT_COUNT 1
+#else
+ #define REPEAT_COUNT 5000
+#endif
+
+static int count_char_points(const SkPaint& paint, char c)
+{
+ SkPath path;
+
+ paint.getTextPath(&c, 1, 0, 0, &path);
+ return path.getPoints(NULL, 0);
+}
+
+static int gOld, gNew, gCount;
+
+static void dump(int c, int oldc, int newc)
+{
+ if (oldc != newc)
+ {
+ gOld += oldc;
+ gNew += newc;
+ gCount += 1;
+ printf("char %c: old = %3d, new = %3d, reduction %g%%\n", c, oldc, newc, 100. * (oldc - newc) / oldc);
+ }
+}
+
+static void tab(int n)
+{
+// printf("[%d] ", n); return;
+ SkASSERT(n >= 0);
+ for (int i = 0; i < n; i++)
+ printf(" ");
+}
+
+#if 0
+#include "badrects.cpp"
+
+static void make_badrgn(SkRegion* rgn, int insetAmount)
+{
+ SkRect16 r, bounds;
+ int i;
+
+ rgn->setEmpty();
+ bounds.setEmpty();
+
+ for (i = 0; i < SK_ARRAY_COUNT(badrects); i++)
+ {
+ SkASSERT(badrects[i].width > 0 && badrects[i].height > 0);
+
+ r.set(badrects[i].x, badrects[i].y, badrects[i].x + badrects[i].width, badrects[i].y + badrects[i].height);
+ r.inset(insetAmount, insetAmount);
+ rgn->op(r, SkRegion::kUnion_Op);
+ bounds.join(r);
+ }
+ SkASSERT(bounds == rgn->getBounds());
+
+ for (i = 0; i < SK_ARRAY_COUNT(badrects); i++)
+ {
+ r.set(badrects[i].x, badrects[i].y, badrects[i].x + badrects[i].width, badrects[i].y + badrects[i].height);
+ SkASSERT(rgn->contains(r));
+ }
+}
+#endif
+
+static void draw_rgn(const SkRegion& rgn, SkCanvas* canvas, const SkPaint& paint)
+{
+ SkRect r;
+ SkRegion::Iterator iter(rgn);
+
+ for (; !iter.done(); iter.next())
+ {
+ r.set(iter.rect());
+ canvas->drawRect(r, paint);
+ }
+}
+
+static void test_break(SkCanvas* canvas, const char text[], size_t length,
+ SkScalar x, SkScalar y, const SkPaint& paint,
+ SkScalar clickX)
+{
+ SkPaint linePaint;
+
+ linePaint.setAntiAlias(true);
+
+ SkScalar measured;
+
+ if (paint.breakText(text, length, clickX - x, &measured, SkPaint::kForward_TextBufferDirection))
+ {
+ linePaint.setColor(SK_ColorRED);
+ canvas->drawLine(x, y, x + measured, y, linePaint);
+ }
+
+ x += paint.measureText(text, length);
+ if (paint.breakText(text, length, x - clickX, &measured, SkPaint::kBackward_TextBufferDirection))
+ {
+ linePaint.setColor(SK_ColorBLUE);
+ canvas->drawLine(x - measured, y, x, y, linePaint);
+ }
+}
+
+static void test_poly()
+{
+ static const SkPoint dst[] = {
+ SkIntToScalar(2), SkIntToScalar(1),
+ SkIntToScalar(5), SkIntToScalar(1),
+ SkIntToScalar(5), SkIntToScalar(3),
+ SkIntToScalar(2), SkIntToScalar(3)
+ };
+
+ static const SkPoint src[] = {
+ SkIntToScalar(0), SkIntToScalar(0),
+ SkIntToScalar(1), SkIntToScalar(0),
+ SkIntToScalar(1), SkIntToScalar(1),
+ SkIntToScalar(0), SkIntToScalar(1)
+ };
+
+ SkMatrix matrix;
+
+ if (matrix.setPolyToPoly(src, dst, 4))
+ {
+ SkPoint pt = { SK_Scalar1/2, SK_Scalar1/2 };
+ matrix.mapPoints(&pt, 1);
+ printf("---- x = %g y = %g\n", SkScalarToFloat(pt.fX), SkScalarToFloat(pt.fY));
+ }
+ else
+ printf("---- setPolyToPoly failed\n");
+}
+
+#include "SkColorShader.h"
+
+static void DrawTheText(SkCanvas* canvas, const char text[], size_t length,
+ SkScalar x, SkScalar y, const SkPaint& paint,
+ SkScalar clickX, SkMaskFilter* mf)
+{
+ SkPaint p(paint);
+
+#if 0
+ canvas->drawText(text, length, x, y, paint);
+#else
+ {
+ SkPoint pts[1000];
+ SkScalar xpos = x;
+ SkASSERT(length <= SK_ARRAY_COUNT(pts));
+ for (size_t i = 0; i < length; i++)
+ pts[i].set(xpos, y), xpos += paint.getTextSize();
+ canvas->drawPosText(text, length, pts, paint);
+ }
+#endif
+
+ p.setSubpixelText(true);
+ x += SkIntToScalar(180);
+ canvas->drawText(text, length, x, y, p);
+
+#ifdef TEST_CLICKX
+ test_break(canvas, text, length, x, y, p, clickX);
+#endif
+
+#ifdef SK_DEBUG
+ if (false)
+ {
+ SkColorShader shader;
+ p.setShader(&shader);
+ x += SkIntToScalar(180);
+ canvas->drawText(text, length, x, y, p);
+ p.setShader(NULL);
+ }
+
+ if (true)
+ {
+ // p.setMaskFilter(mf);
+ p.setSubpixelText(false);
+ p.setLinearText(true);
+ x += SkIntToScalar(180);
+ canvas->drawText(text, length, x, y, p);
+ }
+#endif
+}
+
+class TextSpeedView : public SkView {
+public:
+ TextSpeedView()
+ {
+ fMF = makemf();
+
+ fHints = 0;
+
+ if (false)
+ {
+ static const char extra[] = { '.', ',', ':', ';', '!' };
+ SkPaint paint, paint2;
+
+ paint2.setTypeface(SkTypeface::Create(NULL, SkTypeface::kItalic))->unref();
+
+ for (int i = 0; i < 26; i++)
+ ::dump('a' + i, count_char_points(paint, 'a' + i), count_char_points(paint2, 'a' + i));
+ for (int j = 0; j < SK_ARRAY_COUNT(extra); j++)
+ ::dump(extra[j], count_char_points(paint, extra[j]), count_char_points(paint2, extra[j]));
+
+ printf("--- ave reduction = %g%%\n", 100. * (gOld - gNew) / gOld);
+ }
+
+ if (true)
+ {
+ SkPoint pts[] = { SkIntToScalar(20), 0, SkIntToScalar(256+20), 0 };
+ SkColor colors[] = { SkColorSetARGB(0, 255, 255, 255), SkColorSetARGB(255, 255, 255, 255) };
+ fGradient = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode);
+ }
+
+ fClickX = 0;
+
+ test_breakText();
+ test_typefaceCache();
+ test_poly();
+ }
+
+ virtual ~TextSpeedView()
+ {
+ fGradient->unref();
+ fMF->safeUnref();
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Text");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+// canvas->drawColor(0xFFDDDDDD);
+ canvas->drawColor(SK_ColorWHITE);
+ // canvas->drawColor(SK_ColorBLACK);
+ }
+
+ static void make_textstrip(SkBitmap* bm)
+ {
+ bm->setConfig(SkBitmap::kRGB_565_Config, 200, 18);
+ bm->allocPixels();
+ bm->eraseColor(SK_ColorWHITE);
+
+ SkCanvas canvas(*bm);
+ SkPaint paint;
+ const char* s = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit";
+
+ paint.setFlags(paint.getFlags() | SkPaint::kAntiAlias_Flag
+ | SkPaint::kDevKernText_Flag);
+ paint.setTextSize(SkIntToScalar(14));
+ canvas.drawText(s, strlen(s), SkIntToScalar(8), SkIntToScalar(14), paint);
+ }
+
+ static void fill_pts(SkPoint pts[], size_t n, SkRandom* rand)
+ {
+ for (size_t i = 0; i < n; i++)
+ pts[i].set(rand->nextUScalar1() * 640, rand->nextUScalar1() * 480);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ if (false)
+ {
+ canvas->translate(SkIntToScalar(480), 0);
+ canvas->rotate(SkIntToScalar(90));
+ }
+
+ this->drawBG(canvas);
+
+ if (false)
+ {
+ SkPaint p;
+
+ p.setAntiAlias(true);
+ p.setSubpixelText(true);
+ // p.setLinearText(true);
+
+ SkScalar size = SkIntToScalar(6);
+ SkMSec dur = 0;
+ const int LOOP = 16;
+ const int TIMES = 10;
+
+ for (int times = 0; times < TIMES; times++)
+ {
+ SkMSec now = SkTime::GetMSecs();
+ for (int loop = 0; loop < LOOP; loop++)
+ {
+ p.setTextSize(size);
+ size += SK_Scalar1/5;
+ canvas->drawText("Hamburgefons", 12, SkIntToScalar(10), SkIntToScalar(50), p);
+ }
+ dur += SkTime::GetMSecs() - now;
+ SkGraphics::SetFontCacheUsed(0);
+ }
+
+ printf("----- duration = %g\n", dur * 1.0 / TIMES);
+ this->inval(NULL);
+ return;
+ }
+
+ if (false)
+ {
+ SkPaint p;
+ p.setAntiAlias(true);
+ for (int i = 6; i <= 36; i++)
+ {
+ SkRect r;
+ SkPaint::FontMetrics m;
+ p.setTextSize(SkIntToScalar(i));
+ p.getFontMetrics(&m);
+ int ascent = SkScalarRound(m.fAscent);
+ int descent = SkScalarRound(m.fDescent);
+ for (uint8_t c = ' '; c <= 127; c++)
+ {
+ p.getTextWidths(&c, 1, NULL, &r);
+ if (SkScalarRound(r.fTop) < ascent)
+ printf("PS %d --- %c [%d] top=%g, ascent=%g ymax=%g\n", i, c, c,
+ SkScalarToFloat(r.fTop), SkScalarToFloat(m.fAscent), SkScalarToFloat(m.fTop));
+ if (SkScalarRound(r.fBottom) > descent)
+ printf("PS %d --- %c [%d] bottom=%g, descent=%g ymin=%g\n", i, c, c,
+ SkScalarToFloat(r.fBottom), SkScalarToFloat(m.fDescent), SkScalarToFloat(m.fBottom));
+ }
+ }
+ }
+
+ if (false)
+ {
+ SkPaint p;
+ p.setShader(fGradient);
+
+#ifdef SK_RELEASE
+ SkMSec now = SkTime::GetMSecs();
+ for (int i = 0; i < 100; i++)
+#endif
+ canvas->drawPaint(p);
+#ifdef SK_RELEASE
+ printf("----- %d ms\n", SkTime::GetMSecs() - now);
+ this->inval(NULL);
+#endif
+ return;
+ }
+
+ if (false)
+ {
+ SkBitmap bm;
+
+ make_textstrip(&bm);
+ canvas->translate(0, SkIntToScalar(50));
+ for (int i = 0; i < 10; i++)
+ {
+ float gamma = 1 + i * 0.2f;
+ SkPowerMode mode(SkFloatToScalar(1 / gamma));
+ SkPaint p;
+ p.setXfermode(&mode);
+
+ canvas->drawBitmap(bm, 0, SkIntToScalar(i) * bm.height(), &p);
+ }
+ return;
+ }
+
+ if (false)
+ {
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setDevKernText(true);
+ SkMSec now = SkTime::GetMSecs();
+ for (int i = 0; i < 1000000; i++)
+ {
+ paint.measureText("Hamburgefons", 15, NULL, NULL);
+ }
+ printf("--------- measure %d\n", SkTime::GetMSecs() - now);
+ this->inval(NULL);
+ return;
+ }
+
+ if (false)
+ {
+ SkRegion rgn;
+ SkPath path;
+ SkPaint paint;
+
+ // make_badrgn(&rgn, -2);
+
+ if (false)
+ {
+ paint.setColor(SK_ColorBLUE);
+ canvas->drawIRect(rgn.getBounds(), paint);
+ }
+ paint.setColor(SK_ColorRED);
+ draw_rgn(rgn, canvas, paint);
+
+ rgn.getBoundaryPath(&path);
+ paint.setARGB(0x80, 0, 0, 0xFF);
+ canvas->drawPath(path, paint);
+ return;
+ }
+
+ if (false)
+ {
+ SkRect r = { SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(300), SkIntToScalar(300) };
+ SkPaint p;
+
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setAlpha(0x80);
+ p.setStrokeWidth(SkIntToScalar(20));
+ canvas->drawRect(r, p);
+ }
+
+ if (false)
+ {
+ SkPaint p;
+ SkRect r = { SkIntToScalar(100), SkIntToScalar(100), SkIntToScalar(104), SkIntToScalar(104) };
+ // r.offset(SK_ScalarHalf, SK_ScalarHalf);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1*2);
+ // p.setAntiAliasOn(true);
+ canvas->drawRect(r, p);
+ return;
+ }
+
+ if (false)
+ {
+ Sk64 aa, bb;
+ int64_t a = (int64_t)6062080 * -30596;
+ int64_t b = (int64_t)4816896 * 57957;
+ aa.setMul(6062080, -30596);
+ bb.setMul(4816896, 57957);
+
+ a += b;
+ b = a >> 16;
+
+// SkFixed c = aa.addGetFixed(bb);
+
+ printf("%d %d\n", (int)a, a >> 32);
+
+ SkBitmap bm;
+ SkPaint paint;
+ SkScalar scale = SkFloatToScalar(0.5625f);
+ SkScalar x = SkIntToScalar(100);
+ SkScalar y = SkIntToScalar(100);
+
+ //paint.setFilterType(SkPaint::kBilinear_FilterType);
+
+ SkImageDecoder::DecodeFile("/app_web_browser.png", &bm);
+
+ // canvas->drawBitmap(bm, x, y, paint);
+ x += SkIntToScalar(100);
+ canvas->save();
+ canvas->translate(x, y);
+ canvas->scale(SkIntToScalar(2)/1, SkIntToScalar(2)/1);
+ canvas->translate(-x, -y);
+ canvas->drawBitmap(bm, x, y, &paint);
+ canvas->restore();
+ x += SkIntToScalar(100);
+ canvas->save();
+ canvas->translate(x, y);
+ canvas->scale(scale, scale);
+ canvas->translate(-x, -y);
+ // canvas->drawBitmap(bm, x, y, paint);
+ canvas->restore();
+ return;
+ }
+
+ SkAutoCanvasRestore restore(canvas, false);
+ {
+ SkRect r;
+ r.set(0, 0, SkIntToScalar(1000), SkIntToScalar(20));
+ // canvas->saveLayer(&r, NULL, SkCanvas::kHasAlphaLayer_SaveFlag);
+ }
+
+ SkPaint paint;
+// const uint16_t glyphs[] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 };
+ int index = fHints % SK_ARRAY_COUNT(gHints);
+ index = 1;
+// const char* style = gHints[index].fName;
+
+// canvas->translate(0, SkIntToScalar(50));
+
+ // canvas->drawText(style, strlen(style), SkIntToScalar(20), SkIntToScalar(20), paint);
+
+// paint.setTypeface(SkTypeface::Create(NULL, SkTypeface::kItalic))->unref();
+ paint.setAntiAlias(true);
+ paint.setFlags(paint.getFlags() | gHints[index].fFlags);
+
+ SkMSec now = 0;
+ if (REPEAT_COUNT > 1)
+ now = SkTime::GetMSecs();
+
+ SkRect clip;
+ clip.set(SkIntToScalar(25), SkIntToScalar(34), SkIntToScalar(88), SkIntToScalar(155));
+
+ if (0) {
+ canvas->clipRect(clip);
+ }
+
+ if (0) {
+ SkPath clipPath;
+ clipPath.addOval(clip);
+ canvas->clipPath(clipPath);
+ }
+
+ const char* text = "Hamburgefons";
+ size_t length = strlen(text);
+
+#ifdef TEST_CLICKX
+ {
+ SkPaint p;
+
+ p.setColor(SK_ColorGREEN);
+ p.setAntiAlias(true);
+ canvas->drawLine(fClickX, 0, fClickX, SkIntToScalar(1000), p);
+ }
+#endif
+
+ for (int j = 0; j < REPEAT_COUNT; j++)
+ {
+ SkScalar y = SkIntToScalar(0);
+ for (int i = 9; i <= 24; i++) {
+ paint.setTextSize(SkIntToScalar(i) /*+ (gRand.nextU() & 0xFFFF)*/);
+ for (SkScalar dx = 0; dx <= SkIntToScalar(3)/4; dx += SkIntToScalar(1) /* /4 */)
+ {
+ y += paint.getFontSpacing();
+ DrawTheText(canvas, text, length, SkIntToScalar(20) + dx, y, paint, fClickX, fMF);
+ }
+ }
+ if (gHints[index].fFlushCache) {
+ SkGraphics::SetFontCacheUsed(0);
+ }
+ }
+
+ if (REPEAT_COUNT > 1)
+ {
+ printf("--------- FPS = %g\n", REPEAT_COUNT * 1000. / (SkTime::GetMSecs() - now));
+ this->inval(NULL);
+ }
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ fClickX = x;
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ int fHints;
+ SkScalar fClickX;
+ SkMaskFilter* fMF;
+ SkShader* fGradient;
+
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new TextSpeedView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleTextAlpha.cpp b/samplecode/SampleTextAlpha.cpp
new file mode 100644
index 0000000..d695f23
--- /dev/null
+++ b/samplecode/SampleTextAlpha.cpp
@@ -0,0 +1,122 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkBlurMaskFilter.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkPath.h"
+#include "SkPorterDuff.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+
+#include "SkImageRef.h"
+#include "SkOSFile.h"
+#include "SkStream.h"
+
+static void check_for_nonwhite(const SkBitmap& bm, int alpha) {
+ if (bm.config() != SkBitmap::kRGB_565_Config) {
+ return;
+ }
+
+ for (int y = 0; y < bm.height(); y++) {
+ for (int x = 0; x < bm.width(); x++) {
+ uint16_t c = *bm.getAddr16(x, y);
+ if (c != 0xFFFF) {
+ SkDebugf("------ nonwhite alpha=%x [%d %d] %x\n", alpha, x, y, c);
+ return;
+ }
+ }
+ }
+}
+
+class TextAlphaView : public SkView {
+public:
+ TextAlphaView() {
+ fByte = 0xFF;
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SkString str("TextAlpha");
+ SampleCode::TitleR(evt, str.c_str());
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ const char* str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ SkPaint paint;
+ SkScalar x = SkIntToScalar(10);
+ SkScalar y = SkIntToScalar(20);
+
+ paint.setFlags(0x105);
+
+ paint.setARGB(fByte, 0xFF, 0xFF, 0xFF);
+
+ paint.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
+ SkBlurMaskFilter::kNormal_BlurStyle));
+ paint.getMaskFilter()->unref();
+
+ SkRandom rand;
+
+ for (int ps = 6; ps <= 35; ps++) {
+ paint.setColor(rand.nextU() | (0xFF << 24));
+ paint.setTextSize(SkIntToScalar(ps));
+ paint.setTextSize(SkIntToScalar(24));
+ canvas->drawText(str, strlen(str), x, y, paint);
+ y += paint.getFontMetrics(NULL);
+ }
+ //check_for_nonwhite(canvas->getDevice()->accessBitmap(), fByte);
+ //SkDebugf("------ byte %x\n", fByte);
+
+ if (false) {
+ fByte += 1;
+ fByte &= 0xFF;
+ this->inval(NULL);
+ }
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ return new Click(this);
+ }
+
+ virtual bool onClick(Click* click) {
+ int y = click->fICurr.fY;
+ if (y < 0) {
+ y = 0;
+ } else if (y > 255) {
+ y = 255;
+ }
+ fByte = y;
+ this->inval(NULL);
+ return true;
+ }
+
+private:
+ int fByte;
+
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new TextAlphaView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleTextEffects.cpp b/samplecode/SampleTextEffects.cpp
new file mode 100644
index 0000000..2293a04
--- /dev/null
+++ b/samplecode/SampleTextEffects.cpp
@@ -0,0 +1,466 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTypeface.h"
+#include "SkAvoidXfermode.h"
+
+static inline SkPMColor rgb2gray(SkPMColor c)
+{
+ unsigned r = SkGetPackedR32(c);
+ unsigned g = SkGetPackedG32(c);
+ unsigned b = SkGetPackedB32(c);
+
+ unsigned x = r * 5 + g * 7 + b * 4 >> 4;
+
+ return SkPackARGB32(0, x, x, x) | (c & (SK_A32_MASK << SK_A32_SHIFT));
+}
+
+class SkGrayScaleColorFilter : public SkColorFilter {
+public:
+ virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[])
+ {
+ for (int i = 0; i < count; i++)
+ result[i] = rgb2gray(src[i]);
+ }
+};
+
+class SkChannelMaskColorFilter : public SkColorFilter {
+public:
+ SkChannelMaskColorFilter(U8CPU redMask, U8CPU greenMask, U8CPU blueMask)
+ {
+ fMask = SkPackARGB32(0xFF, redMask, greenMask, blueMask);
+ }
+
+ virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[])
+ {
+ SkPMColor mask = fMask;
+ for (int i = 0; i < count; i++)
+ result[i] = src[i] & mask;
+ }
+
+private:
+ SkPMColor fMask;
+};
+
+///////////////////////////////////////////////////////////
+
+#include "SkGradientShader.h"
+#include "SkLayerRasterizer.h"
+#include "SkBlurMaskFilter.h"
+
+static void r0(SkLayerRasterizer* rast, SkPaint& p)
+{
+ p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
+ SkBlurMaskFilter::kNormal_BlurStyle))->unref();
+ rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
+
+ p.setMaskFilter(NULL);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1);
+ rast->addLayer(p);
+
+ p.setAlpha(0x11);
+ p.setStyle(SkPaint::kFill_Style);
+ p.setPorterDuffXfermode(SkPorterDuff::kSrc_Mode);
+ rast->addLayer(p);
+}
+
+static void r1(SkLayerRasterizer* rast, SkPaint& p)
+{
+ rast->addLayer(p);
+
+ p.setAlpha(0x40);
+ p.setPorterDuffXfermode(SkPorterDuff::kSrc_Mode);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1*2);
+ rast->addLayer(p);
+}
+
+static void r2(SkLayerRasterizer* rast, SkPaint& p)
+{
+ p.setStyle(SkPaint::kStrokeAndFill_Style);
+ p.setStrokeWidth(SK_Scalar1*4);
+ rast->addLayer(p);
+
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1*3/2);
+ p.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ rast->addLayer(p);
+}
+
+static void r3(SkLayerRasterizer* rast, SkPaint& p)
+{
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1*3);
+ rast->addLayer(p);
+
+ p.setAlpha(0x20);
+ p.setStyle(SkPaint::kFill_Style);
+ p.setPorterDuffXfermode(SkPorterDuff::kSrc_Mode);
+ rast->addLayer(p);
+}
+
+static void r4(SkLayerRasterizer* rast, SkPaint& p)
+{
+ p.setAlpha(0x60);
+ rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
+
+ p.setAlpha(0xFF);
+ p.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
+
+ p.setXfermode(NULL);
+ rast->addLayer(p);
+}
+
+#include "SkDiscretePathEffect.h"
+
+static void r5(SkLayerRasterizer* rast, SkPaint& p)
+{
+ rast->addLayer(p);
+
+ p.setPathEffect(new SkDiscretePathEffect(SK_Scalar1*4, SK_Scalar1*3))->unref();
+ p.setPorterDuffXfermode(SkPorterDuff::kSrcOut_Mode);
+ rast->addLayer(p);
+}
+
+static void r6(SkLayerRasterizer* rast, SkPaint& p)
+{
+ rast->addLayer(p);
+
+ p.setAntiAlias(false);
+ SkLayerRasterizer* rast2 = new SkLayerRasterizer;
+ r5(rast2, p);
+ p.setRasterizer(rast2)->unref();
+ p.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ rast->addLayer(p);
+}
+
+#include "Sk2DPathEffect.h"
+
+class Dot2DPathEffect : public Sk2DPathEffect {
+public:
+ Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix)
+ : Sk2DPathEffect(matrix), fRadius(radius) {}
+
+ virtual void flatten(SkFlattenableWriteBuffer& buffer)
+ {
+ this->INHERITED::flatten(buffer);
+
+ buffer.writeScalar(fRadius);
+ }
+ virtual Factory getFactory() { return CreateProc; }
+
+protected:
+ virtual void next(const SkPoint& loc, int u, int v, SkPath* dst)
+ {
+ dst->addCircle(loc.fX, loc.fY, fRadius);
+ }
+
+ Dot2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer)
+ {
+ fRadius = buffer.readScalar();
+ }
+private:
+ SkScalar fRadius;
+
+ static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer)
+ {
+ return new Dot2DPathEffect(buffer);
+ }
+
+ typedef Sk2DPathEffect INHERITED;
+};
+
+static void r7(SkLayerRasterizer* rast, SkPaint& p)
+{
+ SkMatrix lattice;
+ lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
+ lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
+ p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*4, lattice))->unref();
+ rast->addLayer(p);
+}
+
+static void r8(SkLayerRasterizer* rast, SkPaint& p)
+{
+ rast->addLayer(p);
+
+ SkMatrix lattice;
+ lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
+ lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
+ p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*2, lattice))->unref();
+ p.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ rast->addLayer(p);
+
+ p.setPathEffect(NULL);
+ p.setXfermode(NULL);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1);
+ rast->addLayer(p);
+}
+
+class Line2DPathEffect : public Sk2DPathEffect {
+public:
+ Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
+ : Sk2DPathEffect(matrix), fWidth(width) {}
+
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width)
+ {
+ if (this->INHERITED::filterPath(dst, src, width))
+ {
+ *width = fWidth;
+ return true;
+ }
+ return false;
+ }
+
+ virtual Factory getFactory() { return CreateProc; }
+ virtual void flatten(SkFlattenableWriteBuffer& buffer)
+ {
+ this->INHERITED::flatten(buffer);
+ buffer.writeScalar(fWidth);
+ }
+protected:
+ virtual void nextSpan(int u, int v, int ucount, SkPath* dst)
+ {
+ if (ucount > 1)
+ {
+ SkPoint src[2], dstP[2];
+
+ src[0].set(SkIntToScalar(u) + SK_ScalarHalf,
+ SkIntToScalar(v) + SK_ScalarHalf);
+ src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf,
+ SkIntToScalar(v) + SK_ScalarHalf);
+ this->getMatrix().mapPoints(dstP, src, 2);
+
+ dst->moveTo(dstP[0]);
+ dst->lineTo(dstP[1]);
+ }
+ }
+
+ Line2DPathEffect::Line2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer)
+ {
+ fWidth = buffer.readScalar();
+ }
+
+private:
+ SkScalar fWidth;
+
+ static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer)
+ {
+ return new Line2DPathEffect(buffer);
+ }
+
+ typedef Sk2DPathEffect INHERITED;
+};
+
+static void r9(SkLayerRasterizer* rast, SkPaint& p)
+{
+ rast->addLayer(p);
+
+ SkMatrix lattice;
+ lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
+ lattice.postRotate(SkIntToScalar(30), 0, 0);
+ p.setPathEffect(new Line2DPathEffect(SK_Scalar1*2, lattice))->unref();
+ p.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ rast->addLayer(p);
+
+ p.setPathEffect(NULL);
+ p.setXfermode(NULL);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SK_Scalar1);
+ rast->addLayer(p);
+}
+
+typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
+
+static const raster_proc gRastProcs[] = {
+ r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
+};
+
+static const struct {
+ SkColor fMul, fAdd;
+} gLightingColors[] = {
+ { 0x808080, 0x800000 }, // general case
+ { 0x707070, 0x707070 }, // no-pin case
+ { 0xFFFFFF, 0x800000 }, // just-add case
+ { 0x808080, 0x000000 }, // just-mul case
+ { 0xFFFFFF, 0x000000 } // identity case
+};
+
+#include "SkXfermode.h"
+
+static unsigned color_dist16(uint16_t a, uint16_t b)
+{
+ unsigned dr = SkAbs32(SkPacked16ToR32(a) - SkPacked16ToR32(b));
+ unsigned dg = SkAbs32(SkPacked16ToG32(a) - SkPacked16ToG32(b));
+ unsigned db = SkAbs32(SkPacked16ToB32(a) - SkPacked16ToB32(b));
+
+ return SkMax32(dr, SkMax32(dg, db));
+}
+
+static unsigned scale_dist(unsigned dist, unsigned scale)
+{
+ dist >>= 6;
+ dist = (dist << 2) | dist;
+ dist = (dist << 4) | dist;
+ return dist;
+
+// return SkAlphaMul(dist, scale);
+}
+
+static void apply_shader(SkPaint* paint, int index)
+{
+ raster_proc proc = gRastProcs[index];
+ if (proc)
+ {
+ SkPaint p;
+ SkLayerRasterizer* rast = new SkLayerRasterizer;
+
+ p.setAntiAlias(true);
+ proc(rast, p);
+ paint->setRasterizer(rast)->unref();
+ }
+
+#if 0
+ SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
+ paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir, SK_Scalar1/4, SkIntToScalar(4), SkIntToScalar(3)))->unref();
+#endif
+ paint->setColor(SK_ColorBLUE);
+}
+
+static int gRastIndex;
+
+class TextEffectView : public SkView {
+ SkTypeface* fFace;
+public:
+ TextEffectView()
+ {
+ fFace = SkTypeface::CreateFromFile("/Users/reed/Downloads/p052024l.pfb");
+ }
+
+ virtual ~TextEffectView()
+ {
+ fFace->safeUnref();
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt)
+ {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SampleCode::TitleR(evt, "Text Effects");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas)
+ {
+// canvas->drawColor(0xFFDDDDDD);
+ canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas)
+ {
+ this->drawBG(canvas);
+
+ canvas->save();
+// canvas->scale(SK_Scalar1*2, SK_Scalar1*2, 0, 0);
+
+ SkScalar x = SkIntToScalar(20);
+ SkScalar y = SkIntToScalar(40);
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setTextSize(SkIntToScalar(48));
+ paint.setTypeface(SkTypeface::Create("sans-serif", SkTypeface::kBold));
+
+ SkString str("GOOGLE ");
+ str.appendUnichar(0x5700);
+
+ paint.setTypeface(fFace);
+
+ for (int i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++)
+ {
+ apply_shader(&paint, i);
+
+ // paint.setMaskFilter(NULL);
+ // paint.setColor(SK_ColorBLACK);
+
+#if 0
+ int index = i % SK_ARRAY_COUNT(gLightingColors);
+ paint.setColorFilter(SkColorFilter::CreateLightingFilter(
+ gLightingColors[index].fMul,
+ gLightingColors[index].fAdd))->unref();
+#endif
+
+ canvas->drawText(str.c_str(), str.size(), x, y, paint);
+
+ if (0)
+ {
+ SkPath path;
+ paint.getTextPath(str.c_str(), str.size(), x + SkIntToScalar(260), y, &path);
+ canvas->drawPath(path, paint);
+ }
+
+ y += paint.getFontSpacing();
+ }
+
+ canvas->restore();
+
+ if (0)
+ {
+ SkPoint pts[] = { 0, 0, 0, SkIntToScalar(150) };
+ SkColor colors[] = { 0xFFE6E6E6, 0xFFFFFFFF };
+ SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode);
+
+ paint.reset();
+ paint.setShader(s);
+ canvas->drawRectCoords(0, 0, SkIntToScalar(120), SkIntToScalar(150), paint);
+ }
+
+ if (1)
+ {
+ SkAvoidXfermode mode(SK_ColorWHITE, 0xFF,
+ SkAvoidXfermode::kTargetColor_Mode);
+ SkPaint paint;
+ x += SkIntToScalar(20);
+ SkRect r = { x, 0, x + SkIntToScalar(360), SkIntToScalar(700) };
+ paint.setXfermode(&mode);
+ paint.setColor(SK_ColorGREEN);
+ paint.setAntiAlias(true);
+ canvas->drawOval(r, paint);
+ }
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
+ {
+ gRastIndex = (gRastIndex + 1) % SK_ARRAY_COUNT(gRastProcs);
+ this->inval(NULL);
+
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click)
+ {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new TextEffectView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleTextOnPath.cpp b/samplecode/SampleTextOnPath.cpp
new file mode 100644
index 0000000..97b4e8e
--- /dev/null
+++ b/samplecode/SampleTextOnPath.cpp
@@ -0,0 +1,442 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkPackBits.h"
+#include "SkPath.h"
+#include "SkPathMeasure.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTypeface.h"
+#include "SkAvoidXfermode.h"
+
+#define REPEAT_COUNT 1
+
+static const char gText[] = "Hamburgefons";
+
+static bool gDevKern;
+
+static void rand_text(char text[], SkRandom& rand, size_t count) {
+ for (size_t i = 0; i < count; i++) {
+ text[i] = rand.nextU() & 0x7F;
+ }
+}
+
+static SkScalar sum_widths(const SkScalar widths[], int count) {
+ SkScalar w = 0;
+ for (int i = 0; i < count; i++) {
+ w += widths[i];
+ }
+ return w;
+}
+
+static void test_measure(const SkPaint& paint) {
+ char text[256];
+ SkScalar widths[256];
+ SkRect rects[256];
+ SkRect bounds;
+ int count = 256;
+
+ SkRandom rand;
+
+ for (int i = 0; i < 100; i++) {
+ rand_text(text, rand, 256);
+ paint.getTextWidths(text, count, widths, NULL);
+ SkScalar tw0 = sum_widths(widths, count);
+ paint.getTextWidths(text, count, widths, rects);
+ SkScalar tw1 = sum_widths(widths, count);
+ SkASSERT(tw0 == tw1);
+
+ SkScalar w0 = paint.measureText(text, count, NULL);
+ SkScalar w1 = paint.measureText(text, count, &bounds);
+ SkASSERT(w0 == w1);
+ SkASSERT(w0 == tw0);
+
+ SkRect r = rects[0];
+ SkScalar x = 0;
+ for (int j = 1; j < count; j++) {
+ x += widths[j-1];
+ rects[j].offset(x, 0);
+ r.join(rects[j]);
+ }
+ SkASSERT(r == bounds);
+
+ if (r != bounds) {
+ printf("flags=%x i=%d [%g %g %g %g] [%g %g %g %g]\n",
+ paint.getFlags(), i,
+ SkScalarToFloat(r.fLeft),
+ SkScalarToFloat(r.fTop),
+ SkScalarToFloat(r.fRight),
+ SkScalarToFloat(r.fBottom),
+ SkScalarToFloat(bounds.fLeft),
+ SkScalarToFloat(bounds.fTop),
+ SkScalarToFloat(bounds.fRight),
+ SkScalarToFloat(bounds.fBottom));
+ }
+ }
+}
+
+static void test_measure() {
+ SkPaint paint;
+
+ for (int i = 0; i <= SkPaint::kAllFlags; i++) {
+ paint.setFlags(i);
+ test_measure(paint);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void test_textBounds(SkCanvas* canvas) {
+// canvas->scale(SK_Scalar1/2, SK_Scalar1/2);
+
+// canvas->rotate(SkIntToScalar(30));
+
+ gDevKern = !gDevKern;
+
+ SkScalar x = SkIntToScalar(50);
+ SkScalar y = SkIntToScalar(150);
+ SkScalar w[100];
+ SkRect r[100], bounds;
+
+ SkPaint paint;
+ paint.setTextSize(SkIntToScalar(64));
+ paint.setAntiAlias(true);
+ paint.setDevKernText(gDevKern);
+
+ (void)paint.measureText(gText, strlen(gText), &bounds, NULL);
+ paint.setColor(SK_ColorGREEN);
+ bounds.offset(x, y);
+ canvas->drawRect(bounds, paint);
+
+ int count = paint.getTextWidths(gText, strlen(gText), w, r);
+
+ paint.setColor(SK_ColorRED);
+ for (int i = 0; i < count; i++) {
+ r[i].offset(x, y);
+ canvas->drawRect(r[i], paint);
+ x += w[i];
+ }
+ x = SkIntToScalar(50);
+ paint.setColor(gDevKern ? SK_ColorDKGRAY : SK_ColorBLACK);
+ canvas->drawText(gText, strlen(gText), x, y, paint);
+}
+
+static void create_src(SkBitmap* bitmap, SkBitmap::Config config) {
+ bitmap->setConfig(config, 100, 100);
+ bitmap->allocPixels();
+ bitmap->eraseColor(0);
+
+ SkCanvas canvas(*bitmap);
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ canvas.drawCircle(SkIntToScalar(50), SkIntToScalar(50),
+ SkIntToScalar(50), paint);
+}
+
+static void blur(SkBitmap* dst, const SkBitmap& src, SkScalar radius) {
+ *dst = src;
+}
+
+static void test_bitmap_blur(SkCanvas* canvas) {
+ SkBitmap src, dst;
+
+ create_src(&src, SkBitmap::kARGB_8888_Config);
+ blur(&dst, src, SkIntToScalar(4));
+
+ SkPaint paint;
+
+ paint.setColor(SK_ColorRED);
+
+ canvas->drawBitmap(dst, SkIntToScalar(30), SkIntToScalar(60), &paint);
+}
+
+static SkScalar getpathlen(const SkPath& path) {
+ SkPathMeasure meas(path, false);
+ return meas.getLength();
+}
+
+static void test_textpathmatrix(SkCanvas* canvas) {
+ SkPaint paint;
+ SkPath path;
+ SkMatrix matrix;
+
+ path.moveTo(SkIntToScalar(200), SkIntToScalar(300));
+ path.quadTo(SkIntToScalar(400), SkIntToScalar(100),
+ SkIntToScalar(600), SkIntToScalar(300));
+
+ paint.setAntiAlias(true);
+
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawPath(path, paint);
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setTextSize(SkIntToScalar(48));
+ paint.setTextAlign(SkPaint::kRight_Align);
+
+ const char* text = "Android";
+ size_t len = strlen(text);
+ SkScalar pathLen = getpathlen(path);
+
+ canvas->drawTextOnPath(text, len, path, NULL, paint);
+
+ paint.setColor(SK_ColorRED);
+ matrix.setScale(-SK_Scalar1, SK_Scalar1);
+ matrix.postTranslate(pathLen, 0);
+ canvas->drawTextOnPath(text, len, path, &matrix, paint);
+
+ paint.setColor(SK_ColorBLUE);
+ matrix.setScale(SK_Scalar1, -SK_Scalar1);
+ canvas->drawTextOnPath(text, len, path, &matrix, paint);
+
+ paint.setColor(SK_ColorGREEN);
+ matrix.setScale(-SK_Scalar1, -SK_Scalar1);
+ matrix.postTranslate(pathLen, 0);
+ canvas->drawTextOnPath(text, len, path, &matrix, paint);
+}
+
+class TextOnPathView : public SkView {
+public:
+ SkPath fPath;
+ SkScalar fHOffset;
+
+ TextOnPathView() {
+ SkRect r;
+ r.set(SkIntToScalar(100), SkIntToScalar(100),
+ SkIntToScalar(300), SkIntToScalar(300));
+ fPath.addOval(r);
+
+ fHOffset = SkIntToScalar(50);
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Text On Path");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorWHITE);
+#if 0
+ SkRect r;
+ SkPaint p;
+ SkRandom rand;
+ p.setAntiAlias(true);
+
+ for (int i = 0; i < 100; i++) {
+ SkScalar x = rand.nextUScalar1() * 300 + SkIntToScalar(50);
+ SkScalar y = rand.nextUScalar1() * 200 + SkIntToScalar(50);
+ SkScalar w = rand.nextUScalar1() * 10;
+ SkScalar h = rand.nextUScalar1() * 10;
+ r.set(x, y, x + w, y + h);
+ canvas->drawRect(r, p);
+ }
+
+ test_textBounds(canvas);
+// return;
+
+ SkBitmap bm;
+ if (SkImageDecoder::DecodeFile("/loading_tile.png",
+ &bm, SkBitmap::kRGB_565_Config, true))
+ canvas->drawBitmap(bm, 0, 0);
+#endif
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setTextSize(SkIntToScalar(50));
+
+ for (int j = 0; j < REPEAT_COUNT; j++) {
+ SkScalar x = fHOffset;
+
+ paint.setColor(SK_ColorBLACK);
+ canvas->drawTextOnPathHV(gText, sizeof(gText)-1, fPath,
+ x, paint.getTextSize()/2, paint);
+
+ paint.setColor(SK_ColorRED);
+ canvas->drawTextOnPathHV(gText, sizeof(gText)-1, fPath,
+ x + SkIntToScalar(50), 0, paint);
+
+ paint.setColor(SK_ColorBLUE);
+ canvas->drawTextOnPathHV(gText, sizeof(gText)-1, fPath,
+ x + SkIntToScalar(100), -paint.getTextSize()/2, paint);
+ }
+
+ paint.setColor(SK_ColorGREEN);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawPath(fPath, paint);
+
+ canvas->translate(SkIntToScalar(200), 0);
+ test_textpathmatrix(canvas);
+
+ test_bitmap_blur(canvas);
+
+ if (REPEAT_COUNT > 1)
+ this->inval(NULL);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ fHints += 1;
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click) {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ int fHints;
+ typedef SkView INHERITED;
+};
+
+static const uint16_t gTest0[] = { 0, 0, 1, 1 };
+static const uint16_t gTest1[] = { 1, 2, 3, 4, 5, 6 };
+static const uint16_t gTest2[] = { 0, 0, 0, 1, 2, 3, 3, 3 };
+static const uint16_t gTest3[] = { 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 0, 0, 1 };
+
+#include "SkRandom.h"
+static SkRandom gRand;
+static void rand_fill(uint16_t buffer[], int count) {
+ for (int i = 0; i < count; i++)
+ buffer[i] = (uint16_t)gRand.nextU();
+}
+
+static void test_pack16() {
+ static const struct {
+ const uint16_t* fSrc;
+ int fCount;
+ } gTests[] = {
+ { gTest0, SK_ARRAY_COUNT(gTest0) },
+ { gTest1, SK_ARRAY_COUNT(gTest1) },
+ { gTest2, SK_ARRAY_COUNT(gTest2) },
+ { gTest3, SK_ARRAY_COUNT(gTest3) }
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); i++) {
+ uint8_t dst[100];
+ size_t dstSize = SkPackBits::Pack16(gTests[i].fSrc,
+ gTests[i].fCount, dst);
+ printf("Test[%d] orig size = %d, dst size = %d",
+ i, gTests[i].fCount, (int)dstSize);
+ uint16_t src[100];
+ int srcCount = SkPackBits::Unpack16(dst, dstSize, src);
+ printf(", src size = %d", srcCount);
+ bool match = gTests[i].fCount == srcCount && memcmp(gTests[i].fSrc, src,
+ gTests[i].fCount * sizeof(uint16_t)) == 0;
+ printf(", match = %d\n", match);
+ }
+
+ for (int n = 1000; n; n--) {
+ size_t size = 50;
+ uint16_t src[100], src2[100];
+ uint8_t dst[200];
+ rand_fill(src, size);
+
+ size_t dstSize = SkPackBits::Pack16(src, size, dst);
+ size_t maxSize = SkPackBits::ComputeMaxSize16(size);
+ SkASSERT(maxSize >= dstSize);
+
+ int srcCount = SkPackBits::Unpack16(dst, dstSize, src2);
+ SkASSERT(size == srcCount);
+ bool match = memcmp(src, src2, size * sizeof(uint16_t)) == 0;
+ SkASSERT(match);
+ }
+}
+
+static const uint8_t gTest80[] = { 0, 0, 1, 1 };
+static const uint8_t gTest81[] = { 1, 2, 3, 4, 5, 6 };
+static const uint8_t gTest82[] = { 0, 0, 0, 1, 2, 3, 3, 3 };
+static const uint8_t gTest83[] = { 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 0, 0, 1 };
+static const uint8_t gTest84[] = { 1, 0, 3, 0, 0, 0, 2, 1, 1, 2 };
+
+static void rand_fill(uint8_t buffer[], int count) {
+ for (int i = 0; i < count; i++)
+ buffer[i] = (uint8_t)((gRand.nextU() >> 8) & 0x3);
+}
+
+static void test_pack8() {
+ static const struct {
+ const uint8_t* fSrc;
+ int fCount;
+ } gTests[] = {
+ { gTest80, SK_ARRAY_COUNT(gTest80) },
+ { gTest81, SK_ARRAY_COUNT(gTest81) },
+ { gTest82, SK_ARRAY_COUNT(gTest82) },
+ { gTest83, SK_ARRAY_COUNT(gTest83) },
+ { gTest84, SK_ARRAY_COUNT(gTest84) }
+ };
+
+ for (size_t i = 4; i < SK_ARRAY_COUNT(gTests); i++) {
+ uint8_t dst[100];
+ size_t maxSize = SkPackBits::ComputeMaxSize8(gTests[i].fCount);
+ size_t dstSize = SkPackBits::Pack8(gTests[i].fSrc,
+ gTests[i].fCount, dst);
+ SkASSERT(dstSize <= maxSize);
+ printf("Test[%d] orig size = %d, dst size = %d", i,
+ gTests[i].fCount, (int)dstSize);
+ uint8_t src[100];
+ int srcCount = SkPackBits::Unpack8(dst, dstSize, src);
+ printf(", src size = %d", srcCount);
+ bool match = gTests[i].fCount == srcCount &&
+ memcmp(gTests[i].fSrc, src,
+ gTests[i].fCount * sizeof(uint8_t)) == 0;
+ printf(", match = %d\n", match);
+ }
+
+ for (size_t size = 1; size <= 512; size += 1) {
+ for (int n = 200; n; n--) {
+ uint8_t src[600], src2[600];
+ uint8_t dst[600];
+ rand_fill(src, size);
+
+ size_t dstSize = SkPackBits::Pack8(src, size, dst);
+ size_t maxSize = SkPackBits::ComputeMaxSize8(size);
+ SkASSERT(maxSize >= dstSize);
+
+ int srcCount = SkPackBits::Unpack8(dst, dstSize, src2);
+ SkASSERT(size == srcCount);
+ bool match = memcmp(src, src2, size * sizeof(uint8_t)) == 0;
+ SkASSERT(match);
+
+ for (int j = 0; j < 200; j++) {
+ size_t skip = gRand.nextU() % size;
+ size_t write = gRand.nextU() % size;
+ if (skip + write > size) {
+ write = size - skip;
+ }
+ SkPackBits::Unpack8(src, skip, write, dst);
+ bool match = memcmp(src, src2 + skip, write) == 0;
+ SkASSERT(match);
+ }
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() {
+ static bool gOnce;
+ if (!gOnce) {
+// test_pack8();
+ gOnce = true;
+ }
+ return new TextOnPathView;
+}
+
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleTiling.cpp b/samplecode/SampleTiling.cpp
new file mode 100644
index 0000000..759c17c
--- /dev/null
+++ b/samplecode/SampleTiling.cpp
@@ -0,0 +1,170 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTypeface.h"
+
+// effects
+#include "SkGradientShader.h"
+#include "SkUnitMappers.h"
+#include "SkBlurDrawLooper.h"
+
+static void makebm(SkBitmap* bm, SkBitmap::Config config, int w, int h) {
+ bm->setConfig(config, w, h);
+ bm->allocPixels();
+ bm->eraseColor(0);
+
+ SkCanvas canvas(*bm);
+ SkPoint pts[] = { 0, 0, SkIntToScalar(w), SkIntToScalar(h) };
+ SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
+ SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
+ SkPaint paint;
+
+ SkUnitMapper* um = NULL;
+
+ um = new SkCosineMapper;
+// um = new SkDiscreteMapper(12);
+
+ SkAutoUnref au(um);
+
+ paint.setDither(true);
+ paint.setShader(SkGradientShader::CreateLinear(pts, colors, pos,
+ SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode, um))->unref();
+ canvas.drawPaint(paint);
+}
+
+static void setup(SkPaint* paint, const SkBitmap& bm, bool filter,
+ SkShader::TileMode tmx, SkShader::TileMode tmy) {
+ SkShader* shader = SkShader::CreateBitmapShader(bm, tmx, tmy);
+ paint->setShader(shader)->unref();
+ paint->setFilterBitmap(filter);
+}
+
+static const SkBitmap::Config gConfigs[] = {
+ SkBitmap::kARGB_8888_Config,
+ SkBitmap::kRGB_565_Config,
+ SkBitmap::kARGB_4444_Config
+};
+static const int gWidth = 32;
+static const int gHeight = 32;
+
+class TilingView : public SkView {
+ SkBlurDrawLooper fLooper;
+public:
+ TilingView()
+ : fLooper(SkIntToScalar(1), SkIntToScalar(2), SkIntToScalar(2),
+ 0x88000000) {
+ for (int i = 0; i < SK_ARRAY_COUNT(gConfigs); i++) {
+ makebm(&fTexture[i], gConfigs[i], gWidth, gHeight);
+ }
+ }
+
+ SkBitmap fTexture[SK_ARRAY_COUNT(gConfigs)];
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Tiling");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorWHITE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ SkRect r = { 0, 0, SkIntToScalar(gWidth*2), SkIntToScalar(gHeight*2) };
+
+ static const char* gConfigNames[] = { "8888", "565", "4444" };
+
+ static const bool gFilters[] = { false, true };
+ static const char* gFilterNames[] = { "point", "bilinear" };
+
+ static const SkShader::TileMode gModes[] = { SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode };
+ static const char* gModeNames[] = { "C", "R", "M" };
+
+ SkScalar y = SkIntToScalar(24);
+ SkScalar x = SkIntToScalar(10);
+
+ for (int kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
+ for (int ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
+ SkPaint p;
+ SkString str;
+ p.setAntiAlias(true);
+ p.setDither(true);
+ p.setLooper(&fLooper);
+ str.printf("[%s,%s]", gModeNames[kx], gModeNames[ky]);
+
+ p.setTextAlign(SkPaint::kCenter_Align);
+ canvas->drawText(str.c_str(), str.size(), x + r.width()/2, y, p);
+
+ x += r.width() * 4 / 3;
+ }
+ }
+
+ y += SkIntToScalar(16);
+
+ for (int i = 0; i < SK_ARRAY_COUNT(gConfigs); i++) {
+ for (int j = 0; j < SK_ARRAY_COUNT(gFilters); j++) {
+ x = SkIntToScalar(10);
+ for (int kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
+ for (int ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
+ SkPaint paint;
+ setup(&paint, fTexture[i], gFilters[j], gModes[kx], gModes[ky]);
+ paint.setDither(true);
+
+ canvas->save();
+ canvas->translate(x, y);
+ canvas->drawRect(r, paint);
+ canvas->restore();
+
+ x += r.width() * 4 / 3;
+ }
+ }
+ {
+ SkPaint p;
+ SkString str;
+ p.setAntiAlias(true);
+ p.setLooper(&fLooper);
+ str.printf("%s, %s", gConfigNames[i], gFilterNames[j]);
+ canvas->drawText(str.c_str(), str.size(), x, y + r.height() * 2 / 3, p);
+ }
+
+ y += r.height() * 4 / 3;
+ }
+ }
+
+ #ifdef SK_RELEASE
+ this->inval(NULL);
+ #endif
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+
+ virtual bool onClick(Click* click) {
+ return this->INHERITED::onClick(click);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new TilingView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleTypeface.cpp b/samplecode/SampleTypeface.cpp
new file mode 100644
index 0000000..94023b7
--- /dev/null
+++ b/samplecode/SampleTypeface.cpp
@@ -0,0 +1,91 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkTypeface.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "Sk1DPathEffect.h"
+#include "SkCornerPathEffect.h"
+#include "SkPathMeasure.h"
+#include "SkRandom.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkDither.h"
+
+static const struct {
+ const char* fName;
+ SkTypeface::Style fStyle;
+} gFaces[] = {
+ { NULL, SkTypeface::kNormal },
+ { NULL, SkTypeface::kBold },
+ { "serif", SkTypeface::kNormal },
+ { "serif", SkTypeface::kBold },
+ { "serif", SkTypeface::kItalic },
+ { "serif", SkTypeface::kBoldItalic },
+ { "monospace", SkTypeface::kNormal }
+};
+
+static const int gFaceCount = SK_ARRAY_COUNT(gFaces);
+
+class TypefaceView : public SkView {
+ SkTypeface* fFaces[gFaceCount];
+
+public:
+ TypefaceView() {
+ for (int i = 0; i < gFaceCount; i++) {
+ fFaces[i] = SkTypeface::Create(gFaces[i].fName, gFaces[i].fStyle);
+ }
+ }
+
+ virtual ~TypefaceView() {
+ for (int i = 0; i < gFaceCount; i++) {
+ fFaces[i]->safeUnref();
+ }
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Typefaces");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(0xFFDDDDDD);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(SkIntToScalar(30));
+
+ const char* text = "Hamburgefons";
+ const size_t textLen = strlen(text);
+
+ SkScalar x = SkIntToScalar(10);
+ SkScalar dy = paint.getFontMetrics(NULL);
+ SkScalar y = dy;
+
+ for (int i = 0; i < gFaceCount; i++) {
+ paint.setTypeface(fFaces[i]);
+ canvas->drawText(text, textLen, x, y, paint);
+ y += dy;
+ }
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new TypefaceView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleVertices.cpp b/samplecode/SampleVertices.cpp
new file mode 100644
index 0000000..637c661
--- /dev/null
+++ b/samplecode/SampleVertices.cpp
@@ -0,0 +1,278 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkPath.h"
+#include "SkPorterDuff.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+
+#include "SkImageRef.h"
+#include "SkOSFile.h"
+#include "SkStream.h"
+#include "SkNinePatch.h"
+
+void setup_vertexbug(SkPoint verts[], SkPoint texs[], uint16_t index[]);
+
+static void drawbug(SkCanvas* canvas, SkScalar scale) {
+ SkBitmap bm, bm2;
+
+ SkImageDecoder::DecodeFile("/skimages/btn_default_normal.9.png", &bm);
+ SkPaint paint;
+
+ SkIRect subset;
+ subset.set(1, 1, bm.width() - 1, bm.height() - 1);
+ bm.extractSubset(&bm2, subset);
+
+#if 0
+ SkPoint verts[16], texs[16];
+ uint16_t index[54];
+
+ SkShader* s = SkShader::CreateBitmapShader(bm2, SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode);
+ paint.setShader(s)->unref();
+
+ setup_vertexbug(verts, texs, index);
+ int indexCount = 6; // 54
+ canvas->drawVertices(SkCanvas::kTriangles_VertexMode, 16, verts, texs,
+ NULL, NULL, &index[6], indexCount, paint);
+
+#if 0
+ paint.setShader(NULL);
+ canvas->drawVertices(SkCanvas::kTriangles_VertexMode, 16, verts, NULL,
+ NULL, NULL, index, indexCount, paint);
+#endif
+#else
+ SkRect dst;
+ SkIRect margin;
+
+ dst.set(SkIntToScalar(10), SkIntToScalar(10),
+ SkIntToScalar(100) + scale,
+ SkIntToScalar(40) + scale);
+ margin.set(9, 9, 9, 9);
+ SkNinePatch::DrawNine(canvas, dst, bm2, margin, NULL);
+#endif
+}
+
+static SkShader* make_shader0(SkIPoint* size) {
+ SkBitmap bm;
+
+ SkImageDecoder::DecodeFile("/skimages/logo.gif", &bm);
+ size->set(bm.width(), bm.height());
+ return SkShader::CreateBitmapShader(bm, SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode);
+}
+
+static SkShader* make_shader1(const SkIPoint& size) {
+ SkPoint pts[] = { 0, 0, SkIntToScalar(size.fX), SkIntToScalar(size.fY) };
+ SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED };
+ return SkGradientShader::CreateLinear(pts, colors, NULL,
+ SK_ARRAY_COUNT(colors), SkShader::kMirror_TileMode, NULL);
+}
+
+class VerticesView : public SkView {
+ SkShader* fShader0;
+ SkShader* fShader1;
+
+public:
+ VerticesView() {
+ SkIPoint size;
+
+ fShader0 = make_shader0(&size);
+ fShader1 = make_shader1(size);
+
+ make_strip(&fRecs[0], size.fX, size.fY);
+ make_fan(&fRecs[1], size.fX, size.fY);
+ make_tris(&fRecs[2]);
+
+ fScale = SK_Scalar1;
+ }
+
+ virtual ~VerticesView() {
+ fShader0->safeUnref();
+ fShader1->safeUnref();
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt))
+ {
+ SkString str("Vertices");
+ SampleCode::TitleR(evt, str.c_str());
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorGRAY);
+ }
+
+ SkScalar fScale;
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+#if 1
+ canvas->drawColor(SK_ColorWHITE);
+ canvas->translate(SK_Scalar1/2, SkIntToScalar(15) + SK_Scalar1/2);
+ canvas->scale(SkIntToScalar(3)/2, SkIntToScalar(3)/2);
+ drawbug(canvas, fScale);
+ fScale += SK_Scalar1/93;
+ this->inval(NULL);
+ return;
+#endif
+
+ SkPaint paint;
+ paint.setDither(true);
+ paint.setFilterBitmap(true);
+
+ for (int i = 0; i < SK_ARRAY_COUNT(fRecs); i++) {
+ canvas->save();
+
+ paint.setShader(NULL);
+ canvas->drawVertices(fRecs[i].fMode, fRecs[i].fCount,
+ fRecs[i].fVerts, fRecs[i].fTexs,
+ NULL, NULL, NULL, 0, paint);
+
+ canvas->translate(SkIntToScalar(250), 0);
+
+ paint.setShader(fShader0);
+ canvas->drawVertices(fRecs[i].fMode, fRecs[i].fCount,
+ fRecs[i].fVerts, fRecs[i].fTexs,
+ NULL, NULL, NULL, 0, paint);
+
+ canvas->translate(SkIntToScalar(250), 0);
+
+ paint.setShader(fShader1);
+ canvas->drawVertices(fRecs[i].fMode, fRecs[i].fCount,
+ fRecs[i].fVerts, fRecs[i].fTexs,
+ NULL, NULL, NULL, 0, paint);
+ canvas->restore();
+
+ canvas->translate(0, SkIntToScalar(250));
+ }
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ return new Click(this);
+ }
+
+ virtual bool onClick(Click* click) {
+ // fCurrX = click->fICurr.fX;
+ // fCurrY = click->fICurr.fY;
+ this->inval(NULL);
+ return true;
+ }
+
+private:
+ struct Rec {
+ SkCanvas::VertexMode fMode;
+ int fCount;
+ SkPoint* fVerts;
+ SkPoint* fTexs;
+
+ Rec() : fCount(0), fVerts(NULL), fTexs(NULL) {}
+ ~Rec() { delete[] fVerts; delete[] fTexs; }
+ };
+
+ void make_tris(Rec* rec) {
+ int n = 10;
+ SkRandom rand;
+
+ rec->fMode = SkCanvas::kTriangles_VertexMode;
+ rec->fCount = n * 3;
+ rec->fVerts = new SkPoint[rec->fCount];
+
+ for (int i = 0; i < n; i++) {
+ SkPoint* v = &rec->fVerts[i*3];
+ for (int j = 0; j < 3; j++) {
+ v[j].set(rand.nextUScalar1() * 250, rand.nextUScalar1() * 250);
+ }
+ }
+ }
+
+ void make_fan(Rec* rec, int texWidth, int texHeight) {
+ const SkScalar tx = SkIntToScalar(texWidth);
+ const SkScalar ty = SkIntToScalar(texHeight);
+ const int n = 24;
+
+ rec->fMode = SkCanvas::kTriangleFan_VertexMode;
+ rec->fCount = n + 2;
+ rec->fVerts = new SkPoint[rec->fCount];
+ rec->fTexs = new SkPoint[rec->fCount];
+
+ SkPoint* v = rec->fVerts;
+ SkPoint* t = rec->fTexs;
+
+ v[0].set(0, 0);
+ t[0].set(0, 0);
+ for (int i = 0; i < n; i++) {
+ SkScalar cos;
+ SkScalar sin = SkScalarSinCos(SK_ScalarPI * 2 * i / n, &cos);
+ v[i+1].set(cos, sin);
+ t[i+1].set(i*tx/n, ty);
+ }
+ v[n+1] = v[1];
+ t[n+1].set(tx, ty);
+
+ SkMatrix m;
+ m.setScale(SkIntToScalar(100), SkIntToScalar(100));
+ m.postTranslate(SkIntToScalar(110), SkIntToScalar(110));
+ m.mapPoints(v, rec->fCount);
+ }
+
+ void make_strip(Rec* rec, int texWidth, int texHeight) {
+ const SkScalar tx = SkIntToScalar(texWidth);
+ const SkScalar ty = SkIntToScalar(texHeight);
+ const int n = 24;
+
+ rec->fMode = SkCanvas::kTriangleStrip_VertexMode;
+ rec->fCount = 2 * (n + 1);
+ rec->fVerts = new SkPoint[rec->fCount];
+ rec->fTexs = new SkPoint[rec->fCount];
+
+ SkPoint* v = rec->fVerts;
+ SkPoint* t = rec->fTexs;
+
+ for (int i = 0; i < n; i++) {
+ SkScalar cos;
+ SkScalar sin = SkScalarSinCos(SK_ScalarPI * 2 * i / n, &cos);
+ v[i*2 + 0].set(cos/2, sin/2);
+ v[i*2 + 1].set(cos, sin);
+
+ t[i*2 + 0].set(tx * i / n, ty);
+ t[i*2 + 1].set(tx * i / n, 0);
+ }
+ v[2*n + 0] = v[0];
+ v[2*n + 1] = v[1];
+
+ t[2*n + 0].set(tx, ty);
+ t[2*n + 1].set(tx, 0);
+
+ SkMatrix m;
+ m.setScale(SkIntToScalar(100), SkIntToScalar(100));
+ m.postTranslate(SkIntToScalar(110), SkIntToScalar(110));
+ m.mapPoints(v, rec->fCount);
+ }
+
+ Rec fRecs[3];
+
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new VerticesView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/SampleXfermodes.cpp b/samplecode/SampleXfermodes.cpp
new file mode 100644
index 0000000..1dbfc95
--- /dev/null
+++ b/samplecode/SampleXfermodes.cpp
@@ -0,0 +1,265 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "Sk64.h"
+#include "SkCornerPathEffect.h"
+#include "SkGradientShader.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkKernel33MaskFilter.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+#include "SkXfermode.h"
+
+#include "SkStream.h"
+#include "SkXMLParser.h"
+#include "SkColorPriv.h"
+#include "SkImageDecoder.h"
+
+static int newscale(U8CPU a, U8CPU b, int shift) {
+ unsigned prod = a * b + (1 << (shift - 1));
+ return (prod + (prod >> shift)) >> shift;
+}
+
+static void test_srcover565(SkCanvas* canvas) {
+ const int width = 32;
+ SkBitmap bm1, bm2, bm3;
+ bm1.setConfig(SkBitmap::kRGB_565_Config, width, 256); bm1.allocPixels(NULL);
+ bm2.setConfig(SkBitmap::kRGB_565_Config, width, 256); bm2.allocPixels(NULL);
+ bm3.setConfig(SkBitmap::kRGB_565_Config, width, 256); bm3.allocPixels(NULL);
+
+ int rgb = 0x18;
+ int r = rgb >> 3;
+ int g = rgb >> 2;
+ uint16_t dst = SkPackRGB16(r, g, r);
+ for (int alpha = 0; alpha <= 255; alpha++) {
+ SkPMColor pm = SkPreMultiplyARGB(alpha, rgb, rgb, rgb);
+ uint16_t newdst = SkSrcOver32To16(pm, dst);
+ sk_memset16(bm1.getAddr16(0, alpha), newdst, bm1.width());
+
+ int ia = 255 - alpha;
+ int iscale = SkAlpha255To256(ia);
+ int dr = (SkGetPackedR32(pm) + (r * iscale >> 5)) >> 3;
+ int dg = (SkGetPackedG32(pm) + (g * iscale >> 6)) >> 2;
+
+ sk_memset16(bm2.getAddr16(0, alpha), SkPackRGB16(dr, dg, dr), bm2.width());
+
+ int dr2 = (SkMulDiv255Round(alpha, rgb) + newscale(r, ia, 5)) >> 3;
+ int dg2 = (SkMulDiv255Round(alpha, rgb) + newscale(g, ia, 6)) >> 2;
+
+ sk_memset16(bm3.getAddr16(0, alpha), SkPackRGB16(dr2, dg2, dr2), bm3.width());
+
+// if (mr != dr || mg != dg)
+ {
+// SkDebugf("[%d] macro [%d %d] inline [%d %d] new [%d %d]\n", alpha, mr, mg, dr, dg, dr2, dg2);
+ }
+ }
+
+ SkScalar dx = SkIntToScalar(width+4);
+
+ canvas->drawBitmap(bm1, 0, 0, NULL); canvas->translate(dx, 0);
+ canvas->drawBitmap(bm2, 0, 0, NULL); canvas->translate(dx, 0);
+ canvas->drawBitmap(bm3, 0, 0, NULL); canvas->translate(dx, 0);
+
+ SkRect rect = { 0, 0, SkIntToScalar(bm1.width()), SkIntToScalar(bm1.height()) };
+ SkPaint p;
+ p.setARGB(0xFF, rgb, rgb, rgb);
+ canvas->drawRect(rect, p);
+}
+
+static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) {
+ src->setConfig(SkBitmap::kARGB_8888_Config, w, h);
+ src->allocPixels();
+ src->eraseColor(0);
+
+ SkCanvas c(*src);
+ SkPaint p;
+ SkRect r;
+ SkScalar ww = SkIntToScalar(w);
+ SkScalar hh = SkIntToScalar(h);
+
+ p.setAntiAlias(true);
+ p.setColor(0xFFFFCC44);
+ r.set(0, 0, ww*3/4, hh*3/4);
+ c.drawOval(r, p);
+
+ dst->setConfig(SkBitmap::kARGB_8888_Config, w, h);
+ dst->allocPixels();
+ dst->eraseColor(0);
+ c.setBitmapDevice(*dst);
+
+ p.setColor(0xFF66AAFF);
+ r.set(ww/3, hh/3, ww*19/20, hh*19/20);
+ c.drawRect(r, p);
+}
+
+static uint16_t gBG[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
+
+class XfermodesView : public SkView {
+ SkBitmap fBitmap;
+ SkBitmap fBG;
+ SkBitmap fSrcB, fDstB;
+
+ void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha) {
+ SkPaint p;
+
+ canvas->drawBitmap(fSrcB, 0, 0, &p);
+ p.setAlpha(alpha);
+ p.setXfermode(mode);
+ canvas->drawBitmap(fDstB, 0, 0, &p);
+ }
+
+public:
+ XfermodesView() {
+ const int W = 64;
+ const int H = 64;
+
+ fBitmap.setConfig(SkBitmap::kARGB_8888_Config, W, H);
+ fBitmap.allocPixels();
+
+ fBG.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4);
+ fBG.setPixels(gBG);
+ fBG.setIsOpaque(true);
+
+ make_bitmaps(W, H, &fSrcB, &fDstB);
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Xfermodes");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorWHITE);
+ return;
+ SkShader* s = SkShader::CreateBitmapShader(fBG,
+ SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode);
+ SkPaint p;
+ SkMatrix m;
+
+ p.setShader(s)->unref();
+ m.setScale(SkIntToScalar(8), SkIntToScalar(8));
+ s->setLocalMatrix(m);
+ canvas->drawPaint(p);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ if (false) {
+ test_srcover565(canvas);
+ }
+
+ if (false) {
+ SkPaint paint;
+ paint.setFlags(0x43);
+ paint.setTextSize(SkIntToScalar(128));
+ SkMatrix matrix;
+ matrix.reset();
+ matrix.set(0, 0x0019d049);
+ matrix.set(2, 0x712cf400);
+ matrix.set(4, 0x0019c96f);
+ matrix.set(5, 0xF8d76598);
+ canvas->concat(matrix);
+ canvas->drawText("HamburgefonsHamburgefonsHamburgefonsHamburgefons",
+ 48, 0, 0, paint);
+ return;
+ }
+
+ const struct {
+ SkPorterDuff::Mode fMode;
+ const char* fLabel;
+ } gModes[] = {
+ { SkPorterDuff::kClear_Mode, "Clear" },
+ { SkPorterDuff::kSrc_Mode, "Src" },
+ { SkPorterDuff::kDst_Mode, "Dst" },
+ { SkPorterDuff::kSrcOver_Mode, "SrcOver" },
+ { SkPorterDuff::kDstOver_Mode, "DstOver" },
+ { SkPorterDuff::kSrcIn_Mode, "SrcIn" },
+ { SkPorterDuff::kDstIn_Mode, "DstIn" },
+ { SkPorterDuff::kSrcOut_Mode, "SrcOut" },
+ { SkPorterDuff::kDstOut_Mode, "DstOut" },
+ { SkPorterDuff::kSrcATop_Mode, "SrcATop" },
+ { SkPorterDuff::kDstATop_Mode, "DstATop" },
+ { SkPorterDuff::kXor_Mode, "Xor" },
+ { SkPorterDuff::kDarken_Mode, "Darken" },
+ { SkPorterDuff::kLighten_Mode, "Lighten" },
+ { SkPorterDuff::kMultiply_Mode, "Multiply" },
+ { SkPorterDuff::kScreen_Mode, "Screen" }
+ };
+
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
+
+ SkCanvas c(fBitmap);
+ const SkScalar w = SkIntToScalar(fBitmap.width());
+ const SkScalar h = SkIntToScalar(fBitmap.height());
+ SkShader* s = SkShader::CreateBitmapShader(fBG,
+ SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode);
+ SkMatrix m;
+ m.setScale(SkIntToScalar(6), SkIntToScalar(6));
+ s->setLocalMatrix(m);
+
+ SkPaint labelP;
+ labelP.setAntiAlias(true);
+ labelP.setTextAlign(SkPaint::kCenter_Align);
+
+ SkScalar x0 = 0;
+ for (int twice = 0; twice < 2; twice++) {
+ SkScalar x = x0, y = 0;
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
+ SkXfermode* mode = SkPorterDuff::CreateXfermode(gModes[i].fMode);
+
+ fBitmap.eraseColor(0);
+ draw_mode(&c, mode, twice ? 0x88 : 0xFF);
+ mode->safeUnref();
+
+ SkPaint p;
+ SkRect r;
+ r.set(x, y, x+w, y+h);
+ r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
+ p.setStyle(SkPaint::kStroke_Style);
+ canvas->drawRect(r, p);
+ p.setStyle(SkPaint::kFill_Style);
+ p.setShader(s);
+ r.inset(SK_ScalarHalf, SK_ScalarHalf);
+ canvas->drawRect(r, p);
+
+ canvas->drawBitmap(fBitmap, x, y, NULL);
+
+ canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
+ x + w/2, y - labelP.getTextSize()/2, labelP);
+
+ x += w + SkIntToScalar(10);
+ if ((i & 3) == 3) {
+ x = x0;
+ y += h + SkIntToScalar(30);
+ }
+ }
+ x0 += SkIntToScalar(330);
+ }
+ s->unref();
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new XfermodesView; }
+static SkViewRegister reg(MyFactory);
+
diff --git a/samplecode/vertexdump.cpp b/samplecode/vertexdump.cpp
new file mode 100644
index 0000000..c124ad8
--- /dev/null
+++ b/samplecode/vertexdump.cpp
@@ -0,0 +1,88 @@
+#include "SkPoint.h"
+
+void setup_vertexbug(SkPoint verts[], SkPoint texs[], uint16_t index[]);
+
+void setup_vertexbug(SkPoint verts[], SkPoint texs[], uint16_t index[]) {
+ verts[0].set(SkFloatToScalar(107), SkFloatToScalar(189));
+ texs[0].set(SkFloatToScalar(0), SkFloatToScalar(0));
+ verts[1].set(SkFloatToScalar(116), SkFloatToScalar(189));
+ texs[1].set(SkFloatToScalar(9), SkFloatToScalar(0));
+ verts[2].set(SkFloatToScalar(203), SkFloatToScalar(189));
+ texs[2].set(SkFloatToScalar(35), SkFloatToScalar(0));
+ verts[3].set(SkFloatToScalar(212), SkFloatToScalar(189));
+ texs[3].set(SkFloatToScalar(44), SkFloatToScalar(0));
+ verts[4].set(SkFloatToScalar(107), SkFloatToScalar(198));
+ texs[4].set(SkFloatToScalar(0), SkFloatToScalar(9));
+ verts[5].set(SkFloatToScalar(116), SkFloatToScalar(198));
+ texs[5].set(SkFloatToScalar(9), SkFloatToScalar(9));
+ verts[6].set(SkFloatToScalar(203), SkFloatToScalar(198));
+ texs[6].set(SkFloatToScalar(35), SkFloatToScalar(9));
+ verts[7].set(SkFloatToScalar(212), SkFloatToScalar(198));
+ texs[7].set(SkFloatToScalar(44), SkFloatToScalar(9));
+ verts[8].set(SkFloatToScalar(107), SkFloatToScalar(224));
+ texs[8].set(SkFloatToScalar(0), SkFloatToScalar(39));
+ verts[9].set(SkFloatToScalar(116), SkFloatToScalar(224));
+ texs[9].set(SkFloatToScalar(9), SkFloatToScalar(39));
+ verts[10].set(SkFloatToScalar(203), SkFloatToScalar(224));
+ texs[10].set(SkFloatToScalar(35), SkFloatToScalar(39));
+ verts[11].set(SkFloatToScalar(212), SkFloatToScalar(224));
+ texs[11].set(SkFloatToScalar(44), SkFloatToScalar(39));
+ verts[12].set(SkFloatToScalar(107), SkFloatToScalar(233));
+ texs[12].set(SkFloatToScalar(0), SkFloatToScalar(48));
+ verts[13].set(SkFloatToScalar(116), SkFloatToScalar(233));
+ texs[13].set(SkFloatToScalar(9), SkFloatToScalar(48));
+ verts[14].set(SkFloatToScalar(203), SkFloatToScalar(233));
+ texs[14].set(SkFloatToScalar(35), SkFloatToScalar(48));
+ verts[15].set(SkFloatToScalar(212), SkFloatToScalar(233));
+ texs[15].set(SkFloatToScalar(44), SkFloatToScalar(48));
+ index[0] = 0; index[1] = 5; index[2] = 1;
+ index[3] = 0; index[4] = 4; index[5] = 5;
+#if 0
+ index[6] = 1; index[7] = 6; index[8] = 2;
+#else
+ index[6] = 6; index[7] = 2; index[8] = 1;
+#endif
+ index[9] = 1; index[10] = 5; index[11] = 6;
+ index[12] = 2;
+ index[13] = 7;
+ index[14] = 3;
+ index[15] = 2;
+ index[16] = 6;
+ index[17] = 7;
+ index[18] = 4;
+ index[19] = 9;
+ index[20] = 5;
+ index[21] = 4;
+ index[22] = 8;
+ index[23] = 9;
+ index[24] = 5;
+ index[25] = 10;
+ index[26] = 6;
+ index[27] = 5;
+ index[28] = 9;
+ index[29] = 10;
+ index[30] = 6;
+ index[31] = 11;
+ index[32] = 7;
+ index[33] = 6;
+ index[34] = 10;
+ index[35] = 11;
+ index[36] = 8;
+ index[37] = 13;
+ index[38] = 9;
+ index[39] = 8;
+ index[40] = 12;
+ index[41] = 13;
+ index[42] = 9;
+ index[43] = 14;
+ index[44] = 10;
+ index[45] = 9;
+ index[46] = 13;
+ index[47] = 14;
+ index[48] = 10;
+ index[49] = 15;
+ index[50] = 11;
+ index[51] = 10;
+ index[52] = 14;
+ index[53] = 15;
+}