18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Alp Toker <alp@atoker.com> 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Gradient.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSParser.h" 318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "GraphicsContext.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <QGradient> 348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <QPainter> 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Gradient::platformDestroy() 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project delete m_gradient; 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_gradient = 0; 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectQGradient* Gradient::platformGradient() 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_gradient) 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_gradient; 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 49e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block bool reversed = m_r0 > m_r1; 50e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 51e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block qreal innerRadius = reversed ? m_r1 : m_r0; 52e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block qreal outerRadius = reversed ? m_r0 : m_r1; 53e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block QPointF center = reversed ? m_p0 : m_p1; 54e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block QPointF focalPoint = reversed ? m_p1 : m_p0; 55e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_radial) 57e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block m_gradient = new QRadialGradient(center, outerRadius, focalPoint); 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_gradient = new QLinearGradient(m_p0.x(), m_p0.y(), m_p1.x(), m_p1.y()); 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 61ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block m_gradient->setInterpolationMode(QGradient::ComponentInterpolation); 62ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block 63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block sortStopsIfNecessary(); 64dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project QColor stopColor; 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<ColorStop>::iterator stopIterator = m_stops.begin(); 67635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project qreal lastStop(0.0); 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const qreal lastStopDiff = 0.0000001; 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (stopIterator != m_stops.end()) { 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project stopColor.setRgbF(stopIterator->red, stopIterator->green, stopIterator->blue, stopIterator->alpha); 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (qFuzzyCompare(lastStop, qreal(stopIterator->stop))) 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project lastStop = stopIterator->stop + lastStopDiff; 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project lastStop = stopIterator->stop; 75e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 76e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (m_radial && !qFuzzyCompare(1 + outerRadius, qreal(1))) { 77e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block lastStop = lastStop * (1.0f - innerRadius / outerRadius); 78e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (!reversed) 79e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block lastStop += innerRadius / outerRadius; 80e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block } 81e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 82e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block qreal stopPosition = qMin(lastStop, qreal(1.0f)); 83e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 84e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (m_radial && reversed) 85e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block stopPosition = 1 - stopPosition; 86e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 87e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block m_gradient->setColorAt(stopPosition, stopColor); 88dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Keep the lastStop as orginal value, since the following stopColor depend it 89dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block lastStop = stopIterator->stop; 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++stopIterator; 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (m_stops.isEmpty()) { 94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // The behavior of QGradient with no stops is defined differently from HTML5 spec, 95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // where the latter requires the gradient to be transparent black. 96dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_gradient->setColorAt(0.0, QColor(0, 0, 0, 0)); 97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch switch (m_spreadMethod) { 1008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian case SpreadMethodPad: 1018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_gradient->setSpread(QGradient::PadSpread); 1028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian break; 1038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian case SpreadMethodReflect: 1048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_gradient->setSpread(QGradient::ReflectSpread); 1058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian break; 1068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian case SpreadMethodRepeat: 1078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_gradient->setSpread(QGradient::RepeatSpread); 1088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian break; 1098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 1108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_gradient; 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Gradient::fill(GraphicsContext* context, const FloatRect& rect) 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian context->platformContext()->fillRect(rect, *platformGradient()); 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} //namespace 120