blob: 26973ecf94feac77b4a90144d4ea4266b05fef19 [file] [log] [blame]
/*
* Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "config.h"
#include "GraphicsContext.h"
#include "AffineTransform.h"
#include "GraphicsContextPrivate.h"
#include "KURL.h"
#include "NotImplemented.h"
#include "PainterOpenVG.h"
#include "SurfaceOpenVG.h"
#include <wtf/Assertions.h>
#include <wtf/MathExtras.h>
#include <wtf/UnusedParam.h>
#include <wtf/Vector.h>
#if PLATFORM(EGL)
#include "EGLDisplayOpenVG.h"
#include "EGLUtils.h"
#include <egl.h>
#endif
namespace WebCore {
// typedef'ing doesn't work, let's inherit from PainterOpenVG instead
class GraphicsContextPlatformPrivate : public PainterOpenVG {
public:
GraphicsContextPlatformPrivate(SurfaceOpenVG* surface)
: PainterOpenVG(surface)
{
}
};
GraphicsContext::GraphicsContext(SurfaceOpenVG* surface)
: m_common(createGraphicsContextPrivate())
, m_data(surface ? new GraphicsContextPlatformPrivate(surface) : 0)
{
setPaintingDisabled(!surface);
}
GraphicsContext::~GraphicsContext()
{
destroyGraphicsContextPrivate(m_common);
delete m_data;
}
PlatformGraphicsContext* GraphicsContext::platformContext() const
{
if (paintingDisabled())
return 0;
return m_data->baseSurface();
}
AffineTransform GraphicsContext::getCTM() const
{
if (paintingDisabled())
return AffineTransform();
return m_data->transformation();
}
void GraphicsContext::savePlatformState()
{
if (paintingDisabled())
return;
m_data->save();
}
void GraphicsContext::restorePlatformState()
{
if (paintingDisabled())
return;
m_data->restore();
}
void GraphicsContext::drawRect(const IntRect& rect)
{
if (paintingDisabled())
return;
m_data->drawRect(rect);
}
void GraphicsContext::drawLine(const IntPoint& from, const IntPoint& to)
{
if (paintingDisabled())
return;
m_data->drawLine(from, to);
}
/**
* Draw the largest ellipse that fits into the given rectangle.
*/
void GraphicsContext::drawEllipse(const IntRect& rect)
{
if (paintingDisabled())
return;
m_data->drawEllipse(rect);
}
void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
{
if (paintingDisabled())
return;
m_data->drawArc(rect, startAngle, angleSpan, VG_STROKE_PATH);
}
void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias)
{
if (paintingDisabled())
return;
m_data->drawPolygon(numPoints, points);
UNUSED_PARAM(shouldAntialias); // FIXME
}
void GraphicsContext::fillPath()
{
if (paintingDisabled())
return;
m_data->drawPath(VG_FILL_PATH, m_common->state.fillRule);
}
void GraphicsContext::strokePath()
{
if (paintingDisabled())
return;
m_data->drawPath(VG_STROKE_PATH, m_common->state.fillRule);
}
void GraphicsContext::drawPath()
{
if (paintingDisabled())
return;
m_data->drawPath(VG_FILL_PATH | VG_STROKE_PATH, m_common->state.fillRule);
}
void GraphicsContext::fillRect(const FloatRect& rect)
{
if (paintingDisabled())
return;
m_data->drawRect(rect, VG_FILL_PATH);
}
void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
Color oldColor = m_data->fillColor();
m_data->setFillColor(color);
m_data->drawRect(rect, VG_FILL_PATH);
m_data->setFillColor(oldColor);
UNUSED_PARAM(colorSpace); // FIXME
}
void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
Color oldColor = m_data->fillColor();
m_data->setFillColor(color);
m_data->drawRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight, VG_FILL_PATH);
m_data->setFillColor(oldColor);
UNUSED_PARAM(colorSpace); // FIXME
}
void GraphicsContext::beginPath()
{
if (paintingDisabled())
return;
m_data->beginPath();
}
void GraphicsContext::addPath(const Path& path)
{
if (paintingDisabled())
return;
m_data->addPath(path);
}
void GraphicsContext::clip(const FloatRect& rect)
{
if (paintingDisabled())
return;
m_data->intersectClipRect(rect);
}
void GraphicsContext::clipPath(WindRule clipRule)
{
if (paintingDisabled())
return;
m_data->clipPath(*(m_data->currentPath()), PainterOpenVG::IntersectClip, clipRule);
}
void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
{
if (paintingDisabled())
return;
if (rects.isEmpty())
return;
// FIXME: We just unite all focus ring rects into one for now.
// We should outline the edge of the full region.
offset += (width - 1) / 2;
IntRect finalFocusRect;
for (unsigned i = 0; i < rects.size(); i++) {
IntRect focusRect = rects[i];
focusRect.inflate(offset);
finalFocusRect.unite(focusRect);
}
StrokeStyle oldStyle = m_data->strokeStyle();
Color oldStrokeColor = m_data->strokeColor();
m_data->setStrokeStyle(DashedStroke);
m_data->setStrokeColor(color);
strokeRect(FloatRect(finalFocusRect), 1.f);
m_data->setStrokeStyle(oldStyle);
m_data->setStrokeColor(oldStrokeColor);
}
void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
{
if (paintingDisabled())
return;
if (width <= 0)
return;
StrokeStyle oldStyle = m_data->strokeStyle();
m_data->setStrokeStyle(SolidStroke);
drawLine(origin, origin + IntSize(width, 0));
m_data->setStrokeStyle(oldStyle);
UNUSED_PARAM(printing);
}
void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, int width, bool grammar)
{
if (paintingDisabled())
return;
notImplemented();
UNUSED_PARAM(origin);
UNUSED_PARAM(width);
UNUSED_PARAM(grammar);
}
FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
{
if (paintingDisabled())
return FloatRect();
return FloatRect(enclosingIntRect(m_data->transformation().mapRect(rect)));
}
void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
notImplemented();
UNUSED_PARAM(size);
UNUSED_PARAM(blur);
UNUSED_PARAM(color);
UNUSED_PARAM(colorSpace);
}
void GraphicsContext::clearPlatformShadow()
{
if (paintingDisabled())
return;
notImplemented();
}
void GraphicsContext::beginTransparencyLayer(float opacity)
{
if (paintingDisabled())
return;
notImplemented();
UNUSED_PARAM(opacity);
}
void GraphicsContext::endTransparencyLayer()
{
if (paintingDisabled())
return;
notImplemented();
}
void GraphicsContext::clearRect(const FloatRect& rect)
{
if (paintingDisabled())
return;
CompositeOperator op = m_data->compositeOperation();
m_data->setCompositeOperation(CompositeClear);
m_data->drawRect(rect, VG_FILL_PATH);
m_data->setCompositeOperation(op);
}
void GraphicsContext::strokeRect(const FloatRect& rect)
{
if (paintingDisabled())
return;
m_data->drawRect(rect, VG_STROKE_PATH);
}
void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
{
if (paintingDisabled())
return;
float oldThickness = m_data->strokeThickness();
m_data->setStrokeThickness(lineWidth);
m_data->drawRect(rect, VG_STROKE_PATH);
m_data->setStrokeThickness(oldThickness);
}
void GraphicsContext::setLineCap(LineCap lc)
{
if (paintingDisabled())
return;
m_data->setLineCap(lc);
}
void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
{
if (paintingDisabled())
return;
m_data->setLineDash(dashes, dashOffset);
}
void GraphicsContext::setLineJoin(LineJoin lj)
{
if (paintingDisabled())
return;
m_data->setLineJoin(lj);
}
void GraphicsContext::setMiterLimit(float limit)
{
if (paintingDisabled())
return;
m_data->setMiterLimit(limit);
}
void GraphicsContext::setAlpha(float opacity)
{
if (paintingDisabled())
return;
m_data->setOpacity(opacity);
}
void GraphicsContext::setCompositeOperation(CompositeOperator op)
{
if (paintingDisabled())
return;
m_data->setCompositeOperation(op);
}
void GraphicsContext::clip(const Path& path)
{
if (paintingDisabled())
return;
m_data->clipPath(path, PainterOpenVG::IntersectClip, m_common->state.fillRule);
}
void GraphicsContext::canvasClip(const Path& path)
{
clip(path);
}
void GraphicsContext::clipOut(const Path& path)
{
if (paintingDisabled())
return;
m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule);
}
void GraphicsContext::scale(const FloatSize& scaleFactors)
{
if (paintingDisabled())
return;
m_data->scale(scaleFactors);
}
void GraphicsContext::rotate(float radians)
{
if (paintingDisabled())
return;
m_data->rotate(radians);
}
void GraphicsContext::translate(float dx, float dy)
{
if (paintingDisabled())
return;
m_data->translate(dx, dy);
}
IntPoint GraphicsContext::origin()
{
if (paintingDisabled())
return IntPoint();
AffineTransform transformation = m_data->transformation();
return IntPoint(roundf(transformation.e()), roundf(transformation.f()));
}
void GraphicsContext::clipOut(const IntRect& rect)
{
if (paintingDisabled())
return;
Path path;
path.addRect(rect);
m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule);
}
void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
{
if (paintingDisabled())
return;
Path path;
path.addEllipse(rect);
m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule);
}
void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer)
{
if (paintingDisabled())
return;
notImplemented();
UNUSED_PARAM(rect);
UNUSED_PARAM(imageBuffer);
}
void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
{
if (paintingDisabled())
return;
Path path;
path.addEllipse(rect);
path.addEllipse(FloatRect(rect.x() + thickness, rect.y() + thickness,
rect.width() - (thickness * 2), rect.height() - (thickness * 2)));
m_data->clipPath(path, PainterOpenVG::IntersectClip, m_common->state.fillRule);
}
void GraphicsContext::concatCTM(const AffineTransform& transformation)
{
if (paintingDisabled())
return;
m_data->concatTransformation(transformation);
}
void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
{
notImplemented();
UNUSED_PARAM(link);
UNUSED_PARAM(destRect);
}
void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
m_data->setStrokeColor(color);
UNUSED_PARAM(colorSpace); // FIXME
}
void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& strokeStyle)
{
if (paintingDisabled())
return;
m_data->setStrokeStyle(strokeStyle);
}
void GraphicsContext::setPlatformStrokeThickness(float thickness)
{
if (paintingDisabled())
return;
m_data->setStrokeThickness(thickness);
}
void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
m_data->setFillColor(color);
UNUSED_PARAM(colorSpace); // FIXME
}
void GraphicsContext::setPlatformShouldAntialias(bool enable)
{
if (paintingDisabled())
return;
m_data->setAntialiasingEnabled(enable);
}
void GraphicsContext::setImageInterpolationQuality(InterpolationQuality)
{
notImplemented();
}
InterpolationQuality GraphicsContext::imageInterpolationQuality() const
{
notImplemented();
return InterpolationDefault;
}
}