Review URL: https://codereview.chromium.org/23626002

git-svn-id: http://skia.googlecode.com/svn/trunk@10944 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
rmistry@google.com 2013-08-27 18:53:41 +00:00
Родитель 42cb6c0247
Коммит e09d6f4819
5 изменённых файлов: 46 добавлений и 219 удалений

Просмотреть файл

@ -70,7 +70,6 @@
'<(skia_src_path)/core/SkDebug.cpp',
'<(skia_src_path)/core/SkDeque.cpp',
'<(skia_src_path)/core/SkDevice.cpp',
'<(skia_src_path)/core/SkDeviceLooper.cpp',
'<(skia_src_path)/core/SkDeviceProfile.cpp',
'<(skia_src_path)/core/SkDither.cpp',
'<(skia_src_path)/core/SkDraw.cpp',

Просмотреть файл

@ -1,97 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkDeviceLooper.h"
SkDeviceLooper::SkDeviceLooper(const SkBitmap& base,
const SkRasterClip& rc,
const SkIRect& bounds, bool aa)
: fBaseBitmap(base)
, fBaseRC(rc)
, fDelta(aa ? kAA_Delta : kBW_Delta)
{
SkIRect bitmapBounds = SkIRect::MakeWH(base.width(), base.height());
if (!fClippedBounds.intersect(bounds, bitmapBounds)) {
fState = kDone_State;
} else if (this->fitsInDelta(bounds)) {
fCurrBitmap = &fBaseBitmap;
fCurrRC = &fBaseRC;
fState = kSimple_State;
} else {
fCurrBitmap = &fSubsetBitmap;
fCurrRC = &fSubsetRC;
// back up by 1 DX, so that next() will put us in a correct starting
// position.
fCurrOffset.set(fClippedBounds.left() - fDelta,
fClippedBounds.top());
fState = kComplex_State;
}
}
SkDeviceLooper::~SkDeviceLooper() {
}
void SkDeviceLooper::mapRect(SkRect* dst, const SkRect& src) const {
SkASSERT(kDone_State != fState);
*dst = src;
dst->offset(SkIntToScalar(-fCurrOffset.fX),
SkIntToScalar(-fCurrOffset.fY));
}
void SkDeviceLooper::mapMatrix(SkMatrix* dst, const SkMatrix& src) const {
SkASSERT(kDone_State != fState);
*dst = src;
dst->postTranslate(SkIntToScalar(-fCurrOffset.fX),
SkIntToScalar(-fCurrOffset.fY));
}
bool SkDeviceLooper::computeCurrBitmapAndClip() {
SkASSERT(kComplex_State == fState);
SkIRect r = SkIRect::MakeXYWH(fCurrOffset.x(), fCurrOffset.y(),
fDelta, fDelta);
if (!fBaseBitmap.extractSubset(&fSubsetBitmap, r)) {
fState = kDone_State;
return false;
}
fSubsetBitmap.lockPixels();
fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC);
(void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta), SkRegion::kIntersect_Op);
return true;
}
bool SkDeviceLooper::next() {
if (kDone_State == fState) {
return false;
}
if (kSimple_State == fState) {
fCurrBitmap = &fBaseBitmap;
fCurrRC = &fBaseRC;
fCurrOffset.set(0, 0);
fState = kDone_State;
return true;
}
SkASSERT(kComplex_State == fState);
// need to propogate fCurrOffset through clippedbounds
// left to right, until we wrap around and move down
if (fCurrOffset.x() + fDelta < fClippedBounds.right()) {
fCurrOffset.fX += fDelta;
return this->computeCurrBitmapAndClip();
}
fCurrOffset.fX = fClippedBounds.left();
if (fCurrOffset.y() + fDelta < fClippedBounds.bottom()) {
fCurrOffset.fY += fDelta;
return this->computeCurrBitmapAndClip();
}
fState = kDone_State;
return false;
}

Просмотреть файл

@ -1,69 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkDeviceLooper_DEFINED
#define SkDeviceLooper_DEFINED
#include "SkBitmap.h"
#include "SkMatrix.h"
#include "SkRasterClip.h"
class SkDeviceLooper {
public:
SkDeviceLooper(const SkBitmap& base, const SkRasterClip&,
const SkIRect& bounds, bool aa);
~SkDeviceLooper();
const SkBitmap& getBitmap() const {
SkASSERT(kDone_State != fState);
return *fCurrBitmap;
}
const SkRasterClip& getRC() const {
SkASSERT(kDone_State != fState);
return *fCurrRC;
}
void mapRect(SkRect* dst, const SkRect& src) const;
void mapMatrix(SkMatrix* dst, const SkMatrix& src) const;
bool next();
private:
const SkBitmap& fBaseBitmap;
const SkRasterClip& fBaseRC;
enum State {
kDone_State, // iteration is complete, getters will assert
kSimple_State, // no translate/clip mods needed
kComplex_State
};
// storage for our tiled versions. Perhaps could use SkTLazy
SkBitmap fSubsetBitmap;
SkRasterClip fSubsetRC;
const SkBitmap* fCurrBitmap;
const SkRasterClip* fCurrRC;
SkIRect fClippedBounds;
SkIPoint fCurrOffset;
int fDelta;
State fState;
enum Delta {
kBW_Delta = 1 << 14, // 16K, gives room to spare for fixedpoint
kAA_Delta = kBW_Delta >> 2 // supersample 4x
};
bool fitsInDelta(const SkIRect& r) const {
return r.right() < fDelta && r.bottom() < fDelta;
}
bool computeCurrBitmapAndClip();
};
#endif

Просмотреть файл

@ -5,13 +5,13 @@
* found in the LICENSE file.
*/
#include "SkDraw.h"
#include "SkBlitter.h"
#include "SkBounder.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
#include "SkDevice.h"
#include "SkDeviceLooper.h"
#include "SkFixed.h"
#include "SkMaskFilter.h"
#include "SkPaint.h"
@ -873,56 +873,48 @@ void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const {
}
// look for the quick exit, before we build a blitter
SkIRect ir;
devRect.roundOut(&ir);
if (paint.getStyle() != SkPaint::kFill_Style) {
// extra space for hairlines
ir.inset(-1, -1);
}
if (fRC->quickReject(ir)) {
return;
}
SkDeviceLooper looper(*fBitmap, *fRC, ir, paint.isAntiAlias());
while (looper.next()) {
SkRect localDevRect;
looper.mapRect(&localDevRect, devRect);
SkMatrix localMatrix;
looper.mapMatrix(&localMatrix, matrix);
SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix,
paint);
const SkRasterClip& clip = looper.getRC();
SkBlitter* blitter = blitterStorage.get();
// we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
// case we are also hairline (if we've gotten to here), which devolves to
// effectively just kFill
switch (rtype) {
case kFill_RectType:
if (paint.isAntiAlias()) {
SkScan::AntiFillRect(localDevRect, clip, blitter);
} else {
SkScan::FillRect(localDevRect, clip, blitter);
}
break;
case kStroke_RectType:
if (paint.isAntiAlias()) {
SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter);
} else {
SkScan::FrameRect(localDevRect, strokeSize, clip, blitter);
}
break;
case kHair_RectType:
if (paint.isAntiAlias()) {
SkScan::AntiHairRect(localDevRect, clip, blitter);
} else {
SkScan::HairRect(localDevRect, clip, blitter);
}
break;
default:
SkDEBUGFAIL("bad rtype");
if (true) {
SkIRect ir;
devRect.roundOut(&ir);
if (paint.getStyle() != SkPaint::kFill_Style) {
// extra space for hairlines
ir.inset(-1, -1);
}
if (fRC->quickReject(ir))
return;
}
SkAutoBlitterChoose blitterStorage(*fBitmap, matrix, paint);
const SkRasterClip& clip = *fRC;
SkBlitter* blitter = blitterStorage.get();
// we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
// case we are also hairline (if we've gotten to here), which devolves to
// effectively just kFill
switch (rtype) {
case kFill_RectType:
if (paint.isAntiAlias()) {
SkScan::AntiFillRect(devRect, clip, blitter);
} else {
SkScan::FillRect(devRect, clip, blitter);
}
break;
case kStroke_RectType:
if (paint.isAntiAlias()) {
SkScan::AntiFrameRect(devRect, strokeSize, clip, blitter);
} else {
SkScan::FrameRect(devRect, strokeSize, clip, blitter);
}
break;
case kHair_RectType:
if (paint.isAntiAlias()) {
SkScan::AntiHairRect(devRect, clip, blitter);
} else {
SkScan::HairRect(devRect, clip, blitter);
}
break;
default:
SkDEBUGFAIL("bad rtype");
}
}
@ -2833,4 +2825,3 @@ bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
return true;
}

Просмотреть файл

@ -320,7 +320,10 @@ static void TestDrawPath(skiatest::Reporter* reporter) {
if (false) test_crbug131181();
test_infinite_dash(reporter);
test_crbug_165432(reporter);
test_big_aa_rect(reporter);
if (false) { // working on a fix
test_big_aa_rect(reporter);
}
}
#include "TestClassDef.h"