1/* 2 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this program; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 * 19 */ 20 21#include "config.h" 22#include "QtWebPageSGNode.h" 23 24#include <QtGui/QPolygonF> 25#include <QtQuick/QQuickItem> 26#include <QtQuick/QQuickWindow> 27#include <QtQuick/QSGSimpleRectNode> 28#include <WebCore/CoordinatedGraphicsScene.h> 29#include <WebCore/TransformationMatrix.h> 30#include <private/qsgrendernode_p.h> 31 32using namespace WebCore; 33 34namespace WebKit { 35 36class ContentsSGNode : public QSGRenderNode { 37public: 38 ContentsSGNode(PassRefPtr<CoordinatedGraphicsScene> scene) 39 : m_scene(scene) 40 { 41 coordinatedGraphicsScene()->setActive(true); 42 } 43 44 virtual StateFlags changedStates() 45 { 46 return StateFlags(StencilState) | ColorState | BlendState; 47 } 48 49 virtual void render(const RenderState& state) 50 { 51 TransformationMatrix renderMatrix; 52 if (pageNode()->devicePixelRatio() != 1.0) { 53 renderMatrix.scale(pageNode()->devicePixelRatio()); 54 if (matrix()) 55 renderMatrix.multiply(*matrix()); 56 } else if (matrix()) 57 renderMatrix = *matrix(); 58 59 // When rendering to an intermediate surface, Qt will 60 // mirror the projection matrix to fit on the destination coordinate system. 61 const QMatrix4x4* projection = state.projectionMatrix; 62 bool mirrored = projection && (*projection)(0, 0) * (*projection)(1, 1) - (*projection)(0, 1) * (*projection)(1, 0) > 0; 63 64 // FIXME: Support non-rectangular clippings. 65 coordinatedGraphicsScene()->paintToCurrentGLContext(renderMatrix, inheritedOpacity(), clipRect(), mirrored ? TextureMapper::PaintingMirrored : 0); 66 } 67 68 ~ContentsSGNode() 69 { 70 coordinatedGraphicsScene()->purgeGLResources(); 71 } 72 73 const QtWebPageSGNode* pageNode() const 74 { 75 const QtWebPageSGNode* parent = static_cast<QtWebPageSGNode*>(this->parent()); 76 ASSERT(parent); 77 return parent; 78 } 79 80 WebCore::CoordinatedGraphicsScene* coordinatedGraphicsScene() const { return m_scene.get(); } 81 82private: 83 QRectF clipRect() const 84 { 85 // Start with an invalid rect. 86 QRectF resultRect(0, 0, -1, -1); 87 88 for (const QSGClipNode* clip = clipList(); clip; clip = clip->clipList()) { 89 QMatrix4x4 clipMatrix; 90 if (pageNode()->devicePixelRatio() != 1.0) { 91 clipMatrix.scale(pageNode()->devicePixelRatio()); 92 if (clip->matrix()) 93 clipMatrix *= (*clip->matrix()); 94 } else if (clip->matrix()) 95 clipMatrix = *clip->matrix(); 96 97 QRectF currentClip; 98 99 if (clip->isRectangular()) 100 currentClip = clipMatrix.mapRect(clip->clipRect()); 101 else { 102 const QSGGeometry* geometry = clip->geometry(); 103 // Assume here that clipNode has only coordinate data. 104 const QSGGeometry::Point2D* geometryPoints = geometry->vertexDataAsPoint2D(); 105 106 // Clip region should be at least triangle to make valid clip. 107 if (geometry->vertexCount() < 3) 108 continue; 109 110 QPolygonF polygon; 111 112 for (int i = 0; i < geometry->vertexCount(); i++) 113 polygon.append(clipMatrix.map(QPointF(geometryPoints[i].x, geometryPoints[i].y))); 114 currentClip = polygon.boundingRect(); 115 } 116 117 if (currentClip.isEmpty()) 118 continue; 119 120 if (resultRect.isValid()) 121 resultRect &= currentClip; 122 else 123 resultRect = currentClip; 124 } 125 126 return resultRect; 127 } 128 129 RefPtr<WebCore::CoordinatedGraphicsScene> m_scene; 130}; 131 132QtWebPageSGNode::QtWebPageSGNode() 133 : m_contentsNode(0) 134 , m_backgroundNode(new QSGSimpleRectNode) 135 , m_devicePixelRatio(1) 136{ 137 appendChildNode(m_backgroundNode); 138} 139 140void QtWebPageSGNode::setBackground(const QRectF& rect, const QColor& color) 141{ 142 m_backgroundNode->setRect(rect); 143 m_backgroundNode->setColor(color); 144} 145 146void QtWebPageSGNode::setScale(float scale) 147{ 148 QMatrix4x4 matrix; 149 matrix.scale(scale); 150 setMatrix(matrix); 151} 152 153void QtWebPageSGNode::setCoordinatedGraphicsScene(PassRefPtr<WebCore::CoordinatedGraphicsScene> scene) 154{ 155 if (m_contentsNode && m_contentsNode->coordinatedGraphicsScene() == scene) 156 return; 157 158 delete m_contentsNode; 159 m_contentsNode = new ContentsSGNode(scene); 160 // This sets the parent node of the content to QtWebPageSGNode. 161 appendChildNode(m_contentsNode); 162} 163 164} // namespace WebKit 165