Fix inverse scanconversion -- be sure to keep our calls to SkBlitter in scanline
order (top to bottom), since the region blitter explicitly requires this. git-svn-id: http://skia.googlecode.com/svn/trunk@876 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
7239aab311
commit
55b6b58d8f
@ -25,14 +25,14 @@ static const struct {
|
|||||||
{ SkPaint::kStrokeAndFill_Style, SkPaint::kMiter_Join, 10 },
|
{ SkPaint::kStrokeAndFill_Style, SkPaint::kMiter_Join, 10 },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TEST_INVERSE 0
|
#define TEST_INVERSE 1
|
||||||
|
|
||||||
class ComplexClipView : public SkView {
|
class ComplexClipView : public SkView {
|
||||||
SkScalar fWidth;
|
SkScalar fWidth;
|
||||||
public:
|
public:
|
||||||
ComplexClipView() {
|
ComplexClipView() {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// overrides from SkEventSink
|
// overrides from SkEventSink
|
||||||
virtual bool onQuery(SkEvent* evt) {
|
virtual bool onQuery(SkEvent* evt) {
|
||||||
@ -42,11 +42,11 @@ protected:
|
|||||||
}
|
}
|
||||||
return this->INHERITED::onQuery(evt);
|
return this->INHERITED::onQuery(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawBG(SkCanvas* canvas) {
|
void drawBG(SkCanvas* canvas) {
|
||||||
canvas->drawColor(SkColorSetRGB(0xA0,0xDD,0xA0));
|
canvas->drawColor(SkColorSetRGB(0xA0,0xDD,0xA0));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDraw(SkCanvas* canvas) {
|
virtual void onDraw(SkCanvas* canvas) {
|
||||||
SkPath path;
|
SkPath path;
|
||||||
path.moveTo(SkIntToScalar(0), SkIntToScalar(50));
|
path.moveTo(SkIntToScalar(0), SkIntToScalar(50));
|
||||||
@ -116,8 +116,8 @@ protected:
|
|||||||
canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
|
canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
|
||||||
canvas->save();
|
canvas->save();
|
||||||
|
|
||||||
int invALimit = TEST_INVERSE ? 1 : 2;
|
int invALimit = TEST_INVERSE ? 2 : 1;
|
||||||
for (int invA = 0; invALimit < 2; ++invA) {
|
for (int invA = 0; invA < invALimit; ++invA) {
|
||||||
for (int op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
|
for (int op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
|
||||||
int idx = invA * SK_ARRAY_COUNT(gOps) + op;
|
int idx = invA * SK_ARRAY_COUNT(gOps) + op;
|
||||||
if (!(idx % 3)) {
|
if (!(idx % 3)) {
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
**
|
**
|
||||||
** Copyright 2006, The Android Open Source Project
|
** Copyright 2006, The Android Open Source Project
|
||||||
**
|
**
|
||||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
** you may not use this file except in compliance with the License.
|
** you may not use this file except in compliance with the License.
|
||||||
** You may obtain a copy of the License at
|
** You may obtain a copy of the License at
|
||||||
**
|
**
|
||||||
** http://www.apache.org/licenses/LICENSE-2.0
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
**
|
**
|
||||||
** Unless required by applicable law or agreed to in writing, software
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
** See the License for the specific language governing permissions and
|
** See the License for the specific language governing permissions and
|
||||||
** limitations under the License.
|
** limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -40,9 +40,9 @@ void sk_fill_path(const SkPath& path, const SkIRect* clipRect,
|
|||||||
SkBlitter* blitter, int start_y, int stop_y, int shiftEdgesUp,
|
SkBlitter* blitter, int start_y, int stop_y, int shiftEdgesUp,
|
||||||
const SkRegion& clipRgn);
|
const SkRegion& clipRgn);
|
||||||
|
|
||||||
// blit the rects above and below avoid, clipped to clp
|
// blit the rects above and below avoid, clipped to clip
|
||||||
void sk_blit_above_and_below(SkBlitter* blitter, const SkIRect& avoid,
|
void sk_blit_above(SkBlitter*, const SkIRect& avoid, const SkRegion& clip);
|
||||||
const SkRegion& clip);
|
void sk_blit_below(SkBlitter*, const SkIRect& avoid, const SkRegion& clip);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
**
|
**
|
||||||
** Copyright 2006, The Android Open Source Project
|
** Copyright 2006, The Android Open Source Project
|
||||||
**
|
**
|
||||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
** you may not use this file except in compliance with the License.
|
** you may not use this file except in compliance with the License.
|
||||||
** You may obtain a copy of the License at
|
** You may obtain a copy of the License at
|
||||||
**
|
**
|
||||||
** http://www.apache.org/licenses/LICENSE-2.0
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
**
|
**
|
||||||
** Unless required by applicable law or agreed to in writing, software
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
** See the License for the specific language governing permissions and
|
** See the License for the specific language governing permissions and
|
||||||
** limitations under the License.
|
** limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -56,12 +56,12 @@ protected:
|
|||||||
BaseSuperBlitter::BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
|
BaseSuperBlitter::BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
|
||||||
const SkRegion& clip) {
|
const SkRegion& clip) {
|
||||||
fRealBlitter = realBlitter;
|
fRealBlitter = realBlitter;
|
||||||
|
|
||||||
// take the union of the ir bounds and clip, since we may be called with an
|
// take the union of the ir bounds and clip, since we may be called with an
|
||||||
// inverse filltype
|
// inverse filltype
|
||||||
const int left = SkMin32(ir.fLeft, clip.getBounds().fLeft);
|
const int left = SkMin32(ir.fLeft, clip.getBounds().fLeft);
|
||||||
const int right = SkMax32(ir.fRight, clip.getBounds().fRight);
|
const int right = SkMax32(ir.fRight, clip.getBounds().fRight);
|
||||||
|
|
||||||
fLeft = left;
|
fLeft = left;
|
||||||
fSuperLeft = left << SHIFT;
|
fSuperLeft = left << SHIFT;
|
||||||
fWidth = right - left;
|
fWidth = right - left;
|
||||||
@ -153,7 +153,7 @@ void SuperBlitter::blitH(int x, int y, int width)
|
|||||||
// int maxValue = (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT);
|
// int maxValue = (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
SkAntiRun<SHIFT> arun;
|
SkAntiRun<SHIFT> arun;
|
||||||
arun.set(x, x + width);
|
arun.set(x, x + width);
|
||||||
fRuns.add(x >> SHIFT, arun.getStartAlpha(), arun.getMiddleCount(), arun.getStopAlpha(), maxValue);
|
fRuns.add(x >> SHIFT, arun.getStartAlpha(), arun.getMiddleCount(), arun.getStopAlpha(), maxValue);
|
||||||
#else
|
#else
|
||||||
@ -215,11 +215,11 @@ public:
|
|||||||
{
|
{
|
||||||
int width = bounds.width();
|
int width = bounds.width();
|
||||||
int rb = SkAlign4(width);
|
int rb = SkAlign4(width);
|
||||||
|
|
||||||
return (width <= MaskSuperBlitter::kMAX_WIDTH) &&
|
return (width <= MaskSuperBlitter::kMAX_WIDTH) &&
|
||||||
(rb * bounds.height() <= MaskSuperBlitter::kMAX_STORAGE);
|
(rb * bounds.height() <= MaskSuperBlitter::kMAX_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
kMAX_WIDTH = 32, // so we don't try to do very wide things, where the RLE blitter would be faster
|
kMAX_WIDTH = 32, // so we don't try to do very wide things, where the RLE blitter would be faster
|
||||||
@ -242,10 +242,10 @@ MaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
|
|||||||
fMask.fBounds = ir;
|
fMask.fBounds = ir;
|
||||||
fMask.fRowBytes = ir.width();
|
fMask.fRowBytes = ir.width();
|
||||||
fMask.fFormat = SkMask::kA8_Format;
|
fMask.fFormat = SkMask::kA8_Format;
|
||||||
|
|
||||||
fClipRect = ir;
|
fClipRect = ir;
|
||||||
fClipRect.intersect(clip.getBounds());
|
fClipRect.intersect(clip.getBounds());
|
||||||
|
|
||||||
// For valgrind, write 1 extra byte at the end so we don't read
|
// For valgrind, write 1 extra byte at the end so we don't read
|
||||||
// uninitialized memory. See comment in add_aa_span and fStorage[].
|
// uninitialized memory. See comment in add_aa_span and fStorage[].
|
||||||
memset(fStorage, 0, fMask.fBounds.height() * fMask.fRowBytes + 1);
|
memset(fStorage, 0, fMask.fBounds.height() * fMask.fRowBytes + 1);
|
||||||
@ -292,7 +292,7 @@ static void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, U8CPU
|
|||||||
void MaskSuperBlitter::blitH(int x, int y, int width)
|
void MaskSuperBlitter::blitH(int x, int y, int width)
|
||||||
{
|
{
|
||||||
int iy = (y >> SHIFT);
|
int iy = (y >> SHIFT);
|
||||||
|
|
||||||
SkASSERT(iy >= fMask.fBounds.fTop && iy < fMask.fBounds.fBottom);
|
SkASSERT(iy >= fMask.fBounds.fTop && iy < fMask.fBounds.fBottom);
|
||||||
iy -= fMask.fBounds.fTop; // make it relative to 0
|
iy -= fMask.fBounds.fTop; // make it relative to 0
|
||||||
|
|
||||||
@ -309,7 +309,7 @@ void MaskSuperBlitter::blitH(int x, int y, int width)
|
|||||||
SkASSERT(ix >= fMask.fBounds.fLeft && ix < fMask.fBounds.fRight);
|
SkASSERT(ix >= fMask.fBounds.fLeft && ix < fMask.fBounds.fRight);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
x -= (fMask.fBounds.fLeft << SHIFT);
|
x -= (fMask.fBounds.fLeft << SHIFT);
|
||||||
|
|
||||||
// hack, until I figure out why my cubics (I think) go beyond the bounds
|
// hack, until I figure out why my cubics (I think) go beyond the bounds
|
||||||
@ -397,12 +397,12 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip,
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now use the (possibly wrapped) blitter
|
// now use the (possibly wrapped) blitter
|
||||||
blitter = clipper.getBlitter();
|
blitter = clipper.getBlitter();
|
||||||
|
|
||||||
if (path.isInverseFillType()) {
|
if (path.isInverseFillType()) {
|
||||||
sk_blit_above_and_below(blitter, ir, clip);
|
sk_blit_above(blitter, ir, clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkIRect superRect, *superClipRect = NULL;
|
SkIRect superRect, *superClipRect = NULL;
|
||||||
@ -429,4 +429,8 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip,
|
|||||||
SuperBlitter superBlit(blitter, ir, clip);
|
SuperBlitter superBlit(blitter, ir, clip);
|
||||||
sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, clip);
|
sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path.isInverseFillType()) {
|
||||||
|
sk_blit_below(blitter, ir, clip);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
**
|
**
|
||||||
** Copyright 2006, The Android Open Source Project
|
** Copyright 2006, The Android Open Source Project
|
||||||
**
|
**
|
||||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
** you may not use this file except in compliance with the License.
|
** you may not use this file except in compliance with the License.
|
||||||
** You may obtain a copy of the License at
|
** You may obtain a copy of the License at
|
||||||
**
|
**
|
||||||
** http://www.apache.org/licenses/LICENSE-2.0
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
**
|
**
|
||||||
** Unless required by applicable law or agreed to in writing, software
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
** See the License for the specific language governing permissions and
|
** See the License for the specific language governing permissions and
|
||||||
** limitations under the License.
|
** limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ static void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, cur
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
SkEdge* prev = edge->fPrev;
|
SkEdge* prev = edge->fPrev;
|
||||||
|
|
||||||
// add 1 to curr_y since we may have added new edges (built from curves)
|
// add 1 to curr_y since we may have added new edges (built from curves)
|
||||||
// that start on the next scanline
|
// that start on the next scanline
|
||||||
SkASSERT(prev && prev->fFirstY <= curr_y + 1);
|
SkASSERT(prev && prev->fFirstY <= curr_y + 1);
|
||||||
@ -145,11 +145,11 @@ static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType,
|
|||||||
SkFixed prevX = prevHead->fX;
|
SkFixed prevX = prevHead->fX;
|
||||||
|
|
||||||
validate_edges_for_y(currE, curr_y);
|
validate_edges_for_y(currE, curr_y);
|
||||||
|
|
||||||
if (proc) {
|
if (proc) {
|
||||||
proc(blitter, curr_y, PREPOST_START); // pre-proc
|
proc(blitter, curr_y, PREPOST_START); // pre-proc
|
||||||
}
|
}
|
||||||
|
|
||||||
while (currE->fFirstY <= curr_y)
|
while (currE->fFirstY <= curr_y)
|
||||||
{
|
{
|
||||||
SkASSERT(currE->fLastY >= curr_y);
|
SkASSERT(currE->fLastY >= curr_y);
|
||||||
@ -181,7 +181,7 @@ static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType,
|
|||||||
if (((SkCubicEdge*)currE)->updateCubic())
|
if (((SkCubicEdge*)currE)->updateCubic())
|
||||||
{
|
{
|
||||||
SkASSERT(currE->fFirstY == curr_y + 1);
|
SkASSERT(currE->fFirstY == curr_y + 1);
|
||||||
|
|
||||||
newX = currE->fX;
|
newX = currE->fX;
|
||||||
goto NEXT_X;
|
goto NEXT_X;
|
||||||
}
|
}
|
||||||
@ -210,7 +210,7 @@ static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType,
|
|||||||
currE = next;
|
currE = next;
|
||||||
SkASSERT(currE);
|
SkASSERT(currE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proc) {
|
if (proc) {
|
||||||
proc(blitter, curr_y, PREPOST_END); // post-proc
|
proc(blitter, curr_y, PREPOST_END); // post-proc
|
||||||
}
|
}
|
||||||
@ -257,7 +257,7 @@ public:
|
|||||||
}
|
}
|
||||||
fPrevX = x + width;
|
fPrevX = x + width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we do not expect to get called with these entrypoints
|
// we do not expect to get called with these entrypoints
|
||||||
virtual void blitAntiH(int, int, const SkAlpha[], const int16_t runs[]) {
|
virtual void blitAntiH(int, int, const SkAlpha[], const int16_t runs[]) {
|
||||||
SkASSERT(!"blitAntiH unexpected");
|
SkASSERT(!"blitAntiH unexpected");
|
||||||
@ -275,7 +275,7 @@ public:
|
|||||||
SkASSERT(!"justAnOpaqueColor unexpected");
|
SkASSERT(!"justAnOpaqueColor unexpected");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SkBlitter* fBlitter;
|
SkBlitter* fBlitter;
|
||||||
int fFirstX, fLastX, fPrevX;
|
int fFirstX, fLastX, fPrevX;
|
||||||
@ -313,7 +313,7 @@ static int build_edges(SkEdge edge[], const SkPath& path,
|
|||||||
SkPath::Iter iter(path, true);
|
SkPath::Iter iter(path, true);
|
||||||
SkPoint pts[4];
|
SkPoint pts[4];
|
||||||
SkPath::Verb verb;
|
SkPath::Verb verb;
|
||||||
|
|
||||||
SkQuadClipper qclipper;
|
SkQuadClipper qclipper;
|
||||||
if (clipRect) {
|
if (clipRect) {
|
||||||
SkIRect r;
|
SkIRect r;
|
||||||
@ -355,7 +355,7 @@ static int build_edges(SkEdge edge[], const SkPath& path,
|
|||||||
case SkPath::kCubic_Verb: {
|
case SkPath::kCubic_Verb: {
|
||||||
SkPoint tmp[10];
|
SkPoint tmp[10];
|
||||||
SkPoint* p = tmp;
|
SkPoint* p = tmp;
|
||||||
int count = SkChopCubicAtYExtrema(pts, tmp);
|
int count = SkChopCubicAtYExtrema(pts, tmp);
|
||||||
SkASSERT(count >= 0 && count <= 2);
|
SkASSERT(count >= 0 && count <= 2);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -417,7 +417,7 @@ static int worst_case_edge_count(const SkPath& path, size_t* storage)
|
|||||||
*/
|
*/
|
||||||
static int cheap_worst_case_edge_count(const SkPath& path, size_t* storage) {
|
static int cheap_worst_case_edge_count(const SkPath& path, size_t* storage) {
|
||||||
int ptCount = path.getPoints(NULL, 0);
|
int ptCount = path.getPoints(NULL, 0);
|
||||||
// worst case is curve, close, curve, close, as that is
|
// worst case is curve, close, curve, close, as that is
|
||||||
// 2 lines per pt, or : pts * 2
|
// 2 lines per pt, or : pts * 2
|
||||||
// 2 quads + 1 line per 2 pts, or : pts * 3 / 2
|
// 2 quads + 1 line per 2 pts, or : pts * 3 / 2
|
||||||
// 3 cubics + 1 line per 3 pts : pts * 4 / 3
|
// 3 cubics + 1 line per 3 pts : pts * 4 / 3
|
||||||
@ -442,15 +442,15 @@ extern "C" {
|
|||||||
static int edge_compare(const void* a, const void* b) {
|
static int edge_compare(const void* a, const void* b) {
|
||||||
const SkEdge* edgea = *(const SkEdge**)a;
|
const SkEdge* edgea = *(const SkEdge**)a;
|
||||||
const SkEdge* edgeb = *(const SkEdge**)b;
|
const SkEdge* edgeb = *(const SkEdge**)b;
|
||||||
|
|
||||||
int valuea = edgea->fFirstY;
|
int valuea = edgea->fFirstY;
|
||||||
int valueb = edgeb->fFirstY;
|
int valueb = edgeb->fFirstY;
|
||||||
|
|
||||||
if (valuea == valueb) {
|
if (valuea == valueb) {
|
||||||
valuea = edgea->fX;
|
valuea = edgea->fX;
|
||||||
valueb = edgeb->fX;
|
valueb = edgeb->fX;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this overflows if valuea >>> valueb or vice-versa
|
// this overflows if valuea >>> valueb or vice-versa
|
||||||
// return valuea - valueb;
|
// return valuea - valueb;
|
||||||
// do perform the slower but safe compares
|
// do perform the slower but safe compares
|
||||||
@ -460,13 +460,13 @@ extern "C" {
|
|||||||
|
|
||||||
static SkEdge* sort_edges(SkEdge* list[], int count, SkEdge** last) {
|
static SkEdge* sort_edges(SkEdge* list[], int count, SkEdge** last) {
|
||||||
qsort(list, count, sizeof(SkEdge*), edge_compare);
|
qsort(list, count, sizeof(SkEdge*), edge_compare);
|
||||||
|
|
||||||
// now make the edges linked in sorted order
|
// now make the edges linked in sorted order
|
||||||
for (int i = 1; i < count; i++) {
|
for (int i = 1; i < count; i++) {
|
||||||
list[i - 1]->fNext = list[i];
|
list[i - 1]->fNext = list[i];
|
||||||
list[i]->fPrev = list[i - 1];
|
list[i]->fPrev = list[i - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
*last = list[count - 1];
|
*last = list[count - 1];
|
||||||
return list[0];
|
return list[0];
|
||||||
}
|
}
|
||||||
@ -483,7 +483,7 @@ void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte
|
|||||||
|
|
||||||
#ifdef USE_NEW_BUILDER
|
#ifdef USE_NEW_BUILDER
|
||||||
SkEdgeBuilder builder;
|
SkEdgeBuilder builder;
|
||||||
|
|
||||||
int count = builder.build(path, clipRect, shiftEdgesUp);
|
int count = builder.build(path, clipRect, shiftEdgesUp);
|
||||||
SkEdge** list = builder.edgeList();
|
SkEdge** list = builder.edgeList();
|
||||||
#else
|
#else
|
||||||
@ -494,7 +494,7 @@ void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte
|
|||||||
{
|
{
|
||||||
size_t size2;
|
size_t size2;
|
||||||
int maxCount2 = worst_case_edge_count(path, &size2);
|
int maxCount2 = worst_case_edge_count(path, &size2);
|
||||||
|
|
||||||
SkASSERT(maxCount >= maxCount2 && size >= size2);
|
SkASSERT(maxCount >= maxCount2 && size >= size2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -557,20 +557,25 @@ void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte
|
|||||||
walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc);
|
walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sk_blit_above_and_below(SkBlitter* blitter, const SkIRect& ir,
|
void sk_blit_above(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) {
|
||||||
const SkRegion& clip) {
|
|
||||||
const SkIRect& cr = clip.getBounds();
|
const SkIRect& cr = clip.getBounds();
|
||||||
SkIRect tmp;
|
SkIRect tmp;
|
||||||
|
|
||||||
tmp.fLeft = cr.fLeft;
|
tmp.fLeft = cr.fLeft;
|
||||||
tmp.fRight = cr.fRight;
|
tmp.fRight = cr.fRight;
|
||||||
|
|
||||||
tmp.fTop = cr.fTop;
|
tmp.fTop = cr.fTop;
|
||||||
tmp.fBottom = ir.fTop;
|
tmp.fBottom = ir.fTop;
|
||||||
if (!tmp.isEmpty()) {
|
if (!tmp.isEmpty()) {
|
||||||
blitter->blitRectRegion(tmp, clip);
|
blitter->blitRectRegion(tmp, clip);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sk_blit_below(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) {
|
||||||
|
const SkIRect& cr = clip.getBounds();
|
||||||
|
SkIRect tmp;
|
||||||
|
|
||||||
|
tmp.fLeft = cr.fLeft;
|
||||||
|
tmp.fRight = cr.fRight;
|
||||||
tmp.fTop = ir.fBottom;
|
tmp.fTop = ir.fBottom;
|
||||||
tmp.fBottom = cr.fBottom;
|
tmp.fBottom = cr.fBottom;
|
||||||
if (!tmp.isEmpty()) {
|
if (!tmp.isEmpty()) {
|
||||||
@ -635,10 +640,15 @@ void SkScan::FillPath(const SkPath& path, const SkRegion& clip,
|
|||||||
|
|
||||||
blitter = clipper.getBlitter();
|
blitter = clipper.getBlitter();
|
||||||
if (blitter) {
|
if (blitter) {
|
||||||
|
// we have to keep our calls to blitter in sorted order, so we
|
||||||
|
// must blit the above section first, then the middle, then the bottom.
|
||||||
if (path.isInverseFillType()) {
|
if (path.isInverseFillType()) {
|
||||||
sk_blit_above_and_below(blitter, ir, clip);
|
sk_blit_above(blitter, ir, clip);
|
||||||
}
|
}
|
||||||
sk_fill_path(path, clipper.getClipRect(), blitter, ir.fTop, ir.fBottom, 0, clip);
|
sk_fill_path(path, clipper.getClipRect(), blitter, ir.fTop, ir.fBottom, 0, clip);
|
||||||
|
if (path.isInverseFillType()) {
|
||||||
|
sk_blit_below(blitter, ir, clip);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// what does it mean to not have a blitter if path.isInverseFillType???
|
// what does it mean to not have a blitter if path.isInverseFillType???
|
||||||
}
|
}
|
||||||
@ -649,7 +659,7 @@ void SkScan::FillPath(const SkPath& path, const SkRegion& clip,
|
|||||||
static int build_tri_edges(SkEdge edge[], const SkPoint pts[],
|
static int build_tri_edges(SkEdge edge[], const SkPoint pts[],
|
||||||
const SkIRect* clipRect, SkEdge* list[]) {
|
const SkIRect* clipRect, SkEdge* list[]) {
|
||||||
SkEdge** start = list;
|
SkEdge** start = list;
|
||||||
|
|
||||||
if (edge->setLine(pts[0], pts[1], clipRect, 0)) {
|
if (edge->setLine(pts[0], pts[1], clipRect, 0)) {
|
||||||
*list++ = edge;
|
*list++ = edge;
|
||||||
edge = (SkEdge*)((char*)edge + sizeof(SkEdge));
|
edge = (SkEdge*)((char*)edge + sizeof(SkEdge));
|
||||||
@ -668,7 +678,7 @@ static int build_tri_edges(SkEdge edge[], const SkPoint pts[],
|
|||||||
static void sk_fill_triangle(const SkPoint pts[], const SkIRect* clipRect,
|
static void sk_fill_triangle(const SkPoint pts[], const SkIRect* clipRect,
|
||||||
SkBlitter* blitter, const SkIRect& ir) {
|
SkBlitter* blitter, const SkIRect& ir) {
|
||||||
SkASSERT(pts && blitter);
|
SkASSERT(pts && blitter);
|
||||||
|
|
||||||
SkEdge edgeStorage[3];
|
SkEdge edgeStorage[3];
|
||||||
SkEdge* list[3];
|
SkEdge* list[3];
|
||||||
|
|
||||||
@ -681,18 +691,18 @@ static void sk_fill_triangle(const SkPoint pts[], const SkIRect* clipRect,
|
|||||||
|
|
||||||
// this returns the first and last edge after they're sorted into a dlink list
|
// this returns the first and last edge after they're sorted into a dlink list
|
||||||
SkEdge* edge = sort_edges(list, count, &last);
|
SkEdge* edge = sort_edges(list, count, &last);
|
||||||
|
|
||||||
headEdge.fPrev = NULL;
|
headEdge.fPrev = NULL;
|
||||||
headEdge.fNext = edge;
|
headEdge.fNext = edge;
|
||||||
headEdge.fFirstY = kEDGE_HEAD_Y;
|
headEdge.fFirstY = kEDGE_HEAD_Y;
|
||||||
headEdge.fX = SK_MinS32;
|
headEdge.fX = SK_MinS32;
|
||||||
edge->fPrev = &headEdge;
|
edge->fPrev = &headEdge;
|
||||||
|
|
||||||
tailEdge.fPrev = last;
|
tailEdge.fPrev = last;
|
||||||
tailEdge.fNext = NULL;
|
tailEdge.fNext = NULL;
|
||||||
tailEdge.fFirstY = kEDGE_TAIL_Y;
|
tailEdge.fFirstY = kEDGE_TAIL_Y;
|
||||||
last->fNext = &tailEdge;
|
last->fNext = &tailEdge;
|
||||||
|
|
||||||
// now edge is the head of the sorted linklist
|
// now edge is the head of the sorted linklist
|
||||||
int stop_y = ir.fBottom;
|
int stop_y = ir.fBottom;
|
||||||
if (clipRect && stop_y > clipRect->fBottom) {
|
if (clipRect && stop_y > clipRect->fBottom) {
|
||||||
@ -710,7 +720,7 @@ void SkScan::FillTriangle(const SkPoint pts[], const SkRegion* clip,
|
|||||||
if (clip && clip->isEmpty()) {
|
if (clip && clip->isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkRect r;
|
SkRect r;
|
||||||
SkIRect ir;
|
SkIRect ir;
|
||||||
r.set(pts, 3);
|
r.set(pts, 3);
|
||||||
@ -718,9 +728,9 @@ void SkScan::FillTriangle(const SkPoint pts[], const SkRegion* clip,
|
|||||||
if (ir.isEmpty()) {
|
if (ir.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkScanClipper clipper(blitter, clip, ir);
|
SkScanClipper clipper(blitter, clip, ir);
|
||||||
|
|
||||||
blitter = clipper.getBlitter();
|
blitter = clipper.getBlitter();
|
||||||
if (NULL != blitter) {
|
if (NULL != blitter) {
|
||||||
sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir);
|
sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir);
|
||||||
|
Loading…
Reference in New Issue
Block a user