SkPDFShader.cpp revision 1771cbf43d9a1334e3d870c635b4215bb888dd98
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 24da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic void transformBBox(const SkMatrix& matrix, SkRect* bbox) { 25da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix inverse; 26da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org inverse.reset(); 27da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org matrix.invert(&inverse); 28da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org inverse.mapRect(bbox); 29da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 30da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 31da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic void unitToPointsMatrix(const SkPoint pts[2], SkMatrix* matrix) { 32da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkVector vec = pts[1] - pts[0]; 33da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar mag = vec.length(); 34da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar inv = mag ? SkScalarInvert(mag) : 0; 35da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 36da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org vec.scale(inv); 37da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org matrix->setSinCos(vec.fY, vec.fX); 38da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org matrix->preTranslate(pts[0].fX, pts[0].fY); 39da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org matrix->preScale(mag, mag); 40da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 41da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 42da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org/* Assumes t + startOffset is on the stack and does a linear interpolation on t 43da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org between startOffset and endOffset from prevColor to curColor (for each color 44da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org component), leaving the result in component order on the stack. 45da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org @param range endOffset - startOffset 46da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org @param curColor[components] The current color components. 47da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org @param prevColor[components] The previous color components. 48da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org @param result The result ps function. 49da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org */ 50da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic void interpolateColorCode(SkScalar range, SkScalar* curColor, 51da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar* prevColor, int components, 52da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString* result) { 53da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Figure out how to scale each color component. 54316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com SkAutoSTMalloc<4, SkScalar> multiplierAlloc(components); 55316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com SkScalar *multiplier = multiplierAlloc.get(); 56da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = 0; i < components; i++) { 57da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org multiplier[i] = SkScalarDiv(curColor[i] - prevColor[i], range); 58da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 59da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 60da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Calculate when we no longer need to keep a copy of the input parameter t. 61da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // If the last component to use t is i, then dupInput[0..i - 1] = true 62da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // and dupInput[i .. components] = false. 63316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com SkAutoSTMalloc<4, bool> dupInputAlloc(components); 64316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com bool *dupInput = dupInputAlloc.get(); 65da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org dupInput[components - 1] = false; 66da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = components - 2; i >= 0; i--) { 67da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org dupInput[i] = dupInput[i + 1] || multiplier[i + 1] != 0; 68da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 69da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 70da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (!dupInput[0] && multiplier[0] == 0) { 71da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("pop "); 72da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 73da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 74da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = 0; i < components; i++) { 75da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // If the next components needs t, make a copy. 76da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (dupInput[i]) { 77da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("dup "); 78da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 79da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 80da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (multiplier[i] == 0) { 81da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(prevColor[i]); 82da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" "); 83da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 84da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (multiplier[i] != 1) { 85da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(multiplier[i]); 86da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" mul "); 87da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 88da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (prevColor[i] != 0) { 89da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(prevColor[i]); 90da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" add "); 91da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 92da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 93da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 94da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (dupInput[i]) { 95da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("exch\n"); 96da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 97da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 98da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 99da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 100da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org/* Generate Type 4 function code to map t=[0,1) to the passed gradient, 101da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org clamping at the edges of the range. The generated code will be of the form: 102da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (t < 0) { 103da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return colorData[0][r,g,b]; 104da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 105da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (t < info.fColorOffsets[1]) { 106da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return linearinterpolation(colorData[0][r,g,b], 107da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org colorData[1][r,g,b]); 108da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 109da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (t < info.fColorOffsets[2]) { 110da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return linearinterpolation(colorData[1][r,g,b], 111da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org colorData[2][r,g,b]); 112da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 113da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 114da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org ... } else { 115da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return colorData[info.fColorCount - 1][r,g,b]; 116da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 117da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org ... 118da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 119da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 120da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org */ 121da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic void gradientFunctionCode(const SkShader::GradientInfo& info, 122da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString* result) { 123da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org /* We want to linearly interpolate from the previous color to the next. 124da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org Scale the colors from 0..255 to 0..1 and determine the multipliers 125da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for interpolation. 126da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org C{r,g,b}(t, section) = t - offset_(section-1) + t * Multiplier{r,g,b}. 127da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org */ 128da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org static const int kColorComponents = 3; 129316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com typedef SkScalar ColorTuple[kColorComponents]; 130316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(info.fColorCount); 131316338a4eb54b544409e3a98d97ea0a829aef706twiz@google.com ColorTuple *colorData = colorDataAlloc.get(); 132da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org const SkScalar scale = SkScalarInvert(SkIntToScalar(255)); 133da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = 0; i < info.fColorCount; i++) { 134da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org colorData[i][0] = SkScalarMul(SkColorGetR(info.fColors[i]), scale); 135da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org colorData[i][1] = SkScalarMul(SkColorGetG(info.fColors[i]), scale); 136da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org colorData[i][2] = SkScalarMul(SkColorGetB(info.fColors[i]), scale); 137da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 138da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 139da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Clamp the initial color. 140da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("dup 0 le {pop "); 141da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(colorData[0][0]); 142da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" "); 143da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(colorData[0][1]); 144da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" "); 145da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(colorData[0][2]); 146da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" }\n"); 147da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 148da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // The gradient colors. 149da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = 1 ; i < info.fColorCount; i++) { 150da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("{dup "); 151da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(info.fColorOffsets[i]); 152da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" le {"); 153da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (info.fColorOffsets[i - 1] != 0) { 154da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(info.fColorOffsets[i - 1]); 155da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" sub\n"); 156da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 157da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 158da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org interpolateColorCode(info.fColorOffsets[i] - info.fColorOffsets[i - 1], 159da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org colorData[i], colorData[i - 1], kColorComponents, 160da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result); 161da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("}\n"); 162da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 163da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 164da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Clamp the final color. 165da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("{pop "); 166da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(colorData[info.fColorCount - 1][0]); 167da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" "); 168da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(colorData[info.fColorCount - 1][1]); 169da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append(" "); 170da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->appendScalar(colorData[info.fColorCount - 1][2]); 171da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 172da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = 0 ; i < info.fColorCount; i++) { 173da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("} ifelse\n"); 174da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 175da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 176da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 177da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org/* Map a value of t on the stack into [0, 1) for Repeat or Mirror tile mode. */ 178da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic void tileModeCode(SkShader::TileMode mode, SkString* result) { 179da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (mode == SkShader::kRepeat_TileMode) { 180da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("dup truncate sub\n"); // Get the fractional part. 181da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("dup 0 le {1 add} if\n"); // Map (-1,0) => (0,1) 182da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return; 183da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 184da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 185da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (mode == SkShader::kMirror_TileMode) { 186da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Map t mod 2 into [0, 1, 1, 0]. 187da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Code Stack 188da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->append("abs " // Map negative to positive. 189da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "dup " // t.s t.s 190da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "truncate " // t.s t 191da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "dup " // t.s t t 192da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "cvi " // t.s t T 193da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "2 mod " // t.s t (i mod 2) 194da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "1 eq " // t.s t true|false 195da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "3 1 roll " // true|false t.s t 196da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "sub " // true|false 0.s 197da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "exch " // 0.s true|false 198da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "{1 exch sub} if\n"); // 1 - 0.s|0.s 199da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 200da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 201da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 202da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic SkString linearCode(const SkShader::GradientInfo& info) { 203a5c7234e81748f76cbeede40e619351146e5286actguil@chromium.org SkString function("{pop\n"); // Just ditch the y value. 204da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModeCode(info.fTileMode, &function); 205da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org gradientFunctionCode(info, &function); 206da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("}"); 207da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return function; 208da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 209da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 210da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic SkString radialCode(const SkShader::GradientInfo& info) { 211da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString function("{"); 212da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Find the distance from the origin. 213da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("dup " // x y y 214da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "mul " // x y^2 215da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "exch " // y^2 x 216da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "dup " // y^2 x x 217da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "mul " // y^2 x^2 218da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "add " // y^2+x^2 219da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org "sqrt\n"); // sqrt(y^2+x^2) 220da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 221da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModeCode(info.fTileMode, &function); 222da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org gradientFunctionCode(info, &function); 223da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("}"); 224da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return function; 225da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 226da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 227da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org/* The math here is all based on the description in Two_Point_Radial_Gradient, 228da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org with one simplification, the coordinate space has been scaled so that 229da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org Dr = 1. This means we don't need to scale the entire equation by 1/Dr^2. 230da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org */ 231da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic SkString twoPointRadialCode(const SkShader::GradientInfo& info) { 232da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar dx = info.fPoint[0].fX - info.fPoint[1].fX; 233da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar dy = info.fPoint[0].fY - info.fPoint[1].fY; 234da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar sr = info.fRadius[0]; 235da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar a = SkScalarMul(dx, dx) + SkScalarMul(dy, dy) - SK_Scalar1; 236da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org bool posRoot = info.fRadius[1] > info.fRadius[0]; 237da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 238da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // We start with a stack of (x y), copy it and then consume one copy in 239da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // order to calculate b and the other to calculate c. 240da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString function("{"); 241da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("2 copy "); 242da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 243da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Calculate -b and b^2. 244da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.appendScalar(dy); 245da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append(" mul exch "); 246da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.appendScalar(dx); 247da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append(" mul add "); 248da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.appendScalar(sr); 249da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append(" sub 2 mul neg dup dup mul\n"); 250da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 251da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Calculate c 252da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("4 2 roll dup mul exch dup mul add "); 253da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.appendScalar(SkScalarMul(sr, sr)); 254da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append(" sub\n"); 255da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 256da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Calculate the determinate 257da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.appendScalar(SkScalarMul(SkIntToScalar(4), a)); 258da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append(" mul sub abs sqrt\n"); 259da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 260da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // And then the final value of t. 261da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (posRoot) { 262da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("sub "); 263da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 264da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("add "); 265da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 266da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.appendScalar(SkScalarMul(SkIntToScalar(2), a)); 267da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append(" div\n"); 268da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 269da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModeCode(info.fTileMode, &function); 270da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org gradientFunctionCode(info, &function); 271da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("}"); 272da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return function; 273da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 274da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 275da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgstatic SkString sweepCode(const SkShader::GradientInfo& info) { 276da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString function("{exch atan 360 div\n"); 277da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModeCode(info.fTileMode, &function); 278da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org gradientFunctionCode(info, &function); 279da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org function.append("}"); 280da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return function; 281da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 282da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 283421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgclass SkPDFShader::State { 284421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgpublic: 285421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkShader::GradientType fType; 286421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkShader::GradientInfo fInfo; 287421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkAutoFree fColorData; 288421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkMatrix fCanvasTransform; 289421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkMatrix fShaderTransform; 290421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkIRect fBBox; 291421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 292421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkBitmap fImage; 293421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org uint32_t fPixelGeneration; 294421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkShader::TileMode fImageTileModes[2]; 295421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 296421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org explicit State(const SkShader& shader, const SkMatrix& canvasTransform, 297421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org const SkIRect& bbox); 298421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org bool operator==(const State& b) const; 299421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org}; 300421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 301421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgclass SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { 302421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgpublic: 303a5c7234e81748f76cbeede40e619351146e5286actguil@chromium.org explicit SkPDFFunctionShader(SkPDFShader::State* state); 304421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org ~SkPDFFunctionShader() { 305421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (isValid()) { 306421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org RemoveShader(this); 307421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 308421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org fResources.unrefAll(); 309b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org } 310da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 311421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org bool isValid() { return fResources.count() > 0; } 312da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 313421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org void getResources(SkTDArray<SkPDFObject*>* resourceList) { 314421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org GetResourcesHelper(&fResources, resourceList); 315421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 316da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 317421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgprivate: 318421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org static SkPDFObject* RangeObject(); 319da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 320421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkTDArray<SkPDFObject*> fResources; 321421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkAutoTDelete<const SkPDFShader::State> fState; 322da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 323421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); 324421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org}; 325421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 326421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgclass SkPDFImageShader : public SkPDFStream, public SkPDFShader { 327421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgpublic: 328a5c7234e81748f76cbeede40e619351146e5286actguil@chromium.org explicit SkPDFImageShader(SkPDFShader::State* state); 329421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org ~SkPDFImageShader() { 330421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org RemoveShader(this); 331421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org fResources.unrefAll(); 332421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 333421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 334421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org void getResources(SkTDArray<SkPDFObject*>* resourceList) { 335421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org GetResourcesHelper(&fResources, resourceList); 336da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 337421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 338421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgprivate: 339421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkTDArray<SkPDFObject*> fResources; 340421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkAutoTDelete<const SkPDFShader::State> fState; 341421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org}; 342421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 343421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFShader::SkPDFShader() {} 344421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 345421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org// static 346421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgvoid SkPDFShader::RemoveShader(SkPDFObject* shader) { 347421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkAutoMutexAcquire lock(CanonicalShadersMutex()); 348421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org ShaderCanonicalEntry entry(shader, NULL); 349421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org int index = CanonicalShaders().find(entry); 350421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkASSERT(index >= 0); 351421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org CanonicalShaders().removeShuffle(index); 352da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 353da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 354da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org// static 355421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, 356da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org const SkMatrix& matrix, 357da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org const SkIRect& surfaceBBox) { 358421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkPDFObject* result; 359b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org SkAutoMutexAcquire lock(CanonicalShadersMutex()); 360da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkAutoTDelete<State> shaderState(new State(shader, matrix, surfaceBBox)); 361da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 362da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org ShaderCanonicalEntry entry(NULL, shaderState.get()); 363b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org int index = CanonicalShaders().find(entry); 364da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (index >= 0) { 365421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org result = CanonicalShaders()[index].fPDFShader; 366da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->ref(); 367da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return result; 368da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 369da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // The PDFShader takes ownership of the shaderSate. 370421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (shaderState.get()->fType == SkShader::kNone_GradientType) { 371421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org result = new SkPDFImageShader(shaderState.detach()); 372421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } else { 373421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkPDFFunctionShader* functionShader = 374421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org new SkPDFFunctionShader(shaderState.detach()); 375421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (!functionShader->isValid()) { 376421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org delete functionShader; 377421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org return NULL; 378421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 379421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org result = functionShader; 380da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 381421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org entry.fPDFShader = result; 382b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org CanonicalShaders().push(entry); 383421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org return result; // return the reference that came from new. 384da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 385da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 386da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org// static 387b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.orgSkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { 388da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // This initialization is only thread safe with gcc. 389da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; 390da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return gCanonicalShaders; 391da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 392da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 393da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org// static 3941771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.comSkBaseMutex& SkPDFShader::CanonicalShadersMutex() { 3951771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.com // This initialization is only thread safe with gcc or when 3961771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.com // POD-style mutex initialization is used. 3971771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.com SK_DECLARE_STATIC_MUTEX(gCanonicalShadersMutex); 398da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return gCanonicalShadersMutex; 399da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 400da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 401da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org// static 402421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFObject* SkPDFFunctionShader::RangeObject() { 403da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // This initialization is only thread safe with gcc. 404da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org static SkPDFArray* range = NULL; 405b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org // This method is only used with CanonicalShadersMutex, so it's safe to 406da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // populate domain. 407da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (range == NULL) { 408da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org range = new SkPDFArray; 409da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org range->reserve(6); 410c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com range->appendInt(0); 411c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com range->appendInt(1); 412c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com range->appendInt(0); 413c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com range->appendInt(1); 414c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com range->appendInt(0); 415c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com range->appendInt(1); 416da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 417da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return range; 418da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 419da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 420421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) 421421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org : SkPDFDict("Pattern"), 422421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org fState(state) { 423da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL; 424da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkPoint transformPoints[2]; 425da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 426da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Depending on the type of the gradient, we want to transform the 427da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // coordinate space in different ways. 428da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org const SkShader::GradientInfo* info = &fState.get()->fInfo; 429da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[0] = info->fPoint[0]; 430da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1] = info->fPoint[1]; 431da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org switch (fState.get()->fType) { 432da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kLinear_GradientType: 433da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org codeFunction = &linearCode; 434da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 435da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kRadial_GradientType: 436da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1] = transformPoints[0]; 437da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1].fX += info->fRadius[0]; 438da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org codeFunction = &radialCode; 439da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 440da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kRadial2_GradientType: { 441421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org // Bail out if the radii are the same. Empty fResources signals 442421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org // an error and isValid will return false. 443da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (info->fRadius[0] == info->fRadius[1]) { 444da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return; 445da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 446da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1] = transformPoints[0]; 447da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkScalar dr = info->fRadius[1] - info->fRadius[0]; 448da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1].fX += dr; 449da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org codeFunction = &twoPointRadialCode; 450da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 451da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 452da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kSweep_GradientType: 453da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1] = transformPoints[0]; 454da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformPoints[1].fX += 1; 455da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org codeFunction = &sweepCode; 456da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 457da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kColor_GradientType: 458da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kNone_GradientType: 459020798af6780ba29156f4daec87c29ae9e4f4a12vandebo@chromium.org default: 460da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return; 461da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 462da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 463da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Move any scaling (assuming a unit gradient) or translation 464da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // (and rotation for linear gradient), of the final gradient from 465da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // info->fPoints to the matrix (updating bbox appropriately). Now 466da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // the gradient can be drawn on on the unit segment. 467da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix mapperMatrix; 468da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org unitToPointsMatrix(transformPoints, &mapperMatrix); 469da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix finalMatrix = fState.get()->fCanvasTransform; 470da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org finalMatrix.preConcat(mapperMatrix); 471da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org finalMatrix.preConcat(fState.get()->fShaderTransform); 472da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRect bbox; 473da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org bbox.set(fState.get()->fBBox); 474da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformBBox(finalMatrix, &bbox); 475da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 476da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRefPtr<SkPDFArray> domain = new SkPDFArray; 477da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org domain->unref(); // SkRefPtr and new both took a reference. 478da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org domain->reserve(4); 479c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com domain->appendScalar(bbox.fLeft); 480c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com domain->appendScalar(bbox.fRight); 481c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com domain->appendScalar(bbox.fTop); 482c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com domain->appendScalar(bbox.fBottom); 483da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 484da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkString functionCode; 485da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // The two point radial gradient further references fState.get()->fInfo 486da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // in translating from x, y coordinates to the t parameter. So, we have 487da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // to transform the points and radii according to the calculated matrix. 488da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fState.get()->fType == SkShader::kRadial2_GradientType) { 489da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkShader::GradientInfo twoPointRadialInfo = *info; 490da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix inverseMapperMatrix; 491da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org mapperMatrix.invert(&inverseMapperMatrix); 492da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); 493da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org twoPointRadialInfo.fRadius[0] = 494da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org inverseMapperMatrix.mapRadius(info->fRadius[0]); 495da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org twoPointRadialInfo.fRadius[1] = 496da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org inverseMapperMatrix.mapRadius(info->fRadius[1]); 497da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org functionCode = codeFunction(twoPointRadialInfo); 498da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 499da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org functionCode = codeFunction(*info); 500da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 501da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 502da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRefPtr<SkPDFStream> function = makePSFunction(functionCode, domain.get()); 503da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Pass one reference to fResources, SkRefPtr and new both took a reference. 504da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fResources.push(function.get()); 505da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 506da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRefPtr<SkPDFDict> pdfShader = new SkPDFDict; 507da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org pdfShader->unref(); // SkRefPtr and new both took a reference. 508c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com pdfShader->insertInt("ShadingType", 1); 509c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com pdfShader->insertName("ColorSpace", "DeviceRGB"); 510da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org pdfShader->insert("Domain", domain.get()); 511da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org pdfShader->insert("Function", new SkPDFObjRef(function.get()))->unref(); 512da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 513421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertInt("PatternType", 2); 514421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); 515421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insert("Shading", pdfShader.get()); 516da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 517da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 518421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) { 519da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fState.get()->fImage.lockPixels(); 520da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 521da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix finalMatrix = fState.get()->fCanvasTransform; 522da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org finalMatrix.preConcat(fState.get()->fShaderTransform); 523da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRect surfaceBBox; 524da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org surfaceBBox.set(fState.get()->fBBox); 525da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org transformBBox(finalMatrix, &surfaceBBox); 526da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 52775f97e452e8f2ee55cd2b283df7d7734f48bc2bfvandebo@chromium.org SkMatrix unflip; 528be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org unflip.setTranslate(0, SkScalarRound(surfaceBBox.height())); 529663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org unflip.preScale(SK_Scalar1, -SK_Scalar1); 530be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org SkISize size = SkISize::Make(SkScalarRound(surfaceBBox.width()), 531be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org SkScalarRound(surfaceBBox.height())); 532152612938020fa46999f33668027d5bc0f7afd18ctguil@chromium.org SkPDFDevice pattern(size, size, unflip); 533da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkCanvas canvas(&pattern); 534be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org canvas.translate(-surfaceBBox.fLeft, -surfaceBBox.fTop); 535be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org finalMatrix.preTranslate(surfaceBBox.fLeft, surfaceBBox.fTop); 536da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 537da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org const SkBitmap* image = &fState.get()->fImage; 538da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org int width = image->width(); 539da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org int height = image->height(); 540da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkShader::TileMode tileModes[2]; 541da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModes[0] = fState.get()->fImageTileModes[0]; 542da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModes[1] = fState.get()->fImageTileModes[1]; 543da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 544da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmap(*image, 0, 0); 545be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org SkRect patternBBox = SkRect::MakeXYWH(-surfaceBBox.fLeft, -surfaceBBox.fTop, 546be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org width, height); 547da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 548da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Tiling is implied. First we handle mirroring. 549da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[0] == SkShader::kMirror_TileMode) { 550da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix xMirror; 551da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org xMirror.setScale(-1, 1); 552da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org xMirror.postTranslate(2 * width, 0); 553da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(*image, xMirror); 554da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org patternBBox.fRight += width; 555da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 556da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[1] == SkShader::kMirror_TileMode) { 557da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix yMirror; 558663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org yMirror.setScale(SK_Scalar1, -SK_Scalar1); 559da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org yMirror.postTranslate(0, 2 * height); 560da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(*image, yMirror); 561da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org patternBBox.fBottom += height; 562da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 563da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[0] == SkShader::kMirror_TileMode && 564da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModes[1] == SkShader::kMirror_TileMode) { 565da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix mirror; 566da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org mirror.setScale(-1, -1); 567da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org mirror.postTranslate(2 * width, 2 * height); 568da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(*image, mirror); 569da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 570da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 571da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Then handle Clamping, which requires expanding the pattern canvas to 572da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // cover the entire surfaceBBox. 573da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 574da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // If both x and y are in clamp mode, we start by filling in the corners. 575da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // (Which are just a rectangles of the corner colors.) 576da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[0] == SkShader::kClamp_TileMode && 577da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org tileModes[1] == SkShader::kClamp_TileMode) { 578da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkPaint paint; 579da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRect rect; 580da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rect = SkRect::MakeLTRB(surfaceBBox.fLeft, surfaceBBox.fTop, 0, 0); 581da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (!rect.isEmpty()) { 582da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org paint.setColor(image->getColor(0, 0)); 583da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawRect(rect, paint); 584da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 585da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 586da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rect = SkRect::MakeLTRB(width, surfaceBBox.fTop, surfaceBBox.fRight, 0); 587da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (!rect.isEmpty()) { 588da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org paint.setColor(image->getColor(width - 1, 0)); 589da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawRect(rect, paint); 590da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 591da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 592da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rect = SkRect::MakeLTRB(width, height, surfaceBBox.fRight, 593da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org surfaceBBox.fBottom); 594da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (!rect.isEmpty()) { 595da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org paint.setColor(image->getColor(width - 1, height - 1)); 596da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawRect(rect, paint); 597da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 598da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 599da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rect = SkRect::MakeLTRB(surfaceBBox.fLeft, height, 0, 600da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org surfaceBBox.fBottom); 601da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (!rect.isEmpty()) { 602da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org paint.setColor(image->getColor(0, height - 1)); 603da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawRect(rect, paint); 604da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 605da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 606da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 607da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Then expand the left, right, top, then bottom. 608da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[0] == SkShader::kClamp_TileMode) { 609da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkIRect subset = SkIRect::MakeXYWH(0, 0, 1, height); 610da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (surfaceBBox.fLeft < 0) { 611da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkBitmap left; 612da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkAssertResult(image->extractSubset(&left, subset)); 613da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 614da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix leftMatrix; 615da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org leftMatrix.setScale(-surfaceBBox.fLeft, 1); 616da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org leftMatrix.postTranslate(surfaceBBox.fLeft, 0); 617da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(left, leftMatrix); 618da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 619da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[1] == SkShader::kMirror_TileMode) { 620663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org leftMatrix.postScale(SK_Scalar1, -SK_Scalar1); 621da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org leftMatrix.postTranslate(0, 2 * height); 622da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(left, leftMatrix); 623da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 624be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org patternBBox.fLeft = 0; 625da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 626da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 627da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (surfaceBBox.fRight > width) { 628da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkBitmap right; 629da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org subset.offset(width - 1, 0); 630da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkAssertResult(image->extractSubset(&right, subset)); 631da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 632da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix rightMatrix; 633da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rightMatrix.setScale(surfaceBBox.fRight - width, 1); 634da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rightMatrix.postTranslate(width, 0); 635da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(right, rightMatrix); 636da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 637da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[1] == SkShader::kMirror_TileMode) { 638663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org rightMatrix.postScale(SK_Scalar1, -SK_Scalar1); 639da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org rightMatrix.postTranslate(0, 2 * height); 640da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(right, rightMatrix); 641da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 642be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org patternBBox.fRight = surfaceBBox.width(); 643da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 644da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 645da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 646da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[1] == SkShader::kClamp_TileMode) { 647da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkIRect subset = SkIRect::MakeXYWH(0, 0, width, 1); 648da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (surfaceBBox.fTop < 0) { 649da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkBitmap top; 650da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkAssertResult(image->extractSubset(&top, subset)); 651da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 652da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix topMatrix; 653663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org topMatrix.setScale(SK_Scalar1, -surfaceBBox.fTop); 654da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org topMatrix.postTranslate(0, surfaceBBox.fTop); 655da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(top, topMatrix); 656da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 657da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[0] == SkShader::kMirror_TileMode) { 658da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org topMatrix.postScale(-1, 1); 659da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org topMatrix.postTranslate(2 * width, 0); 660da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(top, topMatrix); 661da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 662be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org patternBBox.fTop = 0; 663da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 664da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 665da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (surfaceBBox.fBottom > height) { 666da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkBitmap bottom; 667da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org subset.offset(0, height - 1); 668da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkAssertResult(image->extractSubset(&bottom, subset)); 669da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 670da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix bottomMatrix; 671663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org bottomMatrix.setScale(SK_Scalar1, surfaceBBox.fBottom - height); 672da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org bottomMatrix.postTranslate(0, height); 673da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(bottom, bottomMatrix); 674da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 675da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (tileModes[0] == SkShader::kMirror_TileMode) { 676da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org bottomMatrix.postScale(-1, 1); 677da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org bottomMatrix.postTranslate(2 * width, 0); 678da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org canvas.drawBitmapMatrix(bottom, bottomMatrix); 679da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 680be2048a371813259c46fc2260d53ccadc4ea8133vandebo@chromium.org patternBBox.fBottom = surfaceBBox.height(); 681da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 682da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 683da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 684da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRefPtr<SkPDFArray> patternBBoxArray = new SkPDFArray; 685da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org patternBBoxArray->unref(); // SkRefPtr and new both took a reference. 686da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org patternBBoxArray->reserve(4); 687c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com patternBBoxArray->appendScalar(patternBBox.fLeft); 688c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com patternBBoxArray->appendScalar(patternBBox.fTop); 689c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com patternBBoxArray->appendScalar(patternBBox.fRight); 690c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com patternBBoxArray->appendScalar(patternBBox.fBottom); 691da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 692da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // Put the canvas into the pattern stream (fContent). 693da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkRefPtr<SkStream> content = pattern.content(); 694da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org content->unref(); // SkRefPtr and content() both took a reference. 695da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org pattern.getResources(&fResources); 696da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 697421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org setData(content.get()); 698421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertName("Type", "Pattern"); 699421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertInt("PatternType", 1); 700421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertInt("PaintType", 1); 701421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertInt("TilingType", 1); 702421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insert("BBox", patternBBoxArray.get()); 703421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertScalar("XStep", patternBBox.width()); 704421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertScalar("YStep", patternBBox.height()); 7051feb33068b1313d2647c50b90ae8e0a3d510db2ereed@google.com insert("Resources", pattern.getResourceDict()); 706421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); 707da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 708da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fState.get()->fImage.unlockPixels(); 709da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 710da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 711421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, 712421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkPDFArray* domain) { 713421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), 714421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org psCode.size())); 715421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkPDFStream* result = new SkPDFStream(funcData.get()); 716c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com result->insertInt("FunctionType", 4); 717da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org result->insert("Domain", domain); 718f6c3ebdeb135dcdb9af225bd7af77f1fe1f92787reed@google.com result->insert("Range", RangeObject()); 719da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return result; 720da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 721da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 722421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFShader::ShaderCanonicalEntry::ShaderCanonicalEntry(SkPDFObject* pdfShader, 723421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org const State* state) 724421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org : fPDFShader(pdfShader), 725421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org fState(state) { 726421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org} 727421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 728421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgbool SkPDFShader::ShaderCanonicalEntry::operator==( 729421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org const ShaderCanonicalEntry& b) const { 730421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org return fPDFShader == b.fPDFShader || 731421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org (fState != NULL && b.fState != NULL && *fState == *b.fState); 732421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org} 733421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 734da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgbool SkPDFShader::State::operator==(const SkPDFShader::State& b) const { 735da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fType != b.fType || 736da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fCanvasTransform != b.fCanvasTransform || 737da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fShaderTransform != b.fShaderTransform || 738da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fBBox != b.fBBox) { 739da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return false; 740da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 741da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 742da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fType == SkShader::kNone_GradientType) { 743da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fPixelGeneration != b.fPixelGeneration || 744da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fPixelGeneration == 0 || 745da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fImageTileModes[0] != b.fImageTileModes[0] || 746da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fImageTileModes[1] != b.fImageTileModes[1]) { 747da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return false; 748da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 749da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 750da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fInfo.fColorCount != b.fInfo.fColorCount || 751da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org memcmp(fInfo.fColors, b.fInfo.fColors, 752da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org sizeof(SkColor) * fInfo.fColorCount) != 0 || 753da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org memcmp(fInfo.fColorOffsets, b.fInfo.fColorOffsets, 754da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org sizeof(SkScalar) * fInfo.fColorCount) != 0 || 755da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fPoint[0] != b.fInfo.fPoint[0] || 756da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fTileMode != b.fInfo.fTileMode) { 757da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return false; 758da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 759da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 760da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org switch (fType) { 761da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kLinear_GradientType: 762da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fInfo.fPoint[1] != b.fInfo.fPoint[1]) { 763da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return false; 764da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 765da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 766da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kRadial_GradientType: 767da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fInfo.fRadius[0] != b.fInfo.fRadius[0]) { 768da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return false; 769da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 770da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 771da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kRadial2_GradientType: 772da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fInfo.fPoint[1] != b.fInfo.fPoint[1] || 773da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fRadius[0] != b.fInfo.fRadius[0] || 774da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fRadius[1] != b.fInfo.fRadius[1]) { 775da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return false; 776da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 777da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 778da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kSweep_GradientType: 779da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kNone_GradientType: 780da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org case SkShader::kColor_GradientType: 781da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org break; 782da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 783da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 784da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return true; 785da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 786da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 787da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.orgSkPDFShader::State::State(const SkShader& shader, 788da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org const SkMatrix& canvasTransform, const SkIRect& bbox) 789da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org : fCanvasTransform(canvasTransform), 790e1bc274295ec57cb3d3f01aaa8abff3b49c76c73vandebo@chromium.org fBBox(bbox), 791e1bc274295ec57cb3d3f01aaa8abff3b49c76c73vandebo@chromium.org fPixelGeneration(0) { 792da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fColorCount = 0; 793da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fColors = NULL; 794da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fColorOffsets = NULL; 795da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org shader.getLocalMatrix(&fShaderTransform); 796e1bc274295ec57cb3d3f01aaa8abff3b49c76c73vandebo@chromium.org fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; 797da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 798da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fType = shader.asAGradient(&fInfo); 799da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 800da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fType == SkShader::kNone_GradientType) { 801da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkShader::BitmapType bitmapType; 802da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkMatrix matrix; 803da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes, NULL); 804da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (bitmapType != SkShader::kDefault_BitmapType) { 805da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fImage.reset(); 806da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org return; 807da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 808da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkASSERT(matrix.isIdentity()); 809da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fPixelGeneration = fImage.getGenerationID(); 810da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } else { 811da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fColorData.set(sk_malloc_throw( 812da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); 813a5c7234e81748f76cbeede40e619351146e5286actguil@chromium.org fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); 814020798af6780ba29156f4daec87c29ae9e4f4a12vandebo@chromium.org fInfo.fColorOffsets = 815020798af6780ba29156f4daec87c29ae9e4f4a12vandebo@chromium.org reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); 816da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org shader.asAGradient(&fInfo); 817da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 818da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org} 819