📄 graphicscontextqt.cpp
字号:
/* * Copyright (C) 2006 Dirk Mueller <mueller@kde.org> * Copyright (C) 2006 Zack Rusin <zack@kde.org> * Copyright (C) 2006 George Staikos <staikos@kde.org> * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org> * Copyright (C) 2006 Allan Sandfeld Jensen <sandfeld@kde.org> * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2008 Dirk Schulze <vbs85@gmx.de> * * 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"#ifdef Q_WS_WIN#include <windows.h>#endif#include "TransformationMatrix.h"#include "Color.h"#include "FloatConversion.h"#include "Font.h"#include "GraphicsContext.h"#include "GraphicsContextPrivate.h"#include "ImageBuffer.h"#include "Path.h"#include "Pattern.h"#include "Pen.h"#include "NotImplemented.h"#include <QDebug>#include <QGradient>#include <QPainter>#include <QPaintDevice>#include <QPaintEngine>#include <QPainterPath>#include <QPixmap>#include <QPolygonF>#include <QStack>#include <QVector>#ifndef M_PI#define M_PI 3.14159265358979323846#endifnamespace WebCore {static inline QPainter::CompositionMode toQtCompositionMode(CompositeOperator op){ switch (op) { case CompositeClear: return QPainter::CompositionMode_Clear; case CompositeCopy: return QPainter::CompositionMode_Source; case CompositeSourceOver: return QPainter::CompositionMode_SourceOver; case CompositeSourceIn: return QPainter::CompositionMode_SourceIn; case CompositeSourceOut: return QPainter::CompositionMode_SourceOut; case CompositeSourceAtop: return QPainter::CompositionMode_SourceAtop; case CompositeDestinationOver: return QPainter::CompositionMode_DestinationOver; case CompositeDestinationIn: return QPainter::CompositionMode_DestinationIn; case CompositeDestinationOut: return QPainter::CompositionMode_DestinationOut; case CompositeDestinationAtop: return QPainter::CompositionMode_DestinationAtop; case CompositeXOR: return QPainter::CompositionMode_Xor; case CompositePlusDarker: return QPainter::CompositionMode_SourceOver; case CompositeHighlight: return QPainter::CompositionMode_SourceOver; case CompositePlusLighter: return QPainter::CompositionMode_SourceOver; } return QPainter::CompositionMode_SourceOver;}static inline Qt::PenCapStyle toQtLineCap(LineCap lc){ switch (lc) { case ButtCap: return Qt::FlatCap; case RoundCap: return Qt::RoundCap; case SquareCap: return Qt::SquareCap; } return Qt::FlatCap;}static inline Qt::PenJoinStyle toQtLineJoin(LineJoin lj){ switch (lj) { case MiterJoin: return Qt::SvgMiterJoin; case RoundJoin: return Qt::RoundJoin; case BevelJoin: return Qt::BevelJoin; } return Qt::MiterJoin;}static Qt::PenStyle toQPenStyle(StrokeStyle style){ switch (style) { case NoStroke: return Qt::NoPen; break; case SolidStroke: return Qt::SolidLine; break; case DottedStroke: return Qt::DotLine; break; case DashedStroke: return Qt::DashLine; break; } qWarning("couldn't recognize the pen style"); return Qt::NoPen;}struct TransparencyLayer{ TransparencyLayer(const QPainter* p, const QRect &rect) : pixmap(rect.width(), rect.height()) { offset = rect.topLeft(); pixmap.fill(Qt::transparent); painter.begin(&pixmap); painter.setRenderHint(QPainter::Antialiasing, p->testRenderHint(QPainter::Antialiasing)); painter.translate(-offset); painter.setPen(p->pen()); painter.setBrush(p->brush()); painter.setTransform(p->transform(), true); painter.setOpacity(p->opacity()); painter.setFont(p->font()); if (painter.paintEngine()->hasFeature(QPaintEngine::PorterDuff)) painter.setCompositionMode(p->compositionMode()); painter.setClipPath(p->clipPath()); } TransparencyLayer() { } QPixmap pixmap; QPoint offset; QPainter painter; qreal opacity;private: TransparencyLayer(const TransparencyLayer &) {} TransparencyLayer & operator=(const TransparencyLayer &) { return *this; }};class GraphicsContextPlatformPrivate{public: GraphicsContextPlatformPrivate(QPainter* painter); ~GraphicsContextPlatformPrivate(); inline QPainter* p() { if (layers.isEmpty()) { if (redirect) return redirect; return painter; } else return &layers.top()->painter; } bool antiAliasingForRectsAndLines; QStack<TransparencyLayer *> layers; QPainter* redirect; QBrush solidColor; // Only used by SVG for now. QPainterPath currentPath;private: QPainter* painter;};GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p){ painter = p; redirect = 0; solidColor = QBrush(Qt::black); if (painter) { // use the default the QPainter was constructed with antiAliasingForRectsAndLines = painter->testRenderHint(QPainter::Antialiasing); // FIXME: Maybe only enable in SVG mode? painter->setRenderHint(QPainter::Antialiasing, true); } else { antiAliasingForRectsAndLines = false; }}GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate(){}GraphicsContext::GraphicsContext(PlatformGraphicsContext* context) : m_common(createGraphicsContextPrivate()) , m_data(new GraphicsContextPlatformPrivate(context)){ setPaintingDisabled(!context); if (context) { // Make sure the context starts in sync with our state. setPlatformFillColor(fillColor()); setPlatformStrokeColor(strokeColor()); }}GraphicsContext::~GraphicsContext(){ while(!m_data->layers.isEmpty()) endTransparencyLayer(); destroyGraphicsContextPrivate(m_common); delete m_data;}PlatformGraphicsContext* GraphicsContext::platformContext() const{ return m_data->p();}TransformationMatrix GraphicsContext::getCTM() const{ QTransform matrix(platformContext()->combinedTransform()); return TransformationMatrix(matrix.m11(), matrix.m12(), 0, matrix.m13(), matrix.m21(), matrix.m22(), 0, matrix.m23(), 0, 0, 1, 0, matrix.m31(), matrix.m32(), 0, matrix.m33());}void GraphicsContext::savePlatformState(){ m_data->p()->save();}void GraphicsContext::restorePlatformState(){ m_data->p()->restore(); if (!m_data->currentPath.isEmpty() && m_common->state.pathTransform.isInvertible()) { QTransform matrix = m_common->state.pathTransform; m_data->currentPath = m_data->currentPath * matrix; }}/* FIXME: DISABLED WHILE MERGING BACK FROM UNITYvoid GraphicsContext::drawTextShadow(const TextRun& run, const IntPoint& point, const FontStyle& style){ if (paintingDisabled()) return; if (m_data->shadow.isNull()) return; TextShadow* shadow = &m_data->shadow; if (shadow->blur <= 0) { Pen p = pen(); setPen(shadow->color); font().drawText(this, run, style, IntPoint(point.x() + shadow->x, point.y() + shadow->y)); setPen(p); } else { const int thickness = shadow->blur; // FIXME: OPTIMIZE: limit the area to only the actually painted area + 2*thickness const int w = m_data->p()->device()->width(); const int h = m_data->p()->device()->height(); const QRgb color = qRgb(255, 255, 255); const QRgb bgColor = qRgb(0, 0, 0); QImage image(QSize(w, h), QImage::Format_ARGB32); image.fill(bgColor); QPainter p; Pen curPen = pen(); p.begin(&image); setPen(color); m_data->redirect = &p; font().drawText(this, run, style, IntPoint(point.x() + shadow->x, point.y() + shadow->y)); m_data->redirect = 0; p.end(); setPen(curPen); int md = thickness * thickness; // max-dist^2 // blur map/precalculated shadow-decay float* bmap = (float*) alloca(sizeof(float) * (md + 1)); for (int n = 0; n <= md; n++) { float f; f = n / (float) (md + 1); f = 1.0 - f * f; bmap[n] = f; } float factor = 0.0; // maximal potential opacity-sum for (int n = -thickness; n <= thickness; n++) { for (int m = -thickness; m <= thickness; m++) { int d = n * n + m * m; if (d <= md) factor += bmap[d]; } } // alpha map float* amap = (float*) alloca(sizeof(float) * (h * w)); memset(amap, 0, h * w * (sizeof(float))); for (int j = thickness; j<h-thickness; j++) { for (int i = thickness; i<w-thickness; i++) { QRgb col = image.pixel(i,j); if (col == bgColor) continue; float g = qAlpha(col); g = g / 255; for (int n = -thickness; n <= thickness; n++) { for (int m = -thickness; m <= thickness; m++) { int d = n * n + m * m; if (d > md) continue; float f = bmap[d]; amap[(i + m) + (j + n) * w] += (g * f); } } } } QImage res(QSize(w,h),QImage::Format_ARGB32); int r = shadow->color.red(); int g = shadow->color.green(); int b = shadow->color.blue(); int a1 = shadow->color.alpha(); // arbitratry factor adjustment to make shadows more solid. factor = 1.333 / factor; for (int j = 0; j < h; j++) { for (int i = 0; i < w; i++) { int a = (int) (amap[i + j * w] * factor * a1); if (a > 255) a = 255; res.setPixel(i,j, qRgba(r, g, b, a)); } } m_data->p()->drawImage(0, 0, res, 0, 0, -1, -1, Qt::DiffuseAlphaDither | Qt::ColorOnly | Qt::PreferDither); }}*/// Draws a filled rectangle with a stroked border.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -