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