⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 graphicscontextcg.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. * Copyright (C) 2008 Eric Seidel <eric@webkit.org> * * 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.  */#define _USE_MATH_DEFINES 1#include "config.h"#include "GraphicsContext.h"#include "TransformationMatrix.h"#include "FloatConversion.h"#include "GraphicsContextPrivate.h"#include "GraphicsContextPlatformPrivateCG.h"#include "ImageBuffer.h"#include "KURL.h"#include "Path.h"#include "Pattern.h"#include <CoreGraphics/CGBitmapContext.h>#include <CoreGraphics/CGPDFContext.h>#include <wtf/MathExtras.h>#include <wtf/OwnArrayPtr.h>#include <wtf/RetainPtr.h>#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)#define HAVE_CG_INTERPOLATION_MEDIUM 1#endifusing namespace std;namespace WebCore {static void setCGFillColor(CGContextRef context, const Color& color){    CGFloat red, green, blue, alpha;    color.getRGBA(red, green, blue, alpha);    CGContextSetRGBFillColor(context, red, green, blue, alpha);}static void setCGStrokeColor(CGContextRef context, const Color& color){    CGFloat red, green, blue, alpha;    color.getRGBA(red, green, blue, alpha);    CGContextSetRGBStrokeColor(context, red, green, blue, alpha);}GraphicsContext::GraphicsContext(CGContextRef cgContext)    : m_common(createGraphicsContextPrivate())    , m_data(new GraphicsContextPlatformPrivate(cgContext)){    setPaintingDisabled(!cgContext);    if (cgContext) {        // Make sure the context starts in sync with our state.        setPlatformFillColor(fillColor());        setPlatformStrokeColor(strokeColor());    }}GraphicsContext::~GraphicsContext(){    destroyGraphicsContextPrivate(m_common);    delete m_data;}CGContextRef GraphicsContext::platformContext() const{    ASSERT(!paintingDisabled());    ASSERT(m_data->m_cgContext);    return m_data->m_cgContext;}void GraphicsContext::savePlatformState(){    // 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());    m_data->save();}void GraphicsContext::restorePlatformState(){    // 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());    m_data->restore();    m_data->m_userToDeviceTransformKnownToBeIdentity = false;}// Draws a filled rectangle with a stroked border.void GraphicsContext::drawRect(const IntRect& rect){    // FIXME: this function does not handle patterns and gradients    // like drawPath does, it probably should.    if (paintingDisabled())        return;    CGContextRef context = platformContext();    if (fillColor().alpha())        CGContextFillRect(context, rect);    if (strokeStyle() != NoStroke && strokeColor().alpha()) {        // We do a fill of four rects to simulate the stroke of a border.        Color oldFillColor = fillColor();        if (oldFillColor != strokeColor())            setCGFillColor(context, strokeColor());        CGRect rects[4] = {            FloatRect(rect.x(), rect.y(), rect.width(), 1),            FloatRect(rect.x(), rect.bottom() - 1, rect.width(), 1),            FloatRect(rect.x(), rect.y() + 1, 1, rect.height() - 2),            FloatRect(rect.right() - 1, rect.y() + 1, 1, rect.height() - 2)        };        CGContextFillRects(context, rects, 4);        if (oldFillColor != strokeColor())            setCGFillColor(context, oldFillColor);    }}// This is only used to draw borders.void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2){    if (paintingDisabled())        return;    if (strokeStyle() == NoStroke || !strokeColor().alpha())        return;    float width = strokeThickness();    FloatPoint p1 = point1;    FloatPoint p2 = point2;    bool isVerticalLine = (p1.x() == p2.x());        // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic    // works out.  For example, with a border width of 3, KHTML will pass us (y1+y2)/2, e.g.,    // (50+53)/2 = 103/2 = 51 when we want 51.5.  It is always true that an even width gave    // us a perfect position, but an odd width gave us a position that is off by exactly 0.5.    if (strokeStyle() == DottedStroke || strokeStyle() == DashedStroke) {        if (isVerticalLine) {            p1.move(0, width);            p2.move(0, -width);        } else {            p1.move(width, 0);            p2.move(-width, 0);        }    }        if (((int)width) % 2) {        if (isVerticalLine) {            // We're a vertical line.  Adjust our x.            p1.move(0.5f, 0.0f);            p2.move(0.5f, 0.0f);        } else {            // We're a horizontal line. Adjust our y.            p1.move(0.0f, 0.5f);            p2.move(0.0f, 0.5f);        }    }        int patWidth = 0;    switch (strokeStyle()) {        case NoStroke:        case SolidStroke:            break;        case DottedStroke:            patWidth = (int)width;            break;        case DashedStroke:            patWidth = 3 * (int)width;            break;    }    CGContextRef context = platformContext();        if (shouldAntialias())        CGContextSetShouldAntialias(context, false);    if (patWidth) {        CGContextSaveGState(context);        // Do a rect fill of our endpoints.  This ensures we always have the        // appearance of being a border.  We then draw the actual dotted/dashed line.        setCGFillColor(context, strokeColor());  // The save/restore make it safe to mutate the fill color here without setting it back to the old color.        if (isVerticalLine) {            CGContextFillRect(context, FloatRect(p1.x() - width / 2, p1.y() - width, width, width));            CGContextFillRect(context, FloatRect(p2.x() - width / 2, p2.y(), width, width));        } else {            CGContextFillRect(context, FloatRect(p1.x() - width, p1.y() - width / 2, width, width));            CGContextFillRect(context, FloatRect(p2.x(), p2.y() - width / 2, width, width));        }        // Example: 80 pixels with a width of 30 pixels.        // Remainder is 20.  The maximum pixels of line we could paint        // will be 50 pixels.        int distance = (isVerticalLine ? (point2.y() - point1.y()) : (point2.x() - point1.x())) - 2*(int)width;        int remainder = distance % patWidth;        int coverage = distance - remainder;        int numSegments = coverage / patWidth;        float patternOffset = 0.0f;        // Special case 1px dotted borders for speed.        if (patWidth == 1)            patternOffset = 1.0f;        else {            bool evenNumberOfSegments = numSegments % 2 == 0;            if (remainder)                evenNumberOfSegments = !evenNumberOfSegments;            if (evenNumberOfSegments) {                if (remainder) {                    patternOffset += patWidth - remainder;                    patternOffset += remainder / 2;                } else                    patternOffset = patWidth / 2;            } else {                if (remainder)                    patternOffset = (patWidth - remainder)/2;            }        }                const CGFloat dottedLine[2] = { patWidth, patWidth };        CGContextSetLineDash(context, patternOffset, dottedLine, 2);    }    CGContextBeginPath(context);    CGContextMoveToPoint(context, p1.x(), p1.y());    CGContextAddLineToPoint(context, p2.x(), p2.y());    CGContextStrokePath(context);    if (patWidth)        CGContextRestoreGState(context);            if (shouldAntialias())        CGContextSetShouldAntialias(context, true);}// This method is only used to draw the little circles used in lists.void GraphicsContext::drawEllipse(const IntRect& rect){    // FIXME: CG added CGContextAddEllipseinRect in Tiger, so we should be able to quite easily draw an ellipse.    // This code can only handle circles, not ellipses. But khtml only    // uses it for circles.    ASSERT(rect.width() == rect.height());    if (paintingDisabled())        return;            CGContextRef context = platformContext();    CGContextBeginPath(context);    float r = (float)rect.width() / 2;    CGContextAddArc(context, rect.x() + r, rect.y() + r, r, 0.0f, 2.0f * piFloat, 0);    CGContextClosePath(context);    drawPath();}void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan){     if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f || !strokeColor().alpha())        return;        CGContextRef context = platformContext();    CGContextSaveGState(context);    CGContextBeginPath(context);    CGContextSetShouldAntialias(context, false);        int x = rect.x();    int y = rect.y();    float w = (float)rect.width();    float h = (float)rect.height();    float scaleFactor = h / w;    float reverseScaleFactor = w / h;        if (w != h)        scale(FloatSize(1, scaleFactor));        float hRadius = w / 2;    float vRadius = h / 2;    float fa = startAngle;    float falen =  fa + angleSpan;    float start = -fa * piFloat / 180.0f;    float end = -falen * piFloat / 180.0f;    CGContextAddArc(context, x + hRadius, (y + vRadius) * reverseScaleFactor, hRadius, start, end, true);    if (w != h)        scale(FloatSize(1, reverseScaleFactor));            float width = strokeThickness();    int patWidth = 0;        switch (strokeStyle()) {        case DottedStroke:            patWidth = (int)(width / 2);            break;        case DashedStroke:            patWidth = 3 * (int)(width / 2);            break;        default:            break;    }        if (patWidth) {        // Example: 80 pixels with a width of 30 pixels.        // Remainder is 20.  The maximum pixels of line we could paint        // will be 50 pixels.        int distance;        if (hRadius == vRadius)            distance = static_cast<int>((piFloat * hRadius) / 2.0f);        else // We are elliptical and will have to estimate the distance            distance = static_cast<int>((piFloat * sqrtf((hRadius * hRadius + vRadius * vRadius) / 2.0f)) / 2.0f);                int remainder = distance % patWidth;        int coverage = distance - remainder;        int numSegments = coverage / patWidth;        float patternOffset = 0.0f;        // Special case 1px dotted borders for speed.        if (patWidth == 1)            patternOffset = 1.0f;        else {            bool evenNumberOfSegments = numSegments % 2 == 0;            if (remainder)                evenNumberOfSegments = !evenNumberOfSegments;            if (evenNumberOfSegments) {                if (remainder) {                    patternOffset += patWidth - remainder;                    patternOffset += remainder / 2.0f;                } else                    patternOffset = patWidth / 2.0f;            } else {                if (remainder)                    patternOffset = (patWidth - remainder) / 2.0f;            }        }            const CGFloat dottedLine[2] = { patWidth, patWidth };        CGContextSetLineDash(context, patternOffset, dottedLine, 2);    }    CGContextStrokePath(context);        CGContextRestoreGState(context);}void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool antialiased){    if (paintingDisabled() || !fillColor().alpha() && (strokeThickness() <= 0 || strokeStyle() == NoStroke))        return;    if (npoints <= 1)        return;    CGContextRef context = platformContext();    if (antialiased != shouldAntialias())        CGContextSetShouldAntialias(context, antialiased);        CGContextBeginPath(context);    CGContextMoveToPoint(context, points[0].x(), points[0].y());    for (size_t i = 1; i < npoints; i++)        CGContextAddLineToPoint(context, points[i].x(), points[i].y());    CGContextClosePath(context);    drawPath();        if (antialiased != shouldAntialias())        CGContextSetShouldAntialias(context, shouldAntialias());}void GraphicsContext::applyStrokePattern(){    CGContextRef cgContext = platformContext();        CGPatternRef platformPattern = m_common->state.strokePattern.get()->createPlatformPattern(getCTM());    if (!platformPattern)        return;    CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(0);    CGContextSetStrokeColorSpace(cgContext, patternSpace);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -