--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -2,18 +2,21 @@
/* 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/. */
/* rendering object for replaced elements with image data */
#include "nsImageFrame.h"
+#include "gfx2DGlue.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/EventStates.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/Helpers.h"
#include "mozilla/MouseEvents.h"
#include "nsCOMPtr.h"
#include "nsIImageLoadingContent.h"
#include "nsString.h"
#include "nsPrintfCString.h"
#include "nsPresContext.h"
#include "nsRenderingContext.h"
@@ -65,16 +68,17 @@
#include "nsBlockFrame.h"
#include "nsStyleStructInlines.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/Link.h"
using namespace mozilla;
+using namespace mozilla::gfx;
// sizes (pixels) for image icon, padding and border frame
#define ICON_SIZE (16)
#define ICON_PADDING (3)
#define ALT_BORDER_WIDTH (1)
//we must add hooks soon
@@ -1287,29 +1291,29 @@ nsImageFrame::DisplayAltFeedback(nsRende
}
}
aRenderingContext.ThebesContext()->Restore();
}
#ifdef DEBUG
static void PaintDebugImageMap(nsIFrame* aFrame, nsRenderingContext* aCtx,
- const nsRect& aDirtyRect, nsPoint aPt) {
+ const nsRect& aDirtyRect, nsPoint aPt)
+{
nsImageFrame* f = static_cast<nsImageFrame*>(aFrame);
nsRect inner = f->GetInnerArea() + aPt;
-
- aCtx->SetColor(NS_RGB(0, 0, 0));
- aCtx->ThebesContext()->Save();
gfxPoint devPixelOffset =
nsLayoutUtils::PointToGfxPoint(inner.TopLeft(),
aFrame->PresContext()->AppUnitsPerDevPixel());
- aCtx->ThebesContext()->SetMatrix(
- aCtx->ThebesContext()->CurrentMatrix().Translate(devPixelOffset));
- f->GetImageMap()->Draw(aFrame, *aCtx);
- aCtx->ThebesContext()->Restore();
+ DrawTarget* drawTarget = aCtx->GetDrawTarget();
+ AutoRestoreTransform autoRestoreTransform(drawTarget);
+ drawTarget->SetTransform(
+ drawTarget->GetTransform().PreTranslate(ToPoint(devPixelOffset)));
+ f->GetImageMap()->Draw(aFrame, *drawTarget,
+ ColorPattern(Color(0.f, 0.f, 0.f, 1.f)));
}
#endif
void
nsDisplayImage::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) {
uint32_t flags = imgIContainer::FLAG_NONE;
if (aBuilder->ShouldSyncDecodeImages()) {
@@ -1453,42 +1457,46 @@ nsDisplayImage::ConfigureLayer(ImageLaye
aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
}
void
nsImageFrame::PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
const nsRect& aDirtyRect, imgIContainer* aImage,
uint32_t aFlags)
{
+ DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
+
// Render the image into our content area (the area inside
// the borders and padding)
NS_ASSERTION(GetInnerArea().width == mComputedSize.width, "bad width");
nsRect inner = GetInnerArea() + aPt;
nsRect dest(inner.TopLeft(), mComputedSize);
dest.y -= GetContinuationOffset();
nsLayoutUtils::DrawSingleImage(&aRenderingContext, PresContext(), aImage,
nsLayoutUtils::GetGraphicsFilterForFrame(this), dest, aDirtyRect,
nullptr, aFlags);
nsImageMap* map = GetImageMap();
- if (nullptr != map) {
- aRenderingContext.ThebesContext()->Save();
+ if (map) {
gfxPoint devPixelOffset =
nsLayoutUtils::PointToGfxPoint(inner.TopLeft(),
PresContext()->AppUnitsPerDevPixel());
- aRenderingContext.ThebesContext()->SetMatrix(
- aRenderingContext.ThebesContext()->CurrentMatrix().Translate(devPixelOffset));
- aRenderingContext.SetColor(NS_RGB(255, 255, 255));
- aRenderingContext.SetLineStyle(nsLineStyle_kSolid);
- map->Draw(this, aRenderingContext);
- aRenderingContext.SetColor(NS_RGB(0, 0, 0));
- aRenderingContext.SetLineStyle(nsLineStyle_kDotted);
- map->Draw(this, aRenderingContext);
- aRenderingContext.ThebesContext()->Restore();
+ AutoRestoreTransform autoRestoreTransform(drawTarget);
+ drawTarget->SetTransform(
+ drawTarget->GetTransform().PreTranslate(ToPoint(devPixelOffset)));
+
+ // solid white stroke:
+ map->Draw(this, *drawTarget, ColorPattern(Color(1.f, 1.f, 1.f, 1.f)));
+
+ // then dashed black stroke over the top:
+ StrokeOptions strokeOptions;
+ nsLayoutUtils::InitDashPattern(strokeOptions, NS_STYLE_BORDER_STYLE_DOTTED);
+ map->Draw(this, *drawTarget, ColorPattern(Color(0.f, 0.f, 0.f, 1.f)),
+ strokeOptions);
}
}
void
nsImageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
--- a/layout/generic/nsImageMap.cpp
+++ b/layout/generic/nsImageMap.cpp
@@ -4,16 +4,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* code for HTML client-side image maps */
#include "nsImageMap.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
+#include "mozilla/gfx/PathHelpers.h"
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsRenderingContext.h"
#include "nsPresContext.h"
#include "nsNameSpaceManager.h"
#include "nsGkAtoms.h"
#include "nsImageFrame.h"
#include "nsCoord.h"
@@ -21,26 +22,29 @@
#include "nsIStringBundle.h"
#include "nsContentUtils.h"
#ifdef ACCESSIBILITY
#include "nsAccessibilityService.h"
#endif
using namespace mozilla;
+using namespace mozilla::gfx;
class Area {
public:
explicit Area(nsIContent* aArea);
virtual ~Area();
virtual void ParseCoords(const nsAString& aSpec);
virtual bool IsInside(nscoord x, nscoord y) const = 0;
- virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC) = 0;
+ virtual void Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget,
+ const ColorPattern& aColor,
+ const StrokeOptions& aStrokeOptions) = 0;
virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) = 0;
void HasFocus(bool aHasFocus);
nsCOMPtr<nsIContent> mArea;
nscoord* mCoords;
int32_t mNumCoords;
bool mHasFocus;
@@ -262,45 +266,44 @@ void Area::HasFocus(bool aHasFocus)
//----------------------------------------------------------------------
class DefaultArea : public Area {
public:
explicit DefaultArea(nsIContent* aArea);
virtual bool IsInside(nscoord x, nscoord y) const MOZ_OVERRIDE;
- virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC) MOZ_OVERRIDE;
+ virtual void Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget,
+ const ColorPattern& aColor,
+ const StrokeOptions& aStrokeOptions) MOZ_OVERRIDE;
virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) MOZ_OVERRIDE;
};
DefaultArea::DefaultArea(nsIContent* aArea)
: Area(aArea)
{
}
bool DefaultArea::IsInside(nscoord x, nscoord y) const
{
return true;
}
-void DefaultArea::Draw(nsIFrame* aFrame, nsRenderingContext& aRC)
+void DefaultArea::Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget,
+ const ColorPattern& aColor,
+ const StrokeOptions& aStrokeOptions)
{
if (mHasFocus) {
- nsRect r = aFrame->GetRect();
- r.MoveTo(0, 0);
- nscoord x1 = r.x;
- nscoord y1 = r.y;
+ nsRect r(nsPoint(0, 0), aFrame->GetSize());
const nscoord kOnePixel = nsPresContext::CSSPixelsToAppUnits(1);
- nscoord x2 = r.XMost() - kOnePixel;
- nscoord y2 = r.YMost() - kOnePixel;
- // XXX aRC.DrawRect(r) result is ugly, that's why we use DrawLine.
- aRC.DrawLine(x1, y1, x1, y2);
- aRC.DrawLine(x1, y2, x2, y2);
- aRC.DrawLine(x1, y1, x2, y1);
- aRC.DrawLine(x2, y1, x2, y2);
+ r.width -= kOnePixel;
+ r.height -= kOnePixel;
+ Rect rect =
+ ToRect(nsLayoutUtils::RectToGfxRect(r, aFrame->PresContext()->AppUnitsPerDevPixel()));
+ StrokeSnappedEdgesOfRect(rect, aDrawTarget, aColor, aStrokeOptions);
}
}
void DefaultArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
{
aRect = aFrame->GetRect();
aRect.MoveTo(0, 0);
}
@@ -308,17 +311,19 @@ void DefaultArea::GetRect(nsIFrame* aFra
//----------------------------------------------------------------------
class RectArea : public Area {
public:
explicit RectArea(nsIContent* aArea);
virtual void ParseCoords(const nsAString& aSpec) MOZ_OVERRIDE;
virtual bool IsInside(nscoord x, nscoord y) const MOZ_OVERRIDE;
- virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC) MOZ_OVERRIDE;
+ virtual void Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget,
+ const ColorPattern& aColor,
+ const StrokeOptions& aStrokeOptions) MOZ_OVERRIDE;
virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) MOZ_OVERRIDE;
};
RectArea::RectArea(nsIContent* aArea)
: Area(aArea)
{
}
@@ -370,30 +375,32 @@ bool RectArea::IsInside(nscoord x, nscoo
"Someone screwed up RectArea::ParseCoords");
if ((x >= x1) && (x <= x2) && (y >= y1) && (y <= y2)) {
return true;
}
}
return false;
}
-void RectArea::Draw(nsIFrame* aFrame, nsRenderingContext& aRC)
+void RectArea::Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget,
+ const ColorPattern& aColor,
+ const StrokeOptions& aStrokeOptions)
{
if (mHasFocus) {
if (mNumCoords >= 4) {
nscoord x1 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
nscoord y1 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]);
nscoord x2 = nsPresContext::CSSPixelsToAppUnits(mCoords[2]);
nscoord y2 = nsPresContext::CSSPixelsToAppUnits(mCoords[3]);
NS_ASSERTION(x1 <= x2 && y1 <= y2,
"Someone screwed up RectArea::ParseCoords");
- aRC.DrawLine(x1, y1, x1, y2);
- aRC.DrawLine(x1, y2, x2, y2);
- aRC.DrawLine(x1, y1, x2, y1);
- aRC.DrawLine(x2, y1, x2, y2);
+ nsRect r(x1, y1, x2 - x1, y2 - y1);
+ Rect rect =
+ ToRect(nsLayoutUtils::RectToGfxRect(r, aFrame->PresContext()->AppUnitsPerDevPixel()));
+ StrokeSnappedEdgesOfRect(rect, aDrawTarget, aColor, aStrokeOptions);
}
}
}
void RectArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
{
if (mNumCoords >= 4) {
nscoord x1 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
@@ -410,17 +417,19 @@ void RectArea::GetRect(nsIFrame* aFrame,
//----------------------------------------------------------------------
class PolyArea : public Area {
public:
explicit PolyArea(nsIContent* aArea);
virtual void ParseCoords(const nsAString& aSpec) MOZ_OVERRIDE;
virtual bool IsInside(nscoord x, nscoord y) const MOZ_OVERRIDE;
- virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC) MOZ_OVERRIDE;
+ virtual void Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget,
+ const ColorPattern& aColor,
+ const StrokeOptions& aStrokeOptions) MOZ_OVERRIDE;
virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) MOZ_OVERRIDE;
};
PolyArea::PolyArea(nsIContent* aArea)
: Area(aArea)
{
}
@@ -502,33 +511,46 @@ bool PolyArea::IsInside(nscoord x, nscoo
}
if ((intersects & 1) != 0) {
return true;
}
}
return false;
}
-void PolyArea::Draw(nsIFrame* aFrame, nsRenderingContext& aRC)
+void PolyArea::Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget,
+ const ColorPattern& aColor,
+ const StrokeOptions& aStrokeOptions)
{
if (mHasFocus) {
if (mNumCoords >= 6) {
- nscoord x0 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
- nscoord y0 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]);
- nscoord x1, y1;
+ // Where possible, we want all horizontal and vertical lines to align on
+ // pixel rows or columns, and to start at pixel boundaries so that one
+ // pixel dashing neatly sits on pixels to give us neat lines. To achieve
+ // that we draw each line segment as a separate path, snapping it to
+ // device pixels if applicable.
+ nsPresContext* pc = aFrame->PresContext();
+ Point p1(pc->CSSPixelsToDevPixels(mCoords[0]),
+ pc->CSSPixelsToDevPixels(mCoords[1]));
+ Point p2, p1snapped, p2snapped;
for (int32_t i = 2; i < mNumCoords; i += 2) {
- x1 = nsPresContext::CSSPixelsToAppUnits(mCoords[i]);
- y1 = nsPresContext::CSSPixelsToAppUnits(mCoords[i+1]);
- aRC.DrawLine(x0, y0, x1, y1);
- x0 = x1;
- y0 = y1;
+ p2.x = pc->CSSPixelsToDevPixels(mCoords[i]);
+ p2.y = pc->CSSPixelsToDevPixels(mCoords[i+1]);
+ p1snapped = p1;
+ p2snapped = p2;
+ SnapLineToDevicePixelsForStroking(p1snapped, p2snapped, aDrawTarget);
+ aDrawTarget.StrokeLine(p1snapped, p2snapped, aColor, aStrokeOptions);
+ p1 = p2;
}
- x1 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
- y1 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]);
- aRC.DrawLine(x0, y0, x1, y1);
+ p2.x = pc->CSSPixelsToDevPixels(mCoords[0]);
+ p2.y = pc->CSSPixelsToDevPixels(mCoords[1]);
+ p1snapped = p1;
+ p2snapped = p2;
+ SnapLineToDevicePixelsForStroking(p1snapped, p2snapped, aDrawTarget);
+ aDrawTarget.StrokeLine(p1snapped, p2snapped, aColor, aStrokeOptions);
}
}
}
void PolyArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
{
if (mNumCoords >= 6) {
nscoord x1, x2, y1, y2, xtmp, ytmp;
@@ -550,17 +572,19 @@ void PolyArea::GetRect(nsIFrame* aFrame,
//----------------------------------------------------------------------
class CircleArea : public Area {
public:
explicit CircleArea(nsIContent* aArea);
virtual void ParseCoords(const nsAString& aSpec) MOZ_OVERRIDE;
virtual bool IsInside(nscoord x, nscoord y) const MOZ_OVERRIDE;
- virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC) MOZ_OVERRIDE;
+ virtual void Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget,
+ const ColorPattern& aColor,
+ const StrokeOptions& aStrokeOptions) MOZ_OVERRIDE;
virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) MOZ_OVERRIDE;
};
CircleArea::CircleArea(nsIContent* aArea)
: Area(aArea)
{
}
@@ -609,30 +633,33 @@ bool CircleArea::IsInside(nscoord x, nsc
nscoord dist = (dx * dx) + (dy * dy);
if (dist <= (radius * radius)) {
return true;
}
}
return false;
}
-void CircleArea::Draw(nsIFrame* aFrame, nsRenderingContext& aRC)
+void CircleArea::Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget,
+ const ColorPattern& aColor,
+ const StrokeOptions& aStrokeOptions)
{
if (mHasFocus) {
if (mNumCoords >= 3) {
- nscoord x1 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
- nscoord y1 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]);
- nscoord radius = nsPresContext::CSSPixelsToAppUnits(mCoords[2]);
- if (radius < 0) {
+ Point center(aFrame->PresContext()->CSSPixelsToDevPixels(mCoords[0]),
+ aFrame->PresContext()->CSSPixelsToDevPixels(mCoords[1]));
+ Float diameter =
+ 2 * aFrame->PresContext()->CSSPixelsToDevPixels(mCoords[2]);
+ if (diameter <= 0) {
return;
}
- nscoord x = x1 - radius;
- nscoord y = y1 - radius;
- nscoord w = 2 * radius;
- aRC.DrawEllipse(x, y, w, w);
+ RefPtr<PathBuilder> builder = aDrawTarget.CreatePathBuilder();
+ AppendEllipseToPath(builder, center, Size(diameter, diameter));
+ RefPtr<Path> circle = builder->Finish();
+ aDrawTarget.Stroke(circle, aColor, aStrokeOptions);
}
}
}
void CircleArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
{
if (mNumCoords >= 3) {
nscoord x1 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
@@ -863,22 +890,24 @@ nsImageMap::GetArea(nscoord aX, nscoord
nsIContent*
nsImageMap::GetAreaAt(uint32_t aIndex) const
{
return mAreas.ElementAt(aIndex)->mArea;
}
void
-nsImageMap::Draw(nsIFrame* aFrame, nsRenderingContext& aRC)
+nsImageMap::Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget,
+ const ColorPattern& aColor,
+ const StrokeOptions& aStrokeOptions)
{
uint32_t i, n = mAreas.Length();
for (i = 0; i < n; i++) {
Area* area = mAreas.ElementAt(i);
- area->Draw(aFrame, aRC);
+ area->Draw(aFrame, aDrawTarget, aColor, aStrokeOptions);
}
}
void
nsImageMap::MaybeUpdateAreas(nsIContent *aContent)
{
if (aContent == mMap || mContainsBlockContents) {
UpdateAreas();