git-svn-id: http://skia.googlecode.com/svn/trunk@1090 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
mike@reedtribe.org 2011-04-09 19:16:54 +00:00
Родитель 99219d337f
Коммит bcc1d33e94
3 изменённых файлов: 89 добавлений и 110 удалений

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

@ -21,12 +21,11 @@
typedef int32_t SkFDot6;
#define SK_FDot61 (64)
#define SK_FDot6One (64)
#define SK_FDot6Half (32)
#ifdef SK_DEBUG
inline SkFDot6 SkIntToFDot6(S16CPU x)
{
inline SkFDot6 SkIntToFDot6(S16CPU x) {
SkASSERT(SkToS16(x) == x);
return x << 6;
}
@ -40,8 +39,7 @@ typedef int32_t SkFDot6;
#define SkFixedToFDot6(x) ((x) >> 10)
inline SkFixed SkFDot6ToFixed(SkFDot6 x)
{
inline SkFixed SkFDot6ToFixed(SkFDot6 x) {
SkASSERT((x << 10 >> 10) == x);
return x << 10;
@ -53,14 +51,14 @@ inline SkFixed SkFDot6ToFixed(SkFDot6 x)
#define SkScalarToFDot6(x) ((x) >> 10)
#endif
inline SkFixed SkFDot6Div(SkFDot6 a, SkFDot6 b)
{
inline SkFixed SkFDot6Div(SkFDot6 a, SkFDot6 b) {
SkASSERT(b != 0);
if (a == (int16_t)a)
if (a == (int16_t)a) {
return (a << 16) / b;
else
} else {
return SkFixedDiv(a, b);
}
}
#endif

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

@ -51,14 +51,11 @@ static inline int SmallDot6Scale(int value, int dot6) {
static uint8_t gGammaTable[256];
#define ApplyGamma(table, alpha) (table)[alpha]
static void build_gamma_table()
{
static void build_gamma_table() {
static bool gInit = false;
if (gInit == false)
{
for (int i = 0; i < 256; i++)
{
if (gInit == false) {
for (int i = 0; i < 256; i++) {
SkFixed n = i * 257;
n += n >> 15;
SkASSERT(n >= 0 && n <= SK_Fixed1);
@ -76,8 +73,8 @@ static inline int SmallDot6Scale(int value, int dot6) {
///////////////////////////////////////////////////////////////////////////////
static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, U8CPU alpha)
{
static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count,
U8CPU alpha) {
SkASSERT(count > 0);
int16_t runs[HLINE_STACK_BUFFER + 1];
@ -86,9 +83,9 @@ static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, U8CP
aa[0] = ApplyGamma(gGammaTable, alpha);
do {
int n = count;
if (n > HLINE_STACK_BUFFER)
if (n > HLINE_STACK_BUFFER) {
n = HLINE_STACK_BUFFER;
}
runs[0] = SkToS16(n);
runs[n] = 0;
blitter->blitAntiH(x, y, aa, runs);
@ -97,8 +94,8 @@ static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, U8CP
} while (count > 0);
}
static SkFixed hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/, SkBlitter* blitter, int mod64)
{
static SkFixed hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/,
SkBlitter* blitter, int mod64) {
SkASSERT(x < stopx);
int count = stopx - x;
fy += SK_Fixed1/2;
@ -121,8 +118,8 @@ static SkFixed hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/, SkBlitter*
return fy - SK_Fixed1/2;
}
static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitter, int mod64)
{
static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy,
SkBlitter* blitter, int mod64) {
SkASSERT(x < stopx);
#ifdef TEST_GAMMA
@ -139,8 +136,7 @@ static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitt
int lower_y = fy >> 16;
uint8_t a = (uint8_t)(fy >> 8);
unsigned ma = SmallDot6Scale(a, mod64);
if (ma)
{
if (ma) {
aa[0] = ApplyGamma(gamma, ma);
blitter->blitAntiH(x, lower_y, aa, runs);
// the clipping blitters might edit runs, but should not affect us
@ -148,8 +144,7 @@ static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitt
SkASSERT(runs[1] == 0);
}
ma = SmallDot6Scale(255 - a, mod64);
if (ma)
{
if (ma) {
aa[0] = ApplyGamma(gamma, ma);
blitter->blitAntiH(x, lower_y - 1, aa, runs);
// the clipping blitters might edit runs, but should not affect us
@ -162,8 +157,8 @@ static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitt
return fy - SK_Fixed1/2;
}
static SkFixed vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/, SkBlitter* blitter, int mod64)
{
static SkFixed vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/,
SkBlitter* blitter, int mod64) {
SkASSERT(y < stopy);
fx += SK_Fixed1/2;
@ -171,17 +166,19 @@ static SkFixed vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/, SkBlitter*
int a = (uint8_t)(fx >> 8);
unsigned ma = SmallDot6Scale(a, mod64);
if (ma)
if (ma) {
blitter->blitV(x, y, stopy - y, ApplyGamma(gGammaTable, ma));
}
ma = SmallDot6Scale(255 - a, mod64);
if (ma)
if (ma) {
blitter->blitV(x - 1, y, stopy - y, ApplyGamma(gGammaTable, ma));
}
return fx - SK_Fixed1/2;
}
static SkFixed vertish(int y, int stopy, SkFixed fx, SkFixed dx, SkBlitter* blitter, int mod64)
{
static SkFixed vertish(int y, int stopy, SkFixed fx, SkFixed dx,
SkBlitter* blitter, int mod64) {
SkASSERT(y < stopy);
#ifdef TEST_GAMMA
const uint8_t* gamma = gGammaTable;
@ -211,23 +208,21 @@ static SkFixed vertish(int y, int stopy, SkFixed fx, SkFixed dx, SkBlitter* blit
return fx - SK_Fixed1/2;
}
typedef SkFixed (*LineProc)(int istart, int istop, SkFixed fstart, SkFixed slope, SkBlitter*, int);
typedef SkFixed (*LineProc)(int istart, int istop, SkFixed fstart,
SkFixed slope, SkBlitter*, int);
static inline SkFixed fastfixdiv(SkFDot6 a, SkFDot6 b)
{
static inline SkFixed fastfixdiv(SkFDot6 a, SkFDot6 b) {
SkASSERT((a << 16 >> 16) == a);
SkASSERT(b != 0);
return (a << 16) / b;
}
static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
const SkIRect* clip, SkBlitter* blitter)
{
const SkIRect* clip, SkBlitter* blitter) {
// check that we're no larger than 511 pixels (so we can do a faster div).
// if we are, subdivide and call again
if (SkAbs32(x1 - x0) > SkIntToFDot6(511) || SkAbs32(y1 - y0) > SkIntToFDot6(511))
{
if (SkAbs32(x1 - x0) > SkIntToFDot6(511) || SkAbs32(y1 - y0) > SkIntToFDot6(511)) {
/* instead of (x0 + x1) >> 1, we shift each separately. This is less
precise, but avoids overflowing the intermediate result if the
values are huge. A better fix might be to clip the original pts
@ -246,8 +241,7 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
SkFixed fstart, slope;
LineProc proc;
if (SkAbs32(x1 - x0) > SkAbs32(y1 - y0)) // mostly horizontal
{
if (SkAbs32(x1 - x0) > SkAbs32(y1 - y0)) { // mostly horizontal
if (x0 > x1) { // we want to go left-to-right
SkTSwap<SkFDot6>(x0, x1);
SkTSwap<SkFDot6>(y0, y1);
@ -276,12 +270,11 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
scaleStop = x1 & 63;
}
if (clip)
{
if (istart >= clip->fRight || istop <= clip->fLeft)
if (clip){
if (istart >= clip->fRight || istop <= clip->fLeft) {
return;
if (istart < clip->fLeft)
{
}
if (istart < clip->fLeft) {
fstart += slope * (clip->fLeft - istart);
istart = clip->fLeft;
scaleStart = 64;
@ -291,18 +284,15 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
scaleStop = 64;
}
SkASSERT(istart <= istop);
if (istart == istop)
if (istart == istop) {
return;
}
// now test if our Y values are completely inside the clip
int top, bottom;
if (slope >= 0) // T2B
{
if (slope >= 0) { // T2B
top = SkFixedFloor(fstart - SK_FixedHalf);
bottom = SkFixedCeil(fstart + (istop - istart - 1) * slope + SK_FixedHalf);
}
else // B2T
{
} else { // B2T
bottom = SkFixedCeil(fstart + SK_FixedHalf);
top = SkFixedFloor(fstart + (istop - istart - 1) * slope - SK_FixedHalf);
}
@ -310,16 +300,15 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
top -= 1;
bottom += 1;
#endif
if (top >= clip->fBottom || bottom <= clip->fTop)
if (top >= clip->fBottom || bottom <= clip->fTop) {
return;
if (clip->fTop <= top && clip->fBottom >= bottom)
}
if (clip->fTop <= top && clip->fBottom >= bottom) {
clip = NULL;
}
}
}
else // mostly vertical
{
if (y0 > y1) // we want to go top-to-bottom
{
} else { // mostly vertical
if (y0 > y1) { // we want to go top-to-bottom
SkTSwap<SkFDot6>(x0, x1);
SkTSwap<SkFDot6>(y0, y1);
}
@ -327,16 +316,13 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
istart = SkFDot6Floor(y0);
istop = SkFDot6Ceil(y1);
fstart = SkFDot6ToFixed(x0);
if (x0 == x1)
{
if (x0 == x1) {
if (y0 == y1) { // are we zero length?
return; // nothing to do
}
slope = 0;
proc = vline;
}
else
{
} else {
slope = fastfixdiv(x1 - x0, y1 - y0);
SkASSERT(slope <= SK_Fixed1 && slope >= -SK_Fixed1);
fstart += (slope * (32 - (y0 & 63)) + 32) >> 6;
@ -353,12 +339,11 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
scaleStop = y1 & 63;
}
if (clip)
{
if (istart >= clip->fBottom || istop <= clip->fTop)
if (clip) {
if (istart >= clip->fBottom || istop <= clip->fTop) {
return;
if (istart < clip->fTop)
{
}
if (istart < clip->fTop) {
fstart += slope * (clip->fTop - istart);
istart = clip->fTop;
scaleStart = 64;
@ -373,13 +358,10 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
// now test if our X values are completely inside the clip
int left, right;
if (slope >= 0) // L2R
{
if (slope >= 0) { // L2R
left = SkFixedFloor(fstart - SK_FixedHalf);
right = SkFixedCeil(fstart + (istop - istart - 1) * slope + SK_FixedHalf);
}
else // R2L
{
} else { // R2L
right = SkFixedCeil(fstart + SK_FixedHalf);
left = SkFixedFloor(fstart + (istop - istart - 1) * slope - SK_FixedHalf);
}
@ -387,16 +369,17 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
left -= 1;
right += 1;
#endif
if (left >= clip->fRight || right <= clip->fLeft)
if (left >= clip->fRight || right <= clip->fLeft) {
return;
if (clip->fLeft <= left && clip->fRight >= right)
}
if (clip->fLeft <= left && clip->fRight >= right) {
clip = NULL;
}
}
}
SkRectClipBlitter rectClipper;
if (clip)
{
if (clip) {
rectClipper.init(blitter, *clip);
blitter = &rectClipper;
}
@ -413,10 +396,10 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
}
void SkScan::AntiHairLine(const SkPoint& pt0, const SkPoint& pt1,
const SkRegion* clip, SkBlitter* blitter)
{
if (clip && clip->isEmpty())
const SkRegion* clip, SkBlitter* blitter) {
if (clip && clip->isEmpty()) {
return;
}
SkASSERT(clip == NULL || !clip->getBounds().isEmpty());
@ -480,8 +463,8 @@ void SkScan::AntiHairLine(const SkPoint& pt0, const SkPoint& pt1,
do_anti_hairline(x0, y0, x1, y1, NULL, blitter);
}
void SkScan::AntiHairRect(const SkRect& rect, const SkRegion* clip, SkBlitter* blitter)
{
void SkScan::AntiHairRect(const SkRect& rect, const SkRegion* clip,
SkBlitter* blitter) {
SkPoint p0, p1;
p0.set(rect.fLeft, rect.fTop);
@ -495,7 +478,7 @@ void SkScan::AntiHairRect(const SkRect& rect, const SkRegion* clip, SkBlitter* b
SkScan::AntiHairLine(p0, p1, clip, blitter);
}
//////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
typedef int FDot8; // 24.8 integer fixed point
@ -503,72 +486,70 @@ static inline FDot8 SkFixedToFDot8(SkFixed x) {
return (x + 0x80) >> 8;
}
static void do_scanline(FDot8 L, int top, FDot8 R, U8CPU alpha, SkBlitter* blitter)
{
static void do_scanline(FDot8 L, int top, FDot8 R, U8CPU alpha,
SkBlitter* blitter) {
SkASSERT(L < R);
if ((L >> 8) == ((R - 1) >> 8)) // 1x1 pixel
{
if ((L >> 8) == ((R - 1) >> 8)) { // 1x1 pixel
blitter->blitV(L >> 8, top, 1, SkAlphaMul(alpha, R - L));
return;
}
int left = L >> 8;
if (L & 0xFF)
{
if (L & 0xFF) {
blitter->blitV(left, top, 1, SkAlphaMul(alpha, 256 - (L & 0xFF)));
left += 1;
}
int rite = R >> 8;
int width = rite - left;
if (width > 0)
if (width > 0) {
call_hline_blitter(blitter, left, top, width, alpha);
if (R & 0xFF)
}
if (R & 0xFF) {
blitter->blitV(rite, top, 1, SkAlphaMul(alpha, R & 0xFF));
}
}
static void antifilldot8(FDot8 L, FDot8 T, FDot8 R, FDot8 B, SkBlitter* blitter,
bool fillInner) {
// check for empty now that we're in our reduced precision space
if (L >= R || T >= B)
if (L >= R || T >= B) {
return;
}
int top = T >> 8;
if (top == ((B - 1) >> 8)) // just one scanline high
{
if (top == ((B - 1) >> 8)) { // just one scanline high
do_scanline(L, top, R, B - T - 1, blitter);
return;
}
if (T & 0xFF)
{
if (T & 0xFF) {
do_scanline(L, top, R, 256 - (T & 0xFF), blitter);
top += 1;
}
int bot = B >> 8;
int height = bot - top;
if (height > 0)
{
if (height > 0) {
int left = L >> 8;
if (L & 0xFF)
{
if (L & 0xFF) {
blitter->blitV(left, top, height, 256 - (L & 0xFF));
left += 1;
}
int rite = R >> 8;
int width = rite - left;
if (width > 0 && fillInner)
if (width > 0 && fillInner) {
blitter->blitRect(left, top, width, height);
if (R & 0xFF)
}
if (R & 0xFF) {
blitter->blitV(rite, top, height, R & 0xFF);
}
}
if (B & 0xFF)
if (B & 0xFF) {
do_scanline(L, bot, R, B & 0xFF, blitter);
}
}
static void antifillrect(const SkXRect& xr, SkBlitter* blitter) {

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

@ -76,8 +76,8 @@ void SkScan::HairLine(const SkPoint& pt0, const SkPoint& pt1, const SkRegion* cl
// outset the right and bottom, to account for how hairlines are
// actually drawn, which may hit the pixel to the right or below of
// the coordinate
ptsR.fRight += SK_FDot61;
ptsR.fBottom += SK_FDot61;
ptsR.fRight += SK_FDot6One;
ptsR.fBottom += SK_FDot6One;
if (!SkIRect::Intersects(ptsR, clipR)) {
return;