aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2010-12-20 18:26:13 +0000
committerGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2010-12-20 18:26:13 +0000
commitf2b98d67dcb6fcb3120feede9c72016fc7b3ead8 (patch)
treed78b57945b29865dcdeb1badbb360575289b292d /src
parent29e5054dd07c97c2195c5f64bf67aaa6b5afa204 (diff)
merge with changes for GPU backend
git-svn-id: http://skia.googlecode.com/svn/trunk@637 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r--src/core/SkBitmapProcShader.cpp10
-rw-r--r--src/core/SkBitmapProcShader.h3
-rw-r--r--src/core/SkBlitter_ARGB32.cpp36
-rw-r--r--src/core/SkCanvas.cpp117
-rw-r--r--src/core/SkChunkAlloc.cpp16
-rw-r--r--src/core/SkDevice.cpp80
-rw-r--r--src/core/SkDraw.cpp165
-rw-r--r--src/core/SkDrawProcs.h4
-rw-r--r--src/core/SkGlyphCache.cpp41
-rw-r--r--src/core/SkGlyphCache.h29
-rw-r--r--src/core/SkMatrix.cpp6
-rw-r--r--src/core/SkPaint.cpp13
-rw-r--r--src/core/SkScalerContext.cpp11
-rw-r--r--src/core/SkShader.cpp52
-rw-r--r--src/core/SkStroke.cpp4
-rw-r--r--src/core/SkTextFormatParams.h48
-rw-r--r--src/core/SkUtils.cpp2
-rw-r--r--src/core/core_files.mk1
-rw-r--r--src/pdf/SkPDFDevice.cpp18
-rw-r--r--src/pdf/pdf_files.mk2
-rw-r--r--src/utils/SkProxyCanvas.cpp12
-rw-r--r--src/utils/mac/SkCreateCGImageRef.cpp34
-rw-r--r--src/utils/mac/SkOSWindow_Mac.cpp78
-rw-r--r--src/utils/win/SkOSWindow_Win.cpp782
-rw-r--r--src/views/SkEvent.cpp15
-rw-r--r--src/views/SkMetaData.cpp23
-rw-r--r--src/views/SkTextBox.cpp2
-rw-r--r--src/views/SkView.cpp67
-rw-r--r--src/views/SkWindow.cpp83
29 files changed, 1331 insertions, 423 deletions
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 3c7be4c8b8..1eaa46d4d9 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -44,8 +44,10 @@ void SkBitmapProcShader::endSession() {
this->INHERITED::endSession();
}
-bool SkBitmapProcShader::asABitmap(SkBitmap* texture, SkMatrix* texM,
- TileMode xy[]) {
+SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
+ SkMatrix* texM,
+ TileMode xy[],
+ SkScalar* twoPointRadialParams) {
if (texture) {
*texture = fRawBitmap;
}
@@ -56,7 +58,7 @@ bool SkBitmapProcShader::asABitmap(SkBitmap* texture, SkMatrix* texM,
xy[0] = (TileMode)fState.fTileModeX;
xy[1] = (TileMode)fState.fTileModeY;
}
- return true;
+ return kDefault_BitmapType;
}
void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) {
@@ -82,7 +84,7 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
fState.fOrigBitmap = fRawBitmap;
fState.fOrigBitmap.lockPixels();
- if (!fState.fOrigBitmap.readyToDraw()) {
+ if (!fState.fOrigBitmap.getTexture() && !fState.fOrigBitmap.readyToDraw()) {
fState.fOrigBitmap.unlockPixels();
return false;
}
diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h
index 09d53afe1d..88598fc1fb 100644
--- a/src/core/SkBitmapProcShader.h
+++ b/src/core/SkBitmapProcShader.h
@@ -32,7 +32,8 @@ public:
virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
virtual void beginSession();
virtual void endSession();
- virtual bool asABitmap(SkBitmap*, SkMatrix*, TileMode*);
+ virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*,
+ SkScalar* twoPointRadialParams);
static bool CanDo(const SkBitmap&, TileMode tx, TileMode ty);
diff --git a/src/core/SkBlitter_ARGB32.cpp b/src/core/SkBlitter_ARGB32.cpp
index 905ab6b0b8..88b9491e4c 100644
--- a/src/core/SkBlitter_ARGB32.cpp
+++ b/src/core/SkBlitter_ARGB32.cpp
@@ -40,6 +40,32 @@ using namespace skia_blitter_support;
//////////////////////////////////////////////////////////////////////////////////////
+static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
+ const SkIRect& clip, SkPMColor srcColor) {
+ U8CPU alpha = SkGetPackedA32(srcColor);
+ unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32;
+ if (alpha != 255) {
+ flags |= SkBlitRow::kGlobalAlpha_Flag32;
+ }
+ SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags);
+
+ int x = clip.fLeft;
+ int y = clip.fTop;
+ int width = clip.width();
+ int height = clip.height();
+
+ SkPMColor* dstRow = device.getAddr32(x, y);
+ const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr(x, y));
+
+ do {
+ proc(dstRow, srcRow, width, alpha);
+ dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
+ srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes);
+ } while (--height != 0);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+
SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint)
: INHERITED(device) {
uint32_t color = paint.getColor();
@@ -156,6 +182,9 @@ void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
if (mask.fFormat == SkMask::kBW_Format) {
SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
return;
+ } else if (SkMask::kARGB32_Format == mask.fFormat) {
+ SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
+ return;
}
int x = clip.fLeft;
@@ -188,7 +217,10 @@ void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
if (mask.fFormat == SkMask::kBW_Format) {
SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
return;
- }
+ } else if (SkMask::kARGB32_Format == mask.fFormat) {
+ SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
+ return;
+ }
int x = clip.fLeft;
int y = clip.fTop;
@@ -306,6 +338,8 @@ void SkARGB32_Black_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
SkARGB32_BlitBW(fDevice, mask, clip, black);
+ } else if (SkMask::kARGB32_Format == mask.fFormat) {
+ SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
} else {
#if defined(SK_SUPPORT_LCDTEXT)
const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 5a855bb636..0e36c91a4b 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -74,6 +74,9 @@ struct DeviceCM {
const SkMatrix* fMatrix;
SkPaint* fPaint; // may be null (in the future)
int16_t fX, fY; // relative to base matrix/clip
+ // optional, related to canvas' external matrix
+ const SkMatrix* fMVMatrix;
+ const SkMatrix* fExtMatrix;
DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint)
: fNext(NULL) {
@@ -132,8 +135,18 @@ struct DeviceCM {
SkASSERT(deviceR.contains(fClip.getBounds()));
}
#endif
+ // default is to assume no external matrix
+ fMVMatrix = NULL;
+ fExtMatrix = NULL;
}
-
+
+ // can only be called after calling updateMC()
+ void updateExternalMatrix(const SkMatrix& extM, const SkMatrix& extI) {
+ fMVMatrixStorage.setConcat(extI, *fMatrix);
+ fMVMatrix = &fMVMatrixStorage;
+ fExtMatrix = &extM; // assumes extM has long life-time (owned by canvas)
+ }
+
void translateClip() {
if (fX | fY) {
fClip.translate(fX, fY);
@@ -141,7 +154,7 @@ struct DeviceCM {
}
private:
- SkMatrix fMatrixStorage;
+ SkMatrix fMatrixStorage, fMVMatrixStorage;
};
/* This is the record we keep for each save/restore level in the stack.
@@ -240,16 +253,17 @@ public:
fLayerX = rec->fX;
fLayerY = rec->fY;
fPaint = rec->fPaint;
- SkDEBUGCODE(this->validate(fDevice->width(), fDevice->height());)
+ fMVMatrix = rec->fMVMatrix;
+ fExtMatrix = rec->fExtMatrix;
+ SkDEBUGCODE(this->validate();)
fCurrLayer = rec->fNext;
if (fBounder) {
fBounder->setClip(fClip);
}
-
// fCurrLayer may be NULL now
- fCanvas->prepareForDeviceDraw(fDevice);
+ fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip);
return true;
}
return false;
@@ -401,6 +415,8 @@ SkDevice* SkCanvas::init(SkDevice* device) {
fMCRec->fTopLayer = fMCRec->fLayer;
fMCRec->fNext = NULL;
+ fUseExternalMatrix = false;
+
return this->setDevice(device);
}
@@ -427,7 +443,7 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
inc_canvas();
- SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
+ SkDevice* device = SkNEW_ARGS(SkDevice, (this, bitmap, false));
fDeviceFactory = device->getDeviceFactory();
this->init(device)->unref();
}
@@ -527,8 +543,8 @@ SkDevice* SkCanvas::setDevice(SkDevice* device) {
return device;
}
-SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) {
- SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (bitmap)));
+SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap, bool forLayer) {
+ SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (this, bitmap, forLayer)));
device->unref();
return device;
}
@@ -546,8 +562,9 @@ bool SkCanvas::getViewport(SkIPoint* size) const {
bool SkCanvas::setViewport(int width, int height) {
if ((getDevice()->getDeviceCapabilities() & SkDevice::kGL_Capability) == 0)
return false;
- this->setDevice(createDevice(SkBitmap::kARGB_8888_Config, width, height,
- false, false))->unref();
+
+ this->setDevice(this->createDevice(SkBitmap::kARGB_8888_Config, width, height,
+ false, false))->unref();
return true;
}
@@ -559,21 +576,30 @@ void SkCanvas::updateDeviceCMCache() {
if (NULL == layer->fNext) { // only one layer
layer->updateMC(totalMatrix, totalClip, NULL);
+ if (fUseExternalMatrix) {
+ layer->updateExternalMatrix(fExternalMatrix,
+ fExternalInverse);
+ }
} else {
SkRegion clip;
clip = totalClip; // make a copy
do {
layer->updateMC(totalMatrix, clip, &clip);
+ if (fUseExternalMatrix) {
+ layer->updateExternalMatrix(fExternalMatrix,
+ fExternalInverse);
+ }
} while ((layer = layer->fNext) != NULL);
}
fDeviceCMDirty = false;
}
}
-void SkCanvas::prepareForDeviceDraw(SkDevice* device) {
+void SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix,
+ const SkRegion& clip) {
SkASSERT(device);
if (fLastDeviceToGainFocus != device) {
- device->gainFocus(this);
+ device->gainFocus(this, matrix, clip);
fLastDeviceToGainFocus = device;
}
}
@@ -651,6 +677,9 @@ int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
SkIRect ir;
const SkIRect& clipBounds = this->getTotalClip().getBounds();
+ if (clipBounds.isEmpty()) {
+ return count;
+ }
if (NULL != bounds) {
SkRect r;
@@ -760,7 +789,7 @@ static bool reject_bitmap(const SkBitmap& bitmap) {
bitmap.width() > 32767 || bitmap.height() > 32767;
}
-void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
+void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
const SkMatrix& matrix, const SkPaint* paint) {
if (reject_bitmap(bitmap)) {
return;
@@ -768,9 +797,9 @@ void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
if (NULL == paint) {
SkPaint tmpPaint;
- this->commonDrawBitmap(bitmap, matrix, tmpPaint);
+ this->commonDrawBitmap(bitmap, srcRect, matrix, tmpPaint);
} else {
- this->commonDrawBitmap(bitmap, matrix, *paint);
+ this->commonDrawBitmap(bitmap, srcRect, matrix, *paint);
}
}
@@ -1023,13 +1052,30 @@ const SkRegion& SkCanvas::getTotalClip() const {
return *fMCRec->fRegion;
}
-///////////////////////////////////////////////////////////////////////////////
-
-SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width,
- int height, bool isOpaque, bool isForLayer) {
+void SkCanvas::setExternalMatrix(const SkMatrix* matrix) {
+ if (NULL == matrix || matrix->isIdentity()) {
+ if (fUseExternalMatrix) {
+ fDeviceCMDirty = true;
+ }
+ fUseExternalMatrix = false;
+ } else {
+ fUseExternalMatrix = true;
+ fDeviceCMDirty = true; // |= (fExternalMatrix != *matrix)
+
+ fExternalMatrix = *matrix;
+ matrix->invert(&fExternalInverse);
+ }
+
+ static bool gUseExt;
+ if (gUseExt != fUseExternalMatrix && false) {
+ gUseExt = fUseExternalMatrix;
+ printf("---- fUseExternalMatrix = %d\n", fUseExternalMatrix);
+ }
+}
- return fDeviceFactory->newDevice(config, width, height, isOpaque,
- isForLayer);
+SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height,
+ bool isOpaque, bool forLayer) {
+ return fDeviceFactory->newDevice(this, config, width, height, isOpaque, forLayer);
}
//////////////////////////////////////////////////////////////////////////////
@@ -1116,7 +1162,7 @@ void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
SkMatrix matrix;
matrix.setTranslate(x, y);
- this->internalDrawBitmap(bitmap, matrix, paint);
+ this->internalDrawBitmap(bitmap, NULL, matrix, paint);
}
void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
@@ -1130,15 +1176,7 @@ void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
return;
}
- SkBitmap tmp; // storage if we need a subset of bitmap
const SkBitmap* bitmapPtr = &bitmap;
-
- if (NULL != src) {
- if (!bitmap.extractSubset(&tmp, *src)) {
- return; // extraction failed
- }
- bitmapPtr = &tmp;
- }
SkMatrix matrix;
SkRect tmpSrc;
@@ -1159,23 +1197,32 @@ void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
SkIntToScalar(bitmap.height()));
}
matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
- this->internalDrawBitmap(*bitmapPtr, matrix, paint);
+
+ // ensure that src is "valid" before we pass it to our internal routines
+ // and to SkDevice. i.e. sure it is contained inside the original bitmap.
+ SkIRect tmpISrc;
+ if (src) {
+ tmpISrc.set(0, 0, bitmap.width(), bitmap.height());
+ tmpISrc.intersect(*src);
+ src = &tmpISrc;
+ }
+ this->internalDrawBitmap(*bitmapPtr, src, matrix, paint);
}
void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
const SkPaint* paint) {
SkDEBUGCODE(bitmap.validate();)
- this->internalDrawBitmap(bitmap, matrix, paint);
+ this->internalDrawBitmap(bitmap, NULL, matrix, paint);
}
-void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
- const SkPaint& paint) {
+void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
+ const SkMatrix& matrix, const SkPaint& paint) {
SkDEBUGCODE(bitmap.validate();)
ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
while (iter.next()) {
- iter.fDevice->drawBitmap(iter, bitmap, matrix, paint);
+ iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, paint);
}
ITER_END
diff --git a/src/core/SkChunkAlloc.cpp b/src/core/SkChunkAlloc.cpp
index 90a0c2ad11..e0c03a85a9 100644
--- a/src/core/SkChunkAlloc.cpp
+++ b/src/core/SkChunkAlloc.cpp
@@ -49,6 +49,11 @@ struct SkChunkAlloc::Block {
}
return block;
}
+
+ bool contains(const void* addr) const {
+ const char* ptr = reinterpret_cast<const char*>(addr);
+ return ptr >= (const char*)(this + 1) && ptr < fFreePtr;
+ }
};
SkChunkAlloc::SkChunkAlloc(size_t minSize)
@@ -139,3 +144,14 @@ size_t SkChunkAlloc::unalloc(void* ptr) {
return bytes;
}
+bool SkChunkAlloc::contains(const void* addr) const {
+ const Block* block = fBlock;
+ while (block) {
+ if (block->contains(addr)) {
+ return true;
+ }
+ block = block->fNext;
+ }
+ return false;
+}
+
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 12efaacbaf..8df0e41d72 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -4,9 +4,20 @@
SkDeviceFactory::~SkDeviceFactory() {}
-SkDevice::SkDevice() {}
-
-SkDevice::SkDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {}
+SkDevice::SkDevice(SkCanvas* canvas) : fCanvas(canvas) {}
+
+SkDevice::SkDevice(SkCanvas* canvas, const SkBitmap& bitmap, bool isForLayer)
+ : fCanvas(canvas), fBitmap(bitmap) {
+ // auto-allocate if we're for offscreen drawing
+ if (isForLayer) {
+ if (NULL == fBitmap.getPixels() && NULL == fBitmap.pixelRef()) {
+ fBitmap.allocPixels();
+ if (!fBitmap.isOpaque()) {
+ fBitmap.eraseColor(0);
+ }
+ }
+ }
+}
void SkDevice::lockPixels() {
fBitmap.lockPixels();
@@ -47,6 +58,39 @@ void SkDevice::setMatrixClip(const SkMatrix&, const SkRegion&) {}
///////////////////////////////////////////////////////////////////////////////
+bool SkDevice::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
+ const SkBitmap& src = this->accessBitmap(false);
+
+ SkIRect bounds;
+ bounds.set(0, 0, src.width(), src.height());
+ if (!bounds.intersect(srcRect)) {
+ return false;
+ }
+
+ SkBitmap subset;
+ if (!src.extractSubset(&subset, bounds)) {
+ return false;
+ }
+
+ SkBitmap tmp;
+ if (!subset.copyTo(&tmp, SkBitmap::kARGB_8888_Config)) {
+ return false;
+ }
+
+ tmp.swap(*bitmap);
+ return true;
+}
+
+void SkDevice::writePixels(const SkBitmap& bitmap, int x, int y) {
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+ SkCanvas canvas(this);
+ canvas.drawSprite(bitmap, x, y, &paint);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
void SkDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
draw.drawPaint(paint);
}
@@ -62,13 +106,24 @@ void SkDevice::drawRect(const SkDraw& draw, const SkRect& r,
}
void SkDevice::drawPath(const SkDraw& draw, const SkPath& path,
- const SkPaint& paint) {
- draw.drawPath(path, paint);
+ const SkPaint& paint, const SkMatrix* prePathMatrix,
+ bool pathIsMutable) {
+ draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
}
void SkDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
- const SkMatrix& matrix, const SkPaint& paint) {
- draw.drawBitmap(bitmap, matrix, paint);
+ const SkIRect* srcRect,
+ const SkMatrix& matrix, const SkPaint& paint) {
+ SkBitmap tmp; // storage if we need a subset of bitmap
+ const SkBitmap* bitmapPtr = &bitmap;
+
+ if (srcRect) {
+ if (!bitmap.extractSubset(&tmp, *srcRect)) {
+ return; // extraction failed
+ }
+ bitmapPtr = &tmp;
+ }
+ draw.drawBitmap(*bitmapPtr, matrix, paint);
}
void SkDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
@@ -109,16 +164,15 @@ void SkDevice::drawDevice(const SkDraw& draw, SkDevice* device,
draw.drawSprite(device->accessBitmap(false), x, y, paint);
}
-SkDevice* SkRasterDeviceFactory::newDevice(SkBitmap::Config config, int width,
+///////////////////////////////////////////////////////////////////////////////
+
+SkDevice* SkRasterDeviceFactory::newDevice(SkCanvas* canvas,
+ 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));
+ return SkNEW_ARGS(SkDevice, (canvas, bitmap, isForLayer));
}
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index eff2b32a4c..a117ab7216 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -143,6 +143,10 @@ private:
///////////////////////////////////////////////////////////////////////////////
+SkDraw::SkDraw() {
+ sk_bzero(this, sizeof(*this));
+}
+
SkDraw::SkDraw(const SkDraw& src) {
memcpy(this, &src, sizeof(*this));
}
@@ -276,7 +280,7 @@ static void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect,
}
void SkDraw::drawPaint(const SkPaint& paint) const {
- SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+ SkDEBUGCODE(this->validate();)
if (fClip->isEmpty()) {
return;
@@ -540,7 +544,8 @@ static bool bounder_points(SkBounder* bounder, SkCanvas::PointMode mode,
#define MAX_DEV_PTS 32
void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
- const SkPoint pts[], const SkPaint& paint) const {
+ const SkPoint pts[], const SkPaint& paint,
+ bool forceUseDevice) const {
// if we're in lines mode, force count to be even
if (SkCanvas::kLines_PointMode == mode) {
count &= ~(size_t)1;
@@ -563,7 +568,7 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
}
SkASSERT(pts != NULL);
- SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+ SkDEBUGCODE(this->validate();)
// nothing to draw
if (fClip->isEmpty() ||
@@ -572,7 +577,7 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
}
PtProcRec rec;
- if (rec.init(mode, paint, fMatrix, fClip)) {
+ if (!forceUseDevice && rec.init(mode, paint, fMatrix, fClip)) {
SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
SkPoint devPts[MAX_DEV_PTS];
@@ -614,7 +619,12 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
preMatrix.setTranslate(pts[i].fX, pts[i].fY);
// pass true for the last point, since we can modify
// then path then
- this->drawPath(path, paint, &preMatrix, (count-1) == i);
+ if (fDevice) {
+ fDevice->drawPath(*this, path, paint, &preMatrix,
+ (count-1) == i);
+ } else {
+ this->drawPath(path, paint, &preMatrix, (count-1) == i);
+ }
}
} else {
SkRect r;
@@ -624,7 +634,11 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
r.fTop = pts[i].fY - radius;
r.fRight = r.fLeft + width;
r.fBottom = r.fTop + width;
- this->drawRect(r, paint);
+ if (fDevice) {
+ fDevice->drawRect(*this, r, paint);
+ } else {
+ this->drawRect(r, paint);
+ }
}
}
break;
@@ -639,7 +653,11 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
for (size_t i = 0; i < count; i += inc) {
path.moveTo(pts[i]);
path.lineTo(pts[i+1]);
- this->drawPath(path, p, NULL, true);
+ if (fDevice) {
+ fDevice->drawPath(*this, path, p, NULL, true);
+ } else {
+ this->drawPath(path, p, NULL, true);
+ }
path.rewind();
}
break;
@@ -657,7 +675,7 @@ static inline SkPoint* as_rightbottom(SkRect* r) {
}
void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const {
- SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+ SkDEBUGCODE(this->validate();)
// nothing to draw
if (fClip->isEmpty() ||
@@ -799,7 +817,7 @@ static bool map_radius(const SkMatrix& matrix, SkScalar* value) {
void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& paint,
const SkMatrix* prePathMatrix, bool pathIsMutable) const {
- SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+ SkDEBUGCODE(this->validate();)
// nothing to draw
if (fClip->isEmpty() ||
@@ -846,7 +864,8 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& paint,
// can we approximate a thin (but not hairline) stroke with an alpha-modulated
// hairline? Only if the matrix scales evenly in X and Y, and the device-width is
// less than a pixel
- if (paint.getStyle() == SkPaint::kStroke_Style && paint.getXfermode() == NULL) {
+ if (paint.isAntiAlias() &&
+ paint.getStyle() == SkPaint::kStroke_Style && paint.getXfermode() == NULL) {
SkScalar width = paint.getStrokeWidth();
if (width > 0 && map_radius(*matrix, &width)) {
int scale = (int)SkScalarMul(width, 256);
@@ -1024,7 +1043,7 @@ static bool clipped_out(const SkMatrix& matrix, const SkRegion& clip,
void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
const SkPaint& paint) const {
- SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+ SkDEBUGCODE(this->validate();)
// nothing to draw
if (fClip->isEmpty() ||
@@ -1116,7 +1135,7 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
const SkPaint& paint) const {
- SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+ SkDEBUGCODE(this->validate();)
// nothing to draw
if (fClip->isEmpty() ||
@@ -1207,7 +1226,7 @@ static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
SkScalar x, SkScalar y,
const SkPaint& paint) const {
- SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+ SkDEBUGCODE(this->validate();)
SkTextToPathIter iter(text, byteLength, paint, true, true);
@@ -1220,7 +1239,12 @@ void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
while ((iterPath = iter.next(&xpos)) != NULL) {
matrix.postTranslate(xpos - prevXPos, 0);
- this->drawPath(*iterPath, iter.getPaint(), &matrix, false);
+ const SkPaint& pnt = iter.getPaint();
+ if (fDevice) {
+ fDevice->drawPath(*this, *iterPath, pnt, &matrix, false);
+ } else {
+ this->drawPath(*iterPath, pnt, &matrix, false);
+ }
prevXPos = xpos;
}
}
@@ -1275,7 +1299,10 @@ static void handle_aftertext(const SkDraw* draw, const SkPaint& paint,
//////////////////////////////////////////////////////////////////////////////
static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
- const SkGlyph& glyph, int left, int top) {
+ SkFixed fx, SkFixed fy,
+ const SkGlyph& glyph) {
+ int left = SkFixedFloor(fx);
+ int top = SkFixedFloor(fy);
SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
SkASSERT(state.fClip->isRect());
SkASSERT(NULL == state.fBounder);
@@ -1316,7 +1343,10 @@ static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
}
static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
- const SkGlyph& glyph, int left, int top) {
+ SkFixed fx, SkFixed fy,
+ const SkGlyph& glyph) {
+ int left = SkFixedFloor(fx);
+ int top = SkFixedFloor(fy);
SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
SkASSERT(!state.fClip->isRect());
SkASSERT(NULL == state.fBounder);
@@ -1350,7 +1380,10 @@ static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
}
static void D1G_Bounder(const SkDraw1Glyph& state,
- const SkGlyph& glyph, int left, int top) {
+ SkFixed fx, SkFixed fy,
+ const SkGlyph& glyph) {
+ int left = SkFixedFloor(fx);
+ int top = SkFixedFloor(fy);
SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
SkMask mask;
@@ -1435,7 +1468,7 @@ void SkDraw::drawText(const char text[], size_t byteLength,
SkScalar x, SkScalar y, const SkPaint& paint) const {
SkASSERT(byteLength == 0 || text != NULL);
- SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+ SkDEBUGCODE(this->validate();)
// nothing to draw
if (text == NULL || byteLength == 0 ||
@@ -1470,14 +1503,25 @@ void SkDraw::drawText(const char text[], size_t byteLength,
SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
- SkAutoGlyphCache autoCache(paint, fMatrix);
+ const SkMatrix* matrix = fMatrix;
+ SkFixed finalFYMask = ~0xFFFF; // trunc fy;
+ if (fProcs && fProcs->fD1GProc) {
+ // only support the fMVMatrix (for now) for the GPU case, which also
+ // sets the fD1GProc
+ if (fMVMatrix) {
+ matrix = fMVMatrix;
+ finalFYMask = ~0; // don't truncate
+ }
+ }
+
+ SkAutoGlyphCache autoCache(paint, matrix);
SkGlyphCache* cache = autoCache.getCache();
- SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
+ SkAutoBlitterChoose blitter(*fBitmap, *matrix, paint);
// transform our starting point
{
SkPoint loc;
- fMatrix->mapXY(x, y, &loc);
+ matrix->mapXY(x, y, &loc);
x = loc.fX;
y = loc.fY;
}
@@ -1503,30 +1547,33 @@ void SkDraw::drawText(const char text[], size_t byteLength,
SkFixed fy = SkScalarToFixed(y);
const char* stop = text + byteLength;
+ SkFixed fxMask = ~0;
+ SkFixed fyMask = ~0;
if (paint.isSubpixelText()) {
- RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix);
+ RoundBaseline roundBaseline = computeRoundBaseline(*matrix);
if (kRound_Y_Baseline == roundBaseline) {
- fy = (fy + 0x8000) & ~0xFFFF;
+ fyMask = 0;
+// fy = (fy + 0x8000) & ~0xFFFF;
} else if (kRound_X_Baseline == roundBaseline) {
- fx = (fx + 0x8000) & ~0xFFFF;
+ fxMask = 0;
}
- } else {
- // apply the bias here, so we don't have to add 1/2 in the loop
- fx += SK_Fixed1/2;
- fy += SK_Fixed1/2;
}
+ // apply the bias here, so we don't have to add 1/2 in the loop
+ fx += SK_FixedHalf;
+ fy += SK_FixedHalf;
+ fy &= finalFYMask;
SkAutoKern autokern;
SkDraw1Glyph d1g;
SkDraw1Glyph::Proc proc = d1g.init(this, blitter.get(), cache);
while (text < stop) {
- const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy);
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
fx += autokern.adjust(glyph);
if (glyph.fWidth) {
- proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy));
+ proc(d1g, fx, fy, glyph);
}
fx += glyph.fAdvanceX;
fy += glyph.fAdvanceY;
@@ -1636,7 +1683,7 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
SkASSERT(byteLength == 0 || text != NULL);
SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
- SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+ SkDEBUGCODE(this->validate();)
// nothing to draw
if (text == NULL || byteLength == 0 ||
@@ -1652,39 +1699,52 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
return;
}
+ const SkMatrix* matrix = fMatrix;
+ if (fProcs && fProcs->fD1GProc) {
+ // only support the fMVMatrix (for now) for the GPU case, which also
+ // sets the fD1GProc
+ if (fMVMatrix) {
+ matrix = fMVMatrix;
+ }
+ }
+
SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
- SkAutoGlyphCache autoCache(paint, fMatrix);
+ SkAutoGlyphCache autoCache(paint, matrix);
SkGlyphCache* cache = autoCache.getCache();
- SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
+ SkAutoBlitterChoose blitter(*fBitmap, *matrix, paint);
const char* stop = text + byteLength;
AlignProc alignProc = pick_align_proc(paint.getTextAlign());
SkDraw1Glyph d1g;
SkDraw1Glyph::Proc proc = d1g.init(this, blitter.get(), cache);
- TextMapState tms(*fMatrix, constY);
+ TextMapState tms(*matrix, constY);
TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
if (paint.isSubpixelText()) {
// maybe we should skip the rounding if linearText is set
- RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix);
+ RoundBaseline roundBaseline = computeRoundBaseline(*matrix);
if (SkPaint::kLeft_Align == paint.getTextAlign()) {
while (text < stop) {
+
tmsProc(tms, pos);
SkFixed fx = SkScalarToFixed(tms.fLoc.fX);
SkFixed fy = SkScalarToFixed(tms.fLoc.fY);
+ SkFixed fxMask = ~0;
+ SkFixed fyMask = ~0;
if (kRound_Y_Baseline == roundBaseline) {
- fy = (fy + 0x8000) & ~0xFFFF;
+ fyMask = 0;
} else if (kRound_X_Baseline == roundBaseline) {
- fx = (fx + 0x8000) & ~0xFFFF;
+ fxMask = 0;
}
- const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy);
+ const SkGlyph& glyph = glyphCacheProc(cache, &text,
+ fx & fxMask, fy & fyMask);
if (glyph.fWidth) {
- proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy));
+ proc(d1g, fx, fy, glyph);
}
pos += scalarsPerPosition;
}
@@ -1697,6 +1757,8 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
SkDEBUGCODE(SkFixed prevAdvY = glyph->fAdvanceY;)
SkFixed fx, fy;
+ SkFixed fxMask = ~0;
+ SkFixed fyMask = ~0;
tmsProc(tms, pos);
{
@@ -1706,19 +1768,19 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
fy = fixedLoc.fY;
if (kRound_Y_Baseline == roundBaseline) {
- fy = (fy + 0x8000) & ~0xFFFF;
+ fyMask = 0;
} else if (kRound_X_Baseline == roundBaseline) {
- fx = (fx + 0x8000) & ~0xFFFF;
+ fxMask = 0;
}
}
// have to call again, now that we've been "aligned"
- glyph = &glyphCacheProc(cache, &text, fx, fy);
+ glyph = &glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
// the assumption is that the advance hasn't changed
SkASSERT(prevAdvX == glyph->fAdvanceX);
SkASSERT(prevAdvY == glyph->fAdvanceY);
- proc(d1g, *glyph, SkFixedFloor(fx), SkFixedFloor(fy));
+ proc(d1g, fx, fy, *glyph);
}
pos += scalarsPerPosition;
}
@@ -1734,8 +1796,8 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
SkIPoint fixedLoc;
alignProc(tms.fLoc, glyph, &fixedLoc);
- proc(d1g, glyph,
- SkFixedRound(fixedLoc.fX), SkFixedRound(fixedLoc.fY));
+ proc(d1g, fixedLoc.fX + SK_FixedHalf,
+ fixedLoc.fY + SK_FixedHalf, glyph);
}
pos += scalarsPerPosition;
}
@@ -1863,7 +1925,11 @@ void SkDraw::drawTextOnPath(const char text[], size_t byteLength,
m.postConcat(*matrix);
}
morphpath(&tmp, *iterPath, meas, m);
- this->drawPath(tmp, iter.getPaint());
+ if (fDevice) {
+ fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true);
+ } else {
+ this->drawPath(tmp, iter.getPaint(), NULL, true);
+ }
}
}
@@ -2232,7 +2298,7 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
#ifdef SK_DEBUG
-void SkDraw::validate(int width, int height) const {
+void SkDraw::validate() const {
SkASSERT(fBitmap != NULL);
SkASSERT(fMatrix != NULL);
SkASSERT(fClip != NULL);
@@ -2240,8 +2306,11 @@ void SkDraw::validate(int width, int height) const {
const SkIRect& cr = fClip->getBounds();
SkIRect br;
- br.set(0, 0, width, height);
+ br.set(0, 0, fBitmap->width(), fBitmap->height());
SkASSERT(cr.isEmpty() || br.contains(cr));
+
+ // assert that both are null, or both are not-null
+ SkASSERT(!fMVMatrix == !fExtMatrix);
}
#endif
diff --git a/src/core/SkDrawProcs.h b/src/core/SkDrawProcs.h
index d64c088a30..7d69465d6a 100644
--- a/src/core/SkDrawProcs.h
+++ b/src/core/SkDrawProcs.h
@@ -13,7 +13,9 @@ struct SkDraw1Glyph {
SkGlyphCache* fCache;
SkIRect fClipBounds;
- typedef void (*Proc)(const SkDraw1Glyph&, const SkGlyph&, int x, int y);
+ // The fixed x,y have been pre-rounded (i.e. 1/2 has already been added),
+ // so the impls need just trunc down to an int
+ typedef void (*Proc)(const SkDraw1Glyph&, SkFixed x, SkFixed y, const SkGlyph&);
Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache);
};
diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp
index c744dfe540..199ac14761 100644
--- a/src/core/SkGlyphCache.cpp
+++ b/src/core/SkGlyphCache.cpp
@@ -96,22 +96,7 @@ SkGlyphCache::~SkGlyphCache() {
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_DEBUG
-class AutoCheckForNull {
-public:
- AutoCheckForNull(const SkTDArray<SkGlyph*>& array) : fArray(array) {
- for (int i = 0; i < array.count(); i++)
- SkASSERT(array[i]);
- }
- ~AutoCheckForNull() {
- const SkTDArray<SkGlyph*>& array = fArray;
- for (int i = 0; i < array.count(); i++) {
- SkASSERT(array[i]);
- }
- }
-private:
- const SkTDArray<SkGlyph*>& fArray;
-};
-#define VALIDATE() AutoCheckForNull acfn(fGlyphArray)
+#define VALIDATE() AutoValidate av(this)
#else
#define VALIDATE()
#endif
@@ -288,9 +273,7 @@ SkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) {
glyph = (SkGlyph*)fGlyphAlloc.alloc(sizeof(SkGlyph),
SkChunkAlloc::kThrow_AllocFailType);
- glyph->fID = id;
- glyph->fImage = NULL;
- glyph->fPath = NULL;
+ glyph->init(id);
*fGlyphArray.insert(hi) = glyph;
if (kJustAdvance_MetricsType == mtype) {
@@ -519,6 +502,9 @@ SkGlyphCache* SkGlyphCache::VisitCache(const SkDescriptor* desc,
cache = SkNEW_ARGS(SkGlyphCache, (desc));
FOUND_IT:
+
+ AutoValidate av(cache);
+
if (proc(cache, context)) { // stay detached
if (insideMutex) {
SkASSERT(globals.fTotalMemoryUsed >= cache->fMemoryUsed);
@@ -549,6 +535,7 @@ void SkGlyphCache::AttachCache(SkGlyphCache* cache) {
SkAutoMutexAcquire ac(globals.fMutex);
globals.validate();
+ cache->validate();
// if we have a fixed budget for our cache, do a purge here
{
@@ -664,3 +651,19 @@ size_t SkGlyphCache::InternalFreeCache(SkGlyphCache_Globals* globals,
return bytesFreed;
}
+///////////////////////////////////////////////////////////////////////////////
+#ifdef SK_DEBUG
+
+void SkGlyphCache::validate() const {
+ int count = fGlyphArray.count();
+ for (int i = 0; i < count; i++) {
+ const SkGlyph* glyph = fGlyphArray[i];
+ SkASSERT(glyph);
+ SkASSERT(fGlyphAlloc.contains(glyph));
+ if (glyph->fImage) {
+ SkASSERT(fImageAlloc.contains(glyph->fImage));
+ }
+ }
+}
+
+#endif
diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h
index cc81ed6aa7..16330f87a4 100644
--- a/src/core/SkGlyphCache.h
+++ b/src/core/SkGlyphCache.h
@@ -91,7 +91,9 @@ public:
const SkPaint::FontMetrics& getFontMetricsY() const {
return fFontMetricsY;
}
-
+
+ const SkDescriptor& getDescriptor() const { return *fDesc; }
+
/* AuxProc/Data allow a client to associate data with this cache entry.
Multiple clients can use this, as their data is keyed with a function
pointer. In addition to serving as a key, the function pointer is called
@@ -154,6 +156,31 @@ public:
*/
static bool SetCacheUsed(size_t bytesUsed);
+#ifdef SK_DEBUG
+ void validate() const;
+#else
+ void validate() const {}
+#endif
+
+ class AutoValidate : SkNoncopyable {
+ public:
+ AutoValidate(const SkGlyphCache* cache) : fCache(cache) {
+ if (fCache) {
+ fCache->validate();
+ }
+ }
+ ~AutoValidate() {
+ if (fCache) {
+ fCache->validate();
+ }
+ }
+ void forget() {
+ fCache = NULL;
+ }
+ private:
+ const SkGlyphCache* fCache;
+ };
+
private:
SkGlyphCache(const SkDescriptor*);
~SkGlyphCache();
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index e85c6ece4e..f2d1708114 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -1595,8 +1595,10 @@ uint32_t SkMatrix::flatten(void* buffer) const {
}
uint32_t SkMatrix::unflatten(const void* buffer) {
- memcpy(fMat, buffer, 9 * sizeof(SkScalar));
- this->setTypeMask(kUnknown_Mask);
+ if (buffer) {
+ memcpy(fMat, buffer, 9 * sizeof(SkScalar));
+ this->setTypeMask(kUnknown_Mask);
+ }
return 9 * sizeof(SkScalar);
}
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 88d924b4c0..d4c5b833ba 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1209,6 +1209,11 @@ static SkPaint::Hinting computeHinting(const SkPaint& paint) {
return h;
}
+static SkScalar sk_relax(SkScalar x) {
+ int n = sk_float_round2int(x * 1024);
+ return n / 1024.0f;
+}
+
void SkScalerContext::MakeRec(const SkPaint& paint,
const SkMatrix* deviceMatrix, Rec* rec)
{
@@ -1222,10 +1227,10 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
if (deviceMatrix)
{
- rec->fPost2x2[0][0] = deviceMatrix->getScaleX();
- rec->fPost2x2[0][1] = deviceMatrix->getSkewX();
- rec->fPost2x2[1][0] = deviceMatrix->getSkewY();
- rec->fPost2x2[1][1] = deviceMatrix->getScaleY();
+ rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
+ rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
+ rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
+ rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
}
else
{
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index b149be92ce..983f1addcc 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -344,7 +344,9 @@ void SkScalerContext::getMetrics(SkGlyph* glyph) {
}
}
- glyph->fMaskFormat = fRec.fMaskFormat;
+ if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
+ glyph->fMaskFormat = fRec.fMaskFormat;
+ }
if (fMaskFilter) {
SkMask src, dst;
@@ -668,9 +670,14 @@ protected:
}
};
+extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
+
SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc)
{
- SkScalerContext* c = SkFontHost::CreateScalerContext(desc);
+ SkScalerContext* c = NULL; //SkCreateColorScalerContext(desc);
+ if (NULL == c) {
+ c = SkFontHost::CreateScalerContext(desc);
+ }
if (NULL == c) {
c = SkNEW_ARGS(SkScalerContext_Empty, (desc));
}
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
index 34dc32e0ec..7b3a024c4f 100644
--- a/src/core/SkShader.cpp
+++ b/src/core/SkShader.cpp
@@ -17,6 +17,7 @@
#include "SkShader.h"
#include "SkPaint.h"
+#include "SkMallocPixelRef.h"
SkShader::SkShader() : fLocalMatrix(NULL) {
SkDEBUGCODE(fInSession = false;)
@@ -195,8 +196,9 @@ SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) {
//////////////////////////////////////////////////////////////////////////////
-bool SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) {
- return false;
+SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*,
+ TileMode*, SkScalar*) {
+ return kNone_BitmapType;
}
SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
@@ -209,9 +211,28 @@ SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
#include "SkColorShader.h"
#include "SkUtils.h"
+SkColorShader::SkColorShader() {
+ fFlags = 0;
+ fInheritColor = true;
+ fAsABitmapPixelRef = NULL;
+}
+
+SkColorShader::SkColorShader(SkColor c) {
+ fFlags = 0;
+ fColor = c;
+ fInheritColor = false;
+ fAsABitmapPixelRef = NULL;
+}
+
+SkColorShader::~SkColorShader() {
+ SkSafeUnref(fAsABitmapPixelRef);
+}
+
SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
fFlags = 0; // computed in setContext
- fInheritColor = b.readU8();
+ fAsABitmapPixelRef = NULL;
+
+ fInheritColor = b.readU8();
if (fInheritColor) {
return;
}
@@ -285,3 +306,28 @@ void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
memset(alpha, SkGetPackedA32(fPMColor), count);
}
+// if we had a asAColor method, that would be more efficient...
+SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
+ TileMode modes[],
+ SkScalar* twoPointRadialParams) {
+ // we cache the pixelref, since its generateID is used in the texture cache
+ if (NULL == fAsABitmapPixelRef) {
+ SkPMColor* storage = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor));
+ *storage = fPMColor;
+ fAsABitmapPixelRef = new SkMallocPixelRef(storage, sizeof(SkPMColor),
+ NULL);
+ }
+
+ if (bitmap) {
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
+ bitmap->setPixelRef(fAsABitmapPixelRef);
+ }
+ if (matrix) {
+ matrix->reset();
+ }
+ if (modes) {
+ modes[0] = modes[1] = SkShader::kRepeat_TileMode;
+ }
+ return kDefault_BitmapType;
+}
+
diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp
index 1fb25a6d9a..c35400b515 100644
--- a/src/core/SkStroke.cpp
+++ b/src/core/SkStroke.cpp
@@ -633,6 +633,10 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const {
if (fDoFill) {
dst->addPath(src);
+ } else {
+ if (src.countPoints() == 2) {
+ dst->setIsConvex(true);
+ }
}
}
diff --git a/src/core/SkTextFormatParams.h b/src/core/SkTextFormatParams.h
new file mode 100644
index 0000000000..3306270788
--- /dev/null
+++ b/src/core/SkTextFormatParams.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#ifndef SkTextFormatParams_DEFINES
+#define SkTextFormatParams_DEFINES
+
+#include "SkScalar.h"
+#include "SkTypes.h"
+
+// Fraction of the text size to lower a strike through line below the baseline.
+#define kStdStrikeThru_Offset (-SK_Scalar1 * 6 / 21)
+// Fraction of the text size to lower a underline below the baseline.
+#define kStdUnderline_Offset (SK_Scalar1 / 9)
+// Fraction of the text size to use for a strike through or under-line.
+#define kStdUnderline_Thickness (SK_Scalar1 / 18)
+
+// The fraction of text size to embolden fake bold text scales with text size.
+// At 9 points or below, the stroke width is increased by text size / 24.
+// At 36 points and above, it is increased by text size / 32. In between,
+// it is interpolated between those values.
+static const SkScalar kStdFakeBoldInterpKeys[] = {
+ SkIntToScalar(9),
+ SkIntToScalar(36)
+};
+static const SkScalar kStdFakeBoldInterpValues[] = {
+ SK_Scalar1/24,
+ SK_Scalar1/32
+};
+SK_COMPILE_ASSERT(SK_ARRAY_COUNT(kStdFakeBoldInterpKeys) ==
+ SK_ARRAY_COUNT(kStdFakeBoldInterpValues),
+ mismatched_array_size);
+static const int kStdFakeBoldInterpLength =
+ SK_ARRAY_COUNT(kStdFakeBoldInterpKeys);
+
+#endif //SkTextFormatParams_DEFINES
diff --git a/src/core/SkUtils.cpp b/src/core/SkUtils.cpp
index a88233f412..9fb85c2939 100644
--- a/src/core/SkUtils.cpp
+++ b/src/core/SkUtils.cpp
@@ -124,7 +124,7 @@ void sk_memset32_portable(uint32_t dst[], uint32_t value, int count)
}
}
-#ifndef ANDROID
+#if !defined(ANDROID) || defined(SK_BUILD_FOR_ANDROID_NDK)
static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count)
{
SkMemset16Proc proc = SkMemset16GetPlatformProc();
diff --git a/src/core/core_files.mk b/src/core/core_files.mk
index af7b876859..235fa76ac2 100644
--- a/src/core/core_files.mk
+++ b/src/core/core_files.mk
@@ -72,6 +72,7 @@ SOURCE := \
SkRect.cpp \
SkRefCnt.cpp \
SkRegion.cpp \
+ SkRegion_rects.cpp \
SkRegion_path.cpp \
SkScalar.cpp \
SkScalerContext.cpp \
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index cc65413328..9aefd0a258 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -118,16 +118,23 @@ void alignText(SkDrawCacheProc glyphCacheProc, const SkPaint& paint,
////////////////////////////////////////////////////////////////////////////////
-SkDevice* SkPDFDeviceFactory::newDevice(SkBitmap::Config config,
- int width, int height,
- bool isOpaque, bool isForLayer) {
+SkDevice* SkPDFDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,
+ int width, int height, bool isOpaque,
+ bool /*isForLayer*/) {
return SkNEW_ARGS(SkPDFDevice, (width, height));
}
+static inline SkBitmap makeABitmap(int width, int height) {
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kNo_Config, width, height);
+ return bitmap;
+}
+
SkPDFDevice::SkPDFDevice(int width, int height)
: fWidth(width),
fHeight(height),
- fGraphicStackIndex(0) {
+ fGraphicStackIndex(0),
+ SkDevice(NULL, makeABitmap(width, height), false) {
fGraphicStack[0].fColor = SK_ColorBLACK;
fGraphicStack[0].fTextSize = SK_ScalarNaN; // This has no default value.
fGraphicStack[0].fTextScaleX = SK_Scalar1;
@@ -271,7 +278,10 @@ void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& path,
}
void SkPDFDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap,
+ const SkIRect* srcRect,
const SkMatrix& matrix, const SkPaint& paint) {
+ // TODO: respect srcRect if present
+
SkMatrix transform = matrix;
transform.postConcat(fGraphicStack[fGraphicStackIndex].fTransform);
internalDrawBitmap(transform, bitmap, paint);
diff --git a/src/pdf/pdf_files.mk b/src/pdf/pdf_files.mk
index 8d721eb816..149e802c2a 100644
--- a/src/pdf/pdf_files.mk
+++ b/src/pdf/pdf_files.mk
@@ -8,4 +8,4 @@ SOURCE := \
SkPDFImage.cpp \
SkPDFPage.cpp \
SkPDFStream.cpp \
- SkPDFTypes.cpp \
+ SkPDFTypes.cpp
diff --git a/src/utils/SkProxyCanvas.cpp b/src/utils/SkProxyCanvas.cpp
index c643c8277e..d462d01b12 100644
--- a/src/utils/SkProxyCanvas.cpp
+++ b/src/utils/SkProxyCanvas.cpp
@@ -18,14 +18,6 @@ bool SkProxyCanvas::getViewport(SkIPoint* size) const {
return fProxy->getViewport(size);
}
-bool SkProxyCanvas::setViewport(int x, int y) {
- return fProxy->setViewport(x, y);
-}
-
-SkDevice* SkProxyCanvas::setBitmapDevice(const SkBitmap& bitmap) {
- return fProxy->setBitmapDevice(bitmap);
-}
-
int SkProxyCanvas::save(SaveFlags flags) {
return fProxy->save(flags);
}
@@ -163,8 +155,8 @@ SkDrawFilter* SkProxyCanvas::setDrawFilter(SkDrawFilter* filter) {
return fProxy->setDrawFilter(filter);
}
-SkDevice* SkProxyCanvas::createDevice(SkBitmap::Config config, int width,
- int height, bool isOpaque, bool isForLayer) {
+SkDevice* SkProxyCanvas::createDevice(SkBitmap::Config config, int width, int height,
+ bool isOpaque, bool isForLayer) {
return fProxy->createDevice(config, width, height, isOpaque, isForLayer);
}
diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp
index 5c96e21ff6..2169bc09cb 100644
--- a/src/utils/mac/SkCreateCGImageRef.cpp
+++ b/src/utils/mac/SkCreateCGImageRef.cpp
@@ -26,22 +26,19 @@ static SkBitmap* prepareForImageRef(const SkBitmap& bm,
*bitsPerComponent = 8;
#if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 0, 8, 16) \
|| defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(0, 24, 16, 8)
- *info = kCGBitmapByteOrder32Big |
- kCGImageAlphaPremultipliedLast;
+ *info = kCGBitmapByteOrder32Big;
#elif defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) \
|| defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0)
// Matches the CGBitmapInfo that Apple recommends for best
// performance, used by google chrome.
- *info = kCGBitmapByteOrder32Host |
- kCGImageAlphaPremultipliedFirst;
+ *info = kCGBitmapByteOrder32Little;
#else
// ...add more formats as required...
#warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \
This will probably not work.
// Legacy behavior. Perhaps turn this into an error at some
// point.
- *info = kCGBitmapByteOrder32Big |
- kCGImageAlphaPremultipliedLast;
+ *info = kCGBitmapByteOrder32Big;
#endif
break;
#if 0
@@ -59,6 +56,10 @@ static SkBitmap* prepareForImageRef(const SkBitmap& bm,
return NULL;
}
+ if (!bm.isOpaque()) {
+ *info |= kCGImageAlphaPremultipliedLast;
+ }
+
SkBitmap* copy;
if (upscaleTo32) {
copy = new SkBitmap;
@@ -93,7 +94,7 @@ CGImageRef SkCreateCGImageRef(const SkBitmap& bm) {
CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s,
SkBitmap_ReleaseInfo);
- CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGImageRef ref = CGImageCreate(w, h, bitsPerComponent,
bitmap->bytesPerPixel() * 8,
bitmap->rowBytes(), space, info, dataRef,
@@ -103,4 +104,23 @@ CGImageRef SkCreateCGImageRef(const SkBitmap& bm) {
return ref;
}
+void SkCGDrawBitmap(CGContextRef cg, const SkBitmap& bm, float x, float y) {
+ CGImageRef img = SkCreateCGImageRef(bm);
+
+ if (img) {
+ CGRect r = CGRectMake(0, 0, bm.width(), bm.height());
+
+ CGContextSaveGState(cg);
+ CGContextTranslateCTM(cg, x, r.size.height + y);
+ CGContextScaleCTM(cg, 1, -1);
+
+ CGContextDrawImage(cg, r, img);
+
+ CGContextRestoreGState(cg);
+
+ CGImageRelease(img);
+ }
+}
+
+
diff --git a/src/utils/mac/SkOSWindow_Mac.cpp b/src/utils/mac/SkOSWindow_Mac.cpp
index eb07e2aa73..6828a955f0 100644
--- a/src/utils/mac/SkOSWindow_Mac.cpp
+++ b/src/utils/mac/SkOSWindow_Mac.cpp
@@ -2,6 +2,8 @@
#if defined(SK_BUILD_FOR_MAC) && !defined(SK_USE_WXWIDGETS)
+#include <AGL/agl.h>
+
#include <Carbon/Carbon.h>
#include "SkCGUtils.h"
@@ -82,7 +84,7 @@ static void set_axisposition(HIAxisPosition* pos, HIViewRef parent, HIPositionKi
pos->offset = 0;
}
-SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd)
+SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd), fAGLCtx(NULL)
{
OSStatus result;
WindowRef wr = (WindowRef)hWnd;
@@ -450,5 +452,79 @@ void SkEvent::SignalQueueTimer(SkMSec delay)
}
}
+AGLContext create_gl(WindowRef wref, bool offscreen)
+{
+ GLint major, minor;
+ AGLContext ctx;
+
+ aglGetVersion(&major, &minor);
+ SkDebugf("---- agl version %d %d\n", major, minor);
+
+ const GLint pixelAttrs[] = {
+ AGL_RGBA,
+ AGL_STENCIL_SIZE, 8,
+ AGL_SAMPLE_BUFFERS_ARB, 1,
+ AGL_MULTISAMPLE,
+ AGL_SAMPLES_ARB, 2,
+ (offscreen ? AGL_OFFSCREEN : AGL_ACCELERATED),
+ (offscreen ? AGL_NONE : AGL_DOUBLEBUFFER),
+ AGL_NONE
+ };
+ AGLPixelFormat format = aglChoosePixelFormat(NULL, 0, pixelAttrs);
+ //AGLPixelFormat format = aglCreatePixelFormat(pixelAttrs);
+ SkDebugf("----- agl format %p\n", format);
+ ctx = aglCreateContext(format, NULL);
+ SkDebugf("----- agl context %p\n", ctx);
+ aglDestroyPixelFormat(format);
+
+ static const GLint interval = 1;
+ aglSetInteger(ctx, AGL_SWAP_INTERVAL, &interval);
+ aglSetCurrentContext(ctx);
+ return ctx;
+}
+
+bool SkOSWindow::attachGL(const SkBitmap* offscreen)
+{
+ if (NULL == fAGLCtx) {
+ fAGLCtx = create_gl((WindowRef)fHWND, NULL != offscreen);
+ if (NULL == fAGLCtx) {
+ return false;
+ }
+ }
+
+ GLboolean success = true;
+
+ if (offscreen) {
+ success = aglSetOffScreen((AGLContext)fAGLCtx,
+ offscreen->width(),
+ offscreen->height(),
+ offscreen->rowBytes(),
+ offscreen->getPixels());
+ } else {
+ success = aglSetWindowRef((AGLContext)fAGLCtx, (WindowRef)fHWND);
+ }
+
+ GLenum err = aglGetError();
+ if (err) {
+ SkDebugf("---- setoffscreen %d %d %s [%d %d]\n", success, err,
+ aglErrorString(err), offscreen->width(), offscreen->height());
+ }
+
+ if (success) {
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ }
+ return success;
+}
+
+void SkOSWindow::detachGL() {
+ aglSetWindowRef((AGLContext)fAGLCtx, NULL);
+}
+
+void SkOSWindow::presentGL() {
+ aglSwapBuffers((AGLContext)fAGLCtx);
+ glFlush();
+}
+
#endif
diff --git a/src/utils/win/SkOSWindow_Win.cpp b/src/utils/win/SkOSWindow_Win.cpp
index 376c3bdfda..26993be661 100644
--- a/src/utils/win/SkOSWindow_Win.cpp
+++ b/src/utils/win/SkOSWindow_Win.cpp
@@ -1,213 +1,569 @@
-#include "SkTypes.h"
-
-#if defined(SK_BUILD_FOR_WIN)
-
-#include "SkWindow.h"
-#include "SkCanvas.h"
-#include "SkOSMenu.h"
-#include "SkTime.h"
-
-#include "SkGraphics.h"
-
-static SkOSWindow* gCurrOSWin;
-
-SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd) {
-}
-
-static SkKey winToskKey(WPARAM vk) {
- static const struct {
- WPARAM fVK;
- SkKey fKey;
- } gPair[] = {
- { VK_BACK, kBack_SkKey },
- { VK_CLEAR, kBack_SkKey },
- { VK_RETURN, kOK_SkKey },
- { VK_UP, kUp_SkKey },
- { VK_DOWN, kDown_SkKey },
- { VK_LEFT, kLeft_SkKey },
- { VK_RIGHT, kRight_SkKey }
- };
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
- if (gPair[i].fVK == vk) {
- return gPair[i].fKey;
- }
- }
- return kNONE_SkKey;
-}
-
-bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
- switch (message) {
- case WM_KEYDOWN: {
- SkKey key = winToskKey(wParam);
- if (kNONE_SkKey != key) {
- this->handleKey(key);
- return true;
- }
- } break;
- case WM_KEYUP: {
- SkKey key = winToskKey(wParam);
- if (kNONE_SkKey != key) {
- this->handleKeyUp(key);
- return true;
- }
- } break;
- case WM_UNICHAR:
- this->handleChar(lParam);
- return true;
- case WM_SIZE:
- this->resize(lParam & 0xFFFF, lParam >> 16);
- break;
- case WM_PAINT: {
- PAINTSTRUCT ps;
- HDC hdc = BeginPaint(hWnd, &ps);
- this->doPaint(hdc);
- EndPaint(hWnd, &ps);
- return true;
- } break;
- }
- return false;
-}
-
-void SkOSWindow::doPaint(void* ctx) {
- this->update(NULL);
-
- HDC hdc = (HDC)ctx;
- const SkBitmap& bitmap = this->getBitmap();
-
- BITMAPINFO bmi;
- memset(&bmi, 0, sizeof(bmi));
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = bitmap.width();
- bmi.bmiHeader.biHeight = -bitmap.height(); // top-down image
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biSizeImage = 0;
-
- //
- // Do the SetDIBitsToDevice.
- //
- bitmap.lockPixels();
- int iRet = SetDIBitsToDevice(hdc,
- 0, 0,
- bitmap.width(), bitmap.height(),
- 0, 0,
- 0, bitmap.height(),
- bitmap.getPixels(),
- &bmi,
- DIB_RGB_COLORS);
- bitmap.unlockPixels();
-}
-
-#if 0
-void SkOSWindow::updateSize()
-{
- RECT r;
- GetWindowRect((HWND)this->getHWND(), &r);
- this->resize(r.right - r.left, r.bottom - r.top);
-}
-#endif
-
-void SkOSWindow::onHandleInval(const SkIRect& r) {
- RECT rect;
- rect.left = r.fLeft;
- rect.top = r.fTop;
- rect.right = r.fRight;
- rect.bottom = r.fBottom;
- InvalidateRect((HWND)this->getHWND(), &rect, false);
-}
-
-void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
-{
-}
-
-
-enum {
- SK_MacReturnKey = 36,
- SK_MacDeleteKey = 51,
- SK_MacEndKey = 119,
- SK_MacLeftKey = 123,
- SK_MacRightKey = 124,
- SK_MacDownKey = 125,
- SK_MacUpKey = 126,
-
- SK_Mac0Key = 0x52,
- SK_Mac1Key = 0x53,
- SK_Mac2Key = 0x54,
- SK_Mac3Key = 0x55,
- SK_Mac4Key = 0x56,
- SK_Mac5Key = 0x57,
- SK_Mac6Key = 0x58,
- SK_Mac7Key = 0x59,
- SK_Mac8Key = 0x5b,
- SK_Mac9Key = 0x5c
-};
-
-static SkKey raw2key(uint32_t raw)
-{
- static const struct {
- uint32_t fRaw;
- SkKey fKey;
- } gKeys[] = {
- { SK_MacUpKey, kUp_SkKey },
- { SK_MacDownKey, kDown_SkKey },
- { SK_MacLeftKey, kLeft_SkKey },
- { SK_MacRightKey, kRight_SkKey },
- { SK_MacReturnKey, kOK_SkKey },
- { SK_MacDeleteKey, kBack_SkKey },
- { SK_MacEndKey, kEnd_SkKey },
- { SK_Mac0Key, k0_SkKey },
- { SK_Mac1Key, k1_SkKey },
- { SK_Mac2Key, k2_SkKey },
- { SK_Mac3Key, k3_SkKey },
- { SK_Mac4Key, k4_SkKey },
- { SK_Mac5Key, k5_SkKey },
- { SK_Mac6Key, k6_SkKey },
- { SK_Mac7Key, k7_SkKey },
- { SK_Mac8Key, k8_SkKey },
- { SK_Mac9Key, k9_SkKey }
- };
-
- for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
- if (gKeys[i].fRaw == raw)
- return gKeys[i].fKey;
- return kNONE_SkKey;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-void SkEvent::SignalNonEmptyQueue()
-{
-// post_skmacevent();
-// SkDebugf("signal nonempty\n");
-}
-
-//static void sk_timer_proc(TMTask* rec)
-//{
-// SkEvent::ServiceQueueTimer();
-// SkDebugf("timer task fired\n");
-//}
-
-void SkEvent::SignalQueueTimer(SkMSec delay)
-{
-#if 0
- if (gTMTaskPtr)
- {
- RemoveTimeTask((QElem*)gTMTaskPtr);
- DisposeTimerUPP(gTMTaskPtr->tmAddr);
- gTMTaskPtr = nil;
- }
- if (delay)
- {
- gTMTaskPtr = &gTMTaskRec;
- memset(gTMTaskPtr, 0, sizeof(gTMTaskRec));
- gTMTaskPtr->tmAddr = NewTimerUPP(sk_timer_proc);
- OSErr err = InstallTimeTask((QElem*)gTMTaskPtr);
-// SkDebugf("installtimetask of %d returned %d\n", delay, err);
- PrimeTimeTask((QElem*)gTMTaskPtr, delay);
- }
-#endif
-}
-
-#endif
-
+#include "SkTypes.h"
+
+#if defined(SK_BUILD_FOR_WIN)
+
+#include <GL/glew.h>
+#include <GL/wglew.h>
+#include <GL/gl.h>
+#include <d3d9.h>
+#include <WindowsX.h>
+#include "SkWindow.h"
+#include "SkCanvas.h"
+#include "SkOSMenu.h"
+#include "SkTime.h"
+#include "SkUtils.h"
+
+#include "SkGraphics.h"
+
+#define INVALIDATE_DELAY_MS 200
+
+static SkOSWindow* gCurrOSWin;
+static HWND gEventTarget;
+
+#define WM_EVENT_CALLBACK (WM_USER+0)
+
+void post_skwinevent()
+{
+ PostMessage(gEventTarget, WM_EVENT_CALLBACK, 0, 0);
+}
+
+SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd),
+ fHGLRC(NULL),
+ fGLAttached(false),
+ fD3D9Device(NULL),
+ fD3D9Attached(FALSE) {
+ gEventTarget = (HWND)hWnd;
+}
+
+SkOSWindow::~SkOSWindow() {
+ if (NULL != fD3D9Device) {
+ ((IDirect3DDevice9*)fD3D9Device)->Release();
+ }
+ if (NULL != fHGLRC) {
+ wglDeleteContext((HGLRC)fHGLRC);
+ }
+}
+
+static SkKey winToskKey(WPARAM vk) {
+ static const struct {
+ WPARAM fVK;
+ SkKey fKey;
+ } gPair[] = {
+ { VK_BACK, kBack_SkKey },
+ { VK_CLEAR, kBack_SkKey },
+ { VK_RETURN, kOK_SkKey },
+ { VK_UP, kUp_SkKey },
+ { VK_DOWN, kDown_SkKey },
+ { VK_LEFT, kLeft_SkKey },
+ { VK_RIGHT, kRight_SkKey }
+ };
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
+ if (gPair[i].fVK == vk) {
+ return gPair[i].fKey;
+ }
+ }
+ return kNONE_SkKey;
+}
+
+bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ switch (message) {
+ case WM_KEYDOWN: {
+ SkKey key = winToskKey(wParam);
+ if (kNONE_SkKey != key) {
+ this->handleKey(key);
+ return true;
+ }
+ } break;
+ case WM_KEYUP: {
+ SkKey key = winToskKey(wParam);
+ if (kNONE_SkKey != key) {
+ this->handleKeyUp(key);
+ return true;
+ }
+ } break;
+ case WM_UNICHAR:
+ this->handleChar(wParam);
+ return true;
+ case WM_CHAR: {
+ this->handleChar(SkUTF8_ToUnichar((char*)&wParam));
+ return true;
+ } break;
+ case WM_SIZE:
+ this->resize(lParam & 0xFFFF, lParam >> 16);
+ break;
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hWnd, &ps);
+ this->doPaint(hdc);
+ EndPaint(hWnd, &ps);
+ return true;
+ } break;
+
+ case WM_TIMER: {
+ RECT* rect = (RECT*)wParam;
+ InvalidateRect(hWnd, rect, FALSE);
+ KillTimer(hWnd, (UINT_PTR)rect);
+ delete rect;
+ return true;
+ } break;
+
+ case WM_LBUTTONDOWN:
+ this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kDown_State);
+ return true;
+
+ case WM_MOUSEMOVE:
+ this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kMoved_State);
+ return true;
+
+ case WM_LBUTTONUP:
+ this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kUp_State);
+ return true;
+
+ case WM_EVENT_CALLBACK:
+ if (SkEvent::ProcessEvent()) {
+ post_skwinevent();
+ }
+ return true;
+ }
+ return false;
+}
+
+void SkOSWindow::doPaint(void* ctx) {
+ this->update(NULL);
+
+ if (!fGLAttached && !fD3D9Attached)
+ {
+ HDC hdc = (HDC)ctx;
+ const SkBitmap& bitmap = this->getBitmap();
+
+ BITMAPINFO bmi;
+ memset(&bmi, 0, sizeof(bmi));
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = bitmap.width();
+ bmi.bmiHeader.biHeight = -bitmap.height(); // top-down image
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 32;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biSizeImage = 0;
+
+ //
+ // Do the SetDIBitsToDevice.
+ //
+ bitmap.lockPixels();
+ int iRet = SetDIBitsToDevice(hdc,
+ 0, 0,
+ bitmap.width(), bitmap.height(),
+ 0, 0,
+ 0, bitmap.height(),
+ bitmap.getPixels(),
+ &bmi,
+ DIB_RGB_COLORS);
+ bitmap.unlockPixels();
+ }
+}
+
+#if 0
+void SkOSWindow::updateSize()
+{
+ RECT r;
+ GetWindowRect((HWND)this->getHWND(), &r);
+ this->resize(r.right - r.left, r.bottom - r.top);
+}
+#endif
+
+void SkOSWindow::onHandleInval(const SkIRect& r) {
+ RECT* rect = new RECT;
+ rect->left = r.fLeft;
+ rect->top = r.fTop;
+ rect->right = r.fRight;
+ rect->bottom = r.fBottom;
+ SetTimer((HWND)fHWND, (UINT_PTR)rect, INVALIDATE_DELAY_MS, NULL);
+}
+
+void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
+{
+}
+
+void SkOSWindow::onSetTitle(const char title[]){
+ SetWindowTextA((HWND)fHWND, title);
+}
+
+enum {
+ SK_MacReturnKey = 36,
+ SK_MacDeleteKey = 51,
+ SK_MacEndKey = 119,
+ SK_MacLeftKey = 123,
+ SK_MacRightKey = 124,
+ SK_MacDownKey = 125,
+ SK_MacUpKey = 126,
+
+ SK_Mac0Key = 0x52,
+ SK_Mac1Key = 0x53,
+ SK_Mac2Key = 0x54,
+ SK_Mac3Key = 0x55,
+ SK_Mac4Key = 0x56,
+ SK_Mac5Key = 0x57,
+ SK_Mac6Key = 0x58,
+ SK_Mac7Key = 0x59,
+ SK_Mac8Key = 0x5b,
+ SK_Mac9Key = 0x5c
+};
+
+static SkKey raw2key(uint32_t raw)
+{
+ static const struct {
+ uint32_t fRaw;
+ SkKey fKey;
+ } gKeys[] = {
+ { SK_MacUpKey, kUp_SkKey },
+ { SK_MacDownKey, kDown_SkKey },
+ { SK_MacLeftKey, kLeft_SkKey },
+ { SK_MacRightKey, kRight_SkKey },
+ { SK_MacReturnKey, kOK_SkKey },
+ { SK_MacDeleteKey, kBack_SkKey },
+ { SK_MacEndKey, kEnd_SkKey },
+ { SK_Mac0Key, k0_SkKey },
+ { SK_Mac1Key, k1_SkKey },
+ { SK_Mac2Key, k2_SkKey },
+ { SK_Mac3Key, k3_SkKey },
+ { SK_Mac4Key, k4_SkKey },
+ { SK_Mac5Key, k5_SkKey },
+ { SK_Mac6Key, k6_SkKey },
+ { SK_Mac7Key, k7_SkKey },
+ { SK_Mac8Key, k8_SkKey },
+ { SK_Mac9Key, k9_SkKey }
+ };
+
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
+ if (gKeys[i].fRaw == raw)
+ return gKeys[i].fKey;
+ return kNONE_SkKey;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+void SkEvent::SignalNonEmptyQueue()
+{
+ post_skwinevent();
+ //SkDebugf("signal nonempty\n");
+}
+
+static UINT_PTR gTimer;
+
+VOID CALLBACK sk_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ SkEvent::ServiceQueueTimer();
+ //SkDebugf("timer task fired\n");
+}
+
+void SkEvent::SignalQueueTimer(SkMSec delay)
+{
+ if (gTimer)
+ {
+ KillTimer(NULL, gTimer);
+ gTimer = NULL;
+ }
+ if (delay)
+ {
+ gTimer = SetTimer(NULL, 0, delay, sk_timer_proc);
+ //SkDebugf("SetTimer of %d returned %d\n", delay, gTimer);
+ }
+}
+
+static HWND create_dummy()
+{
+ HMODULE module = GetModuleHandle(NULL);
+ HWND dummy;
+ RECT windowRect;
+ windowRect.left = 0;
+ windowRect.right = 8;
+ windowRect.top = 0;
+ windowRect.bottom = 8;
+
+ WNDCLASS wc;
+
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ wc.lpfnWndProc = (WNDPROC) DefWindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = module;
+ wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = L"DummyWindow";
+
+ if(!RegisterClass(&wc))
+ {
+ return 0;
+ }
+
+ DWORD style, exStyle;
+ exStyle = WS_EX_CLIENTEDGE;
+ style = WS_SYSMENU;
+
+ AdjustWindowRectEx(&windowRect, style, false, exStyle);
+
+ if(!(dummy = CreateWindowEx(exStyle,
+ L"DummyWindow",
+ L"Dummy Window",
+ WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
+ 0, 0,
+ windowRect.right-windowRect.left,
+ windowRect.bottom-windowRect.top,
+ NULL, NULL,
+ module,
+ NULL)))
+ {
+ UnregisterClass(L"Dummy Window", module);
+ return NULL;
+ }
+ ShowWindow(dummy, SW_HIDE);
+
+ return dummy;
+}
+
+void kill_dummy(HWND dummy) {
+ DestroyWindow(dummy);
+ HMODULE module = GetModuleHandle(NULL);
+ UnregisterClass(L"Dummy Window", module);
+}
+
+HGLRC create_gl(HWND hwnd) {
+ HDC hdc;
+ HDC prevHDC;
+ HGLRC prevGLRC, glrc;
+ PIXELFORMATDESCRIPTOR pfd;
+
+ static bool glewInitialized;
+
+ prevGLRC = wglGetCurrentContext();
+ prevHDC = wglGetCurrentDC();
+
+ int format = 0;
+
+ // glew must be initialized after a context has been created and made current
+ // and we need glew already be initialized to get wglChoosePixelFormatEXT :(
+ // Even worse: SetPixelFormat needs to be called before the context is created
+ // But SetPixelFormat is only allowed to succeed once per-window. So we need to
+ // create a dummy window for glew in order for it to call wglGetProcAddress() to
+ // get wglChoosePixelFormatARB(). This is a Windows problem, not a glew problem.
+ if (!glewInitialized) {
+ ZeroMemory(&pfd, sizeof(pfd));
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 32;
+ pfd.cDepthBits = 0;
+ pfd.cStencilBits = 8;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+ HWND dummy = create_dummy();
+ SkASSERT(NULL != dummy);
+ hdc = GetDC(dummy);
+ format = ChoosePixelFormat(hdc, &pfd);
+ SetPixelFormat(hdc, format, &pfd);
+ glrc = wglCreateContext(hdc);
+ SkASSERT(glrc);
+ wglMakeCurrent(hdc, glrc);
+
+ GLenum err;
+ err = glewInit();
+ SkASSERT(GLEW_OK == err);
+ SkASSERT(GLEW_EXT_bgra);
+ SkASSERT(GLEW_EXT_framebuffer_object);
+ SkASSERT(WGLEW_ARB_pixel_format);
+ glewInitialized = true;
+ wglMakeCurrent(hdc, NULL);
+ wglDeleteContext(glrc);
+ glrc = 0;
+ kill_dummy(dummy);
+ }
+
+ hdc = GetDC(hwnd);
+ format = 0;
+
+ GLint iattrs[] = {
+ WGL_DRAW_TO_WINDOW_ARB, TRUE,
+ WGL_DOUBLE_BUFFER_ARB, TRUE,
+ WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
+ WGL_SUPPORT_OPENGL_ARB, TRUE,
+ WGL_COLOR_BITS_ARB, 24,
+ WGL_STENCIL_BITS_ARB, 8,
+ WGL_SAMPLE_BUFFERS_ARB, TRUE,
+ WGL_SAMPLES_ARB, 0,
+ 0,0
+ };
+ for (int samples = 16; samples > 1; --samples) {
+ iattrs[15] = samples;
+ GLfloat fattrs[] = {0,0};
+ GLuint num;
+ int formats[64];
+ wglChoosePixelFormatARB(hdc, iattrs, fattrs, 64, formats, &num);
+ num = min(num,64);
+ for (GLuint i = 0; i < num; ++i) {
+ DescribePixelFormat(hdc, formats[i], sizeof(pfd), &pfd);
+ if (SetPixelFormat(hdc, formats[i], &pfd)) {
+ format = formats[i];
+ break;
+ }
+ }
+ }
+ if (0 == format) {
+ iattrs[12] = iattrs[13] = 0;
+ GLfloat fattrs[] = {0,0};
+ GLuint num;
+ wglChoosePixelFormatARB(hdc, iattrs, fattrs, 1, &format, &num);
+ DescribePixelFormat(hdc, format, sizeof(pfd), &pfd);
+ BOOL set = SetPixelFormat(hdc, format, &pfd);
+ SkASSERT(TRUE == set);
+ }
+
+ glrc = wglCreateContext(hdc);
+ SkASSERT(glrc);
+
+ wglMakeCurrent(prevHDC, prevGLRC);
+ return glrc;
+}
+
+bool SkOSWindow::attachGL(const SkBitmap* offscreen) {
+ if (offscreen) {
+ printf("windows doesn't support rendering to SkBitmap");
+ }
+ if (NULL == fHGLRC) {
+ fHGLRC = create_gl((HWND)fHWND);
+ if (NULL == fHGLRC) {
+ return false;
+ }
+ }
+ if (wglMakeCurrent(GetDC((HWND)fHWND), (HGLRC)fHGLRC)) {
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ fGLAttached = true;
+ return true;
+ }
+ return false;
+}
+
+void SkOSWindow::detachGL() {
+ wglMakeCurrent(GetDC((HWND)fHWND), 0);
+ fGLAttached = false;
+}
+
+void SkOSWindow::presentGL() {
+ glFlush();
+ SwapBuffers(GetDC((HWND)fHWND));
+ glClearColor(0,0,0,0);
+ glClearStencil(0);
+ glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+}
+
+IDirect3DDevice9* create_d3d9_device(HWND hwnd) {
+ HRESULT hr;
+
+ IDirect3D9* d3d9;
+ d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+ if (NULL == d3d9) {
+ return NULL;
+ }
+ D3DDEVTYPE devType = D3DDEVTYPE_HAL;
+ //D3DDEVTYPE devType = D3DDEVTYPE_REF;
+ DWORD qLevels;
+ DWORD qLevelsDepth;
+ D3DMULTISAMPLE_TYPE type;
+ for (type = D3DMULTISAMPLE_16_SAMPLES;
+ type >= D3DMULTISAMPLE_NONMASKABLE; --(*(DWORD*)&type)) {
+ hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT,
+ devType, D3DFMT_D24S8, TRUE,
+ type, &qLevels);
+ qLevels = (hr == D3D_OK) ? qLevels : 0;
+ hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT,
+ devType, D3DFMT_A8R8G8B8, TRUE,
+ type, &qLevelsDepth);
+ qLevelsDepth = (hr == D3D_OK) ? qLevelsDepth : 0;
+ qLevels = min(qLevels,qLevelsDepth);
+ if (qLevels > 0) {
+ break;
+ }
+ }
+ qLevels = 0;
+ IDirect3DDevice9* d3d9Device;
+ D3DPRESENT_PARAMETERS pres;
+ memset(&pres, 0, sizeof(pres));
+ pres.EnableAutoDepthStencil = TRUE;
+ pres.AutoDepthStencilFormat = D3DFMT_D24S8;
+ pres.BackBufferCount = 2;
+ pres.BackBufferFormat = D3DFMT_A8R8G8B8;
+ pres.BackBufferHeight = 0;
+ pres.BackBufferWidth = 0;
+ if (qLevels > 0) {
+ pres.MultiSampleType = type;
+ pres.MultiSampleQuality = qLevels-1;
+ } else {
+ pres.MultiSampleType = D3DMULTISAMPLE_NONE;
+ pres.MultiSampleQuality = 0;
+ }
+ pres.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ pres.Windowed = TRUE;
+ pres.hDeviceWindow = hwnd;
+ pres.PresentationInterval = 1;
+ pres.Flags = 0;
+ hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT,
+ devType,
+ hwnd,
+ D3DCREATE_HARDWARE_VERTEXPROCESSING,
+ &pres,
+ &d3d9Device);
+ D3DERR_INVALIDCALL;
+ if (SUCCEEDED(hr)) {
+ d3d9Device->Clear(0, NULL, D3DCLEAR_TARGET, 0xFFFFFFFF, 0, 0);
+ return d3d9Device;
+ }
+ return NULL;
+}
+
+// This needs some improvement. D3D doesn't have the same notion of attach/detach
+// as GL. However, just allowing GDI to write to the window after creating the
+// D3D device seems to work.
+// We need to handle resizing. On XP and earlier Reset() will trash all our textures
+// so we would need to inform the SkGpu/caches or just recreate them. On Vista+ we
+// could use an IDirect3DDevice9Ex and call ResetEx() to resize without trashing
+// everything. Currently we do nothing and the D3D9 image gets stretched/compressed
+// when resized.
+
+bool SkOSWindow::attachD3D9() {
+ if (NULL == fD3D9Device) {
+ fD3D9Device = (void*) create_d3d9_device((HWND)fHWND);
+ }
+ if (NULL != fD3D9Device) {
+ ((IDirect3DDevice9*)fD3D9Device)->BeginScene();
+ fD3D9Attached = true;
+ }
+ return fD3D9Attached;
+}
+
+void SkOSWindow::detachD3D9() {
+ if (NULL != fD3D9Device) {
+ ((IDirect3DDevice9*)fD3D9Device)->EndScene();
+ }
+ fD3D9Attached = false;
+}
+
+void SkOSWindow::presentD3D9() {
+ if (NULL != fD3D9Device) {
+ HRESULT hr;
+ hr = ((IDirect3DDevice9*)fD3D9Device)->EndScene();
+ SkASSERT(SUCCEEDED(hr));
+ hr = ((IDirect3DDevice9*)d3d9Device())->Present(NULL, NULL, NULL, NULL);
+ SkASSERT(SUCCEEDED(hr));
+ hr = ((IDirect3DDevice9*)fD3D9Device)->Clear(0,NULL,D3DCLEAR_TARGET |
+ D3DCLEAR_STENCIL, 0x0, 0,
+ 0);
+ SkASSERT(SUCCEEDED(hr));
+ hr = ((IDirect3DDevice9*)fD3D9Device)->BeginScene();
+ SkASSERT(SUCCEEDED(hr));
+ }
+}
+
+
+#endif \ No newline at end of file
diff --git a/src/views/SkEvent.cpp b/src/views/SkEvent.cpp
index 67549b48b5..ec4a7b47b7 100644
--- a/src/views/SkEvent.cpp
+++ b/src/views/SkEvent.cpp
@@ -536,6 +536,21 @@ void SkEvent::ServiceQueueTimer()
SkEvent::SignalQueueTimer(time);
}
+int SkEvent::CountEventsOnQueue() {
+ SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_GlobalsTag, create_globals);
+ globals.fEventMutex.acquire();
+
+ int count = 0;
+ const SkEvent* evt = globals.fEventQHead;
+ while (evt) {
+ count += 1;
+ evt = evt->fNextEvent;
+ }
+ globals.fEventMutex.release();
+
+ return count;
+}
+
////////////////////////////////////////////////////////////////
void SkEvent::Init()
diff --git a/src/views/SkMetaData.cpp b/src/views/SkMetaData.cpp
index c366bd3fee..c871efb136 100644
--- a/src/views/SkMetaData.cpp
+++ b/src/views/SkMetaData.cpp
@@ -89,6 +89,10 @@ void SkMetaData::setBool(const char name[], bool value)
(void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
}
+void SkMetaData::setData(const char name[], const void* data, size_t byteCount) {
+ (void)this->set(name, data, sizeof(char), kData_Type, byteCount);
+}
+
void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count)
{
SkASSERT(name);
@@ -129,6 +133,9 @@ void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type
case kBool_Type:
rec->fData.fBool = *(const bool*)rec->data();
break;
+ case kData_Type:
+ rec->fData.fPtr = rec->data();
+ break;
default:
SkASSERT(!"bad type");
break;
@@ -213,6 +220,18 @@ bool SkMetaData::findBool(const char name[], bool* value) const
return false;
}
+const void* SkMetaData::findData(const char name[], size_t* length) const {
+ const Rec* rec = this->find(name, kData_Type);
+ if (rec) {
+ SkASSERT(rec->fDataLen == sizeof(char));
+ if (length) {
+ *length = rec->fDataCount;
+ }
+ return rec->data();
+ }
+ return NULL;
+}
+
const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const
{
const Rec* rec = fRec;
@@ -272,6 +291,10 @@ bool SkMetaData::removeBool(const char name[])
return this->remove(name, kBool_Type);
}
+bool SkMetaData::removeData(const char name[]) {
+ return this->remove(name, kData_Type);
+}
+
///////////////////////////////////////////////////////////////////////////////////
SkMetaData::Iter::Iter(const SkMetaData& metadata)
diff --git a/src/views/SkTextBox.cpp b/src/views/SkTextBox.cpp
index df7de986fa..0e31ac68e4 100644
--- a/src/views/SkTextBox.cpp
+++ b/src/views/SkTextBox.cpp
@@ -16,7 +16,7 @@
*/
#include "SkTextBox.h"
-#include "../src/core/SkGlyphCache.h"
+#include "../core/SkGlyphCache.h"
#include "SkUtils.h"
#include "SkAutoKern.h"
diff --git a/src/views/SkView.cpp b/src/views/SkView.cpp
index 652eb85025..7969d3d23c 100644
--- a/src/views/SkView.cpp
+++ b/src/views/SkView.cpp
@@ -49,6 +49,10 @@ void SkView::setFocusableP(bool pred)
this->setFlags(SkSetClearShift(fFlags, pred, kFocusable_Shift));
}
+void SkView::setClipToBounds(bool pred) {
+ this->setFlags(SkSetClearShift(fFlags, !pred, kNoClip_Shift));
+}
+
void SkView::setSize(SkScalar width, SkScalar height)
{
width = SkMaxScalar(0, width);
@@ -87,12 +91,16 @@ void SkView::draw(SkCanvas* canvas)
{
SkRect r;
r.set(fLoc.fX, fLoc.fY, fLoc.fX + fWidth, fLoc.fY + fHeight);
- if (canvas->quickReject(r, SkCanvas::kBW_EdgeType))
- return;
+ if (this->isClipToBounds() &&
+ canvas->quickReject(r, SkCanvas::kBW_EdgeType)) {
+ return;
+ }
SkAutoCanvasRestore as(canvas, true);
- canvas->clipRect(r);
+ if (this->isClipToBounds()) {
+ canvas->clipRect(r);
+ }
canvas->translate(fLoc.fX, fLoc.fY);
if (fParent) {
@@ -119,37 +127,36 @@ void SkView::draw(SkCanvas* canvas)
}
}
-void SkView::inval(SkRect* rect)
-{
- if (!this->isVisible())
- return;
-
- SkRect bounds;
-
- this->getLocalBounds(&bounds);
- if (rect && !bounds.intersect(*rect))
- return;
-
- rect = &bounds;
+void SkView::inval(SkRect* rect) {
SkView* view = this;
+ SkRect storage;
- for (;;)
- {
- if (view->handleInval(bounds))
- break;
+ for (;;) {
+ if (!view->isVisible()) {
+ return;
+ }
+ if (view->isClipToBounds()) {
+ SkRect bounds;
+ view->getLocalBounds(&bounds);
+ if (rect && !bounds.intersect(*rect)) {
+ return;
+ }
+ storage = bounds;
+ rect = &storage;
+ }
+ if (view->handleInval(rect)) {
+ return;
+ }
- SkRect parentR;
SkView* parent = view->fParent;
+ if (parent == NULL) {
+ return;
+ }
- if (parent == NULL || !parent->isVisible())
- break;
-
- bounds.offset(view->fLoc.fX, view->fLoc.fY);
- parent->getLocalBounds(&parentR);
- if (!bounds.intersect(parentR))
- return;
-
- view = parent;
+ if (rect) {
+ rect->offset(view->fLoc.fX, view->fLoc.fY);
+ }
+ view = parent;
}
}
@@ -456,7 +463,7 @@ bool SkView::onClick(Click*) {
return false;
}
-bool SkView::handleInval(const SkRect& r) {
+bool SkView::handleInval(const SkRect*) {
return false;
}
diff --git a/src/views/SkWindow.cpp b/src/views/SkWindow.cpp
index b63b81a1c0..dbc1eea242 100644
--- a/src/views/SkWindow.cpp
+++ b/src/views/SkWindow.cpp
@@ -1,5 +1,6 @@
#include "SkWindow.h"
#include "SkCanvas.h"
+#include "SkDevice.h"
#include "SkOSMenu.h"
#include "SkSystemEventTypes.h"
#include "SkTime.h"
@@ -48,6 +49,8 @@ SkWindow::SkWindow() : fFocusView(NULL)
#else
fConfig = SkBitmap::kARGB_8888_Config;
#endif
+
+ fMatrix.reset();
}
SkWindow::~SkWindow()
@@ -57,6 +60,25 @@ SkWindow::~SkWindow()
fMenus.deleteAll();
}
+void SkWindow::setMatrix(const SkMatrix& matrix) {
+ if (fMatrix != matrix) {
+ fMatrix = matrix;
+ this->inval(NULL);
+ }
+}
+
+void SkWindow::preConcat(const SkMatrix& matrix) {
+ SkMatrix m;
+ m.setConcat(fMatrix, matrix);
+ this->setMatrix(m);
+}
+
+void SkWindow::postConcat(const SkMatrix& matrix) {
+ SkMatrix m;
+ m.setConcat(matrix, fMatrix);
+ this->setMatrix(m);
+}
+
void SkWindow::setConfig(SkBitmap::Config config)
{
this->resize(fBitmap.width(), fBitmap.height(), config);
@@ -72,6 +94,7 @@ void SkWindow::resize(int width, int height, SkBitmap::Config config)
fConfig = config;
fBitmap.setConfig(config, width, height);
fBitmap.allocPixels();
+ fBitmap.setIsOpaque(true);
this->setSize(SkIntToScalar(width), SkIntToScalar(height));
this->inval(NULL);
@@ -88,25 +111,31 @@ void SkWindow::eraseRGB(U8CPU r, U8CPU g, U8CPU b)
fBitmap.eraseRGB(r, g, b);
}
-bool SkWindow::handleInval(const SkRect& r)
+bool SkWindow::handleInval(const SkRect* localR)
{
SkIRect ir;
- r.round(&ir);
+ if (localR) {
+ SkRect devR;
+ SkMatrix inverse;
+ if (!fMatrix.invert(&inverse)) {
+ return false;
+ }
+ fMatrix.mapRect(&devR, *localR);
+ devR.round(&ir);
+ } else {
+ ir.set(0, 0, this->width(), this->height());
+ }
fDirtyRgn.op(ir, SkRegion::kUnion_Op);
-#ifdef SK_BUILD_FOR_WIN32xxxx
- if (!fWaitingOnInval)
- {
- fWaitingOnInval = true;
- (new SkEvent(SK_EventDelayInval))->post(this->getSinkID(), 10);
- }
-#else
this->onHandleInval(ir);
-#endif
return true;
}
+void SkWindow::forceInvalAll() {
+ fDirtyRgn.setRect(0, 0, this->width(), this->height());
+}
+
#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
#include <windows.h>
#include <gx.h>
@@ -117,7 +146,7 @@ bool SkWindow::handleInval(const SkRect& r)
extern bool gEnableControlledThrow;
#endif
-bool SkWindow::update(SkIRect* updateArea)
+bool SkWindow::update(SkIRect* updateArea, SkCanvas* canvas)
{
if (!fDirtyRgn.isEmpty())
{
@@ -134,37 +163,49 @@ bool SkWindow::update(SkIRect* updateArea)
bm.setPixels(buffer);
#endif
- SkCanvas canvas(bm);
+ SkCanvas rasterCanvas;
+ SkDevice* device;
- canvas.clipRegion(fDirtyRgn);
+ if (NULL == canvas) {
+ canvas = &rasterCanvas;
+ device = new SkDevice(canvas, bm, false);
+ canvas->setDevice(device)->unref();
+ } else {
+ canvas->setBitmapDevice(bm);
+ }
+
+ canvas->clipRegion(fDirtyRgn);
if (updateArea)
*updateArea = fDirtyRgn.getBounds();
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->concat(fMatrix);
+
// empty this now, so we can correctly record any inval calls that
// might be made during the draw call.
fDirtyRgn.setEmpty();
#ifdef TEST_BOUNDER
test_bounder b(bm);
- canvas.setBounder(&b);
+ canvas->setBounder(&b);
#endif
#ifdef SK_SIMULATE_FAILED_MALLOC
gEnableControlledThrow = true;
#endif
#ifdef SK_BUILD_FOR_WIN32
- try {
- this->draw(&canvas);
- }
- catch (...) {
- }
+ //try {
+ this->draw(canvas);
+ //}
+ //catch (...) {
+ //}
#else
- this->draw(&canvas);
+ this->draw(canvas);
#endif
#ifdef SK_SIMULATE_FAILED_MALLOC
gEnableControlledThrow = false;
#endif
#ifdef TEST_BOUNDER
- canvas.setBounder(NULL);
+ canvas->setBounder(NULL);
#endif
#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)