aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bench/RectBench.cpp13
-rw-r--r--bench/SkBenchmark.cpp1
-rw-r--r--bench/SkBenchmark.h16
-rw-r--r--bench/benchmain.cpp18
-rw-r--r--include/core/SkCanvas.h47
-rw-r--r--include/core/SkDevice.h45
-rw-r--r--include/core/SkGraphics.h7
-rw-r--r--include/core/SkPaint.h8
-rw-r--r--include/core/SkPath.h3
-rw-r--r--include/core/SkPictureFlat.h (renamed from src/core/SkPictureFlat.h)0
-rw-r--r--include/core/SkRect.h14
-rw-r--r--include/core/SkTypes.h6
-rw-r--r--include/core/SkXfermode.h2
-rw-r--r--include/effects/SkPorterDuff.h1
-rw-r--r--include/utils/SkGLCanvas.h47
-rw-r--r--src/core/SkBitmapProcShader.cpp25
-rw-r--r--src/core/SkBitmapProcState.cpp11
-rw-r--r--src/core/SkBitmapProcState.h9
-rw-r--r--src/core/SkBitmapProcState_matrixProcs.cpp2
-rw-r--r--src/core/SkBlitter_A8.cpp6
-rw-r--r--src/core/SkCanvas.cpp48
-rw-r--r--src/core/SkDevice.cpp14
-rw-r--r--src/core/SkDraw.cpp2
-rw-r--r--src/core/SkGraphics.cpp12
-rw-r--r--src/core/SkPaint.cpp209
-rw-r--r--src/core/SkPath.cpp17
-rw-r--r--src/core/SkPicturePlayback.cpp2
-rw-r--r--src/core/SkPicturePlayback.h2
-rw-r--r--src/core/SkRegion.cpp14
-rw-r--r--src/core/SkXfermode.cpp24
-rw-r--r--src/effects/SkBlurDrawLooper.cpp9
-rw-r--r--src/effects/SkPorterDuff.cpp3
-rw-r--r--src/gl/SkGLCanvas.cpp192
-rw-r--r--src/gl/SkGLDevice.cpp140
-rw-r--r--src/gl/SkGLDevice.h39
-rw-r--r--src/images/SkFlipPixelRef.cpp1
-rw-r--r--src/images/SkImageDecoder_Factory.cpp14
-rw-r--r--src/images/SkImageDecoder_libico.cpp4
-rw-r--r--src/images/SkImageDecoder_libjpeg.cpp30
-rw-r--r--src/images/SkImageDecoder_libpng.cpp41
-rw-r--r--src/images/SkImageEncoder_Factory.cpp13
-rw-r--r--src/images/SkImageRef_GlobalPool.cpp1
-rw-r--r--src/images/SkScaledBitmapSampler.cpp26
-rw-r--r--src/images/SkScaledBitmapSampler.h3
-rw-r--r--src/ports/SkImageRef_ashmem.cpp34
-rw-r--r--src/ports/SkImageRef_ashmem.h8
-rw-r--r--src/utils/SkCullPoints.cpp64
-rw-r--r--src/utils/SkDumpCanvas.cpp29
-rw-r--r--src/utils/SkNinePatch.cpp29
-rw-r--r--tests/MathTest.cpp1
50 files changed, 866 insertions, 440 deletions
diff --git a/bench/RectBench.cpp b/bench/RectBench.cpp
index 6f34eb5..3874bb3 100644
--- a/bench/RectBench.cpp
+++ b/bench/RectBench.cpp
@@ -89,14 +89,20 @@ public:
protected:
virtual void onDraw(SkCanvas* canvas) {
- static const SkScalar gSizes[] = {
+ SkScalar gSizes[] = {
SkIntToScalar(7), 0
};
+ size_t sizes = SK_ARRAY_COUNT(gSizes);
+
+ if (this->hasStrokeWidth()) {
+ gSizes[0] = this->getStrokeWidth();
+ sizes = 1;
+ }
SkPaint paint;
paint.setStrokeCap(SkPaint::kRound_Cap);
-
- for (size_t i = 0; i < SK_ARRAY_COUNT(gSizes); i++) {
+
+ for (size_t i = 0; i < sizes; i++) {
paint.setStrokeWidth(gSizes[i]);
this->setupPaint(&paint);
canvas->drawPoints(fMode, N * 2,
@@ -132,4 +138,3 @@ static BenchRegistry gRRectReg2(RRectFactory2);
static BenchRegistry gPointsReg(PointsFactory);
static BenchRegistry gLinesReg(LinesFactory);
static BenchRegistry gPolygonReg(PolygonFactory);
-
diff --git a/bench/SkBenchmark.cpp b/bench/SkBenchmark.cpp
index e8bea6e..230a7af 100644
--- a/bench/SkBenchmark.cpp
+++ b/bench/SkBenchmark.cpp
@@ -9,6 +9,7 @@ SkBenchmark::SkBenchmark(void* defineDict) {
fForceAlpha = 0xFF;
fForceAA = true;
fDither = SkTriState::kDefault;
+ fHasStrokeWidth = false;
}
const char* SkBenchmark::getName() {
diff --git a/bench/SkBenchmark.h b/bench/SkBenchmark.h
index bc9794a..945db80 100644
--- a/bench/SkBenchmark.h
+++ b/bench/SkBenchmark.h
@@ -42,6 +42,19 @@ public:
fDither = state;
}
+ void setStrokeWidth(SkScalar width) {
+ strokeWidth = width;
+ fHasStrokeWidth = true;
+ }
+
+ SkScalar getStrokeWidth() {
+ return strokeWidth;
+ }
+
+ bool hasStrokeWidth() {
+ return fHasStrokeWidth;
+ }
+
const char* findDefine(const char* key) const;
bool findDefine32(const char* key, int32_t* value) const;
bool findDefineScalar(const char* key, SkScalar* value) const;
@@ -60,9 +73,10 @@ private:
bool fForceAA;
bool fForceFilter;
SkTriState::State fDither;
+ bool fHasStrokeWidth;
+ SkScalar strokeWidth;
};
typedef SkTRegistry<SkBenchmark*, void*> BenchRegistry;
#endif
-
diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp
index 7443604..2f8b006 100644
--- a/bench/benchmain.cpp
+++ b/bench/benchmain.cpp
@@ -201,6 +201,8 @@ int main (int argc, char * const argv[]) {
bool doClip = false;
bool doPict = false;
const char* matchStr = NULL;
+ bool hasStrokeWidth = false;
+ float strokeWidth;
SkString outDir;
SkBitmap::Config outConfig = SkBitmap::kNo_Config;
@@ -260,6 +262,19 @@ int main (int argc, char * const argv[]) {
return -1;
}
forceAlpha = wantAlpha ? 0x80 : 0xFF;
+ } else if (strcmp(*argv, "-strokeWidth") == 0) {
+ argv++;
+ if (argv < stop) {
+ const char *strokeWidthStr = *argv;
+ if (sscanf(strokeWidthStr, "%f", &strokeWidth) != 1) {
+ log_error("bad arg for -strokeWidth\n");
+ return -1;
+ }
+ hasStrokeWidth = true;
+ } else {
+ log_error("missing arg for -strokeWidth\n");
+ return -1;
+ }
} else if (strcmp(*argv, "-match") == 0) {
argv++;
if (argv < stop) {
@@ -314,6 +329,9 @@ int main (int argc, char * const argv[]) {
bench->setForceAA(forceAA);
bench->setForceFilter(forceFilter);
bench->setDither(forceDither);
+ if (hasStrokeWidth) {
+ bench->setStrokeWidth(strokeWidth);
+ }
// only run benchmarks if their name contains matchStr
if (matchStr && strstr(bench->getName(), matchStr) == NULL) {
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index bfa0d10..b5ccca6 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -29,6 +29,7 @@
class SkBounder;
class SkDevice;
+class SkDeviceFactory;
class SkDraw;
class SkDrawFilter;
class SkPicture;
@@ -51,29 +52,37 @@ class SkShape;
*/
class SkCanvas : public SkRefCnt {
public:
- /** Construct a canvas with the specified bitmap to draw into.
+ /** Construct a canvas with the given device factory.
+ @param factory Specify the factory for generating additional devices.
+ The factory may be null, in which case
+ SkRasterDeviceFactory will be used.
+ */
+ explicit SkCanvas(SkDeviceFactory* factory = NULL);
+
+ /** Construct a canvas with the specified device to draw into. The device
+ factory will be retrieved from the passed device.
+ @param device Specifies a device for the canvas to draw into.
+ */
+ explicit SkCanvas(SkDevice* device);
+
+ /** Deprecated - Construct a canvas with the specified bitmap to draw into.
@param bitmap Specifies a bitmap for the canvas to draw into. Its
structure are copied to the canvas.
*/
explicit SkCanvas(const SkBitmap& bitmap);
- /** Construct a canvas with the specified device to draw into.
- @param device Specifies a device for the canvas to draw into. The
- device may be null.
- */
- explicit SkCanvas(SkDevice* device = NULL);
virtual ~SkCanvas();
///////////////////////////////////////////////////////////////////////////
- /** If this subclass of SkCanvas supports GL viewports, return true and set
- size (if not null) to the size of the viewport. If it is not supported,
- ignore vp and return false.
+ /** If the Device supports GL viewports, return true and set size (if not
+ null) to the size of the viewport. If it is not supported, ignore size
+ and return false.
*/
virtual bool getViewport(SkIPoint* size) const;
-
- /** If this subclass of SkCanvas supports GL viewports, return true and set
- the viewport to the specified x and y dimensions. If it is not
- supported, ignore x and y and return false.
+
+ /** If the Device supports GL viewports, return true and set the viewport
+ to the specified x and y dimensions. If it is not supported, ignore x
+ and y and return false.
*/
virtual bool setViewport(int x, int y);
@@ -88,15 +97,16 @@ public:
device, its reference count is decremented. The new device is returned.
*/
SkDevice* setDevice(SkDevice* device);
-
- /** Specify a bitmap for the canvas to draw into. This is a help method for
- setDevice(), and it creates a device for the bitmap by calling
- createDevice(). The structure of the bitmap is copied into the device.
+
+ /** Deprecated - Specify a bitmap for the canvas to draw into. This is a
+ helper method for setDevice(), and it creates a device for the bitmap by
+ calling createDevice(). The structure of the bitmap is copied into the
+ device.
*/
virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap);
///////////////////////////////////////////////////////////////////////////
-
+
enum SaveFlags {
/** save the matrix state, restoring it on restore() */
kMatrix_SaveFlag = 0x01,
@@ -758,6 +768,7 @@ private:
SkBounder* fBounder;
SkDevice* fLastDeviceToGainFocus;
+ SkDeviceFactory* fDeviceFactory;
void prepareForDeviceDraw(SkDevice*);
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 0d724ba..dbc8fcf 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,26 +22,53 @@
#include "SkCanvas.h"
#include "SkColor.h"
+class SkDevice;
class SkDraw;
struct SkIRect;
class SkMatrix;
class SkRegion;
+/** \class SkDeviceFactory
+
+ Devices that extend SkDevice should also provide a SkDeviceFactory class
+ to pass into SkCanvas. Doing so will eliminate the need to extend
+ SkCanvas as well.
+*/
+class SkDeviceFactory {
+public:
+ virtual ~SkDeviceFactory();
+ virtual SkDevice* newDevice(SkBitmap::Config config, int width, int height,
+ bool isOpaque, bool isForLayer) = 0;
+};
+
+class SkRasterDeviceFactory : public SkDeviceFactory {
+public:
+ virtual SkDevice* newDevice(SkBitmap::Config config, int width, int height,
+ bool isOpaque, bool isForLayer);
+};
+
class SkDevice : public SkRefCnt {
public:
SkDevice();
- /** Construct a new device, extracting the width/height/config/isOpaque values from
- the bitmap. If transferPixelOwnership is true, and the bitmap claims to own its
- own pixels (getOwnsPixels() == true), then transfer this responsibility to the
- device, and call setOwnsPixels(false) on the bitmap.
-
- Subclasses may override the destructor, which is virtual, even though this class
- doesn't have one. SkRefCnt does.
-
+ /** Construct a new device, extracting the width/height/config/isOpaque
+ values from the bitmap. Subclasses may override the destructor, which
+ is virtual, even though this class doesn't have one. SkRefCnt does.
+
@param bitmap A copy of this bitmap is made and stored in the device
*/
SkDevice(const SkBitmap& bitmap);
+ virtual SkDeviceFactory* getDeviceFactory() {
+ return SkNEW(SkRasterDeviceFactory);
+ }
+
+ enum Capabilities {
+ kGL_Capability = 0x1, //!< mask indicating GL support
+ kVector_Capability = 0x2, //!< mask indicating a vector representation
+ kAll_Capabilities = 0x3
+ };
+ virtual uint32_t getDeviceCapabilities() { return 0; }
+
/** Return the width of the device (in pixels).
*/
int width() const { return fBitmap.width(); }
diff --git a/include/core/SkGraphics.h b/include/core/SkGraphics.h
index dd5808a..25c926f 100644
--- a/include/core/SkGraphics.h
+++ b/include/core/SkGraphics.h
@@ -33,7 +33,12 @@ public:
Returns true if some amount was purged from the font cache.
*/
static bool SetFontCacheUsed(size_t usageInBytes);
-
+
+ /** Return the version numbers for the library. If the parameter is not
+ null, it is set to the version number.
+ */
+ static void GetVersion(int32_t* major, int32_t* minor, int32_t* patch);
+
private:
/** This is automatically called by SkGraphics::Init(), and must be
implemented by the host OS. This allows the host OS to register a callback
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 5fef527..ea21ceb 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -806,6 +806,11 @@ public:
void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
SkPath* path) const;
+ const SkGlyph& getUnicharMetrics(SkUnichar);
+ const void* findImage(const SkGlyph&);
+
+ uint32_t getGenerationID() const;
+
private:
SkTypeface* fTypeface;
SkScalar fTextSize;
@@ -830,6 +835,7 @@ private:
unsigned fStyle : 2;
unsigned fTextEncoding : 2; // 3 values
unsigned fHinting : 2;
+ uint32_t fGenerationID;
SkDrawCacheProc getDrawCacheProc() const;
SkMeasureCacheProc getMeasureCacheProc(TextBufferDirection dir,
@@ -842,7 +848,7 @@ private:
void descriptorProc(const SkMatrix* deviceMatrix,
void (*proc)(const SkDescriptor*, void*),
- void* context) const;
+ void* context, bool ignoreGamma = false) const;
const SkRect& computeStrokeFastBounds(const SkRect& orig,
SkRect* storage) const;
diff --git a/include/core/SkPath.h b/include/core/SkPath.h
index 3afea09..eb5ff6d 100644
--- a/include/core/SkPath.h
+++ b/include/core/SkPath.h
@@ -571,6 +571,8 @@ public:
*/
void subdivide(SkScalar dist, bool bendLines, SkPath* dst = NULL) const;
+ uint32_t getGenerationID() const;
+
SkDEBUGCODE(void validate() const;)
private:
@@ -580,6 +582,7 @@ private:
mutable uint8_t fBoundsIsDirty;
uint8_t fFillType;
uint8_t fIsConvex;
+ uint32_t fGenerationID;
// called, if dirty, by getBounds()
void computeBounds() const;
diff --git a/src/core/SkPictureFlat.h b/include/core/SkPictureFlat.h
index 2c0af5a..2c0af5a 100644
--- a/src/core/SkPictureFlat.h
+++ b/include/core/SkPictureFlat.h
diff --git a/include/core/SkRect.h b/include/core/SkRect.h
index 879d81a..fbd9f7f 100644
--- a/include/core/SkRect.h
+++ b/include/core/SkRect.h
@@ -233,6 +233,18 @@ struct SkIRect {
struct SkRect {
SkScalar fLeft, fTop, fRight, fBottom;
+ static SkRect MakeEmpty() {
+ SkRect r;
+ r.setEmpty();
+ return r;
+ }
+
+ static SkRect MakeWH(SkScalar w, SkScalar h) {
+ SkRect r;
+ r.set(0, 0, w, h);
+ return r;
+ }
+
static SkRect MakeSize(const SkSize& size) {
SkRect r;
r.set(0, 0, size.width(), size.height());
@@ -250,7 +262,7 @@ struct SkRect {
r.set(x, y, x + w, y + h);
return r;
}
-
+
/** Return true if the rectangle's width or height are <= 0
*/
bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
diff --git a/include/core/SkTypes.h b/include/core/SkTypes.h
index fa21adc..1f8ecaa 100644
--- a/include/core/SkTypes.h
+++ b/include/core/SkTypes.h
@@ -30,6 +30,12 @@
/** \file SkTypes.h
*/
+/** See SkGraphics::GetVersion() to retrieve these at runtime
+ */
+#define SKIA_VERSION_MAJOR 1
+#define SKIA_VERSION_MINOR 0
+#define SKIA_VERSION_PATCH 0
+
/*
memory wrappers to be implemented by the porting layer (platform)
*/
diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h
index 7a06467..d92d346 100644
--- a/include/core/SkXfermode.h
+++ b/include/core/SkXfermode.h
@@ -137,6 +137,8 @@ public:
return false and ignore the mode parameter.
*/
static bool IsMode(SkXfermode*, Mode* mode);
+
+ Mode fMode;
protected:
SkXfermode(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {}
diff --git a/include/effects/SkPorterDuff.h b/include/effects/SkPorterDuff.h
index 6f4ac20..4d7fb31 100644
--- a/include/effects/SkPorterDuff.h
+++ b/include/effects/SkPorterDuff.h
@@ -52,6 +52,7 @@ public:
kMultiply_Mode, //!< [Sa * Da, Sc * Dc]
kScreen_Mode, //!< [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]
kAdd_Mode, //!< Saturate(S + D)
+ kOverlay_Mode,
kModeCount
};
diff --git a/include/utils/SkGLCanvas.h b/include/utils/SkGLCanvas.h
index 40fc52d..eb99527 100644
--- a/include/utils/SkGLCanvas.h
+++ b/include/utils/SkGLCanvas.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,31 +19,11 @@
#include "SkCanvas.h"
-#ifdef SK_BUILD_FOR_MAC
- #include <OpenGL/gl.h>
-#elif defined(ANDROID)
- #include <GLES/gl.h>
-#endif
-
-class SkGLDevice;
-class SkGLClipIter;
-
+// Deprecated. You should now use SkGLDevice and SkGLDeviceFactory with
+// SkCanvas.
class SkGLCanvas : public SkCanvas {
public:
- // notice, we do NOT allow the SkCanvas(bitmap) constructor, since that
- // does not create a SkGLDevice, which we require
SkGLCanvas();
- virtual ~SkGLCanvas();
-
- // overrides from SkCanvas
-
- virtual bool getViewport(SkIPoint*) const;
- virtual bool setViewport(int width, int height);
-
- virtual SkDevice* createDevice(SkBitmap::Config, int width, int height,
- bool isOpaque, bool isForLayer);
-
- // settings for the global texture cache
static size_t GetTextureCacheMaxCount();
static void SetTextureCacheMaxCount(size_t count);
@@ -51,30 +31,9 @@ public:
static size_t GetTextureCacheMaxSize();
static void SetTextureCacheMaxSize(size_t size);
- /** Call glDeleteTextures for all textures (including those for text)
- This should be called while the gl-context is still valid. Its purpose
- is to free up gl resources. Note that if a bitmap or text is drawn after
- this call, new caches will be created.
- */
static void DeleteAllTextures();
- /** Forget all textures without calling delete (including those for text).
- This should be called if the gl-context has changed, and the texture
- IDs that have been cached are no longer valid.
- */
static void AbandonAllTextures();
-
-private:
- SkIPoint fViewportSize;
-
- // need to disallow this guy
- virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap) {
- sk_throw();
- return NULL;
- }
-
- typedef SkCanvas INHERITED;
};
#endif
-
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index bd4fece..c3fd7d0 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -137,6 +137,15 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
#define BUF_MAX 128
+#define TEST_BUFFER_OVERRITEx
+
+#ifdef TEST_BUFFER_OVERRITE
+ #define TEST_BUFFER_EXTRA 32
+ #define TEST_PATTERN 0x88888888
+#else
+ #define TEST_BUFFER_EXTRA 0
+#endif
+
void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
const SkBitmapProcState& state = fState;
if (state.fShaderProc32) {
@@ -144,10 +153,10 @@ void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
return;
}
- uint32_t buffer[BUF_MAX];
+ uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
SkBitmapProcState::MatrixProc mproc = state.fMatrixProc;
SkBitmapProcState::SampleProc32 sproc = state.fSampleProc32;
- int max = fState.maxCountForBufferSize(sizeof(buffer));
+ int max = fState.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
SkASSERT(state.fBitmap->getPixels());
SkASSERT(state.fBitmap->pixelRef() == NULL ||
@@ -158,12 +167,24 @@ void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
if (n > max) {
n = max;
}
+ SkASSERT(n > 0 && n < BUF_MAX*2);
+#ifdef TEST_BUFFER_OVERRITE
+ for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
+ buffer[BUF_MAX + i] = TEST_PATTERN;
+ }
+#endif
mproc(state, buffer, n, x, y);
+#ifdef TEST_BUFFER_OVERRITE
+ for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
+ SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
+ }
+#endif
sproc(state, buffer, n, dstC);
if ((count -= n) == 0) {
break;
}
+ SkASSERT(count > 0);
x += n;
dstC += n;
}
diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp
index eabd966..e54818d 100644
--- a/src/core/SkBitmapProcState.cpp
+++ b/src/core/SkBitmapProcState.cpp
@@ -543,7 +543,6 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
*/
int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
int32_t size = static_cast<int32_t>(bufferSize);
- int perElemShift;
size &= ~3; // only care about 4-byte aligned chunks
if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
@@ -551,11 +550,15 @@ int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
if (size < 0) {
size = 0;
}
- perElemShift = fDoFilter ? 2 : 1;
+ size >>= 1;
} else {
- perElemShift = fDoFilter ? 3 : 2;
+ size >>= 2;
}
- return size >> perElemShift;
+ if (fDoFilter) {
+ size >>= 1;
+ }
+
+ return size;
}
diff --git a/src/core/SkBitmapProcState.h b/src/core/SkBitmapProcState.h
index dd73c33..303696f 100644
--- a/src/core/SkBitmapProcState.h
+++ b/src/core/SkBitmapProcState.h
@@ -91,10 +91,11 @@ struct SkBitmapProcState {
*/
void platformProcs();
- /** Given the size of a buffer, to be used for calling the matrix and
- sample procs, this return the maximum count that can be stored in the
- buffer, taking into account that filtering and scale-vs-affine affect
- this value.
+ /** Given the byte size of the index buffer to be passed to the matrix proc,
+ return the maximum number of resulting pixels that can be computed
+ (i.e. the number of SkPMColor values to be written by the sample proc).
+ This routine takes into account that filtering and scale-vs-affine
+ affect the amount of buffer space needed.
Only valid to call after chooseProcs (setContext) has been called. It is
safe to call this inside the shader's shadeSpan() method.
diff --git a/src/core/SkBitmapProcState_matrixProcs.cpp b/src/core/SkBitmapProcState_matrixProcs.cpp
index 6654312..d0bc8d8 100644
--- a/src/core/SkBitmapProcState_matrixProcs.cpp
+++ b/src/core/SkBitmapProcState_matrixProcs.cpp
@@ -368,7 +368,7 @@ static void clampx_nofilter_trans(const SkBitmapProcState& s,
}
// fill the remaining with the max value
- sk_memset16(xptr, width - 1, count * sizeof(uint16_t));
+ sk_memset16(xptr, width - 1, count);
}
static void repeatx_nofilter_trans(const SkBitmapProcState& s,
diff --git a/src/core/SkBlitter_A8.cpp b/src/core/SkBlitter_A8.cpp
index 18b0881..37ecdfc 100644
--- a/src/core/SkBlitter_A8.cpp
+++ b/src/core/SkBlitter_A8.cpp
@@ -271,7 +271,7 @@ SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint&
SkA8_Shader_Blitter::~SkA8_Shader_Blitter()
{
- fXfermode->safeUnref();
+ if (fXfermode) fXfermode->safeUnref();
sk_free(fBuffer);
}
@@ -377,7 +377,9 @@ void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip)
while (--height >= 0)
{
fShader->shadeSpan(x, y, span, width);
- fXfermode->xferA8(device, span, width, alpha);
+ if (fXfermode) {
+ fXfermode->xferA8(device, span, width, alpha);
+ }
y += 1;
device += fDevice.rowBytes();
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 26e39b5..94c2439 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -404,8 +404,20 @@ SkDevice* SkCanvas::init(SkDevice* device) {
return this->setDevice(device);
}
+SkCanvas::SkCanvas(SkDeviceFactory* factory)
+ : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)),
+ fDeviceFactory(factory) {
+ inc_canvas();
+
+ if (!factory)
+ fDeviceFactory = SkNEW(SkRasterDeviceFactory);
+
+ this->init(NULL);
+}
+
SkCanvas::SkCanvas(SkDevice* device)
- : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
+ : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)),
+ fDeviceFactory(device->getDeviceFactory()) {
inc_canvas();
this->init(device);
@@ -415,7 +427,9 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
inc_canvas();
- this->init(SkNEW_ARGS(SkDevice, (bitmap)))->unref();
+ SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
+ fDeviceFactory = device->getDeviceFactory();
+ this->init(device)->unref();
}
SkCanvas::~SkCanvas() {
@@ -423,8 +437,9 @@ SkCanvas::~SkCanvas() {
this->restoreToCount(1); // restore everything but the last
this->internalRestore(); // restore the last, since we're going away
- fBounder->safeUnref();
-
+ SkSafeUnref(fBounder);
+ SkDELETE(fDeviceFactory);
+
dec_canvas();
}
@@ -521,11 +536,19 @@ SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) {
//////////////////////////////////////////////////////////////////////////////
bool SkCanvas::getViewport(SkIPoint* size) const {
- return false;
+ if ((getDevice()->getDeviceCapabilities() & SkDevice::kGL_Capability) == 0)
+ return false;
+ if (size)
+ size->set(getDevice()->width(), getDevice()->height());
+ return true;
}
bool SkCanvas::setViewport(int width, int height) {
- return false;
+ if ((getDevice()->getDeviceCapabilities() & SkDevice::kGL_Capability) == 0)
+ return false;
+ this->setDevice(createDevice(SkBitmap::kARGB_8888_Config, width, height,
+ false, false))->unref();
+ return true;
}
void SkCanvas::updateDeviceCMCache() {
@@ -1004,18 +1027,9 @@ const SkRegion& SkCanvas::getTotalClip() const {
SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width,
int height, bool isOpaque, bool isForLayer) {
- SkBitmap bitmap;
-
- bitmap.setConfig(config, width, height);
- bitmap.setIsOpaque(isOpaque);
-
- // should this happen in the device subclass?
- bitmap.allocPixels();
- if (!bitmap.isOpaque()) {
- bitmap.eraseARGB(0, 0, 0, 0);
- }
- return SkNEW_ARGS(SkDevice, (bitmap));
+ return fDeviceFactory->newDevice(config, width, height, isOpaque,
+ isForLayer);
}
//////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 8ce1bd8..b629e9a 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -2,6 +2,8 @@
#include "SkDraw.h"
#include "SkRect.h"
+SkDeviceFactory::~SkDeviceFactory() {}
+
SkDevice::SkDevice() {}
SkDevice::SkDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {}
@@ -113,4 +115,16 @@ void SkDevice::drawDevice(const SkDraw& draw, SkDevice* device,
draw.drawSprite(device->accessBitmap(false), x, y, paint);
}
+SkDevice* SkRasterDeviceFactory::newDevice(SkBitmap::Config config, int width,
+ int height, bool isOpaque,
+ bool isForLayer) {
+ SkBitmap bitmap;
+ bitmap.setConfig(config, width, height);
+ bitmap.setIsOpaque(isOpaque);
+
+ bitmap.allocPixels();
+ if (!bitmap.isOpaque())
+ bitmap.eraseARGB(0, 0, 0, 0);
+ return SkNEW_ARGS(SkDevice, (bitmap));
+}
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 301c0e4..fb5e045 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -789,7 +789,7 @@ static bool map_radius(const SkMatrix& matrix, SkScalar* value) {
matrix.mapVectors(dst, src, 2);
SkScalar len0 = fast_len(dst[0]);
SkScalar len1 = fast_len(dst[1]);
- if (len0 < SK_Scalar1 && len1 < SK_Scalar1) {
+ if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
*value = SkScalarAve(len0, len1);
return true;
}
diff --git a/src/core/SkGraphics.cpp b/src/core/SkGraphics.cpp
index 65a16e2..40f0ea3 100644
--- a/src/core/SkGraphics.cpp
+++ b/src/core/SkGraphics.cpp
@@ -374,3 +374,15 @@ bool SkGraphics::SetFontCacheUsed(size_t usageInBytes) {
return SkGlyphCache::SetCacheUsed(usageInBytes);
}
+void SkGraphics::GetVersion(int32_t* major, int32_t* minor, int32_t* patch) {
+ if (major) {
+ *major = SKIA_VERSION_MAJOR;
+ }
+ if (minor) {
+ *minor = SKIA_VERSION_MINOR;
+ }
+ if (patch) {
+ *patch = SKIA_VERSION_PATCH;
+ }
+}
+
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index da818c4..40d3ae8 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -63,6 +63,7 @@ SkPaint::SkPaint() {
fStyle = kFill_Style;
fTextEncoding = kUTF8_TextEncoding;
fHinting = kNormal_Hinting;
+ fGenerationID = 0;
}
SkPaint::SkPaint(const SkPaint& src)
@@ -114,6 +115,7 @@ SkPaint& SkPaint::operator=(const SkPaint& src)
fLooper->safeUnref();
memcpy(this, &src, sizeof(src));
+ fGenerationID++;
return *this;
}
@@ -128,72 +130,117 @@ void SkPaint::reset()
SkPaint init;
*this = init;
+ fGenerationID++;
+}
+
+uint32_t SkPaint::getGenerationID() const {
+ return fGenerationID;
}
void SkPaint::setFlags(uint32_t flags)
{
- fFlags = flags;
+ if (fFlags != flags) {
+ fFlags = flags;
+ fGenerationID++;
+ }
}
void SkPaint::setAntiAlias(bool doAA)
{
- this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
+ if (doAA != isAntiAlias()) {
+ this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
+ fGenerationID++;
+ }
}
void SkPaint::setDither(bool doDither)
{
- this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
+ if (doDither != isDither()) {
+ this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
+ fGenerationID++;
+ }
}
void SkPaint::setSubpixelText(bool doSubpixel)
{
- this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
+ if (doSubpixel != isSubpixelText()) {
+ this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
+ fGenerationID++;
+ }
}
void SkPaint::setLCDRenderText(bool doLCDRender)
{
- this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
+ if (doLCDRender != isLCDRenderText()) {
+ this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
+ fGenerationID++;
+ }
}
void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText)
{
- this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
+ if (doEmbeddedBitmapText != isEmbeddedBitmapText()) {
+ this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
+ fGenerationID++;
+ }
}
void SkPaint::setLinearText(bool doLinearText)
{
- this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
+ if (doLinearText != isLinearText()) {
+ this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
+ fGenerationID++;
+ }
}
void SkPaint::setUnderlineText(bool doUnderline)
{
- this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
+ if (doUnderline != isUnderlineText()) {
+ this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
+ fGenerationID++;
+ }
}
void SkPaint::setStrikeThruText(bool doStrikeThru)
{
- this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
+ if (doStrikeThru != isStrikeThruText()) {
+ this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
+ fGenerationID++;
+ }
}
void SkPaint::setFakeBoldText(bool doFakeBold)
{
- this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
+ if (doFakeBold != isFakeBoldText()) {
+ this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
+ fGenerationID++;
+ }
}
void SkPaint::setDevKernText(bool doDevKern)
{
- this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
+ if (doDevKern != isDevKernText()) {
+ this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
+ fGenerationID++;
+ }
}
void SkPaint::setFilterBitmap(bool doFilter)
{
- this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag));
+ if (doFilter != isFilterBitmap()) {
+ this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag));
+ fGenerationID++;
+ }
}
void SkPaint::setStyle(Style style)
{
- if ((unsigned)style < kStyleCount)
- fStyle = style;
+ if ((unsigned)style < kStyleCount) {
+ if ((unsigned)style != fStyle) {
+ fStyle = style;
+ fGenerationID++;
+ }
+ }
#ifdef SK_DEBUG
else
SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
@@ -202,23 +249,38 @@ void SkPaint::setStyle(Style style)
void SkPaint::setColor(SkColor color)
{
- fColor = color;
+ if (color != fColor) {
+ fColor = color;
+ fGenerationID++;
+ }
}
void SkPaint::setAlpha(U8CPU a)
{
- fColor = SkColorSetARGB(a, SkColorGetR(fColor), SkColorGetG(fColor), SkColorGetB(fColor));
+ U8CPU oldA = SkColorGetA(fColor);
+ if (a != oldA) {
+ fColor = SkColorSetARGB(a, SkColorGetR(fColor), SkColorGetG(fColor), SkColorGetB(fColor));
+ fGenerationID++;
+ }
}
void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
{
+ SkColor oldColor = fColor;
fColor = SkColorSetARGB(a, r, g, b);
+ if (oldColor != fColor) {
+ fGenerationID++;
+ }
}
void SkPaint::setStrokeWidth(SkScalar width)
{
- if (width >= 0)
- fWidth = width;
+ if (width >= 0) {
+ if (width != fWidth) {
+ fWidth = width;
+ fGenerationID++;
+ }
+ }
#ifdef SK_DEBUG
else
SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
@@ -227,8 +289,12 @@ void SkPaint::setStrokeWidth(SkScalar width)
void SkPaint::setStrokeMiter(SkScalar limit)
{
- if (limit >= 0)
- fMiterLimit = limit;
+ if (limit >= 0) {
+ if (limit != fMiterLimit) {
+ fMiterLimit = limit;
+ fGenerationID++;
+ }
+ }
#ifdef SK_DEBUG
else
SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
@@ -237,8 +303,12 @@ void SkPaint::setStrokeMiter(SkScalar limit)
void SkPaint::setStrokeCap(Cap ct)
{
- if ((unsigned)ct < kCapCount)
- fCapType = SkToU8(ct);
+ if ((unsigned)ct < kCapCount) {
+ if ((unsigned)ct != fCapType) {
+ fCapType = SkToU8(ct);
+ fGenerationID++;
+ }
+ }
#ifdef SK_DEBUG
else
SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
@@ -247,8 +317,12 @@ void SkPaint::setStrokeCap(Cap ct)
void SkPaint::setStrokeJoin(Join jt)
{
- if ((unsigned)jt < kJoinCount)
- fJoinType = SkToU8(jt);
+ if ((unsigned)jt < kJoinCount) {
+ if ((unsigned)jt != fJoinType) {
+ fJoinType = SkToU8(jt);
+ fGenerationID++;
+ }
+ }
#ifdef SK_DEBUG
else
SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
@@ -259,8 +333,12 @@ void SkPaint::setStrokeJoin(Join jt)
void SkPaint::setTextAlign(Align align)
{
- if ((unsigned)align < kAlignCount)
- fTextAlign = SkToU8(align);
+ if ((unsigned)align < kAlignCount) {
+ if ((unsigned)align != fTextAlign) {
+ fTextAlign = SkToU8(align);
+ fGenerationID++;
+ }
+ }
#ifdef SK_DEBUG
else
SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
@@ -269,8 +347,12 @@ void SkPaint::setTextAlign(Align align)
void SkPaint::setTextSize(SkScalar ts)
{
- if (ts > 0)
- fTextSize = ts;
+ if (ts > 0) {
+ if (ts != fTextSize) {
+ fTextSize = ts;
+ fGenerationID++;
+ }
+ }
#ifdef SK_DEBUG
else
SkDebugf("SkPaint::setTextSize() called with non-positive value\n");
@@ -279,18 +361,28 @@ void SkPaint::setTextSize(SkScalar ts)
void SkPaint::setTextScaleX(SkScalar scaleX)
{
- fTextScaleX = scaleX;
+ if (scaleX != fTextScaleX) {
+ fTextScaleX = scaleX;
+ fGenerationID++;
+ }
}
void SkPaint::setTextSkewX(SkScalar skewX)
{
- fTextSkewX = skewX;
+ if (skewX != fTextSkewX) {
+ fTextSkewX = skewX;
+ fGenerationID++;
+ }
}
void SkPaint::setTextEncoding(TextEncoding encoding)
{
- if ((unsigned)encoding <= kGlyphID_TextEncoding)
- fTextEncoding = encoding;
+ if ((unsigned)encoding <= kGlyphID_TextEncoding) {
+ if ((unsigned)encoding != fTextEncoding) {
+ fTextEncoding = encoding;
+ fGenerationID++;
+ }
+ }
#ifdef SK_DEBUG
else
SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
@@ -302,18 +394,21 @@ void SkPaint::setTextEncoding(TextEncoding encoding)
SkTypeface* SkPaint::setTypeface(SkTypeface* font)
{
SkRefCnt_SafeAssign(fTypeface, font);
+ fGenerationID++;
return font;
}
SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r)
{
SkRefCnt_SafeAssign(fRasterizer, r);
+ fGenerationID++;
return r;
}
SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper)
{
SkRefCnt_SafeAssign(fLooper, looper);
+ fGenerationID++;
return looper;
}
@@ -322,6 +417,29 @@ SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper)
#include "SkGlyphCache.h"
#include "SkUtils.h"
+const SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text) {
+ SkAutoGlyphCache autoCache(*this, NULL);
+ SkGlyphCache* cache = autoCache.getCache();
+
+ return cache->getUnicharMetrics(text);
+}
+
+static void DetachDescProc(const SkDescriptor* desc, void* context)
+{
+ *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc);
+}
+
+const void* SkPaint::findImage(const SkGlyph& glyph) {
+ // See ::detachCache()
+ SkGlyphCache* cache;
+ descriptorProc(NULL, DetachDescProc, &cache, true);
+
+ const void* image = cache->findImage(glyph);
+
+ SkGlyphCache::AttachCache(cache);
+ return image;
+}
+
int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
uint16_t glyphs[]) const {
if (byteLength == 0) {
@@ -1330,11 +1448,15 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
void (*proc)(const SkDescriptor*, void*),
- void* context) const
+ void* context, bool ignoreGamma) const
{
SkScalerContext::Rec rec;
SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
+ if (ignoreGamma) {
+ rec.fFlags &= ~(SkScalerContext::kGammaForBlack_Flag |
+ SkScalerContext::kGammaForWhite_Flag);
+ }
size_t descSize = sizeof(rec);
int entryCount = 1;
@@ -1389,11 +1511,6 @@ void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
proc(desc, context);
}
-static void DetachDescProc(const SkDescriptor* desc, void* context)
-{
- *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc);
-}
-
SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const
{
SkGlyphCache* cache;
@@ -1548,18 +1665,27 @@ void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
SkShader* SkPaint::setShader(SkShader* shader)
{
+ if (shader != fShader) {
+ fGenerationID++;
+ }
SkRefCnt_SafeAssign(fShader, shader);
return shader;
}
SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter)
{
+ if (filter != fColorFilter) {
+ fGenerationID++;
+ }
SkRefCnt_SafeAssign(fColorFilter, filter);
return filter;
}
SkXfermode* SkPaint::setXfermode(SkXfermode* mode)
{
+ if (mode != fXfermode) {
+ fGenerationID++;
+ }
SkRefCnt_SafeAssign(fXfermode, mode);
return mode;
}
@@ -1567,17 +1693,24 @@ SkXfermode* SkPaint::setXfermode(SkXfermode* mode)
SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
SkSafeUnref(fXfermode);
fXfermode = SkXfermode::Create(mode);
+ fGenerationID++;
return fXfermode;
}
SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect)
{
+ if (effect != fPathEffect) {
+ fGenerationID++;
+ }
SkRefCnt_SafeAssign(fPathEffect, effect);
return effect;
}
SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter)
{
+ if (filter != fMaskFilter) {
+ fGenerationID++;
+ }
SkRefCnt_SafeAssign(fMaskFilter, filter);
return filter;
}
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 9c0b8af..62edb32 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -97,6 +97,7 @@ static void compute_pt_bounds(SkRect* bounds, const SkTDArray<SkPoint>& pts) {
SkPath::SkPath() : fBoundsIsDirty(true), fFillType(kWinding_FillType) {
fIsConvex = false;
+ fGenerationID = 0;
}
SkPath::SkPath(const SkPath& src) {
@@ -118,6 +119,7 @@ SkPath& SkPath::operator=(const SkPath& src) {
fFillType = src.fFillType;
fBoundsIsDirty = src.fBoundsIsDirty;
fIsConvex = src.fIsConvex;
+ fGenerationID++;
}
SkDEBUGCODE(this->validate();)
return *this;
@@ -140,14 +142,20 @@ void SkPath::swap(SkPath& other) {
SkTSwap<uint8_t>(fFillType, other.fFillType);
SkTSwap<uint8_t>(fBoundsIsDirty, other.fBoundsIsDirty);
SkTSwap<uint8_t>(fIsConvex, other.fIsConvex);
+ fGenerationID++;
}
}
+uint32_t SkPath::getGenerationID() const {
+ return fGenerationID;
+}
+
void SkPath::reset() {
SkDEBUGCODE(this->validate();)
fPts.reset();
fVerbs.reset();
+ fGenerationID++;
fBoundsIsDirty = true;
}
@@ -156,6 +164,7 @@ void SkPath::rewind() {
fPts.rewind();
fVerbs.rewind();
+ fGenerationID++;
fBoundsIsDirty = true;
}
@@ -212,6 +221,7 @@ void SkPath::setLastPt(SkScalar x, SkScalar y) {
this->moveTo(x, y);
} else {
fPts[count - 1].set(x, y);
+ fGenerationID++;
}
}
@@ -249,6 +259,7 @@ void SkPath::moveTo(SkScalar x, SkScalar y) {
}
pt->set(x, y);
+ fGenerationID++;
fBoundsIsDirty = true;
}
@@ -268,6 +279,7 @@ void SkPath::lineTo(SkScalar x, SkScalar y) {
fPts.append()->set(x, y);
*fVerbs.append() = kLine_Verb;
+ fGenerationID++;
fBoundsIsDirty = true;
}
@@ -290,6 +302,7 @@ void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
pts[1].set(x2, y2);
*fVerbs.append() = kQuad_Verb;
+ fGenerationID++;
fBoundsIsDirty = true;
}
@@ -313,6 +326,7 @@ void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
pts[2].set(x3, y3);
*fVerbs.append() = kCubic_Verb;
+ fGenerationID++;
fBoundsIsDirty = true;
}
@@ -334,6 +348,7 @@ void SkPath::close() {
case kQuad_Verb:
case kCubic_Verb:
*fVerbs.append() = kClose_Verb;
+ fGenerationID++;
break;
default:
// don't add a close if the prev wasn't a primitive
@@ -936,6 +951,7 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const {
matrix.mapRect(&dst->fBounds, fBounds);
dst->fBoundsIsDirty = false;
} else {
+ dst->fGenerationID++;
dst->fBoundsIsDirty = true;
}
@@ -1243,6 +1259,7 @@ void SkPath::unflatten(SkFlattenableReadBuffer& buffer) {
buffer.read(fPts.begin(), sizeof(SkPoint) * fPts.count());
buffer.read(fVerbs.begin(), fVerbs.count());
+ fGenerationID++;
fBoundsIsDirty = true;
SkDEBUGCODE(this->validate();)
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index f488565..c73e21c 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -528,6 +528,8 @@ void SkPicturePlayback::draw(SkCanvas& canvas) {
SkipClipRec skipRect, skipRegion, skipPath;
#endif
+ SkAutoMutexAcquire autoMutex(fDrawMutex);
+
TextContainer text;
fReader.rewind();
diff --git a/src/core/SkPicturePlayback.h b/src/core/SkPicturePlayback.h
index ae9641a..f5bf038 100644
--- a/src/core/SkPicturePlayback.h
+++ b/src/core/SkPicturePlayback.h
@@ -12,6 +12,7 @@
#include "SkRegion.h"
#include "SkPictureFlat.h"
#include "SkShape.h"
+#include "SkThread.h"
class SkPictureRecord;
class SkStream;
@@ -172,6 +173,7 @@ private:
SkRefCntPlayback fRCPlayback;
SkTypefacePlayback fTFPlayback;
SkFactoryPlayback* fFactoryPlayback;
+ SkMutex fDrawMutex;
};
#endif
diff --git a/src/core/SkRegion.cpp b/src/core/SkRegion.cpp
index 032dc81..a5a1555 100644
--- a/src/core/SkRegion.cpp
+++ b/src/core/SkRegion.cpp
@@ -783,7 +783,13 @@ static int operate( const SkRegion::RunType a_runs[],
SkRegion::RunType dst[],
SkRegion::Op op)
{
- const SkRegion::RunType sentinel = SkRegion::kRunTypeSentinel;
+ const SkRegion::RunType gSentinel[] = {
+ SkRegion::kRunTypeSentinel,
+ // just need a 2nd value, since spanRec.init() reads 2 values, even
+ // though if the first value is the sentinel, it ignores the 2nd value.
+ // w/o the 2nd value here, we might read uninitialized memory.
+ 0,
+ };
int a_top = *a_runs++;
int a_bot = *a_runs++;
@@ -803,8 +809,8 @@ static int operate( const SkRegion::RunType a_runs[],
while (a_bot < SkRegion::kRunTypeSentinel || b_bot < SkRegion::kRunTypeSentinel)
{
int top, bot SK_INIT_TO_AVOID_WARNING;
- const SkRegion::RunType* run0 = &sentinel;
- const SkRegion::RunType* run1 = &sentinel;
+ const SkRegion::RunType* run0 = gSentinel;
+ const SkRegion::RunType* run1 = gSentinel;
bool a_flush = false;
bool b_flush = false;
int inside;
@@ -854,7 +860,7 @@ static int operate( const SkRegion::RunType a_runs[],
}
if (top > prevBot)
- oper.addSpan(top, &sentinel, &sentinel);
+ oper.addSpan(top, gSentinel, gSentinel);
// if ((unsigned)(inside - oper.fMin) <= (unsigned)(oper.fMax - oper.fMin))
{
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 8d1531a..7ed77b2 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -315,10 +315,12 @@ void SkProcXfermode::xferA8(SK_RESTRICT SkAlpha dst[],
SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
: SkXfermode(buffer) {
fProc = (SkXfermodeProc)buffer.readFunctionPtr();
+ fMode = (Mode) buffer.readInt();
}
void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) {
buffer.writeFunctionPtr((void*)fProc);
+ buffer.writeInt(fMode);
}
///////////////////////////////////////////////////////////////////////////////
@@ -941,30 +943,36 @@ SkXfermode* SkXfermode::Create(Mode mode) {
SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
SkASSERT((unsigned)mode < kModeCount);
+ SkXfermode* xferMode = NULL;
switch (mode) {
case kClear_Mode:
- return SkNEW(SkClearXfermode);
+ xferMode = SkNEW(SkClearXfermode);
+ break;
case kSrc_Mode:
- return SkNEW(SkSrcXfermode);
+ xferMode = SkNEW(SkSrcXfermode);
+ break;
case kSrcOver_Mode:
return NULL;
case kDstIn_Mode:
- return SkNEW(SkDstInXfermode);
+ xferMode = SkNEW(SkDstInXfermode);
+ break;
case kDstOut_Mode:
- return SkNEW(SkDstOutXfermode);
+ xferMode = SkNEW(SkDstOutXfermode);
+ break;
// use the table
default: {
const ProcCoeff& rec = gProcCoeffs[mode];
if ((unsigned)rec.fSC < SkXfermode::kCoeffCount &&
(unsigned)rec.fDC < SkXfermode::kCoeffCount) {
- return SkNEW_ARGS(SkProcCoeffXfermode, (rec.fProc,
- rec.fSC,
- rec.fDC));
+ xferMode = SkNEW_ARGS(SkProcCoeffXfermode, (rec.fProc, rec.fSC, rec.fDC));
} else {
- return SkNEW_ARGS(SkProcXfermode, (rec.fProc));
+ xferMode = SkNEW_ARGS(SkProcXfermode, (rec.fProc));
}
+ break;
}
}
+ xferMode->fMode = mode;
+ return xferMode;
}
bool SkXfermode::IsMode(SkXfermode* xfer, Mode* mode) {
diff --git a/src/effects/SkBlurDrawLooper.cpp b/src/effects/SkBlurDrawLooper.cpp
index 6ad0136..6ad4451 100644
--- a/src/effects/SkBlurDrawLooper.cpp
+++ b/src/effects/SkBlurDrawLooper.cpp
@@ -52,10 +52,17 @@ void SkBlurDrawLooper::init(SkCanvas* canvas, SkPaint* paint)
bool SkBlurDrawLooper::next()
{
+ SkColor blurColor;
+ SkAlpha alpha;
switch (fState) {
case kBeforeEdge:
fSavedColor = fPaint->getColor();
- fPaint->setColor(fBlurColor);
+ blurColor = fBlurColor;
+ alpha = SkColorGetA(blurColor);
+ if (alpha == 255) {
+ blurColor = SkColorSetA(blurColor, fPaint->getAlpha());
+ }
+ fPaint->setColor(blurColor);
fPaint->setMaskFilter(fBlur);
fCanvas->save(SkCanvas::kMatrix_SaveFlag);
fCanvas->translate(fDx, fDy);
diff --git a/src/effects/SkPorterDuff.cpp b/src/effects/SkPorterDuff.cpp
index 58447ad..d0264ba 100644
--- a/src/effects/SkPorterDuff.cpp
+++ b/src/effects/SkPorterDuff.cpp
@@ -29,7 +29,8 @@ static const struct Pair {
MAKE_PAIR(Lighten),
MAKE_PAIR(Multiply),
MAKE_PAIR(Screen),
- { SkPorterDuff::kAdd_Mode, SkXfermode::kPlus_Mode }
+ { SkPorterDuff::kAdd_Mode, SkXfermode::kPlus_Mode },
+ MAKE_PAIR(Overlay),
};
static bool find_pdmode(SkXfermode::Mode src, SkPorterDuff::Mode* dst) {
diff --git a/src/gl/SkGLCanvas.cpp b/src/gl/SkGLCanvas.cpp
index f7bc96d..17e6016 100644
--- a/src/gl/SkGLCanvas.cpp
+++ b/src/gl/SkGLCanvas.cpp
@@ -1,180 +1,50 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#include "SkGLCanvas.h"
#include "SkGLDevice.h"
-#include "SkBlitter.h"
-#include "SkDraw.h"
-#include "SkDrawProcs.h"
-#include "SkGL.h"
-#include "SkGlyphCache.h"
-#include "SkTemplates.h"
-#include "SkUtils.h"
-#include "SkXfermode.h"
-
-#ifdef SK_GL_DEVICE_FBO
- #define USE_FBO_DEVICE
- #include "SkGLDevice_FBO.h"
-#else
- #define USE_SWLAYER_DEVICE
- #include "SkGLDevice_SWLayer.h"
-#endif
-
-// maximum number of entries in our texture cache (before purging)
-#define kTexCountMax_Default 256
-// maximum number of bytes used (by gl) for the texture cache (before purging)
-#define kTexSizeMax_Default (4 * 1024 * 1024)
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkGLCanvas::SkGLCanvas() {
- glEnable(GL_TEXTURE_2D);
- glEnable(GL_SCISSOR_TEST);
- glEnableClientState(GL_VERTEX_ARRAY);
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- fViewportSize.set(0, 0);
-}
-
-SkGLCanvas::~SkGLCanvas() {
- // call this now, while our override of restore() is in effect
- this->restoreToCount(1);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-bool SkGLCanvas::getViewport(SkIPoint* size) const {
- if (size) {
- *size = fViewportSize;
- }
- return true;
-}
-
-bool SkGLCanvas::setViewport(int width, int height) {
- fViewportSize.set(width, height);
-
- const bool isOpaque = false; // should this be a parameter to setViewport?
- const bool isForLayer = false; // viewport is the base layer
- SkDevice* device = this->createDevice(SkBitmap::kARGB_8888_Config, width,
- height, isOpaque, isForLayer);
- this->setDevice(device)->unref();
-
- return true;
-}
-
-SkDevice* SkGLCanvas::createDevice(SkBitmap::Config, int width, int height,
- bool isOpaque, bool isForLayer) {
- SkBitmap bitmap;
-
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
- bitmap.setIsOpaque(isOpaque);
-
-#ifdef USE_FBO_DEVICE
- return SkNEW_ARGS(SkGLDevice_FBO, (bitmap, isForLayer));
-#elif defined(USE_SWLAYER_DEVICE)
- if (isForLayer) {
- bitmap.allocPixels();
- if (!bitmap.isOpaque()) {
- bitmap.eraseColor(0);
- }
- return SkNEW_ARGS(SkGLDevice_SWLayer, (bitmap));
- } else {
- return SkNEW_ARGS(SkGLDevice, (bitmap, isForLayer));
- }
-#else
- return SkNEW_ARGS(SkGLDevice, (bitmap, isForLayer));
-#endif
-}
-///////////////////////////////////////////////////////////////////////////////
-
-#include "SkTextureCache.h"
-#include "SkThread.h"
-
-static SkMutex gTextureCacheMutex;
-static SkTextureCache gTextureCache(kTexCountMax_Default, kTexSizeMax_Default);
-
-SkGLDevice::TexCache* SkGLDevice::LockTexCache(const SkBitmap& bitmap,
- GLuint* name, SkPoint* size) {
- SkAutoMutexAcquire amc(gTextureCacheMutex);
-
- SkTextureCache::Entry* entry = gTextureCache.lock(bitmap);
- if (NULL != entry) {
- if (name) {
- *name = entry->name();
- }
- if (size) {
- *size = entry->texSize();
- }
- }
- return (TexCache*)entry;
-}
-
-void SkGLDevice::UnlockTexCache(TexCache* cache) {
- SkAutoMutexAcquire amc(gTextureCacheMutex);
- gTextureCache.unlock((SkTextureCache::Entry*)cache);
-}
-
-// public exposure of texture cache settings
+SkGLCanvas::SkGLCanvas() : SkCanvas(SkNEW(SkGLDeviceFactory)) {}
+// static
size_t SkGLCanvas::GetTextureCacheMaxCount() {
- SkAutoMutexAcquire amc(gTextureCacheMutex);
- return gTextureCache.getMaxCount();
-}
-
-size_t SkGLCanvas::GetTextureCacheMaxSize() {
- SkAutoMutexAcquire amc(gTextureCacheMutex);
- return gTextureCache.getMaxSize();
+ return SkGLDevice::GetTextureCacheMaxCount();
}
+// static
void SkGLCanvas::SetTextureCacheMaxCount(size_t count) {
- SkAutoMutexAcquire amc(gTextureCacheMutex);
- gTextureCache.setMaxCount(count);
+ SkGLDevice::SetTextureCacheMaxCount(count);
}
-void SkGLCanvas::SetTextureCacheMaxSize(size_t size) {
- SkAutoMutexAcquire amc(gTextureCacheMutex);
- gTextureCache.setMaxSize(size);
+// static
+size_t SkGLCanvas::GetTextureCacheMaxSize() {
+ return SkGLDevice::GetTextureCacheMaxSize();
}
-///////////////////////////////////////////////////////////////////////////////
-
-#include "SkGLTextCache.h"
-
-static bool deleteCachesProc(SkGlyphCache* cache, void* texturesAreValid) {
- void* auxData;
- if (cache->getAuxProcData(SkGLDevice::GlyphCacheAuxProc, &auxData)) {
- bool valid = texturesAreValid != NULL;
- SkGLTextCache* textCache = static_cast<SkGLTextCache*>(auxData);
- // call this before delete, in case valid is false
- textCache->deleteAllStrikes(valid);
- // now free the memory for the cache itself
- SkDELETE(textCache);
- // now remove the entry in the glyphcache (does not call the proc)
- cache->removeAuxProc(SkGLDevice::GlyphCacheAuxProc);
- }
- return false; // keep going
+// static
+void SkGLCanvas::SetTextureCacheMaxSize(size_t size) {
+ SkGLDevice::SetTextureCacheMaxSize(size);
}
+// static
void SkGLCanvas::DeleteAllTextures() {
- // free the textures in our cache
-
- gTextureCacheMutex.acquire();
- gTextureCache.deleteAllCaches(true);
- gTextureCacheMutex.release();
-
- // now free the textures in the font cache
-
- SkGlyphCache::VisitAllCaches(deleteCachesProc, reinterpret_cast<void*>(true));
+ SkGLDevice::DeleteAllTextures();
}
+// static
void SkGLCanvas::AbandonAllTextures() {
- // abandon the textures in our cache
-
- gTextureCacheMutex.acquire();
- gTextureCache.deleteAllCaches(false);
- gTextureCacheMutex.release();
-
- // abandon the textures in the font cache
-
- SkGlyphCache::VisitAllCaches(deleteCachesProc, reinterpret_cast<void*>(false));
+ SkGLDevice::AbandonAllTextures();
}
-
diff --git a/src/gl/SkGLDevice.cpp b/src/gl/SkGLDevice.cpp
index d839498..ad4377c 100644
--- a/src/gl/SkGLDevice.cpp
+++ b/src/gl/SkGLDevice.cpp
@@ -4,6 +4,19 @@
#include "SkRegion.h"
#include "SkThread.h"
+#ifdef SK_GL_DEVICE_FBO
+ #define USE_FBO_DEVICE
+ #include "SkGLDevice_FBO.h"
+#else
+ #define USE_SWLAYER_DEVICE
+ #include "SkGLDevice_SWLayer.h"
+#endif
+
+// maximum number of entries in our texture cache (before purging)
+#define kTexCountMax_Default 256
+// maximum number of bytes used (by gl) for the texture cache (before purging)
+#define kTexSizeMax_Default (4 * 1024 * 1024)
+
static void TRACE_DRAW(const char func[], SkGLDevice* device,
const SkDraw& draw) {
// SkDebugf("--- <%s> %p %p\n", func, canvas, draw.fDevice);
@@ -69,8 +82,39 @@ private:
///////////////////////////////////////////////////////////////////////////////
+SkDevice* SkGLDeviceFactory::newDevice(SkBitmap::Config config, int width,
+ int height, bool isOpaque,
+ bool isForLayer) {
+ SkBitmap bitmap;
+
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ bitmap.setIsOpaque(isOpaque);
+
+#ifdef USE_FBO_DEVICE
+ return SkNEW_ARGS(SkGLDevice_FBO, (bitmap, isForLayer));
+#elif defined(USE_SWLAYER_DEVICE)
+ if (isForLayer) {
+ bitmap.allocPixels();
+ if (!bitmap.isOpaque()) {
+ bitmap.eraseColor(0);
+ }
+ return SkNEW_ARGS(SkGLDevice_SWLayer, (bitmap));
+ } else {
+ return SkNEW_ARGS(SkGLDevice, (bitmap, isForLayer));
+ }
+#else
+ return SkNEW_ARGS(SkGLDevice, (bitmap, isForLayer));
+#endif
+}
+
SkGLDevice::SkGLDevice(const SkBitmap& bitmap, bool offscreen)
: SkDevice(bitmap), fClipIter(bitmap.height()) {
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_SCISSOR_TEST);
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
fDrawProcs = NULL;
}
@@ -811,3 +855,99 @@ void SkGLDevice::drawTextOnPath(const SkDraw& draw, const void* text,
SkGL_unimpl("drawTextOnPath");
}
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkTextureCache.h"
+#include "SkThread.h"
+
+static SkMutex gTextureCacheMutex;
+static SkTextureCache gTextureCache(kTexCountMax_Default, kTexSizeMax_Default);
+
+SkGLDevice::TexCache* SkGLDevice::LockTexCache(const SkBitmap& bitmap,
+ GLuint* name, SkPoint* size) {
+ SkAutoMutexAcquire amc(gTextureCacheMutex);
+
+ SkTextureCache::Entry* entry = gTextureCache.lock(bitmap);
+ if (NULL != entry) {
+ if (name) {
+ *name = entry->name();
+ }
+ if (size) {
+ *size = entry->texSize();
+ }
+ }
+ return (TexCache*)entry;
+}
+
+void SkGLDevice::UnlockTexCache(TexCache* cache) {
+ SkAutoMutexAcquire amc(gTextureCacheMutex);
+ gTextureCache.unlock((SkTextureCache::Entry*)cache);
+}
+
+// public exposure of texture cache settings
+
+size_t SkGLDevice::GetTextureCacheMaxCount() {
+ SkAutoMutexAcquire amc(gTextureCacheMutex);
+ return gTextureCache.getMaxCount();
+}
+
+size_t SkGLDevice::GetTextureCacheMaxSize() {
+ SkAutoMutexAcquire amc(gTextureCacheMutex);
+ return gTextureCache.getMaxSize();
+}
+
+void SkGLDevice::SetTextureCacheMaxCount(size_t count) {
+ SkAutoMutexAcquire amc(gTextureCacheMutex);
+ gTextureCache.setMaxCount(count);
+}
+
+void SkGLDevice::SetTextureCacheMaxSize(size_t size) {
+ SkAutoMutexAcquire amc(gTextureCacheMutex);
+ gTextureCache.setMaxSize(size);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkGLTextCache.h"
+
+static bool deleteCachesProc(SkGlyphCache* cache, void* texturesAreValid) {
+ void* auxData;
+ if (cache->getAuxProcData(SkGLDevice::GlyphCacheAuxProc, &auxData)) {
+ bool valid = texturesAreValid != NULL;
+ SkGLTextCache* textCache = static_cast<SkGLTextCache*>(auxData);
+ // call this before delete, in case valid is false
+ textCache->deleteAllStrikes(valid);
+ // now free the memory for the cache itself
+ SkDELETE(textCache);
+ // now remove the entry in the glyphcache (does not call the proc)
+ cache->removeAuxProc(SkGLDevice::GlyphCacheAuxProc);
+ }
+ return false; // keep going
+}
+
+void SkGLDevice::DeleteAllTextures() {
+ // free the textures in our cache
+
+ gTextureCacheMutex.acquire();
+ gTextureCache.deleteAllCaches(true);
+ gTextureCacheMutex.release();
+
+ // now free the textures in the font cache
+
+ SkGlyphCache::VisitAllCaches(deleteCachesProc, reinterpret_cast<void*>(true)
+);
+}
+
+void SkGLDevice::AbandonAllTextures() {
+ // abandon the textures in our cache
+
+ gTextureCacheMutex.acquire();
+ gTextureCache.deleteAllCaches(false);
+ gTextureCacheMutex.release();
+
+ // abandon the textures in the font cache
+
+ SkGlyphCache::VisitAllCaches(deleteCachesProc, reinterpret_cast<void*>(false
+));
+}
+
diff --git a/src/gl/SkGLDevice.h b/src/gl/SkGLDevice.h
index 0fc9e47..a939b07 100644
--- a/src/gl/SkGLDevice.h
+++ b/src/gl/SkGLDevice.h
@@ -5,6 +5,18 @@
#include "SkGL.h"
#include "SkRegion.h"
+#ifdef SK_BUILD_FOR_MAC
+ #include <OpenGL/gl.h>
+#elif defined(ANDROID)
+ #include <GLES/gl.h>
+#endif
+
+class SkGLDeviceFactory : public SkDeviceFactory {
+public:
+ virtual SkDevice* newDevice(SkBitmap::Config config, int width, int height,
+ bool isOpaque, bool isForLayer);
+};
+
struct SkGLDrawProcs;
class SkGLDevice : public SkDevice {
@@ -12,6 +24,12 @@ public:
SkGLDevice(const SkBitmap& bitmap, bool offscreen);
virtual ~SkGLDevice();
+ virtual SkDeviceFactory* getDeviceFactory() {
+ return SkNEW(SkGLDeviceFactory);
+ }
+
+ virtual uint32_t getDeviceCapabilities() { return kGL_Capability; }
+
// used to identify GLTextCache data in the glyphcache
static void GlyphCacheAuxProc(void* data);
@@ -63,6 +81,27 @@ public:
virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
const SkPaint&);
+ // settings for the global texture cache
+
+ static size_t GetTextureCacheMaxCount();
+ static void SetTextureCacheMaxCount(size_t count);
+
+ static size_t GetTextureCacheMaxSize();
+ static void SetTextureCacheMaxSize(size_t size);
+
+ /** Call glDeleteTextures for all textures (including those for text)
+ This should be called while the gl-context is still valid. Its purpose
+ is to free up gl resources. Note that if a bitmap or text is drawn after
+ this call, new caches will be created.
+ */
+ static void DeleteAllTextures();
+
+ /** Forget all textures without calling delete (including those for text).
+ This should be called if the gl-context has changed, and the texture
+ IDs that have been cached are no longer valid.
+ */
+ static void AbandonAllTextures();
+
protected:
/** Return the current glmatrix, from a previous call to setMatrixClip */
const SkMatrix& matrix() const { return fMatrix; }
diff --git a/src/images/SkFlipPixelRef.cpp b/src/images/SkFlipPixelRef.cpp
index 6f96b03..39e1a12 100644
--- a/src/images/SkFlipPixelRef.cpp
+++ b/src/images/SkFlipPixelRef.cpp
@@ -125,4 +125,3 @@ void SkFlipPixelRef::CopyBitsFromAddr(const SkBitmap& dst, const SkRegion& clip,
iter.next();
}
}
-
diff --git a/src/images/SkImageDecoder_Factory.cpp b/src/images/SkImageDecoder_Factory.cpp
index bd81d1f..e7c71e5 100644
--- a/src/images/SkImageDecoder_Factory.cpp
+++ b/src/images/SkImageDecoder_Factory.cpp
@@ -24,10 +24,15 @@ typedef SkTRegistry<SkImageDecoder*, SkStream*> DecodeReg;
template DecodeReg* DecodeReg::gHead;
+#ifdef SK_ENABLE_LIBPNG
+ extern SkImageDecoder* sk_libpng_dfactory(SkStream*);
+#endif
+
SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
+ SkImageDecoder* codec = NULL;
const DecodeReg* curr = DecodeReg::Head();
while (curr) {
- SkImageDecoder* codec = curr->factory()(stream);
+ codec = curr->factory()(stream);
// we rewind here, because we promise later when we call "decode", that
// the stream will be at its beginning.
stream->rewind();
@@ -36,6 +41,13 @@ SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
}
curr = curr->next();
}
+#ifdef SK_ENABLE_LIBPNG
+ codec = sk_libpng_dfactory(stream);
+ stream->rewind();
+ if (codec) {
+ return codec;
+ }
+#endif
return NULL;
}
diff --git a/src/images/SkImageDecoder_libico.cpp b/src/images/SkImageDecoder_libico.cpp
index ef5b7ac..52e9e4f 100644
--- a/src/images/SkImageDecoder_libico.cpp
+++ b/src/images/SkImageDecoder_libico.cpp
@@ -351,7 +351,7 @@ static void editPixelBit24(const int pixelNo, const unsigned char* buf,
int alphaBit = (alphaByte & m) >> shift;
//alphaBit == 1 => alpha = 0
int alpha = (alphaBit-1) & 0xFF;
- *address = SkPackARGB32(alpha, red & alpha, green & alpha, blue & alpha);
+ *address = SkPreMultiplyARGB(alpha, red, green, blue);
}
static void editPixelBit32(const int pixelNo, const unsigned char* buf,
@@ -364,7 +364,7 @@ static void editPixelBit32(const int pixelNo, const unsigned char* buf,
int red = readByte(buf, xorOffset + 4*pixelNo + 2);
int alphaBit = (alphaByte & m) >> shift;
int alpha = readByte(buf, xorOffset + 4*pixelNo + 3) & ((alphaBit-1)&0xFF);
- *address = SkPackARGB32(alpha, red & alpha, green & alpha, blue & alpha);
+ *address = SkPreMultiplyARGB(alpha, red, green, blue);
}
/////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index e3aefea..dc6ac5b 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -264,13 +264,9 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
if (config == SkBitmap::kARGB_8888_Config) {
cinfo.out_color_space = JCS_RGBA_8888;
} else if (config == SkBitmap::kRGB_565_Config) {
- if (sampleSize == 1) {
- // SkScaledBitmapSampler can't handle RGB_565 yet,
- // so don't even try.
- cinfo.out_color_space = JCS_RGB_565;
- if (this->getDitherImage()) {
- cinfo.dither_mode = JDITHER_ORDERED;
- }
+ cinfo.out_color_space = JCS_RGB_565;
+ if (this->getDitherImage()) {
+ cinfo.dither_mode = JDITHER_ORDERED;
}
}
#endif
@@ -360,8 +356,8 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
#ifdef ANDROID_RGB
} else if (JCS_RGBA_8888 == cinfo.out_color_space) {
sc = SkScaledBitmapSampler::kRGBX;
- //} else if (JCS_RGB_565 == cinfo.out_color_space) {
- // sc = SkScaledBitmapSampler::kRGB_565;
+ } else if (JCS_RGB_565 == cinfo.out_color_space) {
+ sc = SkScaledBitmapSampler::kRGB_565;
#endif
} else if (1 == cinfo.out_color_components &&
JCS_GRAYSCALE == cinfo.out_color_space) {
@@ -532,18 +528,18 @@ bool SkJPEGImageDecoder::onDecodeRegion(SkBitmap* bm, SkIRect region) {
config != SkBitmap::kRGB_565_Config) {
config = SkBitmap::kARGB_8888_Config;
}
+
+ /* default format is RGB */
+ cinfo->out_color_space = JCS_RGB;
+
#ifdef ANDROID_RGB
cinfo->dither_mode = JDITHER_NONE;
if (config == SkBitmap::kARGB_8888_Config) {
cinfo->out_color_space = JCS_RGBA_8888;
} else if (config == SkBitmap::kRGB_565_Config) {
- if (requestedSampleSize == 1) {
- // SkScaledBitmapSampler can't handle RGB_565 yet,
- // so don't even try.
- cinfo->out_color_space = JCS_RGB_565;
- if (this->getDitherImage()) {
- cinfo->dither_mode = JDITHER_ORDERED;
- }
+ cinfo->out_color_space = JCS_RGB_565;
+ if (this->getDitherImage()) {
+ cinfo->dither_mode = JDITHER_ORDERED;
}
}
#endif
@@ -606,6 +602,8 @@ bool SkJPEGImageDecoder::onDecodeRegion(SkBitmap* bm, SkIRect region) {
#ifdef ANDROID_RGB
} else if (JCS_RGBA_8888 == cinfo->out_color_space) {
sc = SkScaledBitmapSampler::kRGBX;
+ } else if (JCS_RGB_565 == cinfo->out_color_space) {
+ sc = SkScaledBitmapSampler::kRGB_565;
#endif
} else if (1 == cinfo->out_color_components &&
JCS_GRAYSCALE == cinfo->out_color_space) {
diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp
index 2b6a28e..e550767 100644
--- a/src/images/SkImageDecoder_libpng.cpp
+++ b/src/images/SkImageDecoder_libpng.cpp
@@ -62,10 +62,10 @@ public:
delete index;
}
}
- virtual bool buildTileIndex(SkStream *stream,
- int *width, int *height, bool isShareable);
protected:
+ virtual bool onBuildTileIndex(SkStream *stream,
+ int *width, int *height);
virtual bool onDecodeRegion(SkBitmap* bitmap, SkIRect rect);
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
@@ -419,33 +419,13 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
return true;
}
-bool SkPNGImageDecoder::buildTileIndex(SkStream* sk_stream,
- int *width, int *height, bool isShareable) {
+bool SkPNGImageDecoder::onBuildTileIndex(SkStream* sk_stream, int *width,
+ int *height) {
png_structp png_ptr;
png_infop info_ptr;
this->index = new SkPNGImageIndex();
- if (!isShareable) {
- size_t len, inputLen = 0;
- size_t bufferSize = 4096;
- void *tmp = sk_malloc_throw(bufferSize);
-
- while ((len = sk_stream->read((char*) tmp + inputLen,
- bufferSize - inputLen)) != 0) {
- inputLen += len;
- if (inputLen == bufferSize) {
- bufferSize *= 2;
- tmp = sk_realloc_throw(tmp, bufferSize);
- }
- }
- tmp = sk_realloc_throw(tmp, inputLen);
-
- SkMemoryStream *mem_stream = new SkMemoryStream(tmp, inputLen, true);
- this->index->inputStream = mem_stream;
- sk_stream = mem_stream;
- }
-
if (onDecodeInit(sk_stream, &png_ptr, &info_ptr) == false) {
return false;
}
@@ -1148,7 +1128,12 @@ bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap,
#include "SkTRegistry.h"
-static SkImageDecoder* DFactory(SkStream* stream) {
+#ifdef SK_ENABLE_LIBPNG
+ SkImageDecoder* sk_libpng_dfactory(SkStream*);
+ SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type);
+#endif
+
+SkImageDecoder* sk_libpng_dfactory(SkStream* stream) {
char buf[PNG_BYTES_TO_CHECK];
if (stream->read(buf, PNG_BYTES_TO_CHECK) == PNG_BYTES_TO_CHECK &&
!png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) {
@@ -1157,9 +1142,9 @@ static SkImageDecoder* DFactory(SkStream* stream) {
return NULL;
}
-static SkImageEncoder* EFactory(SkImageEncoder::Type t) {
+SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL;
}
-static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(EFactory);
-static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(DFactory);
+static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efactory);
+static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory);
diff --git a/src/images/SkImageEncoder_Factory.cpp b/src/images/SkImageEncoder_Factory.cpp
index d673167..0bb4d1a 100644
--- a/src/images/SkImageEncoder_Factory.cpp
+++ b/src/images/SkImageEncoder_Factory.cpp
@@ -21,15 +21,24 @@ typedef SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> EncodeReg;
template EncodeReg* EncodeReg::gHead;
+#ifdef SK_ENABLE_LIBPNG
+ extern SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type);
+#endif
+
SkImageEncoder* SkImageEncoder::Create(Type t) {
+ SkImageEncoder* codec = NULL;
const EncodeReg* curr = EncodeReg::Head();
while (curr) {
- SkImageEncoder* codec = curr->factory()(t);
- if (codec) {
+ if ((codec = curr->factory()(t)) != NULL) {
return codec;
}
curr = curr->next();
}
+#ifdef SK_ENABLE_LIBPNG
+ if ((codec = sk_libpng_efactory(t)) != NULL) {
+ return codec;
+ }
+#endif
return NULL;
}
diff --git a/src/images/SkImageRef_GlobalPool.cpp b/src/images/SkImageRef_GlobalPool.cpp
index 33a3c46..1f44a84 100644
--- a/src/images/SkImageRef_GlobalPool.cpp
+++ b/src/images/SkImageRef_GlobalPool.cpp
@@ -80,4 +80,3 @@ void SkImageRef_GlobalPool::DumpPool() {
SkAutoMutexAcquire ac(gImageRefMutex);
gGlobalImageRefPool.dump();
}
-
diff --git a/src/images/SkScaledBitmapSampler.cpp b/src/images/SkScaledBitmapSampler.cpp
index 3ba38f7..32b78ef 100644
--- a/src/images/SkScaledBitmapSampler.cpp
+++ b/src/images/SkScaledBitmapSampler.cpp
@@ -93,6 +93,18 @@ static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
return false;
}
+static bool Sample_D565_D565(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int, const SkPMColor[]) {
+ uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+ uint16_t* SK_RESTRICT castedSrc = (uint16_t*) src;
+ for (int x = 0; x < width; x++) {
+ dst[x] = castedSrc[0];
+ castedSrc += deltaSrc >> 1;
+ }
+ return false;
+}
+
static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
int width, int deltaSrc, int y, const SkPMColor[]) {
@@ -335,21 +347,25 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
Sample_RGBx_D8888, Sample_RGBx_D8888,
Sample_RGBA_D8888, Sample_RGBA_D8888,
Sample_Index_D8888, Sample_Index_D8888,
+ NULL, NULL,
// 565 (no alpha distinction)
Sample_Gray_D565, Sample_Gray_D565_D,
Sample_RGBx_D565, Sample_RGBx_D565_D,
Sample_RGBx_D565, Sample_RGBx_D565_D,
Sample_Index_D565, Sample_Index_D565_D,
+ Sample_D565_D565, Sample_D565_D565,
// 4444
Sample_Gray_D4444, Sample_Gray_D4444_D,
Sample_RGBx_D4444, Sample_RGBx_D4444_D,
Sample_RGBA_D4444, Sample_RGBA_D4444_D,
Sample_Index_D4444, Sample_Index_D4444_D,
+ NULL, NULL,
// Index8
NULL, NULL,
NULL, NULL,
NULL, NULL,
Sample_Index_DI, Sample_Index_DI,
+ NULL, NULL,
};
fCTable = ctable;
@@ -379,6 +395,10 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
fSrcPixelSize = 1;
index += 6;
break;
+ case SkScaledBitmapSampler::kRGB_565:
+ fSrcPixelSize = 2;
+ index += 8;
+ break;
default:
return false;
}
@@ -388,13 +408,13 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
index += 0;
break;
case SkBitmap::kRGB_565_Config:
- index += 8;
+ index += 10;
break;
case SkBitmap::kARGB_4444_Config:
- index += 16;
+ index += 20;
break;
case SkBitmap::kIndex8_Config:
- index += 24;
+ index += 30;
break;
default:
return false;
diff --git a/src/images/SkScaledBitmapSampler.h b/src/images/SkScaledBitmapSampler.h
index 84a75ba..43f1669 100644
--- a/src/images/SkScaledBitmapSampler.h
+++ b/src/images/SkScaledBitmapSampler.h
@@ -21,7 +21,8 @@ public:
kIndex, // 1 byte per pixel
kRGB, // 3 bytes per pixel
kRGBX, // 4 byes per pixel (ignore 4th)
- kRGBA // 4 bytes per pixel
+ kRGBA, // 4 bytes per pixel
+ kRGB_565 // 2 bytes per pixel
};
// Given a dst bitmap (with pixels already allocated) and a src-config,
diff --git a/src/ports/SkImageRef_ashmem.cpp b/src/ports/SkImageRef_ashmem.cpp
index a904bae..5dd3a59 100644
--- a/src/ports/SkImageRef_ashmem.cpp
+++ b/src/ports/SkImageRef_ashmem.cpp
@@ -1,5 +1,6 @@
#include "SkImageRef_ashmem.h"
#include "SkImageDecoder.h"
+#include "SkFlattenable.h"
#include "SkThread.h"
#include <sys/mman.h>
@@ -201,3 +202,36 @@ void SkImageRef_ashmem::onUnlockPixels() {
fBitmap.setPixels(NULL, NULL);
}
+void SkImageRef_ashmem::flatten(SkFlattenableWriteBuffer& buffer) const {
+ this->INHERITED::flatten(buffer);
+ const char* uri = getURI();
+ if (uri) {
+ size_t len = strlen(uri);
+ buffer.write32(len);
+ buffer.writePad(uri, len);
+ } else {
+ buffer.write32(0);
+ }
+}
+
+SkImageRef_ashmem::SkImageRef_ashmem(SkFlattenableReadBuffer& buffer)
+ : INHERITED(buffer) {
+ fRec.fFD = -1;
+ fRec.fAddr = NULL;
+ fRec.fSize = 0;
+ fRec.fPinned = false;
+ fCT = NULL;
+ size_t length = buffer.readU32();
+ if (length) {
+ char* buf = (char*) malloc(length);
+ buffer.read(buf, length);
+ setURI(buf, length);
+ }
+}
+
+SkPixelRef* SkImageRef_ashmem::Create(SkFlattenableReadBuffer& buffer) {
+ return SkNEW_ARGS(SkImageRef_ashmem, (buffer));
+}
+
+static SkPixelRef::Registrar reg("SkImageRef_ashmem",
+ SkImageRef_ashmem::Create);
diff --git a/src/ports/SkImageRef_ashmem.h b/src/ports/SkImageRef_ashmem.h
index 193a01d..2c485e3 100644
--- a/src/ports/SkImageRef_ashmem.h
+++ b/src/ports/SkImageRef_ashmem.h
@@ -15,6 +15,13 @@ public:
SkImageRef_ashmem(SkStream*, SkBitmap::Config, int sampleSize = 1);
virtual ~SkImageRef_ashmem();
+ // overrides
+ virtual void flatten(SkFlattenableWriteBuffer&) const;
+ virtual Factory getFactory() const {
+ return Create;
+ }
+ static SkPixelRef* Create(SkFlattenableReadBuffer&);
+
protected:
virtual bool onDecode(SkImageDecoder* codec, SkStream* stream,
SkBitmap* bitmap, SkBitmap::Config config,
@@ -24,6 +31,7 @@ protected:
virtual void onUnlockPixels();
private:
+ SkImageRef_ashmem(SkFlattenableReadBuffer&);
void closeFD();
SkColorTable* fCT;
diff --git a/src/utils/SkCullPoints.cpp b/src/utils/SkCullPoints.cpp
index 23d00b6..03bfa99 100644
--- a/src/utils/SkCullPoints.cpp
+++ b/src/utils/SkCullPoints.cpp
@@ -18,8 +18,7 @@
#include "SkCullPoints.h"
#include "Sk64.h"
-static bool cross_product_is_neg(const SkIPoint& v, int dx, int dy)
-{
+static bool cross_product_is_neg(const SkIPoint& v, int dx, int dy) {
#if 0
return v.fX * dy - v.fY * dx < 0;
#else
@@ -32,19 +31,20 @@ static bool cross_product_is_neg(const SkIPoint& v, int dx, int dy)
#endif
}
-bool SkCullPoints::sect_test(int x0, int y0, int x1, int y1) const
-{
+bool SkCullPoints::sect_test(int x0, int y0, int x1, int y1) const {
const SkIRect& r = fR;
- if (x0 < r.fLeft && x1 < r.fLeft ||
- x0 > r.fRight && x1 > r.fRight ||
- y0 < r.fTop && y1 < r.fTop ||
- y0 > r.fBottom && y1 > r.fBottom)
+ if ((x0 < r.fLeft && x1 < r.fLeft) ||
+ (x0 > r.fRight && x1 > r.fRight) ||
+ (y0 < r.fTop && y1 < r.fTop) ||
+ (y0 > r.fBottom && y1 > r.fBottom)) {
return false;
+ }
// since the crossprod test is a little expensive, check for easy-in cases first
- if (r.contains(x0, y0) || r.contains(x1, y1))
+ if (r.contains(x0, y0) || r.contains(x1, y1)) {
return true;
+ }
// At this point we're not sure, so we do a crossprod test
SkIPoint vec;
@@ -53,16 +53,14 @@ bool SkCullPoints::sect_test(int x0, int y0, int x1, int y1) const
vec.set(x1 - x0, y1 - y0);
bool isNeg = cross_product_is_neg(vec, x0 - rAsQuad[0].fX, y0 - rAsQuad[0].fY);
for (int i = 1; i < 4; i++) {
- if (cross_product_is_neg(vec, x0 - rAsQuad[i].fX, y0 - rAsQuad[i].fY) != isNeg)
- {
+ if (cross_product_is_neg(vec, x0 - rAsQuad[i].fX, y0 - rAsQuad[i].fY) != isNeg) {
return true;
}
}
return false; // we didn't intersect
}
-static void toQuad(const SkIRect& r, SkIPoint quad[4])
-{
+static void toQuad(const SkIRect& r, SkIPoint quad[4]) {
SkASSERT(quad);
quad[0].set(r.fLeft, r.fTop);
@@ -71,34 +69,29 @@ static void toQuad(const SkIRect& r, SkIPoint quad[4])
quad[3].set(r.fLeft, r.fBottom);
}
-SkCullPoints::SkCullPoints()
-{
+SkCullPoints::SkCullPoints() {
SkIRect r;
r.setEmpty();
this->reset(r);
}
-SkCullPoints::SkCullPoints(const SkIRect& r)
-{
+SkCullPoints::SkCullPoints(const SkIRect& r) {
this->reset(r);
}
-void SkCullPoints::reset(const SkIRect& r)
-{
+void SkCullPoints::reset(const SkIRect& r) {
fR = r;
toQuad(fR, fAsQuad);
fPrevPt.set(0, 0);
fPrevResult = kNo_Result;
}
-void SkCullPoints::moveTo(int x, int y)
-{
+void SkCullPoints::moveTo(int x, int y) {
fPrevPt.set(x, y);
fPrevResult = kNo_Result; // so we trigger a movetolineto later
}
-SkCullPoints::LineToResult SkCullPoints::lineTo(int x, int y, SkIPoint line[])
-{
+SkCullPoints::LineToResult SkCullPoints::lineTo(int x, int y, SkIPoint line[]) {
SkASSERT(line != NULL);
LineToResult result = kNo_Result;
@@ -108,15 +101,15 @@ SkCullPoints::LineToResult SkCullPoints::lineTo(int x, int y, SkIPoint line[])
// need to upgrade sect_test to chop the result
// and to correctly return kLineTo_Result when the result is connected
// to the previous call-out
- if (this->sect_test(x0, y0, x, y))
- {
+ if (this->sect_test(x0, y0, x, y)) {
line[0].set(x0, y0);
line[1].set(x, y);
- if (fPrevResult != kNo_Result && fPrevPt.equals(x0, y0))
+ if (fPrevResult != kNo_Result && fPrevPt.equals(x0, y0)) {
result = kLineTo_Result;
- else
+ } else {
result = kMoveToLineTo_Result;
+ }
}
fPrevPt.set(x, y);
@@ -130,28 +123,23 @@ SkCullPoints::LineToResult SkCullPoints::lineTo(int x, int y, SkIPoint line[])
#include "SkPath.h"
SkCullPointsPath::SkCullPointsPath()
- : fCP(), fPath(NULL)
-{
+ : fCP(), fPath(NULL) {
}
SkCullPointsPath::SkCullPointsPath(const SkIRect& r, SkPath* dst)
- : fCP(r), fPath(dst)
-{
+ : fCP(r), fPath(dst) {
}
-void SkCullPointsPath::reset(const SkIRect& r, SkPath* dst)
-{
+void SkCullPointsPath::reset(const SkIRect& r, SkPath* dst) {
fCP.reset(r);
fPath = dst;
}
-
-void SkCullPointsPath::moveTo(int x, int y)
-{
+
+void SkCullPointsPath::moveTo(int x, int y) {
fCP.moveTo(x, y);
}
-void SkCullPointsPath::lineTo(int x, int y)
-{
+void SkCullPointsPath::lineTo(int x, int y) {
SkIPoint pts[2];
switch (fCP.lineTo(x, y, pts)) {
diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp
index 737307c..4ff7a50 100644
--- a/src/utils/SkDumpCanvas.cpp
+++ b/src/utils/SkDumpCanvas.cpp
@@ -121,8 +121,7 @@ static void toString(const SkBitmap& bm, SkString* str) {
}
static void toString(const void* text, size_t len, SkPaint::TextEncoding enc,
- SkString* str, const SkPaint& paint,
- const SkScalar xpos[] = NULL) {
+ SkString* str) {
switch (enc) {
case SkPaint::kUTF8_TextEncoding:
str->printf("\"%.*s\"%s", SkMax32(len, 32), text,
@@ -132,21 +131,9 @@ static void toString(const void* text, size_t len, SkPaint::TextEncoding enc,
str->printf("\"%.*S\"%s", SkMax32(len, 32), text,
len > 64 ? "..." : "");
break;
- case SkPaint::kGlyphID_TextEncoding: {
- const uint16_t* glyphs = (const uint16_t*)text;
- const int max = 32;
- SkUnichar uni[max];
- int count = SkMin32(len >> 1, max);
- paint.glyphsToUnichars(glyphs, count, uni);
- str->append("\"");
- for (int i = 0; i < count; i++) {
- str->appendUnichar(uni[i]);
- }
- if ((size_t)count < (len >> 1)) {
- str->append("...");
- }
- str->append("\"");
- } break;
+ case SkPaint::kGlyphID_TextEncoding:
+ str->set("<glyphs>");
+ break;
}
}
@@ -331,7 +318,7 @@ void SkDumpCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
void SkDumpCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
SkScalar y, const SkPaint& paint) {
SkString str;
- toString(text, byteLength, paint.getTextEncoding(), &str, paint);
+ toString(text, byteLength, paint.getTextEncoding(), &str);
this->dump(kDrawText_Verb, &paint, "drawText(%s [%d] %g %g)", str.c_str(),
byteLength, SkScalarToFloat(x), SkScalarToFloat(y));
}
@@ -339,7 +326,7 @@ void SkDumpCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
void SkDumpCanvas::drawPosText(const void* text, size_t byteLength,
const SkPoint pos[], const SkPaint& paint) {
SkString str;
- toString(text, byteLength, paint.getTextEncoding(), &str, paint);
+ toString(text, byteLength, paint.getTextEncoding(), &str);
this->dump(kDrawText_Verb, &paint, "drawPosText(%s [%d] %g %g ...)",
str.c_str(), byteLength, SkScalarToFloat(pos[0].fX),
SkScalarToFloat(pos[0].fY));
@@ -349,7 +336,7 @@ void SkDumpCanvas::drawPosTextH(const void* text, size_t byteLength,
const SkScalar xpos[], SkScalar constY,
const SkPaint& paint) {
SkString str;
- toString(text, byteLength, paint.getTextEncoding(), &str, paint, xpos);
+ toString(text, byteLength, paint.getTextEncoding(), &str);
this->dump(kDrawText_Verb, &paint, "drawPosTextH(%s [%d] %g %g ...)",
str.c_str(), byteLength, SkScalarToFloat(xpos[0]),
SkScalarToFloat(constY));
@@ -359,7 +346,7 @@ void SkDumpCanvas::drawTextOnPath(const void* text, size_t byteLength,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint) {
SkString str;
- toString(text, byteLength, paint.getTextEncoding(), &str, paint);
+ toString(text, byteLength, paint.getTextEncoding(), &str);
this->dump(kDrawText_Verb, &paint, "drawTextOnPath(%s [%d])",
str.c_str(), byteLength);
}
diff --git a/src/utils/SkNinePatch.cpp b/src/utils/SkNinePatch.cpp
index 3d85edc..0b601eb 100644
--- a/src/utils/SkNinePatch.cpp
+++ b/src/utils/SkNinePatch.cpp
@@ -235,15 +235,27 @@ static void drawNineViaRects(SkCanvas* canvas, const SkRect& dst,
const int32_t srcY[4] = {
0, margins.fTop, bitmap.height() - margins.fBottom, bitmap.height()
};
- const SkScalar dstX[4] = {
+ SkScalar dstX[4] = {
dst.fLeft, dst.fLeft + SkIntToScalar(margins.fLeft),
dst.fRight - SkIntToScalar(margins.fRight), dst.fRight
};
- const SkScalar dstY[4] = {
+ SkScalar dstY[4] = {
dst.fTop, dst.fTop + SkIntToScalar(margins.fTop),
dst.fBottom - SkIntToScalar(margins.fBottom), dst.fBottom
};
-
+
+ if (dstX[1] > dstX[2]) {
+ dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * SkIntToScalar(margins.fLeft) /
+ (SkIntToScalar(margins.fLeft) + SkIntToScalar(margins.fRight));
+ dstX[2] = dstX[1];
+ }
+
+ if (dstY[1] > dstY[2]) {
+ dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * SkIntToScalar(margins.fTop) /
+ (SkIntToScalar(margins.fTop) + SkIntToScalar(margins.fBottom));
+ dstY[2] = dstY[1];
+ }
+
SkIRect s;
SkRect d;
for (int y = 0; y < 3; y++) {
@@ -278,6 +290,17 @@ void SkNinePatch::DrawNine(SkCanvas* canvas, const SkRect& bounds,
xDivs[1] = bitmap.width() - margins.fRight;
yDivs[0] = margins.fTop;
yDivs[1] = bitmap.height() - margins.fBottom;
+
+ if (xDivs[0] > xDivs[1]) {
+ xDivs[0] = bitmap.width() * margins.fLeft /
+ (margins.fLeft + margins.fRight);
+ xDivs[1] = xDivs[0];
+ }
+ if (yDivs[0] > yDivs[1]) {
+ yDivs[0] = bitmap.height() * margins.fTop /
+ (margins.fTop + margins.fBottom);
+ yDivs[1] = yDivs[0];
+ }
SkNinePatch::DrawMesh(canvas, bounds, bitmap,
xDivs, 2, yDivs, 2, paint);
diff --git a/tests/MathTest.cpp b/tests/MathTest.cpp
index dec93de..4bfbd94 100644
--- a/tests/MathTest.cpp
+++ b/tests/MathTest.cpp
@@ -1,4 +1,5 @@
#include "Test.h"
+#include "SkFloatingPoint.h"
#include "SkPoint.h"
#include "SkRandom.h"