b=429915, color mismatch with 1x1 images (SetColor API broken) ; r=stuart, a=damon
--- a/gfx/src/thebes/nsThebesImage.cpp
+++ b/gfx/src/thebes/nsThebesImage.cpp
@@ -374,17 +374,17 @@ nsThebesImage::LockImagePixels(PRBool aM
// Recover the pixels
mImageSurface = new gfxImageSurface(gfxIntSize(mWidth, mHeight),
gfxImageSurface::ImageFormatARGB32);
if (!mImageSurface || mImageSurface->CairoStatus())
return NS_ERROR_OUT_OF_MEMORY;
gfxContext context(mImageSurface);
context.SetOperator(gfxContext::OPERATOR_SOURCE);
if (mSinglePixel)
- context.SetColor(mSinglePixelColor);
+ context.SetDeviceColor(mSinglePixelColor);
else
context.SetSource(mOptSurface);
context.Paint();
#ifdef XP_WIN
mWinSurface = nsnull;
#endif
#ifdef XP_MACOSX
@@ -436,17 +436,17 @@ nsThebesImage::Draw(nsIRenderingContext
if (mSinglePixelColor.a == 0.0)
return NS_OK;
// otherwise
gfxContext::GraphicsOperator op = ctx->CurrentOperator();
if (op == gfxContext::OPERATOR_OVER && mSinglePixelColor.a == 1.0)
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
- ctx->SetColor(mSinglePixelColor);
+ ctx->SetDeviceColor(mSinglePixelColor);
ctx->NewPath();
ctx->Rectangle(aDestRect, PR_TRUE);
ctx->Fill();
ctx->SetOperator(op);
return NS_OK;
}
gfxFloat xscale = aDestRect.size.width / aSourceRect.size.width;
@@ -605,17 +605,17 @@ nsThebesImage::Draw(nsIRenderingContext
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->NewPath();
ctx->SetPattern(pat);
ctx->Rectangle(destRect);
ctx->Fill();
ctx->SetOperator(op);
- ctx->SetColor(gfxRGBA(0,0,0,0));
+ ctx->SetDeviceColor(gfxRGBA(0,0,0,0));
return NS_OK;
}
nsresult
nsThebesImage::ThebesDrawTile(gfxContext *thebesContext,
nsIDeviceContext* dx,
const gfxPoint& offset,
@@ -635,17 +635,17 @@ nsThebesImage::ThebesDrawTile(gfxContext
PRBool doSnap = !(thebesContext->CurrentMatrix().HasNonTranslation());
PRBool hasPadding = ((xPadding != 0) || (yPadding != 0));
gfxImageSurface::gfxImageFormat format = mFormat;
gfxPoint tmpOffset = offset;
if (mSinglePixel && !hasPadding) {
- thebesContext->SetColor(mSinglePixelColor);
+ thebesContext->SetDeviceColor(mSinglePixelColor);
} else {
nsRefPtr<gfxASurface> surface;
PRInt32 width, height;
if (hasPadding) {
/* Ugh we have padding; create a temporary surface that's the size of the surface + pad area,
* and render the image into it first. Then we'll tile that surface. */
width = mWidth + xPadding;
@@ -659,17 +659,17 @@ nsThebesImage::ThebesDrawTile(gfxContext
surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(
gfxIntSize(width, height), format);
if (!surface || surface->CairoStatus()) {
return NS_ERROR_OUT_OF_MEMORY;
}
gfxContext tmpContext(surface);
if (mSinglePixel) {
- tmpContext.SetColor(mSinglePixelColor);
+ tmpContext.SetDeviceColor(mSinglePixelColor);
} else {
tmpContext.SetSource(ThebesSurface());
}
tmpContext.SetOperator(gfxContext::OPERATOR_SOURCE);
tmpContext.Rectangle(gfxRect(0, 0, mWidth, mHeight));
tmpContext.Fill();
} else {
width = mWidth;
@@ -797,17 +797,17 @@ nsThebesImage::ThebesDrawTile(gfxContext
if (op == gfxContext::OPERATOR_OVER && format == gfxASurface::ImageFormatRGB24)
thebesContext->SetOperator(gfxContext::OPERATOR_SOURCE);
thebesContext->NewPath();
thebesContext->Rectangle(targetRect, doSnap);
thebesContext->Fill();
thebesContext->SetOperator(op);
- thebesContext->SetColor(gfxRGBA(0,0,0,0));
+ thebesContext->SetDeviceColor(gfxRGBA(0,0,0,0));
return NS_OK;
}
PRBool
nsThebesImage::ShouldUseImageSurfaces()
{
#ifdef XP_WIN
--- a/gfx/src/thebes/nsThebesRenderingContext.cpp
+++ b/gfx/src/thebes/nsThebesRenderingContext.cpp
@@ -343,16 +343,19 @@ nsThebesRenderingContext::SetLineStyle(n
return NS_OK;
}
NS_IMETHODIMP
nsThebesRenderingContext::SetColor(nscolor aColor)
{
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::SetColor 0x%08x\n", this, aColor));
+ /* This sets the color assuming the sRGB color space, since that's what all
+ * CSS colors are defined to be in by the spec.
+ */
mThebes->SetColor(gfxRGBA(aColor));
mColor = aColor;
return NS_OK;
}
NS_IMETHODIMP
nsThebesRenderingContext::GetColor(nscolor &aColor) const
--- a/gfx/thebes/public/gfxContext.h
+++ b/gfx/thebes/public/gfxContext.h
@@ -309,26 +309,34 @@ public:
*/
void PixelSnappedRectangleAndSetPattern(const gfxRect& rect, gfxPattern *pattern);
/**
** Painting sources
**/
/**
- * Uses a solid color for drawing.
+ * Set a solid color to use for drawing. This color is in the device color space
+ * and is not transformed.
*/
- void SetColor(const gfxRGBA& c);
+ void SetDeviceColor(const gfxRGBA& c);
/**
- * Gets the current color.
+ * Gets the current color. It's returned in the device color space.
* returns PR_FALSE if there is something other than a color
* set as the current source (pattern, surface, etc)
*/
- PRBool GetColor(gfxRGBA& c);
+ PRBool GetDeviceColor(gfxRGBA& c);
+
+ /**
+ * Set a solid color in the sRGB color space to use for drawing.
+ * If CMS is not enabled, the color is treated as a device-space color
+ * and this call is identical to SetDeviceColor().
+ */
+ void SetColor(const gfxRGBA& c);
/**
* Uses a surface for drawing. This is a shorthand for creating a
* pattern and setting it.
*
* @param offset ?
*/
void SetSource(gfxASurface *surface, const gfxPoint& offset = gfxPoint(0.0, 0.0));
--- a/gfx/thebes/src/gfxContext.cpp
+++ b/gfx/thebes/src/gfxContext.cpp
@@ -640,18 +640,24 @@ gfxContext::SetColor(const gfxRGBA& c)
cairo_set_source_rgba(mCairo, cms.r, cms.g, cms.b, cms.a);
return;
}
}
cairo_set_source_rgba(mCairo, c.r, c.g, c.b, c.a);
}
+void
+gfxContext::SetDeviceColor(const gfxRGBA& c)
+{
+ cairo_set_source_rgba(mCairo, c.r, c.g, c.b, c.a);
+}
+
PRBool
-gfxContext::GetColor(gfxRGBA& c)
+gfxContext::GetDeviceColor(gfxRGBA& c)
{
return cairo_pattern_get_rgba(cairo_get_source(mCairo),
&c.r,
&c.g,
&c.b,
&c.a) == CAIRO_STATUS_SUCCESS;
}
--- a/gfx/thebes/src/gfxFont.cpp
+++ b/gfx/thebes/src/gfxFont.cpp
@@ -1395,17 +1395,17 @@ HasSyntheticBold(gfxTextRun *aRun, PRUin
return PR_FALSE;
}
// returns true if color is non-opaque (i.e. alpha != 1.0) or completely transparent, false otherwise
// if true, color is set on output
static PRBool
HasNonOpaqueColor(gfxContext *aContext, gfxRGBA& aCurrentColor)
{
- if (aContext->GetColor(aCurrentColor)) {
+ if (aContext->GetDeviceColor(aCurrentColor)) {
if (aCurrentColor.a < 1.0 && aCurrentColor.a > 0.0) {
return PR_TRUE;
}
}
return PR_FALSE;
}
--- a/gfx/thebes/src/gfxFontMissingGlyphs.cpp
+++ b/gfx/thebes/src/gfxFontMissingGlyphs.cpp
@@ -195,17 +195,17 @@ DrawHexChar(gfxContext *aContext, const
void
gfxFontMissingGlyphs::DrawMissingGlyph(gfxContext *aContext, const gfxRect& aRect,
PRUint32 aChar)
{
aContext->Save();
gfxRGBA currentColor;
- if (!aContext->GetColor(currentColor)) {
+ if (!aContext->GetDeviceColor(currentColor)) {
// We're currently drawing with some kind of pattern... Just draw
// the missing-glyph data in black.
currentColor = gfxRGBA(0,0,0,1);
}
// Stroke a rectangle so that the stroke's left edge is inset one pixel
// from the left edge of the glyph box and the stroke's right edge
// is inset one pixel from the right edge of the glyph box.
@@ -216,46 +216,46 @@ gfxFontMissingGlyphs::DrawMissingGlyph(g
borderRight - borderLeft, aRect.Height() - 2*halfBorderWidth);
if (!borderStrokeRect.IsEmpty()) {
aContext->SetLineWidth(BOX_BORDER_WIDTH);
aContext->SetDash(gfxContext::gfxLineSolid);
aContext->SetLineCap(gfxContext::LINE_CAP_SQUARE);
aContext->SetLineJoin(gfxContext::LINE_JOIN_MITER);
gfxRGBA color = currentColor;
color.a *= BOX_BORDER_OPACITY;
- aContext->SetColor(color);
+ aContext->SetDeviceColor(color);
aContext->NewPath();
aContext->Rectangle(borderStrokeRect);
aContext->Stroke();
}
gfxPoint center(aRect.X() + aRect.Width()/2,
aRect.Y() + aRect.Height()/2);
gfxFloat halfGap = HEX_CHAR_GAP/2.0;
gfxFloat top = -(MINIFONT_HEIGHT + halfGap);
if (aChar < 0x10000) {
if (aRect.Width() >= 2*MINIFONT_WIDTH + HEX_CHAR_GAP &&
aRect.Height() >= 2*MINIFONT_HEIGHT + HEX_CHAR_GAP) {
// Draw 4 digits for BMP
- aContext->SetColor(currentColor);
+ aContext->SetDeviceColor(currentColor);
gfxFloat left = -(MINIFONT_WIDTH + halfGap);
DrawHexChar(aContext,
center + gfxPoint(left, top), (aChar >> 12) & 0xF);
DrawHexChar(aContext,
center + gfxPoint(halfGap, top), (aChar >> 8) & 0xF);
DrawHexChar(aContext,
center + gfxPoint(left, halfGap), (aChar >> 4) & 0xF);
DrawHexChar(aContext,
center + gfxPoint(halfGap, halfGap), aChar & 0xF);
}
} else {
if (aRect.Width() >= 3*MINIFONT_WIDTH + 2*HEX_CHAR_GAP &&
aRect.Height() >= 2*MINIFONT_HEIGHT + HEX_CHAR_GAP) {
// Draw 6 digits for non-BMP
- aContext->SetColor(currentColor);
+ aContext->SetDeviceColor(currentColor);
gfxFloat first = -(MINIFONT_WIDTH * 1.5 + HEX_CHAR_GAP);
gfxFloat second = -(MINIFONT_WIDTH / 2.0);
gfxFloat third = (MINIFONT_WIDTH / 2.0 + HEX_CHAR_GAP);
DrawHexChar(aContext,
center + gfxPoint(first, top), (aChar >> 20) & 0xF);
DrawHexChar(aContext,
center + gfxPoint(second, top), (aChar >> 16) & 0xF);
DrawHexChar(aContext,