From 03202c9c3dfbf8c4feb0a1ee9b3680817e633f58 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Fri, 9 Jan 2009 17:51:21 -0800 Subject: auto import from //branches/cupcake/...@125939 --- samplecode/SampleAll.cpp | 791 +++++++++++++++++++++++++++++++++++++++ samplecode/SampleApp.cpp | 607 ++++++++++++++++++++++++++++++ samplecode/SampleArc.cpp | 187 +++++++++ samplecode/SampleBitmapRect.cpp | 110 ++++++ samplecode/SampleCamera.cpp | 106 ++++++ samplecode/SampleCircle.cpp | 137 +++++++ samplecode/SampleCode.h | 38 ++ samplecode/SampleCull.cpp | 230 ++++++++++++ samplecode/SampleDither.cpp | 197 ++++++++++ samplecode/SampleDrawLooper.cpp | 103 +++++ samplecode/SampleEmboss.cpp | 77 ++++ samplecode/SampleEncode.cpp | 253 +++++++++++++ samplecode/SampleFillType.cpp | 101 +++++ samplecode/SampleFilter.cpp | 163 ++++++++ samplecode/SampleFilter2.cpp | 123 ++++++ samplecode/SampleFontCache.cpp | 171 +++++++++ samplecode/SampleGL.cpp | 206 ++++++++++ samplecode/SampleImage.cpp | 158 ++++++++ samplecode/SampleImageDir.cpp | 319 ++++++++++++++++ samplecode/SampleLayers.cpp | 258 +++++++++++++ samplecode/SampleLines.cpp | 146 ++++++++ samplecode/SampleMeasure.cpp | 138 +++++++ samplecode/SampleNinePatch.cpp | 56 +++ samplecode/SampleOverflow.cpp | 106 ++++++ samplecode/SamplePageFlip.cpp | 173 +++++++++ samplecode/SamplePatch.cpp | 417 +++++++++++++++++++++ samplecode/SamplePath.cpp | 163 ++++++++ samplecode/SamplePathEffects.cpp | 282 ++++++++++++++ samplecode/SamplePicture.cpp | 157 ++++++++ samplecode/SamplePoints.cpp | 121 ++++++ samplecode/SamplePolyToPoly.cpp | 165 ++++++++ samplecode/SampleRegion.cpp | 307 +++++++++++++++ samplecode/SampleShaders.cpp | 157 ++++++++ samplecode/SampleStrokeText.cpp | 147 ++++++++ samplecode/SampleTests.cpp | 99 +++++ samplecode/SampleText.cpp | 791 +++++++++++++++++++++++++++++++++++++++ samplecode/SampleTextAlpha.cpp | 122 ++++++ samplecode/SampleTextEffects.cpp | 466 +++++++++++++++++++++++ samplecode/SampleTextOnPath.cpp | 442 ++++++++++++++++++++++ samplecode/SampleTiling.cpp | 170 +++++++++ samplecode/SampleTypeface.cpp | 91 +++++ samplecode/SampleVertices.cpp | 278 ++++++++++++++ samplecode/SampleXfermodes.cpp | 265 +++++++++++++ samplecode/vertexdump.cpp | 88 +++++ 44 files changed, 9682 insertions(+) create mode 100644 samplecode/SampleAll.cpp create mode 100644 samplecode/SampleApp.cpp create mode 100644 samplecode/SampleArc.cpp create mode 100644 samplecode/SampleBitmapRect.cpp create mode 100644 samplecode/SampleCamera.cpp create mode 100644 samplecode/SampleCircle.cpp create mode 100644 samplecode/SampleCode.h create mode 100644 samplecode/SampleCull.cpp create mode 100644 samplecode/SampleDither.cpp create mode 100644 samplecode/SampleDrawLooper.cpp create mode 100644 samplecode/SampleEmboss.cpp create mode 100644 samplecode/SampleEncode.cpp create mode 100644 samplecode/SampleFillType.cpp create mode 100644 samplecode/SampleFilter.cpp create mode 100644 samplecode/SampleFilter2.cpp create mode 100644 samplecode/SampleFontCache.cpp create mode 100644 samplecode/SampleGL.cpp create mode 100644 samplecode/SampleImage.cpp create mode 100644 samplecode/SampleImageDir.cpp create mode 100644 samplecode/SampleLayers.cpp create mode 100644 samplecode/SampleLines.cpp create mode 100644 samplecode/SampleMeasure.cpp create mode 100644 samplecode/SampleNinePatch.cpp create mode 100644 samplecode/SampleOverflow.cpp create mode 100644 samplecode/SamplePageFlip.cpp create mode 100644 samplecode/SamplePatch.cpp create mode 100644 samplecode/SamplePath.cpp create mode 100644 samplecode/SamplePathEffects.cpp create mode 100644 samplecode/SamplePicture.cpp create mode 100644 samplecode/SamplePoints.cpp create mode 100644 samplecode/SamplePolyToPoly.cpp create mode 100644 samplecode/SampleRegion.cpp create mode 100644 samplecode/SampleShaders.cpp create mode 100644 samplecode/SampleStrokeText.cpp create mode 100644 samplecode/SampleTests.cpp create mode 100644 samplecode/SampleText.cpp create mode 100644 samplecode/SampleTextAlpha.cpp create mode 100644 samplecode/SampleTextEffects.cpp create mode 100644 samplecode/SampleTextOnPath.cpp create mode 100644 samplecode/SampleTiling.cpp create mode 100644 samplecode/SampleTypeface.cpp create mode 100644 samplecode/SampleVertices.cpp create mode 100644 samplecode/SampleXfermodes.cpp create mode 100644 samplecode/vertexdump.cpp (limited to 'samplecode') 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 + +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(pos); + pos.setCount(asciiLength); + for (index = 0; index < asciiLength; index++) + pos[index].set(SkIntToScalar(index * 10), SkIntToScalar(index * 2)); + SkTDArray(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 +#include +#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(""); + } + + title.prepend(gCanvasTypePrefix[fCanvasType]); + + title.prepend(" "); + title.prepend(configToString(this->getBitmap().config())); + + if (fAnimating) { + title.prepend(" "); + } + + 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 + +#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 + +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 + +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 +#include + +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 autoWidths(len); + SkScalar* widths = autoWidths.get(); + SkAutoTMalloc 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 + +#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(context); + SkFlipPixelRef* ref = static_cast(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(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 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 stripStorage(stripCount * 2); + SkAutoTMalloc 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; +} -- cgit v1.1