📄 kwqpainter.cpp
字号:
/*
* Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
* Portions Copyright (c) 2005 Nokia Corporation, Inc. 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 "KWQPainter.h"
#include "KWQAssertions.h"
#include "KWQExceptions.h"
#include "KWQFontMetrics.h"
#include "KWQKHTMLPart.h"
#include "KWQPaintDevice.h"
#include "KWQPixmap.h"
#include "KWQPointArray.h"
#include "KWQPrinter.h"
#include "KWQPtrStack.h"
#include "KWQWidget.h"
#include "KWQFontFamily.h"
#include "WebCoreGraphicsBridge.h"
#include "WebCoreImageRenderer.h"
#include "WebCoreImageRendererFactory.h"
#include "WebCoreTextRenderer.h"
#include "WebCoreTextRendererFactory.h"
#include "WebCoreWidget.h"
#include "WebCoreGraphicsContext.h"
#include <e32std.h>
#include <fbs.h>
struct QPState
OOM_MODIFIED
{
QPState() : paintingDisabled(false) { }
QFont font;
QPen pen;
QBrush brush;
QRegion clip;
bool paintingDisabled;
TWebCoreSavedContext iSavedGc;
};
struct QPainterPrivate
OOM_MODIFIED
{
QPainterPrivate() : focusRingPath(0), focusRingWidth(0), focusRingOffset(0),
hasFocusRingColor(false), iGc(0) { }
~QPainterPrivate() {
delete focusRingPath;
}
QPState state;
QPtrStack<QPState> stack;
QRect *focusRingPath;
int focusRingWidth;
int focusRingOffset;
bool hasFocusRingColor;
QColor focusRingColor;
CWebCoreGraphicsContext* iGc;
};
QPainter::QPainter() : data(new QPainterPrivate), _isForPrinting(false), _usesInactiveTextBackgroundColor(false), _drawsFocusRing(true)
{
}
QPainter::QPainter(bool forPrinting) : data(new QPainterPrivate), _isForPrinting(forPrinting), _usesInactiveTextBackgroundColor(false), _drawsFocusRing(true)
{
}
QPainter::~QPainter()
{
delete data;
}
CWebCoreGraphicsContext& QPainter::Gc()
{
return *data->iGc;
}
void QPainter::SetGc(CWebCoreGraphicsContext& aGc)
{
data->iGc = &aGc;
}
QPaintDevice *QPainter::device() const
{
static QPrinter printer;
static QPaintDevice screen;
return _isForPrinting ? &printer : &screen;
}
const QFont &QPainter::font() const
{
return data->state.font;
}
void QPainter::setFont(const QFont &aFont)
{
data->state.font = aFont;
}
QFontMetrics QPainter::fontMetrics() const
{
return data->state.font;
}
const QPen &QPainter::pen() const
{
return data->state.pen;
}
void QPainter::setPen(const QPen &pen)
{
data->state.pen = pen;
}
void QPainter::setPen(PenStyle style)
{
data->state.pen.setStyle(style);
data->state.pen.setColor(Qt::black);
data->state.pen.setWidth(0);
}
void QPainter::setPen(QRgb rgb)
{
data->state.pen.setStyle(SolidLine);
data->state.pen.setColor(rgb);
data->state.pen.setWidth(0);
}
void QPainter::setBrush(const QBrush &brush)
{
data->state.brush = brush;
}
void QPainter::setBrush(BrushStyle style)
{
data->state.brush.setStyle(style);
data->state.brush.setColor(Qt::black);
}
void QPainter::setBrush(QRgb rgb)
{
data->state.brush.setStyle(SolidPattern);
data->state.brush.setColor(rgb);
}
const QBrush &QPainter::brush() const
{
return data->state.brush;
}
QRect QPainter::xForm(const QRect &aRect) const
{
// No difference between device and model coords, so the identity transform is ok.
return aRect;
}
void QPainter::save()
{
if( data->iGc )
data->state.iSavedGc = data->iGc->Save();
data->stack.push(new QPState(data->state));
}
void QPainter::restore()
{
if (data->stack.isEmpty()) {
return;
}
QPState *ps = data->stack.pop();
data->state = *ps;
delete ps;
if( data->iGc )
data->iGc->Restore( data->state.iSavedGc );
}
// Draws a filled rectangle with a stroked border.
void QPainter::drawRect(int x, int y, int w, int h)
{
CFbsBitGc* gContext = NULL;
if (data->iGc) {
gContext = &data->iGc->Gc();
}
if (data->state.paintingDisabled)
return;
if (data->state.brush.style() != NoBrush)
_fillRect(x, y, w, h, data->state.brush.color());
if (gContext) {
if (data->state.pen.style() != NoPen) {
gContext->SetBrushStyle(CGraphicsContext::ENullBrush);
_setColorFromPen();
TRect r(x, y, (x+w), (y+h));
gContext->DrawRect(xForm(r));
}
}
}
void QPainter::_setColorFromBrush()
{
TRgb brushColor = data->state.brush.color().Rgb();
CFbsBitGc* gContext = NULL;
if (data->iGc) {
gContext = &data->iGc->Gc();
}
if (gContext) {
gContext->SetBrushColor(brushColor);
gContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
// set pen too, otherwise border area is not drawn
gContext->SetPenColor(brushColor);
gContext->SetPenStyle(CGraphicsContext::ESolidPen);
}
}
void QPainter::_setColorFromPen()
{
TRgb penColor = data->state.pen.color().Rgb();
CFbsBitGc* gContext = NULL;
if (data->iGc) {
gContext = &data->iGc->Gc();
}
if (gContext) {
gContext->SetPenColor(penColor);
gContext->SetPenStyle(CGraphicsContext::ESolidPen);
}
}
// This is only used to draw borders.
void QPainter::drawLine(int x1, int y1, int x2, int y2)
{
CFbsBitGc* gContext = NULL;
if (data->iGc) {
gContext = &data->iGc->Gc();
}
if (data->state.paintingDisabled)
return;
PenStyle penStyle = data->state.pen.style();
if (penStyle == NoPen)
return;
_setColorFromPen();
if (gContext) {
switch(penStyle) {
case DotLine:
case DashLine: {
int d = data->state.pen.width();
if(d != 0) {
int dx = (x1 == x2) ? d : (penStyle == DashLine) ? 2*d : d;
int dy = (x1 == x2) ? ((penStyle == DashLine) ? 2*d : d ) : d;
//Need to do this because Symbian doesnt draw dotted lines with thickness
gContext->SetPenStyle(CGraphicsContext::ENullPen);
gContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
TRgb brushColor = data->state.pen.color().Rgb();
gContext->SetBrushColor(brushColor);
//Draw the first rect and the last rect
TPoint pt1((x1 == x2)? x1 - dx/2 : x1,(x1 == x2)? y1 : y1 - dy/2);
gContext->DrawRect(TRect(xForm(pt1),xForm(TSize(dx,dy))));
TPoint pt2((x1 == x2)? x1 - dx/2 : x2 - dx,(x1 == x2)? y2 - dy : y1 - dy/2);
gContext->DrawRect(TRect(xForm(pt2),xForm(TSize(dx,dy))));
//Calculate the length of the remaining segments and apply correction
//so that error because of remainder evens out
int length = (x1 == x2) ? (y2 - y1) : (x2 - x1);
length -= 2*((x1 == x2) ? dy : dx);
int n = length/((x1 == x2) ? dy : dx);
int reminder = length%d;
bool even = (n%2 == 0);
int delta = (x1 == x2) ? dy : dx;
delta -= (reminder) ? ((even) ? (delta - reminder)/2 : -reminder/2) : ((even) ? -delta/2 : 0);
int pos = ((x1 == x2) ? (y1 + dy) : (x1 + dx)) + delta;
//Draw the remaining rects
for(int i = 0; i < n/2 ; i++) {
TPoint pt3((x1 == x2) ? x1 - dx/2 : pos,(x1 == x2) ? pos : y1 - dy/2);
gContext->DrawRect(TRect(xForm(pt3),xForm(TSize(dx,dy))));
pos += (2*(( x1 == x2 ) ? dy : dx ));
}
}
break;
}
case SolidLine:
default:
gContext->DrawLine(xForm(TPoint(x1, y1)), xForm(TPoint(x2, y2)));
break;
}
}
}
// This method is only used to draw the little circles used in lists.
void QPainter::drawEllipse(int x, int y, int w, int h)
{
// This code can only handle circles, not ellipses. But khtml only
// uses it for circles.
ASSERT(w == h);
CFbsBitGc* gContext = NULL;
if (data->iGc) {
gContext = &data->iGc->Gc();
}
if (data->state.paintingDisabled)
return;
if ((gContext) && (data->state.brush.style() != NoBrush)) {
_setColorFromBrush();
gContext->DrawEllipse(xForm(TRect(x, y, x+w, y+h)));
}
if ((gContext) && (data->state.pen.style() != NoPen)) {
_setColorFromPen();
gContext->DrawEllipse(xForm(TRect(x, y, x+w, y+h)));
}
}
void QPainter::drawArc (int x, int y, int w, int h, int a, int alen)
{
// Only supports arc on circles. That's all khtml needs.
ASSERT(w == h);
if (data->state.paintingDisabled)
return;
if (data->state.pen.style() != NoPen) {
_setColorFromPen();
// NEEDS_IMPLEMENTATION
// data->iGc->DrawArc(TRect(x, y, x+w, y+h));
}
}
void QPainter::drawLineSegments(const QPointArray &points, int index, int nlines)
{
if (data->state.paintingDisabled)
return;
_drawPoints (points, 0, index, nlines, false);
}
void QPainter::drawPolyline(const QPointArray &points, int index, int npoints)
{
_drawPoints (points, 0, index, npoints, false);
}
void QPainter::drawPolygon(const QPointArray &points, bool winding, int index,
int npoints)
{
_drawPoints (points, winding, index, npoints, true);
}
void QPainter::drawConvexPolygon(const QPointArray &points)
{
_drawPoints (points, false, 0, -1, true);
}
void QPainter::_drawPoints (const QPointArray &_points, bool winding, int index, int _npoints, bool fill)
{
if (data->state.paintingDisabled)
return;
CFbsBitGc* gContext = NULL;
if (data->iGc) {
gContext = &data->iGc->Gc();
}
int npoints = _npoints != -1 ? _npoints : _points.size()-index;
// test for zero width
if (npoints==4 && ( (_points[index+0].y()==_points[index+1].y() && _points[index+2].y()==_points[index+3].y()) ||
(_points[index+0].x()==_points[index+3].x() && _points[index+1].x()==_points[index+2].x()) ))
return;
TPoint* points = new TPoint[npoints];
for (int i = 0; i < npoints; i++) {
points[i] = xForm(TPoint(_points[index+i].x(), _points[index+i].y()));
}
if (fill && data->state.brush.style() != NoBrush) {
_setColorFromBrush();
}
if (data->state.pen.style() != NoPen) {
_setColorFromPen();
}
if (gContext) {
if (fill) {
// qt and symbian coordinate systems are different
// ###hack, this relies on the order of points used in khtml
if (npoints==4) {
points[1].iY--;
points[2].iY--;
points[2].iX--;
points[3].iX--;
if (points[0].iY>points[3].iY)
points[0].iY--;
if (points[1].iX>points[0].iX)
points[1].iX--;
if (points[2].iY<points[1].iY)
points[2].iY++;
if (points[3].iX<points[2].iX)
points[3].iX++;
}
gContext->DrawPolygon(points, npoints, CGraphicsContext::EAlternate);
}
else {
gContext->DrawPolyLine(points, npoints);
}
}
delete[] points;
}
void QPainter::drawPixmap(const QPoint &p, const QPixmap &pix)
{
drawPixmap( p.x(), p.y(), pix.width(), pix.height(), pix, 0, 0, pix.width(), pix.height(), 0 );
}
void QPainter::drawPixmap(const QPoint &p, const QPixmap &pix, const QRect &r)
{
drawPixmap( p.x(), p.y(), pix.width(), pix.height(), pix, r.top(), r.left(), r.width(), r.height(), 0 );
}
void QPainter::drawPixmap( int x, int y, const QPixmap & pix,
int sx, int sy, int sw, int sh, int compositeOperator)
{
drawPixmap( x, y, pix.width(), pix.height(), pix, sx, sy, sw, sh, 0 );
}
void QPainter::drawPixmap( int x, int y, int w, int h, const QPixmap& pixmap,
int sx, int sy, int sw, int sh, int compositeOperator)
{
if (data->state.paintingDisabled)
return;
if( pixmap.isNull() ) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -