зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1220629 - Part 3: Implement PushLayer/PopLayer API in cairo. r=jrmuizel
--HG-- extra : rebase_source : 058ed10659456f59761535f7538ced6df5425aec
This commit is contained in:
Родитель
fd6c57413d
Коммит
6b108bc5cb
|
@ -1234,6 +1234,18 @@ DrawTargetCairo::Fill(const Path *aPath,
|
|||
DrawPattern(aPattern, StrokeOptions(), aOptions, DRAW_FILL);
|
||||
}
|
||||
|
||||
bool
|
||||
DrawTargetCairo::IsCurrentGroupOpaque()
|
||||
{
|
||||
cairo_surface_t* surf = cairo_get_group_target(mContext);
|
||||
|
||||
if (!surf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return cairo_surface_get_content(surf) == CAIRO_CONTENT_COLOR;
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::SetPermitSubpixelAA(bool aPermitSubpixelAA)
|
||||
{
|
||||
|
@ -1455,6 +1467,87 @@ DrawTargetCairo::PopClip()
|
|||
|
||||
cairo_set_matrix(mContext, &mat);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform, const IntRect& aBounds,
|
||||
bool aCopyBackground)
|
||||
{
|
||||
cairo_content_t content = CAIRO_CONTENT_COLOR_ALPHA;
|
||||
|
||||
if (mFormat == SurfaceFormat::A8) {
|
||||
content = CAIRO_CONTENT_ALPHA;
|
||||
} else if (aOpaque) {
|
||||
content = CAIRO_CONTENT_COLOR;
|
||||
}
|
||||
|
||||
if (aCopyBackground) {
|
||||
cairo_surface_t* source = cairo_get_group_target(mContext);
|
||||
cairo_push_group_with_content(mContext, content);
|
||||
cairo_surface_t* dest = cairo_get_group_target(mContext);
|
||||
cairo_t* ctx = cairo_create(dest);
|
||||
cairo_set_source_surface(ctx, source, 0, 0);
|
||||
cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_paint(ctx);
|
||||
cairo_destroy(ctx);
|
||||
} else {
|
||||
cairo_push_group_with_content(mContext, content);
|
||||
}
|
||||
|
||||
PushedLayer layer(aOpacity, mPermitSubpixelAA);
|
||||
|
||||
if (aMask) {
|
||||
cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(aMask);
|
||||
if (surf) {
|
||||
layer.mMaskPattern = cairo_pattern_create_for_surface(surf);
|
||||
cairo_matrix_t mat;
|
||||
GfxMatrixToCairoMatrix(aMaskTransform, mat);
|
||||
cairo_matrix_invert(&mat);
|
||||
cairo_pattern_set_matrix(layer.mMaskPattern, &mat);
|
||||
cairo_surface_destroy(surf);
|
||||
} else {
|
||||
gfxCriticalError() << "Failed to get cairo surface for mask surface!";
|
||||
}
|
||||
}
|
||||
|
||||
mPushedLayers.push_back(layer);
|
||||
|
||||
SetPermitSubpixelAA(aOpaque);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::PopLayer()
|
||||
{
|
||||
MOZ_ASSERT(mPushedLayers.size());
|
||||
|
||||
cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
|
||||
|
||||
cairo_pop_group_to_source(mContext);
|
||||
|
||||
PushedLayer layer = mPushedLayers.back();
|
||||
mPushedLayers.pop_back();
|
||||
|
||||
if (!layer.mMaskPattern) {
|
||||
cairo_paint_with_alpha(mContext, layer.mOpacity);
|
||||
} else {
|
||||
if (layer.mOpacity != Float(1.0)) {
|
||||
cairo_push_group_with_content(mContext, CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
// Now draw the content using the desired operator
|
||||
cairo_paint_with_alpha(mContext, layer.mOpacity);
|
||||
|
||||
cairo_pop_group_to_source(mContext);
|
||||
}
|
||||
cairo_mask(mContext, layer.mMaskPattern);
|
||||
}
|
||||
|
||||
cairo_matrix_t mat;
|
||||
GfxMatrixToCairoMatrix(mTransform, mat);
|
||||
cairo_set_matrix(mContext, &mat);
|
||||
|
||||
cairo_pattern_destroy(layer.mMaskPattern);
|
||||
SetPermitSubpixelAA(layer.mWasPermittingSubpixelAA);
|
||||
}
|
||||
|
||||
already_AddRefed<PathBuilder>
|
||||
DrawTargetCairo::CreatePathBuilder(FillRule aFillRule /* = FillRule::FILL_WINDING */) const
|
||||
|
@ -1772,7 +1865,7 @@ void *
|
|||
DrawTargetCairo::GetNativeSurface(NativeSurfaceType aType)
|
||||
{
|
||||
if (aType == NativeSurfaceType::CAIRO_SURFACE) {
|
||||
return cairo_get_target(mContext);
|
||||
return cairo_get_group_target(mContext);
|
||||
}
|
||||
if (aType == NativeSurfaceType::CAIRO_CONTEXT) {
|
||||
return mContext;
|
||||
|
|
|
@ -65,6 +65,8 @@ public:
|
|||
virtual already_AddRefed<SourceSurface> Snapshot() override;
|
||||
virtual IntSize GetSize() override;
|
||||
|
||||
virtual bool IsCurrentGroupOpaque() override;
|
||||
|
||||
virtual void SetPermitSubpixelAA(bool aPermitSubpixelAA) override;
|
||||
|
||||
virtual bool LockBits(uint8_t** aData, IntSize* aSize,
|
||||
|
@ -134,6 +136,12 @@ public:
|
|||
virtual void PushClip(const Path *aPath) override;
|
||||
virtual void PushClipRect(const Rect &aRect) override;
|
||||
virtual void PopClip() override;
|
||||
virtual void PushLayer(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false) override;
|
||||
virtual void PopLayer() override;
|
||||
|
||||
virtual already_AddRefed<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override;
|
||||
|
||||
|
@ -214,6 +222,19 @@ private: // data
|
|||
|
||||
uint8_t* mLockedBits;
|
||||
|
||||
struct PushedLayer
|
||||
{
|
||||
PushedLayer(Float aOpacity, bool aWasPermittingSubpixelAA)
|
||||
: mOpacity(aOpacity)
|
||||
, mMaskPattern(nullptr)
|
||||
, mWasPermittingSubpixelAA(aWasPermittingSubpixelAA)
|
||||
{}
|
||||
Float mOpacity;
|
||||
cairo_pattern_t* mMaskPattern;
|
||||
bool mWasPermittingSubpixelAA;
|
||||
};
|
||||
std::vector<PushedLayer> mPushedLayers;
|
||||
|
||||
// The latest snapshot of this surface. This needs to be told when this
|
||||
// target is modified. We keep it alive as a cache.
|
||||
RefPtr<SourceSurfaceCairo> mSnapshot;
|
||||
|
|
|
@ -115,8 +115,10 @@ gfxContext::CurrentSurface(gfxFloat *dx, gfxFloat *dy)
|
|||
(cairo_surface_t*)mDT->GetNativeSurface(NativeSurfaceType::CAIRO_SURFACE);
|
||||
if (s) {
|
||||
if (dx && dy) {
|
||||
*dx = -CurrentState().deviceOffset.x;
|
||||
*dy = -CurrentState().deviceOffset.y;
|
||||
double sdx, sdy;
|
||||
cairo_surface_get_device_offset(s, &sdx, &sdy);
|
||||
*dx = -CurrentState().deviceOffset.x + sdx;
|
||||
*dy = -CurrentState().deviceOffset.y + sdy;
|
||||
}
|
||||
return gfxASurface::Wrap(s);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче