| /* |
| * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> |
| * |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "GraphicsContext.h" |
| |
| #include "AffineTransform.h" |
| #include "CString.h" |
| #include "Color.h" |
| #include "Font.h" |
| #include "FontData.h" |
| #include "NotImplemented.h" |
| #include "Path.h" |
| #include "Pen.h" |
| #include <GraphicsDefs.h> |
| #include <Region.h> |
| #include <View.h> |
| #include <Window.h> |
| #include <stdio.h> |
| |
| |
| namespace WebCore { |
| |
| class GraphicsContextPlatformPrivate { |
| public: |
| GraphicsContextPlatformPrivate(BView* view); |
| ~GraphicsContextPlatformPrivate(); |
| |
| BView* m_view; |
| }; |
| |
| GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(BView* view) |
| : m_view(view) |
| { |
| } |
| |
| GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate() |
| { |
| } |
| |
| GraphicsContext::GraphicsContext(PlatformGraphicsContext* context) |
| : m_common(createGraphicsContextPrivate()) |
| , m_data(new GraphicsContextPlatformPrivate(context)) |
| { |
| setPaintingDisabled(!context); |
| } |
| |
| GraphicsContext::~GraphicsContext() |
| { |
| destroyGraphicsContextPrivate(m_common); |
| delete m_data; |
| } |
| |
| PlatformGraphicsContext* GraphicsContext::platformContext() const |
| { |
| return m_data->m_view; |
| } |
| |
| void GraphicsContext::savePlatformState() |
| { |
| m_data->m_view->PushState(); |
| } |
| |
| void GraphicsContext::restorePlatformState() |
| { |
| m_data->m_view->PopState(); |
| } |
| |
| // Draws a filled rectangle with a stroked border. |
| void GraphicsContext::drawRect(const IntRect& rect) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| m_data->m_view->FillRect(rect); |
| if (strokeStyle() != NoStroke) |
| m_data->m_view->StrokeRect(rect, getHaikuStrokeStyle()); |
| } |
| |
| // This is only used to draw borders. |
| void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| if (strokeStyle() == NoStroke) |
| return; |
| |
| m_data->m_view->StrokeLine(point1, point2, getHaikuStrokeStyle()); |
| } |
| |
| // This method is only used to draw the little circles used in lists. |
| void GraphicsContext::drawEllipse(const IntRect& rect) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| m_data->m_view->FillEllipse(rect); |
| if (strokeStyle() != NoStroke) |
| m_data->m_view->StrokeEllipse(rect, getHaikuStrokeStyle()); |
| } |
| |
| void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| m_data->m_view->StrokeArc(rect, startAngle, angleSpan, getHaikuStrokeStyle()); |
| } |
| |
| void GraphicsContext::strokePath() |
| { |
| notImplemented(); |
| } |
| |
| void GraphicsContext::drawConvexPolygon(size_t pointsLength, const FloatPoint* points, bool shouldAntialias) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| BPoint bPoints[pointsLength]; |
| for (size_t i = 0; i < pointsLength; i++) |
| bPoints[i] = points[i]; |
| |
| m_data->m_view->FillPolygon(bPoints, pointsLength); |
| if (strokeStyle() != NoStroke) |
| // Stroke with low color |
| m_data->m_view->StrokePolygon(bPoints, pointsLength, true, getHaikuStrokeStyle()); |
| } |
| |
| void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| rgb_color oldColor = m_data->m_view->HighColor(); |
| m_data->m_view->SetHighColor(color); |
| m_data->m_view->FillRect(rect); |
| m_data->m_view->SetHighColor(oldColor); |
| } |
| |
| void GraphicsContext::fillRect(const FloatRect& rect) |
| { |
| if (paintingDisabled()) |
| return; |
| } |
| |
| 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() || !color.alpha()) |
| return; |
| |
| notImplemented(); |
| // FIXME: A simple implementation could just use FillRoundRect if all |
| // the sizes are the same, or even if they are not. Otherwise several |
| // FillRect and FillArc calls are needed. |
| } |
| |
| void GraphicsContext::fillPath() |
| { |
| notImplemented(); |
| } |
| |
| void GraphicsContext::beginPath() |
| { |
| notImplemented(); |
| } |
| |
| void GraphicsContext::addPath(const Path& path) |
| { |
| notImplemented(); |
| } |
| |
| void GraphicsContext::clip(const FloatRect& rect) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| BRegion region(rect); |
| m_data->m_view->ConstrainClippingRegion(®ion); |
| } |
| |
| void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color) |
| { |
| // FIXME: implement |
| } |
| |
| void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| unsigned rectCount = rects.size(); |
| |
| // FIXME: maybe we should implement this with BShape? |
| |
| if (rects.size() > 1) { |
| BRegion region; |
| for (int i = 0; i < rectCount; ++i) |
| region.Include(BRect(rects[i])); |
| |
| m_data->m_view->SetHighColor(color); |
| m_data->m_view->StrokeRect(region.Frame(), B_MIXED_COLORS); |
| } |
| } |
| |
| void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| IntPoint endPoint = origin + IntSize(width, 0); |
| drawLine(origin, endPoint); |
| } |
| |
| void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&, int width, bool grammar) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect) |
| { |
| notImplemented(); |
| return rect; |
| } |
| |
| void GraphicsContext::beginTransparencyLayer(float opacity) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| void GraphicsContext::endTransparencyLayer() |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| void GraphicsContext::clearRect(const FloatRect& rect) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| void GraphicsContext::strokeRect(const FloatRect& rect, float width) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| float oldSize = m_data->m_view->PenSize(); |
| m_data->m_view->SetPenSize(width); |
| m_data->m_view->StrokeRect(rect, getHaikuStrokeStyle()); |
| m_data->m_view->SetPenSize(oldSize); |
| } |
| |
| void GraphicsContext::setLineCap(LineCap lineCap) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| cap_mode mode = B_BUTT_CAP; |
| switch (lineCap) { |
| case RoundCap: |
| mode = B_ROUND_CAP; |
| break; |
| case SquareCap: |
| mode = B_SQUARE_CAP; |
| break; |
| case ButtCap: |
| default: |
| break; |
| } |
| |
| m_data->m_view->SetLineMode(mode, m_data->m_view->LineJoinMode(), m_data->m_view->LineMiterLimit()); |
| } |
| |
| void GraphicsContext::setLineJoin(LineJoin lineJoin) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| join_mode mode = B_MITER_JOIN; |
| switch (lineJoin) { |
| case RoundJoin: |
| mode = B_ROUND_JOIN; |
| break; |
| case BevelJoin: |
| mode = B_BEVEL_JOIN; |
| break; |
| case MiterJoin: |
| default: |
| break; |
| } |
| |
| m_data->m_view->SetLineMode(m_data->m_view->LineCapMode(), mode, m_data->m_view->LineMiterLimit()); |
| } |
| |
| void GraphicsContext::setMiterLimit(float limit) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| m_data->m_view->SetLineMode(m_data->m_view->LineCapMode(), m_data->m_view->LineJoinMode(), limit); |
| } |
| |
| void GraphicsContext::setAlpha(float opacity) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| void GraphicsContext::setCompositeOperation(CompositeOperator op) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| drawing_mode mode = B_OP_COPY; |
| switch (op) { |
| case CompositeClear: |
| case CompositeCopy: |
| // Use the default above |
| break; |
| case CompositeSourceOver: |
| mode = B_OP_OVER; |
| break; |
| default: |
| printf("GraphicsContext::setCompositeOperation: Unsupported composite operation %s\n", |
| compositeOperatorName(op).utf8().data()); |
| } |
| m_data->m_view->SetDrawingMode(mode); |
| } |
| |
| void GraphicsContext::clip(const Path& path) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| m_data->m_view->ConstrainClippingRegion(path.platformPath()); |
| } |
| |
| void GraphicsContext::canvasClip(const Path& path) |
| { |
| clip(path); |
| } |
| |
| void GraphicsContext::clipOut(const Path& path) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*) |
| { |
| notImplemented(); |
| } |
| |
| AffineTransform GraphicsContext::getCTM() const |
| { |
| notImplemented(); |
| return AffineTransform(); |
| } |
| |
| void GraphicsContext::translate(float x, float y) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| IntPoint GraphicsContext::origin() |
| { |
| notImplemented(); |
| return IntPoint(0, 0); |
| } |
| |
| void GraphicsContext::rotate(float radians) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| void GraphicsContext::scale(const FloatSize& size) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| void GraphicsContext::clipOut(const IntRect& rect) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| void GraphicsContext::concatCTM(const AffineTransform& transform) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| void GraphicsContext::setPlatformShouldAntialias(bool enable) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| notImplemented(); |
| } |
| |
| void GraphicsContext::setImageInterpolationQuality(InterpolationQuality) |
| { |
| } |
| |
| void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) |
| { |
| notImplemented(); |
| } |
| |
| void GraphicsContext::setPlatformFont(const Font& font) |
| { |
| m_data->m_view->SetFont(font.primaryFont()->platformData().font()); |
| } |
| |
| void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| m_data->m_view->SetHighColor(color); |
| } |
| |
| pattern GraphicsContext::getHaikuStrokeStyle() |
| { |
| switch (strokeStyle()) { |
| case SolidStroke: |
| return B_SOLID_HIGH; |
| break; |
| case DottedStroke: |
| return B_MIXED_COLORS; |
| break; |
| case DashedStroke: |
| // FIXME: use a better dashed stroke! |
| notImplemented(); |
| return B_MIXED_COLORS; |
| break; |
| default: |
| return B_SOLID_LOW; |
| break; |
| } |
| } |
| |
| void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& strokeStyle) |
| { |
| // FIXME: see getHaikuStrokeStyle. |
| notImplemented(); |
| } |
| |
| void GraphicsContext::setPlatformStrokeThickness(float thickness) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| m_data->m_view->SetPenSize(thickness); |
| } |
| |
| void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace) |
| { |
| if (paintingDisabled()) |
| return; |
| |
| m_data->m_view->SetHighColor(color); |
| } |
| |
| void GraphicsContext::clearPlatformShadow() |
| { |
| notImplemented(); |
| } |
| |
| void GraphicsContext::setPlatformShadow(IntSize const&, int, Color const&, ColorSpace) |
| { |
| notImplemented(); |
| } |
| |
| } // namespace WebCore |
| |