merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-07-07 14:18:45 +02:00
Родитель a7777778f7 281199134a
Коммит 2d8d746257
102 изменённых файлов: 1078 добавлений и 699 удалений

Просмотреть файл

@ -16,7 +16,6 @@ class nsMacShellService : public nsIMacShellService,
{
public:
nsMacShellService() : mCheckedThisSession(false) {};
virtual ~nsMacShellService() {};
NS_DECL_ISUPPORTS
NS_DECL_NSISHELLSERVICE
@ -24,6 +23,7 @@ public:
NS_DECL_NSIWEBPROGRESSLISTENER
protected:
virtual ~nsMacShellService() {};
private:
nsCOMPtr<nsIFile> mBackgroundFile;

Просмотреть файл

@ -43,10 +43,6 @@ public:
SetIsDOMBinding();
}
~DOMMatrixReadOnly()
{
}
#define GetMatrixMember(entry2D, entry3D, default) \
{ \
if (mMatrix3D) { \
@ -135,6 +131,10 @@ protected:
nsCOMPtr<nsISupports> mParent;
nsAutoPtr<gfx::Matrix> mMatrix2D;
nsAutoPtr<gfx::Matrix4x4> mMatrix3D;
~DOMMatrixReadOnly()
{
}
private:
DOMMatrixReadOnly() MOZ_DELETE;
DOMMatrixReadOnly(const DOMMatrixReadOnly&) MOZ_DELETE;
@ -248,6 +248,8 @@ public:
DOMMatrix* SetMatrixValue(const nsAString& aTransformList, ErrorResult& aRv);
private:
void Ensure3DMatrix();
~DOMMatrix() {}
};
}

Просмотреть файл

@ -1385,7 +1385,6 @@ public:
NS_DECL_NSIDOMEVENTLISTENER
WebGLObserver(WebGLContext* aContext);
~WebGLObserver();
void Destroy();
@ -1396,6 +1395,8 @@ public:
void UnregisterMemoryPressureEvent();
private:
~WebGLObserver();
WebGLContext* mContext;
};

Просмотреть файл

@ -94,7 +94,7 @@ SVGCircleElement::ConstructPath(gfxContext *aCtx)
}
TemporaryRef<Path>
SVGCircleElement::BuildPath()
SVGCircleElement::BuildPath(PathBuilder* aBuilder)
{
float x, y, r;
GetAnimatedLengthValues(&x, &y, &r, nullptr);
@ -103,7 +103,7 @@ SVGCircleElement::BuildPath()
return nullptr;
}
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
RefPtr<PathBuilder> pathBuilder = aBuilder ? aBuilder : CreatePathBuilder();
pathBuilder->Arc(Point(x, y), r, 0, Float(2*M_PI));

Просмотреть файл

@ -31,7 +31,7 @@ public:
// nsSVGPathGeometryElement methods:
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath() MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;

Просмотреть файл

@ -8,8 +8,13 @@
#include "SVGContentUtils.h"
// Keep others in (case-insensitive) order:
#include "gfx2DGlue.h"
#include "gfxMatrix.h"
#include "gfxPlatform.h"
#include "gfxSVGGlyphs.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/dom/SVGSVGElement.h"
#include "mozilla/RefPtr.h"
#include "nsComputedDOMStyle.h"
#include "nsFontMetrics.h"
#include "nsIFrame.h"
@ -20,12 +25,14 @@
#include "nsContentUtils.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Types.h"
#include "gfx2DGlue.h"
#include "nsStyleContext.h"
#include "nsSVGPathDataParser.h"
#include "SVGPathData.h"
#include "SVGPathElement.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::gfx;
SVGSVGElement*
SVGContentUtils::GetOuterSVGElement(nsSVGElement *aSVGElement)
@ -54,6 +61,179 @@ SVGContentUtils::ActivateByHyperlink(nsIContent *aContent)
static_cast<SVGAnimationElement*>(aContent)->ActivateByHyperlink();
}
enum DashState {
eDashedStroke,
eContinuousStroke, //< all dashes, no gaps
eNoStroke //< all gaps, no dashes
};
static DashState
GetStrokeDashData(SVGContentUtils::AutoStrokeOptions* aStrokeOptions,
nsSVGElement* aElement,
const nsStyleSVG* aStyleSVG,
gfxTextContextPaint *aContextPaint)
{
size_t dashArrayLength;
Float totalLengthOfDashes = 0.0, totalLengthOfGaps = 0.0;
if (aContextPaint && aStyleSVG->mStrokeDasharrayFromObject) {
const FallibleTArray<gfxFloat>& dashSrc = aContextPaint->GetStrokeDashArray();
dashArrayLength = dashSrc.Length();
if (dashArrayLength <= 0) {
return eContinuousStroke;
}
Float* dashPattern = aStrokeOptions->InitDashPattern(dashArrayLength);
if (!dashPattern) {
return eContinuousStroke;
}
for (size_t i = 0; i < dashArrayLength; i++) {
if (dashSrc[i] < 0.0) {
return eContinuousStroke; // invalid
}
dashPattern[i] = Float(dashSrc[i]);
(i % 2 ? totalLengthOfGaps : totalLengthOfDashes) += dashSrc[i];
}
} else {
const nsStyleCoord *dasharray = aStyleSVG->mStrokeDasharray;
dashArrayLength = aStyleSVG->mStrokeDasharrayLength;
if (dashArrayLength <= 0) {
return eContinuousStroke;
}
Float pathScale = 1.0;
if (aElement->Tag() == nsGkAtoms::path) {
pathScale = static_cast<SVGPathElement*>(aElement)->
GetPathLengthScale(SVGPathElement::eForStroking);
if (pathScale <= 0) {
return eContinuousStroke;
}
}
Float* dashPattern = aStrokeOptions->InitDashPattern(dashArrayLength);
if (!dashPattern) {
return eContinuousStroke;
}
for (uint32_t i = 0; i < dashArrayLength; i++) {
Float dashLength =
SVGContentUtils::CoordToFloat(aElement, dasharray[i]) * pathScale;
if (dashLength < 0.0) {
return eContinuousStroke; // invalid
}
dashPattern[i] = dashLength;
(i % 2 ? totalLengthOfGaps : totalLengthOfDashes) += dashLength;
}
}
// Now that aStrokeOptions.mDashPattern is fully initialized we can safely
// set mDashLength:
aStrokeOptions->mDashLength = dashArrayLength;
if (totalLengthOfDashes <= 0 || totalLengthOfGaps <= 0) {
if (totalLengthOfGaps > 0 && totalLengthOfDashes <= 0) {
return eNoStroke;
}
return eContinuousStroke;
}
if (aContextPaint && aStyleSVG->mStrokeDashoffsetFromObject) {
aStrokeOptions->mDashOffset = Float(aContextPaint->GetStrokeDashOffset());
} else {
aStrokeOptions->mDashOffset =
SVGContentUtils::CoordToFloat(aElement, aStyleSVG->mStrokeDashoffset);
}
return eDashedStroke;
}
void
SVGContentUtils::GetStrokeOptions(AutoStrokeOptions* aStrokeOptions,
nsSVGElement* aElement,
nsStyleContext* aStyleContext,
gfxTextContextPaint *aContextPaint)
{
nsRefPtr<nsStyleContext> styleContext;
if (aStyleContext) {
styleContext = aStyleContext;
} else {
styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement, nullptr,
nullptr);
}
if (!styleContext) {
return;
}
const nsStyleSVG* styleSVG = styleContext->StyleSVG();
DashState dashState =
GetStrokeDashData(aStrokeOptions, aElement, styleSVG, aContextPaint);
if (dashState == eNoStroke) {
// Hopefully this will shortcircuit any stroke operations:
aStrokeOptions->mLineWidth = 0;
return;
}
if (dashState == eContinuousStroke) {
// Prevent our caller from wasting time looking at the dash array:
aStrokeOptions->mDashLength = 0;
}
aStrokeOptions->mLineWidth =
GetStrokeWidth(aElement, styleContext, aContextPaint);
aStrokeOptions->mMiterLimit = Float(styleSVG->mStrokeMiterlimit);
switch (styleSVG->mStrokeLinejoin) {
case NS_STYLE_STROKE_LINEJOIN_MITER:
aStrokeOptions->mLineJoin = JoinStyle::MITER;
break;
case NS_STYLE_STROKE_LINEJOIN_ROUND:
aStrokeOptions->mLineJoin = JoinStyle::ROUND;
break;
case NS_STYLE_STROKE_LINEJOIN_BEVEL:
aStrokeOptions->mLineJoin = JoinStyle::BEVEL;
break;
}
switch (styleSVG->mStrokeLinecap) {
case NS_STYLE_STROKE_LINECAP_BUTT:
aStrokeOptions->mLineCap = CapStyle::BUTT;
break;
case NS_STYLE_STROKE_LINECAP_ROUND:
aStrokeOptions->mLineCap = CapStyle::ROUND;
break;
case NS_STYLE_STROKE_LINECAP_SQUARE:
aStrokeOptions->mLineCap = CapStyle::SQUARE;
break;
}
}
Float
SVGContentUtils::GetStrokeWidth(nsSVGElement* aElement,
nsStyleContext* aStyleContext,
gfxTextContextPaint *aContextPaint)
{
nsRefPtr<nsStyleContext> styleContext;
if (aStyleContext) {
styleContext = aStyleContext;
} else {
styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement, nullptr,
nullptr);
}
if (!styleContext) {
return 0.0f;
}
const nsStyleSVG* styleSVG = styleContext->StyleSVG();
if (aContextPaint && styleSVG->mStrokeWidthFromObject) {
return aContextPaint->GetStrokeWidth();
}
return SVGContentUtils::CoordToFloat(aElement, styleSVG->mStrokeWidth);
}
float
SVGContentUtils::GetFontSize(Element *aElement)
{
@ -596,5 +776,10 @@ SVGContentUtils::GetPath(const nsAString& aPathString)
return NULL;
}
return pathData.BuildPath(mozilla::gfx::FillRule::FILL_WINDING, NS_STYLE_STROKE_LINECAP_BUTT, 1);
RefPtr<DrawTarget> drawTarget =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
RefPtr<PathBuilder> builder =
drawTarget->CreatePathBuilder(FillRule::FILL_WINDING);
return pathData.BuildPath(builder, NS_STYLE_STROKE_LINECAP_BUTT, 1);
}

Просмотреть файл

