SkPDFShader.cpp revision 386dfc049baa400c13e4e98727d4c04d0242b7b8
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 4da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org */ 8da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 10da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org#include "SkPDFShader.h" 11da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 12da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org#include "SkCanvas.h" 13421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org#include "SkData.h" 14da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org#include "SkPDFCatalog.h" 15da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org#include "SkPDFDevice.h" 16da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org#include "SkPDFTypes.h" 17da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org#include "SkPDFUtils.h" 18da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org#include "SkScalar.h" 19da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org#include "SkStream.h" 20316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com#include "SkTemplates.h" 21da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org#include "SkThread.h" 22da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org#include "SkTypes.h" 23da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 24386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.orgstatic bool transformBBox(const SkMatrix& matrix, SkRect* bbox) { 25da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix inverse; 26b054990307b7338e599a12d9af10eb2058b94051vandebo@chromium.org if (!matrix.invert(&inverse)) { 27386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org return false; 28b054990307b7338e599a12d9af10eb2058b94051vandebo@chromium.org } 29da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org inverse.mapRect(bbox); 30386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org return true; 31da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 32da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 33da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic void unitToPointsMatrix(const SkPoint pts[2], SkMatrix* matrix) { 34da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkVector vec = pts[1] - pts[0]; 35da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar mag = vec.length(); 36da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar inv = mag ? SkScalarInvert(mag) : 0; 37da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 38da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org vec.scale(inv); 39da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org matrix->setSinCos(vec.fY, vec.fX); 40da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org matrix->preTranslate(pts[0].fX, pts[0].fY); 41da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org matrix->preScale(mag, mag); 42da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 43da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 44da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org/* Assumes t + startOffset is on the stack and does a linear interpolation on t 45da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org between startOffset and endOffset from prevColor to curColor (for each color 46da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org component), leaving the result in component order on the stack. 47da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org @param range endOffset - startOffset 48da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org @param curColor[components] The current color components. 49da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org @param prevColor[components] The previous color components. 50da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org @param result The result ps function. 51da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org */ 52da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic void interpolateColorCode(SkScalar range, SkScalar* curColor, 53da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar* prevColor, int components, 54da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString* result) { 55da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Figure out how to scale each color component. 56316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com SkAutoSTMalloc<4, SkScalar> multiplierAlloc(components); 57316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com SkScalar *multiplier = multiplierAlloc.get(); 58da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = 0; i < components; i++) { 59da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org multiplier[i] = SkScalarDiv(curColor[i] - prevColor[i], range); 60da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 61da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 62da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Calculate when we no longer need to keep a copy of the input parameter t. 63da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // If the last component to use t is i, then dupInput[0..i - 1] = true 64da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // and dupInput[i .. components] = false. 65316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com SkAutoSTMalloc<4, bool> dupInputAlloc(components); 66316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com bool *dupInput = dupInputAlloc.get(); 67da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org dupInput[components - 1] = false; 68da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = components - 2; i >= 0; i--) { 69da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org dupInput[i] = dupInput[i + 1] || multiplier[i + 1] != 0; 70da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 71da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 72da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (!dupInput[0] && multiplier[0] == 0) { 73da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("pop "); 74da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 75da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 76da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = 0; i < components; i++) { 77da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // If the next components needs t, make a copy. 78da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (dupInput[i]) { 79da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("dup "); 80da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 81da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 82da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (multiplier[i] == 0) { 83da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(prevColor[i]); 84da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" "); 85da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 86da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (multiplier[i] != 1) { 87da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(multiplier[i]); 88da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" mul "); 89da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 90da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (prevColor[i] != 0) { 91da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(prevColor[i]); 92da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" add "); 93da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 94da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 95da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 96da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (dupInput[i]) { 97da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("exch\n"); 98da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 99da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 100da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 101da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 102da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org/* Generate Type 4 function code to map t=[0,1) to the passed gradient, 103da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org clamping at the edges of the range. The generated code will be of the form: 104da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (t < 0) { 105da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return colorData[0][r,g,b]; 106da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 107da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (t < info.fColorOffsets[1]) { 108da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return linearinterpolation(colorData[0][r,g,b], 109da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org colorData[1][r,g,b]); 110da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 111da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (t < info.fColorOffsets[2]) { 112da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return linearinterpolation(colorData[1][r,g,b], 113da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org colorData[2][r,g,b]); 114da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 115da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 116da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org ... } else { 117da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return colorData[info.fColorCount - 1][r,g,b]; 118da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 119da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org ... 120da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 121da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 122da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org */ 123da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic void gradientFunctionCode(const SkShader::GradientInfo& info, 124da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString* result) { 125da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org /* We want to linearly interpolate from the previous color to the next. 126da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org Scale the colors from 0..255 to 0..1 and determine the multipliers 127da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for interpolation. 128da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org C{r,g,b}(t, section) = t - offset_(section-1) + t * Multiplier{r,g,b}. 129da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org */ 130da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org static const int kColorComponents = 3; 131316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com typedef SkScalar ColorTuple[kColorComponents]; 132316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(info.fColorCount); 133316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com ColorTuple *colorData = colorDataAlloc.get(); 134da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org const SkScalar scale = SkScalarInvert(SkIntToScalar(255)); 135da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = 0; i < info.fColorCount; i++) { 136da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org colorData[i][0] = SkScalarMul(SkColorGetR(info.fColors[i]), scale); 137da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org colorData[i][1] = SkScalarMul(SkColorGetG(info.fColors[i]), scale); 138da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org colorData[i][2] = SkScalarMul(SkColorGetB(info.fColors[i]), scale); 139da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 140da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 141da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Clamp the initial color. 142da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("dup 0 le {pop "); 143da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(colorData[0][0]); 144da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" "); 145da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(colorData[0][1]); 146da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" "); 147da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(colorData[0][2]); 148da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" }\n"); 149da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 150da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // The gradient colors. 151da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = 1 ; i < info.fColorCount; i++) { 152da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("{dup "); 153da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(info.fColorOffsets[i]); 154da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" le {"); 155da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (info.fColorOffsets[i - 1] != 0) { 156da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(info.fColorOffsets[i - 1]); 157da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" sub\n"); 158da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 159da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 160da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org interpolateColorCode(info.fColorOffsets[i] - info.fColorOffsets[i - 1], 161da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org colorData[i], colorData[i - 1], kColorComponents, 162da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result); 163da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("}\n"); 164da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 165da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 166da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Clamp the final color. 167da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("{pop "); 168da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(colorData[info.fColorCount - 1][0]); 169da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" "); 170da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(colorData[info.fColorCount - 1][1]); 171da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" "); 172da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(colorData[info.fColorCount - 1][2]); 173da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 174da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = 0 ; i < info.fColorCount; i++) { 175da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("} ifelse\n"); 176da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 177da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 178da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 179da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org/* Map a value of t on the stack into [0, 1) for Repeat or Mirror tile mode. */ 180da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic void tileModeCode(SkShader::TileMode mode, SkString* result) { 181da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (mode == SkShader::kRepeat_TileMode) { 182da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("dup truncate sub\n"); // Get the fractional part. 183da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("dup 0 le {1 add} if\n"); // Map (-1,0) => (0,1) 184da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return; 185da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 186da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 187da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (mode == SkShader::kMirror_TileMode) { 188da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Map t mod 2 into [0, 1, 1, 0]. 189da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Code Stack 190da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("abs " // Map negative to positive. 191da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "dup " // t.s t.s 192da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "truncate " // t.s t 193da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "dup " // t.s t t 194da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "cvi " // t.s t T 195da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "2 mod " // t.s t (i mod 2) 196da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "1 eq " // t.s t true|false 197da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "3 1 roll " // true|false t.s t 198da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "sub " // true|false 0.s 199da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "exch " // 0.s true|false 200da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "{1 exch sub} if\n"); // 1 - 0.s|0.s 201da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 202da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 203da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 204da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic SkString linearCode(const SkShader::GradientInfo& info) { 205a5c7234e81748f76cbeede40e619351146e5286actguil@chromium.org SkString function("{pop\n"); // Just ditch the y value. 206da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModeCode(info.fTileMode, &function); 207da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org gradientFunctionCode(info, &function); 208da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("}"); 209da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return function; 210da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 211da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 212da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic SkString radialCode(const SkShader::GradientInfo& info) { 213da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString function("{"); 214da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Find the distance from the origin. 215da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("dup " // x y y 216da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "mul " // x y^2 217da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "exch " // y^2 x 218da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "dup " // y^2 x x 219da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "mul " // y^2 x^2 220da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "add " // y^2+x^2 221da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "sqrt\n"); // sqrt(y^2+x^2) 222da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 223da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModeCode(info.fTileMode, &function); 224da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org gradientFunctionCode(info, &function); 225da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("}"); 226da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return function; 227da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 228da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 229da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org/* The math here is all based on the description in Two_Point_Radial_Gradient, 230da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org with one simplification, the coordinate space has been scaled so that 231da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org Dr = 1. This means we don't need to scale the entire equation by 1/Dr^2. 232da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org */ 233da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic SkString twoPointRadialCode(const SkShader::GradientInfo& info) { 234da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar dx = info.fPoint[0].fX - info.fPoint[1].fX; 235da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar dy = info.fPoint[0].fY - info.fPoint[1].fY; 236da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar sr = info.fRadius[0]; 237da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar a = SkScalarMul(dx, dx) + SkScalarMul(dy, dy) - SK_Scalar1; 238da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org bool posRoot = info.fRadius[1] > info.fRadius[0]; 239da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 240da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // We start with a stack of (x y), copy it and then consume one copy in 241da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // order to calculate b and the other to calculate c. 242da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString function("{"); 243da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("2 copy "); 244da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 245da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Calculate -b and b^2. 246da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.appendScalar(dy); 247da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append(" mul exch "); 248da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.appendScalar(dx); 249da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append(" mul add "); 250da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.appendScalar(sr); 251da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append(" sub 2 mul neg dup dup mul\n"); 252da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 253da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Calculate c 254da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("4 2 roll dup mul exch dup mul add "); 255da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.appendScalar(SkScalarMul(sr, sr)); 256da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append(" sub\n"); 257da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 258da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Calculate the determinate 259da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.appendScalar(SkScalarMul(SkIntToScalar(4), a)); 260da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append(" mul sub abs sqrt\n"); 261da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 262da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // And then the final value of t. 263da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (posRoot) { 264da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("sub "); 265da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 266da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("add "); 267da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 268da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.appendScalar(SkScalarMul(SkIntToScalar(2), a)); 269da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append(" div\n"); 270da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 271da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModeCode(info.fTileMode, &function); 272da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org gradientFunctionCode(info, &function); 273da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("}"); 274da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return function; 275da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 276da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 277da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic SkString sweepCode(const SkShader::GradientInfo& info) { 278da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString function("{exch atan 360 div\n"); 279da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModeCode(info.fTileMode, &function); 280da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org gradientFunctionCode(info, &function); 281da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("}"); 282da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return function; 283da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 284da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 285421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgclass SkPDFShader::State { 286421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgpublic: 287421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkShader::GradientType fType; 288421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkShader::GradientInfo fInfo; 289421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkAutoFree fColorData; 290421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkMatrix fCanvasTransform; 291421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkMatrix fShaderTransform; 292421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkIRect fBBox; 293421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 294421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkBitmap fImage; 295421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org uint32_t fPixelGeneration; 296421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkShader::TileMode fImageTileModes[2]; 297421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 298421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org explicit State(const SkShader& shader, const SkMatrix& canvasTransform, 299421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org const SkIRect& bbox); 300421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org bool operator==(const State& b) const; 301421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org}; 302421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 303421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgclass SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { 304421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgpublic: 305a5c7234e81748f76cbeede40e619351146e5286actguil@chromium.org explicit SkPDFFunctionShader(SkPDFShader::State* state); 306421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org ~SkPDFFunctionShader() { 307421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (isValid()) { 308421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org RemoveShader(this); 309421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 310421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org fResources.unrefAll(); 311b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org } 312da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 313386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org virtual bool isValid() { return fResources.count() > 0; } 314da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 315421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org void getResources(SkTDArray<SkPDFObject*>* resourceList) { 316421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org GetResourcesHelper(&fResources, resourceList); 317421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 318da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 319421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgprivate: 320421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org static SkPDFObject* RangeObject(); 321da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 322421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkTDArray<SkPDFObject*> fResources; 323421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkAutoTDelete<const SkPDFShader::State> fState; 324da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 325421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); 326421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org}; 327421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 328421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgclass SkPDFImageShader : public SkPDFStream, public SkPDFShader { 329421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgpublic: 330a5c7234e81748f76cbeede40e619351146e5286actguil@chromium.org explicit SkPDFImageShader(SkPDFShader::State* state); 331421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org ~SkPDFImageShader() { 332421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org RemoveShader(this); 333421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org fResources.unrefAll(); 334421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 335421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 336386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org virtual bool isValid() { return size() > 0; } 337386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org 338421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org void getResources(SkTDArray<SkPDFObject*>* resourceList) { 339421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org GetResourcesHelper(&fResources, resourceList); 340da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 341421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 342421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgprivate: 343421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkTDArray<SkPDFObject*> fResources; 344421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkAutoTDelete<const SkPDFShader::State> fState; 345421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org}; 346421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 347421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFShader::SkPDFShader() {} 348421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 349421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org// static 350421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgvoid SkPDFShader::RemoveShader(SkPDFObject* shader) { 351421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkAutoMutexAcquire lock(CanonicalShadersMutex()); 352421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org ShaderCanonicalEntry entry(shader, NULL); 353421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org int index = CanonicalShaders().find(entry); 354421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkASSERT(index >= 0); 355421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org CanonicalShaders().removeShuffle(index); 356da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 357da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 358da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org// static 359421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, 360da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org const SkMatrix& matrix, 361da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org const SkIRect& surfaceBBox) { 362421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkPDFObject* result; 363b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org SkAutoMutexAcquire lock(CanonicalShadersMutex()); 364da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkAutoTDelete<State> shaderState(new State(shader, matrix, surfaceBBox)); 365da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 366da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org ShaderCanonicalEntry entry(NULL, shaderState.get()); 367b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org int index = CanonicalShaders().find(entry); 368da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (index >= 0) { 369421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org result = CanonicalShaders()[index].fPDFShader; 370da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->ref(); 371da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return result; 372da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 373386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org 374386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org bool valid = false; 375da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // The PDFShader takes ownership of the shaderSate. 376421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (shaderState.get()->fType == SkShader::kNone_GradientType) { 377386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org SkPDFImageShader* imageShader = 378386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org new SkPDFImageShader(shaderState.detach()); 379386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org valid = imageShader->isValid(); 380386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org result = imageShader; 381421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } else { 382421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkPDFFunctionShader* functionShader = 383421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org new SkPDFFunctionShader(shaderState.detach()); 384386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org valid = functionShader->isValid(); 385421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org result = functionShader; 386da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 387386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org if (!valid) { 388386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org delete result; 389386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org return NULL; 390386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org } 391421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org entry.fPDFShader = result; 392b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org CanonicalShaders().push(entry); 393421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org return result; // return the reference that came from new. 394da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 395da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 396da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org// static 397b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.orgSkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { 398da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // This initialization is only thread safe with gcc. 399da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; 400da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return gCanonicalShaders; 401da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 402da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 403da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org// static 4041771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.comSkBaseMutex& SkPDFShader::CanonicalShadersMutex() { 4051771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.com // This initialization is only thread safe with gcc or when 4061771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.com // POD-style mutex initialization is used. 4071771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.com SK_DECLARE_STATIC_MUTEX(gCanonicalShadersMutex); 408da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return gCanonicalShadersMutex; 409da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 410da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 411da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org// static 412421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFObject* SkPDFFunctionShader::RangeObject() { 413da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // This initialization is only thread safe with gcc. 414da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org static SkPDFArray* range = NULL; 415b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org // This method is only used with CanonicalShadersMutex, so it's safe to 416da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // populate domain. 417da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (range == NULL) { 418da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org range = new SkPDFArray; 419da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org range->reserve(6); 420c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com range->appendInt(0); 421c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com range->appendInt(1); 422c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com range->appendInt(0); 423c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com range->appendInt(1); 424c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com range->appendInt(0); 425c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com range->appendInt(1); 426da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 427da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return range; 428da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 429da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 430421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) 431421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org : SkPDFDict("Pattern"), 432421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org fState(state) { 433da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL; 434da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkPoint transformPoints[2]; 435da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 436da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Depending on the type of the gradient, we want to transform the 437da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // coordinate space in different ways. 438da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org const SkShader::GradientInfo* info = &fState.get()->fInfo; 439da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[0] = info->fPoint[0]; 440da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1] = info->fPoint[1]; 441da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org switch (fState.get()->fType) { 442da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kLinear_GradientType: 443da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org codeFunction = &linearCode; 444da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 445da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kRadial_GradientType: 446da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1] = transformPoints[0]; 447da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1].fX += info->fRadius[0]; 448da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org codeFunction = &radialCode; 449da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 450da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kRadial2_GradientType: { 451421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org // Bail out if the radii are the same. Empty fResources signals 452421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org // an error and isValid will return false. 453da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (info->fRadius[0] == info->fRadius[1]) { 454da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return; 455da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 456da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1] = transformPoints[0]; 457da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar dr = info->fRadius[1] - info->fRadius[0]; 458da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1].fX += dr; 459da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org codeFunction = &twoPointRadialCode; 460da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 461da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 462da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kSweep_GradientType: 463da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1] = transformPoints[0]; 464c39c8674c94dba8b1ffe938cd99c825320cc1475vandebo@chromium.org transformPoints[1].fX += SK_Scalar1; 465da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org codeFunction = &sweepCode; 466da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 467da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kColor_GradientType: 468da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kNone_GradientType: 469020798af6780ba29156f4daec87c29ae9e4f4a12vandebo@chromium.org default: 470da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return; 471da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 472da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 473da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Move any scaling (assuming a unit gradient) or translation 474da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // (and rotation for linear gradient), of the final gradient from 475da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // info->fPoints to the matrix (updating bbox appropriately). Now 476da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // the gradient can be drawn on on the unit segment. 477da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix mapperMatrix; 478da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org unitToPointsMatrix(transformPoints, &mapperMatrix); 479da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix finalMatrix = fState.get()->fCanvasTransform; 480da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org finalMatrix.preConcat(mapperMatrix); 481da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org finalMatrix.preConcat(fState.get()->fShaderTransform); 482da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRect bbox; 483da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org bbox.set(fState.get()->fBBox); 484386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org if (!transformBBox(finalMatrix, &bbox)) { 485386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org return; 486386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org } 487da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 488da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRefPtr<SkPDFArray> domain = new SkPDFArray; 489da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org domain->unref(); // SkRefPtr and new both took a reference. 490da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org domain->reserve(4); 491c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com domain->appendScalar(bbox.fLeft); 492c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com domain->appendScalar(bbox.fRight); 493c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com domain->appendScalar(bbox.fTop); 494c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com domain->appendScalar(bbox.fBottom); 495da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 496da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString functionCode; 497da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // The two point radial gradient further references fState.get()->fInfo 498da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // in translating from x, y coordinates to the t parameter. So, we have 499da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // to transform the points and radii according to the calculated matrix. 500da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fState.get()->fType == SkShader::kRadial2_GradientType) { 501da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkShader::GradientInfo twoPointRadialInfo = *info; 502da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix inverseMapperMatrix; 503b054990307b7338e599a12d9af10eb2058b94051vandebo@chromium.org if (!mapperMatrix.invert(&inverseMapperMatrix)) { 504386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org return; 505b054990307b7338e599a12d9af10eb2058b94051vandebo@chromium.org } 506da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); 507da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org twoPointRadialInfo.fRadius[0] = 508da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org inverseMapperMatrix.mapRadius(info->fRadius[0]); 509da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org twoPointRadialInfo.fRadius[1] = 510da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org inverseMapperMatrix.mapRadius(info->fRadius[1]); 511da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org functionCode = codeFunction(twoPointRadialInfo); 512da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 513da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org functionCode = codeFunction(*info); 514da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 515da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 516da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRefPtr<SkPDFStream> function = makePSFunction(functionCode, domain.get()); 517da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Pass one reference to fResources, SkRefPtr and new both took a reference. 518da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fResources.push(function.get()); 519da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 520da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRefPtr<SkPDFDict> pdfShader = new SkPDFDict; 521da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org pdfShader->unref(); // SkRefPtr and new both took a reference. 522c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com pdfShader->insertInt("ShadingType", 1); 523c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com pdfShader->insertName("ColorSpace", "DeviceRGB"); 524da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org pdfShader->insert("Domain", domain.get()); 525da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org pdfShader->insert("Function", new SkPDFObjRef(function.get()))->unref(); 526da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 527421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertInt("PatternType", 2); 528421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); 529421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insert("Shading", pdfShader.get()); 530da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 531da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 532421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) { 533da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fState.get()->fImage.lockPixels(); 534da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 535da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix finalMatrix = fState.get()->fCanvasTransform; 536da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org finalMatrix.preConcat(fState.get()->fShaderTransform); 537da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRect surfaceBBox; 538da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org surfaceBBox.set(fState.get()->fBBox); 539386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org if (!transformBBox(finalMatrix, &surfaceBBox)) { 540386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org return; 541386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org } 542da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 54375f97e452e8f2ee55cd2b283df7d7734f48bc2bfvandebo@chromium.org SkMatrix unflip; 54454ff85c79d5a59ad9978a91b1aec1177e54104c5vandebo@chromium.org unflip.setTranslate(0, SkScalarRoundToScalar(surfaceBBox.height())); 545663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org unflip.preScale(SK_Scalar1, -SK_Scalar1); 546be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org SkISize size = SkISize::Make(SkScalarRound(surfaceBBox.width()), 547be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org SkScalarRound(surfaceBBox.height())); 548152612938020fa46999f33668027d5bc0f7afd18ctguil@chromium.org SkPDFDevice pattern(size, size, unflip); 549da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkCanvas canvas(&pattern); 550be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org canvas.translate(-surfaceBBox.fLeft, -surfaceBBox.fTop); 551be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org finalMatrix.preTranslate(surfaceBBox.fLeft, surfaceBBox.fTop); 552da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 553da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org const SkBitmap* image = &fState.get()->fImage; 55454ff85c79d5a59ad9978a91b1aec1177e54104c5vandebo@chromium.org SkScalar width = SkIntToScalar(image->width()); 55554ff85c79d5a59ad9978a91b1aec1177e54104c5vandebo@chromium.org SkScalar height = SkIntToScalar(image->height()); 556da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkShader::TileMode tileModes[2]; 557da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModes[0] = fState.get()->fImageTileModes[0]; 558da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModes[1] = fState.get()->fImageTileModes[1]; 559da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 560da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmap(*image, 0, 0); 561be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org SkRect patternBBox = SkRect::MakeXYWH(-surfaceBBox.fLeft, -surfaceBBox.fTop, 562be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org width, height); 563da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 564da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Tiling is implied. First we handle mirroring. 565da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[0] == SkShader::kMirror_TileMode) { 566da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix xMirror; 567da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org xMirror.setScale(-1, 1); 568da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org xMirror.postTranslate(2 * width, 0); 569da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(*image, xMirror); 570da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org patternBBox.fRight += width; 571da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 572da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[1] == SkShader::kMirror_TileMode) { 573da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix yMirror; 574663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org yMirror.setScale(SK_Scalar1, -SK_Scalar1); 575da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org yMirror.postTranslate(0, 2 * height); 576da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(*image, yMirror); 577da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org patternBBox.fBottom += height; 578da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 579da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[0] == SkShader::kMirror_TileMode && 580da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModes[1] == SkShader::kMirror_TileMode) { 581da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix mirror; 582da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org mirror.setScale(-1, -1); 583da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org mirror.postTranslate(2 * width, 2 * height); 584da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(*image, mirror); 585da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 586da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 587da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Then handle Clamping, which requires expanding the pattern canvas to 588da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // cover the entire surfaceBBox. 589da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 590da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // If both x and y are in clamp mode, we start by filling in the corners. 591da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // (Which are just a rectangles of the corner colors.) 592da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[0] == SkShader::kClamp_TileMode && 593da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModes[1] == SkShader::kClamp_TileMode) { 594da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkPaint paint; 595da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRect rect; 596da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rect = SkRect::MakeLTRB(surfaceBBox.fLeft, surfaceBBox.fTop, 0, 0); 597da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (!rect.isEmpty()) { 598da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org paint.setColor(image->getColor(0, 0)); 599da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawRect(rect, paint); 600da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 601da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 602da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rect = SkRect::MakeLTRB(width, surfaceBBox.fTop, surfaceBBox.fRight, 0); 603da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (!rect.isEmpty()) { 60454ff85c79d5a59ad9978a91b1aec1177e54104c5vandebo@chromium.org paint.setColor(image->getColor(image->width() - 1, 0)); 605da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawRect(rect, paint); 606da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 607da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 608da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rect = SkRect::MakeLTRB(width, height, surfaceBBox.fRight, 609da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org surfaceBBox.fBottom); 610da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (!rect.isEmpty()) { 61154ff85c79d5a59ad9978a91b1aec1177e54104c5vandebo@chromium.org paint.setColor(image->getColor(image->width() - 1, 61254ff85c79d5a59ad9978a91b1aec1177e54104c5vandebo@chromium.org image->height() - 1)); 613da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawRect(rect, paint); 614da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 615da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 616da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rect = SkRect::MakeLTRB(surfaceBBox.fLeft, height, 0, 617da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org surfaceBBox.fBottom); 618da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (!rect.isEmpty()) { 61954ff85c79d5a59ad9978a91b1aec1177e54104c5vandebo@chromium.org paint.setColor(image->getColor(0, image->height() - 1)); 620da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawRect(rect, paint); 621da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 622da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 623da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 624da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Then expand the left, right, top, then bottom. 625da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[0] == SkShader::kClamp_TileMode) { 62654ff85c79d5a59ad9978a91b1aec1177e54104c5vandebo@chromium.org SkIRect subset = SkIRect::MakeXYWH(0, 0, 1, image->height()); 627da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (surfaceBBox.fLeft < 0) { 628da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkBitmap left; 629da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkAssertResult(image->extractSubset(&left, subset)); 630da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 631da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix leftMatrix; 632da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org leftMatrix.setScale(-surfaceBBox.fLeft, 1); 633da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org leftMatrix.postTranslate(surfaceBBox.fLeft, 0); 634da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(left, leftMatrix); 635da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 636da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[1] == SkShader::kMirror_TileMode) { 637663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org leftMatrix.postScale(SK_Scalar1, -SK_Scalar1); 638da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org leftMatrix.postTranslate(0, 2 * height); 639da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(left, leftMatrix); 640da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 641be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org patternBBox.fLeft = 0; 642da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 643da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 644da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (surfaceBBox.fRight > width) { 645da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkBitmap right; 64654ff85c79d5a59ad9978a91b1aec1177e54104c5vandebo@chromium.org subset.offset(image->width() - 1, 0); 647da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkAssertResult(image->extractSubset(&right, subset)); 648da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 649da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix rightMatrix; 650da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rightMatrix.setScale(surfaceBBox.fRight - width, 1); 651da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rightMatrix.postTranslate(width, 0); 652da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(right, rightMatrix); 653da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 654da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[1] == SkShader::kMirror_TileMode) { 655663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org rightMatrix.postScale(SK_Scalar1, -SK_Scalar1); 656da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rightMatrix.postTranslate(0, 2 * height); 657da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(right, rightMatrix); 658da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 659be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org patternBBox.fRight = surfaceBBox.width(); 660da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 661da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 662da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 663da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[1] == SkShader::kClamp_TileMode) { 66454ff85c79d5a59ad9978a91b1aec1177e54104c5vandebo@chromium.org SkIRect subset = SkIRect::MakeXYWH(0, 0, image->width(), 1); 665da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (surfaceBBox.fTop < 0) { 666da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkBitmap top; 667da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkAssertResult(image->extractSubset(&top, subset)); 668da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 669da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix topMatrix; 670663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org topMatrix.setScale(SK_Scalar1, -surfaceBBox.fTop); 671da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org topMatrix.postTranslate(0, surfaceBBox.fTop); 672da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(top, topMatrix); 673da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 674da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[0] == SkShader::kMirror_TileMode) { 675da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org topMatrix.postScale(-1, 1); 676da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org topMatrix.postTranslate(2 * width, 0); 677da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(top, topMatrix); 678da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 679be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org patternBBox.fTop = 0; 680da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 681da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 682da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (surfaceBBox.fBottom > height) { 683da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkBitmap bottom; 68454ff85c79d5a59ad9978a91b1aec1177e54104c5vandebo@chromium.org subset.offset(0, image->height() - 1); 685da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkAssertResult(image->extractSubset(&bottom, subset)); 686da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 687da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix bottomMatrix; 688663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org bottomMatrix.setScale(SK_Scalar1, surfaceBBox.fBottom - height); 689da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org bottomMatrix.postTranslate(0, height); 690da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(bottom, bottomMatrix); 691da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 692da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[0] == SkShader::kMirror_TileMode) { 693da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org bottomMatrix.postScale(-1, 1); 694da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org bottomMatrix.postTranslate(2 * width, 0); 695da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(bottom, bottomMatrix); 696da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 697be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org patternBBox.fBottom = surfaceBBox.height(); 698da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 699da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 700da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 701da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRefPtr<SkPDFArray> patternBBoxArray = new SkPDFArray; 702da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org patternBBoxArray->unref(); // SkRefPtr and new both took a reference. 703da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org patternBBoxArray->reserve(4); 704c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com patternBBoxArray->appendScalar(patternBBox.fLeft); 705c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com patternBBoxArray->appendScalar(patternBBox.fTop); 706c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com patternBBoxArray->appendScalar(patternBBox.fRight); 707c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com patternBBoxArray->appendScalar(patternBBox.fBottom); 708da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 709da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Put the canvas into the pattern stream (fContent). 710da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRefPtr<SkStream> content = pattern.content(); 711da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org content->unref(); // SkRefPtr and content() both took a reference. 712188838c20818307fda770ffc395a76ea63c1c8ccvandebo@chromium.org pattern.getResources(&fResources, false); 713da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 714421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org setData(content.get()); 715421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertName("Type", "Pattern"); 716421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertInt("PatternType", 1); 717421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertInt("PaintType", 1); 718421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertInt("TilingType", 1); 719421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insert("BBox", patternBBoxArray.get()); 720421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertScalar("XStep", patternBBox.width()); 721421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertScalar("YStep", patternBBox.height()); 7221feb33068b1313d2647c50b90ae8e0a3d510db2ereed@google.com insert("Resources", pattern.getResourceDict()); 723421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); 724da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 725da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fState.get()->fImage.unlockPixels(); 726da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 727da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 728421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, 729421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkPDFArray* domain) { 730421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), 731421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org psCode.size())); 732421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkPDFStream* result = new SkPDFStream(funcData.get()); 733c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com result->insertInt("FunctionType", 4); 734da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->insert("Domain", domain); 735f6c3ebdeb135dcdb9af225bd7af77f1fe1f92787reed@google.com result->insert("Range", RangeObject()); 736da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return result; 737da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 738da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 739421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFShader::ShaderCanonicalEntry::ShaderCanonicalEntry(SkPDFObject* pdfShader, 740421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org const State* state) 741421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org : fPDFShader(pdfShader), 742421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org fState(state) { 743421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org} 744421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 745421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgbool SkPDFShader::ShaderCanonicalEntry::operator==( 746421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org const ShaderCanonicalEntry& b) const { 747421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org return fPDFShader == b.fPDFShader || 748421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org (fState != NULL && b.fState != NULL && *fState == *b.fState); 749421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org} 750421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 751da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgbool SkPDFShader::State::operator==(const SkPDFShader::State& b) const { 752da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fType != b.fType || 753da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fCanvasTransform != b.fCanvasTransform || 754da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fShaderTransform != b.fShaderTransform || 755da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fBBox != b.fBBox) { 756da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return false; 757da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 758da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 759da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fType == SkShader::kNone_GradientType) { 760da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fPixelGeneration != b.fPixelGeneration || 761da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fPixelGeneration == 0 || 762da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fImageTileModes[0] != b.fImageTileModes[0] || 763da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fImageTileModes[1] != b.fImageTileModes[1]) { 764da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return false; 765da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 766da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 767da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fInfo.fColorCount != b.fInfo.fColorCount || 768da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org memcmp(fInfo.fColors, b.fInfo.fColors, 769da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org sizeof(SkColor) * fInfo.fColorCount) != 0 || 770da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org memcmp(fInfo.fColorOffsets, b.fInfo.fColorOffsets, 771da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org sizeof(SkScalar) * fInfo.fColorCount) != 0 || 772da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fPoint[0] != b.fInfo.fPoint[0] || 773da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fTileMode != b.fInfo.fTileMode) { 774da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return false; 775da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 776da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 777da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org switch (fType) { 778da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kLinear_GradientType: 779da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fInfo.fPoint[1] != b.fInfo.fPoint[1]) { 780da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return false; 781da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 782da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 783da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kRadial_GradientType: 784da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fInfo.fRadius[0] != b.fInfo.fRadius[0]) { 785da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return false; 786da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 787da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 788da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kRadial2_GradientType: 789da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fInfo.fPoint[1] != b.fInfo.fPoint[1] || 790da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fRadius[0] != b.fInfo.fRadius[0] || 791da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fRadius[1] != b.fInfo.fRadius[1]) { 792da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return false; 793da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 794da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 795da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kSweep_GradientType: 796da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kNone_GradientType: 797da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kColor_GradientType: 798da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 799da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 800da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 801da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return true; 802da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 803da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 804da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgSkPDFShader::State::State(const SkShader& shader, 805da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org const SkMatrix& canvasTransform, const SkIRect& bbox) 806da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org : fCanvasTransform(canvasTransform), 807e1bc274295ec57cb3d3f01aaa8abff3b49c76c73vandebo@chromium.org fBBox(bbox), 808e1bc274295ec57cb3d3f01aaa8abff3b49c76c73vandebo@chromium.org fPixelGeneration(0) { 809da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fColorCount = 0; 810da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fColors = NULL; 811da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fColorOffsets = NULL; 812da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org shader.getLocalMatrix(&fShaderTransform); 813e1bc274295ec57cb3d3f01aaa8abff3b49c76c73vandebo@chromium.org fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; 814da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 815da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fType = shader.asAGradient(&fInfo); 816da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 817da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fType == SkShader::kNone_GradientType) { 818da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkShader::BitmapType bitmapType; 819da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix matrix; 820da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes, NULL); 821da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (bitmapType != SkShader::kDefault_BitmapType) { 822da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fImage.reset(); 823da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return; 824da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 825da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkASSERT(matrix.isIdentity()); 826da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fPixelGeneration = fImage.getGenerationID(); 827da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 828da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fColorData.set(sk_malloc_throw( 829da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); 830a5c7234e81748f76cbeede40e619351146e5286actguil@chromium.org fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); 831020798af6780ba29156f4daec87c29ae9e4f4a12vandebo@chromium.org fInfo.fColorOffsets = 832020798af6780ba29156f4daec87c29ae9e4f4a12vandebo@chromium.org reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); 833da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org shader.asAGradient(&fInfo); 834da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 835da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 836