Back out bug 746883, bug 764125, bug 761895, bug 746883, bug 748116

This commit is contained in:
Nicholas Cameron 2012-07-26 18:48:24 +12:00
parent 800f256f44
commit 9e4ceaecb8
42 changed files with 475 additions and 715 deletions

View File

@ -549,11 +549,37 @@ PRUint8 (*nsCanvasRenderingContext2DAzure::sPremultiplyTable)[256] = nsnull;
namespace mozilla {
namespace dom {
static bool
AzureCanvasEnabledOnPlatform()
{
#ifdef XP_WIN
if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() !=
gfxWindowsPlatform::RENDER_DIRECT2D ||
!gfxWindowsPlatform::GetPlatform()->DWriteEnabled()) {
static bool checkedPref = false;
static bool preferSkia;
if (!checkedPref) {
preferSkia = Preferences::GetBool("gfx.canvas.azure.prefer-skia", false);
checkedPref = true;
}
return preferSkia;
}
#elif !defined(XP_MACOSX) && !defined(ANDROID) && !defined(LINUX)
return false;
#endif
return true;
}
bool
AzureCanvasEnabled()
{
BackendType dontCare;
return gfxPlatform::GetPlatform()->SupportsAzureCanvas(dontCare);
static bool checkedPref = false;
static bool azureEnabled;
if (!checkedPref) {
azureEnabled = Preferences::GetBool("gfx.canvas.azure.enabled", false);
checkedPref = true;
}
return azureEnabled && AzureCanvasEnabledOnPlatform();
}
}
@ -562,9 +588,7 @@ AzureCanvasEnabled()
nsresult
NS_NewCanvasRenderingContext2DAzure(nsIDOMCanvasRenderingContext2D** aResult)
{
// XXX[nrc] remove this check when Thebes canvas is removed
// (because we will always support Azure)
if (!AzureCanvasEnabled()) {
if (!AzureCanvasEnabledOnPlatform()) {
return NS_ERROR_NOT_AVAILABLE;
}
@ -890,12 +914,30 @@ nsCanvasRenderingContext2DAzure::SetDimensions(PRInt32 width, PRInt32 height)
}
nsresult
nsCanvasRenderingContext2DAzure::Initialize(PRInt32 width, PRInt32 height)
nsCanvasRenderingContext2DAzure::InitializeWithTarget(DrawTarget *target, PRInt32 width, PRInt32 height)
{
Reset();
NS_ASSERTION(mCanvasElement, "Must have a canvas element!");
mDocShell = nsnull;
mWidth = width;
mHeight = height;
if (!mValid) {
// This first time this is called on this object is via
// nsHTMLCanvasElement::GetContext. If target was non-null then mTarget is
// non-null, otherwise we'll return an error here and GetContext won't
// return this context object and we'll never enter this code again.
// All other times this method is called, if target is null then
// mTarget won't be changed, i.e. it will remain non-null, or else it
// will be set to non-null.
// In all cases, any usable canvas context will have non-null mTarget.
if (target) {
mValid = true;
mTarget = target;
} else {
mValid = false;
// Create a dummy target in the hopes that it will help us deal with users
// calling into us after having changed the size where the size resulted
// in an inability to create a correct DrawTarget.
@ -927,45 +969,6 @@ nsCanvasRenderingContext2DAzure::Initialize(PRInt32 width, PRInt32 height)
return mValid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
nsresult
nsCanvasRenderingContext2DAzure::InitializeWithTarget(DrawTarget *target, PRInt32 width, PRInt32 height)
{
Reset();
NS_ASSERTION(mCanvasElement, "Must have a canvas element!");
mDocShell = nsnull;
// This first time this is called on this object is via
// nsHTMLCanvasElement::GetContext. If target was non-null then mTarget is
// non-null, otherwise we'll return an error here and GetContext won't
// return this context object and we'll never enter this code again.
// All other times this method is called, if target is null then
// mTarget won't be changed, i.e. it will remain non-null, or else it
// will be set to non-null.
// In all cases, any usable canvas context will have non-null mTarget.
if (target) {
mValid = true;
mTarget = target;
} else {
mValid = false;
}
return Initialize(width, height);
}
NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height)
{
mDocShell = shell;
mThebesSurface = surface;
mTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, IntSize(width, height));
mValid = mTarget != nsnull;
return Initialize(width, height);
}
NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::SetIsOpaque(bool isOpaque)
{
@ -2490,7 +2493,6 @@ nsCanvasRenderingContext2DAzure::EnsureWritablePath()
}
if (!mPath) {
NS_ASSERTION(!mPathTransformWillUpdate, "mPathTransformWillUpdate should be false, if all paths are null");
mPathBuilder = mTarget->CreatePathBuilder(fillRule);
} else if (!mPathTransformWillUpdate) {
mPathBuilder = mPath->CopyToBuilder(fillRule);
@ -2502,7 +2504,7 @@ nsCanvasRenderingContext2DAzure::EnsureWritablePath()
}
void
nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* = true */)
nsCanvasRenderingContext2DAzure::EnsureUserSpacePath()
{
FillRule fillRule = CurrentState().fillRule;
@ -2515,9 +2517,7 @@ nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* =
mPathBuilder = nsnull;
}
if (aCommitTransform &&
mPath &&
mPathTransformWillUpdate) {
if (mPath && mPathTransformWillUpdate) {
mDSPathBuilder =
mPath->TransformedCopyToBuilder(mPathToDS, fillRule);
mPath = nsnull;
@ -2531,7 +2531,6 @@ nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* =
Matrix inverse = mTarget->GetTransform();
if (!inverse.Invert()) {
NS_WARNING("Could not invert transform");
return;
}
@ -2545,8 +2544,6 @@ nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* =
mPathBuilder = mPath->CopyToBuilder(fillRule);
mPath = mPathBuilder->Finish();
}
NS_ASSERTION(mPath, "mPath should exist");
}
void
@ -3047,7 +3044,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
const gfxTextRun::CompressedGlyph *glyphs = mTextRun->GetCharacterGlyphs();
RefPtr<ScaledFont> scaledFont =
gfxPlatform::GetPlatform()->GetScaledFontForFont(mCtx->mTarget, font);
gfxPlatform::GetPlatform()->GetScaledFontForFont(font);
if (!scaledFont) {
// This can occur when something switched DirectWrite off.
@ -3107,21 +3104,21 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
AdjustedTarget(mCtx)->
FillGlyphs(scaledFont, buffer,
CanvasGeneralPattern().
ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_FILL, mCtx->mTarget),
DrawOptions(mState->globalAlpha, mCtx->UsedOperation()));
ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_FILL, mCtx->mTarget),
DrawOptions(mState->globalAlpha, mCtx->UsedOperation()));
} else if (mOp == nsCanvasRenderingContext2DAzure::TEXT_DRAW_OPERATION_STROKE) {
RefPtr<Path> path = scaledFont->GetPathForGlyphs(buffer, mCtx->mTarget);
const ContextState& state = *mState;
AdjustedTarget(mCtx)->
Stroke(path, CanvasGeneralPattern().
ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget),
StrokeOptions(state.lineWidth, state.lineJoin,
state.lineCap, state.miterLimit,
state.dash.Length(),
state.dash.Elements(),
state.dashOffset),
DrawOptions(state.globalAlpha, mCtx->UsedOperation()));
ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget),
StrokeOptions(state.lineWidth, state.lineJoin,
state.lineCap, state.miterLimit,
state.dash.Length(),
state.dash.Elements(),
state.dashOffset),
DrawOptions(state.globalAlpha, mCtx->UsedOperation()));
}
}
@ -3610,14 +3607,9 @@ nsCanvasRenderingContext2DAzure::IsPointInPath(double x, double y)
return false;
}
EnsureUserSpacePath(false);
if (!mPath) {
return false;
}
if (mPathTransformWillUpdate) {
return mPath->ContainsPoint(Point(x, y), mPathToDS);
}
return mPath->ContainsPoint(Point(x, y), mTarget->GetTransform());
EnsureUserSpacePath();
return mPath && mPath->ContainsPoint(Point(x, y), mTarget->GetTransform());
}
NS_IMETHODIMP
@ -3676,14 +3668,12 @@ nsCanvasRenderingContext2DAzure::DrawImage(const HTMLImageOrCanvasOrVideoElement
// This might not be an Azure canvas!
srcSurf = srcCanvas->GetSurfaceSnapshot();
if (srcSurf) {
if (mCanvasElement) {
// Do security check here.
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
element->NodePrincipal(),
canvas->IsWriteOnly(),
false);
}
if (srcSurf && mCanvasElement) {
// Do security check here.
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
element->NodePrincipal(),
canvas->IsWriteOnly(),
false);
imgSize = gfxIntSize(srcSurf->GetSize().width, srcSurf->GetSize().height);
}
}
@ -4265,12 +4255,11 @@ nsCanvasRenderingContext2DAzure::GetImageDataArray(JSContext* aCx,
RefPtr<DataSourceSurface> readback;
if (!srcReadRect.IsEmpty()) {
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
if (snapshot) {
readback = snapshot->GetDataSurface();
srcStride = readback->Stride();
src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
}
readback = snapshot->GetDataSurface();
srcStride = readback->Stride();
src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
}
// make sure sUnpremultiplyTable has been created
@ -4278,8 +4267,6 @@ nsCanvasRenderingContext2DAzure::GetImageDataArray(JSContext* aCx,
// NOTE! dst is the same as src, and this relies on reading
// from src and advancing that ptr before writing to dst.
// NOTE! I'm not sure that it is, I think this comment might have been
// inherited from Thebes canvas and is no longer true
uint8_t* dst = data + dstWriteRect.y * (aWidth * 4) + dstWriteRect.x * 4;
for (int32_t j = 0; j < dstWriteRect.height; ++j) {
@ -4611,8 +4598,8 @@ static PRUint8 g2DContextLayerUserData;
already_AddRefed<CanvasLayer>
nsCanvasRenderingContext2DAzure::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
LayerManager *aManager)
CanvasLayer *aOldLayer,
LayerManager *aManager)
{
if (!mValid) {
return nsnull;
@ -4682,9 +4669,3 @@ nsCanvasRenderingContext2DAzure::MarkContextClean()
mInvalidateCount = 0;
}
bool
nsCanvasRenderingContext2DAzure::ShouldForceInactiveLayer(LayerManager *aManager)
{
return !aManager->CanUseCanvasLayerForSize(gfxIntSize(mWidth, mHeight));
}

View File

@ -464,7 +464,8 @@ public:
// nsICanvasRenderingContextInternal
NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height);
NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height)
{ return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD Render(gfxContext *ctx,
gfxPattern::GraphicsFilter aFilter,
@ -482,7 +483,6 @@ public:
already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
LayerManager *aManager);
virtual bool ShouldForceInactiveLayer(LayerManager *aManager);
void MarkContextClean();
NS_IMETHOD SetIsIPC(bool isIPC);
// this rect is in canvas device space
@ -542,11 +542,6 @@ protected:
uint32_t aWidth, uint32_t aHeight,
JSObject** aRetval);
/**
* Internal method to complete initialisation, expects mTarget to have been set
*/
nsresult Initialize(PRInt32 width, PRInt32 height);
nsresult InitializeWithTarget(mozilla::gfx::DrawTarget *surface,
PRInt32 width, PRInt32 height);
@ -601,14 +596,11 @@ protected:
/* This function ensures there is a writable pathbuilder available, this
* pathbuilder may be working in user space or in device space or
* device space.
* After calling this function mPathTransformWillUpdate will be false
*/
void EnsureWritablePath();
// Ensures a path in UserSpace is available.
// If aCommitTransform is true, then any transform on the context will be
// used for the path.
void EnsureUserSpacePath(bool aCommitTransform = true);
void EnsureUserSpacePath();
void TransformWillUpdate();

View File

@ -55,7 +55,6 @@ MOCHITEST_FILES = \
test_canvas_strokeStyle_getter.html \
test_bug613794.html \
test_bug753758.html \
test_bug764125.html \
test_drawImage_edge_cases.html \
$(NULL)

View File

@ -1,36 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=764125
Test the correct behaviour for isPointInPath in the presence of multiple transforms,
where only one tranform ought to be applied.
-->
<head>
<title>Test for Bug 764125</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=764125">Mozilla Bug 764125</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script>
/** Test for Bug 764125 **/
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
ctx.translate(50, 0);
ctx.rect(50, 0, 20, 20);
ctx.translate(0, 50);
ok(ctx.isPointInPath(60, 10) === false, "ctx.isPointInPath(60, 10) === false");
ok(ctx.isPointInPath(110, 10) === true, "ctx.isPointInPath(110, 10) === true");
ok(ctx.isPointInPath(110, 60) === false, "ctx.isPointInPath(110, 60) === false");
</script>
</pre>
</body>
</html>

View File

@ -18,10 +18,6 @@ function IsD2DEnabled() {
return enabled;
}
function IsLinux() {
return navigator.platform.indexOf("Linux") == 0;
}
function IsMacOSX10_5orOlder() {
var is105orOlder = false;
@ -44,8 +40,7 @@ function IsAzureEnabled() {
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
enabled = (backend != "none");
enabled = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).AzureEnabled;
} catch (e) { }
return enabled;
@ -63,18 +58,6 @@ function IsAzureSkia() {
return enabled;
}
function IsAzureCairo() {
var enabled = false;
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
enabled = (backend == "cairo");
} catch (e) { }
return enabled;
}
</script>
<!-- Includes all the tests in the content/canvas/tests except for test_bug397524.html -->
@ -11312,24 +11295,10 @@ isPixel(ctx, 50,25, 0,255,0,255, 0);
isPixel(ctx, 1,1, 0,255,0,255, 0);
isPixel(ctx, 98,1, 0,255,0,255, 0);
isPixel(ctx, 1,48, 0,255,0,255, 0);
// Fails on Linux with Azure/Cairo only
// The arc is drawn badly due to Cairo limitations, the error only becomes
// apparent on Linux because of anti-aliasing, probably due to X.
// The limitation is that Cairo draws arcs by stroking perpendicular to the arc,
// and at very large stroke thicknesses, this becomes a fan. Where exactly the
// 'blades' of the fan appear seems to depend on exactly how the arc is defined
// and the platform. So if the blades of the fan are where pixels are tested it
// passes the test, if the testing pixels fall in between the blades, then we fail.
// With Thebes/Cairo, we were rendering wrong, but got lucky with the test, now
// we are not so lucky.
// Bug 764125
if (IsAzureCairo() && IsLinux()) {
todo_isPixel(ctx, 20,48, 0,255,0,255, 0);
} else {
isPixel(ctx, 20,48, 0,255,0,255, 0);
}
isPixel(ctx, 20,48, 0,255,0,255, 0);
isPixel(ctx, 98,48, 0,255,0,255, 0);
}
</script>
@ -14688,14 +14657,9 @@ isPixel(ctx, 0,25, 0,255,0,255, 0);
isPixel(ctx, 50,25, 0,255,0,255, 0);
isPixel(ctx, 99,25, 0,255,0,255, 0);
isPixel(ctx, 0,49, 0,255,0,255, 0);
if (IsAzureEnabled() && IsAzureCairo()) {
// Bug 764108
todo_isPixel(ctx, 50,49, 0,255,0,255, 0);
todo_isPixel(ctx, 99,49, 0,255,0,255, 0);
} else {
isPixel(ctx, 50,49, 0,255,0,255, 0);
isPixel(ctx, 99,49, 0,255,0,255, 0);
}
isPixel(ctx, 50,49, 0,255,0,255, 0);
isPixel(ctx, 99,49, 0,255,0,255, 0);
}
</script>

View File

@ -802,7 +802,7 @@ class GFX2D_API Factory
public:
static bool HasSSE2();
static TemporaryRef<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize);
static TemporaryRef<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface);
static TemporaryRef<DrawTarget>
CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat);

View File

@ -13,8 +13,6 @@
#include "cairo.h"
#include "Blur.h"
#include "Logging.h"
#include "Tools.h"
#ifdef CAIRO_HAS_QUARTZ_SURFACE
#include "cairo-quartz.h"
@ -118,51 +116,6 @@ PatternIsCompatible(const Pattern& aPattern)
}
}
static cairo_user_data_key_t surfaceDataKey;
void
ReleaseData(void* aData)
{
static_cast<DataSourceSurface*>(aData)->Release();
}
/**
* Returns cairo surface for the given SourceSurface.
* If possible, it will use the cairo_surface associated with aSurface,
* otherwise, it will create a new cairo_surface.
* In either case, the caller must call cairo_surface_destroy on the
* result when it is done with it.
*/
cairo_surface_t*
GetCairoSurfaceForSourceSurface(SourceSurface *aSurface)
{
if (aSurface->GetType() == SURFACE_CAIRO) {
cairo_surface_t* surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
cairo_surface_reference(surf);
return surf;
}
if (aSurface->GetType() == SURFACE_CAIRO_IMAGE) {
cairo_surface_t* surf =
static_cast<const DataSourceSurfaceCairo*>(aSurface)->GetSurface();
cairo_surface_reference(surf);
return surf;
}
RefPtr<DataSourceSurface> data = aSurface->GetDataSurface();
cairo_surface_t* surf =
cairo_image_surface_create_for_data(data->GetData(),
GfxFormatToCairoFormat(data->GetFormat()),
data->GetSize().width,
data->GetSize().height,
data->Stride());
cairo_surface_set_user_data(surf,
&surfaceDataKey,
data.forget().drop(),
ReleaseData);
return surf;
}
// Never returns NULL. As such, you must always pass in Cairo-compatible
// patterns, most notably gradients with a GradientStopCairo.
// The pattern returned must have cairo_pattern_destroy() called on it by the
@ -187,7 +140,28 @@ GfxPatternToCairoPattern(const Pattern& aPattern, Float aAlpha)
case PATTERN_SURFACE:
{
const SurfacePattern& pattern = static_cast<const SurfacePattern&>(aPattern);
cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(pattern.mSurface);
cairo_surface_t* surf;
// After this block, |surf| always has an extra cairo reference to be
// destroyed. This makes creating new surfaces or reusing old ones more
// uniform.
if (pattern.mSurface->GetType() == SURFACE_CAIRO) {
const SourceSurfaceCairo* source = static_cast<const SourceSurfaceCairo*>(pattern.mSurface.get());
surf = source->GetSurface();
cairo_surface_reference(surf);
} else if (pattern.mSurface->GetType() == SURFACE_CAIRO_IMAGE) {
const DataSourceSurfaceCairo* source =
static_cast<const DataSourceSurfaceCairo*>(pattern.mSurface.get());
surf = source->GetSurface();
cairo_surface_reference(surf);
} else {
RefPtr<DataSourceSurface> source = pattern.mSurface->GetDataSurface();
surf = cairo_image_surface_create_for_data(source->GetData(),
GfxFormatToCairoFormat(source->GetFormat()),
source->GetSize().width,
source->GetSize().height,
source->Stride());
}
pat = cairo_pattern_create_for_surface(surf);
cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(pattern.mFilter));
@ -244,21 +218,6 @@ GfxPatternToCairoPattern(const Pattern& aPattern, Float aAlpha)
return pat;
}
/**
* Returns true iff the the given operator should affect areas of the
* destination where the source is transparent. Among other things, this
* implies that a fully transparent source would still affect the canvas.
*/
static bool
OperatorAffectsUncoveredAreas(CompositionOp op)
{
return op == OP_IN ||
op == OP_OUT ||
op == OP_DEST_IN ||
op == OP_DEST_ATOP ||
op == OP_DEST_OUT;
}
static bool
NeedIntermediateSurface(const Pattern& aPattern, const DrawOptions& aOptions)
{
@ -285,28 +244,29 @@ DrawTargetCairo::~DrawTargetCairo()
mPathObserver->ForgetDrawTarget();
}
cairo_destroy(mContext);
if (mSurface) {
cairo_surface_destroy(mSurface);
}
}
IntSize
DrawTargetCairo::GetSize()
{
return mSize;
return IntSize();
}
TemporaryRef<SourceSurface>
DrawTargetCairo::Snapshot()
{
IntSize size = GetSize();
cairo_surface_t* csurf = cairo_get_target(mContext);
IntSize size;
if (GetCairoSurfaceSize(csurf, size)) {
cairo_content_t content = cairo_surface_get_content(csurf);
RefPtr<SourceSurfaceCairo> surf = new SourceSurfaceCairo(csurf, size,
CairoContentToGfxFormat(content),
this);
AppendSnapshot(surf);
return surf;
}
cairo_content_t content = cairo_surface_get_content(mSurface);
RefPtr<SourceSurfaceCairo> surf = new SourceSurfaceCairo(mSurface, size,
CairoContentToGfxFormat(content),
this);
AppendSnapshot(surf);
return surf;
return NULL;
}
void
@ -335,40 +295,29 @@ DrawTargetCairo::DrawSurface(SourceSurface *aSurface,
float sy = aSource.Height() / aDest.Height();
cairo_matrix_t src_mat;
cairo_matrix_init_translate(&src_mat, aSource.X(), aSource.Y());
cairo_matrix_scale(&src_mat, sx, sy);
cairo_matrix_init_scale(&src_mat, sx, sy);
cairo_matrix_translate(&src_mat, aSource.X(), aSource.Y());
cairo_surface_t* surf = NULL;
if (aSurface->GetType() == SURFACE_CAIRO) {
surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
}
cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(aSurface);
cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf);
cairo_surface_destroy(surf);
cairo_pattern_set_matrix(pat, &src_mat);
cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(aSurfOptions.mFilter));
cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
cairo_save(mContext);
cairo_translate(mContext, aDest.X(), aDest.Y());
if (OperatorAffectsUncoveredAreas(aOptions.mCompositionOp) ||
aOptions.mCompositionOp == OP_SOURCE) {
cairo_push_group(mContext);
cairo_new_path(mContext);
cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
//TODO[nrc] remove comments if test ok
//cairo_clip(mContext);
cairo_set_source(mContext, pat);
//cairo_paint(mContext);
cairo_fill(mContext);
cairo_pop_group_to_source(mContext);
} else {
cairo_new_path(mContext);
cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
cairo_clip(mContext);
cairo_set_source(mContext, pat);
}
cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
cairo_translate(mContext, aDest.X(), aDest.Y());
cairo_set_source(mContext, pat);
cairo_new_path(mContext);
cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
cairo_clip(mContext);
cairo_paint_with_alpha(mContext, aOptions.mAlpha);
cairo_restore(mContext);
@ -384,11 +333,13 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface,
Float aSigma,
CompositionOp aOperator)
{
WillChange();
if (aSurface->GetType() != SURFACE_CAIRO) {
return;
}
WillChange();
SourceSurfaceCairo* source = static_cast<SourceSurfaceCairo*>(aSurface);
Float width = aSurface->GetSize().width;
Float height = aSurface->GetSize().height;
@ -402,19 +353,16 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface,
}
IntSize blursize = blur.GetSize();
cairo_surface_t* blursurf = cairo_image_surface_create_for_data(blur.GetData(),
CAIRO_FORMAT_A8,
blursize.width,
blursize.height,
blur.GetStride());
ClearSurfaceForUnboundedSource(aOperator);
// Draw the source surface into the surface we're going to blur.
SourceSurfaceCairo* source = static_cast<SourceSurfaceCairo*>(aSurface);
cairo_surface_t* surf = source->GetSurface();
cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf);
cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
cairo_t* ctx = cairo_create(blursurf);
@ -431,39 +379,26 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface,
// Blur the result, then use that blurred result as a mask to draw the shadow
// colour to the surface.
blur.Blur();
cairo_save(mContext);
cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
cairo_identity_matrix(mContext);
cairo_translate(mContext, aDest.x, aDest.y);
if (OperatorAffectsUncoveredAreas(aOperator) ||
aOperator == OP_SOURCE){
cairo_push_group(mContext);
cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
cairo_pop_group_to_source(mContext);
cairo_paint(mContext);
cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
// Now that the shadow has been drawn, we can draw the surface on top.
cairo_push_group(mContext);
cairo_new_path(mContext);
cairo_rectangle(mContext, 0, 0, width, height);
//TODO[nrc] remove comments if test ok
//cairo_clip(mContext);
cairo_set_source(mContext, pat);
//cairo_paint(mContext);
cairo_fill(mContext);
cairo_pop_group_to_source(mContext);
} else {
cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
// Now that the shadow has been drawn, we can draw the surface on top.
// Now that the shadow has been drawn, we can draw the surface on top.
cairo_set_source(mContext, pat);
cairo_new_path(mContext);
cairo_rectangle(mContext, 0, 0, width, height);
cairo_clip(mContext);
}
cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
cairo_set_source(mContext, pat);
cairo_new_path(mContext);
cairo_rectangle(mContext, 0, 0, width, height);
cairo_clip(mContext);
cairo_paint(mContext);
@ -485,12 +420,9 @@ DrawTargetCairo::DrawPattern(const Pattern& aPattern,
cairo_pattern_t* pat = GfxPatternToCairoPattern(aPattern, aOptions.mAlpha);
cairo_set_source(mContext, pat);
if (NeedIntermediateSurface(aPattern, aOptions) ||
OperatorAffectsUncoveredAreas(aOptions.mCompositionOp)) {
if (NeedIntermediateSurface(aPattern, aOptions)) {
cairo_push_group_with_content(mContext, CAIRO_CONTENT_COLOR_ALPHA);
ClearSurfaceForUnboundedSource(aOptions.mCompositionOp);
// Don't want operators to be applied twice
cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
@ -507,7 +439,6 @@ DrawTargetCairo::DrawPattern(const Pattern& aPattern,
cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
cairo_paint_with_alpha(mContext, aOptions.mAlpha);
} else {
ClearSurfaceForUnboundedSource(aOptions.mCompositionOp);
cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
if (aDrawType == DRAW_STROKE) {
@ -536,31 +467,10 @@ DrawTargetCairo::FillRect(const Rect &aRect,
void
DrawTargetCairo::CopySurface(SourceSurface *aSurface,
const IntRect &aSource,
const IntPoint &aDest)
const IntRect &aSourceRect,
const IntPoint &aDestination)
{
AutoPrepareForDrawing prep(this, mContext);
if (!aSurface || aSurface->GetType() != SURFACE_CAIRO) {
gfxWarning() << "Unsupported surface type specified";
return;
}
cairo_surface_t* surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
cairo_save(mContext);
cairo_identity_matrix(mContext);
cairo_set_source_surface(mContext, surf, aDest.x - aSource.x, aDest.y - aSource.y);
cairo_set_operator(mContext, CAIRO_OPERATOR_SOURCE);
cairo_reset_clip(mContext);
cairo_new_path(mContext);
cairo_rectangle(mContext, aDest.x, aDest.y, aSource.width, aSource.height);
cairo_fill(mContext);
cairo_restore(mContext);
}
void
@ -726,19 +636,6 @@ DrawTargetCairo::CreatePathBuilder(FillRule aFillRule /* = FILL_WINDING */) cons
return builder;
}
void
DrawTargetCairo::ClearSurfaceForUnboundedSource(const CompositionOp &aOperator)
{
if (aOperator != OP_SOURCE)
return;
cairo_set_operator(mContext, CAIRO_OPERATOR_CLEAR);
// It doesn't really matter what the source is here, since Paint
// isn't bounded by the source and the mask covers the entire clip
// region.
cairo_paint(mContext);
}
TemporaryRef<GradientStops>
DrawTargetCairo::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const
{
@ -746,40 +643,19 @@ DrawTargetCairo::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, E
return stops;
}
/**
* Copies pixel data from aData into aSurface; aData must have the dimensions
* given in aSize, with a stride of aStride bytes and aPixelWidth bytes per pixel
*/
static void
CopyDataToCairoSurface(cairo_surface_t* aSurface,
unsigned char *aData,
const IntSize &aSize,
int32_t aStride,
int32_t aPixelWidth)
{
unsigned char* surfData = cairo_image_surface_get_data(aSurface);
for (int32_t y = 0; y < aSize.height; ++y) {
memcpy(surfData + y * aSize.width * aPixelWidth,
aData + y * aStride,
aSize.width * aPixelWidth);
}
cairo_surface_mark_dirty(aSurface);
}
TemporaryRef<SourceSurface>
DrawTargetCairo::CreateSourceSurfaceFromData(unsigned char *aData,
const IntSize &aSize,
int32_t aStride,
SurfaceFormat aFormat) const
{
cairo_surface_t* surf = cairo_image_surface_create(GfxFormatToCairoFormat(aFormat),
aSize.width,
aSize.height);
CopyDataToCairoSurface(surf, aData, aSize, aStride, BytesPerPixel(aFormat));
cairo_surface_t* surf = cairo_image_surface_create_for_data(aData,
GfxFormatToCairoFormat(aFormat),
aSize.width,
aSize.height,
aStride);
RefPtr<SourceSurfaceCairo> source_surf = new SourceSurfaceCairo(surf, aSize, aFormat);
cairo_surface_destroy(surf);
return source_surf;
}
@ -814,7 +690,7 @@ DrawTargetCairo::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFo
if (!cairo_surface_status(similar)) {
RefPtr<DrawTargetCairo> target = new DrawTargetCairo();
target->Init(similar, aSize);
target->Init(similar);
return target;
}
@ -822,13 +698,9 @@ DrawTargetCairo::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFo
}
bool
DrawTargetCairo::Init(cairo_surface_t* aSurface, const IntSize& aSize)
DrawTargetCairo::Init(cairo_surface_t* aSurface)
{
mContext = cairo_create(aSurface);
mSurface = aSurface;
cairo_surface_reference(mSurface);
mSize = aSize;
mFormat = CairoContentToGfxFormat(cairo_surface_get_content(aSurface));
return true;
}

View File

@ -123,7 +123,7 @@ public:
virtual void *GetNativeSurface(NativeSurfaceType aType);
bool Init(cairo_surface_t* aSurface, const IntSize& aSize);
bool Init(cairo_surface_t* aSurface);
void SetPathObserver(CairoPathContext* aPathObserver);
@ -155,13 +155,8 @@ private: // methods
// target; for example, because we're going to be destroyed.
void MarkSnapshotsIndependent();
// If the current operator is "source" then clear the destination before we
// draw into it, to simulate the effect of an unbounded source operator.
void ClearSurfaceForUnboundedSource(const CompositionOp &aOperator);
private: // data
cairo_t* mContext;
cairo_surface_t* mSurface;
IntSize mSize;
std::vector<SourceSurfaceCairo*> mSnapshots;
mutable RefPtr<CairoPathContext> mPathObserver;
};

View File

@ -239,10 +239,6 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSiz
{
return new ScaledFontDWrite(static_cast<IDWriteFontFace*>(aNativeFont.mFont), aSize);
}
case NATIVE_FONT_GDI_FONT_FACE:
{
return new ScaledFontWin(static_cast<LOGFONT*>(aNativeFont.mFont), aSize);
}
#endif
#ifdef XP_MACOSX
case NATIVE_FONT_MAC_FONT_FACE:
@ -251,6 +247,12 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSiz
}
#endif
#ifdef USE_SKIA
#ifdef WIN32
case NATIVE_FONT_GDI_FONT_FACE:
{
return new ScaledFontWin(static_cast<LOGFONT*>(aNativeFont.mFont), aSize);
}
#endif
#ifdef MOZ_ENABLE_FREETYPE
case NATIVE_FONT_SKIA_FONT_FACE:
{
@ -261,9 +263,7 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSiz
#ifdef USE_CAIRO
case NATIVE_FONT_CAIRO_FONT_FACE:
{
ScaledFontBase* fontBase = new ScaledFontBase(aSize);
fontBase->SetCairoScaledFont(static_cast<cairo_scaled_font_t*>(aNativeFont.mFont));
return fontBase;
return new ScaledFontBase(aSize);
}
#endif
default:
@ -367,11 +367,11 @@ Factory::GetD2DVRAMUsageSourceSurface()
#endif // XP_WIN
TemporaryRef<DrawTarget>
Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize)
Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface)
{
#ifdef USE_CAIRO
RefPtr<DrawTargetCairo> newTarget = new DrawTargetCairo();
if (newTarget->Init(aSurface, aSize)) {
if (newTarget->Init(aSurface)) {
return newTarget;
}

View File

@ -76,7 +76,7 @@ JoinStyleToSkiaJoin(JoinStyle aJoin)
static inline bool
StrokeOptionsToPaint(SkPaint& aPaint, const StrokeOptions &aOptions)
{
// Skia renders 0 width strokes with a width of 1 (and in black),
// Skia rendewrs 0 width strokes with a width of 1 (and in black),
// so we should just skip the draw call entirely.
if (!aOptions.mLineWidth) {
return false;

View File

@ -44,28 +44,6 @@ CairoPathContext::~CairoPathContext()
cairo_destroy(mContext);
}
void
CairoPathContext::ObserveTarget(DrawTargetCairo* aDrawTarget)
{
if (!aDrawTarget) {
return;
}
if (mDrawTarget) {
mDrawTarget->SetPathObserver(NULL);
}
mDrawTarget = aDrawTarget;
// If there is a transform on the path, then we must have a separate context
// from the draw target, so we cannot be its observer
if (!mTransform.IsIdentity()) {
ForgetDrawTarget();
return;
}
mDrawTarget->SetPathObserver(this);
}
void
CairoPathContext::DuplicateContextAndPath(const Matrix& aMatrix /* = Matrix() */)
{
@ -342,7 +320,11 @@ PathCairo::CopyPathTo(cairo_t* aContext, DrawTargetCairo* aDrawTarget)
// Since aDrawTarget wants us to be the current path on its context, we
// should also listen to it for updates to that path (as an optimization).
mPathContext->ObserveTarget(aDrawTarget);
// The easiest way to do this is to just recreate mPathContext, since it
// registers with aDrawTarget for updates.
mPathContext = new CairoPathContext(aContext, aDrawTarget,
mPathContext->GetFillRule(),
mPathContext->GetTransform());
}
}

View File

@ -68,10 +68,6 @@ public:
// Returns true if this CairoPathContext represents path.
bool ContainsPath(const Path* path);
// add ourselves as an observer of aDrawTarget, if possible
// if we succeed, then mDrawTarget is set to aDrawTarget
void ObserveTarget(DrawTargetCairo* aDrawTarget);
cairo_t* GetContext() const { return mContext; }
DrawTargetCairo* GetDrawTarget() const { return mDrawTarget; }
Matrix GetTransform() const { return mTransform; }

View File

@ -103,7 +103,6 @@ SourceSurfaceCairo::DrawTargetWillChange()
cairo_set_source(ctx, pat);
cairo_paint(ctx);
cairo_destroy(ctx);
cairo_pattern_destroy(pat);
// Swap in this new surface.
cairo_surface_destroy(mSurface);

View File

@ -38,7 +38,7 @@ enum SurfaceFormat
enum BackendType
{
BACKEND_NONE = 0,
BACKEND_NONE,
BACKEND_DIRECT2D,
BACKEND_COREGRAPHICS,
BACKEND_CAIRO,

View File

@ -484,11 +484,8 @@ TemporaryRef<DrawTarget>
LayerManagerD3D10::CreateDrawTarget(const IntSize &aSize,
SurfaceFormat aFormat)
{
BackendType backend;
if ((aFormat != FORMAT_B8G8R8A8 &&
aFormat != FORMAT_B8G8R8X8) ||
!gfxPlatform::GetPlatform()->SupportsAzureCanvas(backend) ||
backend != BACKEND_DIRECT2D) {
aFormat != FORMAT_B8G8R8X8)) {
return LayerManager::CreateDrawTarget(aSize, aFormat);
}

View File

@ -32,7 +32,6 @@ CanvasLayerD3D9::Initialize(const Data& aData)
if (aData.mDrawTarget) {
mDrawTarget = aData.mDrawTarget;
mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
mNeedsYFlip = false;
mDataIsPremultiplied = true;
} else if (aData.mSurface) {
@ -140,11 +139,18 @@ CanvasLayerD3D9::UpdateSurface()
D3DLOCKED_RECT lockedRect = textureLock.GetLockRect();
nsRefPtr<gfxImageSurface> sourceSurface;
nsRefPtr<gfxASurface> tempSurface;
if (mDrawTarget) {
tempSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
}
else {
tempSurface = mSurface;
}
if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
sourceSurface = mSurface->GetAsImageSurface();
} else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
sourceSurface = static_cast<gfxImageSurface*>(mSurface.get());
if (tempSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
sourceSurface = tempSurface->GetAsImageSurface();
} else if (tempSurface->GetType() == gfxASurface::SurfaceTypeImage) {
sourceSurface = static_cast<gfxImageSurface*>(tempSurface.get());
if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 &&
sourceSurface->Format() != gfxASurface::ImageFormatRGB24)
{
@ -155,7 +161,7 @@ CanvasLayerD3D9::UpdateSurface()
gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetSource(mSurface);
ctx->SetSource(tempSurface);
ctx->Paint();
}

View File

@ -75,7 +75,6 @@ CanvasLayerOGL::Initialize(const Data& aData)
if (aData.mDrawTarget) {
mDrawTarget = aData.mDrawTarget;
mCanvasSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
mNeedsYFlip = false;
} else if (aData.mSurface) {
mCanvasSurface = aData.mSurface;
@ -163,7 +162,11 @@ CanvasLayerOGL::UpdateSurface()
} else {
nsRefPtr<gfxASurface> updatedAreaSurface;
if (mCanvasSurface) {
if (mDrawTarget) {
// TODO: This is suboptimal - We should have direct handling for the surface types instead of
// going via a gfxASurface.
updatedAreaSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
} else if (mCanvasSurface) {
updatedAreaSurface = mCanvasSurface;
} else if (mCanvasGLContext) {
gfxIntSize size(mBounds.width, mBounds.height);
@ -223,8 +226,13 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
drawRect.IntersectRect(drawRect, GetEffectiveVisibleRegion().GetBounds());
nsRefPtr<gfxASurface> surf = mCanvasSurface;
if (mDrawTarget) {
surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
}
mLayerProgram =
gl()->UploadSurfaceToTexture(mCanvasSurface,
gl()->UploadSurfaceToTexture(surf,
nsIntRect(0, 0, drawRect.width, drawRect.height),
mTexture,
true,

View File

@ -161,19 +161,16 @@ gfxAndroidPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
}
RefPtr<ScaledFont>
gfxAndroidPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
gfxAndroidPlatform::GetScaledFontForFont(gfxFont *aFont)
{
NativeFont nativeFont;
if (aTarget->GetType() == BACKEND_CAIRO) {
nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
nativeFont.mFont = NULL;
return Factory::CreateScaledFontWithCairo(nativeFont, aFont->GetAdjustedSize(), aFont->GetCairoScaledFont());
}
NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_FT2, "Expecting Freetype font");
NativeFont nativeFont;
nativeFont.mType = NATIVE_FONT_SKIA_FONT_FACE;
nativeFont.mFont = static_cast<gfxFT2FontBase*>(aFont)->GetFontOptions();
return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
RefPtr<ScaledFont> scaledFont =
Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
return scaledFont;
}
bool

View File

@ -33,10 +33,12 @@ public:
CreateOffscreenSurface(const gfxIntSize& size,
gfxASurface::gfxContentType contentType);
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend) { aBackend = mozilla::gfx::BACKEND_SKIA; return true; }
virtual gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
mozilla::RefPtr<mozilla::gfx::ScaledFont>
GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
GetScaledFontForFont(gfxFont *aFont);
// to support IPC font list (sharing between chrome and content)
void GetFontList(InfallibleTArray<FontListEntry>* retValue);

View File

@ -1783,7 +1783,7 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
} else {
RefPtr<ScaledFont> scaledFont =
gfxPlatform::GetPlatform()->GetScaledFontForFont(dt, this);
gfxPlatform::GetPlatform()->GetScaledFontForFont(this);
if (!scaledFont) {
return;

View File

@ -1547,8 +1547,7 @@ public:
FONT_TYPE_GDI,
FONT_TYPE_FT2,
FONT_TYPE_MAC,
FONT_TYPE_OS2,
FONT_TYPE_CAIRO
FONT_TYPE_OS2
} FontType;
virtual FontType GetType() const = 0;

View File

@ -48,7 +48,6 @@
#include "nsTArray.h"
#include "nsUnicharUtilCIID.h"
#include "nsILocaleService.h"
#include "nsReadableUtils.h"
#include "nsWeakReference.h"
@ -76,7 +75,6 @@ using namespace mozilla::layers;
gfxPlatform *gPlatform = nsnull;
static bool gEverInitialized = false;
static nsTArray<nsCString>* gBackendList = nsnull;
// These two may point to the same profile
static qcms_profile *gCMSOutputProfile = nsnull;
@ -213,7 +211,7 @@ static const char *gPrefLangNames[] = {
};
gfxPlatform::gfxPlatform()
: mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureCanvasBackendInfo)
: mAzureBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
{
mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
mAllowDownloadableFonts = UNINITIALIZED_VALUE;
@ -225,8 +223,11 @@ gfxPlatform::gfxPlatform()
#endif
mBidiNumeralOption = UNINITIALIZED_VALUE;
PRUint32 backendMask = (1 << BACKEND_CAIRO) | (1 << BACKEND_SKIA);
InitCanvasBackend(backendMask);
if (Preferences::GetBool("gfx.canvas.azure.prefer-skia", false)) {
mPreferredDrawTargetBackend = BACKEND_SKIA;
} else {
mPreferredDrawTargetBackend = BACKEND_NONE;
}
}
gfxPlatform*
@ -406,9 +407,6 @@ gfxPlatform::Shutdown()
CompositorParent::ShutDown();
delete gBackendList;
gBackendList = nsnull;
delete gPlatform;
gPlatform = nsnull;
}
@ -475,9 +473,9 @@ gfxPlatform::OptimizeImage(gfxImageSurface *aSurface,
cairo_user_data_key_t kDrawTarget;
RefPtr<DrawTarget>
gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface, const IntSize& aSize)
gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface)
{
RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(), aSize);
RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface());
aSurface->SetData(&kDrawTarget, drawTarget, NULL);
return drawTarget;
}
@ -534,8 +532,11 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
if (!srcBuffer) {
nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
bool isWin32ImageSurf = imgSurface &&
aSurface->GetType() == gfxASurface::SurfaceTypeWin32;
bool isWin32ImageSurf = false;
if (imgSurface && aSurface->GetType() != gfxASurface::SurfaceTypeWin32) {
isWin32ImageSurf = true;
}
if (!imgSurface) {
imgSurface = new gfxImageSurface(aSurface->GetSize(), OptimalFormatForContent(aSurface->GetContentType()));
@ -571,8 +572,8 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
if (!srcBuffer) {
// We need to check if our gfxASurface will keep the underlying data
// alive. This is true if gfxASurface actually -is- an ImageSurface or
// if it is a gfxWindowsSurface which supports GetAsImageSurface.
// alive! This is true if gfxASurface actually -is- an ImageSurface or
// if it is a gfxWindowsSurface which supportes GetAsImageSurface.
if (imgSurface != aSurface && !isWin32ImageSurf) {
// This shouldn't happen for now, it can be easily supported by making
// a copy. For now let's just abort.
@ -604,73 +605,77 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
}
RefPtr<ScaledFont>
gfxPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
gfxPlatform::GetScaledFontForFont(gfxFont *aFont)
{
NativeFont nativeFont;
nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
nativeFont.mFont = aFont->GetCairoScaledFont();
nativeFont.mFont = aFont;
RefPtr<ScaledFont> scaledFont =
Factory::CreateScaledFontForNativeFont(nativeFont,
aFont->GetAdjustedSize());
return scaledFont;
}
cairo_user_data_key_t kDrawSourceSurface;
static void
DataSourceSurfaceDestroy(void *dataSourceSurface)
UserDataKey kThebesSurfaceKey;
void
DestroyThebesSurface(void *data)
{
static_cast<DataSourceSurface*>(dataSourceSurface)->Release();
}
cairo_user_data_key_t kDrawTargetForSurface;
static void
DataDrawTargetDestroy(void *aTarget)
{
static_cast<DrawTarget*>(aTarget)->Release();
gfxASurface *surface = static_cast<gfxASurface*>(data);
surface->Release();
}
already_AddRefed<gfxASurface>
gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
{
// If we have already created a thebes surface, we can just return it.
void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
if (surface) {
nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
return surf.forget();
}
nsRefPtr<gfxASurface> surf;
if (aTarget->GetType() == BACKEND_CAIRO) {
cairo_surface_t* csurf =
static_cast<cairo_surface_t*>(aTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE));
return gfxASurface::Wrap(csurf);
surf = gfxASurface::Wrap(csurf);
} else {
// The semantics of this part of the function are sort of weird. If we
// don't have direct support for the backend, we snapshot the first time
// and then return the snapshotted surface for the lifetime of the draw
// target. Sometimes it seems like this works out, but it seems like it
// might result in no updates ever.
RefPtr<SourceSurface> source = aTarget->Snapshot();
RefPtr<DataSourceSurface> data = source->GetDataSurface();
if (!data) {
return NULL;
}
IntSize size = data->GetSize();
gfxASurface::gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat()));
// We need to make a copy here because data might change its data under us
nsRefPtr<gfxImageSurface> imageSurf = new gfxImageSurface(gfxIntSize(size.width, size.height), format, false);
bool resultOfCopy = imageSurf->CopyFrom(source);
NS_ASSERTION(resultOfCopy, "Failed to copy surface.");
surf = imageSurf;
}
// The semantics of this part of the function are sort of weird. If we
// don't have direct support for the backend, we snapshot the first time
// and then return the snapshotted surface for the lifetime of the draw
// target. Sometimes it seems like this works out, but it seems like it
// might result in no updates ever.
RefPtr<SourceSurface> source = aTarget->Snapshot();
RefPtr<DataSourceSurface> data = source->GetDataSurface();
if (!data) {
return NULL;
}
IntSize size = data->GetSize();
gfxASurface::gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat()));
nsRefPtr<gfxASurface> surf =
new gfxImageSurface(data->GetData(), gfxIntSize(size.width, size.height),
data->Stride(), format);
surf->SetData(&kDrawSourceSurface, data.forget().drop(), DataSourceSurfaceDestroy);
// keep the draw target alive as long as we need its data
aTarget->AddRef();
surf->SetData(&kDrawTargetForSurface, aTarget, DataDrawTargetDestroy);
// add a reference to be held by the drawTarget
// careful, the reference graph is getting complicated here
surf->AddRef();
aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
return surf.forget();
}
RefPtr<DrawTarget>
gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
gfxPlatform::CreateOffscreenDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
{
BackendType backend;
if (!SupportsAzureCanvas(backend)) {
if (!SupportsAzure(backend)) {
return NULL;
}
@ -682,70 +687,26 @@ gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSi
// now, but this might need to change in the future (using
// CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
// backends).
if (aBackend == BACKEND_CAIRO) {
if (backend == BACKEND_CAIRO) {
nsRefPtr<gfxASurface> surf = CreateOffscreenSurface(ThebesIntSize(aSize),
ContentForFormat(aFormat));
if (!surf) {
return NULL;
}
return CreateDrawTargetForSurface(surf, aSize);
return CreateDrawTargetForSurface(surf);
} else {
return Factory::CreateDrawTarget(aBackend, aSize, aFormat);
return Factory::CreateDrawTarget(backend, aSize, aFormat);
}
}
RefPtr<DrawTarget>
gfxPlatform::CreateOffscreenDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
{
BackendType backend;
if (!SupportsAzureCanvas(backend)) {
return NULL;
}
RefPtr<DrawTarget> target = CreateDrawTargetForBackend(backend, aSize, aFormat);
if (target ||
mFallbackCanvasBackend == BACKEND_NONE) {
return target;
}
return CreateDrawTargetForBackend(mFallbackCanvasBackend, aSize, aFormat);
}
RefPtr<DrawTarget>
gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat)
{
BackendType backend;
if (!SupportsAzureCanvas(backend)) {
if (!SupportsAzure(backend)) {
return NULL;
}
return Factory::CreateDrawTargetForData(backend, aData, aSize, aStride, aFormat);
}
bool
gfxPlatform::SupportsAzureCanvas(BackendType& aBackend)
{
NS_ASSERTION(mFallbackCanvasBackend == BACKEND_NONE || mPreferredCanvasBackend != BACKEND_NONE,
"fallback backend with no preferred backend");
aBackend = mPreferredCanvasBackend;
return mPreferredCanvasBackend != BACKEND_NONE;
}
/* static */ BackendType
gfxPlatform::BackendTypeForName(const nsCString& aName)
{
if (aName.EqualsLiteral("cairo"))
return BACKEND_CAIRO;
if (aName.EqualsLiteral("skia"))
return BACKEND_SKIA;
if (aName.EqualsLiteral("direct2d"))
return BACKEND_DIRECT2D;
if (aName.EqualsLiteral("cg"))
return BACKEND_COREGRAPHICS;
return BACKEND_NONE;
}
nsresult
gfxPlatform::GetFontList(nsIAtom *aLangGroup,
const nsACString& aGenericFamily,
@ -1166,53 +1127,20 @@ gfxPlatform::AppendPrefLang(eFontPrefLang aPrefLangs[], PRUint32& aLen, eFontPre
}
}
void
gfxPlatform::InitCanvasBackend(PRUint32 aBackendBitmask)
{
if (!Preferences::GetBool("gfx.canvas.azure.enabled", false)) {
mPreferredCanvasBackend = BACKEND_NONE;
mFallbackCanvasBackend = BACKEND_NONE;
return;
}
mPreferredCanvasBackend = GetCanvasBackendPref(aBackendBitmask);
mFallbackCanvasBackend = GetCanvasBackendPref(aBackendBitmask & ~(1 << mPreferredCanvasBackend));
}
/* static */ BackendType
gfxPlatform::GetCanvasBackendPref(PRUint32 aBackendBitmask)
{
if (!gBackendList) {
gBackendList = new nsTArray<nsCString>();
nsCString prefString;
if (NS_SUCCEEDED(Preferences::GetCString("gfx.canvas.azure.backends", &prefString))) {
ParseString(prefString, ',', *gBackendList);
}
}
for (PRUint32 i = 0; i < gBackendList->Length(); ++i) {
BackendType result = BackendTypeForName((*gBackendList)[i]);
if ((1 << result) & aBackendBitmask) {
return result;
}
}
return BACKEND_NONE;
}
bool
gfxPlatform::UseProgressiveTilePainting()
{
static bool sUseProgressiveTilePainting;
static bool sUseProgressiveTilePaintingPrefCached = false;
static bool sUseProgressiveTilePainting;
static bool sUseProgressiveTilePaintingPrefCached = false;
if (!sUseProgressiveTilePaintingPrefCached) {
sUseProgressiveTilePaintingPrefCached = true;
mozilla::Preferences::AddBoolVarCache(&sUseProgressiveTilePainting,
"layers.progressive-paint",
false);
}
if (!sUseProgressiveTilePaintingPrefCached) {
sUseProgressiveTilePaintingPrefCached = true;
mozilla::Preferences::AddBoolVarCache(&sUseProgressiveTilePainting,
"layers.progressive-paint",
false);
}
return sUseProgressiveTilePainting;
return sUseProgressiveTilePainting;
}
bool

View File

@ -38,6 +38,9 @@ class gfxTextRun;
class nsIURI;
class nsIAtom;
extern mozilla::gfx::UserDataKey kThebesSurfaceKey;
void DestroyThebesSurface(void *data);
extern cairo_user_data_key_t kDrawTarget;
// pref lang id's for font prefs
@ -127,7 +130,7 @@ GetBackendName(mozilla::gfx::BackendType aBackend)
case mozilla::gfx::BACKEND_NONE:
return "none";
}
MOZ_NOT_REACHED("Incomplete switch");
MOZ_NOT_REACHED("Incomplet switch");
}
class THEBES_API gfxPlatform {
@ -169,21 +172,18 @@ public:
gfxASurface::gfxImageFormat format);
virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
CreateDrawTargetForSurface(gfxASurface *aSurface, const mozilla::gfx::IntSize& aSize);
CreateDrawTargetForSurface(gfxASurface *aSurface);
/*
* Creates a SourceSurface for a gfxASurface. This function does no caching,
* so the caller should cache the gfxASurface if it will be used frequently.
* The returned surface keeps a reference to aTarget, so it is OK to keep the
* surface, even if aTarget changes.
* aTarget should not keep a reference to the returned surface because that
* will cause a cycle.
* Creates a SourceSurface for a gfxASurface. This surface should -not- be
* held around by the user after the underlying gfxASurface has been
* destroyed as a copy of the data is not guaranteed.
*/
virtual mozilla::RefPtr<mozilla::gfx::SourceSurface>
GetSourceSurfaceForSurface(mozilla::gfx::DrawTarget *aTarget, gfxASurface *aSurface);
virtual mozilla::RefPtr<mozilla::gfx::ScaledFont>
GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
GetScaledFontForFont(gfxFont *aFont);
virtual already_AddRefed<gfxASurface>
GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
@ -195,12 +195,13 @@ public:
CreateDrawTargetForData(unsigned char* aData, const mozilla::gfx::IntSize& aSize,
int32_t aStride, mozilla::gfx::SurfaceFormat aFormat);
// aBackend will be set to the preferred backend for Azure canvas
bool SupportsAzureCanvas(mozilla::gfx::BackendType& aBackend);
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend) { return false; }
// aObj will contain the preferred backend for Azure canvas
void GetAzureCanvasBackendInfo(mozilla::widget::InfoObject &aObj) {
aObj.DefineProperty("AzureBackend", GetBackendName(mPreferredCanvasBackend));
void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) {
mozilla::gfx::BackendType backend;
if (SupportsAzure(backend)) {
aObj.DefineProperty("AzureBackend", GetBackendName(backend));
}
}
/*
@ -454,30 +455,7 @@ protected:
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], PRUint32 &aLen,
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
/**
* Helper method, creates a draw target for a specific Azure backend.
* Used by CreateOffscreenDrawTarget.
*/
mozilla::RefPtr<mozilla::gfx::DrawTarget>
CreateDrawTargetForBackend(mozilla::gfx::BackendType aBackend,
const mozilla::gfx::IntSize& aSize,
mozilla::gfx::SurfaceFormat aFormat);
/**
* Initialise the preferred and fallback canvas backends
* aBackendBitmask specifies the backends which are acceptable to the caller.
* The backend used is determined by aBackendBitmask and the order specified
* by the gfx.canvas.azure.backends pref.
*/
void InitCanvasBackend(PRUint32 aBackendBitmask);
/**
* returns the first backend named in the pref gfx.canvas.azure.backends
* which is a component of aBackendBitmask, a bitmask of backend types
*/
static mozilla::gfx::BackendType GetCanvasBackendPref(PRUint32 aBackendBitmask);
static mozilla::gfx::BackendType BackendTypeForName(const nsCString& aName);
PRInt8 mAllowDownloadableFonts;
PRInt8 mDownloadableFontsSanitize;
#ifdef MOZ_GRAPHITE
@ -493,6 +471,9 @@ protected:
// which scripts should be shaped with harfbuzz
PRInt32 mUseHarfBuzzScripts;
// The preferred draw target backend to use
mozilla::gfx::BackendType mPreferredDrawTargetBackend;
private:
/**
* Start up Thebes.
@ -505,13 +486,7 @@ private:
nsTArray<PRUint32> mCJKPrefLangs;
nsCOMPtr<nsIObserver> mSRGBOverrideObserver;
nsCOMPtr<nsIObserver> mFontPrefsObserver;
// The preferred draw target backend to use for canvas
mozilla::gfx::BackendType mPreferredCanvasBackend;
// The fallback draw target backend to use for canvas, if the preferred backend fails
mozilla::gfx::BackendType mFallbackCanvasBackend;
mozilla::widget::GfxInfoCollector<gfxPlatform> mAzureCanvasBackendCollector;
mozilla::widget::GfxInfoCollector<gfxPlatform> mAzureBackendCollector;
bool mWorkAroundDriverBugs;
};

View File

@ -730,16 +730,22 @@ gfxPlatformGtk::GetGdkDrawable(gfxASurface *target)
#endif
RefPtr<ScaledFont>
gfxPlatformGtk::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
gfxPlatformGtk::GetScaledFontForFont(gfxFont *aFont)
{
NativeFont nativeFont;
if (aTarget->GetType() == BACKEND_CAIRO) {
nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
nativeFont.mFont = NULL;
return Factory::CreateScaledFontWithCairo(nativeFont, aFont->GetAdjustedSize(), aFont->GetCairoScaledFont());
}
NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_FT2, "Expecting Freetype font");
NativeFont nativeFont;
nativeFont.mType = NATIVE_FONT_SKIA_FONT_FACE;
nativeFont.mFont = static_cast<gfxFT2FontBase*>(aFont)->GetFontOptions();
return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
RefPtr<ScaledFont> scaledFont =
Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
return scaledFont;
}
bool
gfxPlatformGtk::SupportsAzure(BackendType& aBackend)
{
aBackend = BACKEND_SKIA;
return true;
}

View File

@ -36,7 +36,9 @@ public:
gfxASurface::gfxContentType contentType);
mozilla::RefPtr<mozilla::gfx::ScaledFont>
GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
GetScaledFontForFont(gfxFont *aFont);
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
nsresult GetFontList(nsIAtom *aLangGroup,
const nsACString& aGenericFamily,

View File

@ -69,9 +69,6 @@ gfxPlatformMac::gfxPlatformMac()
DisableFontActivation();
}
mFontAntiAliasingThreshold = ReadAntiAliasingThreshold();
PRUint32 backendMask = (1 << BACKEND_CAIRO) | (1 << BACKEND_SKIA) | (1 << BACKEND_COREGRAPHICS);
InitCanvasBackend(backendMask);
}
gfxPlatformMac::~gfxPlatformMac()
@ -136,12 +133,24 @@ gfxPlatformMac::OptimizeImage(gfxImageSurface *aSurface,
}
RefPtr<ScaledFont>
gfxPlatformMac::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
gfxPlatformMac::GetScaledFontForFont(gfxFont *aFont)
{
gfxMacFont *font = static_cast<gfxMacFont*>(aFont);
return font->GetScaledFont();
}
bool
gfxPlatformMac::SupportsAzure(BackendType& aBackend)
{
if (mPreferredDrawTargetBackend != BACKEND_NONE) {
aBackend = mPreferredDrawTargetBackend;
} else {
aBackend = BACKEND_COREGRAPHICS;
}
return true;
}
nsresult
gfxPlatformMac::ResolveFontName(const nsAString& aFontName,
FontResolverCallback aCallback,
@ -380,16 +389,26 @@ already_AddRefed<gfxASurface>
gfxPlatformMac::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
{
if (aTarget->GetType() == BACKEND_COREGRAPHICS) {
CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
if (surface) {
nsRefPtr<gfxASurface> surf = static_cast<gfxQuartzSurface*>(surface);
return surf.forget();
} else {
CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
//XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize
IntSize intSize = aTarget->GetSize();
gfxIntSize size(intSize.width, intSize.height);
//XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize
IntSize intSize = aTarget->GetSize();
gfxIntSize size(intSize.width, intSize.height);
nsRefPtr<gfxASurface> surf =
new gfxQuartzSurface(cg, size);
nsRefPtr<gfxASurface> surf =
new gfxQuartzSurface(cg, size);
return surf.forget();
// add a reference to be held by the drawTarget
surf->AddRef();
aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
return surf.forget();
}
}
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);

View File

@ -39,7 +39,9 @@ public:
gfxASurface::gfxImageFormat format);
mozilla::RefPtr<mozilla::gfx::ScaledFont>
GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
GetScaledFontForFont(gfxFont *aFont);
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
nsresult ResolveFontName(const nsAString& aFontName,
FontResolverCallback aCallback,

View File

@ -606,3 +606,10 @@ gfxQtPlatform::GetOffscreenFormat()
return sOffscreenFormat;
}
bool
gfxQtPlatform::SupportsAzure(BackendType& aBackend)
{
aBackend = BACKEND_SKIA;
return true;
}

View File

@ -47,6 +47,8 @@ public:
already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
gfxASurface::gfxContentType contentType);
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
nsresult GetFontList(nsIAtom *aLangGroup,
const nsACString& aGenericFamily,
nsTArray<nsString>& aListOfFonts);

View File

@ -515,14 +515,6 @@ gfxWindowsPlatform::UpdateRenderMode()
}
}
#endif
PRUint32 backendMask = 1 << BACKEND_CAIRO;
if (mRenderMode == RENDER_DIRECT2D) {
backendMask |= 1 << BACKEND_DIRECT2D;
} else {
backendMask |= 1 << BACKEND_SKIA;
}
InitCanvasBackend(backendMask);
}
void
@ -772,7 +764,7 @@ gfxWindowsPlatform::CreateOffscreenImageSurface(const gfxIntSize& aSize,
}
RefPtr<ScaledFont>
gfxWindowsPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
gfxWindowsPlatform::GetScaledFontForFont(gfxFont *aFont)
{
if (aFont->GetType() == gfxFont::FONT_TYPE_DWRITE) {
gfxDWriteFont *font = static_cast<gfxDWriteFont*>(aFont);
@ -794,14 +786,10 @@ gfxWindowsPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
LOGFONT lf;
GetObject(static_cast<gfxGDIFont*>(aFont)->GetHFONT(), sizeof(LOGFONT), &lf);
nativeFont.mFont = &lf;
RefPtr<ScaledFont> scaledFont =
Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
if (aTarget->GetType() == BACKEND_CAIRO) {
return Factory::CreateScaledFontWithCairo(nativeFont,
aFont->GetAdjustedSize(),
aFont->GetCairoScaledFont());
}
return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
return scaledFont;
}
already_AddRefed<gfxASurface>
@ -809,32 +797,64 @@ gfxWindowsPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
{
#ifdef XP_WIN
if (aTarget->GetType() == BACKEND_DIRECT2D) {
if (!GetD2DDevice()) {
// We no longer have a D2D device, can't do this.
return NULL;
void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
if (surface) {
nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
return surf.forget();
} else {
if (!GetD2DDevice()) {
// We no longer have a D2D device, can't do this.
return NULL;
}
RefPtr<ID3D10Texture2D> texture =
static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
if (!texture) {
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
}
aTarget->Flush();
nsRefPtr<gfxASurface> surf =
new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat()));
// add a reference to be held by the drawTarget
surf->AddRef();
aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
/* "It might be worth it to clear cairo surfaces associated with a drawtarget.
The strong reference means for example for D2D that cairo's scratch surface
will be kept alive (well after a user being done) and consume extra VRAM.
We can deal with this in a follow-up though." */
// shouldn't this hold a reference?
surf->SetData(&kDrawTarget, aTarget, NULL);
return surf.forget();
}
RefPtr<ID3D10Texture2D> texture =
static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
if (!texture) {
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
}
aTarget->Flush();
nsRefPtr<gfxASurface> surf =
new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat()));
// shouldn't this hold a reference?
surf->SetData(&kDrawTarget, aTarget, NULL);
return surf.forget();
}
#endif
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
}
bool
gfxWindowsPlatform::SupportsAzure(BackendType& aBackend)
{
#ifdef CAIRO_HAS_D2D_SURFACE
if (mRenderMode == RENDER_DIRECT2D) {
aBackend = BACKEND_DIRECT2D;
return true;
}
#endif
if (mPreferredDrawTargetBackend != BACKEND_NONE) {
aBackend = mPreferredDrawTargetBackend;
return true;
}
return false;
}
nsresult
gfxWindowsPlatform::GetFontList(nsIAtom *aLangGroup,
const nsACString& aGenericFamily,

View File

@ -108,9 +108,11 @@ public:
gfxASurface::gfxContentType aContentType);
virtual mozilla::RefPtr<mozilla::gfx::ScaledFont>
GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
GetScaledFontForFont(gfxFont *aFont);
virtual already_AddRefed<gfxASurface>
GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
enum RenderMode {
/* Use GDI and windows surfaces */

View File

@ -225,17 +225,10 @@ pref("gfx.font_rendering.directwrite.use_gdi_table_loading", true);
#ifdef XP_WIN
pref("gfx.canvas.azure.enabled", true);
// comma separated list of backends to use in order of preference
// e.g., pref("gfx.canvas.azure.backends", "direct2d,skia,cairo");
pref("gfx.canvas.azure.backends", "direct2d");
pref("gfx.content.azure.enabled", true);
#else
#ifdef XP_MACOSX
pref("gfx.canvas.azure.enabled", true);
pref("gfx.canvas.azure.backends", "cg");
#else
pref("gfx.canvas.azure.enabled", false);
pref("gfx.canvas.azure.backends", "cairo,skia");
#endif
#endif

View File

@ -43,6 +43,12 @@ GfxInfo::GetDWriteEnabled(bool *aEnabled)
return NS_ERROR_FAILURE;
}
nsresult
GfxInfo::GetAzureEnabled(bool *aEnabled)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString DWriteVersion; */
NS_IMETHODIMP
GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)

