SkDrawGradient.cpp revision ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976e
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
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.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawGradient.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkAnimateMaker.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkAnimatorScript.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGradientShader.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUnitMapper.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScalar SkUnitToScalar(U16CPU x) {
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_SCALAR_IS_FLOAT
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return x / 65535.0f;
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return x + (x >> 8);
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comU16CPU SkScalarToUnit(SkScalar x) {
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar pin =  SkScalarPin(x, 0, SK_Scalar1);
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_SCALAR_IS_FLOAT
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (int) (pin * 65535.0f);
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return pin - (pin >= 32768);
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkGradientUnitMapper : public SkUnitMapper {
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGradientUnitMapper(SkAnimateMaker* maker, const char* script) : fMaker(maker), fScript(script) {
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // overrides for SkFlattenable
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return NULL; }
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual uint16_t mapUnit16(uint16_t x) {
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fUnit = SkUnitToScalar(x);
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScriptValue value;
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAnimatorScript engine(*fMaker, NULL, SkType_Float);
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        engine.propertyCallBack(GetUnitValue, &fUnit);
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (engine.evaluate(fScript, &value, SkType_Float))
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x = SkScalarToUnit(value.fOperand.fScalar);
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return x;
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static bool GetUnitValue(const char* token, size_t len, void* unitPtr, SkScriptValue* value) {
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (SK_LITERAL_STR_EQUAL("unit", token, len)) {
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            value->fOperand.fScalar = *(SkScalar*) unitPtr;
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            value->fType = SkType_Float;
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAnimateMaker* fMaker;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* fScript;
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar fUnit;
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if SK_USE_CONDENSED_INFO == 0
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMemberInfo SkGradient::fInfo[] = {
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_INHERITED,
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_ARRAY(offsets, Float),
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER(unitMapper, String)
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDEFINE_GET_MEMBER(SkGradient);
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkGradient::SkGradient() : fUnitMapper(NULL) {
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkGradient::~SkGradient() {
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int index = 0; index < fDrawColors.count(); index++)
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        delete fDrawColors[index];
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    delete fUnitMapper;
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkGradient::add(SkAnimateMaker& , SkDisplayable* child) {
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(child);
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (child->isColor()) {
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawColor* color = (SkDrawColor*) child;
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *fDrawColors.append() = color;
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkGradient::addPrelude() {
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int count = fDrawColors.count();
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fColors.setCount(count);
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int index = 0; index < count; index++)
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fColors[index] = fDrawColors[index]->color;
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DUMP_ENABLED
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkGradient::dumpRest(SkAnimateMaker* maker) {
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpAttrs(maker);
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    //can a gradient have no colors?
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool closedYet = false;
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDisplayList::fIndent += 4;
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (SkDrawColor** ptr = fDrawColors.begin(); ptr < fDrawColors.end(); ptr++) {
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (closedYet == false) {
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf(">\n");
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            closedYet = true;
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawColor* color = *ptr;
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        color->dump(maker);
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDisplayList::fIndent -= 4;
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpChildren(maker, closedYet); //dumps the matrix if it has one
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkGradient::onEndElement(SkAnimateMaker& maker) {
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (offsets.count() != 0) {
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (offsets.count() != fDrawColors.count()) {
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsDontMatchColors);
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (offsets[0] != 0) {
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustStartWithZero);
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (offsets[offsets.count()-1] != SK_Scalar1) {
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustEndWithOne);
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (int i = 1; i < offsets.count(); i++) {
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (offsets[i] <= offsets[i-1]) {
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustIncrease);
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (offsets[i] > SK_Scalar1) {
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustBeNoMoreThanOne);
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (unitMapper.size() > 0)
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fUnitMapper = new SkGradientUnitMapper(&maker, unitMapper.c_str());
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    INHERITED::onEndElement(maker);
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if SK_USE_CONDENSED_INFO == 0
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMemberInfo SkLinearGradient::fInfo[] = {
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_INHERITED,
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_ARRAY(points, Float),
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDEFINE_GET_MEMBER(SkLinearGradient);
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkLinearGradient::SkLinearGradient() {
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkLinearGradient::onEndElement(SkAnimateMaker& maker)
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (points.count() != 4)
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        maker.setErrorCode(SkDisplayXMLParserError::kGradientPointsLengthMustBeFour);
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    INHERITED::onEndElement(maker);
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DUMP_ENABLED
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkLinearGradient::dump(SkAnimateMaker* maker) {
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpBase(maker);
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpRest(maker);
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkShader* SkLinearGradient::getShader() {
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (addPrelude() == 0 || points.count() != 4)
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader* shader = SkGradientShader::CreateLinear((SkPoint*)points.begin(),
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper);
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoTDelete<SkShader> autoDel(shader);
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    addPostlude(shader);
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (void)autoDel.detach();
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return shader;
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if SK_USE_CONDENSED_INFO == 0
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMemberInfo SkRadialGradient::fInfo[] = {
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_INHERITED,
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER(center, Point),
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER(radius, Float)
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDEFINE_GET_MEMBER(SkRadialGradient);
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRadialGradient::SkRadialGradient() : radius(0) {
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    center.set(0, 0);
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DUMP_ENABLED
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRadialGradient::dump(SkAnimateMaker* maker) {
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpBase(maker);
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpRest(maker);
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkShader* SkRadialGradient::getShader() {
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (addPrelude() == 0)
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader* shader = SkGradientShader::CreateRadial(center,
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper);
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoTDelete<SkShader> autoDel(shader);
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    addPostlude(shader);
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (void)autoDel.detach();
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return shader;
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
228