1 /* 2 * Copyright 2006, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "Gradient.h" 28 29 #include "android_graphics.h" 30 #include "CSSParser.h" 31 #include "GraphicsContext.h" 32 #include "NotImplemented.h" 33 #include "SkCanvas.h" 34 #include "SkColorShader.h" 35 #include "SkGradientShader.h" 36 #include "SkPaint.h" 37 38 class PlatformGradientRec { 39 public: 40 PlatformGradientRec() : m_shader(NULL) {} 41 ~PlatformGradientRec() { m_shader->safeUnref(); } 42 43 SkShader* m_shader; 44 SkShader::TileMode m_tileMode; 45 int m_colorCountWhenShaderWasBuilt; 46 }; 47 48 namespace WebCore { 49 50 void Gradient::platformDestroy() 51 { 52 delete m_gradient; 53 m_gradient = 0; 54 } 55 56 static U8CPU F2B(float x) 57 { 58 return (int)(x * 255); 59 } 60 61 SkShader* Gradient::getShader(SkShader::TileMode mode) 62 { 63 if (NULL == m_gradient) 64 m_gradient = new PlatformGradientRec; 65 else if (mode == m_gradient->m_tileMode) 66 return m_gradient->m_shader; 67 68 // need to ensure that the m_stops array is sorted. We call getColor() 69 // which, as a side effect, does the sort. 70 // TODO: refactor Gradient.h to formally expose a sort method 71 { 72 float r, g, b, a; 73 this->getColor(0, &r, &g, &b, &a); 74 } 75 76 SkPoint pts[2] = { m_p0, m_p1 }; // convert to SkPoint 77 78 const size_t count = m_stops.size(); 79 SkAutoMalloc storage(count * (sizeof(SkColor) + sizeof(SkScalar))); 80 SkColor* colors = (SkColor*)storage.get(); 81 SkScalar* pos = (SkScalar*)(colors + count); 82 83 Vector<ColorStop>::iterator iter = m_stops.begin(); 84 for (int i = 0; iter != m_stops.end(); i++) { 85 pos[i] = SkFloatToScalar(iter->stop); 86 colors[i] = SkColorSetARGB(F2B(iter->alpha), F2B(iter->red), 87 F2B(iter->green), F2B(iter->blue)); 88 ++iter; 89 } 90 91 SkShader* s; 92 if (m_radial) 93 s = SkGradientShader::CreateTwoPointRadial(pts[0], 94 SkFloatToScalar(m_r0), 95 pts[1], 96 SkFloatToScalar(m_r1), 97 colors, pos, count, mode); 98 else 99 s = SkGradientShader::CreateLinear(pts, colors, pos, count, mode); 100 101 if (NULL == s) 102 s = new SkColorShader(0); 103 104 // zap our previous shader, if present 105 m_gradient->m_shader->safeUnref(); 106 m_gradient->m_shader = s; 107 m_gradient->m_tileMode = mode; 108 SkMatrix matrix = m_gradientSpaceTransformation; 109 s->setLocalMatrix(matrix); 110 111 return s; 112 } 113 114 void Gradient::fill(GraphicsContext* context, const FloatRect& rect) 115 { 116 SkRect r; 117 SkPaint paint; 118 // we don't care about the mode, so try to use the existing one 119 SkShader::TileMode mode = m_gradient ? m_gradient->m_tileMode : 120 SkShader::kClamp_TileMode; 121 122 paint.setAntiAlias(true); 123 paint.setShader(this->getShader(mode)); 124 android_gc2canvas(context)->drawRect(rect, paint); 125 } 126 127 128 } //namespace 129