@ -10,12 +10,15 @@
#define _USE_MATH_DEFINES
#include <math.h>
#include "mozilla/fallible.h"
#include "mozilla/gfx/2D.h" // for StrokeOptions
#include "mozilla/gfx/Matrix.h"
#include "mozilla/RangedPtr.h"
#include "nsError.h"
#include "nsStringFwd.h"
#include "gfx2DGlue.h"
class gfxTextContextPaint;
class nsIContent;
class nsIDocument;
class nsIFrame;
@ -58,6 +61,8 @@ IsSVGWhitespace(char16_t aChar)
class SVGContentUtils
{
public:
typedef mozilla::gfx::Float Float;
typedef mozilla::gfx::StrokeOptions StrokeOptions;
typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
typedef mozilla::SVGPreserveAspectRatio SVGPreserveAspectRatio;
@ -76,6 +81,64 @@ public:
*/
static void ActivateByHyperlink(nsIContent *aContent);
/**
* Moz2D's StrokeOptions requires someone else to own its mDashPattern
* buffer, which is a pain when you want to initialize a StrokeOptions object
* in a helper function and pass it out. This sub-class owns the mDashPattern
* buffer so that consumers of such a helper function don't need to worry
* about creating it, passing it in, or deleting it. (An added benefit is
* that in the typical case when stroke-dasharray is short it will avoid
* allocating.)
*/
struct AutoStrokeOptions : public StrokeOptions {
AutoStrokeOptions()
{
MOZ_ASSERT(mDashLength == 0, "InitDashPattern() depends on this");
}
~AutoStrokeOptions() {
if (mDashPattern && mDashPattern != mSmallArray) {
delete [] mDashPattern;
}
}
/**
* Creates the buffer to store the stroke-dasharray, assuming out-of-memory
* does not occur. The buffer's address is assigned to mDashPattern and
* returned to the caller as a non-const pointer (so that the caller can
* initialize the values in the buffer, since mDashPattern is const).
*/
Float* InitDashPattern(size_t aDashCount) {
if (aDashCount <= MOZ_ARRAY_LENGTH(mSmallArray)) {
mDashPattern = mSmallArray;
return mSmallArray;
}
static const mozilla::fallible_t fallible = mozilla::fallible_t();
Float* nonConstArray = new (fallible) Float[aDashCount];
mDashPattern = nonConstArray;
return nonConstArray;
}
private:
// Most dasharrays will fit in this and save us allocating
Float mSmallArray[16];
};
static void GetStrokeOptions(AutoStrokeOptions* aStrokeOptions,
nsSVGElement* aElement,
nsStyleContext* aStyleContext,
gfxTextContextPaint *aContextPaint);
/**
* Returns the current computed value of the CSS property 'stroke-width' for
* the given element. aStyleContext may be provided as an optimization.
* aContextPaint is also optional.
*
* Note that this function does NOT take account of the value of the 'stroke'
* and 'stroke-opacity' properties to, say, return zero if they are "none" or
* "0", respectively.
*/
static Float GetStrokeWidth(nsSVGElement* aElement,
nsStyleContext* aStyleContext,
gfxTextContextPaint *aContextPaint);
/*
* Get the number of CSS px (user units) per em (i.e. the em-height in user
* units) for an nsIContent

Просмотреть файл

@ -7,6 +7,7 @@
#include "mozilla/dom/SVGEllipseElementBinding.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/RefPtr.h"
#include "gfxContext.h"
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Ellipse)
@ -96,7 +97,12 @@ void
SVGEllipseElement::ConstructPath(gfxContext *aCtx)
{
if (!aCtx->IsCairo()) {
RefPtr<Path> path = BuildPath();
RefPtr<DrawTarget> dt = aCtx->GetDrawTarget();
FillRule fillRule =
aCtx->CurrentFillRule() == gfxContext::FILL_RULE_WINDING ?
FillRule::FILL_WINDING : FillRule::FILL_EVEN_ODD;
RefPtr<PathBuilder> builder = dt->CreatePathBuilder(fillRule);
RefPtr<Path> path = BuildPath(builder);
if (path) {
nsRefPtr<gfxPath> gfxpath = new gfxPath(path);
aCtx->SetPath(gfxpath);
@ -114,7 +120,7 @@ SVGEllipseElement::ConstructPath(gfxContext *aCtx)
}
TemporaryRef<Path>
SVGEllipseElement::BuildPath()
SVGEllipseElement::BuildPath(PathBuilder* aBuilder)
{
float x, y, rx, ry;
GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
@ -123,7 +129,7 @@ SVGEllipseElement::BuildPath()
return nullptr;
}
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
RefPtr<PathBuilder> pathBuilder = aBuilder ? aBuilder : CreatePathBuilder();
EllipseToBezier(pathBuilder.get(), Point(x, y), Size(rx, ry));

Просмотреть файл

@ -31,7 +31,7 @@ public:
// nsSVGPathGeometryElement methods:
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath() MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;

Просмотреть файл

@ -241,7 +241,7 @@ SVGImageElement::ConstructPath(gfxContext *aCtx)
}
TemporaryRef<Path>
SVGImageElement::BuildPath()
SVGImageElement::BuildPath(PathBuilder* aBuilder)
{
// We get called in order to get bounds for this element, and for
// hit-testing against it. For that we just pretend to be a rectangle.
@ -253,7 +253,7 @@ SVGImageElement::BuildPath()
return nullptr;
}
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
RefPtr<PathBuilder> pathBuilder = aBuilder ? aBuilder : CreatePathBuilder();
Rect r(x, y, width, height);
pathBuilder->MoveTo(r.TopLeft());

Просмотреть файл

@ -54,7 +54,7 @@ public:
// nsSVGPathGeometryElement methods:
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath() MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
// nsSVGSVGElement methods:
virtual bool HasValidDimensions() const MOZ_OVERRIDE;

Просмотреть файл

@ -119,9 +119,9 @@ SVGLineElement::ConstructPath(gfxContext *aCtx)
}
TemporaryRef<Path>
SVGLineElement::BuildPath()
SVGLineElement::BuildPath(PathBuilder* aBuilder)
{
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
RefPtr<PathBuilder> pathBuilder = aBuilder ? aBuilder : CreatePathBuilder();
float x1, y1, x2, y2;
GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);

Просмотреть файл

@ -33,7 +33,7 @@ public:
virtual bool IsMarkable() MOZ_OVERRIDE { return true; }
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE;
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath() MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const;

Просмотреть файл

@ -302,7 +302,7 @@ ApproximateZeroLengthSubpathSquareCaps(const gfxPoint &aPoint, gfxContext *aCtx)
} while(0)
TemporaryRef<Path>
SVGPathData::BuildPath(FillRule aFillRule,
SVGPathData::BuildPath(PathBuilder* builder,
uint8_t aStrokeLineCap,
Float aStrokeWidth) const
{
@ -310,14 +310,6 @@ SVGPathData::BuildPath(FillRule aFillRule,
return nullptr; // paths without an initial moveto are invalid
}
RefPtr<DrawTarget> drawTarget =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
NS_ASSERTION(gfxPlatform::GetPlatform()->
SupportsAzureContentForDrawTarget(drawTarget),
"Should support Moz2D content drawing");
RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder(aFillRule);
bool capsAreSquare = aStrokeLineCap == NS_STYLE_STROKE_LINECAP_SQUARE;
bool subpathHasLength = false; // visual length
bool subpathContainsNonArc = false;
@ -814,15 +806,19 @@ TemporaryRef<Path>
SVGPathData::ToPathForLengthOrPositionMeasuring() const
{
// Since the path that we return will not be used for painting it doesn't
// matter what we pass to BuildPath as aFillRule. Hawever, we do want to
// pass something other than NS_STYLE_STROKE_LINECAP_SQUARE as aStrokeLineCap
// to avoid the insertion of extra little lines (by
// matter what we pass to CreatePathBuilder as aFillRule. Hawever, we do want
// to pass something other than NS_STYLE_STROKE_LINECAP_SQUARE as
// aStrokeLineCap to avoid the insertion of extra little lines (by
// ApproximateZeroLengthSubpathSquareCaps), in which case the value that we
// pass as aStrokeWidth doesn't matter (since it's only used to determine the
// length of those extra little lines).
if (!mCachedPath) {
mCachedPath = BuildPath(FillRule::FILL_WINDING, NS_STYLE_STROKE_LINECAP_BUTT, 0);
RefPtr<DrawTarget> drawTarget =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
RefPtr<PathBuilder> builder =
drawTarget->CreatePathBuilder(FillRule::FILL_WINDING);
mCachedPath = BuildPath(builder, NS_STYLE_STROKE_LINECAP_BUTT, 0);
}
return mCachedPath;

Просмотреть файл

@ -84,6 +84,7 @@ class SVGPathData
typedef gfx::DrawTarget DrawTarget;
typedef gfx::Path Path;
typedef gfx::PathBuilder PathBuilder;
typedef gfx::FillRule FillRule;
typedef gfx::Float Float;
typedef gfx::CapStyle CapStyle;
@ -166,7 +167,7 @@ public:
TemporaryRef<Path> ToPathForLengthOrPositionMeasuring() const;
void ConstructPath(gfxContext *aCtx) const;
TemporaryRef<Path> BuildPath(FillRule aFillRule,
TemporaryRef<Path> BuildPath(PathBuilder* aBuilder,
uint8_t aCapStyle,
Float aStrokeWidth) const;

Просмотреть файл

@ -11,8 +11,10 @@
#include "DOMSVGPathSegList.h"
#include "DOMSVGPoint.h"
#include "gfx2DGlue.h"
#include "gfxPlatform.h"
#include "mozilla/dom/SVGPathElementBinding.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
#include "nsCOMPtr.h"
#include "nsComputedDOMStyle.h"
#include "nsGkAtoms.h"
@ -370,7 +372,7 @@ SVGPathElement::GetPathLengthScale(PathLengthScaleForType aFor)
}
TemporaryRef<Path>
SVGPathElement::BuildPath()
SVGPathElement::BuildPath(PathBuilder* aBuilder)
{
// The Moz2D PathBuilder that our SVGPathData will be using only cares about
// the fill rule. However, in order to fulfill the requirements of the SVG
@ -392,19 +394,28 @@ SVGPathElement::BuildPath()
// opacity here.
if (style->mStrokeLinecap == NS_STYLE_STROKE_LINECAP_SQUARE) {
strokeLineCap = style->mStrokeLinecap;
strokeWidth = GetStrokeWidth();
strokeWidth = SVGContentUtils::GetStrokeWidth(this, styleContext, nullptr);
}
}
// The fill rule that we pass must be the current
// computed value of our CSS 'fill-rule' property if the path that we return
// will be used for painting or hit-testing. For all other uses (bounds
// calculatons, length measurement, position-at-offset calculations) the fill
// rule that we pass doesn't matter. As a result we can just pass the current
// computed value regardless of who's calling us, or what they're going to do
// with the path that we return.
RefPtr<PathBuilder> builder;
if (aBuilder) {
builder = aBuilder;
} else {
RefPtr<DrawTarget> drawTarget =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
// The fill rule that we pass must be the current computed value of our
// CSS 'fill-rule' property if the path that we return will be used for
// painting or hit-testing. For all other uses (bounds calculatons, length
// measurement, position-at-offset calculations) the fill rule that we pass
// doesn't matter. As a result we can just pass the current computed value
// regardless of who's calling us, or what they're going to do with the
// path that we return.
RefPtr<PathBuilder> builder =
drawTarget->CreatePathBuilder(GetFillRule());
}
return mD.GetAnimValue().BuildPath(GetFillRule(), strokeLineCap, strokeWidth);
return mD.GetAnimValue().BuildPath(builder, strokeLineCap, strokeWidth);
}
} // namespace dom

Просмотреть файл

@ -53,7 +53,7 @@ public:
virtual bool IsMarkable() MOZ_OVERRIDE;
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE;
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath() MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
/**
* This returns a path without the extra little line segments that

Просмотреть файл

@ -153,7 +153,7 @@ SVGRectElement::ConstructPath(gfxContext *aCtx)
}
TemporaryRef<Path>
SVGRectElement::BuildPath()
SVGRectElement::BuildPath(PathBuilder* aBuilder)
{
float x, y, width, height, rx, ry;
GetAnimatedLengthValues(&x, &y, &width, &height, &rx, &ry, nullptr);
@ -162,7 +162,7 @@ SVGRectElement::BuildPath()
return nullptr;
}
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
RefPtr<PathBuilder> pathBuilder = aBuilder ? aBuilder : CreatePathBuilder();
rx = std::max(rx, 0.0f);
ry = std::max(ry, 0.0f);

Просмотреть файл

@ -31,7 +31,7 @@ public:
// nsSVGPathGeometryElement methods:
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath() MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;

Просмотреть файл

@ -111,15 +111,3 @@ nsSVGPathGeometryElement::GetFillRule()
return fillRule;
}
Float
nsSVGPathGeometryElement::GetStrokeWidth()
{
nsRefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(this, nullptr,
nullptr);
return styleContext ?
SVGContentUtils::CoordToFloat(this,
styleContext->StyleSVG()->mStrokeWidth) :
0.0f;
}

Просмотреть файл

@ -62,7 +62,7 @@ public:
* Returns a Path that can be used to paint, hit-test or calculate bounds for
* this element. May return nullptr if there is no [valid] path.
*/
virtual mozilla::TemporaryRef<Path> BuildPath() = 0;
virtual mozilla::TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) = 0;
virtual mozilla::TemporaryRef<Path> GetPathForLengthOrPositionMeasuring();
@ -77,14 +77,6 @@ public:
* this element.
*/
FillRule GetFillRule();
/**
* Returns the current computed value of the CSS property 'stroke-width' for
* this element. (I.e. this does NOT take account of the value of the
* 'stroke' and 'stroke-opacity' properties to, say, return zero if they are
* "none" or "0", respectively.)
*/
Float GetStrokeWidth();
};
#endif

Просмотреть файл

@ -132,7 +132,7 @@ nsSVGPolyElement::ConstructPath(gfxContext *aCtx)
}
TemporaryRef<Path>
nsSVGPolyElement::BuildPath()
nsSVGPolyElement::BuildPath(PathBuilder* aBuilder)
{
const SVGPointList &points = mPoints.GetAnimValue();
@ -140,7 +140,7 @@ nsSVGPolyElement::BuildPath()
return nullptr;
}
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
RefPtr<PathBuilder> pathBuilder = aBuilder ? aBuilder : CreatePathBuilder();
pathBuilder->MoveTo(points[0]);
for (uint32_t i = 1; i < points.Length(); ++i) {

Просмотреть файл

@ -46,7 +46,7 @@ public:
virtual bool IsMarkable() MOZ_OVERRIDE { return true; }
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE;
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual mozilla::TemporaryRef<Path> BuildPath() MOZ_OVERRIDE;
virtual mozilla::TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
// WebIDL
already_AddRefed<mozilla::DOMSVGPointList> Points();

Просмотреть файл

@ -6,6 +6,13 @@ text { font: 20px monospace; }
</style>
<g id="g">
<svg id="svg1" x="10" y="10" width="25" height="30"/>
<svg id="svg2" width="1" height="1" overflow="visible">
<rect width="2" height="2" fill="yellow"/>
</svg>
<svg id="svg3" width="1" height="1" overflow="hidden">
<rect width="2" height="2" fill="yellow"/>
</svg>
<text id="text1" x="25" y="25">abc</text>
<text id="text1a" x="85" y="25" stroke="black" stroke-width="4">abc</text>
<rect id="rect1" x="50" y="50" width="50" height="50" fill="green"/>

До

Ширина:  |  Высота:  |  Размер: 1.7 KiB

После

Ширина:  |  Высота:  |  Размер: 2.0 KiB

Просмотреть файл

@ -44,6 +44,24 @@ function runTest()
{
var doc = $("svg").contentWindow.document;
var svg1Bounds = doc.getElementById("svg1").getBoundingClientRect();
is(svg1Bounds.left, 10, "svg1.getBoundingClientRect().left");
is(svg1Bounds.top, 10, "svg1.getBoundingClientRect().top");
is(svg1Bounds.width, 25, "svg1.getBoundingClientRect().width");
is(svg1Bounds.height, 30, "svg1.getBoundingClientRect().height");
var svg2Bounds = doc.getElementById("svg2").getBoundingClientRect();
is(svg2Bounds.left, 0, "svg2.getBoundingClientRect().left");
is(svg2Bounds.top, 0, "svg2.getBoundingClientRect().top");
is(svg2Bounds.width, 2, "svg2.getBoundingClientRect().width");
is(svg2Bounds.height, 2, "svg2.getBoundingClientRect().height");
var svg3Bounds = doc.getElementById("svg3").getBoundingClientRect();
is(svg3Bounds.left, 0, "svg3.getBoundingClientRect().left");
is(svg3Bounds.top, 0, "svg3.getBoundingClientRect().top");
is(svg3Bounds.width, 1, "svg3.getBoundingClientRect().width");
is(svg3Bounds.height, 1, "svg3.getBoundingClientRect().height");
var text1 = doc.getElementById("text1");
var text1Bounds = text1.getBoundingClientRect();

Просмотреть файл

@ -22,7 +22,7 @@ function run()
var originY = div.offsetTop;
var circle = document.getElementById("circle");
var elementFromPoint = document.elementFromPoint(originX + 150, originY + 51);
var elementFromPoint = document.elementFromPoint(originX + 150, originY + 52);
is(elementFromPoint, circle, "Top of circle should hit");
var elementFromPoint = document.elementFromPoint(originX + 249, originY + 150);
@ -44,10 +44,10 @@ function run()
<div id="content">
<div width="100%" height="1" id="div">
</div>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="400" id="svg">
<circle id="circle" cx="1.5" cy="1.5" r="1" transform="scale(100, 100)"/>
</svg>
</div>
</div>
<pre id="test">

Просмотреть файл

@ -2135,7 +2135,7 @@ this.DOMApplicationRegistry = {
if (xhr.status == 200) {
if (!AppsUtils.checkManifestContentType(app.installOrigin, app.origin,
xhr.getResponseHeader("content-type"))) {
sendError("INVALID_MANIFEST");
sendError("INVALID_MANIFEST_CONTENT_TYPE");
return;
}
@ -2235,7 +2235,7 @@ this.DOMApplicationRegistry = {
if (xhr.status == 200) {
if (!AppsUtils.checkManifestContentType(app.installOrigin, app.origin,
xhr.getResponseHeader("content-type"))) {
sendError("INVALID_MANIFEST");
sendError("INVALID_MANIFEST_CONTENT_TYPE");
return;
}

Просмотреть файл

@ -110,7 +110,7 @@ var steps = [
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&noManifestContentType=true";
checkAppInstallError(miniManifestURL, "INVALID_MANIFEST");
checkAppInstallError(miniManifestURL, "INVALID_MANIFEST_CONTENT_TYPE");
},
function() {
// Test mini-manifest 'size' value is not number. Bug 839435.

Просмотреть файл

@ -68,6 +68,8 @@ public:
private:
IDBDatabase* mDatabase;
~VersionChangeListener() {}
};
NS_IMPL_ISUPPORTS(VersionChangeListener, nsIDOMEventListener)

Просмотреть файл

@ -32,9 +32,12 @@
</hbox>
</vbox>
<!-- wrap svg in a div so that it can take its intrinsic width -->
<div>
<svg:svg id="svgbase" width="45" height="20" xmlns:svg="http://www.w3.org/2000/svg">
<svg:rect id="svgrect" x="3" y="5" width="45" height="20" fill="red"/>
</svg:svg>
</div>
</vbox>

Просмотреть файл

@ -91,7 +91,7 @@ function invalidContent(next) {
var request = navigator.mozApps.install(url, null);
request.onerror = function onInstallError() {
is(this.error.name, "INVALID_MANIFEST", "manifest with bad content type");
is(this.error.name, "INVALID_MANIFEST_CONTENT_TYPE", "manifest with bad content type");
next();
};

Просмотреть файл

@ -213,6 +213,9 @@ class ServiceWorkerUpdateInstance MOZ_FINAL : public nsISupports
nsCOMPtr<nsPIDOMWindow> mWindow;
bool mAborted;
~ServiceWorkerUpdateInstance() {}
public:
NS_DECL_ISUPPORTS

Просмотреть файл

@ -1,15 +0,0 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script>
<![CDATA[
function boom()
{
document.createElement("head").innerHTML = "<";
}
]]>
</script></head>
<body onload="boom();"></body>
</html>

Просмотреть файл

@ -17,14 +17,16 @@
class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
{
public:
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIPRINTPROGRESS
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_NSIPRINTSTATUSFEEDBACK
nsPrintProgress();
virtual ~nsPrintProgress();
nsPrintProgress();
protected:
virtual ~nsPrintProgress();
private:
nsresult ReleaseListeners();

Просмотреть файл

@ -11,12 +11,14 @@
class nsPrintProgressParams : public nsIPrintProgressParams
{
public:
NS_DECL_ISUPPORTS
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPRINTPROGRESSPARAMS
nsPrintProgressParams();
virtual ~nsPrintProgressParams();
nsPrintProgressParams();
protected:
virtual ~nsPrintProgressParams();
private:
nsString mDocTitle;

Просмотреть файл

@ -30,7 +30,6 @@ class nsPrintingPromptService: public nsIPrintingPromptService,
{
public:
nsPrintingPromptService();
virtual ~nsPrintingPromptService();
nsresult Init();
@ -38,6 +37,9 @@ public:
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_ISUPPORTS
protected:
virtual ~nsPrintingPromptService();
private:
nsCOMPtr<nsIPrintProgress> mPrintProgress;
};

Просмотреть файл

@ -8,6 +8,10 @@
#include "mozilla/RefPtr.h"
#include "mozilla/NullPtr.h"
#include "mozilla/Likely.h"
#include "MainThreadUtils.h"
#include "base/message_loop.h"
#include "base/task.h"
namespace mozilla {
@ -18,10 +22,21 @@ class AtomicRefCountedWithFinalize
AtomicRefCountedWithFinalize()
: mRecycleCallback(nullptr)
, mRefCount(0)
, mMessageLoopToPostDestructionTo(nullptr)
{}
~AtomicRefCountedWithFinalize() {}
void SetMessageLoopToPostDestructionTo(MessageLoop* l) {
MOZ_ASSERT(NS_IsMainThread());
mMessageLoopToPostDestructionTo = l;
}
static void DestroyToBeCalledOnMainThread(T* ptr) {
MOZ_ASSERT(NS_IsMainThread());
delete ptr;
}
public:
void AddRef() {
MOZ_ASSERT(mRefCount >= 0);
@ -43,7 +58,17 @@ class AtomicRefCountedWithFinalize
#endif
T* derived = static_cast<T*>(this);
derived->Finalize();
delete derived;
if (MOZ_LIKELY(!mMessageLoopToPostDestructionTo)) {
delete derived;
} else {
if (MOZ_LIKELY(NS_IsMainThread())) {
delete derived;
} else {
mMessageLoopToPostDestructionTo->PostTask(
FROM_HERE,
NewRunnableFunction(&DestroyToBeCalledOnMainThread, derived));
}
}
} else if (1 == currCount && recycleCallback) {
T* derived = static_cast<T*>(this);
recycleCallback(derived, mClosure);
@ -71,6 +96,7 @@ private:
RecycleCallback mRecycleCallback;
void *mClosure;
Atomic<int> mRefCount;
MessageLoop *mMessageLoopToPostDestructionTo;
};
}

Просмотреть файл

@ -18,7 +18,6 @@
#include "basic/BasicLayers.h" // for BasicLayerManager, etc
#include "gfx3DMatrix.h" // for gfx3DMatrix
#include "gfxASurface.h" // for gfxASurface, etc
#include "gfxCachedTempSurface.h" // for gfxCachedTempSurface
#include "gfxColor.h" // for gfxRGBA
#include "gfxContext.h" // for gfxContext, etc
#include "gfxImageSurface.h" // for gfxImageSurface
@ -98,7 +97,8 @@ BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
// clipped precisely to the visible region.
*aNeedsClipToVisibleRegion = !didCompleteClip || aRegion.GetNumRects() > 1;
MOZ_ASSERT(!aContext->IsCairo());
result = PushGroupWithCachedSurface(aContext, gfxContentType::COLOR);
aContext->PushGroup(gfxContentType::COLOR);
result = aContext;
} else {
*aNeedsClipToVisibleRegion = false;
result = aContext;
@ -235,7 +235,6 @@ BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
mPhase(PHASE_NONE),
mWidget(aWidget)
, mDoubleBuffering(BufferMode::BUFFER_NONE), mUsingDefaultTarget(false)
, mCachedSurfaceInUse(false)
, mTransactionIncomplete(false)
, mCompositorMightResample(false)
{
@ -247,7 +246,6 @@ BasicLayerManager::BasicLayerManager() :
mPhase(PHASE_NONE),
mWidget(nullptr)
, mDoubleBuffering(BufferMode::BUFFER_NONE), mUsingDefaultTarget(false)
, mCachedSurfaceInUse(false)
, mTransactionIncomplete(false)
{
MOZ_COUNT_CTOR(BasicLayerManager);
@ -286,53 +284,6 @@ BasicLayerManager::BeginTransaction()
BeginTransactionWithTarget(mDefaultTarget);
}
already_AddRefed<gfxContext>
BasicLayerManager::PushGroupWithCachedSurface(gfxContext *aTarget,
gfxContentType aContent)
{
nsRefPtr<gfxContext> ctx;
// We can't cache Azure DrawTargets at this point.
if (!mCachedSurfaceInUse && aTarget->IsCairo()) {
gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
aTarget->IdentityMatrix();
nsRefPtr<gfxASurface> currentSurf = aTarget->CurrentSurface();
gfxRect clip = aTarget->GetClipExtents();
clip.RoundOut();
ctx = mCachedSurface.Get(aContent, clip, currentSurf);
if (ctx) {
mCachedSurfaceInUse = true;
/* Align our buffer for the original surface */
ctx->SetMatrix(saveMatrix.Matrix());
return ctx.forget();
}
}
ctx = aTarget;
ctx->PushGroup(aContent);
return ctx.forget();
}
void
BasicLayerManager::PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxContext *aPushed)
{
if (!aTarget)
return;
if (aTarget->IsCairo()) {
nsRefPtr<gfxASurface> current = aPushed->CurrentSurface();
if (mCachedSurface.IsSurface(current)) {
gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
aTarget->IdentityMatrix();
aTarget->SetSource(current);
mCachedSurfaceInUse = false;
return;
}
}
aTarget->PopGroupToSource();
}
void
BasicLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
{
@ -924,7 +875,7 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
nsRefPtr<gfxContext> groupTarget = PushGroupForLayer(aTarget, aLayer, aLayer->GetEffectiveVisibleRegion(),
&needsClipToVisibleRegion);
PaintSelfOrChildren(paintLayerContext, groupTarget);
PopGroupToSourceWithCachedSurface(aTarget, groupTarget);
aTarget->PopGroupToSource();
FlushGroup(paintLayerContext, needsClipToVisibleRegion);
} else {
PaintSelfOrChildren(paintLayerContext, aTarget);
@ -988,7 +939,6 @@ BasicLayerManager::ClearCachedResources(Layer* aSubtree)
} else if (mRoot) {
ClearLayer(mRoot);
}
mCachedSurface.Expire();
}
void
BasicLayerManager::ClearLayer(Layer* aLayer)

Просмотреть файл

@ -9,7 +9,6 @@
#include <stdint.h> // for INT32_MAX, int32_t
#include "Layers.h" // for Layer (ptr only), etc
#include "gfxTypes.h"
#include "gfxCachedTempSurface.h" // for gfxCachedTempSurface
#include "gfxContext.h" // for gfxContext
#include "mozilla/Attributes.h" // for MOZ_OVERRIDE
#include "mozilla/WidgetUtils.h" // for ScreenRotation
@ -136,9 +135,6 @@ public:
already_AddRefed<gfxContext> PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
const nsIntRegion& aRegion,
bool* aNeedsClipToVisibleRegion);
already_AddRefed<gfxContext> PushGroupWithCachedSurface(gfxContext *aTarget,
gfxContentType aContent);
void PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxContext *aPushed);
virtual bool IsCompositingCheap() { return false; }
virtual int32_t GetMaxTextureSize() const { return INT32_MAX; }
@ -186,12 +182,8 @@ protected:
// Image factory we use.
nsRefPtr<ImageFactory> mFactory;
// Cached surface for double buffering
gfxCachedTempSurface mCachedSurface;
BufferMode mDoubleBuffering;
bool mUsingDefaultTarget;
bool mCachedSurfaceInUse;
bool mTransactionIncomplete;
bool mCompositorMightResample;
};

Просмотреть файл

@ -93,7 +93,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
SetAntialiasingFlags(this, groupContext);
aCallback(this, groupContext, toDraw, DrawRegionClip::CLIP_NONE, nsIntRegion(), aCallbackData);
if (needsGroup) {
BasicManager()->PopGroupToSourceWithCachedSurface(aContext, groupContext);
aContext->PopGroupToSource();
if (needsClipToVisibleRegion) {
gfxUtils::ClipToRegion(aContext, toDraw);
}

Просмотреть файл

@ -471,11 +471,12 @@ static void
FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
const nsIntPoint& aOffset, const gfxRGBA& aColor)
{
nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
gfxUtils::ClipToRegion(ctx, aRegion);
ctx->SetColor(aColor);
ctx->Paint();
nsIntRegionRectIterator iter(aRegion);
const nsIntRect* r;
while ((r = iter.Next()) != nullptr) {
nsIntRect rect = *r + aOffset;
gfxUtils::ClearThebesSurface(aSurface, &rect, aColor);
}
}
void
@ -526,17 +527,13 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
if (!destinationSurface)
return;
nsRefPtr<gfxContext> context;
if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(BackendType::CAIRO)) {
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(destinationSurface,
IntSize(destinationSurface->GetSize().width,
destinationSurface->GetSize().height));
MOZ_ASSERT(gfxPlatform::GetPlatform()->SupportsAzureContentForType(BackendType::CAIRO));
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(destinationSurface,
IntSize(destinationSurface->GetSize().width,
destinationSurface->GetSize().height));
context = new gfxContext(dt);
} else {
context = new gfxContext(destinationSurface);
}
nsRefPtr<gfxContext> context = new gfxContext(dt);
context->Translate(gfxPoint(-bounds.x, -bounds.y));
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();

Просмотреть файл

@ -17,6 +17,7 @@
#include "nsCOMPtr.h" // for nsCOMPtr
#include "nsHashKeys.h" // for nsUint64HashKey
#include "nsISupportsImpl.h" // for NS_INLINE_DECL_REFCOUNTING
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
class nsIObserver;
@ -29,7 +30,8 @@ struct FrameMetrics;
class CompositorChild MOZ_FINAL : public PCompositorChild
{
NS_INLINE_DECL_REFCOUNTING(CompositorChild)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorChild)
public:
CompositorChild(ClientLayerManager *aLayerManager);

Просмотреть файл

@ -53,6 +53,7 @@
#include "mozilla/unused.h"
#include "mozilla/Hal.h"
#include "mozilla/HalTypes.h"
#include "mozilla/StaticPtr.h"
namespace mozilla {
namespace layers {
@ -73,64 +74,65 @@ CompositorParent::LayerTreeState::LayerTreeState()
typedef map<uint64_t, CompositorParent::LayerTreeState> LayerTreeMap;
static LayerTreeMap sIndirectLayerTrees;
// FIXME/bug 774386: we're assuming that there's only one
// CompositorParent, but that's not always true. This assumption only
// affects CrossProcessCompositorParent below.
static Thread* sCompositorThread = nullptr;
// manual reference count of the compositor thread.
static int sCompositorThreadRefCount = 0;
static MessageLoop* sMainLoop = nullptr;
/**
* A global map referencing each compositor by ID.
*
* This map is used by the ImageBridge protocol to trigger
* compositions without having to keep references to the
* compositor
*/
typedef map<uint64_t,CompositorParent*> CompositorMap;
static CompositorMap* sCompositorMap;
static void CreateCompositorMap()
{
MOZ_ASSERT(!sCompositorMap);
sCompositorMap = new CompositorMap;
}
static void DestroyCompositorMap()
{
MOZ_ASSERT(sCompositorMap);
MOZ_ASSERT(sCompositorMap->empty());
delete sCompositorMap;
sCompositorMap = nullptr;
}
// See ImageBridgeChild.cpp
void ReleaseImageBridgeParentSingleton();
static void DeferredDeleteCompositorParent(CompositorParent* aNowReadyToDie)
CompositorThreadHolder::CompositorThreadHolder()
: mCompositorThread(CreateCompositorThread())
{
aNowReadyToDie->Release();
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_CTOR(CompositorThreadHolder);
}
static void DeleteCompositorThread()
CompositorThreadHolder::~CompositorThreadHolder()
{
if (NS_IsMainThread()){
ReleaseImageBridgeParentSingleton();
delete sCompositorThread;
sCompositorThread = nullptr;
} else {
sMainLoop->PostTask(FROM_HERE, NewRunnableFunction(&DeleteCompositorThread));
}
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_DTOR(CompositorThreadHolder);
DestroyCompositorThread(mCompositorThread);
}
static void ReleaseCompositorThread()
static StaticRefPtr<CompositorThreadHolder> sCompositorThreadHolder;
static bool sFinishedCompositorShutDown = false;
CompositorThreadHolder* GetCompositorThreadHolder()
{
if(--sCompositorThreadRefCount == 0) {
DeleteCompositorThread();
}
return sCompositorThreadHolder;
}
static void SetThreadPriority()
/* static */ Thread*
CompositorThreadHolder::CreateCompositorThread()
{
hal::SetCurrentThreadPriority(hal::THREAD_PRIORITY_COMPOSITOR);
}
MOZ_ASSERT(NS_IsMainThread());
void CompositorParent::StartUp()
{
CreateCompositorMap();
CreateThread();
sMainLoop = MessageLoop::current();
}
MOZ_ASSERT(!sCompositorThreadHolder, "The compositor thread has already been started!");
void CompositorParent::ShutDown()
{
DestroyThread();
DestroyCompositorMap();
}
bool CompositorParent::CreateThread()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(!sCompositorThread);
sCompositorThreadRefCount = 1;
sCompositorThread = new Thread("Compositor");
Thread* compositorThread = new Thread("Compositor");
Thread::Options options;
/* Timeout values are powers-of-two to enable us get better data.
@ -141,24 +143,64 @@ bool CompositorParent::CreateThread()
than the default hang timeout on major platforms (about 5 seconds). */
options.permanent_hang_timeout = 8192; // milliseconds
if (!sCompositorThread->StartWithOptions(options)) {
delete sCompositorThread;
sCompositorThread = nullptr;
return false;
if (!compositorThread->StartWithOptions(options)) {
delete compositorThread;
return nullptr;
}
return true;
CreateCompositorMap();
return compositorThread;
}
void CompositorParent::DestroyThread()
/* static */ void
CompositorThreadHolder::DestroyCompositorThread(Thread* aCompositorThread)
{
NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
ReleaseCompositorThread();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!sCompositorThreadHolder, "We shouldn't be destroying the compositor thread yet.");
DestroyCompositorMap();
delete aCompositorThread;
sFinishedCompositorShutDown = true;
}
static Thread* CompositorThread() {
return sCompositorThreadHolder ? sCompositorThreadHolder->GetCompositorThread() : nullptr;
}
static void SetThreadPriority()
{
hal::SetCurrentThreadPriority(hal::THREAD_PRIORITY_COMPOSITOR);
}
void CompositorParent::StartUp()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(!sCompositorThreadHolder, "The compositor thread has already been started!");
sCompositorThreadHolder = new CompositorThreadHolder();
}
void CompositorParent::ShutDown()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(sCompositorThreadHolder, "The compositor thread has already been shut down!");
ReleaseImageBridgeParentSingleton();
sCompositorThreadHolder = nullptr;
// No locking is needed around sFinishedCompositorShutDown because it is only
// ever accessed on the main thread.
while (!sFinishedCompositorShutDown) {
NS_ProcessNextEvent(nullptr, true);
}
}
MessageLoop* CompositorParent::CompositorLoop()
{
return sCompositorThread ? sCompositorThread->message_loop() : nullptr;
return CompositorThread() ? CompositorThread()->message_loop() : nullptr;
}
CompositorParent::CompositorParent(nsIWidget* aWidget,
@ -175,9 +217,11 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
, mResumeCompositionMonitor("ResumeCompositionMonitor")
, mOverrideComposeReadiness(false)
, mForceCompositionTask(nullptr)
, mCompositorThreadHolder(sCompositorThreadHolder)
{
MOZ_ASSERT(sCompositorThread != nullptr,
"The compositor thread must be Initialized before instanciating a CmpositorParent.");
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(CompositorThread(),
"The compositor thread must be Initialized before instanciating a CompositorParent.");
MOZ_COUNT_CTOR(CompositorParent);
mCompositorID = 0;
// FIXME: This holds on the the fact that right now the only thing that
@ -192,13 +236,12 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
sIndirectLayerTrees[mRootLayerTreeID].mParent = this;
mApzcTreeManager = new APZCTreeManager();
++sCompositorThreadRefCount;
}
bool
CompositorParent::IsInCompositorThread()
{
return sCompositorThread && sCompositorThread->thread_id() == PlatformThread::CurrentId();
return CompositorThread() && CompositorThread()->thread_id() == PlatformThread::CurrentId();
}
uint64_t
@ -209,9 +252,8 @@ CompositorParent::RootLayerTreeId()
CompositorParent::~CompositorParent()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_DTOR(CompositorParent);
ReleaseCompositorThread();
}
void
@ -264,6 +306,13 @@ CompositorParent::RecvWillStop()
return true;
}
void CompositorParent::DeferredDestroy()
{
MOZ_ASSERT(!NS_IsMainThread());
mCompositorThreadHolder = nullptr;
Release();
}
bool
CompositorParent::RecvStop()
{
@ -273,10 +322,9 @@ CompositorParent::RecvStop()
// this thread.
// We must keep the compositor parent alive untill the code handling message
// reception is finished on this thread.
this->AddRef(); // Corresponds to DeferredDeleteCompositorParent's Release
CompositorLoop()->PostTask(FROM_HERE,
NewRunnableFunction(&DeferredDeleteCompositorParent,
this));
this->AddRef(); // Corresponds to DeferredDestroy's Release
MessageLoop::current()->PostTask(FROM_HERE,
NewRunnableMethod(this,&CompositorParent::DeferredDestroy));
return true;
}
@ -921,27 +969,6 @@ CompositorParent::DeallocPLayerTransactionParent(PLayerTransactionParent* actor)
return true;
}
typedef map<uint64_t,CompositorParent*> CompositorMap;
static CompositorMap* sCompositorMap;
void CompositorParent::CreateCompositorMap()
{
if (sCompositorMap == nullptr) {
sCompositorMap = new CompositorMap;
}
}
void CompositorParent::DestroyCompositorMap()
{
if (sCompositorMap != nullptr) {
NS_ASSERTION(sCompositorMap->empty(),
"The Compositor map should be empty when destroyed>");
delete sCompositorMap;
sCompositorMap = nullptr;
}
}
CompositorParent* CompositorParent::GetCompositor(uint64_t id)
{
CompositorMap::iterator it = sCompositorMap->find(id);
@ -1077,12 +1104,15 @@ class CrossProcessCompositorParent MOZ_FINAL : public PCompositorParent,
{
friend class CompositorParent;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CrossProcessCompositorParent)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CrossProcessCompositorParent)
public:
CrossProcessCompositorParent(Transport* aTransport, ProcessId aOtherProcess)
: mTransport(aTransport)
, mChildProcessId(aOtherProcess)
{}
, mCompositorThreadHolder(sCompositorThreadHolder)
{
MOZ_ASSERT(NS_IsMainThread());
}
// IToplevelProtocol::CloneToplevel()
virtual IToplevelProtocol*
@ -1145,6 +1175,8 @@ private:
Transport* mTransport;
// Child side's process Id.
base::ProcessId mChildProcessId;
nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder;
};
void
@ -1176,6 +1208,8 @@ OpenCompositor(CrossProcessCompositorParent* aCompositor,
/*static*/ PCompositorParent*
CompositorParent::Create(Transport* aTransport, ProcessId aOtherProcess)
{
gfxPlatform::InitLayersIPC();
nsRefPtr<CrossProcessCompositorParent> cpcp =
new CrossProcessCompositorParent(aTransport, aOtherProcess);
ProcessHandle handle;
@ -1404,16 +1438,14 @@ CrossProcessCompositorParent::GetCompositionManager(LayerTransactionParent* aLay
void
CrossProcessCompositorParent::DeferredDestroy()
{
CrossProcessCompositorParent* self;
mSelfRef.forget(&self);
nsCOMPtr<nsIRunnable> runnable =
NS_NewNonOwningRunnableMethod(self, &CrossProcessCompositorParent::Release);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
mCompositorThreadHolder = nullptr;
mSelfRef = nullptr;
}
CrossProcessCompositorParent::~CrossProcessCompositorParent()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_GetIOMessageLoop());
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<Transport>(mTransport));
}

