зеркало из https://github.com/mozilla/gecko-dev.git
Bug 467518. Interpret gfxBlur's border radius properly, as the actual boundary of the shadow, not the box-blur size. r=vlad
This commit is contained in:
Родитель
941d69d39a
Коммит
f66d4d802b
|
@ -186,6 +186,48 @@ BoxBlurVertical(unsigned char* aInput,
|
|||
}
|
||||
}
|
||||
|
||||
static void ComputeLobes(PRInt32 aRadius, PRInt32 aLobes[3][2])
|
||||
{
|
||||
PRInt32 major, minor, final;
|
||||
|
||||
/* See http://www.w3.org/TR/SVG/filters.html#feGaussianBlur for
|
||||
* some notes about approximating the Gaussian blur with box-blurs.
|
||||
* The comments below are in the terminology of that page.
|
||||
*/
|
||||
PRInt32 z = aRadius/3;
|
||||
switch (aRadius % 3) {
|
||||
case 0:
|
||||
// aRadius = z*3; choose d = 2*z + 1
|
||||
major = minor = final = z;
|
||||
break;
|
||||
case 1:
|
||||
// aRadius = z*3 + 1
|
||||
// This is a tricky case since there is no value of d which will
|
||||
// yield a radius of exactly aRadius. If d is odd, i.e. d=2*k + 1
|
||||
// for some integer k, then the radius will be 3*k. If d is even,
|
||||
// i.e. d=2*k, then the radius will be 3*k - 1.
|
||||
// So we have to choose values that don't match the standard
|
||||
// algorithm.
|
||||
major = z + 1;
|
||||
minor = final = z;
|
||||
break;
|
||||
case 2:
|
||||
// aRadius = z*3 + 2; choose d = 2*z + 2
|
||||
major = final = z + 1;
|
||||
minor = z;
|
||||
break;
|
||||
}
|
||||
NS_ASSERTION(major + minor + final == aRadius,
|
||||
"Lobes don't sum to the right length");
|
||||
|
||||
aLobes[0][0] = major;
|
||||
aLobes[0][1] = minor;
|
||||
aLobes[1][0] = minor;
|
||||
aLobes[1][1] = major;
|
||||
aLobes[2][0] = final;
|
||||
aLobes[2][1] = final;
|
||||
}
|
||||
|
||||
void
|
||||
gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx, const gfxPoint& offset)
|
||||
{
|
||||
|
@ -196,12 +238,6 @@ gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx, const gfxPoint& offset)
|
|||
|
||||
// no need to do all this if not blurring
|
||||
if (mBlurRadius.width != 0 || mBlurRadius.height != 0) {
|
||||
// A blur radius of 1 achieves nothing (1/2 = 0 in int terms),
|
||||
// but we still want a blur!
|
||||
// XXX this may not be appropriate... perhaps just use actuall Gaussian here?
|
||||
mBlurRadius.width = PR_MAX(mBlurRadius.width, 2);
|
||||
mBlurRadius.height = PR_MAX(mBlurRadius.height, 2);
|
||||
|
||||
nsTArray<unsigned char> tempAlphaDataBuf;
|
||||
if (!tempAlphaDataBuf.SetLength(mImageSurface->GetDataSize()))
|
||||
return; // OOM
|
||||
|
@ -211,19 +247,19 @@ gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx, const gfxPoint& offset)
|
|||
PRInt32 rows = mImageSurface->Height();
|
||||
|
||||
if (mBlurRadius.width > 0) {
|
||||
PRInt32 longLobe = mBlurRadius.width / 2;
|
||||
PRInt32 shortLobe = (mBlurRadius.width & 1) ? longLobe : longLobe - 1;
|
||||
BoxBlurHorizontal(boxData, tmpData, longLobe, shortLobe, stride, rows);
|
||||
BoxBlurHorizontal(tmpData, boxData, shortLobe, longLobe, stride, rows);
|
||||
BoxBlurHorizontal(boxData, tmpData, longLobe, longLobe, stride, rows);
|
||||
PRInt32 lobes[3][2];
|
||||
ComputeLobes(mBlurRadius.width, lobes);
|
||||
BoxBlurHorizontal(boxData, tmpData, lobes[0][0], lobes[0][1], stride, rows);
|
||||
BoxBlurHorizontal(tmpData, boxData, lobes[1][0], lobes[1][1], stride, rows);
|
||||
BoxBlurHorizontal(boxData, tmpData, lobes[2][0], lobes[2][1], stride, rows);
|
||||
}
|
||||
|
||||
if (mBlurRadius.height > 0) {
|
||||
PRInt32 longLobe = mBlurRadius.height / 2;
|
||||
PRInt32 shortLobe = (mBlurRadius.height & 1) ? longLobe : longLobe - 1;
|
||||
BoxBlurVertical(tmpData, boxData, longLobe, shortLobe, stride, rows);
|
||||
BoxBlurVertical(boxData, tmpData, shortLobe, longLobe, stride, rows);
|
||||
BoxBlurVertical(tmpData, boxData, longLobe, longLobe, stride, rows);
|
||||
PRInt32 lobes[3][2];
|
||||
ComputeLobes(mBlurRadius.height, lobes);
|
||||
BoxBlurVertical(tmpData, boxData, lobes[0][0], lobes[0][1], stride, rows);
|
||||
BoxBlurVertical(boxData, tmpData, lobes[1][0], lobes[1][1], stride, rows);
|
||||
BoxBlurVertical(tmpData, boxData, lobes[2][0], lobes[2][1], stride, rows);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,7 +277,8 @@ gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx, const gfxPoint& offset)
|
|||
}
|
||||
}
|
||||
|
||||
static const gfxFloat GAUSSIAN_SCALE_FACTOR = 3 * sqrt(2 * M_PI) / 4;
|
||||
// Blur radius is approximately 3/2 times the box-blur size
|
||||
static const gfxFloat GAUSSIAN_SCALE_FACTOR = (3 * sqrt(2 * M_PI) / 4) * (3/2);
|
||||
|
||||
gfxIntSize gfxAlphaBoxBlur::CalculateBlurRadius(const gfxPoint& aStd)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче