Bug 740200 - BorrowedContext support for cairo; r=mattwoodrow

This commit is contained in:
Anthony Jones 2013-09-20 14:00:35 +12:00
parent a2a4818d2c
commit d37823e898
3 changed files with 92 additions and 0 deletions

View File

@ -27,6 +27,9 @@
#include <string>
#endif
struct _cairo;
typedef struct _cairo cairo_t;
struct _cairo_surface;
typedef _cairo_surface cairo_surface_t;
@ -1017,6 +1020,60 @@ private:
static DrawEventRecorder *mRecorder;
};
/* This is a helper class that let's you borrow a cairo_t from a
* DrawTargetCairo. This is used for drawing themed widgets.
*
* Callers should check the cr member after constructing the object
* to see if it succeeded. The DrawTarget should not be used while
* the context is borrowed. */
class BorrowedCairoContext
{
public:
BorrowedCairoContext()
: mCairo(nullptr)
, mDT(nullptr)
{ }
BorrowedCairoContext(DrawTarget *aDT)
: mDT(aDT)
{
mCairo = BorrowCairoContextFromDrawTarget(aDT);
}
// We can optionally Init after construction in
// case we don't know what the DT will be at construction
// time.
cairo_t *Init(DrawTarget *aDT)
{
MOZ_ASSERT(!mDT, "Can't initialize twice!");
mDT = aDT;
return mCairo = BorrowCairoContextFromDrawTarget(aDT);
}
// The caller needs to call Finish if cr is non-null when
// they are done with the context. This is currently explicit
// instead of happening implicitly in the destructor to make
// what's happening in the caller more clear. It also
// let's you resume using the DrawTarget in the same scope.
void Finish()
{
if (mCairo) {
ReturnCairoContextToDrawTarget(mDT, mCairo);
mCairo = nullptr;
}
}
~BorrowedCairoContext() {
MOZ_ASSERT(!mCairo);
}
cairo_t *mCairo;
private:
static cairo_t* BorrowCairoContextFromDrawTarget(DrawTarget *aDT);
static void ReturnCairoContextToDrawTarget(DrawTarget *aDT, cairo_t *aCairo);
DrawTarget *mDT;
};
#ifdef XP_MACOSX
/* This is a helper class that let's you borrow a CGContextRef from a
* DrawTargetCG. This is used for drawing themed widgets.

View File

@ -1096,5 +1096,38 @@ DrawTargetCairo::SetTransform(const Matrix& aTransform)
cairo_set_matrix(mContext, &mat);
}
cairo_t*
BorrowedCairoContext::BorrowCairoContextFromDrawTarget(DrawTarget* aDT)
{
if (aDT->GetType() != BACKEND_CAIRO || aDT->IsDualDrawTarget()) {
return nullptr;
}
DrawTargetCairo* cairoDT = static_cast<DrawTargetCairo*>(aDT);
cairoDT->WillChange();
// save the state to make it easier for callers to avoid mucking with things
cairo_save(cairoDT->mContext);
// Neuter the DrawTarget while the context is being borrowed
cairo_t* cairo = cairoDT->mContext;
cairoDT->mContext = nullptr;
return cairo;
}
void
BorrowedCairoContext::ReturnCairoContextToDrawTarget(DrawTarget* aDT,
cairo_t* aCairo)
{
if (aDT->GetType() != BACKEND_CAIRO || aDT->IsDualDrawTarget()) {
return;
}
DrawTargetCairo* cairoDT = static_cast<DrawTargetCairo*>(aDT);
cairo_restore(aCairo);
cairoDT->mContext = aCairo;
}
}
}

View File

@ -51,6 +51,8 @@ class GradientStopsCairo : public GradientStops
class DrawTargetCairo : public DrawTarget
{
public:
friend class BorrowedCairoContext;
DrawTargetCairo();
virtual ~DrawTargetCairo();