diff options
Diffstat (limited to 'WebCore/platform/graphics/qt')
-rw-r--r-- | WebCore/platform/graphics/qt/FontPlatformDataQt.cpp | 2 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/FontQt.cpp | 81 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/GradientQt.cpp | 17 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/GraphicsContextQt.cpp | 138 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/ImageBufferQt.cpp | 107 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/ImageQt.cpp | 58 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/ImageSourceQt.cpp | 2 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp | 58 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h | 43 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/PathQt.cpp | 80 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/PatternQt.cpp | 5 | ||||
-rw-r--r-- | WebCore/platform/graphics/qt/TransformationMatrixQt.cpp | 167 |
12 files changed, 458 insertions, 300 deletions
diff --git a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp index ea51fe8..f0dd3ea 100644 --- a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp +++ b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp @@ -61,12 +61,14 @@ FontPlatformData::FontPlatformData(const QFont& font, bool bold) { } +#if ENABLE(SVG_FONTS) FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) : m_size(size) , m_bold(bold) , m_oblique(oblique) { } +#endif FontPlatformData::FontPlatformData() : m_size(0.0f) diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index deeea99..9ed5915 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -1,6 +1,7 @@ /* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) Copyright (C) 2008 Holger Hans Peter Freyther + Copyright (C) 2009 Dirk Schulze <krit@webkit.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -24,11 +25,18 @@ #include "FontFallbackList.h" #include "FontSelector.h" +#include "Gradient.h" #include "GraphicsContext.h" -#include <QTextLayout> -#include <QPainter> -#include <QFontMetrics> +#include "Pattern.h" +#include "TransformationMatrix.h" + +#include <QBrush> #include <QFontInfo> +#include <QFontMetrics> +#include <QPainter> +#include <QPainterPath> +#include <QPen> +#include <QTextLayout> #include <qalgorithms.h> #include <qdebug.h> @@ -37,20 +45,27 @@ #if QT_VERSION >= 0x040400 namespace WebCore { -static QString qstring(const TextRun& run) +static const QString qstring(const TextRun& run) +{ + //We don't detach + return QString::fromRawData((const QChar *)run.characters(), run.length()); +} + +static const QString fixSpacing(const QString &string) { - QString string((QChar *)run.characters(), run.length()); - QChar *uc = string.data(); + //Only detach if we're actually changing something + QString possiblyDetached = string; for (int i = 0; i < string.length(); ++i) { - if (Font::treatAsSpace(uc[i].unicode())) - uc[i] = 0x20; - else if (Font::treatAsZeroWidthSpace(uc[i].unicode())) - uc[i] = 0x200c; + const QChar c = string.at(i); + if (c.unicode() != 0x20 && Font::treatAsSpace(c.unicode())) { + possiblyDetached[i] = 0x20; //detach + } else if (c.unicode() != 0x200c && Font::treatAsZeroWidthSpace(c.unicode())) { + possiblyDetached[i] = 0x200c; //detach + } } - return string; + return possiblyDetached; } - static QTextLine setupLayout(QTextLayout* layout, const TextRun& style) { int flags = style.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight; @@ -72,10 +87,32 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float to = run.length(); QPainter *p = ctx->platformContext(); - Color color = ctx->fillColor(); - p->setPen(QColor(color)); - QString string = qstring(run); + if (ctx->textDrawingMode() & cTextFill) { + if (ctx->fillGradient()) { + QBrush brush(*ctx->fillGradient()->platformGradient()); + brush.setTransform(ctx->fillGradient()->gradientSpaceTransform()); + p->setPen(QPen(brush, 0)); + } else if (ctx->fillPattern()) { + TransformationMatrix affine; + p->setPen(QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0)); + } else + p->setPen(QColor(ctx->fillColor())); + } + + if (ctx->textDrawingMode() & cTextStroke) { + if (ctx->strokeGradient()) { + QBrush brush(*ctx->strokeGradient()->platformGradient()); + brush.setTransform(ctx->strokeGradient()->gradientSpaceTransform()); + p->setPen(QPen(brush, ctx->strokeThickness())); + } else if (ctx->strokePattern()) { + TransformationMatrix affine; + p->setPen(QPen(QBrush(ctx->strokePattern()->createPlatformPattern(affine)), ctx->strokeThickness())); + } else + p->setPen(QPen(QColor(ctx->strokeColor()), ctx->strokeThickness())); + } + + const QString string = fixSpacing(qstring(run)); // text shadow IntSize shadowSize; @@ -137,14 +174,20 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float p->drawText(pt, string, flags, run.padding()); p->restore(); } - p->drawText(pt, string, flags, run.padding()); + if (ctx->textDrawingMode() & cTextStroke) { + QPainterPath path; + path.addText(pt, font(), string); + p->strokePath(path, p->pen()); + } + if (ctx->textDrawingMode() & cTextFill) + p->drawText(pt, string, flags, run.padding()); } float Font::floatWidthForComplexText(const TextRun& run) const { if (!run.length()) return 0; - QString string = qstring(run); + const QString string = fixSpacing(qstring(run)); QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); int w = int(line.naturalTextWidth()); @@ -157,7 +200,7 @@ float Font::floatWidthForComplexText(const TextRun& run) const int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool includePartialGlyphs) const { - QString string = qstring(run); + const QString string = fixSpacing(qstring(run)); QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); return line.xToCursor(position); @@ -165,7 +208,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const { - QString string = qstring(run); + const QString string = fixSpacing(qstring(run)); QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); diff --git a/WebCore/platform/graphics/qt/GradientQt.cpp b/WebCore/platform/graphics/qt/GradientQt.cpp index a0edf8d..1e71f58 100644 --- a/WebCore/platform/graphics/qt/GradientQt.cpp +++ b/WebCore/platform/graphics/qt/GradientQt.cpp @@ -28,9 +28,10 @@ #include "Gradient.h" #include "CSSParser.h" -#include "NotImplemented.h" +#include "GraphicsContext.h" #include <QGradient> +#include <QPainter> namespace WebCore { @@ -66,12 +67,24 @@ QGradient* Gradient::platformGradient() ++stopIterator; } + switch(m_spreadMethod) { + case SpreadMethodPad: + m_gradient->setSpread(QGradient::PadSpread); + break; + case SpreadMethodReflect: + m_gradient->setSpread(QGradient::ReflectSpread); + break; + case SpreadMethodRepeat: + m_gradient->setSpread(QGradient::RepeatSpread); + break; + } + return m_gradient; } void Gradient::fill(GraphicsContext* context, const FloatRect& rect) { - notImplemented(); + context->platformContext()->fillRect(rect, *platformGradient()); } } //namespace diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 2e7cdcb..ccf4b06 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -51,6 +51,7 @@ #include "Pen.h" #include "NotImplemented.h" +#include <QBrush> #include <QDebug> #include <QGradient> #include <QPainter> @@ -152,22 +153,6 @@ static Qt::PenStyle toQPenStyle(StrokeStyle style) return Qt::NoPen; } -static inline QGradient applySpreadMethod(QGradient gradient, GradientSpreadMethod spreadMethod) -{ - switch (spreadMethod) { - case SpreadMethodPad: - gradient.setSpread(QGradient::PadSpread); - break; - case SpreadMethodReflect: - gradient.setSpread(QGradient::ReflectSpread); - break; - case SpreadMethodRepeat: - gradient.setSpread(QGradient::RepeatSpread); - break; - } - return gradient; -} - struct TransparencyLayer { TransparencyLayer(const QPainter* p, const QRect &rect) @@ -282,7 +267,11 @@ PlatformGraphicsContext* GraphicsContext::platformContext() const TransformationMatrix GraphicsContext::getCTM() const { - return platformContext()->combinedMatrix(); + 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() @@ -295,7 +284,7 @@ void GraphicsContext::restorePlatformState() m_data->p()->restore(); if (!m_data->currentPath.isEmpty() && m_common->state.pathTransform.isInvertible()) { - QMatrix matrix = m_common->state.pathTransform; + QTransform matrix = m_common->state.pathTransform; m_data->currentPath = m_data->currentPath * matrix; } } @@ -458,13 +447,21 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) if (paintingDisabled()) return; + StrokeStyle style = strokeStyle(); + Color color = strokeColor(); + if (style == NoStroke || !color.alpha()) + return; + + float width = strokeThickness(); + FloatPoint p1 = point1; FloatPoint p2 = point2; + bool isVerticalLine = (p1.x() == p2.x()); QPainter *p = m_data->p(); const bool antiAlias = p->testRenderHint(QPainter::Antialiasing); p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines); - adjustLineToPixelBoundaries(p1, p2, strokeThickness(), strokeStyle()); + adjustLineToPixelBoundaries(p1, p2, width, style); IntSize shadowSize; int shadowBlur; @@ -477,8 +474,76 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) p->restore(); } + int patWidth = 0; + switch (style) { + case NoStroke: + case SolidStroke: + break; + case DottedStroke: + patWidth = (int)width; + break; + case DashedStroke: + patWidth = 3 * (int)width; + break; + } + + if (patWidth) { + p->save(); + + // 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. + if (isVerticalLine) { + p->fillRect(FloatRect(p1.x() - width / 2, p1.y() - width, width, width), QColor(color)); + p->fillRect(FloatRect(p2.x() - width / 2, p2.y(), width, width), QColor(color)); + } else { + p->fillRect(FloatRect(p1.x() - width, p1.y() - width / 2, width, width), QColor(color)); + p->fillRect(FloatRect(p2.x(), p2.y() - width / 2, width, width), QColor(color)); + } + + // 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; + } + } + + QVector<qreal> dashes; + dashes << qreal(patWidth) / width << qreal(patWidth) / width; + + QPen pen = p->pen(); + pen.setWidthF(width); + pen.setCapStyle(Qt::FlatCap); + pen.setDashPattern(dashes); + pen.setDashOffset(patternOffset / width); + p->setPen(pen); + } + p->drawLine(p1, p2); + if (patWidth) + p->restore(); + p->setRenderHint(QPainter::Antialiasing, antiAlias); } @@ -553,9 +618,9 @@ void GraphicsContext::fillPath() break; } case GradientColorSpace: - QGradient* gradient = m_common->state.fillGradient->platformGradient(); - *gradient = applySpreadMethod(*gradient, spreadMethod()); - p->fillPath(path, QBrush(*gradient)); + QBrush brush(*m_common->state.fillGradient->platformGradient()); + brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform()); + p->fillPath(path, brush); break; } m_data->currentPath = QPainterPath(); @@ -583,9 +648,9 @@ void GraphicsContext::strokePath() break; } case GradientColorSpace: { - QGradient* gradient = m_common->state.strokeGradient->platformGradient(); - *gradient = applySpreadMethod(*gradient, spreadMethod()); - pen.setBrush(QBrush(*gradient)); + QBrush brush(*m_common->state.strokeGradient->platformGradient()); + brush.setTransform(m_common->state.strokeGradient->gradientSpaceTransform()); + pen.setBrush(brush); p->setPen(pen); p->strokePath(path, pen); break; @@ -612,7 +677,9 @@ void GraphicsContext::fillRect(const FloatRect& rect) break; } case GradientColorSpace: - p->fillRect(rect, QBrush(*(m_common->state.fillGradient.get()->platformGradient()))); + QBrush brush(*m_common->state.fillGradient->platformGradient()); + brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform()); + p->fillRect(rect, brush); break; } m_data->currentPath = QPainterPath(); @@ -663,10 +730,7 @@ void GraphicsContext::clip(const FloatRect& rect) if (paintingDisabled()) return; - QPainter *p = m_data->p(); - if (p->clipRegion().isEmpty()) - p->setClipRect(rect); - else p->setClipRect(rect, Qt::IntersectClip); + m_data->p()->setClipRect(rect, Qt::IntersectClip); } void GraphicsContext::clipPath(WindRule clipRule) @@ -818,7 +882,7 @@ void GraphicsContext::clearRect(const FloatRect& rect) QPainter::CompositionMode currentCompositionMode = p->compositionMode(); if (p->paintEngine()->hasFeature(QPaintEngine::PorterDuff)) p->setCompositionMode(QPainter::CompositionMode_Source); - p->eraseRect(rect); + p->fillRect(rect, Qt::transparent); if (p->paintEngine()->hasFeature(QPaintEngine::PorterDuff)) p->setCompositionMode(currentCompositionMode); } @@ -939,7 +1003,7 @@ void GraphicsContext::translate(float x, float y) m_data->p()->translate(x, y); if (!m_data->currentPath.isEmpty()) { - QMatrix matrix; + QTransform matrix; m_data->currentPath = m_data->currentPath * matrix.translate(-x, -y); m_common->state.pathTransform.translate(x, y); } @@ -961,7 +1025,7 @@ void GraphicsContext::rotate(float radians) m_data->p()->rotate(180/M_PI*radians); if (!m_data->currentPath.isEmpty()) { - QMatrix matrix; + QTransform matrix; m_data->currentPath = m_data->currentPath * matrix.rotate(-180/M_PI*radians); m_common->state.pathTransform.rotate(radians); } @@ -975,9 +1039,9 @@ void GraphicsContext::scale(const FloatSize& s) m_data->p()->scale(s.width(), s.height()); if (!m_data->currentPath.isEmpty()) { - QMatrix matrix; + QTransform matrix; m_data->currentPath = m_data->currentPath * matrix.scale(1 / s.width(), 1 / s.height()); - m_common->state.pathTransform.scale(s.width(), s.height()); + m_common->state.pathTransform.scaleNonUniform(s.width(), s.height()); } } @@ -1041,12 +1105,12 @@ void GraphicsContext::concatCTM(const TransformationMatrix& transform) if (paintingDisabled()) return; - m_data->p()->setMatrix(transform, true); + m_data->p()->setWorldTransform(transform, true); // Transformations to the context shouldn't transform the currentPath. // We have to undo every change made to the context from the currentPath to avoid wrong drawings. if (!m_data->currentPath.isEmpty() && transform.isInvertible()) { - QMatrix matrix = transform.inverse(); + QTransform matrix = transform.inverse(); m_data->currentPath = m_data->currentPath * matrix; m_common->state.pathTransform.multiply(transform); } diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp index d4ab59f..d748305 100644 --- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) 2008 Holger Hans Peter Freyther + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,10 +32,11 @@ #include "GraphicsContext.h" #include "ImageData.h" #include "MIMETypeRegistry.h" -#include "NotImplemented.h" #include "StillImageQt.h" #include <QBuffer> +#include <QColor> +#include <QImage> #include <QImageWriter> #include <QPainter> #include <QPixmap> @@ -79,15 +81,108 @@ Image* ImageBuffer::image() const return m_image.get(); } -PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect&) const +PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const { - notImplemented(); - return 0; + PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height()); + unsigned char* data = result->data()->data()->data(); + + if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > m_size.width() || (rect.y() + rect.height()) > m_size.height()) + memset(data, 0, result->data()->length()); + + int originx = rect.x(); + int destx = 0; + if (originx < 0) { + destx = -originx; + originx = 0; + } + int endx = rect.x() + rect.width(); + if (endx > m_size.width()) + endx = m_size.width(); + int numColumns = endx - originx; + + int originy = rect.y(); + int desty = 0; + if (originy < 0) { + desty = -originy; + originy = 0; + } + int endy = rect.y() + rect.height(); + if (endy > m_size.height()) + endy = m_size.height(); + int numRows = endy - originy; + + QImage image = m_data.m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32); + ASSERT(!image.isNull()); + + unsigned destBytesPerRow = 4 * rect.width(); + unsigned char* destRows = data + desty * destBytesPerRow + destx * 4; + for (int y = 0; y < numRows; ++y) { + for (int x = 0; x < numColumns; x++) { + QRgb value = image.pixel(x + originx, y + originy); + int basex = x * 4; + + destRows[basex] = qRed(value); + destRows[basex + 1] = qGreen(value); + destRows[basex + 2] = qBlue(value); + destRows[basex + 3] = qAlpha(value); + } + destRows += destBytesPerRow; + } + + return result; } -void ImageBuffer::putImageData(ImageData*, const IntRect&, const IntPoint&) +void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) { - notImplemented(); + ASSERT(sourceRect.width() > 0); + ASSERT(sourceRect.height() > 0); + + int originx = sourceRect.x(); + int destx = destPoint.x() + sourceRect.x(); + ASSERT(destx >= 0); + ASSERT(destx < m_size.width()); + ASSERT(originx >= 0); + ASSERT(originx <= sourceRect.right()); + + int endx = destPoint.x() + sourceRect.right(); + ASSERT(endx <= m_size.width()); + + int numColumns = endx - destx; + + int originy = sourceRect.y(); + int desty = destPoint.y() + sourceRect.y(); + ASSERT(desty >= 0); + ASSERT(desty < m_size.height()); + ASSERT(originy >= 0); + ASSERT(originy <= sourceRect.bottom()); + + int endy = destPoint.y() + sourceRect.bottom(); + ASSERT(endy <= m_size.height()); + int numRows = endy - desty; + + unsigned srcBytesPerRow = 4 * source->width(); + + bool isPainting = m_data.m_painter->isActive(); + if (isPainting) + m_data.m_painter->end(); + + QImage image = m_data.m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32); + + unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4; + for (int y = 0; y < numRows; ++y) { + quint32* scanLine = reinterpret_cast<quint32*>(image.scanLine(y + desty)); + for (int x = 0; x < numColumns; x++) { + int basex = x * 4; + scanLine[x + destx] = reinterpret_cast<quint32*>(srcRows + basex)[0]; + } + + srcRows += srcBytesPerRow; + } + + m_data.m_pixmap = QPixmap::fromImage(image); + + if (isPainting) + m_data.m_painter->begin(&m_data.m_pixmap); } // We get a mimeType here but QImageWriter does not support mimetypes but diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp index 99062f9..3bc67ae 100644 --- a/WebCore/platform/graphics/qt/ImageQt.cpp +++ b/WebCore/platform/graphics/qt/ImageQt.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org> * Copyright (C) 2006 Zack Rusin <zack@kde.org> * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org> + * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ * * All rights reserved. * @@ -96,7 +97,26 @@ PassRefPtr<Image> Image::loadPlatformResource(const char* name) void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect) { - notImplemented(); + QPixmap* framePixmap = nativeImageForCurrentFrame(); + if (!framePixmap) // If it's too early we won't have an image yet. + return; + + QPixmap pixmap = *framePixmap; + QRect tr = QRectF(tileRect).toRect(); + if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height()) { + pixmap = pixmap.copy(tr); + } + + QBrush b(pixmap); + b.setTransform(patternTransform); + ctxt->save(); + ctxt->setCompositeOperation(op); + QPainter* p = ctxt->platformContext(); + if (!pixmap.hasAlpha() && p->compositionMode() == QPainter::CompositionMode_SourceOver) + p->setCompositionMode(QPainter::CompositionMode_Source); + p->setBrushOrigin(phase); + p->fillRect(destRect, b); + ctxt->restore(); } void BitmapImage::initPlatformData() @@ -131,6 +151,9 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, QPainter* painter(ctxt->platformContext()); + if (!image->hasAlpha() && painter->compositionMode() == QPainter::CompositionMode_SourceOver) + painter->setCompositionMode(QPainter::CompositionMode_Source); + // Test using example site at // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html painter->drawPixmap(dst, *image, src); @@ -138,33 +161,20 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, ctxt->restore(); } -void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform, - const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect) +void BitmapImage::checkForSolidColor() { - QPixmap* framePixmap = nativeImageForCurrentFrame(); - if (!framePixmap) // If it's too early we won't have an image yet. - return; + m_isSolidColor = false; + m_checkedForSolidColor = true; - QPixmap pixmap = *framePixmap; - QRect tr = QRectF(tileRect).toRect(); - if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height()) { - pixmap = pixmap.copy(tr); - } + if (frameCount() > 1) + return; - QBrush b(pixmap); - b.setMatrix(patternTransform); - ctxt->save(); - ctxt->setCompositeOperation(op); - QPainter* p = ctxt->platformContext(); - p->setBrushOrigin(phase); - p->fillRect(destRect, b); - ctxt->restore(); -} + QPixmap* framePixmap = frameAtIndex(0); + if (!framePixmap || framePixmap->width() != 1 || framePixmap->height() != 1) + return; -void BitmapImage::checkForSolidColor() -{ - // FIXME: It's easy to implement this optimization. Just need to check the RGBA32 buffer to see if it is 1x1. - m_isSolidColor = false; + m_isSolidColor = true; + m_solidColor = QColor::fromRgba(framePixmap->toImage().pixel(0, 0)); } } diff --git a/WebCore/platform/graphics/qt/ImageSourceQt.cpp b/WebCore/platform/graphics/qt/ImageSourceQt.cpp index d62acc3..84de443 100644 --- a/WebCore/platform/graphics/qt/ImageSourceQt.cpp +++ b/WebCore/platform/graphics/qt/ImageSourceQt.cpp @@ -163,7 +163,7 @@ void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* delete m_decoder; m_decoder = 0; if (data) - setData(data, allDataReceived); + setData(data, allDataReceived); } } diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp index b1a48fb..c80d73b 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp @@ -1,5 +1,6 @@ /* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2009 Apple Inc. 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 @@ -76,7 +77,7 @@ namespace WebCore { MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) : m_player(player) , m_networkState(MediaPlayer::Empty) - , m_readyState(MediaPlayer::DataUnavailable) + , m_readyState(MediaPlayer::HaveNothing) , m_mediaObject(new MediaObject()) , m_videoWidget(new VideoWidget(0)) , m_audioOutput(new AudioOutput()) @@ -110,6 +111,18 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) connect(m_mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64))); } +MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) +{ + return new MediaPlayerPrivate(player); +} + +void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) +{ + if (isAvailable()) + registrar(create, getSupportedTypes, supportsType); +} + + MediaPlayerPrivate::~MediaPlayerPrivate() { LOG(Media, "MediaPlayerPrivatePhonon::dtor deleting videowidget"); @@ -131,6 +144,13 @@ void MediaPlayerPrivate::getSupportedTypes(HashSet<String>&) notImplemented(); } +MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs) +{ + // FIXME: do the real thing + notImplemented(); + return MediaPlayer::IsNotSupported; +} + bool MediaPlayerPrivate::hasVideo() const { bool hasVideo = m_mediaObject->hasVideo(); @@ -138,7 +158,7 @@ bool MediaPlayerPrivate::hasVideo() const return hasVideo; } -void MediaPlayerPrivate::load(String url) +void MediaPlayerPrivate::load(const String& url) { LOG(Media, "MediaPlayerPrivatePhonon::load(\"%s\")", url.utf8().data()); @@ -149,8 +169,8 @@ void MediaPlayerPrivate::load(String url) } // And we don't have any data yet - if (m_readyState != MediaPlayer::DataUnavailable) { - m_readyState = MediaPlayer::DataUnavailable; + if (m_readyState != MediaPlayer::HaveNothing) { + m_readyState = MediaPlayer::HaveNothing; m_player->readyStateChanged(); } @@ -205,7 +225,7 @@ bool MediaPlayerPrivate::seeking() const float MediaPlayerPrivate::duration() const { - if (m_networkState < MediaPlayer::LoadedMetaData) + if (m_readyState < MediaPlayer::HaveMetadata) return 0.0f; float duration = m_mediaObject->totalTime() / 1000.0f; @@ -309,18 +329,19 @@ void MediaPlayerPrivate::updateStates() Phonon::State phononState = m_mediaObject->state(); if (phononState == Phonon::StoppedState) { - if (oldNetworkState < MediaPlayer::LoadedMetaData) { - m_networkState = MediaPlayer::LoadedMetaData; - m_readyState = MediaPlayer::DataUnavailable; + if (m_readyState < MediaPlayer::HaveMetadata) { + m_networkState = MediaPlayer::Loading; // FIXME: should this be MediaPlayer::Idle? + m_readyState = MediaPlayer::HaveMetadata; m_mediaObject->pause(); } } else if (phononState == Phonon::PausedState) { m_networkState = MediaPlayer::Loaded; - m_readyState = MediaPlayer::CanPlayThrough; + m_readyState = MediaPlayer::HaveEnoughData; } else if (phononState == Phonon::ErrorState) { if (!m_mediaObject || m_mediaObject->errorType() == Phonon::FatalError) { - m_networkState = MediaPlayer::LoadFailed; - m_readyState = MediaPlayer::DataUnavailable; + // FIXME: is it possile to differentiate between different types of errors + m_networkState = MediaPlayer::NetworkError; + m_readyState = MediaPlayer::HaveNothing; cancelLoad(); } else { m_mediaObject->pause(); @@ -328,7 +349,7 @@ void MediaPlayerPrivate::updateStates() } if (seeking()) - m_readyState = MediaPlayer::DataUnavailable; + m_readyState = MediaPlayer::HaveNothing; if (m_networkState != oldNetworkState) { const QMetaObject* metaObj = this->metaObject(); @@ -357,19 +378,18 @@ void MediaPlayerPrivate::setVisible(bool visible) m_videoWidget->setVisible(m_isVisible); } -void MediaPlayerPrivate::setRect(const IntRect& newRect) +void MediaPlayerPrivate::setSize(const IntSize& newSize) { if (!m_videoWidget) return; - LOG(Media, "MediaPlayerPrivatePhonon::setRect(%d,%d %dx%d)", - newRect.x(), newRect.y(), - newRect.width(), newRect.height()); + LOG(Media, "MediaPlayerPrivatePhonon::setSize(%d,%d)", + newSize.width(), newSize.height()); QRect currentRect = m_videoWidget->rect(); - if (newRect.width() != currentRect.width() || newRect.height() != currentRect.height()) - m_videoWidget->resize(newRect.width(), newRect.height()); + if (newSize.width() != currentRect.width() || newSize.height() != currentRect.height()) + m_videoWidget->resize(newSize.width(), newSize.height()); } IntSize MediaPlayerPrivate::naturalSize() const @@ -380,7 +400,7 @@ IntSize MediaPlayerPrivate::naturalSize() const return IntSize(); } - if (m_networkState < MediaPlayer::LoadedMetaData) { + if (m_readyState < MediaPlayer::HaveMetadata) { LOG(Media, "MediaPlayerPrivatePhonon::naturalSize() -> %dx%d", 0, 0); return IntSize(); diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h index 1b20a84..9572d61 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h @@ -1,5 +1,6 @@ /* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2009 Apple Inc. 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 @@ -20,8 +21,7 @@ #ifndef MediaPlayerPrivatePhonon_h #define MediaPlayerPrivatePhonon_h -#include "MediaPlayer.h" -#include <wtf/Noncopyable.h> +#include "MediaPlayerPrivate.h" #include <QObject> #include <phononnamespace.h> @@ -40,31 +40,33 @@ QT_END_NAMESPACE namespace WebCore { - class MediaPlayerPrivate : public QObject, Noncopyable { + class MediaPlayerPrivate : public QObject, public MediaPlayerPrivateInterface { Q_OBJECT public: - MediaPlayerPrivate(MediaPlayer*); + static void registerMediaEngine(MediaEngineRegistrar); ~MediaPlayerPrivate(); // These enums are used for debugging Q_ENUMS(ReadyState NetworkState PhononState) enum ReadyState { - DataUnavailable, - CanShowCurrentFrame, - CanPlay, - CanPlayThrough + HaveNothing, + HaveMetadata, + HaveCurrentData, + HaveFutureData, + HaveEnoughData }; enum NetworkState { - Empty, - LoadFailed, - Loading, - LoadedMetaData, - LoadedFirstFrame, - Loaded + Empty, + Idle, + Loading, + Loaded, + FormatError, + NetworkError, + DecodeError }; enum PhononState { @@ -79,7 +81,7 @@ namespace WebCore { IntSize naturalSize() const; bool hasVideo() const; - void load(String url); + void load(const String &url); void cancelLoad(); void play(); @@ -109,11 +111,9 @@ namespace WebCore { unsigned totalBytes() const; void setVisible(bool); - void setRect(const IntRect&); + void setSize(const IntSize&); void paint(GraphicsContext*, const IntRect&); - static void getSupportedTypes(HashSet<String>&); - static bool isAvailable() { return true; } protected: bool eventFilter(QObject*, QEvent*); @@ -130,6 +130,13 @@ namespace WebCore { void totalTimeChanged(qint64); private: + MediaPlayerPrivate(MediaPlayer*); + static MediaPlayerPrivateInterface* create(MediaPlayer* player); + + static void getSupportedTypes(HashSet<String>&); + static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs); + static bool isAvailable() { return true; } + void updateStates(); MediaPlayer* m_player; diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index bd0192c..a8a3ea2 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -1,6 +1,7 @@ /* - * Copyright (C) 2006 Zack Rusin <zack@kde.org> - * 2006 Rob Buis <buis@kde.org> + * Copyright (C) 2006 Zack Rusin <zack@kde.org> + * 2006 Rob Buis <buis@kde.org> + * 2009 Dirk Schulze <krit@webkit.org> * * All rights reserved. * @@ -36,7 +37,7 @@ #include "PlatformString.h" #include "StrokeStyleApplier.h" #include <QPainterPath> -#include <QMatrix> +#include <QTransform> #include <QString> #define _USE_MATH_DEFINES @@ -108,7 +109,7 @@ bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) void Path::translate(const FloatSize& size) { - QMatrix matrix; + QTransform matrix; matrix.translate(size.width(), size.height()); *m_path = (*m_path) * matrix; } @@ -161,9 +162,72 @@ void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) { - //FIXME: busted - qWarning("arcTo is busted"); - m_path->arcTo(p1.x(), p1.y(), p2.x(), p2.y(), radius, 90); + FloatPoint p0(m_path->currentPosition()); + + if ((p1.x() == p0.x() && p1.y() == p0.y()) || (p1.x() == p2.x() && p1.y() == p2.y()) || radius == 0.f) { + m_path->lineTo(p1); + return; + } + + FloatPoint p1p0((p0.x() - p1.x()),(p0.y() - p1.y())); + FloatPoint p1p2((p2.x() - p1.x()),(p2.y() - p1.y())); + float p1p0_length = sqrtf(p1p0.x() * p1p0.x() + p1p0.y() * p1p0.y()); + float p1p2_length = sqrtf(p1p2.x() * p1p2.x() + p1p2.y() * p1p2.y()); + + double cos_phi = (p1p0.x() * p1p2.x() + p1p0.y() * p1p2.y()) / (p1p0_length * p1p2_length); + // all points on a line logic + if (cos_phi == -1) { + m_path->lineTo(p1); + return; + } + if (cos_phi == 1) { + // add infinite far away point + unsigned int max_length = 65535; + double factor_max = max_length / p1p0_length; + FloatPoint ep((p0.x() + factor_max * p1p0.x()), (p0.y() + factor_max * p1p0.y())); + m_path->lineTo(ep); + return; + } + + float tangent = radius / tan(acos(cos_phi) / 2); + float factor_p1p0 = tangent / p1p0_length; + FloatPoint t_p1p0((p1.x() + factor_p1p0 * p1p0.x()), (p1.y() + factor_p1p0 * p1p0.y())); + + FloatPoint orth_p1p0(p1p0.y(), -p1p0.x()); + float orth_p1p0_length = sqrt(orth_p1p0.x() * orth_p1p0.x() + orth_p1p0.y() * orth_p1p0.y()); + float factor_ra = radius / orth_p1p0_length; + + // angle between orth_p1p0 and p1p2 to get the right vector orthographic to p1p0 + double cos_alpha = (orth_p1p0.x() * p1p2.x() + orth_p1p0.y() * p1p2.y()) / (orth_p1p0_length * p1p2_length); + if (cos_alpha < 0.f) + orth_p1p0 = FloatPoint(-orth_p1p0.x(), -orth_p1p0.y()); + + FloatPoint p((t_p1p0.x() + factor_ra * orth_p1p0.x()), (t_p1p0.y() + factor_ra * orth_p1p0.y())); + + // calculate angles for addArc + orth_p1p0 = FloatPoint(-orth_p1p0.x(), -orth_p1p0.y()); + float sa = acos(orth_p1p0.x() / orth_p1p0_length); + if (orth_p1p0.y() < 0.f) + sa = 2 * piDouble - sa; + + // anticlockwise logic + bool anticlockwise = false; + + float factor_p1p2 = tangent / p1p2_length; + FloatPoint t_p1p2((p1.x() + factor_p1p2 * p1p2.x()), (p1.y() + factor_p1p2 * p1p2.y())); + FloatPoint orth_p1p2((t_p1p2.x() - p.x()),(t_p1p2.y() - p.y())); + float orth_p1p2_length = sqrtf(orth_p1p2.x() * orth_p1p2.x() + orth_p1p2.y() * orth_p1p2.y()); + float ea = acos(orth_p1p2.x() / orth_p1p2_length); + if (orth_p1p2.y() < 0) + ea = 2 * piDouble - ea; + if ((sa > ea) && ((sa - ea) < piDouble)) + anticlockwise = true; + if ((sa < ea) && ((ea - sa) > piDouble)) + anticlockwise = true; + + m_path->lineTo(t_p1p0); + + addArc(p, radius, sa, ea, anticlockwise); } void Path::closeSubpath() @@ -316,7 +380,7 @@ void Path::apply(void* info, PathApplierFunction function) const void Path::transform(const TransformationMatrix& transform) { if (m_path) { - QMatrix mat = transform; + QTransform mat = transform; QPainterPath temp = mat.map(*m_path); delete m_path; m_path = new QPainterPath(temp); diff --git a/WebCore/platform/graphics/qt/PatternQt.cpp b/WebCore/platform/graphics/qt/PatternQt.cpp index 5b76841..b261613 100644 --- a/WebCore/platform/graphics/qt/PatternQt.cpp +++ b/WebCore/platform/graphics/qt/PatternQt.cpp @@ -31,14 +31,15 @@ namespace WebCore { -QBrush Pattern::createPlatformPattern(const TransformationMatrix& transform) const +QBrush Pattern::createPlatformPattern(const TransformationMatrix&) const { QPixmap* pixmap = tileImage()->nativeImageForCurrentFrame(); if (!pixmap) return QBrush(); + // Qt merges patter space and user space itself QBrush brush(*pixmap); - brush.setMatrix(transform); + brush.setTransform(m_patternSpaceTransformation); return brush; } diff --git a/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp b/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp index 47abd17..15f0cc5 100644 --- a/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp +++ b/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp @@ -31,170 +31,9 @@ namespace WebCore { -TransformationMatrix::TransformationMatrix() - : m_transform() -{ -} - -TransformationMatrix::TransformationMatrix(double a, double b, double c, double d, double tx, double ty) - : m_transform(a, b, c, d, tx, ty) -{ -} - -TransformationMatrix::TransformationMatrix(const PlatformTransformationMatrix& matrix) - : m_transform(matrix) -{ -} - -void TransformationMatrix::setMatrix(double a, double b, double c, double d, double tx, double ty) -{ - m_transform.setMatrix(a, b, c, d, tx, ty); -} - -void TransformationMatrix::map(double x, double y, double* x2, double* y2) const -{ - qreal tx2, ty2; - m_transform.map(qreal(x), qreal(y), &tx2, &ty2); - *x2 = tx2; - *y2 = ty2; -} - -IntRect TransformationMatrix::mapRect(const IntRect& rect) const -{ - return m_transform.mapRect(rect); -} - -FloatRect TransformationMatrix::mapRect(const FloatRect& rect) const -{ - return m_transform.mapRect(rect); -} - -bool TransformationMatrix::isIdentity() const -{ - return m_transform.isIdentity(); -} - -double TransformationMatrix::a() const -{ - return m_transform.m11(); -} - -void TransformationMatrix::setA(double a) -{ - m_transform.setMatrix(a, b(), c(), d(), e(), f()); -} - -double TransformationMatrix::b() const -{ - return m_transform.m12(); -} - -void TransformationMatrix::setB(double b) -{ - m_transform.setMatrix(a(), b, c(), d(), e(), f()); -} - -double TransformationMatrix::c() const -{ - return m_transform.m21(); -} - -void TransformationMatrix::setC(double c) -{ - m_transform.setMatrix(a(), b(), c, d(), e(), f()); -} - -double TransformationMatrix::d() const -{ - return m_transform.m22(); -} - -void TransformationMatrix::setD(double d) -{ - m_transform.setMatrix(a(), b(), c(), d, e(), f()); -} - -double TransformationMatrix::e() const -{ - return m_transform.dx(); -} - -void TransformationMatrix::setE(double e) -{ - m_transform.setMatrix(a(), b(), c(), d(), e, f()); -} - -double TransformationMatrix::f() const -{ - return m_transform.dy(); -} - -void TransformationMatrix::setF(double f) -{ - m_transform.setMatrix(a(), b(), c(), d(), e(), f); -} - -void TransformationMatrix::reset() -{ - m_transform.reset(); -} - -TransformationMatrix& TransformationMatrix::scale(double sx, double sy) -{ - m_transform.scale(sx, sy); - return *this; -} - -TransformationMatrix& TransformationMatrix::rotate(double d) -{ - m_transform.rotate(d); - return *this; -} - -TransformationMatrix& TransformationMatrix::translate(double tx, double ty) -{ - m_transform.translate(tx, ty); - return *this; -} - -TransformationMatrix& TransformationMatrix::shear(double sx, double sy) -{ - m_transform.shear(sx, sy); - return *this; -} - -double TransformationMatrix::det() const -{ - return m_transform.det(); -} - -TransformationMatrix TransformationMatrix::inverse() const -{ - if(!isInvertible()) - return TransformationMatrix(); - - return m_transform.inverted(); -} - -TransformationMatrix::operator QMatrix() const -{ - return m_transform; -} - -bool TransformationMatrix::operator==(const TransformationMatrix& other) const -{ - return m_transform == other.m_transform; -} - -TransformationMatrix& TransformationMatrix::operator*=(const TransformationMatrix& other) -{ - m_transform *= other.m_transform; - return *this; -} - -TransformationMatrix TransformationMatrix::operator*(const TransformationMatrix& other) -{ - return m_transform * other.m_transform; +TransformationMatrix::operator QTransform() const +{ + return QTransform(m11(), m12(), m14(), m21(), m22(), m24(), m41(), m42(), m44()); } } |