Bug 369528 - SVG code not handing surface endianness properly. r+sr=roc

This commit is contained in:
tor%cs.brown.edu 2007-03-09 20:27:01 +00:00
Родитель 8d36248c77
Коммит 0307c2f9f6
5 изменённых файлов: 86 добавлений и 49 удалений

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

@ -59,6 +59,7 @@
#include "nsIDocument.h" #include "nsIDocument.h"
#include "nsIFrame.h" #include "nsIFrame.h"
#include "nsSVGAnimatedInteger.h" #include "nsSVGAnimatedInteger.h"
#include "gfxColor.h"
nsSVGElement::LengthInfo nsSVGFE::sLengthInfo[4] = nsSVGElement::LengthInfo nsSVGFE::sLengthInfo[4] =
{ {
@ -938,9 +939,10 @@ nsSVGFEBlendElement::Filter(nsSVGFilterInstance *instance)
for (PRInt32 x = rect.x; x < rect.XMost(); x++) { for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
for (PRInt32 y = rect.y; y < rect.YMost(); y++) { for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
PRUint32 targIndex = y * stride + 4 * x; PRUint32 targIndex = y * stride + 4 * x;
PRUint32 qa = targetData[targIndex + 3]; PRUint32 qa = targetData[targIndex + GFX_ARGB32_OFFSET_A];
PRUint32 qb = sourceData[targIndex + 3]; PRUint32 qb = sourceData[targIndex + GFX_ARGB32_OFFSET_A];
for (PRInt32 i = 0; i < 3; i++) { for (PRInt32 i = PR_MIN(GFX_ARGB32_OFFSET_B, GFX_ARGB32_OFFSET_R);
i <= PR_MAX(GFX_ARGB32_OFFSET_B, GFX_ARGB32_OFFSET_R); i++) {
PRUint32 ca = targetData[targIndex + i]; PRUint32 ca = targetData[targIndex + i];
PRUint32 cb = sourceData[targIndex + i]; PRUint32 cb = sourceData[targIndex + i];
PRUint32 val; PRUint32 val;
@ -970,7 +972,7 @@ nsSVGFEBlendElement::Filter(nsSVGFilterInstance *instance)
targetData[targIndex + i] = NS_STATIC_CAST(PRUint8, val); targetData[targIndex + i] = NS_STATIC_CAST(PRUint8, val);
} }
PRUint32 alpha = 255 * 255 - (255 - qa) * (255 - qb); PRUint32 alpha = 255 * 255 - (255 - qa) * (255 - qb);
FAST_DIVIDE_BY_255(targetData[targIndex + 3], alpha); FAST_DIVIDE_BY_255(targetData[targIndex + GFX_ARGB32_OFFSET_A], alpha);
} }
} }
return NS_OK; return NS_OK;
@ -1285,17 +1287,22 @@ nsSVGFEColorMatrixElement::Filter(nsSVGFilterInstance *instance)
float col[4]; float col[4];
for (int i = 0, row = 0; i < 4; i++, row += 5) { for (int i = 0, row = 0; i < 4; i++, row += 5) {
col[i] = sourceData[targIndex + 2] * colorMatrix[row + 0] + col[i] =
sourceData[targIndex + 1] * colorMatrix[row + 1] + sourceData[targIndex + GFX_ARGB32_OFFSET_R] * colorMatrix[row + 0] +
sourceData[targIndex + 0] * colorMatrix[row + 2] + sourceData[targIndex + GFX_ARGB32_OFFSET_G] * colorMatrix[row + 1] +
sourceData[targIndex + 3] * colorMatrix[row + 3] + sourceData[targIndex + GFX_ARGB32_OFFSET_B] * colorMatrix[row + 2] +
sourceData[targIndex + GFX_ARGB32_OFFSET_A] * colorMatrix[row + 3] +
255 * colorMatrix[row + 4]; 255 * colorMatrix[row + 4];
col[i] = PR_MIN(PR_MAX(0, col[i]), 255); col[i] = PR_MIN(PR_MAX(0, col[i]), 255);
} }
targetData[targIndex + 2] = NS_STATIC_CAST(PRUint8, col[0]); targetData[targIndex + GFX_ARGB32_OFFSET_R] =
targetData[targIndex + 1] = NS_STATIC_CAST(PRUint8, col[1]); NS_STATIC_CAST(PRUint8, col[0]);
targetData[targIndex + 0] = NS_STATIC_CAST(PRUint8, col[2]); targetData[targIndex + GFX_ARGB32_OFFSET_G] =
targetData[targIndex + 3] = NS_STATIC_CAST(PRUint8, col[3]); NS_STATIC_CAST(PRUint8, col[1]);
targetData[targIndex + GFX_ARGB32_OFFSET_B] =
NS_STATIC_CAST(PRUint8, col[2]);
targetData[targIndex + GFX_ARGB32_OFFSET_A] =
NS_STATIC_CAST(PRUint8, col[3]);
} }
} }
return NS_OK; return NS_OK;
@ -1748,10 +1755,14 @@ nsSVGFEComponentTransferElement::Filter(nsSVGFilterInstance *instance)
for (PRInt32 y = rect.y; y < rect.YMost(); y++) for (PRInt32 y = rect.y; y < rect.YMost(); y++)
for (PRInt32 x = rect.x; x < rect.XMost(); x++) { for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
PRInt32 targIndex = y * stride + x * 4; PRInt32 targIndex = y * stride + x * 4;
targetData[targIndex] = tableB[sourceData[targIndex]]; targetData[targIndex + GFX_ARGB32_OFFSET_B] =
targetData[targIndex + 1] = tableG[sourceData[targIndex + 1]]; tableB[sourceData[targIndex + GFX_ARGB32_OFFSET_B]];
targetData[targIndex + 2] = tableR[sourceData[targIndex + 2]]; targetData[targIndex + GFX_ARGB32_OFFSET_G] =
targetData[targIndex + 3] = tableA[sourceData[targIndex + 3]]; tableG[sourceData[targIndex + GFX_ARGB32_OFFSET_G]];
targetData[targIndex + GFX_ARGB32_OFFSET_R] =
tableR[sourceData[targIndex + GFX_ARGB32_OFFSET_R]];
targetData[targIndex + GFX_ARGB32_OFFSET_A] =
tableA[sourceData[targIndex + GFX_ARGB32_OFFSET_A]];
} }
return NS_OK; return NS_OK;
} }
@ -3108,10 +3119,10 @@ nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance)
FAST_DIVIDE_BY_255(g, unsigned(col[1]) * a); FAST_DIVIDE_BY_255(g, unsigned(col[1]) * a);
FAST_DIVIDE_BY_255(b, unsigned(col[2]) * a); FAST_DIVIDE_BY_255(b, unsigned(col[2]) * a);
targetData[targIndex ] = b; targetData[targIndex + GFX_ARGB32_OFFSET_B] = b;
targetData[targIndex + 1] = g; targetData[targIndex + GFX_ARGB32_OFFSET_G] = g;
targetData[targIndex + 2] = r; targetData[targIndex + GFX_ARGB32_OFFSET_R] = r;
targetData[targIndex + 3] = a; targetData[targIndex + GFX_ARGB32_OFFSET_A] = a;
} }
} }

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

@ -318,10 +318,11 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
for (PRUint32 yy=0; yy<filterResY; yy++) for (PRUint32 yy=0; yy<filterResY; yy++)
for (PRUint32 xx=0; xx<filterResX; xx++) { for (PRUint32 xx=0; xx<filterResX; xx++) {
alphaData[stride*yy + 4*xx] = 0; alphaData[stride*yy + 4*xx + GFX_ARGB32_OFFSET_B] = 0;
alphaData[stride*yy + 4*xx + 1] = 0; alphaData[stride*yy + 4*xx + GFX_ARGB32_OFFSET_G] = 0;
alphaData[stride*yy + 4*xx + 2] = 0; alphaData[stride*yy + 4*xx + GFX_ARGB32_OFFSET_R] = 0;
alphaData[stride*yy + 4*xx + 3] = data[stride*yy + 4*xx + 3]; alphaData[stride*yy + 4*xx + GFX_ARGB32_OFFSET_A] =
data[stride*yy + 4*xx + 3];
} }
instance.DefineImage(NS_LITERAL_STRING("SourceAlpha"), alpha, instance.DefineImage(NS_LITERAL_STRING("SourceAlpha"), alpha,

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

@ -229,13 +229,14 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRenderState *aContext,
PRUint8 *pixel = data + stride * y + 4 * x; PRUint8 *pixel = data + stride * y + 4 * x;
/* linearRGB -> intensity */ /* linearRGB -> intensity */
pixel[3] = (PRUint8)((pixel[2] * 0.2125 + PRUint8 alpha =
pixel[1] * 0.7154 + NS_STATIC_CAST(PRUint8,
pixel[0] * 0.0721) * (pixel[GFX_ARGB32_OFFSET_R] * 0.2125 +
(pixel[3] / 255.0) * aOpacity); pixel[GFX_ARGB32_OFFSET_G] * 0.7154 +
pixel[0] = 255; pixel[GFX_ARGB32_OFFSET_B] * 0.0721) *
pixel[1] = 255; (pixel[GFX_ARGB32_OFFSET_A] / 255.0) * aOpacity);
pixel[2] = 255;
memset(pixel, alpha, 4);
} }
cairo_pattern_t *retval = cairo_pattern_create_for_surface(image); cairo_pattern_t *retval = cairo_pattern_create_for_surface(image);

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

@ -318,18 +318,18 @@ nsSVGUtils::UnPremultiplyImageDataAlpha(PRUint8 *data,
for (PRInt32 x = rect.x; x < rect.XMost(); x++) { for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
PRUint8 *pixel = data + stride * y + 4 * x; PRUint8 *pixel = data + stride * y + 4 * x;
PRUint8 a = pixel[3]; PRUint8 a = pixel[GFX_ARGB32_OFFSET_A];
if (a == 255) if (a == 255)
continue; continue;
if (a) { if (a) {
pixel[0] = (255 * pixel[0]) / a; pixel[GFX_ARGB32_OFFSET_B] = (255 * pixel[GFX_ARGB32_OFFSET_B]) / a;
pixel[1] = (255 * pixel[1]) / a; pixel[GFX_ARGB32_OFFSET_G] = (255 * pixel[GFX_ARGB32_OFFSET_G]) / a;
pixel[2] = (255 * pixel[2]) / a; pixel[GFX_ARGB32_OFFSET_R] = (255 * pixel[GFX_ARGB32_OFFSET_R]) / a;
} else { } else {
pixel[0] = 0; pixel[GFX_ARGB32_OFFSET_B] = 0;
pixel[1] = 0; pixel[GFX_ARGB32_OFFSET_G] = 0;
pixel[2] = 0; pixel[GFX_ARGB32_OFFSET_R] = 0;
} }
} }
} }
@ -344,13 +344,16 @@ nsSVGUtils::PremultiplyImageDataAlpha(PRUint8 *data,
for (PRInt32 x = rect.x; x < rect.XMost(); x++) { for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
PRUint8 *pixel = data + stride * y + 4 * x; PRUint8 *pixel = data + stride * y + 4 * x;
PRUint8 a = pixel[3]; PRUint8 a = pixel[GFX_ARGB32_OFFSET_A];
if (a == 255) if (a == 255)
continue; continue;
FAST_DIVIDE_BY_255(pixel[0], pixel[0] * a); FAST_DIVIDE_BY_255(pixel[GFX_ARGB32_OFFSET_B],
FAST_DIVIDE_BY_255(pixel[1], pixel[1] * a); pixel[GFX_ARGB32_OFFSET_B] * a);
FAST_DIVIDE_BY_255(pixel[2], pixel[2] * a); FAST_DIVIDE_BY_255(pixel[GFX_ARGB32_OFFSET_G],
pixel[GFX_ARGB32_OFFSET_G] * a);
FAST_DIVIDE_BY_255(pixel[GFX_ARGB32_OFFSET_R],
pixel[GFX_ARGB32_OFFSET_R] * a);
} }
} }
} }
@ -364,9 +367,12 @@ nsSVGUtils::ConvertImageDataToLinearRGB(PRUint8 *data,
for (PRInt32 x = rect.x; x < rect.XMost(); x++) { for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
PRUint8 *pixel = data + stride * y + 4 * x; PRUint8 *pixel = data + stride * y + 4 * x;
pixel[0] = gsRGBToLinearRGBMap[pixel[0]]; pixel[GFX_ARGB32_OFFSET_B] =
pixel[1] = gsRGBToLinearRGBMap[pixel[1]]; gsRGBToLinearRGBMap[pixel[GFX_ARGB32_OFFSET_B]];
pixel[2] = gsRGBToLinearRGBMap[pixel[2]]; pixel[GFX_ARGB32_OFFSET_G] =
gsRGBToLinearRGBMap[pixel[GFX_ARGB32_OFFSET_G]];
pixel[GFX_ARGB32_OFFSET_R] =
gsRGBToLinearRGBMap[pixel[GFX_ARGB32_OFFSET_R]];
} }
} }
} }
@ -380,9 +386,12 @@ nsSVGUtils::ConvertImageDataFromLinearRGB(PRUint8 *data,
for (PRInt32 x = rect.x; x < rect.XMost(); x++) { for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
PRUint8 *pixel = data + stride * y + 4 * x; PRUint8 *pixel = data + stride * y + 4 * x;
pixel[0] = glinearRGBTosRGBMap[pixel[0]]; pixel[GFX_ARGB32_OFFSET_B] =
pixel[1] = glinearRGBTosRGBMap[pixel[1]]; glinearRGBTosRGBMap[pixel[GFX_ARGB32_OFFSET_B]];
pixel[2] = glinearRGBTosRGBMap[pixel[2]]; pixel[GFX_ARGB32_OFFSET_G] =
glinearRGBTosRGBMap[pixel[GFX_ARGB32_OFFSET_G]];
pixel[GFX_ARGB32_OFFSET_R] =
glinearRGBTosRGBMap[pixel[GFX_ARGB32_OFFSET_R]];
} }
} }
} }

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

@ -98,6 +98,21 @@ struct gfxMatrix;
/* are we the child of a non-display container? */ /* are we the child of a non-display container? */
#define NS_STATE_SVG_NONDISPLAY_CHILD 0x20000000 #define NS_STATE_SVG_NONDISPLAY_CHILD 0x20000000
/**
* Byte offsets of channels in a native packed gfxColor or cairo image surface.
*/
#ifdef IS_BIG_ENDIAN
#define GFX_ARGB32_OFFSET_A 0
#define GFX_ARGB32_OFFSET_R 1
#define GFX_ARGB32_OFFSET_G 2
#define GFX_ARGB32_OFFSET_B 3
#else
#define GFX_ARGB32_OFFSET_A 3
#define GFX_ARGB32_OFFSET_R 2
#define GFX_ARGB32_OFFSET_G 1
#define GFX_ARGB32_OFFSET_B 0
#endif
/* /*
* Checks the svg enable preference and if a renderer could * Checks the svg enable preference and if a renderer could
* successfully be created. Declared as a function instead of a * successfully be created. Declared as a function instead of a