Просмотреть файл

@ -20,6 +20,7 @@
#include "ShadowLayersManager.h" // for ShadowLayersManager
#include "base/basictypes.h" // for DISALLOW_EVIL_CONSTRUCTORS
#include "base/platform_thread.h" // for PlatformThreadId
#include "base/thread.h" // for Thread
#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2
#include "mozilla/Attributes.h" // for MOZ_OVERRIDE
#include "mozilla/Monitor.h" // for Monitor
@ -33,6 +34,7 @@
#include "nsAutoPtr.h" // for nsRefPtr
#include "nsISupportsImpl.h"
#include "nsSize.h" // for nsIntSize
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
class CancelableTask;
class MessageLoop;
@ -63,10 +65,32 @@ private:
uint64_t mLayersId;
};
class CompositorThreadHolder MOZ_FINAL
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorThreadHolder)
public:
CompositorThreadHolder();
base::Thread* GetCompositorThread() const {
return mCompositorThread;
}
private:
~CompositorThreadHolder();
base::Thread* const mCompositorThread;
static base::Thread* CreateCompositorThread();
static void DestroyCompositorThread(base::Thread* aCompositorThread);
friend class CompositorParent;
};
class CompositorParent : public PCompositorParent,
public ShadowLayersManager
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorParent)
public:
CompositorParent(nsIWidget* aWidget,
@ -166,7 +190,10 @@ public:
static void StartUp();
/**
* Destroys the compositor thread and the global compositor map.
* Waits for all [CrossProcess]CompositorParent's to be gone,
* and destroys the compositor thread and global compositor map.
*
* Does not return until all of that has completed.
*/
static void ShutDown();
@ -239,6 +266,8 @@ protected:
// Protected destructor, to discourage deletion outside of Release():
virtual ~CompositorParent();
void DeferredDestroy();
virtual PLayerTransactionParent*
AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
const uint64_t& aId,
@ -259,36 +288,6 @@ protected:
void ForceComposition();
void CancelCurrentCompositeTask();
/**
* Creates a global map referencing each compositor by ID.
*
* This map is used by the ImageBridge protocol to trigger
* compositions without having to keep references to the
* compositor
*/
static void CreateCompositorMap();
static void DestroyCompositorMap();
/**
* Creates the compositor thread.
*
* All compositors live on the same thread.
* The thread is not lazily created on first access to avoid dealing with
* thread safety. Therefore it's best to create and destroy the thread when
* we know we areb't using it (So creating/destroying along with gfxPlatform
* looks like a good place).
*/
static bool CreateThread();
/**
* Destroys the compositor thread.
*
* It is safe to call this fucntion more than once, although the second call
* will have no effect.
* This function is not thread-safe.
*/
static void DestroyThread();
/**
* Add a compositor to the global compositor map.
*/
@ -336,6 +335,8 @@ protected:
nsRefPtr<APZCTreeManager> mApzcTreeManager;
nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder;
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
};

Просмотреть файл

@ -221,7 +221,6 @@ static void ImageBridgeShutdownStep2(ReentrantMonitor *aBarrier, bool *aDone)
sImageBridgeChildSingleton->SendStop();
sImageBridgeChildSingleton = nullptr;
*aDone = true;
aBarrier->NotifyAll();
}
@ -248,10 +247,14 @@ static void ConnectImageBridge(ImageBridgeChild * child, ImageBridgeParent * par
ImageBridgeChild::ImageBridgeChild()
: mShuttingDown(false)
{
MOZ_ASSERT(NS_IsMainThread());
mTxn = new CompositableTransaction();
}
ImageBridgeChild::~ImageBridgeChild()
{
MOZ_ASSERT(NS_IsMainThread());
delete mTxn;
}
@ -547,7 +550,7 @@ PImageBridgeChild*
ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
ProcessId aOtherProcess)
{
NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(NS_IsMainThread());
gfxPlatform::GetPlatform();
@ -572,7 +575,7 @@ ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
void ImageBridgeChild::ShutDown()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(NS_IsMainThread());
if (ImageBridgeChild::IsCreated()) {
MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
@ -600,6 +603,8 @@ void ImageBridgeChild::ShutDown()
}
}
sImageBridgeChildSingleton = nullptr;
delete sImageBridgeChildThread;
sImageBridgeChildThread = nullptr;
}

Просмотреть файл

@ -17,6 +17,7 @@
#include "mozilla/layers/PImageBridgeChild.h"
#include "nsDebug.h" // for NS_RUNTIMEABORT
#include "nsRegion.h" // for nsIntRegion
class MessageLoop;
struct nsIntPoint;
struct nsIntRect;

Просмотреть файл

@ -44,13 +44,25 @@ using namespace mozilla::gfx;
std::map<base::ProcessId, ImageBridgeParent*> ImageBridgeParent::sImageBridges;
MessageLoop* ImageBridgeParent::sMainLoop = nullptr;
// defined in CompositorParent.cpp
CompositorThreadHolder* GetCompositorThreadHolder();
ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop,
Transport* aTransport,
ProcessId aChildProcessId)
: mMessageLoop(aLoop)
, mTransport(aTransport)
, mChildProcessId(aChildProcessId)
, mCompositorThreadHolder(GetCompositorThreadHolder())
{
MOZ_ASSERT(NS_IsMainThread());
sMainLoop = MessageLoop::current();
// top-level actors must be destroyed on the main thread.
SetMessageLoopToPostDestructionTo(sMainLoop);
// creates the map only if it has not been created already, so it is safe
// with several bridges
CompositableMap::Create();
@ -59,10 +71,14 @@ ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop,
ImageBridgeParent::~ImageBridgeParent()
{
MOZ_ASSERT(NS_IsMainThread());
if (mTransport) {
MOZ_ASSERT(XRE_GetIOMessageLoop());
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<Transport>(mTransport));
}
sImageBridges.erase(mChildProcessId);
}
@ -160,10 +176,25 @@ bool ImageBridgeParent::RecvWillStop()
return true;
}
static void
ReleaseImageBridgeParent(ImageBridgeParent* aImageBridgeParent)
{
aImageBridgeParent->Release();
}
bool ImageBridgeParent::RecvStop()
{
// Nothing to do. This message just serves as synchronization between the
// This message just serves as synchronization between the
// child and parent threads during shutdown.
// There is one thing that we need to do here: temporarily addref, so that
// the handling of this sync message can't race with the destruction of
// the ImageBridgeParent, which would trigger the dreaded "mismatched CxxStackFrames"
// assertion of MessageChannel.
AddRef();
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableFunction(&ReleaseImageBridgeParent, this));
return true;
}
@ -265,32 +296,11 @@ MessageLoop * ImageBridgeParent::GetMessageLoop() const {
return mMessageLoop;
}
class ReleaseRunnable : public nsRunnable
{
public:
ReleaseRunnable(ImageBridgeParent* aRef)
: mRef(aRef)
{
}
NS_IMETHOD Run()
{
mRef->Release();
return NS_OK;
}
private:
ImageBridgeParent* mRef;
};
void
ImageBridgeParent::DeferredDestroy()
{
ImageBridgeParent* self;
mSelfRef.forget(&self);
nsCOMPtr<nsIRunnable> runnable = new ReleaseRunnable(self);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
mCompositorThreadHolder = nullptr;
mSelfRef = nullptr;
}
ImageBridgeParent*

Просмотреть файл

@ -9,6 +9,7 @@
#include <stddef.h> // for size_t
#include <stdint.h> // for uint32_t, uint64_t
#include "CompositableTransactionParent.h"
#include "CompositorParent.h"
#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2
#include "mozilla/Attributes.h" // for MOZ_OVERRIDE
#include "mozilla/ipc/ProtocolUtils.h"
@ -151,6 +152,10 @@ private:
* Map of all living ImageBridgeParent instances
*/
static std::map<base::ProcessId, ImageBridgeParent*> sImageBridges;
static MessageLoop* sMainLoop;
nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder;
};
} // layers

Просмотреть файл

@ -0,0 +1,83 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef THREADSAFEREFCOUNTINGWITHMAINTHREADDESTRUCTION_H_
#define THREADSAFEREFCOUNTINGWITHMAINTHREADDESTRUCTION_H_
#include "MainThreadUtils.h"
#include "base/message_loop.h"
#include "base/task.h"
namespace mozilla {
namespace layers {
inline MessageLoop* GetMainLoopAssertingMainThread()
{
MOZ_ASSERT(NS_IsMainThread());
return MessageLoop::current();
}
inline MessageLoop* GetMainLoop()
{
static MessageLoop* sMainLoop = GetMainLoopAssertingMainThread();
return sMainLoop;
}
struct HelperForMainThreadDestruction
{
HelperForMainThreadDestruction()
{
MOZ_ASSERT(NS_IsMainThread());
GetMainLoop();
}
~HelperForMainThreadDestruction()
{
MOZ_ASSERT(NS_IsMainThread());
}
};
} // namespace layers
} // namespace mozilla
#define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(_class) \
public: \
NS_METHOD_(MozExternalRefCountType) AddRef(void) { \
MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
nsrefcnt count = ++mRefCnt; \
NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
return (nsrefcnt) count; \
} \
static void DestroyToBeCalledOnMainThread(_class* ptr) { \
MOZ_ASSERT(NS_IsMainThread()); \
NS_LOG_RELEASE(ptr, 0, #_class); \
delete ptr; \
} \
NS_METHOD_(MozExternalRefCountType) Release(void) { \
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
nsrefcnt count = --mRefCnt; \
if (count == 0) { \
if (NS_IsMainThread()) { \
NS_LOG_RELEASE(this, 0, #_class); \
delete this; \
} else { \
/* no NS_LOG_RELEASE here, will be in the runnable */ \
MessageLoop *l = ::mozilla::layers::GetMainLoop(); \
l->PostTask(FROM_HERE, \
NewRunnableFunction(&DestroyToBeCalledOnMainThread, \
this)); \
} \
} else { \
NS_LOG_RELEASE(this, count, #_class); \
} \
return count; \
} \
protected: \
::mozilla::ThreadSafeAutoRefCnt mRefCnt; \
private: \
::mozilla::layers::HelperForMainThreadDestruction mHelperForMainThreadDestruction; \
public:
#endif

Просмотреть файл

@ -27,6 +27,7 @@ EXPORTS += [
'ipc/CompositorChild.h',
'ipc/CompositorParent.h',
'ipc/ShadowLayersManager.h',
'ipc/ThreadSafeRefcountingWithMainThreadDestruction.h',
'Layers.h',
'LayerScope.h',
'LayersLogging.h',

Просмотреть файл

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body style="font-variant: small-caps; font-family: 'Times New Roman';">
<div>x&#xE0131;</div>
</body>
</html>

Просмотреть файл

@ -108,3 +108,4 @@ load 893572-1.html
load 893572-2.html
load 893572-3.html
load 893572-4.html
load 1034403-1.html

Просмотреть файл

@ -1,106 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gfxCachedTempSurface.h"
#include "gfxContext.h"
#include "mozilla/Attributes.h"
class CachedSurfaceExpirationTracker MOZ_FINAL :
public nsExpirationTracker<gfxCachedTempSurface,2> {
public:
// With K = 2, this means that surfaces will be released when they are not
// used for 1-2 seconds.
enum { TIMEOUT_MS = 1000 };
CachedSurfaceExpirationTracker()
: nsExpirationTracker<gfxCachedTempSurface,2>(TIMEOUT_MS) {}
~CachedSurfaceExpirationTracker() {
AgeAllGenerations();
}
virtual void NotifyExpired(gfxCachedTempSurface* aSurface) {
RemoveObject(aSurface);
aSurface->Expire();
}
static void MarkSurfaceUsed(gfxCachedTempSurface* aSurface)
{
if (aSurface->GetExpirationState()->IsTracked()) {
sExpirationTracker->MarkUsed(aSurface);
return;
}
if (!sExpirationTracker) {
sExpirationTracker = new CachedSurfaceExpirationTracker();
}
sExpirationTracker->AddObject(aSurface);
}
static void RemoveSurface(gfxCachedTempSurface* aSurface)
{
if (!sExpirationTracker)
return;
if (aSurface->GetExpirationState()->IsTracked()) {
sExpirationTracker->RemoveObject(aSurface);
}
if (sExpirationTracker->IsEmpty()) {
delete sExpirationTracker;
sExpirationTracker = nullptr;
}
}
private:
static CachedSurfaceExpirationTracker* sExpirationTracker;
};
CachedSurfaceExpirationTracker*
CachedSurfaceExpirationTracker::sExpirationTracker = nullptr;
gfxCachedTempSurface::~gfxCachedTempSurface()
{
CachedSurfaceExpirationTracker::RemoveSurface(this);
}
already_AddRefed<gfxContext>
gfxCachedTempSurface::Get(gfxContentType aContentType,
const gfxRect& aRect,
gfxASurface* aSimilarTo)
{
if (mSurface) {
/* Verify the current buffer is valid for this purpose */
if (mSize.width < aRect.width || mSize.height < aRect.height
|| mSurface->GetContentType() != aContentType
|| mType != aSimilarTo->GetType()) {
mSurface = nullptr;
}
}
bool cleared = false;
if (!mSurface) {
mSize = gfxIntSize(int32_t(ceil(aRect.width)), int32_t(ceil(aRect.height)));
mSurface = aSimilarTo->CreateSimilarSurface(aContentType, mSize);
if (!mSurface)
return nullptr;
cleared = true;
mType = aSimilarTo->GetType();
}
mSurface->SetDeviceOffset(-aRect.TopLeft());
nsRefPtr<gfxContext> ctx = new gfxContext(mSurface);
ctx->Rectangle(aRect);
ctx->Clip();
if (!cleared && aContentType != gfxContentType::COLOR) {
ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
ctx->Paint();
ctx->SetOperator(gfxContext::OPERATOR_OVER);
}
CachedSurfaceExpirationTracker::MarkSurfaceUsed(this);
return ctx.forget();
}

Просмотреть файл

@ -1,58 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_CACHED_TEMP_SURFACE_H
#define GFX_CACHED_TEMP_SURFACE_H
#include "gfxASurface.h"
#include "nsExpirationTracker.h"
#include "nsSize.h"
class gfxContext;
/**
* This class can be used to cache double-buffering back surfaces.
*
* Large resource allocations may have an overhead that can be avoided by
* caching. Caching also alows the system to use history in deciding whether
* to manage the surfaces in video or system memory.
*
* However, because we don't want to set aside megabytes of unused resources
* unncessarily, these surfaces are released on a timer.
*/
class gfxCachedTempSurface {
public:
/**
* Returns a context for a surface that can be efficiently copied to
* |aSimilarTo|.
*
* When |aContentType| has an alpha component, the surface will be cleared.
* For opaque surfaces, the initial surface contents are undefined.
* When |aContentType| differs in different invocations this is handled
* appropriately, creating a new surface if necessary.
*
* Because the cached surface may have been created during a previous
* invocation, this will not be efficient if the new |aSimilarTo| has a
* different format, size, or gfxSurfaceType.
*/
already_AddRefed<gfxContext> Get(gfxContentType aContentType,
const gfxRect& aRect,
gfxASurface* aSimilarTo);
void Expire() { mSurface = nullptr; }
nsExpirationState* GetExpirationState() { return &mExpirationState; }
~gfxCachedTempSurface();
bool IsSurface(gfxASurface* aSurface) { return mSurface == aSurface; }
private:
nsRefPtr<gfxASurface> mSurface;
gfxIntSize mSize;
nsExpirationState mExpirationState;
gfxSurfaceType mType;
};
#endif /* GFX_CACHED_TEMP_SURFACE_H */

Просмотреть файл

@ -5764,6 +5764,9 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
uint32_t runStart = 0;
for (uint32_t i = 0; i <= aLength; ++i) {
uint32_t extraCodeUnits = 0; // Will be set to 1 if we need to consume
// a trailing surrogate as well as the
// current code unit.
RunCaseAction chAction = kNoChange;
// Unless we're at the end, figure out what treatment the current
// character will need.
@ -5772,6 +5775,7 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
if (NS_IS_HIGH_SURROGATE(ch) && i < aLength - 1 &&
NS_IS_LOW_SURROGATE(aText[i + 1])) {
ch = SURROGATE_TO_UCS4(ch, aText[i + 1]);
extraCodeUnits = 1;
}
// Characters that aren't the start of a cluster are ignored here.
// They get added to whatever lowercase/non-lowercase run we're in.
@ -5885,6 +5889,7 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
runStart = i;
}
i += extraCodeUnits;
if (i < aLength) {
runAction = chAction;
}

Просмотреть файл

@ -1005,7 +1005,9 @@ gfxUtils::ConvertYCbCrToRGB(const PlanarYCbCrData& aData,
}
}
/* static */ void gfxUtils::ClearThebesSurface(gfxASurface* aSurface)
/* static */ void gfxUtils::ClearThebesSurface(gfxASurface* aSurface,
nsIntRect* aRect,
const gfxRGBA& aColor)
{
if (aSurface->CairoStatus()) {
return;
@ -1015,8 +1017,16 @@ gfxUtils::ConvertYCbCrToRGB(const PlanarYCbCrData& aData,
return;
}
cairo_t* ctx = cairo_create(surf);
cairo_set_operator(ctx, CAIRO_OPERATOR_CLEAR);
cairo_paint_with_alpha(ctx, 1.0);
cairo_set_source_rgba(ctx, aColor.r, aColor.g, aColor.b, aColor.a);
cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE);
nsIntRect bounds;
if (aRect) {
bounds = *aRect;
} else {
bounds = nsIntRect(nsIntPoint(0, 0), aSurface->GetSize());
}
cairo_rectangle(ctx, bounds.x, bounds.y, bounds.width, bounds.height);
cairo_fill(ctx);
cairo_destroy(ctx);
}

Просмотреть файл

@ -6,6 +6,7 @@
#ifndef GFX_UTILS_H
#define GFX_UTILS_H
#include "gfxColor.h"
#include "gfxTypes.h"
#include "GraphicsFilter.h"
#include "imgIContainer.h"
@ -171,9 +172,11 @@ public:
int32_t aStride);
/**
* Clears surface to transparent black.
* Clears surface to aColor (which defaults to transparent black).
*/
static void ClearThebesSurface(gfxASurface* aSurface);
static void ClearThebesSurface(gfxASurface* aSurface,
nsIntRect* aRect = nullptr,
const gfxRGBA& aColor = gfxRGBA(0.0, 0.0, 0.0, 0.0));
/**
* Creates a copy of aSurface, but having the SurfaceFormat aFormat.

Просмотреть файл

@ -12,7 +12,6 @@ EXPORTS += [
'gfxASurface.h',
'gfxBaseSharedMemorySurface.h',
'gfxBlur.h',
'gfxCachedTempSurface.h',
'gfxColor.h',
'gfxContext.h',
'gfxDrawable.h',
@ -223,7 +222,6 @@ UNIFIED_SOURCES += [
'gfxAlphaRecovery.cpp',
'gfxBaseSharedMemorySurface.cpp',
'gfxBlur.cpp',
'gfxCachedTempSurface.cpp',
'gfxContext.cpp',
'gfxFontFeatures.cpp',
'gfxFontInfoLoader.cpp',

Просмотреть файл

@ -115,6 +115,9 @@ struct SingletonDestroyer MOZ_FINAL : public nsIObserver
{
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
private:
~SingletonDestroyer() {}
};
NS_IMPL_ISUPPORTS(SingletonDestroyer, nsIObserver)

Просмотреть файл

@ -31,11 +31,12 @@ public:
NS_DECL_NSISTREAMLISTENER
nsIconChannel();
virtual ~nsIconChannel();
nsresult Init(nsIURI* uri);
protected:
virtual ~nsIconChannel();
nsCOMPtr<nsIURI> mUrl;
nsCOMPtr<nsIURI> mOriginalURI;
int64_t mContentLength;

Просмотреть файл

@ -22,7 +22,6 @@ class nsCollationMacUC MOZ_FINAL : public nsICollation {
public:
nsCollationMacUC();
~nsCollationMacUC();
// nsISupports interface
NS_DECL_ISUPPORTS
@ -31,6 +30,8 @@ public:
NS_DECL_NSICOLLATION
protected:
~nsCollationMacUC();
nsresult ConvertLocale(nsILocale* aNSLocale, LocaleRef* aMacLocale);
nsresult StrengthToOptions(const int32_t aStrength,
UCCollateOptions* aOptions);

Просмотреть файл

@ -45,9 +45,10 @@ public:
nsAString& stringOut);
nsDateTimeFormatMac() {}
protected:
virtual ~nsDateTimeFormatMac() {}
private:
// init this interface to a specified locale
NS_IMETHOD Initialize(nsILocale* locale);

Просмотреть файл

@ -19,11 +19,14 @@ namespace ipc {
IToplevelProtocol::~IToplevelProtocol()
{
MOZ_ASSERT(NS_IsMainThread());
mOpenActors.clear();
}
void IToplevelProtocol::AddOpenedActor(IToplevelProtocol* aActor)
{
MOZ_ASSERT(NS_IsMainThread());
#ifdef DEBUG
for (const IToplevelProtocol* actor = mOpenActors.getFirst();
actor;

Просмотреть файл

@ -21,6 +21,7 @@
#include "mozilla/ipc/Transport.h"
#include "mozilla/ipc/MessageLink.h"
#include "mozilla/LinkedList.h"
#include "MainThreadUtils.h"
#if defined(ANDROID) && defined(DEBUG)
#include <android/log.h>
@ -187,6 +188,7 @@ protected:
: mProtocolId(aProtoId)
, mTrans(nullptr)
{
MOZ_ASSERT(NS_IsMainThread());
}
~IToplevelProtocol();
@ -212,10 +214,12 @@ public:
*/
IToplevelProtocol* GetFirstOpenedActors()
{
MOZ_ASSERT(NS_IsMainThread());
return mOpenActors.getFirst();
}
const IToplevelProtocol* GetFirstOpenedActors() const
{
MOZ_ASSERT(NS_IsMainThread());
return mOpenActors.getFirst();
}

Просмотреть файл

@ -303,9 +303,11 @@ AssertMarkedOrAllocated(const EdgeValue &edge)
if (!edge.thing || IsMarkedOrAllocated(static_cast<Cell *>(edge.thing)))
return;
// Permanent atoms aren't marked during graph traversal.
// Permanent atoms and well-known symbols aren't marked during graph traversal.
if (edge.kind == JSTRACE_STRING && static_cast<JSString *>(edge.thing)->isPermanentAtom())
return;
if (edge.kind == JSTRACE_SYMBOL && static_cast<JS::Symbol *>(edge.thing)->isWellKnownSymbol())
return;
char msgbuf[1024];
const char *label = edge.label;

Просмотреть файл

@ -0,0 +1,3 @@
gczeal(4);
var symbols = [Symbol(), Symbol("comet"), Symbol.for("moon"), Symbol.iterator, 0];
for (var a of symbols) {}

Просмотреть файл

@ -0,0 +1,29 @@
var tests = [
{T: Uint8Array, result: 0},
{T: Uint8ClampedArray, result: 0},
{T: Int16Array, result: 0},
{T: Float32Array, result: NaN}
];
var LENGTH = 1024, SYMBOL_INDEX = 999;
var big = [];
for (var i = 0; i < LENGTH; i++)
big[i] = (i === SYMBOL_INDEX ? Symbol.for("comet") : i);
function copy(arr, big) {
for (var i = 0; i < LENGTH; i++)
arr[i] = big[i];
}
for (var {T, result} of tests) {
// Typed array constructors convert symbols to NaN or 0.
arr = new T(big);
assertEq(arr[SYMBOL_INDEX], result);
// Element assignment does the same.
for (var k = 0; k < 3; k++) {
copy(arr, big);
assertEq(arr[SYMBOL_INDEX], result);
}
}

Просмотреть файл

@ -27,6 +27,13 @@ BEGIN_TEST(testGCHeapPostBarriers)
return true;
}
MOZ_NEVER_INLINE bool
Passthrough(bool value)
{
/* Work around a Win64 optimization bug in VS2010. (Bug 1033146) */
return value;
}
template <typename T>
bool
TestHeapPostBarriers(T initialObj)
@ -37,7 +44,7 @@ TestHeapPostBarriers(T initialObj)
/* Construct Heap<> wrapper. */
JS::Heap<T> *heapData = new JS::Heap<T>();
CHECK(heapData);
CHECK(heapData->get() == nullptr);
CHECK(Passthrough(heapData->get() == nullptr));
heapData->set(initialObj);
/* Store the pointer as an integer so that the hazard analysis will miss it. */

Просмотреть файл

@ -5769,7 +5769,7 @@ DumpProperty(JSObject *obj, Shape &shape)
jsid id = shape.propid();
uint8_t attrs = shape.attributes();
fprintf(stderr, " ((JSShape *) %p) ", (void *) &shape);
fprintf(stderr, " ((js::Shape *) %p) ", (void *) &shape);
if (attrs & JSPROP_ENUMERATE) fprintf(stderr, "enumerate ");
if (attrs & JSPROP_READONLY) fprintf(stderr, "readonly ");
if (attrs & JSPROP_PERMANENT) fprintf(stderr, "permanent ");
@ -5785,10 +5785,8 @@ DumpProperty(JSObject *obj, Shape &shape)
else if (!shape.hasDefaultSetter())
fprintf(stderr, "setterOp=%p ", JS_FUNC_TO_DATA_PTR(void *, shape.setterOp()));
if (JSID_IS_ATOM(id))
JSID_TO_STRING(id)->dump();
else if (JSID_IS_INT(id))
fprintf(stderr, "%d", (int) JSID_TO_INT(id));
if (JSID_IS_ATOM(id) || JSID_IS_INT(id) || JSID_IS_SYMBOL(id))
dumpValue(js::IdToValue(id));
else
fprintf(stderr, "unknown jsid %p", (void *) JSID_BITS(id));

Просмотреть файл

@ -292,7 +292,7 @@ PreprocessValue(JSContext *cx, HandleObject holder, KeyType key, MutableHandleVa
static inline bool
IsFilteredValue(const Value &v)
{
return v.isUndefined() || IsCallable(v);
return v.isUndefined() || v.isSymbol() || IsCallable(v);
}
/* ES5 15.12.3 JO. */

Просмотреть файл

@ -0,0 +1,19 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/ */
// JSON.stringify ignores symbol-keyed properties, even enumerable ones.
var obj = {a: 1};
obj[Symbol.for("ponies")] = {toJSON: function () { throw "fit"; }};
obj[Symbol.iterator] = {toJSON: function () { throw "fit"; }};
assertEq(JSON.stringify(obj), '{"a":1}');
var replacer = function (k, v) {
if (typeof k === "symbol")
throw "fit";
return v;
};
assertEq(JSON.stringify(obj, replacer), '{"a":1}');
if (typeof reportCompare === 'function')
reportCompare(0, 0, 'ok');

Просмотреть файл

@ -0,0 +1,33 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/ */
// To JSON.stringify, symbols are the same as undefined.
var symbols = [
Symbol(),
Symbol.for("ponies"),
Symbol.iterator
];
for (var sym of symbols) {
assertEq(JSON.stringify(sym), undefined);
assertEq(JSON.stringify([sym]), "[null]");
// JSON.stringify skips symbol-valued properties!
assertEq(JSON.stringify({x: sym}), '{}');
// However such properties are passed to the replacerFunction if any.
var replacer = function (key, val) {
assertEq(typeof this, "object");
if (typeof val === "symbol") {
assertEq(val, sym);
return "ding";
}
return val;
};
assertEq(JSON.stringify(sym, replacer), '"ding"');
assertEq(JSON.stringify({x: sym}, replacer), '{"x":"ding"}');
}
if (typeof reportCompare === 'function')
reportCompare(0, 0, 'ok');

Просмотреть файл

@ -0,0 +1,26 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/ */
// Symbol-to-number type conversions involving typed arrays.
var tests = [
{T: Uint8Array, result: 0},
{T: Uint8ClampedArray, result: 0},
{T: Int16Array, result: 0},
{T: Float32Array, result: NaN}
];
for (var {T, result} of tests) {
// Typed array constructors convert symbols to NaN or 0.
var arr = new T([Symbol("a")]);
assertEq(arr.length, 1);
assertEq(arr[0], result);
// Assignment also converts symbols to NaN or 0.
arr[0] = 0;
assertEq(arr[0] = Symbol.iterator, Symbol.iterator);
assertEq(arr[0], result);
}
if (typeof reportCompare === "function")
reportCompare(0, 0);

Просмотреть файл

@ -84,6 +84,7 @@ class Test:
self.jitflags = [] # jit flags to enable
self.slow = False # True means the test is slow-running
self.allow_oom = False # True means that OOM is not considered a failure
self.allow_unhandlable_oom = False # True means CrashAtUnhandlableOOM is not considered a failure
self.allow_overrecursed = False # True means that hitting recursion the
# limits is not considered a failure.
self.valgrind = False # True means run under valgrind
@ -96,6 +97,7 @@ class Test:
t.jitflags = self.jitflags[:]
t.slow = self.slow
t.allow_oom = self.allow_oom
t.allow_unhandlable_oom = self.allow_unhandlable_oom
t.allow_overrecursed = self.allow_overrecursed
t.valgrind = self.valgrind
t.tz_pacific = self.tz_pacific
@ -141,6 +143,8 @@ class Test:
test.slow = True
elif name == 'allow-oom':
test.allow_oom = True
elif name == 'allow-unhandlable-oom':
test.allow_unhandlable_oom = True
elif name == 'allow-overrecursed':
test.allow_overrecursed = True
elif name == 'valgrind':
@ -390,6 +394,11 @@ def check_output(out, err, rc, timed_out, test):
if test.allow_oom and 'out of memory' in err and 'Assertion failure' not in err:
return True
# Allow a non-zero exit code if we want to allow unhandlable OOM, but
# only if we actually got unhandlable OOM.
if test.allow_unhandlable_oom and 'Assertion failure: [unhandlable oom]' in err:
return True
# Allow a non-zero exit code if we want to all too-much-recursion and
# the test actually over-recursed.
if test.allow_overrecursed and 'too much recursion' in err and 'Assertion failure' not in err:

Просмотреть файл

@ -883,7 +883,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
static bool
canConvertInfallibly(const Value &v)
{
return v.isNumber() || v.isBoolean() || v.isNull() || v.isUndefined();
return v.isNumber() || v.isBoolean() || v.isNull() || v.isUndefined() || v.isSymbol();
}
static NativeType
@ -898,7 +898,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
if (v.isNull())
return NativeType(0);
MOZ_ASSERT(v.isUndefined());
MOZ_ASSERT(v.isUndefined() || v.isSymbol());
return ArrayTypeIsFloatingPoint() ? NativeType(GenericNaN()) : NativeType(0);
}

Просмотреть файл

@ -249,16 +249,6 @@ nsDisplayCanvasBackgroundColor::WriteDebugInfo(nsACString& aTo)
}
#endif
static void BlitSurface(gfxContext* aDest, const gfxRect& aRect, gfxASurface* aSource)
{
aDest->Translate(gfxPoint(aRect.x, aRect.y));
aDest->SetSource(aSource);
aDest->NewPath();
aDest->Rectangle(gfxRect(0, 0, aRect.width, aRect.height));
aDest->Fill();
aDest->Translate(-gfxPoint(aRect.x, aRect.y));
}
static void BlitSurface(DrawTarget* aDest, const gfxRect& aRect, DrawTarget* aSource)
{
RefPtr<SourceSurface> source = aSource->Snapshot();
@ -277,9 +267,7 @@ nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
nsRefPtr<nsRenderingContext> context;
nsRefPtr<gfxContext> dest = aCtx->ThebesContext();
nsRefPtr<gfxASurface> surf;
RefPtr<DrawTarget> dt;
nsRefPtr<gfxContext> ctx;
gfxRect destRect;
#ifndef MOZ_GFX_OPTIMIZE_MOBILE
if (IsSingleFixedPositionImage(aBuilder, bgClipRect, &destRect) &&
@ -288,31 +276,15 @@ nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
// Snap image rectangle to nearest pixel boundaries. This is the right way
// to snap for this context, because we checked HasNonIntegerTranslation above.
destRect.Round();
if (dest->IsCairo()) {
surf = static_cast<gfxASurface*>(Frame()->Properties().Get(nsIFrame::CachedBackgroundImage()));
nsRefPtr<gfxASurface> destSurf = dest->CurrentSurface();
if (surf && surf->GetType() == destSurf->GetType()) {
BlitSurface(dest, destRect, surf);
return;
}
surf = destSurf->CreateSimilarSurface(
gfxContentType::COLOR_ALPHA,
gfxIntSize(ceil(destRect.width), ceil(destRect.height)));
} else {
dt = static_cast<DrawTarget*>(Frame()->Properties().Get(nsIFrame::CachedBackgroundImageDT()));
DrawTarget* destDT = dest->GetDrawTarget();
if (dt) {
BlitSurface(destDT, destRect, dt);
return;
}
dt = destDT->CreateSimilarDrawTarget(IntSize(ceil(destRect.width), ceil(destRect.height)), SurfaceFormat::B8G8R8A8);
dt = static_cast<DrawTarget*>(Frame()->Properties().Get(nsIFrame::CachedBackgroundImageDT()));
DrawTarget* destDT = dest->GetDrawTarget();
if (dt) {
BlitSurface(destDT, destRect, dt);
return;
}
if (surf || dt) {
if (surf) {
ctx = new gfxContext(surf);
} else {
ctx = new gfxContext(dt);
}
dt = destDT->CreateSimilarDrawTarget(IntSize(ceil(destRect.width), ceil(destRect.height)), SurfaceFormat::B8G8R8A8);
if (dt) {
nsRefPtr<gfxContext> ctx = new gfxContext(dt);
ctx->Translate(-gfxPoint(destRect.x, destRect.y));
context = new nsRenderingContext();
context->Init(aCtx->DeviceContext(), ctx);
@ -321,15 +293,10 @@ nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
#endif
PaintInternal(aBuilder,
(surf || dt) ? context.get() : aCtx,
(surf || dt) ? bgClipRect: mVisibleRect,
dt ? context.get() : aCtx,
dt ? bgClipRect: mVisibleRect,
&bgClipRect);
if (surf) {
BlitSurface(dest, destRect, surf);
frame->Properties().Set(nsIFrame::CachedBackgroundImage(),
surf.forget().take());
}
if (dt) {
BlitSurface(dest->GetDrawTarget(), destRect, dt);
frame->Properties().Set(nsIFrame::CachedBackgroundImageDT(), dt.forget().drop());

Просмотреть файл

@ -298,30 +298,18 @@ nsFilterInstance::ComputeNeededBoxes()
nsresult
nsFilterInstance::BuildSourcePaint(SourceInfo *aSource,
gfxASurface* aTargetSurface,
DrawTarget* aTargetDT)
{
nsIntRect neededRect = aSource->mNeededBounds;
RefPtr<DrawTarget> offscreenDT;
nsRefPtr<gfxASurface> offscreenSurface;
nsRefPtr<gfxContext> ctx;
if (aTargetSurface) {
offscreenSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(
neededRect.Size().ToIntSize(), gfxContentType::COLOR_ALPHA);
if (!offscreenSurface || offscreenSurface->CairoStatus()) {
return NS_ERROR_OUT_OF_MEMORY;
}
ctx = new gfxContext(offscreenSurface);
} else {
offscreenDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
RefPtr<DrawTarget> offscreenDT =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
ToIntSize(neededRect.Size()), SurfaceFormat::B8G8R8A8);
if (!offscreenDT) {
return NS_ERROR_OUT_OF_MEMORY;
}
ctx = new gfxContext(offscreenDT);
if (!offscreenDT) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsRefPtr<gfxContext> ctx = new gfxContext(offscreenDT);
ctx->Translate(-neededRect.TopLeft());
nsRefPtr<nsRenderingContext> tmpCtx(new nsRenderingContext());
@ -348,63 +336,46 @@ nsFilterInstance::BuildSourcePaint(SourceInfo *aSource,
}
gfx->Restore();
if (offscreenSurface) {
aSource->mSourceSurface =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTargetDT, offscreenSurface);
} else {
aSource->mSourceSurface = offscreenDT->Snapshot();
}
aSource->mSourceSurface = offscreenDT->Snapshot();
aSource->mSurfaceRect = ToIntRect(neededRect);
return NS_OK;
}
nsresult
nsFilterInstance::BuildSourcePaints(gfxASurface* aTargetSurface,
DrawTarget* aTargetDT)
nsFilterInstance::BuildSourcePaints(DrawTarget* aTargetDT)
{
nsresult rv = NS_OK;
if (!mFillPaint.mNeededBounds.IsEmpty()) {
rv = BuildSourcePaint(&mFillPaint, aTargetSurface, aTargetDT);
rv = BuildSourcePaint(&mFillPaint, aTargetDT);
NS_ENSURE_SUCCESS(rv, rv);
}
if (!mStrokePaint.mNeededBounds.IsEmpty()) {
rv = BuildSourcePaint(&mStrokePaint, aTargetSurface, aTargetDT);
rv = BuildSourcePaint(&mStrokePaint, aTargetDT);
NS_ENSURE_SUCCESS(rv, rv);
}
return rv;
}
nsresult
nsFilterInstance::BuildSourceImage(gfxASurface* aTargetSurface,
DrawTarget* aTargetDT)
nsFilterInstance::BuildSourceImage(DrawTarget* aTargetDT)
{
nsIntRect neededRect = mSourceGraphic.mNeededBounds;
if (neededRect.IsEmpty()) {
return NS_OK;
}
RefPtr<DrawTarget> offscreenDT;
nsRefPtr<gfxASurface> offscreenSurface;
nsRefPtr<gfxContext> ctx;
if (aTargetSurface) {
offscreenSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(
neededRect.Size().ToIntSize(), gfxContentType::COLOR_ALPHA);
if (!offscreenSurface || offscreenSurface->CairoStatus()) {
return NS_ERROR_OUT_OF_MEMORY;
}
ctx = new gfxContext(offscreenSurface);
} else {
offscreenDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
RefPtr<DrawTarget> offscreenDT =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
ToIntSize(neededRect.Size()), SurfaceFormat::B8G8R8A8);
if (!offscreenDT) {
return NS_ERROR_OUT_OF_MEMORY;
}
ctx = new gfxContext(offscreenDT);
if (!offscreenDT) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsRefPtr<gfxContext> ctx = new gfxContext(offscreenDT);
ctx->Translate(-neededRect.TopLeft());
nsRefPtr<nsRenderingContext> tmpCtx(new nsRenderingContext());
@ -431,16 +402,7 @@ nsFilterInstance::BuildSourceImage(gfxASurface* aTargetSurface,
tmpCtx->ThebesContext()->Multiply(deviceToFilterSpace);
mPaintCallback->Paint(tmpCtx, mTargetFrame, &dirty, mTransformRoot);
RefPtr<SourceSurface> sourceGraphicSource;
if (offscreenSurface) {
sourceGraphicSource =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTargetDT, offscreenSurface);
} else {
sourceGraphicSource = offscreenDT->Snapshot();
}
mSourceGraphic.mSourceSurface = sourceGraphicSource;
mSourceGraphic.mSourceSurface = offscreenDT->Snapshot();
mSourceGraphic.mSurfaceRect = ToIntRect(neededRect);
return NS_OK;
@ -457,34 +419,18 @@ nsFilterInstance::Render(gfxContext* aContext)
}
Matrix oldDTMatrix;
nsRefPtr<gfxASurface> resultImage;
RefPtr<DrawTarget> dt;
if (aContext->IsCairo()) {
resultImage =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(filterRect.Size().ToIntSize(),
gfxContentType::COLOR_ALPHA);
if (!resultImage || resultImage->CairoStatus())
return NS_ERROR_OUT_OF_MEMORY;
// Create a Cairo DrawTarget around resultImage.
dt = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(
resultImage, ToIntSize(filterRect.Size()));
} else {
// When we have a DrawTarget-backed context, we can call DrawFilter
// directly on the target DrawTarget and don't need a temporary DT.
dt = aContext->GetDrawTarget();
oldDTMatrix = dt->GetTransform();
Matrix matrix = ToMatrix(ctm);
matrix.Translate(filterRect.x, filterRect.y);
dt->SetTransform(matrix * oldDTMatrix);
}
RefPtr<DrawTarget> dt = aContext->GetDrawTarget();
oldDTMatrix = dt->GetTransform();
Matrix matrix = ToMatrix(ctm);
matrix.Translate(filterRect.x, filterRect.y);
dt->SetTransform(matrix * oldDTMatrix);
ComputeNeededBoxes();
nsresult rv = BuildSourceImage(resultImage, dt);
nsresult rv = BuildSourceImage(dt);
if (NS_FAILED(rv))
return rv;
rv = BuildSourcePaints(resultImage, dt);
rv = BuildSourcePaints(dt);
if (NS_FAILED(rv))
return rv;
@ -498,16 +444,7 @@ nsFilterInstance::Render(gfxContext* aContext)
mStrokePaint.mSourceSurface, mStrokePaint.mSurfaceRect,
mInputImages);
if (resultImage) {
aContext->Save();
aContext->Multiply(ctm);
aContext->Translate(filterRect.TopLeft());
aContext->SetSource(resultImage);
aContext->Paint();
aContext->Restore();
} else {
dt->SetTransform(oldDTMatrix);
}
dt->SetTransform(oldDTMatrix);
return NS_OK;
}

Просмотреть файл

@ -183,7 +183,6 @@ private:
* nodes
*/
nsresult BuildSourcePaint(SourceInfo *aPrimitive,
gfxASurface* aTargetSurface,
DrawTarget* aTargetDT);
/**
@ -191,15 +190,13 @@ private:
* nodes, fills its contents and assigns it to mFillPaint.mSourceSurface and
* mStrokePaint.mSourceSurface respectively.
*/
nsresult BuildSourcePaints(gfxASurface* aTargetSurface,
DrawTarget* aTargetDT);
nsresult BuildSourcePaints(DrawTarget* aTargetDT);
/**
* Creates the SourceSurface for the SourceGraphic graph node, paints its
* contents, and assigns it to mSourceGraphic.mSourceSurface.
*/
nsresult BuildSourceImage(gfxASurface* aTargetSurface,
DrawTarget* aTargetDT);
nsresult BuildSourceImage(DrawTarget* aTargetDT);
/**
* Build the list of FilterPrimitiveDescriptions that describes the filter's

Просмотреть файл

@ -91,6 +91,25 @@ nsSVGInnerSVGFrame::PaintSVG(nsRenderingContext *aContext,
return nsSVGInnerSVGFrameBase::PaintSVG(aContext, aDirtyRect);
}
nsRect
nsSVGInnerSVGFrame::GetCoveredRegion()
{
float x, y, w, h;
static_cast<SVGSVGElement*>(mContent)->
GetAnimatedLengthValues(&x, &y, &w, &h, nullptr);
if (w < 0.0f) w = 0.0f;
if (h < 0.0f) h = 0.0f;
// GetCanvasTM includes the x,y translation
nsRect bounds = nsSVGUtils::ToCanvasBounds(gfxRect(0.0, 0.0, w, h),
GetCanvasTM(FOR_OUTERSVG_TM),
PresContext());
if (!StyleDisplay()->IsScrollableOverflow()) {
bounds.UnionRect(bounds, nsSVGUtils::GetCoveredRegion(mFrames));
}
return bounds;
}
void
nsSVGInnerSVGFrame::ReflowSVG()
{

Просмотреть файл

@ -56,6 +56,7 @@ public:
virtual nsresult PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
virtual nsRect GetCoveredRegion() MOZ_OVERRIDE;
virtual void ReflowSVG() MOZ_OVERRIDE;
virtual void NotifySVGChanged(uint32_t aFlags) MOZ_OVERRIDE;
virtual nsIFrame* GetFrameForPoint(const nsPoint &aPoint) MOZ_OVERRIDE;

Просмотреть файл

@ -112,7 +112,6 @@ public:
virtual nsresult PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
virtual SVGBBox GetBBoxContribution(const Matrix &aToBBoxUserspace,
uint32_t aFlags) MOZ_OVERRIDE;

Просмотреть файл

@ -7,9 +7,12 @@
#include "nsSVGPathGeometryFrame.h"
// Keep others in (case-insensitive) order:
#include "gfx2DGlue.h"
#include "gfxContext.h"
#include "gfxPlatform.h"
#include "gfxSVGGlyphs.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
#include "nsDisplayList.h"
#include "nsGkAtoms.h"
#include "nsRenderingContext.h"
@ -20,6 +23,7 @@
#include "nsSVGUtils.h"
#include "mozilla/ArrayUtils.h"
#include "SVGAnimatedTransformList.h"
#include "SVGContentUtils.h"
#include "SVGGraphicsElement.h"
using namespace mozilla;
@ -234,48 +238,77 @@ nsSVGPathGeometryFrame::PaintSVG(nsRenderingContext *aContext,
nsIFrame*
nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint)
{
gfxMatrix canvasTM = GetCanvasTM(FOR_HIT_TESTING);
if (canvasTM.IsSingular()) {
gfxMatrix hitTestingTM = GetCanvasTM(FOR_HIT_TESTING);
if (hitTestingTM.IsSingular()) {
return nullptr;
}
uint16_t fillRule, hitTestFlags;
FillRule fillRule;
uint16_t hitTestFlags;
if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) {
hitTestFlags = SVG_HIT_TEST_FILL;
fillRule = StyleSVG()->mClipRule;
fillRule = StyleSVG()->mClipRule == NS_STYLE_FILL_RULE_NONZERO
? FillRule::FILL_WINDING : FillRule::FILL_EVEN_ODD;
} else {
hitTestFlags = GetHitTestFlags();
nsPoint point =
nsSVGUtils::TransformOuterSVGPointToChildFrame(aPoint, canvasTM, PresContext());
nsSVGUtils::TransformOuterSVGPointToChildFrame(aPoint, hitTestingTM, PresContext());
if (!hitTestFlags || ((hitTestFlags & SVG_HIT_TEST_CHECK_MRECT) &&
!mRect.Contains(point)))
!mRect.Contains(point))) {
return nullptr;
fillRule = StyleSVG()->mFillRule;
}
fillRule = StyleSVG()->mFillRule == NS_STYLE_FILL_RULE_NONZERO
? FillRule::FILL_WINDING : FillRule::FILL_EVEN_ODD;
}
bool isHit = false;
nsRefPtr<gfxContext> tmpCtx =
new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
nsSVGPathGeometryElement* content =
static_cast<nsSVGPathGeometryElement*>(mContent);
GeneratePath(tmpCtx, ToMatrix(canvasTM));
gfxPoint userSpacePoint =
tmpCtx->DeviceToUser(gfxPoint(aPoint.x, aPoint.y) / PresContext()->AppUnitsPerCSSPixel());
// Using ScreenReferenceDrawTarget() opens us to Moz2D backend specific hit-
// testing bugs. Maybe we should use a BackendType::CAIRO DT for hit-testing
// so that we get more consistent/backwards compatible results?
RefPtr<DrawTarget> drawTarget =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
RefPtr<PathBuilder> builder =
drawTarget->CreatePathBuilder(fillRule);
RefPtr<Path> path = content->BuildPath(builder);
if (!path) {
return nullptr; // no path, so we don't paint anything that can be hit
}
if (fillRule == NS_STYLE_FILL_RULE_EVENODD)
tmpCtx->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
else
tmpCtx->SetFillRule(gfxContext::FILL_RULE_WINDING);
if (!hitTestingTM.IsIdentity()) {
// We'll only get here if we don't have a nsDisplayItem that has called us
// (for example, if we're a NS_FRAME_IS_NONDISPLAY frame under a clipPath).
RefPtr<PathBuilder> builder =
path->TransformedCopyToBuilder(ToMatrix(hitTestingTM), fillRule);
path = builder->Finish();
}
if (hitTestFlags & SVG_HIT_TEST_FILL)
isHit = tmpCtx->PointInFill(userSpacePoint);
int32_t appUnitsPerCSSPx = PresContext()->AppUnitsPerCSSPixel();
Point userSpacePoint = Point(Float(aPoint.x) / appUnitsPerCSSPx,
Float(aPoint.y) / appUnitsPerCSSPx);
if (hitTestFlags & SVG_HIT_TEST_FILL) {
isHit = path->ContainsPoint(userSpacePoint, Matrix());
}
if (!isHit && (hitTestFlags & SVG_HIT_TEST_STROKE)) {
nsSVGUtils::SetupCairoStrokeGeometry(this, tmpCtx);
// tmpCtx's matrix may have transformed by SetupCairoStrokeGeometry
// if there is a non-scaling stroke. We need to transform userSpacePoint
// so that everything is using the same co-ordinate system.
userSpacePoint =
nsSVGUtils::GetStrokeTransform(this).Invert().Transform(userSpacePoint);
isHit = tmpCtx->PointInStroke(userSpacePoint);
SVGContentUtils::AutoStrokeOptions stroke;
SVGContentUtils::GetStrokeOptions(&stroke, content, StyleContext(), nullptr);
Matrix nonScalingStrokeMatrix =
ToMatrix(nsSVGUtils::GetStrokeTransform(this));
if (!nonScalingStrokeMatrix.IsIdentity()) {
// We need to transform the path back into the appropriate ancestor
// coordinate system in order for non-scaled stroke to be correct.
// Naturally we also need to transform the point into the same
// coordinate system in order to hit-test against the path.
nonScalingStrokeMatrix.Invert();
userSpacePoint = ToMatrix(hitTestingTM) * nonScalingStrokeMatrix * userSpacePoint;
RefPtr<PathBuilder> builder =
path->TransformedCopyToBuilder(nonScalingStrokeMatrix, fillRule);
path = builder->Finish();
}
isHit = path->StrokeContainsPoint(stroke, userSpacePoint, Matrix());
}
if (isHit && nsSVGUtils::HitTestClip(this, aPoint))
@ -416,8 +449,21 @@ nsSVGPathGeometryFrame::GetBBoxContribution(const Matrix &aToBBoxUserspace,
return bbox;
}
nsRefPtr<gfxContext> tmpCtx =
new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
RefPtr<DrawTarget> tmpDT;
#ifdef XP_WIN
// Unfortunately D2D backed DrawTarget produces bounds with rounding errors
// when whole number results are expected, even in the case of trivial
// calculations. To avoid that and meet the expectations of web content we
// have to use a CAIRO DrawTarget. The most efficient way to do that is to
// wrap the cached cairo_surface_t from ScreenReferenceSurface():
nsRefPtr<gfxASurface> refSurf =
gfxPlatform::GetPlatform()->ScreenReferenceSurface();
tmpDT = gfxPlatform::GetPlatform()->
CreateDrawTargetForSurface(refSurf, IntSize(1, 1));
#else
tmpDT = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
#endif
nsRefPtr<gfxContext> tmpCtx = new gfxContext(tmpDT);
GeneratePath(tmpCtx, aToBBoxUserspace);
tmpCtx->IdentityMatrix();

Просмотреть файл

@ -356,9 +356,13 @@ nsSVGUtils::GetOuterSVGFrameAndCoveredRegion(nsIFrame* aFrame, nsRect* aRect)
nsISVGChildFrame* svg = do_QueryFrame(aFrame);
if (!svg)
return nullptr;
nsSVGOuterSVGFrame* outer = GetOuterSVGFrame(aFrame);
if (outer == svg) {
return nullptr;
}
*aRect = (aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY) ?
nsRect(0, 0, 0, 0) : svg->GetCoveredRegion();
return GetOuterSVGFrame(aFrame);
return outer;
}
gfxMatrix

Просмотреть файл

@ -19,11 +19,13 @@ public:
NS_DECL_NSIOBSERVER
nsNetworkLinkService();
virtual ~nsNetworkLinkService();
nsresult Init();
nsresult Shutdown();
protected:
virtual ~nsNetworkLinkService();
private:
bool mLinkUp;
bool mStatusKnown;

Просмотреть файл

@ -12,12 +12,14 @@ class nsUserInfo: public nsIUserInfo
{
public:
nsUserInfo();
virtual ~nsUserInfo() {}
NS_DECL_ISUPPORTS
NS_DECL_NSIUSERINFO
nsresult GetPrimaryEmailAddress(nsCString &aEmailAddress);
protected:
virtual ~nsUserInfo() {}
};
#endif /* __nsUserInfo_h */

Просмотреть файл

@ -30,13 +30,15 @@ public:
NS_DECL_NSITIMERCALLBACK
OSXNotificationCenter();
virtual ~OSXNotificationCenter();
nsresult Init();
void CloseAlertCocoaString(NSString *aAlertName);
void OnClick(NSString *aAlertName);
void ShowPendingNotification(OSXNotificationInfo *osxni);
protected:
virtual ~OSXNotificationCenter();
private:
mozNotificationCenterDelegate *mDelegate;
nsTArray<nsRefPtr<OSXNotificationInfo> > mActiveAlerts;

Просмотреть файл

@ -49,6 +49,8 @@ public:
NS_DECL_ISUPPORTS;
private:
~MacWakeLockListener() {}
IOPMAssertionID mAssertionID = kIOPMNullAssertionID;
NS_IMETHOD Callback(const nsAString& aTopic, const nsAString& aState) {

Просмотреть файл

@ -16,6 +16,8 @@ public:
NS_DECL_NSIBIDIKEYBOARD
nsBidiKeyboard();
protected:
virtual ~nsBidiKeyboard();
};

Просмотреть файл

@ -35,6 +35,8 @@ public:
void Done();
private:
~nsColorPicker();
static NSColor* GetNSColorFromHexString(const nsAString& aColor);
static void GetHexStringFromNSColor(NSColor* aColor, nsAString& aResult);

Просмотреть файл

@ -97,6 +97,10 @@ NS_IMPL_ISUPPORTS(nsColorPicker, nsIColorPicker)
NSColorPanelWrapper* nsColorPicker::sColorPanelWrapper = nullptr;
nsColorPicker::~nsColorPicker()
{
}
NS_IMETHODIMP
nsColorPicker::Init(nsIDOMWindow* aParent, const nsAString& aTitle,
const nsAString& aInitialColor)

Просмотреть файл

@ -21,7 +21,6 @@ class nsFilePicker : public nsBaseFilePicker
{
public:
nsFilePicker();
virtual ~nsFilePicker();
NS_DECL_ISUPPORTS
@ -46,6 +45,7 @@ public:
NSArray* GetFilterList();
protected:
virtual ~nsFilePicker();
virtual void InitNative(nsIWidget *aParent, const nsAString& aTitle);

Просмотреть файл

@ -15,13 +15,14 @@ class nsMacDockSupport : public nsIMacDockSupport, public nsITaskbarProgress
{
public:
nsMacDockSupport();
virtual ~nsMacDockSupport();
NS_DECL_ISUPPORTS
NS_DECL_NSIMACDOCKSUPPORT
NS_DECL_NSITASKBARPROGRESS
protected:
virtual ~nsMacDockSupport();
nsCOMPtr<nsIStandaloneNativeMenu> mDockMenu;
nsString mBadgeText;

Просмотреть файл

@ -11,10 +11,12 @@
class nsMacWebAppUtils : public nsIMacWebAppUtils {
public:
nsMacWebAppUtils() {}
virtual ~nsMacWebAppUtils() {}
NS_DECL_ISUPPORTS
NS_DECL_NSIMACWEBAPPUTILS
protected:
virtual ~nsMacWebAppUtils() {}
};
#endif //_MAC_WEB_APP_UTILS_H_

Просмотреть файл

@ -28,9 +28,11 @@ public:
NS_DECL_ISUPPORTS
nsNativeMenuServiceX() {}
virtual ~nsNativeMenuServiceX() {}
NS_IMETHOD CreateNativeMenuBar(nsIWidget* aParent, nsIContent* aMenuBarNode);
protected:
virtual ~nsNativeMenuServiceX() {}
};
@interface NSMenu (Undocumented)

Просмотреть файл

@ -27,7 +27,6 @@ class nsMenuGroupOwnerX : public nsMenuObjectX, public nsIMutationObserver
{
public:
nsMenuGroupOwnerX();
virtual ~nsMenuGroupOwnerX();
nsresult Create(nsIContent * aContent);
@ -42,6 +41,8 @@ public:
NS_DECL_NSIMUTATIONOBSERVER
protected:
virtual ~nsMenuGroupOwnerX();
nsChangeObserver* LookupContentChangeObserver(nsIContent* aContent);
uint32_t mCurrentCommandID; // unique command id (per menu-bar) to

Просмотреть файл

@ -19,7 +19,6 @@ class nsPrintDialogServiceX : public nsIPrintDialogService
{
public:
nsPrintDialogServiceX();
virtual ~nsPrintDialogServiceX();
NS_DECL_ISUPPORTS
@ -28,6 +27,9 @@ public:
nsIWebBrowserPrint *aWebBrowserPrint);
NS_IMETHODIMP ShowPageSetup(nsIDOMWindow *aParent,
nsIPrintSettings *aSettings);
protected:
virtual ~nsPrintDialogServiceX();
};
@interface PrintPanelAccessoryView : NSView

Просмотреть файл

@ -17,11 +17,13 @@ class nsScreenManagerCocoa : public nsIScreenManager
{
public:
nsScreenManagerCocoa();
virtual ~nsScreenManagerCocoa();
NS_DECL_ISUPPORTS
NS_DECL_NSISCREENMANAGER
protected:
virtual ~nsScreenManagerCocoa();
private:
nsScreenCocoa *ScreenForCocoaScreen(NSScreen *screen);

Просмотреть файл

@ -15,11 +15,13 @@ class nsSound : public nsISound,
{
public:
nsSound();
virtual ~nsSound();
NS_DECL_ISUPPORTS
NS_DECL_NSISOUND
NS_DECL_NSISTREAMLOADEROBSERVER
protected:
virtual ~nsSound();
};
#endif // nsSound_h_

Просмотреть файл

@ -14,7 +14,6 @@ class nsStandaloneNativeMenu : public nsMenuGroupOwnerX, public nsIStandaloneNat
{
public:
nsStandaloneNativeMenu();
virtual ~nsStandaloneNativeMenu();
NS_DECL_ISUPPORTS
NS_DECL_NSISTANDALONENATIVEMENU
@ -26,6 +25,8 @@ public:
nsMenuX * GetMenuXObject() { return mMenu; }
protected:
virtual ~nsStandaloneNativeMenu();
nsMenuX * mMenu;
};

Просмотреть файл

@ -25,7 +25,6 @@ class nsBaseClipboard : public nsIClipboard
public:
nsBaseClipboard();
virtual ~nsBaseClipboard();
//nsISupports
NS_DECL_ISUPPORTS
@ -34,6 +33,7 @@ public:
NS_DECL_NSICLIPBOARD
protected:
virtual ~nsBaseClipboard();
NS_IMETHOD SetNativeClipboardData ( int32_t aWhichClipboard ) = 0;
NS_IMETHOD GetNativeClipboardData ( nsITransferable * aTransferable, int32_t aWhichClipboard ) = 0;

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше