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
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if SK_USE_CONDENSED_INFO == 0
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1799547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comconst SkMemberInfo SkDrawGradient::fInfo[] = {
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_INHERITED,
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_ARRAY(offsets, Float),
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER(unitMapper, String)
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2599547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comDEFINE_GET_MEMBER(SkDrawGradient);
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2783f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.orgSkDrawGradient::SkDrawGradient() {
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3099547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comSkDrawGradient::~SkDrawGradient() {
31d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    for (int index = 0; index < fDrawColors.count(); index++)
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        delete fDrawColors[index];
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
351d3c411f5e4d2ad31bc92b3a85957004329ac00dtfarina@chromium.orgbool SkDrawGradient::addChild(SkAnimateMaker& , SkDisplayable* child) {
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(child);
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (child->isColor()) {
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawColor* color = (SkDrawColor*) child;
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *fDrawColors.append() = color;
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4599547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comint SkDrawGradient::addPrelude() {
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int count = fDrawColors.count();
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fColors.setCount(count);
48d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    for (int index = 0; index < count; index++)
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fColors[index] = fDrawColors[index]->color;
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DUMP_ENABLED
5499547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comvoid SkDrawGradient::dumpRest(SkAnimateMaker* maker) {
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpAttrs(maker);
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    //can a gradient have no colors?
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool closedYet = false;
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDisplayList::fIndent += 4;
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (SkDrawColor** ptr = fDrawColors.begin(); ptr < fDrawColors.end(); ptr++) {
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (closedYet == false) {
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf(">\n");
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            closedYet = true;
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawColor* color = *ptr;
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        color->dump(maker);
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
67d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    SkDisplayList::fIndent -= 4;
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpChildren(maker, closedYet); //dumps the matrix if it has one
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7299547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comvoid SkDrawGradient::onEndElement(SkAnimateMaker& maker) {
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (offsets.count() != 0) {
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (offsets.count() != fDrawColors.count()) {
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsDontMatchColors);
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (offsets[0] != 0) {
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustStartWithZero);
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (offsets[offsets.count()-1] != SK_Scalar1) {
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustEndWithOne);
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (int i = 1; i < offsets.count(); i++) {
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (offsets[i] <= offsets[i-1]) {
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustIncrease);
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (offsets[i] > SK_Scalar1) {
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustBeNoMoreThanOne);
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    INHERITED::onEndElement(maker);
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if SK_USE_CONDENSED_INFO == 0
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10299547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comconst SkMemberInfo SkDrawLinearGradient::fInfo[] = {
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_INHERITED,
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_ARRAY(points, Float),
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10999547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comDEFINE_GET_MEMBER(SkDrawLinearGradient);
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
111d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comSkDrawLinearGradient::SkDrawLinearGradient() {
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11499547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comvoid SkDrawLinearGradient::onEndElement(SkAnimateMaker& maker)
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (points.count() != 4)
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        maker.setErrorCode(SkDisplayXMLParserError::kGradientPointsLengthMustBeFour);
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    INHERITED::onEndElement(maker);
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DUMP_ENABLED
12299547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comvoid SkDrawLinearGradient::dump(SkAnimateMaker* maker) {
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpBase(maker);
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpRest(maker);
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12899547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comSkShader* SkDrawLinearGradient::getShader() {
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (addPrelude() == 0 || points.count() != 4)
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader* shader = SkGradientShader::CreateLinear((SkPoint*)points.begin(),
1329c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org        fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode,
13383f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org        0, getMatrix());
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoTDelete<SkShader> autoDel(shader);
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (void)autoDel.detach();
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return shader;
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if SK_USE_CONDENSED_INFO == 0
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14299547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comconst SkMemberInfo SkDrawRadialGradient::fInfo[] = {
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_INHERITED,
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER(center, Point),
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER(radius, Float)
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15099547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comDEFINE_GET_MEMBER(SkDrawRadialGradient);
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
152d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comSkDrawRadialGradient::SkDrawRadialGradient() : radius(0) {
153d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    center.set(0, 0);
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DUMP_ENABLED
15799547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comvoid SkDrawRadialGradient::dump(SkAnimateMaker* maker) {
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpBase(maker);
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpRest(maker);
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16399547767e9cdabcdae6a575f0f6bfde01d809865rileya@google.comSkShader* SkDrawRadialGradient::getShader() {
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (addPrelude() == 0)
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader* shader = SkGradientShader::CreateRadial(center,
1679c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org        radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode,
16883f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org        0, getMatrix());
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoTDelete<SkShader> autoDel(shader);
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (void)autoDel.detach();
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return shader;
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
173