https://bugs.webkit.org/show_bug.cgi?id=152940
Reviewed by Zalan Bujtas.
Call into the display list recorder for top-level entrypoints implemented in platform-specific
files.
The convention is that if a function begins with "platform", it's not a top-level
entry point, and should only be called when there's a platform context (i.e. not
recording, and not paintingDisabled).
A few instances are stubbed out until we have a more complete display list implementation.
* platform/graphics/GraphicsContext.cpp:
(WebCore::GraphicsContext::drawText):
* platform/graphics/cairo/GraphicsContextCairo.cpp:
(WebCore::GraphicsContext::getCTM):
(WebCore::GraphicsContext::savePlatformState):
(WebCore::GraphicsContext::restorePlatformState):
(WebCore::GraphicsContext::drawRect):
(WebCore::GraphicsContext::drawNativeImage):
(WebCore::GraphicsContext::drawLine):
(WebCore::GraphicsContext::drawEllipse):
(WebCore::GraphicsContext::drawConvexPolygon):
(WebCore::GraphicsContext::clipConvexPolygon):
(WebCore::GraphicsContext::fillPath):
(WebCore::GraphicsContext::strokePath):
(WebCore::GraphicsContext::fillRect):
(WebCore::GraphicsContext::clip):
(WebCore::GraphicsContext::clipPath):
(WebCore::GraphicsContext::clipBounds):
(WebCore::GraphicsContext::drawLinesForText):
(WebCore::GraphicsContext::roundToDevicePixels):
(WebCore::GraphicsContext::translate):
(WebCore::GraphicsContext::setPlatformStrokeThickness):
(WebCore::GraphicsContext::setPlatformStrokeStyle):
(WebCore::GraphicsContext::concatCTM):
(WebCore::GraphicsContext::setCTM):
(WebCore::GraphicsContext::beginPlatformTransparencyLayer):
(WebCore::GraphicsContext::endPlatformTransparencyLayer):
(WebCore::GraphicsContext::clearRect):
(WebCore::GraphicsContext::strokeRect):
(WebCore::GraphicsContext::setLineCap):
(WebCore::GraphicsContext::setLineDash):
(WebCore::GraphicsContext::setLineJoin):
(WebCore::GraphicsContext::clipOut):
(WebCore::GraphicsContext::rotate):
(WebCore::GraphicsContext::scale):
(WebCore::GraphicsContext::platformFillRoundedRect):
(WebCore::GraphicsContext::fillRectWithRoundedHole):
(WebCore::GraphicsContext::drawPattern):
(WebCore::GraphicsContext::setPlatformShouldAntialias):
(WebCore::GraphicsContext::setPlatformImageInterpolationQuality):
(WebCore::GraphicsContext::isAcceleratedContext):
* platform/graphics/cg/GraphicsContextCG.cpp:
(WebCore::GraphicsContext::savePlatformState):
(WebCore::GraphicsContext::restorePlatformState):
(WebCore::GraphicsContext::drawNativeImage):
(WebCore::GraphicsContext::drawPattern):
(WebCore::GraphicsContext::drawRect):
(WebCore::GraphicsContext::drawLine):
(WebCore::GraphicsContext::drawEllipse):
(WebCore::GraphicsContext::drawConvexPolygon):
(WebCore::GraphicsContext::clipConvexPolygon):
(WebCore::GraphicsContext::applyStrokePattern):
(WebCore::GraphicsContext::applyFillPattern):
(WebCore::GraphicsContext::drawPath):
(WebCore::GraphicsContext::fillPath):
(WebCore::GraphicsContext::strokePath):
(WebCore::GraphicsContext::fillRect):
(WebCore::GraphicsContext::platformFillRoundedRect):
(WebCore::GraphicsContext::fillRectWithRoundedHole):
(WebCore::GraphicsContext::clip):
(WebCore::GraphicsContext::clipOut):
(WebCore::GraphicsContext::clipPath):
(WebCore::GraphicsContext::clipBounds):
(WebCore::GraphicsContext::beginPlatformTransparencyLayer):
(WebCore::GraphicsContext::endPlatformTransparencyLayer):
(WebCore::GraphicsContext::setPlatformShadow):
(WebCore::GraphicsContext::setMiterLimit):
(WebCore::GraphicsContext::clearRect):
(WebCore::GraphicsContext::strokeRect):
(WebCore::GraphicsContext::setLineCap):
(WebCore::GraphicsContext::setLineDash):
(WebCore::GraphicsContext::setLineJoin):
(WebCore::GraphicsContext::scale):
(WebCore::GraphicsContext::rotate):
(WebCore::GraphicsContext::translate):
(WebCore::GraphicsContext::concatCTM):
(WebCore::GraphicsContext::setCTM):
(WebCore::GraphicsContext::getCTM):
(WebCore::GraphicsContext::roundToDevicePixels):
(WebCore::GraphicsContext::drawLinesForText):
(WebCore::GraphicsContext::setURLForRect):
(WebCore::GraphicsContext::setIsCALayerContext):
(WebCore::GraphicsContext::isCALayerContext):
(WebCore::GraphicsContext::setIsAcceleratedContext):
(WebCore::GraphicsContext::isAcceleratedContext):
(WebCore::GraphicsContext::setPlatformTextDrawingMode):
(WebCore::GraphicsContext::setPlatformStrokeColor):
(WebCore::GraphicsContext::setPlatformStrokeThickness):
(WebCore::GraphicsContext::setPlatformFillColor):
(WebCore::GraphicsContext::setPlatformShouldAntialias):
(WebCore::GraphicsContext::setPlatformShouldSmoothFonts):
(WebCore::GraphicsContext::setPlatformAlpha):
(WebCore::GraphicsContext::setPlatformCompositeOperation):
(WebCore::GraphicsContext::platformApplyDeviceScaleFactor):
(WebCore::GraphicsContext::platformFillEllipse):
(WebCore::GraphicsContext::platformStrokeEllipse):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194816
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
2016-01-08 Simon Fraser <simon.fraser@apple.com>
+ Add display-list drawing hooks to platform-specific GraphicsContext files
+ https://bugs.webkit.org/show_bug.cgi?id=152940
+
+ Reviewed by Zalan Bujtas.
+
+ Call into the display list recorder for top-level entrypoints implemented in platform-specific
+ files.
+
+ The convention is that if a function begins with "platform", it's not a top-level
+ entry point, and should only be called when there's a platform context (i.e. not
+ recording, and not paintingDisabled).
+
+ A few instances are stubbed out until we have a more complete display list implementation.
+
+ * platform/graphics/GraphicsContext.cpp:
+ (WebCore::GraphicsContext::drawText):
+ * platform/graphics/cairo/GraphicsContextCairo.cpp:
+ (WebCore::GraphicsContext::getCTM):
+ (WebCore::GraphicsContext::savePlatformState):
+ (WebCore::GraphicsContext::restorePlatformState):
+ (WebCore::GraphicsContext::drawRect):
+ (WebCore::GraphicsContext::drawNativeImage):
+ (WebCore::GraphicsContext::drawLine):
+ (WebCore::GraphicsContext::drawEllipse):
+ (WebCore::GraphicsContext::drawConvexPolygon):
+ (WebCore::GraphicsContext::clipConvexPolygon):
+ (WebCore::GraphicsContext::fillPath):
+ (WebCore::GraphicsContext::strokePath):
+ (WebCore::GraphicsContext::fillRect):
+ (WebCore::GraphicsContext::clip):
+ (WebCore::GraphicsContext::clipPath):
+ (WebCore::GraphicsContext::clipBounds):
+ (WebCore::GraphicsContext::drawLinesForText):
+ (WebCore::GraphicsContext::roundToDevicePixels):
+ (WebCore::GraphicsContext::translate):
+ (WebCore::GraphicsContext::setPlatformStrokeThickness):
+ (WebCore::GraphicsContext::setPlatformStrokeStyle):
+ (WebCore::GraphicsContext::concatCTM):
+ (WebCore::GraphicsContext::setCTM):
+ (WebCore::GraphicsContext::beginPlatformTransparencyLayer):
+ (WebCore::GraphicsContext::endPlatformTransparencyLayer):
+ (WebCore::GraphicsContext::clearRect):
+ (WebCore::GraphicsContext::strokeRect):
+ (WebCore::GraphicsContext::setLineCap):
+ (WebCore::GraphicsContext::setLineDash):
+ (WebCore::GraphicsContext::setLineJoin):
+ (WebCore::GraphicsContext::clipOut):
+ (WebCore::GraphicsContext::rotate):
+ (WebCore::GraphicsContext::scale):
+ (WebCore::GraphicsContext::platformFillRoundedRect):
+ (WebCore::GraphicsContext::fillRectWithRoundedHole):
+ (WebCore::GraphicsContext::drawPattern):
+ (WebCore::GraphicsContext::setPlatformShouldAntialias):
+ (WebCore::GraphicsContext::setPlatformImageInterpolationQuality):
+ (WebCore::GraphicsContext::isAcceleratedContext):
+ * platform/graphics/cg/GraphicsContextCG.cpp:
+ (WebCore::GraphicsContext::savePlatformState):
+ (WebCore::GraphicsContext::restorePlatformState):
+ (WebCore::GraphicsContext::drawNativeImage):
+ (WebCore::GraphicsContext::drawPattern):
+ (WebCore::GraphicsContext::drawRect):
+ (WebCore::GraphicsContext::drawLine):
+ (WebCore::GraphicsContext::drawEllipse):
+ (WebCore::GraphicsContext::drawConvexPolygon):
+ (WebCore::GraphicsContext::clipConvexPolygon):
+ (WebCore::GraphicsContext::applyStrokePattern):
+ (WebCore::GraphicsContext::applyFillPattern):
+ (WebCore::GraphicsContext::drawPath):
+ (WebCore::GraphicsContext::fillPath):
+ (WebCore::GraphicsContext::strokePath):
+ (WebCore::GraphicsContext::fillRect):
+ (WebCore::GraphicsContext::platformFillRoundedRect):
+ (WebCore::GraphicsContext::fillRectWithRoundedHole):
+ (WebCore::GraphicsContext::clip):
+ (WebCore::GraphicsContext::clipOut):
+ (WebCore::GraphicsContext::clipPath):
+ (WebCore::GraphicsContext::clipBounds):
+ (WebCore::GraphicsContext::beginPlatformTransparencyLayer):
+ (WebCore::GraphicsContext::endPlatformTransparencyLayer):
+ (WebCore::GraphicsContext::setPlatformShadow):
+ (WebCore::GraphicsContext::setMiterLimit):
+ (WebCore::GraphicsContext::clearRect):
+ (WebCore::GraphicsContext::strokeRect):
+ (WebCore::GraphicsContext::setLineCap):
+ (WebCore::GraphicsContext::setLineDash):
+ (WebCore::GraphicsContext::setLineJoin):
+ (WebCore::GraphicsContext::scale):
+ (WebCore::GraphicsContext::rotate):
+ (WebCore::GraphicsContext::translate):
+ (WebCore::GraphicsContext::concatCTM):
+ (WebCore::GraphicsContext::setCTM):
+ (WebCore::GraphicsContext::getCTM):
+ (WebCore::GraphicsContext::roundToDevicePixels):
+ (WebCore::GraphicsContext::drawLinesForText):
+ (WebCore::GraphicsContext::setURLForRect):
+ (WebCore::GraphicsContext::setIsCALayerContext):
+ (WebCore::GraphicsContext::isCALayerContext):
+ (WebCore::GraphicsContext::setIsAcceleratedContext):
+ (WebCore::GraphicsContext::isAcceleratedContext):
+ (WebCore::GraphicsContext::setPlatformTextDrawingMode):
+ (WebCore::GraphicsContext::setPlatformStrokeColor):
+ (WebCore::GraphicsContext::setPlatformStrokeThickness):
+ (WebCore::GraphicsContext::setPlatformFillColor):
+ (WebCore::GraphicsContext::setPlatformShouldAntialias):
+ (WebCore::GraphicsContext::setPlatformShouldSmoothFonts):
+ (WebCore::GraphicsContext::setPlatformAlpha):
+ (WebCore::GraphicsContext::setPlatformCompositeOperation):
+ (WebCore::GraphicsContext::platformApplyDeviceScaleFactor):
+ (WebCore::GraphicsContext::platformFillEllipse):
+ (WebCore::GraphicsContext::platformStrokeEllipse):
+
+2016-01-08 Simon Fraser <simon.fraser@apple.com>
+
Add DisplayList hooks into GraphicsContext
https://bugs.webkit.org/show_bug.cgi?id=152932
if (paintingDisabled())
return 0;
+ if (isRecording()) {
+ // FIXME: Text drawing with display lists TBD.
+ return 0;
+ }
+
return font.drawText(*this, run, point, from, to);
}
#include "AffineTransform.h"
#include "CairoUtilities.h"
+#include "DisplayListRecorder.h"
#include "DrawErrorUnderline.h"
#include "FloatConversion.h"
#include "FloatRect.h"
if (paintingDisabled())
return AffineTransform();
+ if (isRecording()) {
+ WTFLogAlways("GraphicsContext::getCTM() is not yet compatible with recording contexts.");
+ return AffineTransform();
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_matrix_t m;
cairo_get_matrix(cr, &m);
void GraphicsContext::savePlatformState()
{
+ ASSERT(!isRecording());
platformContext()->save();
m_data->save();
}
void GraphicsContext::restorePlatformState()
{
+ ASSERT(!isRecording());
platformContext()->restore();
m_data->restore();
}
// Draws a filled rectangle with a stroked border.
-void GraphicsContext::drawRect(const FloatRect& rect, float)
+void GraphicsContext::drawRect(const FloatRect& rect, float borderThickness)
{
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawRect(rect, borderThickness);
+ return;
+ }
+
ASSERT(!rect.isEmpty());
cairo_t* cr = platformContext()->cr();
FloatRect r(rect);
r.inflate(-.5f);
cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
- cairo_set_line_width(cr, 1.0);
+ cairo_set_line_width(cr, 1.0); // borderThickness?
cairo_stroke(cr);
}
void GraphicsContext::drawNativeImage(PassNativeImagePtr imagePtr, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode, ImageOrientation orientation)
{
- UNUSED_PARAM(imageSize);
+ if (paintingDisabled())
+ return;
+
+ if (isRecording()) {
+ m_displayListRecorder->drawNativeImage(imagePtr, imageSize, destRect, srcRect, op, blendMode, orientation);
+ return;
+ }
NativeImagePtr image = imagePtr;
if (strokeStyle() == NoStroke)
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawLine(point1, point2);
+ return;
+ }
+
const Color& strokeColor = this->strokeColor();
float thickness = strokeThickness();
bool isVerticalLine = (point1.x() + thickness == point2.x());
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawEllipse(rect);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_save(cr);
float yRadius = .5 * rect.height();
if (npoints <= 1)
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawConvexPolygon(npoints, points, shouldAntialias);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_save(cr);
if (numPoints <= 1)
return;
+ if (isRecording()) {
+ m_displayListRecorder->clipConvexPolygon(numPoints, points, antialiased);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_new_path(cr);
if (paintingDisabled() || path.isEmpty())
return;
+ if (isRecording()) {
+ m_displayListRecorder->fillPath(path);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
setPathOnCairoContext(cr, path.platformPath()->context());
shadowAndFillCurrentCairoPath(*this);
if (paintingDisabled() || path.isEmpty())
return;
+ if (isRecording()) {
+ m_displayListRecorder->strokePath(path);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
setPathOnCairoContext(cr, path.platformPath()->context());
shadowAndStrokeCurrentCairoPath(*this);
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->fillRect(rect);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
shadowAndFillCurrentCairoPath(*this);
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->fillRect(rect, color);
+ return;
+ }
+
if (hasShadow())
platformContext()->shadowBlur().drawRectShadow(*this, FloatRoundedRect(rect));
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clip(rect);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clipPath(path, clipRule);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
if (!path.isNull())
setPathOnCairoContext(cr, path.platformPath()->context());
IntRect GraphicsContext::clipBounds() const
{
+ if (paintingDisabled())
+ return IntRect();
+
+ if (isRecording()) {
+ WTFLogAlways("Getting the clip bounds not yet supported with display lists");
+ return IntRect(-2048, -2048, 4096, 4096); // FIXME: display lists.
+ }
+
double x1, x2, y1, y2;
cairo_clip_extents(platformContext()->cr(), &x1, &y1, &x2, &y2);
return enclosingIntRect(FloatRect(x1, y1, x2 - x1, y2 - y1));
if (widths.size() <= 0)
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawLinesForText(point, widths, printing, doubleUnderlines, strokeThickness());
+ return;
+ }
+
Color localStrokeColor(strokeColor());
FloatRect bounds = computeLineBoundsAndAntialiasingModeForText(point, widths.last(), printing, localStrokeColor);
FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect, RoundingMode)
{
+ if (paintingDisabled())
+ return frect;
+
+ if (!isRecording()) {
+ WTFLogAlways("GraphicsContext::roundToDevicePixels() is not yet compatible with recording contexts.");
+ return frect;
+ }
+
FloatRect result;
double x = frect.x();
double y = frect.y();
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->translate(x, y);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_translate(cr, x, y);
m_data->translate(x, y);
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
cairo_set_line_width(platformContext()->cr(), strokeThickness);
}
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
switch (strokeStyle) {
case NoStroke:
// FIXME: is it the right way to emulate NoStroke?
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->concatCTM(transform);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
const cairo_matrix_t matrix = cairo_matrix_t(transform);
cairo_transform(cr, &matrix);
if (paintingDisabled())
return;
+ if (isRecording()) {
+ WTFLogAlways("GraphicsContext::setCTM() is not compatible with recording contexts.");
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
const cairo_matrix_t matrix = cairo_matrix_t(transform);
cairo_set_matrix(cr, &matrix);
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
cairo_t* cr = platformContext()->cr();
cairo_push_group(cr);
m_data->layers.append(opacity);
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
cairo_t* cr = platformContext()->cr();
cairo_pop_group_to_source(cr);
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clearRect(rect);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_save(cr);
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->strokeRect(rect, width);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
cairo_save(cr);
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->setLineCap(lineCap);
+ return;
+ }
+
cairo_line_cap_t cairoCap = CAIRO_LINE_CAP_BUTT;
switch (lineCap) {
case ButtCap:
void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
{
+ if (paintingDisabled())
+ return;
+
+ if (isRecording()) {
+ m_displayListRecorder->setLineDash(dashes, dashOffset);
+ return;
+ }
+
if (isDashArrayAllZero(dashes))
cairo_set_dash(platformContext()->cr(), 0, 0, 0);
else
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->setLineJoin(lineJoin);
+ return;
+ }
+
cairo_line_join_t cairoJoin = CAIRO_LINE_JOIN_MITER;
switch (lineJoin) {
case MiterJoin:
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clipOut(path);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->rotate(radians);
+ return;
+ }
+
cairo_rotate(platformContext()->cr(), radians);
m_data->rotate(radians);
}
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->scale(size);
+ return;
+ }
+
cairo_scale(platformContext()->cr(), size.width(), size.height());
m_data->scale(size);
}
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clipOut(r);
+ return;
+ }
+
cairo_t* cr = platformContext()->cr();
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
if (hasShadow())
platformContext()->shadowBlur().drawRectShadow(*this, rect);
if (paintingDisabled() || !color.isValid())
return;
+ if (isRecording()) {
+ m_displayListRecorder->fillRectWithRoundedHole(rect, roundedHoleRect, color);
+ return;
+ }
+
if (this->mustUseShadowBlur())
platformContext()->shadowBlur().drawInsetShadow(*this, rect, roundedHoleRect);
cairo_restore(cr);
}
-void GraphicsContext::drawPattern(Image& image, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize&, CompositeOperator op, const FloatRect& destRect, BlendMode)
+void GraphicsContext::drawPattern(Image& image, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode)
{
+ if (paintingDisabled())
+ return;
+
+ if (isRecording()) {
+ m_displayListRecorder->drawPattern(image, tileRect, patternTransform, phase, spacing, op, destRect, blendMode);
+ return;
+ }
+
RefPtr<cairo_surface_t> surface = image.nativeImageForCurrentFrame();
if (!surface) // If it's too early we won't have an image yet.
return;
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
// When true, use the default Cairo backend antialias mode (usually this
// enables standard 'grayscale' antialiasing); false to explicitly disable
// antialiasing. This is the same strategy as used in drawConvexPolygon().
void GraphicsContext::setPlatformImageInterpolationQuality(InterpolationQuality quality)
{
+ ASSERT(!isRecording());
+
platformContext()->setImageInterpolationQuality(quality);
}
bool GraphicsContext::isAcceleratedContext() const
{
+ if (isRecording())
+ return false;
+
return cairo_surface_get_type(cairo_get_target(platformContext()->cr())) == CAIRO_SURFACE_TYPE_GL;
}
#include "AffineTransform.h"
#include "CoreGraphicsSPI.h"
+#include "DisplayListRecorder.h"
#include "FloatConversion.h"
#include "GraphicsContextPlatformPrivateCG.h"
#include "ImageBuffer.h"
void GraphicsContext::savePlatformState()
{
ASSERT(!paintingDisabled());
+ ASSERT(!isRecording());
+
// Note: Do not use this function within this class implementation, since we want to avoid the extra
// save of the secondary context (in GraphicsContextPlatformPrivateCG.h).
CGContextSaveGState(platformContext());
void GraphicsContext::restorePlatformState()
{
ASSERT(!paintingDisabled());
+ ASSERT(!isRecording());
+
// Note: Do not use this function within this class implementation, since we want to avoid the extra
// restore of the secondary context (in GraphicsContextPlatformPrivateCG.h).
CGContextRestoreGState(platformContext());
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawNativeImage(imagePtr, imageSize, destRect, srcRect, op, blendMode, orientation);
+ return;
+ }
+
RetainPtr<CGImageRef> image(imagePtr);
float currHeight = orientation.usesWidthAsHeight() ? CGImageGetWidth(image.get()) : CGImageGetHeight(image.get());
if (paintingDisabled() || !patternTransform.isInvertible())
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawPattern(image, tileRect, patternTransform, phase, spacing, op, destRect, blendMode);
+ return;
+ }
+
CGContextRef context = platformContext();
CGContextStateSaver stateSaver(context);
CGContextClipToRect(context, destRect);
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawRect(rect, borderThickness);
+ return;
+ }
+
// FIXME: this function does not handle patterns and gradients like drawPath does, it probably should.
ASSERT(!rect.isEmpty());
if (strokeStyle() == NoStroke)
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawLine(point1, point2);
+ return;
+ }
+
float thickness = strokeThickness();
bool isVerticalLine = (point1.x() + thickness == point2.x());
float strokeWidth = isVerticalLine ? point2.y() - point1.y() : point2.x() - point1.x();
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawEllipse(rect);
+ return;
+ }
+
Path path;
path.addEllipse(rect);
drawPath(path);
if (numberOfPoints <= 1)
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawConvexPolygon(numberOfPoints, points, antialiased);
+ return;
+ }
+
CGContextRef context = platformContext();
if (antialiased != shouldAntialias())
if (numberOfPoints <= 1)
return;
+ if (isRecording()) {
+ m_displayListRecorder->clipConvexPolygon(numberOfPoints, points, antialias);
+ return;
+ }
+
CGContextRef context = platformContext();
if (antialias != shouldAntialias())
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->applyStrokePattern();
+ return;
+ }
+
CGContextRef cgContext = platformContext();
AffineTransform userToBaseCTM = AffineTransform(getUserToBaseCTM(cgContext));
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->applyFillPattern();
+ return;
+ }
+
CGContextRef cgContext = platformContext();
AffineTransform userToBaseCTM = AffineTransform(getUserToBaseCTM(cgContext));
if (paintingDisabled() || path.isEmpty())
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawPath(path);
+ return;
+ }
+
CGContextRef context = platformContext();
const GraphicsContextState& state = m_state;
if (paintingDisabled() || path.isEmpty())
return;
+ if (isRecording()) {
+ m_displayListRecorder->fillPath(path);
+ return;
+ }
+
CGContextRef context = platformContext();
if (m_state.fillGradient) {
if (paintingDisabled() || path.isEmpty())
return;
+ if (isRecording()) {
+ m_displayListRecorder->strokePath(path);
+ return;
+ }
+
CGContextRef context = platformContext();
CGContextBeginPath(context);
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->fillRect(rect);
+ return;
+ }
+
CGContextRef context = platformContext();
if (m_state.fillGradient) {
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->fillRect(rect, color);
+ return;
+ }
+
CGContextRef context = platformContext();
Color oldFillColor = fillColor();
{
if (paintingDisabled())
return;
+
+ ASSERT(!isRecording());
CGContextRef context = platformContext();
Color oldFillColor = fillColor();
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->fillRectWithRoundedHole(rect, roundedHoleRect, color);
+ return;
+ }
+
CGContextRef context = platformContext();
Path path;
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clip(rect);
+ return;
+ }
+
CGContextClipToRect(platformContext(), rect);
m_data->clip(rect);
}
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clipOut(rect);
+ return;
+ }
+
// FIXME: Using CGRectInfinite is much faster than getting the clip bounding box. However, due
// to <rdar://problem/12584492>, CGRectInfinite can't be used with an accelerated context that
// has certain transforms that aren't just a translation or a scale. And due to <rdar://problem/14634453>
CGContextEOClip(platformContext());
}
+void GraphicsContext::clipOut(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ if (isRecording()) {
+ m_displayListRecorder->clipOut(path);
+ return;
+ }
+
+ CGContextBeginPath(platformContext());
+ CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext()));
+ if (!path.isEmpty())
+ CGContextAddPath(platformContext(), path.platformPath());
+ CGContextEOClip(platformContext());
+}
+
void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
{
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->clipPath(path, clipRule);
+ return;
+ }
+
CGContextRef context = platformContext();
if (path.isEmpty())
CGContextClipToRect(context, CGRectZero);
if (paintingDisabled())
return IntRect();
+ if (isRecording()) {
+ WTFLogAlways("Getting the clip bounds not yet supported with display lists");
+ return IntRect(-2048, -2048, 4096, 4096); // FIXME: display lists.
+ }
+
+
return enclosingIntRect(CGContextGetClipBoundingBox(platformContext()));
}
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
save();
CGContextRef context = platformContext();
{
if (paintingDisabled())
return;
+
+ ASSERT(!isRecording());
+
CGContextRef context = platformContext();
CGContextEndTransparencyLayer(context);
{
if (paintingDisabled())
return;
+
+ ASSERT(!isRecording());
// FIXME: we could avoid the shadow setup cost when we know we'll render the shadow ourselves.
{
if (paintingDisabled())
return;
+
+ if (isRecording()) {
+ // Maybe this should be part of the state.
+ m_displayListRecorder->setMiterLimit(limit);
+ return;
+ }
+
CGContextSetMiterLimit(platformContext(), limit);
}
{
if (paintingDisabled())
return;
+
+ if (isRecording()) {
+ m_displayListRecorder->clearRect(r);
+ return;
+ }
+
CGContextClearRect(platformContext(), r);
}
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->strokeRect(rect, lineWidth);
+ return;
+ }
+
CGContextRef context = platformContext();
if (m_state.strokeGradient) {
{
if (paintingDisabled())
return;
+
+ if (isRecording()) {
+ m_displayListRecorder->setLineCap(cap);
+ return;
+ }
+
switch (cap) {
case ButtCap:
CGContextSetLineCap(platformContext(), kCGLineCapButt);
if (paintingDisabled())
return;
+ if (isRecording()) {
+ m_displayListRecorder->setLineDash(dashes, dashOffset);
+ return;
+ }
+
if (dashOffset < 0) {
float length = 0;
for (size_t i = 0; i < dashes.size(); ++i)
{
if (paintingDisabled())
return;
+
+ if (isRecording()) {
+ m_displayListRecorder->setLineJoin(join);
+ return;
+ }
+
switch (join) {
case MiterJoin:
CGContextSetLineJoin(platformContext(), kCGLineJoinMiter);
clipPath(path, fillRule);
}
-void GraphicsContext::clipOut(const Path& path)
+void GraphicsContext::scale(const FloatSize& size)
{
if (paintingDisabled())
return;
- CGContextBeginPath(platformContext());
- CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext()));
- if (!path.isEmpty())
- CGContextAddPath(platformContext(), path.platformPath());
- CGContextEOClip(platformContext());
-}
-
-void GraphicsContext::scale(const FloatSize& size)
-{
- if (paintingDisabled())
+ if (isRecording()) {
+ m_displayListRecorder->scale(size);
return;
+ }
+
CGContextScaleCTM(platformContext(), size.width(), size.height());
m_data->scale(size);
m_data->m_userToDeviceTransformKnownToBeIdentity = false;
{
if (paintingDisabled())
return;
+
+ if (isRecording()) {
+ m_displayListRecorder->rotate(angle);
+ return;
+ }
+
CGContextRotateCTM(platformContext(), angle);
m_data->rotate(angle);
m_data->m_userToDeviceTransformKnownToBeIdentity = false;
{
if (paintingDisabled())
return;
+
+ if (isRecording()) {
+ m_displayListRecorder->translate(x, y);
+ return;
+ }
+
CGContextTranslateCTM(platformContext(), x, y);
m_data->translate(x, y);
m_data->m_userToDeviceTransformKnownToBeIdentity = false;
{
if (paintingDisabled())
return;
+
+ if (isRecording()) {
+ m_displayListRecorder->concatCTM(transform);
+ return;
+ }
+
CGContextConcatCTM(platformContext(), transform);
m_data->concatCTM(transform);
m_data->m_userToDeviceTransformKnownToBeIdentity = false;
{
if (paintingDisabled())
return;
+
+ if (isRecording()) {
+ WTFLogAlways("GraphicsContext::setCTM() is not compatible with recording contexts.");
+ return;
+ }
+
CGContextSetCTM(platformContext(), transform);
m_data->setCTM(transform);
m_data->m_userToDeviceTransformKnownToBeIdentity = false;
if (paintingDisabled())
return AffineTransform();
+ if (isRecording()) {
+ WTFLogAlways("GraphicsContext::getCTM() is not yet compatible with recording contexts.");
+ return AffineTransform();
+ }
+
// The CTM usually includes the deviceScaleFactor except in WebKit 1 when the
// content is non-composited, since the scale factor is integrated at a lower
// level. To guarantee the deviceScale is included, we can use this CG API.
if (paintingDisabled())
return rect;
+ if (!isRecording()) {
+ WTFLogAlways("GraphicsContext::roundToDevicePixels() is not yet compatible with recording contexts.");
+ return rect;
+ }
+
// It is not enough just to round to pixels in device space. The rotation part of the
// affine transform matrix to device space can mess with this conversion if we have a
// rotating image like the hands of the world clock widget. We just need the scale, so
if (!widths.size())
return;
+ if (isRecording()) {
+ m_displayListRecorder->drawLinesForText(point, widths, printing, doubleLines, strokeThickness());
+ return;
+ }
+
Color localStrokeColor(strokeColor());
FloatRect bounds = computeLineBoundsAndAntialiasingModeForText(point, widths.last(), printing, localStrokeColor);
if (paintingDisabled())
return;
+ if (isRecording()) {
+ WTFLogAlways("GraphicsContext::setURLForRect() is not yet compatible with recording contexts.");
+ return; // FIXME for display lists.
+ }
+
RetainPtr<CFURLRef> urlRef = link.createCFURL();
if (!urlRef)
return;
if (paintingDisabled())
return;
+ // FIXME
+ if (isRecording())
+ return;
+
if (isLayerContext)
m_data->m_contextFlags |= IsLayerCGContext;
else
if (paintingDisabled())
return false;
+ // FIXME
+ if (isRecording())
+ return false;
+
return m_data->m_contextFlags & IsLayerCGContext;
}
if (paintingDisabled())
return;
+ // FIXME
+ if (isRecording())
+ return;
+
if (isAccelerated)
m_data->m_contextFlags |= IsAcceleratedCGContext;
else
if (paintingDisabled())
return false;
+ // FIXME
+ if (isRecording())
+ return false;
+
return m_data->m_contextFlags & IsAcceleratedCGContext;
}
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
CGContextRef context = platformContext();
switch (mode) {
case TextModeFill:
{
if (paintingDisabled())
return;
+
+ ASSERT(!isRecording());
+
setCGStrokeColor(platformContext(), color);
}
{
if (paintingDisabled())
return;
+
+ ASSERT(!isRecording());
+
CGContextSetLineWidth(platformContext(), std::max(thickness, 0.f));
}
{
if (paintingDisabled())
return;
+
+ ASSERT(!isRecording());
+
setCGFillColor(platformContext(), color);
}
{
if (paintingDisabled())
return;
+
+ ASSERT(!isRecording());
+
CGContextSetShouldAntialias(platformContext(), enable);
}
{
if (paintingDisabled())
return;
+
+ ASSERT(!isRecording());
+
CGContextSetShouldSmoothFonts(platformContext(), enable);
}
{
if (paintingDisabled())
return;
+
+ ASSERT(!isRecording());
+
CGContextSetAlpha(platformContext(), alpha);
}
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
CGBlendMode target = kCGBlendModeNormal;
if (blendMode != BlendModeNormal) {
switch (blendMode) {
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
// CoreGraphics expects the base CTM of a HiDPI context to have the scale factor applied to it.
// Failing to change the base level CTM will cause certain CG features, such as focus rings,
// to draw with a scale factor of 1 rather than the actual scale factor.
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
// CGContextFillEllipseInRect only supports solid colors.
if (m_state.fillGradient || m_state.fillPattern) {
fillEllipseAsPath(ellipse);
if (paintingDisabled())
return;
+ ASSERT(!isRecording());
+
// CGContextStrokeEllipseInRect only supports solid colors.
if (m_state.strokeGradient || m_state.strokePattern) {
strokeEllipseAsPath(ellipse);