1 /* 2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 4 * Copyright (C) 2007 Alp Toker <alp (at) atoker.com> 5 * Copyright (C) 2008 Eric Seidel <eric (at) webkit.org> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "config.h" 30 #include "CanvasStyle.h" 31 32 #include "CSSParser.h" 33 #include "CanvasGradient.h" 34 #include "CanvasPattern.h" 35 #include "GraphicsContext.h" 36 #include <wtf/PassRefPtr.h> 37 38 #if PLATFORM(CG) 39 #include <CoreGraphics/CGContext.h> 40 #endif 41 42 #if PLATFORM(QT) 43 #include <QPainter> 44 #include <QBrush> 45 #include <QPen> 46 #include <QColor> 47 #endif 48 49 namespace WebCore { 50 51 CanvasStyle::CanvasStyle(const String& color) 52 : m_type(ColorString) 53 , m_color(color) 54 { 55 } 56 57 CanvasStyle::CanvasStyle(float grayLevel) 58 : m_type(GrayLevel) 59 , m_alpha(1) 60 , m_grayLevel(grayLevel) 61 { 62 } 63 64 CanvasStyle::CanvasStyle(const String& color, float alpha) 65 : m_type(ColorStringWithAlpha) 66 , m_color(color) 67 , m_alpha(alpha) 68 { 69 } 70 71 CanvasStyle::CanvasStyle(float grayLevel, float alpha) 72 : m_type(GrayLevel) 73 , m_alpha(alpha) 74 , m_grayLevel(grayLevel) 75 { 76 } 77 78 CanvasStyle::CanvasStyle(float r, float g, float b, float a) 79 : m_type(RGBA) 80 , m_alpha(a) 81 , m_red(r) 82 , m_green(g) 83 , m_blue(b) 84 { 85 } 86 87 CanvasStyle::CanvasStyle(float c, float m, float y, float k, float a) 88 : m_type(CMYKA) 89 , m_alpha(a) 90 , m_cyan(c) 91 , m_magenta(m) 92 , m_yellow(y) 93 , m_black(k) 94 { 95 } 96 97 CanvasStyle::CanvasStyle(PassRefPtr<CanvasGradient> gradient) 98 : m_type(gradient ? Gradient : ColorString) 99 , m_gradient(gradient) 100 { 101 } 102 103 CanvasStyle::CanvasStyle(PassRefPtr<CanvasPattern> pattern) 104 : m_type(pattern ? ImagePattern : ColorString) 105 , m_pattern(pattern) 106 { 107 } 108 109 void CanvasStyle::applyStrokeColor(GraphicsContext* context) 110 { 111 if (!context) 112 return; 113 switch (m_type) { 114 case ColorString: { 115 Color c = Color(m_color); 116 if (c.isValid()) { 117 context->setStrokeColor(c.rgb(), DeviceColorSpace); 118 break; 119 } 120 RGBA32 color = 0; // default is transparent black 121 if (CSSParser::parseColor(color, m_color)) 122 context->setStrokeColor(color, DeviceColorSpace); 123 break; 124 } 125 case ColorStringWithAlpha: { 126 Color c = Color(m_color); 127 if (c.isValid()) { 128 context->setStrokeColor(colorWithOverrideAlpha(c.rgb(), m_alpha), DeviceColorSpace); 129 break; 130 } 131 RGBA32 color = 0; // default is transparent black 132 if (CSSParser::parseColor(color, m_color)) 133 context->setStrokeColor(colorWithOverrideAlpha(color, m_alpha), DeviceColorSpace); 134 break; 135 } 136 case GrayLevel: 137 // We're only supporting 255 levels of gray here. Since this isn't 138 // even part of HTML5, I don't expect anyone will care. If they do 139 // we'll make a fancier Color abstraction. 140 context->setStrokeColor(Color(m_grayLevel, m_grayLevel, m_grayLevel, m_alpha), DeviceColorSpace); 141 break; 142 case RGBA: 143 context->setStrokeColor(Color(m_red, m_green, m_blue, m_alpha), DeviceColorSpace); 144 break; 145 case CMYKA: { 146 // FIXME: Do this through platform-independent GraphicsContext API. 147 // We'll need a fancier Color abstraction to support CYMKA correctly 148 #if PLATFORM(CG) 149 CGContextSetCMYKStrokeColor(context->platformContext(), m_cyan, m_magenta, m_yellow, m_black, m_alpha); 150 #elif PLATFORM(QT) 151 QPen currentPen = context->platformContext()->pen(); 152 QColor clr; 153 clr.setCmykF(m_cyan, m_magenta, m_yellow, m_black, m_alpha); 154 currentPen.setColor(clr); 155 context->platformContext()->setPen(currentPen); 156 #else 157 context->setStrokeColor(Color(m_cyan, m_magenta, m_yellow, m_black, m_alpha), DeviceColorSpace); 158 #endif 159 break; 160 } 161 case Gradient: 162 context->setStrokeGradient(canvasGradient()->gradient()); 163 break; 164 case ImagePattern: 165 context->setStrokePattern(canvasPattern()->pattern()); 166 break; 167 } 168 } 169 170 void CanvasStyle::applyFillColor(GraphicsContext* context) 171 { 172 if (!context) 173 return; 174 switch (m_type) { 175 case ColorString: { 176 Color c = Color(m_color); 177 if (c.isValid()) { 178 context->setFillColor(c.rgb(), DeviceColorSpace); 179 break; 180 } 181 RGBA32 rgba = 0; // default is transparent black 182 if (CSSParser::parseColor(rgba, m_color)) 183 context->setFillColor(rgba, DeviceColorSpace); 184 break; 185 } 186 case ColorStringWithAlpha: { 187 Color c = Color(m_color); 188 if (c.isValid()) { 189 context->setFillColor(colorWithOverrideAlpha(c.rgb(), m_alpha), DeviceColorSpace); 190 break; 191 } 192 RGBA32 color = 0; // default is transparent black 193 if (CSSParser::parseColor(color, m_color)) 194 context->setFillColor(colorWithOverrideAlpha(color, m_alpha), DeviceColorSpace); 195 break; 196 } 197 case GrayLevel: 198 // We're only supporting 255 levels of gray here. Since this isn't 199 // even part of HTML5, I don't expect anyone will care. If they do 200 // we'll make a fancier Color abstraction. 201 context->setFillColor(Color(m_grayLevel, m_grayLevel, m_grayLevel, m_alpha), DeviceColorSpace); 202 break; 203 case RGBA: 204 context->setFillColor(Color(m_red, m_green, m_blue, m_alpha), DeviceColorSpace); 205 break; 206 case CMYKA: { 207 // FIXME: Do this through platform-independent GraphicsContext API. 208 // We'll need a fancier Color abstraction to support CYMKA correctly 209 #if PLATFORM(CG) 210 CGContextSetCMYKFillColor(context->platformContext(), m_cyan, m_magenta, m_yellow, m_black, m_alpha); 211 #elif PLATFORM(QT) 212 QBrush currentBrush = context->platformContext()->brush(); 213 QColor clr; 214 clr.setCmykF(m_cyan, m_magenta, m_yellow, m_black, m_alpha); 215 currentBrush.setColor(clr); 216 context->platformContext()->setBrush(currentBrush); 217 #else 218 context->setFillColor(Color(m_cyan, m_magenta, m_yellow, m_black, m_alpha), DeviceColorSpace); 219 #endif 220 break; 221 } 222 case Gradient: 223 context->setFillGradient(canvasGradient()->gradient()); 224 break; 225 case ImagePattern: 226 context->setFillPattern(canvasPattern()->pattern()); 227 break; 228 } 229 } 230 231 } 232