View File

@ -25,6 +25,7 @@ public:
// rest is brought forward from GfxInfoBase.
NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);

View File

@ -24,6 +24,7 @@ public:
// rest is brought forward from GfxInfoBase.
NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);

View File

@ -154,6 +154,20 @@ GfxInfo::GetD2DEnabled(bool *aEnabled)
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetAzureEnabled(bool *aEnabled)
{
bool azure = false;
nsresult rv = mozilla::Preferences::GetBool("gfx.canvas.azure.enabled", &azure);
if (NS_SUCCEEDED(rv) && azure) {
*aEnabled = true;
} else {
*aEnabled = false;
}
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDWriteEnabled(bool *aEnabled)
{

View File

@ -16,6 +16,7 @@ interface nsIGfxInfo : nsISupports
*/
readonly attribute boolean D2DEnabled;
readonly attribute boolean DWriteEnabled;
readonly attribute boolean AzureEnabled;
readonly attribute DOMString DWriteVersion;
readonly attribute DOMString cleartypeParameters;

View File

@ -59,6 +59,26 @@ GfxInfo::GetDWriteEnabled(bool *aEnabled)
return NS_OK;
}
nsresult
GfxInfo::GetAzureEnabled(bool *aEnabled)
{
*aEnabled = false;
bool d2dEnabled =
gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D;
if (d2dEnabled) {
bool azure = false;
nsresult rv = mozilla::Preferences::GetBool("gfx.canvas.azure.enabled", &azure);
if (NS_SUCCEEDED(rv) && azure) {
*aEnabled = true;
}
}
return NS_OK;
}
/* readonly attribute DOMString DWriteVersion; */
NS_IMETHODIMP
GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)

View File

@ -22,6 +22,7 @@ public:
// rest is brought forward from GfxInfoBase.
NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);

View File

@ -61,7 +61,7 @@ GetRenderingContext(nsIDocShell *shell, gfxASurface *surface,
if (!ctx) {
// create the canvas rendering context
ctx = do_CreateInstance("@mozilla.org/content/canvas-rendering-context;1?id=2d", &rv);
ctx = do_CreateInstance("@mozilla.org/content/2dthebes-canvas-rendering-context;1", &rv);
if (NS_FAILED(rv)) {
NS_WARNING("Could not create nsICanvasRenderingContext2D for tab previews!");
return rv;

View File

@ -370,6 +370,12 @@ GfxInfo::GetDWriteEnabled(bool *aEnabled)
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetAzureEnabled(bool *aEnabled)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString DWriteVersion; */
NS_IMETHODIMP
GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)

View File

@ -21,6 +21,7 @@ public:
// rest is brought forward from GfxInfoBase.
NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);