зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1209765 (Part 1) - Support sync decoding of border-image in nsCSSRendering. r=tn
This commit is contained in:
Родитель
b2aa4e334a
Коммит
6a4f2f8dde
|
@ -401,13 +401,14 @@ struct ColorStop {
|
|||
};
|
||||
|
||||
/* Local functions */
|
||||
static void DrawBorderImage(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aBorderArea,
|
||||
const nsStyleBorder& aStyleBorder,
|
||||
const nsRect& aDirtyRect,
|
||||
Sides aSkipSides);
|
||||
static DrawResult DrawBorderImage(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aBorderArea,
|
||||
const nsStyleBorder& aStyleBorder,
|
||||
const nsRect& aDirtyRect,
|
||||
Sides aSkipSides,
|
||||
PaintBorderFlags aFlags);
|
||||
|
||||
static nscolor MakeBevelColor(mozilla::css::Side whichSide, uint8_t style,
|
||||
nscolor aBackgroundColor,
|
||||
|
@ -616,13 +617,14 @@ nsCSSRendering::ComputePixelRadii(const nscoord *aAppUnitsRadii,
|
|||
radii[NS_CORNER_BOTTOM_LEFT_Y]);
|
||||
}
|
||||
|
||||
void
|
||||
DrawResult
|
||||
nsCSSRendering::PaintBorder(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsRect& aBorderArea,
|
||||
nsStyleContext* aStyleContext,
|
||||
PaintBorderFlags aFlags,
|
||||
Sides aSkipSides)
|
||||
{
|
||||
PROFILER_LABEL("nsCSSRendering", "PaintBorder",
|
||||
|
@ -633,10 +635,9 @@ nsCSSRendering::PaintBorder(nsPresContext* aPresContext,
|
|||
// Don't check RelevantLinkVisited here, since we want to take the
|
||||
// same amount of time whether or not it's true.
|
||||
if (!styleIfVisited) {
|
||||
PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
|
||||
aDirtyRect, aBorderArea, *styleBorder,
|
||||
aStyleContext, aSkipSides);
|
||||
return;
|
||||
return PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
|
||||
aDirtyRect, aBorderArea, *styleBorder,
|
||||
aStyleContext, aFlags, aSkipSides);
|
||||
}
|
||||
|
||||
nsStyleBorder newStyleBorder(*styleBorder);
|
||||
|
@ -650,17 +651,20 @@ nsCSSRendering::PaintBorder(nsPresContext* aPresContext,
|
|||
aStyleContext->GetVisitedDependentColor(
|
||||
nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color)[side]));
|
||||
}
|
||||
PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
|
||||
aDirtyRect, aBorderArea, newStyleBorder,
|
||||
aStyleContext, aSkipSides);
|
||||
DrawResult result =
|
||||
PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
|
||||
aDirtyRect, aBorderArea, newStyleBorder,
|
||||
aStyleContext, aFlags, aSkipSides);
|
||||
|
||||
// We could do something fancy to avoid the TrackImage/UntrackImage
|
||||
// work, but it doesn't seem worth it. (We need to call UntrackImage
|
||||
// since we're not going through nsStyleBorder::Destroy.)
|
||||
newStyleBorder.UntrackImage(aPresContext);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
DrawResult
|
||||
nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsIFrame* aForFrame,
|
||||
|
@ -668,6 +672,7 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
|||
const nsRect& aBorderArea,
|
||||
const nsStyleBorder& aStyleBorder,
|
||||
nsStyleContext* aStyleContext,
|
||||
PaintBorderFlags aFlags,
|
||||
Sides aSkipSides)
|
||||
{
|
||||
DrawTarget& aDrawTarget = *aRenderingContext.GetDrawTarget();
|
||||
|
@ -680,14 +685,26 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
|||
const nsStyleDisplay* displayData = aStyleContext->StyleDisplay();
|
||||
if (displayData->mAppearance) {
|
||||
nsITheme *theme = aPresContext->GetTheme();
|
||||
if (theme && theme->ThemeSupportsWidget(aPresContext, aForFrame, displayData->mAppearance))
|
||||
return; // Let the theme handle it.
|
||||
if (theme &&
|
||||
theme->ThemeSupportsWidget(aPresContext, aForFrame,
|
||||
displayData->mAppearance)) {
|
||||
return DrawResult::SUCCESS; // Let the theme handle it.
|
||||
}
|
||||
}
|
||||
|
||||
if (aStyleBorder.IsBorderImageLoaded()) {
|
||||
DrawBorderImage(aPresContext, aRenderingContext, aForFrame,
|
||||
aBorderArea, aStyleBorder, aDirtyRect, aSkipSides);
|
||||
return;
|
||||
return DrawBorderImage(aPresContext, aRenderingContext, aForFrame,
|
||||
aBorderArea, aStyleBorder, aDirtyRect,
|
||||
aSkipSides, aFlags);
|
||||
}
|
||||
|
||||
DrawResult result = DrawResult::SUCCESS;
|
||||
|
||||
// If we had a border-image, but it wasn't loaded, then we should return
|
||||
// DrawResult::NOT_READY; we'll want to try again if we do a paint with sync
|
||||
// decoding enabled.
|
||||
if (aStyleBorder.mBorderImageSource.GetType() != eStyleImageType_Null) {
|
||||
result = DrawResult::NOT_READY;
|
||||
}
|
||||
|
||||
// Get our style context's color struct.
|
||||
|
@ -705,7 +722,7 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
|||
if (0 == border.left && 0 == border.right &&
|
||||
0 == border.top && 0 == border.bottom) {
|
||||
// Empty border area
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Compute the outermost boundary of the area that might be painted.
|
||||
|
@ -789,6 +806,8 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
|||
ctx->Restore();
|
||||
|
||||
PrintAsStringNewline();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static nsRect
|
||||
|
@ -3347,22 +3366,28 @@ nsCSSRendering::GetBackgroundLayerRect(nsPresContext* aPresContext,
|
|||
return state.mFillArea;
|
||||
}
|
||||
|
||||
static void
|
||||
static DrawResult
|
||||
DrawBorderImage(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aBorderArea,
|
||||
const nsStyleBorder& aStyleBorder,
|
||||
const nsRect& aDirtyRect,
|
||||
Sides aSkipSides)
|
||||
Sides aSkipSides,
|
||||
PaintBorderFlags aFlags)
|
||||
{
|
||||
NS_PRECONDITION(aStyleBorder.IsBorderImageLoaded(),
|
||||
"drawing border image that isn't successfully loaded");
|
||||
|
||||
if (aDirtyRect.IsEmpty())
|
||||
return;
|
||||
if (aDirtyRect.IsEmpty()) {
|
||||
return DrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
nsImageRenderer renderer(aForFrame, &aStyleBorder.mBorderImageSource, 0);
|
||||
uint32_t irFlags = 0;
|
||||
if (aFlags & PaintBorderFlags::SYNC_DECODE_IMAGES) {
|
||||
irFlags |= nsImageRenderer::FLAG_SYNC_DECODE_IMAGES;
|
||||
}
|
||||
nsImageRenderer renderer(aForFrame, &aStyleBorder.mBorderImageSource, irFlags);
|
||||
|
||||
// Ensure we get invalidated for loads and animations of the image.
|
||||
// We need to do this here because this might be the only code that
|
||||
|
@ -3373,7 +3398,7 @@ DrawBorderImage(nsPresContext* aPresContext,
|
|||
aForFrame->AssociateImage(aStyleBorder.mBorderImageSource, aPresContext);
|
||||
|
||||
if (!renderer.PrepareImage()) {
|
||||
return;
|
||||
return renderer.PrepareResult();
|
||||
}
|
||||
|
||||
// NOTE: no Save() yet, we do that later by calling autoSR.EnsureSaved()
|
||||
|
@ -3549,6 +3574,8 @@ DrawBorderImage(nsPresContext* aPresContext,
|
|||
slice.bottom,
|
||||
};
|
||||
|
||||
DrawResult result = DrawResult::SUCCESS;
|
||||
|
||||
for (int i = LEFT; i <= RIGHT; i++) {
|
||||
for (int j = TOP; j <= BOTTOM; j++) {
|
||||
uint8_t fillStyleH, fillStyleV;
|
||||
|
@ -3633,16 +3660,19 @@ DrawBorderImage(nsPresContext* aPresContext,
|
|||
nsRect subArea(sliceX[i], sliceY[j], sliceWidth[i], sliceHeight[j]);
|
||||
nsIntRect intSubArea = subArea.ToOutsidePixels(nsPresContext::AppUnitsPerCSSPixel());
|
||||
|
||||
renderer.DrawBorderImageComponent(aPresContext,
|
||||
aRenderingContext, aDirtyRect,
|
||||
destArea, CSSIntRect(intSubArea.x,
|
||||
intSubArea.y,
|
||||
intSubArea.width,
|
||||
intSubArea.height),
|
||||
fillStyleH, fillStyleV,
|
||||
unitSize, j * (RIGHT + 1) + i);
|
||||
result &=
|
||||
renderer.DrawBorderImageComponent(aPresContext,
|
||||
aRenderingContext, aDirtyRect,
|
||||
destArea, CSSIntRect(intSubArea.x,
|
||||
intSubArea.y,
|
||||
intSubArea.width,
|
||||
intSubArea.height),
|
||||
fillStyleH, fillStyleV,
|
||||
unitSize, j * (RIGHT + 1) + i);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Begin table border-collapsing section
|
||||
|
@ -5031,17 +5061,18 @@ nsImageRenderer::Draw(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
nsCOMPtr<imgIContainer> image(ImageOps::CreateFromDrawable(drawable));
|
||||
nsLayoutUtils::DrawImage(*aRenderingContext.ThebesContext(),
|
||||
aPresContext, image,
|
||||
filter, aDest, aFill, aAnchor, aDirtyRect,
|
||||
ConvertImageRendererToDrawFlags(mFlags));
|
||||
DrawResult result =
|
||||
nsLayoutUtils::DrawImage(*aRenderingContext.ThebesContext(),
|
||||
aPresContext, image,
|
||||
filter, aDest, aFill, aAnchor, aDirtyRect,
|
||||
ConvertImageRendererToDrawFlags(mFlags));
|
||||
|
||||
if (op != CompositionOp::OP_OVER) {
|
||||
ctx->PopGroupToSource();
|
||||
ctx->Paint();
|
||||
}
|
||||
|
||||
return DrawResult::SUCCESS;
|
||||
return result;
|
||||
}
|
||||
case eStyleImageType_Null:
|
||||
default:
|
||||
|
@ -5177,7 +5208,7 @@ RequiresScaling(const nsRect& aFill,
|
|||
aUnitSize.height != aFill.height);
|
||||
}
|
||||
|
||||
void
|
||||
DrawResult
|
||||
nsImageRenderer::DrawBorderImageComponent(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect,
|
||||
|
@ -5190,10 +5221,10 @@ nsImageRenderer::DrawBorderImageComponent(nsPresContext* aPresContext,
|
|||
{
|
||||
if (!IsReady()) {
|
||||
NS_NOTREACHED("Ensure PrepareImage() has returned true before calling me");
|
||||
return;
|
||||
return DrawResult::BAD_ARGS;
|
||||
}
|
||||
if (aFill.IsEmpty() || aSrc.IsEmpty()) {
|
||||
return;
|
||||
return DrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
if (mType == eStyleImageType_Image || mType == eStyleImageType_Element) {
|
||||
|
@ -5219,7 +5250,7 @@ nsImageRenderer::DrawBorderImageComponent(nsPresContext* aPresContext,
|
|||
aRenderingContext);
|
||||
if (!drawable) {
|
||||
NS_WARNING("Could not create drawable for element");
|
||||
return;
|
||||
return DrawResult::TEMPORARY_ERROR;
|
||||
}
|
||||
|
||||
nsCOMPtr<imgIContainer> image(ImageOps::CreateFromDrawable(drawable));
|
||||
|
@ -5229,32 +5260,30 @@ nsImageRenderer::DrawBorderImageComponent(nsPresContext* aPresContext,
|
|||
Filter filter = nsLayoutUtils::GetGraphicsFilterForFrame(mForFrame);
|
||||
|
||||
if (!RequiresScaling(aFill, aHFill, aVFill, aUnitSize)) {
|
||||
nsLayoutUtils::DrawSingleImage(*aRenderingContext.ThebesContext(),
|
||||
aPresContext,
|
||||
subImage,
|
||||
filter,
|
||||
aFill, aDirtyRect,
|
||||
nullptr,
|
||||
imgIContainer::FLAG_NONE);
|
||||
return;
|
||||
return nsLayoutUtils::DrawSingleImage(*aRenderingContext.ThebesContext(),
|
||||
aPresContext,
|
||||
subImage,
|
||||
filter,
|
||||
aFill, aDirtyRect,
|
||||
nullptr,
|
||||
ConvertImageRendererToDrawFlags(mFlags));
|
||||
}
|
||||
|
||||
nsRect tile = ComputeTile(aFill, aHFill, aVFill, aUnitSize);
|
||||
nsLayoutUtils::DrawImage(*aRenderingContext.ThebesContext(),
|
||||
aPresContext,
|
||||
subImage,
|
||||
filter,
|
||||
tile, aFill, tile.TopLeft(), aDirtyRect,
|
||||
imgIContainer::FLAG_NONE);
|
||||
return;
|
||||
return nsLayoutUtils::DrawImage(*aRenderingContext.ThebesContext(),
|
||||
aPresContext,
|
||||
subImage,
|
||||
filter,
|
||||
tile, aFill, tile.TopLeft(), aDirtyRect,
|
||||
ConvertImageRendererToDrawFlags(mFlags));
|
||||
}
|
||||
|
||||
nsRect destTile = RequiresScaling(aFill, aHFill, aVFill, aUnitSize)
|
||||
? ComputeTile(aFill, aHFill, aVFill, aUnitSize)
|
||||
: aFill;
|
||||
|
||||
Draw(aPresContext, aRenderingContext, aDirtyRect, destTile,
|
||||
aFill, destTile.TopLeft(), aSrc);
|
||||
return Draw(aPresContext, aRenderingContext, aDirtyRect, destTile,
|
||||
aFill, destTile.TopLeft(), aSrc);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "imgIContainer.h"
|
||||
#include "mozilla/gfx/PathHelpers.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsStyleStruct.h"
|
||||
#include "nsIFrame.h"
|
||||
|
@ -99,6 +100,12 @@ struct CSSSizeOrRatio
|
|||
bool mHasHeight;
|
||||
};
|
||||
|
||||
enum class PaintBorderFlags : uint8_t
|
||||
{
|
||||
SYNC_DECODE_IMAGES = 1 << 0
|
||||
};
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(PaintBorderFlags)
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
|
@ -225,7 +232,7 @@ public:
|
|||
* 3 4 5
|
||||
* 6 7 8
|
||||
*/
|
||||
void
|
||||
DrawResult
|
||||
DrawBorderImageComponent(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect,
|
||||
|
@ -380,27 +387,29 @@ struct nsCSSRendering {
|
|||
* for borders. aSkipSides says which sides to skip
|
||||
* when rendering, the default is to skip none.
|
||||
*/
|
||||
static void PaintBorder(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsRect& aBorderArea,
|
||||
nsStyleContext* aStyleContext,
|
||||
Sides aSkipSides = Sides());
|
||||
static DrawResult PaintBorder(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsRect& aBorderArea,
|
||||
nsStyleContext* aStyleContext,
|
||||
mozilla::PaintBorderFlags aFlags,
|
||||
Sides aSkipSides = Sides());
|
||||
|
||||
/**
|
||||
* Like PaintBorder, but taking an nsStyleBorder argument instead of
|
||||
* getting it from aStyleContext. aSkipSides says which sides to skip
|
||||
* when rendering, the default is to skip none.
|
||||
*/
|
||||
static void PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsRect& aBorderArea,
|
||||
const nsStyleBorder& aBorderStyle,
|
||||
nsStyleContext* aStyleContext,
|
||||
Sides aSkipSides = Sides());
|
||||
static DrawResult PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsRect& aBorderArea,
|
||||
const nsStyleBorder& aBorderStyle,
|
||||
nsStyleContext* aStyleContext,
|
||||
mozilla::PaintBorderFlags aFlags,
|
||||
Sides aSkipSides = Sides());
|
||||
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче