<commit_before>
// Backup related functions are placed here to keep vital sections of
// code contained while maintaining clean code.

#include "wallet/walletdb.h"
#include "wallet/wallet.h"
#include "util.h"

#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>

#include <fstream>
#include <string>

boost::filesystem::path GetBackupPath();

using namespace boost;

boost::filesystem::path GetBackupPath()
{
    filesystem::path defaultDir = GetDataDir() / "walletbackups";
    return GetArg("-backupdir", defaultDir.string());
}

std::string GetBackupFilename(const std::string& basename, const std::string& suffix = "")
{
    time_t biTime;
    struct tm * blTime;
    time (&biTime);
    blTime = localtime(&biTime);
    char boTime[200];
    strftime(boTime, sizeof(boTime), "%Y-%m-%dT%H-%M-%S", blTime);
    std::string sBackupFilename;
    filesystem::path rpath;
    sBackupFilename = basename + "-" + std::string(boTime);
    if (!suffix.empty())
        sBackupFilename = sBackupFilename + "-" + suffix;
    rpath = GetBackupPath() / sBackupFilename;
    return rpath.string();
}

bool BackupConfigFile(const std::string& strDest)
{
    // Check to see if there is a parent_path in strDest to support custom locations by ui - bug fix

    filesystem::path ConfigSource = GetConfigFile();
    filesystem::path ConfigTarget = strDest;
    filesystem::create_directories(ConfigTarget.parent_path());
    try
    {
        #if BOOST_VERSION >= 104000
            filesystem::copy_file(ConfigSource, ConfigTarget, filesystem::copy_option::overwrite_if_exists);
        #else
            filesystem::copy_file(ConfigSource, ConfigTarget);
        #endif
        LogPrintf("BackupConfigFile: Copied gridcoinresearch.conf to %s", ConfigTarget.string());
        return true;
    }
    catch(const filesystem::filesystem_error &e)
    {
        LogPrintf("BackupConfigFile: Error copying gridcoinresearch.conf to %s - %s", ConfigTarget.string(), e.what());
        return false;
    }
    return false;
}

bool BackupWallet(const CWallet& wallet, const std::string& strDest)
{
    if (!wallet.fFileBacked)
        return false;

    LOCK(bitdb.cs_db);
    if (!bitdb.mapFileUseCount.count(wallet.strWalletFile) || bitdb.mapFileUseCount[wallet.strWalletFile] == 0)
    {
        // Flush log data to the dat file
        bitdb.CloseDb(wallet.strWalletFile);
        bitdb.CheckpointLSN(wallet.strWalletFile);
        LogPrintf("Issuing lsn_reset for backup file portability.");
        bitdb.lsn_reset(wallet.strWalletFile);
        bitdb.mapFileUseCount.erase(wallet.strWalletFile);

        // Copy wallet.dat
        filesystem::path WalletSource = GetDataDir() / wallet.strWalletFile;
        filesystem::path WalletTarget = strDest;
        filesystem::create_directories(WalletTarget.parent_path());
        if (filesystem::is_directory(WalletTarget))
            WalletTarget /= wallet.strWalletFile;
        try
        {
#if BOOST_VERSION >= 104000
            filesystem::copy_file(WalletSource, WalletTarget, filesystem::copy_option::overwrite_if_exists);
#else
            filesystem::copy_file(WalletSource, WalletTarget);
#endif
            LogPrintf("BackupWallet: Copied wallet.dat to %s", WalletTarget.string());
            return true;
        }
        catch(const filesystem::filesystem_error &e) {
            LogPrintf("BackupWallet: Error copying wallet.dat to %s - %s", WalletTarget.string(), e.what());
            return false;
        }
    }

    return false;
}

bool BackupPrivateKeys(const CWallet& wallet, std::string& sTarget, std::string& sErrors)
{
    if (wallet.IsLocked() || fWalletUnlockStakingOnly)
    {
        sErrors = "Wallet needs to be fully unlocked to backup private keys.";
        return false;
    }
    filesystem::path PrivateKeysTarget = GetBackupFilename("keys.dat");
    filesystem::create_directories(PrivateKeysTarget.parent_path());
    sTarget = PrivateKeysTarget.string();
    fsbridge::ofstream myBackup;
    myBackup.open(PrivateKeysTarget);
    std::string sError;
    for(const auto& keyPair : wallet.GetAllPrivateKeys(sError))
    {
        if (!sError.empty())
        {
            sErrors = sError;
            return false;
        }
        myBackup << "Address: " << keyPair.first.ToString() << ", Secret: " << keyPair.second.ToString() << std::endl;
    }
    LogPrintf("BackupPrivateKeys: Backup made to %s", PrivateKeysTarget.string());
    myBackup.close();
    return true;
}
<commit_msg>Fix compatibility with Boost 1.74<commit_after>
// Backup related functions are placed here to keep vital sections of
// code contained while maintaining clean code.

#include "wallet/walletdb.h"
#include "wallet/wallet.h"
#include "util.h"

#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>

#include <fstream>
#include <string>

boost::filesystem::path GetBackupPath();

using namespace boost;

boost::filesystem::path GetBackupPath()
{
    filesystem::path defaultDir = GetDataDir() / "walletbackups";
    return GetArg("-backupdir", defaultDir.string());
}

std::string GetBackupFilename(const std::string& basename, const std::string& suffix = "")
{
    time_t biTime;
    struct tm * blTime;
    time (&biTime);
    blTime = localtime(&biTime);
    char boTime[200];
    strftime(boTime, sizeof(boTime), "%Y-%m-%dT%H-%M-%S", blTime);
    std::string sBackupFilename;
    filesystem::path rpath;
    sBackupFilename = basename + "-" + std::string(boTime);
    if (!suffix.empty())
        sBackupFilename = sBackupFilename + "-" + suffix;
    rpath = GetBackupPath() / sBackupFilename;
    return rpath.string();
}

bool BackupConfigFile(const std::string& strDest)
{
    // Check to see if there is a parent_path in strDest to support custom locations by ui - bug fix

    filesystem::path ConfigSource = GetConfigFile();
    filesystem::path ConfigTarget = strDest;
    filesystem::create_directories(ConfigTarget.parent_path());
    try
    {
        #if BOOST_VERSION >= 107400
            filesystem::copy_file(ConfigSource, ConfigTarget, filesystem::copy_options::overwrite_existing);
        #elif BOOST_VERSION >= 104000
            filesystem::copy_file(ConfigSource, ConfigTarget, filesystem::copy_option::overwrite_if_exists);
        #else
            filesystem::copy_file(ConfigSource, ConfigTarget);
        #endif
        LogPrintf("BackupConfigFile: Copied gridcoinresearch.conf to %s", ConfigTarget.string());
        return true;
    }
    catch(const filesystem::filesystem_error &e)
    {
        LogPrintf("BackupConfigFile: Error copying gridcoinresearch.conf to %s - %s", ConfigTarget.string(), e.what());
        return false;
    }
    return false;
}

bool BackupWallet(const CWallet& wallet, const std::string& strDest)
{
    if (!wallet.fFileBacked)
        return false;

    LOCK(bitdb.cs_db);
    if (!bitdb.mapFileUseCount.count(wallet.strWalletFile) || bitdb.mapFileUseCount[wallet.strWalletFile] == 0)
    {
        // Flush log data to the dat file
        bitdb.CloseDb(wallet.strWalletFile);
        bitdb.CheckpointLSN(wallet.strWalletFile);
        LogPrintf("Issuing lsn_reset for backup file portability.");
        bitdb.lsn_reset(wallet.strWalletFile);
        bitdb.mapFileUseCount.erase(wallet.strWalletFile);

        // Copy wallet.dat
        filesystem::path WalletSource = GetDataDir() / wallet.strWalletFile;
        filesystem::path WalletTarget = strDest;
        filesystem::create_directories(WalletTarget.parent_path());
        if (filesystem::is_directory(WalletTarget))
            WalletTarget /= wallet.strWalletFile;
        try
        {
#if BOOST_VERSION >= 107400
            filesystem::copy_file(WalletSource, WalletTarget, filesystem::copy_options::overwrite_existing);
#elif BOOST_VERSION >= 104000
            filesystem::copy_file(WalletSource, WalletTarget, filesystem::copy_option::overwrite_if_exists);
#else
            filesystem::copy_file(WalletSource, WalletTarget);
#endif
            LogPrintf("BackupWallet: Copied wallet.dat to %s", WalletTarget.string());
            return true;
        }
        catch(const filesystem::filesystem_error &e) {
            LogPrintf("BackupWallet: Error copying wallet.dat to %s - %s", WalletTarget.string(), e.what());
            return false;
        }
    }

    return false;
}

bool BackupPrivateKeys(const CWallet& wallet, std::string& sTarget, std::string& sErrors)
{
    if (wallet.IsLocked() || fWalletUnlockStakingOnly)
    {
        sErrors = "Wallet needs to be fully unlocked to backup private keys.";
        return false;
    }
    filesystem::path PrivateKeysTarget = GetBackupFilename("keys.dat");
    filesystem::create_directories(PrivateKeysTarget.parent_path());
    sTarget = PrivateKeysTarget.string();
    fsbridge::ofstream myBackup;
    myBackup.open(PrivateKeysTarget);
    std::string sError;
    for(const auto& keyPair : wallet.GetAllPrivateKeys(sError))
    {
        if (!sError.empty())
        {
            sErrors = sError;
            return false;
        }
        myBackup << "Address: " << keyPair.first.ToString() << ", Secret: " << keyPair.second.ToString() << std::endl;
    }
    LogPrintf("BackupPrivateKeys: Backup made to %s", PrivateKeysTarget.string());
    myBackup.close();
    return true;
}
<|endoftext|>


<commit_before>/**
 * @file base64.cpp
 * @brief modified base64 encoding/decoding
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#include "mega/base64.h"

namespace mega {
// modified base64 conversion (no trailing '=' and '-_' instead of '+/')
unsigned char Base64::to64(byte c)
{
    c &= 63;

    if (c < 26)
    {
        return c + 'A';
    }

    if (c < 52)
    {
        return c - 26 + 'a';
    }

    if (c < 62)
    {
        return c - 52 + '0';
    }

    if (c == 62)
    {
        return '-';
    }

    return '_';
}

unsigned char Base64::from64(byte c)
{
    if ((c >= 'A') && (c <= 'Z'))
    {
        return c - 'A';
    }

    if ((c >= 'a') && (c <= 'z'))
    {
        return c - 'a' + 26;
    }

    if ((c >= '0') && (c <= '9'))
    {
        return c - '0' + 52;
    }

    if (c == '-')
    {
        return 62;
    }

    if (c == '_')
    {
        return 63;
    }

    return 255;
}

int Base64::atob(const char* a, byte* b, int blen)
{
    byte c[4];
    int i;
    int p = 0;

    c[3] = 0;

    for (;;)
    {
        for (i = 0; i < 4; i++)
        {
            if ((c[i] = from64(*a++)) == 255)
            {
                break;
            }
        }

        if ((p >= blen) || !i)
        {
            return p;
        }

        b[p++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);

        if ((p >= blen) || (i < 3))
        {
            return p;
        }

        b[p++] = (c[1] << 4) | ((c[2] & 0x3c) >> 2);

        if ((p >= blen) || (i < 4))
        {
            return p;
        }

        b[p++] = (c[2] << 6) | c[3];
    }

    return p;
}

int Base64::btoa(const byte* b, int blen, char* a)
{
    int p = 0;

    for (;;)
    {
        if (blen <= 0)
        {
            break;
        }

        a[p++] = to64(*b >> 2);
        a[p++] = to64((*b << 4) | (((blen > 1) ? b[1] : 0) >> 4));

        if (blen < 2)
        {
            break;
        }

        a[p++] = to64(b[1] << 2 | (((blen > 2) ? b[2] : 0) >> 6));

        if (blen < 3)
        {
            break;
        }

        a[p++] = to64(b[2]);

        blen -= 3;
        b += 3;
    }

    a[p] = 0;

    return p;
}

byte Base32::to32(byte c)
{
    c &= 31;

    if (c < 26)
    {
        return c + 'a';
    }

    return c - 26 + '2';
}

byte Base32::from32(byte c)
{
    if ((c >= 'a') && (c <= 'z'))
    {
        return c - 'a';
    }

    if ((c >= '2') && (c <= '9'))
    {
        return c - '2' + 26;
    }

    return 255;
}

int Base32::btoa(const byte *b, int blen, char *a)
{
    int p = 0;

    for (;;)
    {
        if (blen <= 0)
        {
            break;
        }

        a[p++] = to32( *b >> 3);
        a[p++] = to32((*b << 2) | (((blen > 1) ? b[1] : 0) >> 6));

        if (blen < 2)
        {
            break;
        }

        a[p++] = to32(b[1] >> 1);
        a[p++] = to32(b[1] << 4 | (((blen > 2) ? b[2] : 0) >> 4));

        if (blen < 3)
        {
            break;
        }

        a[p++] = to32((b[2] << 1) | (((blen > 3) ? b[3] : 0) >> 7));

        if (blen < 4)
        {
            break;
        }

        a[p++] = to32(b[3] >> 2);
        a[p++] = to32(b[3] << 3 | (((blen > 4) ? b[4] : 0) >> 5));

        if (blen < 5)
        {
            break;
        }

        a[p++] = to32(b[4]);

        blen -= 5;
        b += 5;
    }

    a[p] = 0;

    return p;
}

int Base32::atob(const char *a, byte *b, int blen)
{
    byte c[8];
    int i;
    int p = 0;

    c[7] = 0;

    for (;;)
    {
        for (i = 0; i < 8; i++)
        {
            if ((c[i] = from32(*a++)) == 255)
            {
                break;
            }
        }

        if ((p >= blen) || !i)
        {
            return p;
        }

        b[p++] = (c[0] << 3) | ((c[1] & 0x1C) >> 2);

        if ((p >= blen) || (i < 4))
        {
            return p;
        }

        b[p++] = (c[1] << 6) | (c[2] << 1) | ((c[3] & 0x10) >> 4);

        if ((p >= blen) || (i < 5))
        {
            return p;
        }

        b[p++] = (c[3] << 4) | ((c[4] & 0x1E) >> 1);

        if ((p >= blen) || (i < 7))
        {
            return p;
        }

        b[p++] = (c[4] << 7) | (c[5] << 2) | ((c[6] & 0x18) >> 3);

        if ((p >= blen) || (i < 8))
        {
            return p;
        }

        b[p++] = (c[6] << 5) | c[7];
    }

    return p;
}

bool URLCodec::issafe(char c)
{
    if (ishexdigit(c)
            || (c >= 'a' && c <= 'z')
            || (c >= 'A' && c <= 'Z')
            || c == '-' || c == '.'
            || c == '_' || c == '~')
    {
        return true;
    }
    return false;
}

char URLCodec::hexval(char c)
{
    return c > '9' ? (c > 'a' ? c - 'a' + 10 : c - 'A' + 10) : c - '0';
}

bool URLCodec::ishexdigit(char c)
{
    return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}

void URLCodec::escape(string *plain, string *escaped)
{
    if (!escaped || !plain)
    {
        return;
    }

    escaped->clear();
    int len = plain->size();
    int escapedIndex = 0;
    for (int i = 0; i < len; i++)
    {
        char c = plain->at(i);
        if (issafe(c))
        {
            escaped->push_back(c);
            escapedIndex++;
        }
        else
        {
            escaped->resize(escapedIndex + 3);
            sprintf((char *)escaped->c_str() + escapedIndex, "%%%02x", c);
            escapedIndex += 3;
        }
    }
}

void URLCodec::unescape(string *escaped, string *plain)
{
    if (!escaped || !plain)
    {
        return;
    }

    plain->clear();
    plain->reserve(escaped->size());
    int len = escaped->size();
    for (int i = 0; i < len; i++)
    {
        if (escaped->at(i) == '%' && ishexdigit(escaped->at(i + 1)) && ishexdigit(escaped->at(i + 2)))
        {
            char c1 = hexval(escaped->at(i + 1));
            char c2 = hexval(escaped->at(i + 2));
            char c = 0xFF & ((c1 << 4) | c2);

            plain->push_back(c);
            i += 2;
        }
        else
        {
            plain->push_back(escaped->at(i));
        }
    }
}

} // namespace
<commit_msg>Fixed a bug encoding non-ASCII characters<commit_after>/**
 * @file base64.cpp
 * @brief modified base64 encoding/decoding
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#include "mega/base64.h"

namespace mega {
// modified base64 conversion (no trailing '=' and '-_' instead of '+/')
unsigned char Base64::to64(byte c)
{
    c &= 63;

    if (c < 26)
    {
        return c + 'A';
    }

    if (c < 52)
    {
        return c - 26 + 'a';
    }

    if (c < 62)
    {
        return c - 52 + '0';
    }

    if (c == 62)
    {
        return '-';
    }

    return '_';
}

unsigned char Base64::from64(byte c)
{
    if ((c >= 'A') && (c <= 'Z'))
    {
        return c - 'A';
    }

    if ((c >= 'a') && (c <= 'z'))
    {
        return c - 'a' + 26;
    }

    if ((c >= '0') && (c <= '9'))
    {
        return c - '0' + 52;
    }

    if (c == '-')
    {
        return 62;
    }

    if (c == '_')
    {
        return 63;
    }

    return 255;
}

int Base64::atob(const char* a, byte* b, int blen)
{
    byte c[4];
    int i;
    int p = 0;

    c[3] = 0;

    for (;;)
    {
        for (i = 0; i < 4; i++)
        {
            if ((c[i] = from64(*a++)) == 255)
            {
                break;
            }
        }

        if ((p >= blen) || !i)
        {
            return p;
        }

        b[p++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);

        if ((p >= blen) || (i < 3))
        {
            return p;
        }

        b[p++] = (c[1] << 4) | ((c[2] & 0x3c) >> 2);

        if ((p >= blen) || (i < 4))
        {
            return p;
        }

        b[p++] = (c[2] << 6) | c[3];
    }

    return p;
}

int Base64::btoa(const byte* b, int blen, char* a)
{
    int p = 0;

    for (;;)
    {
        if (blen <= 0)
        {
            break;
        }

        a[p++] = to64(*b >> 2);
        a[p++] = to64((*b << 4) | (((blen > 1) ? b[1] : 0) >> 4));

        if (blen < 2)
        {
            break;
        }

        a[p++] = to64(b[1] << 2 | (((blen > 2) ? b[2] : 0) >> 6));

        if (blen < 3)
        {
            break;
        }

        a[p++] = to64(b[2]);

        blen -= 3;
        b += 3;
    }

    a[p] = 0;

    return p;
}

byte Base32::to32(byte c)
{
    c &= 31;

    if (c < 26)
    {
        return c + 'a';
    }

    return c - 26 + '2';
}

byte Base32::from32(byte c)
{
    if ((c >= 'a') && (c <= 'z'))
    {
        return c - 'a';
    }

    if ((c >= '2') && (c <= '9'))
    {
        return c - '2' + 26;
    }

    return 255;
}

int Base32::btoa(const byte *b, int blen, char *a)
{
    int p = 0;

    for (;;)
    {
        if (blen <= 0)
        {
            break;
        }

        a[p++] = to32( *b >> 3);
        a[p++] = to32((*b << 2) | (((blen > 1) ? b[1] : 0) >> 6));

        if (blen < 2)
        {
            break;
        }

        a[p++] = to32(b[1] >> 1);
        a[p++] = to32(b[1] << 4 | (((blen > 2) ? b[2] : 0) >> 4));

        if (blen < 3)
        {
            break;
        }

        a[p++] = to32((b[2] << 1) | (((blen > 3) ? b[3] : 0) >> 7));

        if (blen < 4)
        {
            break;
        }

        a[p++] = to32(b[3] >> 2);
        a[p++] = to32(b[3] << 3 | (((blen > 4) ? b[4] : 0) >> 5));

        if (blen < 5)
        {
            break;
        }

        a[p++] = to32(b[4]);

        blen -= 5;
        b += 5;
    }

    a[p] = 0;

    return p;
}

int Base32::atob(const char *a, byte *b, int blen)
{
    byte c[8];
    int i;
    int p = 0;

    c[7] = 0;

    for (;;)
    {
        for (i = 0; i < 8; i++)
        {
            if ((c[i] = from32(*a++)) == 255)
            {
                break;
            }
        }

        if ((p >= blen) || !i)
        {
            return p;
        }

        b[p++] = (c[0] << 3) | ((c[1] & 0x1C) >> 2);

        if ((p >= blen) || (i < 4))
        {
            return p;
        }

        b[p++] = (c[1] << 6) | (c[2] << 1) | ((c[3] & 0x10) >> 4);

        if ((p >= blen) || (i < 5))
        {
            return p;
        }

        b[p++] = (c[3] << 4) | ((c[4] & 0x1E) >> 1);

        if ((p >= blen) || (i < 7))
        {
            return p;
        }

        b[p++] = (c[4] << 7) | (c[5] << 2) | ((c[6] & 0x18) >> 3);

        if ((p >= blen) || (i < 8))
        {
            return p;
        }

        b[p++] = (c[6] << 5) | c[7];
    }

    return p;
}

bool URLCodec::issafe(char c)
{
    if (ishexdigit(c)
            || (c >= 'a' && c <= 'z')
            || (c >= 'A' && c <= 'Z')
            || c == '-' || c == '.'
            || c == '_' || c == '~')
    {
        return true;
    }
    return false;
}

char URLCodec::hexval(char c)
{
    return c > '9' ? (c > 'a' ? c - 'a' + 10 : c - 'A' + 10) : c - '0';
}

bool URLCodec::ishexdigit(char c)
{
    return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}

void URLCodec::escape(string *plain, string *escaped)
{
    if (!escaped || !plain)
    {
        return;
    }

    escaped->clear();
    int len = plain->size();
    int escapedIndex = 0;
    for (int i = 0; i < len; i++)
    {
        unsigned char c = (unsigned char)plain->at(i);
        if (issafe(c))
        {
            escaped->push_back(c);
            escapedIndex++;
        }
        else
        {
            escaped->resize(escapedIndex + 3);
            sprintf((char *)escaped->c_str() + escapedIndex, "%%%02x", c);
            escapedIndex += 3;
        }
    }
}

void URLCodec::unescape(string *escaped, string *plain)
{
    if (!escaped || !plain)
    {
        return;
    }

    plain->clear();
    plain->reserve(escaped->size());
    int len = escaped->size();
    for (int i = 0; i < len; i++)
    {
        if (escaped->at(i) == '%' && ishexdigit(escaped->at(i + 1)) && ishexdigit(escaped->at(i + 2)))
        {
            char c1 = hexval(escaped->at(i + 1));
            char c2 = hexval(escaped->at(i + 2));
            char c = 0xFF & ((c1 << 4) | c2);

            plain->push_back(c);
            i += 2;
        }
        else
        {
            plain->push_back(escaped->at(i));
        }
    }
}

} // namespace
<|endoftext|>


<commit_before>/*
 * Copyright 2013 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkXfermodeImageFilter.h"
#include "SkArithmeticImageFilter.h"
#include "SkCanvas.h"
#include "SkColorData.h"
#include "SkColorSpaceXformer.h"
#include "SkImageFilterPriv.h"
#include "SkReadBuffer.h"
#include "SkSpecialImage.h"
#include "SkSpecialSurface.h"
#include "SkWriteBuffer.h"
#if SK_SUPPORT_GPU
#include "GrClip.h"
#include "GrColorSpaceXform.h"
#include "GrContext.h"
#include "GrRenderTargetContext.h"
#include "GrTextureProxy.h"

#include "effects/GrConstColorProcessor.h"
#include "effects/GrTextureDomain.h"
#include "effects/GrSimpleTextureEffect.h"
#include "SkGr.h"
#endif
#include "SkClipOpPriv.h"

class SkXfermodeImageFilter_Base : public SkImageFilter {
public:
    SkXfermodeImageFilter_Base(SkBlendMode mode, sk_sp<SkImageFilter> inputs[2],
                               const CropRect* cropRect);

protected:
    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
                                        SkIPoint* offset) const override;
    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;

    SkIRect onFilterBounds(const SkIRect&, const SkMatrix& ctm,
                           MapDirection, const SkIRect* inputRect) const override;

#if SK_SUPPORT_GPU
    sk_sp<SkSpecialImage> filterImageGPU(SkSpecialImage* source,
                                         sk_sp<SkSpecialImage> background,
                                         const SkIPoint& backgroundOffset,
                                         sk_sp<SkSpecialImage> foreground,
                                         const SkIPoint& foregroundOffset,
                                         const SkIRect& bounds,
                                         const OutputProperties& outputProperties) const;
#endif

    void flatten(SkWriteBuffer&) const override;

    void drawForeground(SkCanvas* canvas, SkSpecialImage*, const SkIRect&) const;
#if SK_SUPPORT_GPU
    std::unique_ptr<GrFragmentProcessor> makeFGFrag(
            std::unique_ptr<GrFragmentProcessor> bgFP) const;
#endif

private:
    SK_FLATTENABLE_HOOKS(SkXfermodeImageFilter_Base)

    static sk_sp<SkFlattenable> LegacyArithmeticCreateProc(SkReadBuffer& buffer);

    SkBlendMode fMode;

    friend class SkXfermodeImageFilter;

    typedef SkImageFilter INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(SkBlendMode mode,
                                                 sk_sp<SkImageFilter> background,
                                                 sk_sp<SkImageFilter> foreground,
                                                 const SkImageFilter::CropRect* cropRect) {
    sk_sp<SkImageFilter> inputs[2] = { std::move(background), std::move(foreground) };
    return sk_sp<SkImageFilter>(new SkXfermodeImageFilter_Base(mode, inputs, cropRect));
}

SkXfermodeImageFilter_Base::SkXfermodeImageFilter_Base(SkBlendMode mode,
                                                       sk_sp<SkImageFilter> inputs[2],
                                                       const CropRect* cropRect)
    : INHERITED(inputs, 2, cropRect)
    , fMode(mode)
{}

static unsigned unflatten_blendmode(SkReadBuffer& buffer) {
    unsigned mode = buffer.read32();
    (void)buffer.validate(mode <= (unsigned)SkBlendMode::kLastMode);
    return mode;
}

sk_sp<SkFlattenable> SkXfermodeImageFilter_Base::CreateProc(SkReadBuffer& buffer) {
    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
    unsigned mode = unflatten_blendmode(buffer);
    if (!buffer.isValid()) {
        return nullptr;
    }
    return SkXfermodeImageFilter::Make((SkBlendMode)mode, common.getInput(0),
                                       common.getInput(1), &common.cropRect());
}

void SkXfermodeImageFilter_Base::flatten(SkWriteBuffer& buffer) const {
    this->INHERITED::flatten(buffer);
    buffer.write32((unsigned)fMode);
}

sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::onFilterImage(SkSpecialImage* source,
                                                                const Context& ctx,
                                                                SkIPoint* offset) const {
    SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
    sk_sp<SkSpecialImage> background(this->filterInput(0, source, ctx, &backgroundOffset));

    SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
    sk_sp<SkSpecialImage> foreground(this->filterInput(1, source, ctx, &foregroundOffset));

    SkIRect foregroundBounds = SkIRect::EmptyIRect();
    if (foreground) {
        foregroundBounds = SkIRect::MakeXYWH(foregroundOffset.x(), foregroundOffset.y(),
                                             foreground->width(), foreground->height());
    }

    SkIRect srcBounds = SkIRect::EmptyIRect();
    if (background) {
        srcBounds = SkIRect::MakeXYWH(backgroundOffset.x(), backgroundOffset.y(),
                                      background->width(), background->height());
    }

    srcBounds.join(foregroundBounds);
    if (srcBounds.isEmpty()) {
        return nullptr;
    }

    SkIRect bounds;
    if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
        return nullptr;
    }

    offset->fX = bounds.left();
    offset->fY = bounds.top();

#if SK_SUPPORT_GPU
    if (source->isTextureBacked()) {
        return this->filterImageGPU(source,
                                    background, backgroundOffset,
                                    foreground, foregroundOffset,
                                    bounds, ctx.outputProperties());
    }
#endif

    sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size()));
    if (!surf) {
        return nullptr;
    }

    SkCanvas* canvas = surf->getCanvas();
    SkASSERT(canvas);

    canvas->clear(0x0); // can't count on background to fully clear the background
    canvas->translate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));

    if (background) {
        SkPaint paint;
        paint.setBlendMode(SkBlendMode::kSrc);
        background->draw(canvas,
                         SkIntToScalar(backgroundOffset.fX), SkIntToScalar(backgroundOffset.fY),
                         &paint);
    }

    this->drawForeground(canvas, foreground.get(), foregroundBounds);

    return surf->makeImageSnapshot();
}

SkIRect SkXfermodeImageFilter_Base::onFilterBounds(const SkIRect& src,
                                                   const SkMatrix& ctm,
                                                   MapDirection dir,
                                                   const SkIRect* inputRect) const {
    if (kReverse_MapDirection == dir) {
        return SkImageFilter::onFilterBounds(src, ctm, dir, inputRect);
    }

    SkASSERT(!inputRect);
    SkASSERT(2 == this->countInputs());
    auto getBackground = [&]() {
        return this->getInput(0) ? this->getInput(0)->filterBounds(src, ctm, dir, inputRect) : src;
    };
    auto getForeground = [&]() {
        return this->getInput(1) ? this->getInput(1)->filterBounds(src, ctm, dir, inputRect) : src;
    };
    switch (fMode) {
        case SkBlendMode::kClear:
            return SkIRect::MakeEmpty();

        case SkBlendMode::kSrc:
        case SkBlendMode::kDstATop:
            return getForeground();

        case SkBlendMode::kDst:
        case SkBlendMode::kSrcATop:
            return getBackground();

        case SkBlendMode::kSrcIn:
        case SkBlendMode::kDstIn: {
            auto result = getBackground();
            if (!result.intersect(getForeground())) {
                return SkIRect::MakeEmpty();
            }
            return result;
        }

        default: {
            auto result = getBackground();
            result.join(getForeground());
            return result;
        }
    }
}

sk_sp<SkImageFilter> SkXfermodeImageFilter_Base::onMakeColorSpace(SkColorSpaceXformer* xformer)
const {
    SkASSERT(2 == this->countInputs());
    auto background = xformer->apply(this->getInput(0));
    auto foreground = xformer->apply(this->getInput(1));
    if (background.get() != this->getInput(0) || foreground.get() != this->getInput(1)) {
        return SkXfermodeImageFilter::Make(fMode, std::move(background), std::move(foreground),
                                           this->getCropRectIfSet());
    }
    return this->refMe();
}

void SkXfermodeImageFilter_Base::drawForeground(SkCanvas* canvas, SkSpecialImage* img,
                                                const SkIRect& fgBounds) const {
    SkPaint paint;
    paint.setBlendMode(fMode);
    if (img) {
        img->draw(canvas, SkIntToScalar(fgBounds.fLeft), SkIntToScalar(fgBounds.fTop), &paint);
    }

    SkAutoCanvasRestore acr(canvas, true);
    canvas->clipRect(SkRect::Make(fgBounds), kDifference_SkClipOp);
    paint.setColor(0);
    canvas->drawPaint(paint);
}

#if SK_SUPPORT_GPU

#include "effects/GrXfermodeFragmentProcessor.h"

sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU(
                                                   SkSpecialImage* source,
                                                   sk_sp<SkSpecialImage> background,
                                                   const SkIPoint& backgroundOffset,
                                                   sk_sp<SkSpecialImage> foreground,
                                                   const SkIPoint& foregroundOffset,
                                                   const SkIRect& bounds,
                                                   const OutputProperties& outputProperties) const {
    SkASSERT(source->isTextureBacked());

    GrContext* context = source->getContext();

    sk_sp<GrTextureProxy> backgroundProxy, foregroundProxy;

    if (background) {
        backgroundProxy = background->asTextureProxyRef(context);
    }

    if (foreground) {
        foregroundProxy = foreground->asTextureProxyRef(context);
    }

    GrPaint paint;
    std::unique_ptr<GrFragmentProcessor> bgFP;

    if (backgroundProxy) {
        SkMatrix bgMatrix = SkMatrix::MakeTrans(-SkIntToScalar(backgroundOffset.fX),
                                                -SkIntToScalar(backgroundOffset.fY));
        bgFP = GrTextureDomainEffect::Make(std::move(backgroundProxy), bgMatrix,
                                           GrTextureDomain::MakeTexelDomain(background->subset()),
                                           GrTextureDomain::kDecal_Mode,
                                           GrSamplerState::Filter::kNearest);
        bgFP = GrColorSpaceXformEffect::Make(std::move(bgFP), background->getColorSpace(),
                                             background->alphaType(),
                                             outputProperties.colorSpace());
    } else {
        bgFP = GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
                                           GrConstColorProcessor::InputMode::kIgnore);
    }

    if (foregroundProxy) {
        SkMatrix fgMatrix = SkMatrix::MakeTrans(-SkIntToScalar(foregroundOffset.fX),
                                                -SkIntToScalar(foregroundOffset.fY));
        auto foregroundFP = GrTextureDomainEffect::Make(
                std::move(foregroundProxy), fgMatrix,
                GrTextureDomain::MakeTexelDomain(foreground->subset()),
                GrTextureDomain::kDecal_Mode, GrSamplerState::Filter::kNearest);
        foregroundFP = GrColorSpaceXformEffect::Make(std::move(foregroundFP),
                                                     foreground->getColorSpace(),
                                                     foreground->alphaType(),
                                                     outputProperties.colorSpace());
        paint.addColorFragmentProcessor(std::move(foregroundFP));

        std::unique_ptr<GrFragmentProcessor> xferFP = this->makeFGFrag(std::move(bgFP));

        // A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed
        if (xferFP) {
            paint.addColorFragmentProcessor(std::move(xferFP));
        }
    } else {
        paint.addColorFragmentProcessor(std::move(bgFP));
    }

    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);

    sk_sp<GrRenderTargetContext> renderTargetContext(
        context->contextPriv().makeDeferredRenderTargetContext(
                                    SkBackingFit::kApprox, bounds.width(), bounds.height(),
                                    SkColorType2GrPixelConfig(outputProperties.colorType()),
                                    sk_ref_sp(outputProperties.colorSpace())));
    if (!renderTargetContext) {
        return nullptr;
    }

    SkMatrix matrix;
    matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix,
                                  SkRect::Make(bounds));

    return SkSpecialImage::MakeDeferredFromGpu(
            context,
            SkIRect::MakeWH(bounds.width(), bounds.height()),
            kNeedNewImageUniqueID_SpecialImage,
            renderTargetContext->asTextureProxyRef(),
            renderTargetContext->colorSpaceInfo().refColorSpace());
}

std::unique_ptr<GrFragmentProcessor> SkXfermodeImageFilter_Base::makeFGFrag(
        std::unique_ptr<GrFragmentProcessor> bgFP) const {
    return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(bgFP), fMode);
}

#endif
///////////////////////////////////////////////////////////////////////////////////////////////////

sk_sp<SkFlattenable> SkXfermodeImageFilter_Base::LegacyArithmeticCreateProc(SkReadBuffer& buffer) {
    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
    // skip the unused mode (srcover) field
    SkDEBUGCODE(unsigned mode =) unflatten_blendmode(buffer);
    if (!buffer.isValid()) {
        return nullptr;
    }
    SkASSERT(SkBlendMode::kSrcOver == (SkBlendMode)mode);
    float k[4];
    for (int i = 0; i < 4; ++i) {
        k[i] = buffer.readScalar();
    }
    const bool enforcePMColor = buffer.readBool();
    if (!buffer.isValid()) {
        return nullptr;
    }
    return SkArithmeticImageFilter::Make(k[0], k[1], k[2], k[3], enforcePMColor, common.getInput(0),
                                         common.getInput(1), &common.cropRect());
}

///////////////////////////////////////////////////////////////////////////////////////////////////

void SkXfermodeImageFilter::InitializeFlattenables() {
    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkXfermodeImageFilter_Base)

    // TODO(mtklein): remove these old factory registrations?

    // Register the legacy serialized name "SkXfermodeImageFilter" too.
    SkFlattenable::Register("SkXfermodeImageFilter",
                            SkXfermodeImageFilter_Base::CreateProc);
    // "SkArithmeticImageFilter" used to be implemented as an xfermode image filter.
    SkFlattenable::Register("SkArithmeticImageFilter",
                            SkXfermodeImageFilter_Base::LegacyArithmeticCreateProc);
}
<commit_msg>remove old type deserialization aliases<commit_after>/*
 * Copyright 2013 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkXfermodeImageFilter.h"
#include "SkArithmeticImageFilter.h"
#include "SkCanvas.h"
#include "SkColorData.h"
#include "SkColorSpaceXformer.h"
#include "SkImageFilterPriv.h"
#include "SkReadBuffer.h"
#include "SkSpecialImage.h"
#include "SkSpecialSurface.h"
#include "SkWriteBuffer.h"
#if SK_SUPPORT_GPU
#include "GrClip.h"
#include "GrColorSpaceXform.h"
#include "GrContext.h"
#include "GrRenderTargetContext.h"
#include "GrTextureProxy.h"

#include "effects/GrConstColorProcessor.h"
#include "effects/GrTextureDomain.h"
#include "effects/GrSimpleTextureEffect.h"
#include "SkGr.h"
#endif
#include "SkClipOpPriv.h"

class SkXfermodeImageFilter_Base : public SkImageFilter {
public:
    SkXfermodeImageFilter_Base(SkBlendMode mode, sk_sp<SkImageFilter> inputs[2],
                               const CropRect* cropRect);

protected:
    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
                                        SkIPoint* offset) const override;
    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;

    SkIRect onFilterBounds(const SkIRect&, const SkMatrix& ctm,
                           MapDirection, const SkIRect* inputRect) const override;

#if SK_SUPPORT_GPU
    sk_sp<SkSpecialImage> filterImageGPU(SkSpecialImage* source,
                                         sk_sp<SkSpecialImage> background,
                                         const SkIPoint& backgroundOffset,
                                         sk_sp<SkSpecialImage> foreground,
                                         const SkIPoint& foregroundOffset,
                                         const SkIRect& bounds,
                                         const OutputProperties& outputProperties) const;
#endif

    void flatten(SkWriteBuffer&) const override;

    void drawForeground(SkCanvas* canvas, SkSpecialImage*, const SkIRect&) const;
#if SK_SUPPORT_GPU
    std::unique_ptr<GrFragmentProcessor> makeFGFrag(
            std::unique_ptr<GrFragmentProcessor> bgFP) const;
#endif

private:
    SK_FLATTENABLE_HOOKS(SkXfermodeImageFilter_Base)

    SkBlendMode fMode;

    friend class SkXfermodeImageFilter;

    typedef SkImageFilter INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(SkBlendMode mode,
                                                 sk_sp<SkImageFilter> background,
                                                 sk_sp<SkImageFilter> foreground,
                                                 const SkImageFilter::CropRect* cropRect) {
    sk_sp<SkImageFilter> inputs[2] = { std::move(background), std::move(foreground) };
    return sk_sp<SkImageFilter>(new SkXfermodeImageFilter_Base(mode, inputs, cropRect));
}

SkXfermodeImageFilter_Base::SkXfermodeImageFilter_Base(SkBlendMode mode,
                                                       sk_sp<SkImageFilter> inputs[2],
                                                       const CropRect* cropRect)
    : INHERITED(inputs, 2, cropRect)
    , fMode(mode)
{}

static unsigned unflatten_blendmode(SkReadBuffer& buffer) {
    unsigned mode = buffer.read32();
    (void)buffer.validate(mode <= (unsigned)SkBlendMode::kLastMode);
    return mode;
}

sk_sp<SkFlattenable> SkXfermodeImageFilter_Base::CreateProc(SkReadBuffer& buffer) {
    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
    unsigned mode = unflatten_blendmode(buffer);
    if (!buffer.isValid()) {
        return nullptr;
    }
    return SkXfermodeImageFilter::Make((SkBlendMode)mode, common.getInput(0),
                                       common.getInput(1), &common.cropRect());
}

void SkXfermodeImageFilter_Base::flatten(SkWriteBuffer& buffer) const {
    this->INHERITED::flatten(buffer);
    buffer.write32((unsigned)fMode);
}

sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::onFilterImage(SkSpecialImage* source,
                                                                const Context& ctx,
                                                                SkIPoint* offset) const {
    SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
    sk_sp<SkSpecialImage> background(this->filterInput(0, source, ctx, &backgroundOffset));

    SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
    sk_sp<SkSpecialImage> foreground(this->filterInput(1, source, ctx, &foregroundOffset));

    SkIRect foregroundBounds = SkIRect::EmptyIRect();
    if (foreground) {
        foregroundBounds = SkIRect::MakeXYWH(foregroundOffset.x(), foregroundOffset.y(),
                                             foreground->width(), foreground->height());
    }

    SkIRect srcBounds = SkIRect::EmptyIRect();
    if (background) {
        srcBounds = SkIRect::MakeXYWH(backgroundOffset.x(), backgroundOffset.y(),
                                      background->width(), background->height());
    }

    srcBounds.join(foregroundBounds);
    if (srcBounds.isEmpty()) {
        return nullptr;
    }

    SkIRect bounds;
    if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
        return nullptr;
    }

    offset->fX = bounds.left();
    offset->fY = bounds.top();

#if SK_SUPPORT_GPU
    if (source->isTextureBacked()) {
        return this->filterImageGPU(source,
                                    background, backgroundOffset,
                                    foreground, foregroundOffset,
                                    bounds, ctx.outputProperties());
    }
#endif

    sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size()));
    if (!surf) {
        return nullptr;
    }

    SkCanvas* canvas = surf->getCanvas();
    SkASSERT(canvas);

    canvas->clear(0x0); // can't count on background to fully clear the background
    canvas->translate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));

    if (background) {
        SkPaint paint;
        paint.setBlendMode(SkBlendMode::kSrc);
        background->draw(canvas,
                         SkIntToScalar(backgroundOffset.fX), SkIntToScalar(backgroundOffset.fY),
                         &paint);
    }

    this->drawForeground(canvas, foreground.get(), foregroundBounds);

    return surf->makeImageSnapshot();
}

SkIRect SkXfermodeImageFilter_Base::onFilterBounds(const SkIRect& src,
                                                   const SkMatrix& ctm,
                                                   MapDirection dir,
                                                   const SkIRect* inputRect) const {
    if (kReverse_MapDirection == dir) {
        return SkImageFilter::onFilterBounds(src, ctm, dir, inputRect);
    }

    SkASSERT(!inputRect);
    SkASSERT(2 == this->countInputs());
    auto getBackground = [&]() {
        return this->getInput(0) ? this->getInput(0)->filterBounds(src, ctm, dir, inputRect) : src;
    };
    auto getForeground = [&]() {
        return this->getInput(1) ? this->getInput(1)->filterBounds(src, ctm, dir, inputRect) : src;
    };
    switch (fMode) {
        case SkBlendMode::kClear:
            return SkIRect::MakeEmpty();

        case SkBlendMode::kSrc:
        case SkBlendMode::kDstATop:
            return getForeground();

        case SkBlendMode::kDst:
        case SkBlendMode::kSrcATop:
            return getBackground();

        case SkBlendMode::kSrcIn:
        case SkBlendMode::kDstIn: {
            auto result = getBackground();
            if (!result.intersect(getForeground())) {
                return SkIRect::MakeEmpty();
            }
            return result;
        }

        default: {
            auto result = getBackground();
            result.join(getForeground());
            return result;
        }
    }
}

sk_sp<SkImageFilter> SkXfermodeImageFilter_Base::onMakeColorSpace(SkColorSpaceXformer* xformer)
const {
    SkASSERT(2 == this->countInputs());
    auto background = xformer->apply(this->getInput(0));
    auto foreground = xformer->apply(this->getInput(1));
    if (background.get() != this->getInput(0) || foreground.get() != this->getInput(1)) {
        return SkXfermodeImageFilter::Make(fMode, std::move(background), std::move(foreground),
                                           this->getCropRectIfSet());
    }
    return this->refMe();
}

void SkXfermodeImageFilter_Base::drawForeground(SkCanvas* canvas, SkSpecialImage* img,
                                                const SkIRect& fgBounds) const {
    SkPaint paint;
    paint.setBlendMode(fMode);
    if (img) {
        img->draw(canvas, SkIntToScalar(fgBounds.fLeft), SkIntToScalar(fgBounds.fTop), &paint);
    }

    SkAutoCanvasRestore acr(canvas, true);
    canvas->clipRect(SkRect::Make(fgBounds), kDifference_SkClipOp);
    paint.setColor(0);
    canvas->drawPaint(paint);
}

#if SK_SUPPORT_GPU

#include "effects/GrXfermodeFragmentProcessor.h"

sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU(
                                                   SkSpecialImage* source,
                                                   sk_sp<SkSpecialImage> background,
                                                   const SkIPoint& backgroundOffset,
                                                   sk_sp<SkSpecialImage> foreground,
                                                   const SkIPoint& foregroundOffset,
                                                   const SkIRect& bounds,
                                                   const OutputProperties& outputProperties) const {
    SkASSERT(source->isTextureBacked());

    GrContext* context = source->getContext();

    sk_sp<GrTextureProxy> backgroundProxy, foregroundProxy;

    if (background) {
        backgroundProxy = background->asTextureProxyRef(context);
    }

    if (foreground) {
        foregroundProxy = foreground->asTextureProxyRef(context);
    }

    GrPaint paint;
    std::unique_ptr<GrFragmentProcessor> bgFP;

    if (backgroundProxy) {
        SkMatrix bgMatrix = SkMatrix::MakeTrans(-SkIntToScalar(backgroundOffset.fX),
                                                -SkIntToScalar(backgroundOffset.fY));
        bgFP = GrTextureDomainEffect::Make(std::move(backgroundProxy), bgMatrix,
                                           GrTextureDomain::MakeTexelDomain(background->subset()),
                                           GrTextureDomain::kDecal_Mode,
                                           GrSamplerState::Filter::kNearest);
        bgFP = GrColorSpaceXformEffect::Make(std::move(bgFP), background->getColorSpace(),
                                             background->alphaType(),
                                             outputProperties.colorSpace());
    } else {
        bgFP = GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
                                           GrConstColorProcessor::InputMode::kIgnore);
    }

    if (foregroundProxy) {
        SkMatrix fgMatrix = SkMatrix::MakeTrans(-SkIntToScalar(foregroundOffset.fX),
                                                -SkIntToScalar(foregroundOffset.fY));
        auto foregroundFP = GrTextureDomainEffect::Make(
                std::move(foregroundProxy), fgMatrix,
                GrTextureDomain::MakeTexelDomain(foreground->subset()),
                GrTextureDomain::kDecal_Mode, GrSamplerState::Filter::kNearest);
        foregroundFP = GrColorSpaceXformEffect::Make(std::move(foregroundFP),
                                                     foreground->getColorSpace(),
                                                     foreground->alphaType(),
                                                     outputProperties.colorSpace());
        paint.addColorFragmentProcessor(std::move(foregroundFP));

        std::unique_ptr<GrFragmentProcessor> xferFP = this->makeFGFrag(std::move(bgFP));

        // A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed
        if (xferFP) {
            paint.addColorFragmentProcessor(std::move(xferFP));
        }
    } else {
        paint.addColorFragmentProcessor(std::move(bgFP));
    }

    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);

    sk_sp<GrRenderTargetContext> renderTargetContext(
        context->contextPriv().makeDeferredRenderTargetContext(
                                    SkBackingFit::kApprox, bounds.width(), bounds.height(),
                                    SkColorType2GrPixelConfig(outputProperties.colorType()),
                                    sk_ref_sp(outputProperties.colorSpace())));
    if (!renderTargetContext) {
        return nullptr;
    }

    SkMatrix matrix;
    matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix,
                                  SkRect::Make(bounds));

    return SkSpecialImage::MakeDeferredFromGpu(
            context,
            SkIRect::MakeWH(bounds.width(), bounds.height()),
            kNeedNewImageUniqueID_SpecialImage,
            renderTargetContext->asTextureProxyRef(),
            renderTargetContext->colorSpaceInfo().refColorSpace());
}

std::unique_ptr<GrFragmentProcessor> SkXfermodeImageFilter_Base::makeFGFrag(
        std::unique_ptr<GrFragmentProcessor> bgFP) const {
    return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(bgFP), fMode);
}

#endif
///////////////////////////////////////////////////////////////////////////////////////////////////

void SkXfermodeImageFilter::InitializeFlattenables() {
    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkXfermodeImageFilter_Base)
}
<|endoftext|>


<commit_before>#include "filler.h"

BRepFill_Filling* siren_filler_get(mrb_state* mrb, mrb_value obj)
{
  return static_cast<BRepFill_Filling*>(mrb_get_datatype(mrb, obj, &siren_filler_type));
}

bool siren_filler_install(mrb_state* mrb, struct RClass* rclass)
{
  rclass = mrb_define_class(mrb, "Filler", mrb->object_class);
  MRB_SET_INSTANCE_TT(rclass, MRB_TT_DATA);
  mrb_define_method(mrb, rclass, "initialize", siren_filler_init,      MRB_ARGS_OPT(10));
  mrb_define_method(mrb, rclass, "add_bound",  siren_filler_add_bound, MRB_ARGS_REQ(2));
  mrb_define_method(mrb, rclass, "add",        siren_filler_add,       MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1));
  mrb_define_method(mrb, rclass, "build",      siren_filler_build,     MRB_ARGS_NONE());
  mrb_define_method(mrb, rclass, "done?",      siren_filler_is_done,   MRB_ARGS_NONE());
  mrb_define_method(mrb, rclass, "face",       siren_filler_face,      MRB_ARGS_NONE());
  mrb_define_method(mrb, rclass, "g0error",    siren_filler_g0error,   MRB_ARGS_OPT(1));
  mrb_define_method(mrb, rclass, "g1error",    siren_filler_g1error,   MRB_ARGS_OPT(1));
  mrb_define_method(mrb, rclass, "g2error",    siren_filler_g2error,   MRB_ARGS_OPT(1));
  return true;
}

mrb_value siren_filler_init(mrb_state* mrb, mrb_value self)
{
  mrb_int degree, nbptsoncur, nbiter;
  mrb_bool anisotropie;
  mrb_float tol2d, tol3d, tolang, tolcurv;
  mrb_int maxdeg, maxsegs;
  int argc = mrb_get_args(mrb, "|iiibffffii",
      &degree, &nbptsoncur, &nbiter, &anisotropie,
      &tol2d, &tol3d, &tolang, &tolcurv, &maxdeg, &maxsegs);

  mrb_value obj;
  obj = mrb_instance_alloc(mrb, mrb_obj_value(mrb_class_get(mrb, "Filler")));
  void* p = mrb_malloc(mrb, sizeof(BRepFill_Filling));
  BRepFill_Filling* inner = NULL;

  switch (argc) {
    case 1:
      inner = new(p) BRepFill_Filling(degree);
      break;
    case 2:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur);
      break;
    case 3:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter);
      break;
    case 4:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie);
      break;
    case 5:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie,
          tol2d);
      break;
    case 6:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie,
          tol2d, tol3d);
      break;
    case 7:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie,
          tol2d, tol3d, tolang);
      break;
    case 8:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie,
          tol2d, tol3d, tolang, tolcurv);
      break;
    case 9:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie,
          tol2d, tol3d, tolang, tolcurv, maxdeg);
      break;
    case 10:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie,
          tol2d, tol3d, tolang, tolcurv, maxdeg, maxsegs);
      break;
    default:
      inner = new(p) BRepFill_Filling();
      break;
  }

  DATA_PTR(obj)  = inner;
  DATA_TYPE(obj) = &siren_filler_type;
  return obj;
}

void siren_filler_final(mrb_state* mrb, void* p)
{
  BRepFill_Filling* pp = static_cast<BRepFill_Filling*>(p);
  mrb_free(mrb, pp);
}

mrb_value siren_filler_add_bound(mrb_state* mrb, mrb_value self)
{
  mrb_value edge;
  mrb_int order;
  int argc = mrb_get_args(mrb, "oi", &edge, &order);
  TopoDS_Shape* s = siren_shape_get(mrb, edge);
  TopoDS_Edge e = TopoDS::Edge(*s);
  siren_filler_get(mrb, self)->Add(e, (GeomAbs_Shape)order,
      /* IsBound= */ Standard_True);
  return mrb_nil_value();
}

mrb_value siren_filler_add(mrb_state* mrb, mrb_value self)
{
  mrb_value obj;
  mrb_int order;
  int argc = mrb_get_args(mrb, "o|i", &obj, &order);
  if (argc == 2) {
    TopoDS_Shape* s = siren_shape_get(mrb, obj);
    TopoDS_Edge e = TopoDS::Edge(*s);
    siren_filler_get(mrb, self)->Add(e, (GeomAbs_Shape)order,
        /* IsBound= */ Standard_False);
  }
  else {
    gp_Pnt pnt = siren_ary_to_pnt(mrb, obj);
    siren_filler_get(mrb, self)->Add(pnt);
  }
  return mrb_nil_value();
}

mrb_value siren_filler_build(mrb_state* mrb, mrb_value self)
{
  siren_filler_get(mrb, self)->Build();
  return mrb_nil_value();
}

mrb_value siren_filler_is_done(mrb_state* mrb, mrb_value self)
{
  return siren_filler_get(mrb, self)->IsDone() == Standard_True ?
    mrb_true_value() : mrb_false_value();
}

mrb_value siren_filler_face(mrb_state* mrb, mrb_value self)
{
  TopoDS_Face f = siren_filler_get(mrb, self)->Face();
  return siren_shape_new(mrb, f);
}

mrb_value siren_filler_g0error(mrb_state* mrb, mrb_value self)
{
  mrb_int index;
  int argc = mrb_get_args(mrb, "|i", &index);
  Standard_Real value;
  if (argc) {
    value = siren_filler_get(mrb, self)->G0Error(index);
  }
  else {
    value = siren_filler_get(mrb, self)->G0Error();
  }
  return mrb_float_value(mrb, value);
}

mrb_value siren_filler_g1error(mrb_state* mrb, mrb_value self)
{
  mrb_int index;
  int argc = mrb_get_args(mrb, "|i", &index);
  Standard_Real value;
  if (argc) {
    value = siren_filler_get(mrb, self)->G1Error(index);
  }
  else {
    value = siren_filler_get(mrb, self)->G1Error();
  }
  return mrb_float_value(mrb, value);
}

mrb_value siren_filler_g2error(mrb_state* mrb, mrb_value self)
{
  mrb_int index;
  int argc = mrb_get_args(mrb, "|i", &index);
  Standard_Real value;
  if (argc) {
    value = siren_filler_get(mrb, self)->G2Error(index);
  }
  else {
    value = siren_filler_get(mrb, self)->G2Error();
  }
  return mrb_float_value(mrb, value);
}

<commit_msg>Small fix.<commit_after>#include "filler.h"

BRepFill_Filling* siren_filler_get(mrb_state* mrb, mrb_value obj)
{
  return static_cast<BRepFill_Filling*>(mrb_get_datatype(mrb, obj, &siren_filler_type));
}

bool siren_filler_install(mrb_state* mrb, struct RClass* rclass)
{
  rclass = mrb_define_class(mrb, "Filler", mrb->object_class);
  MRB_SET_INSTANCE_TT(rclass, MRB_TT_DATA);
  mrb_define_method(mrb, rclass, "initialize", siren_filler_init,      MRB_ARGS_OPT(10));
  mrb_define_method(mrb, rclass, "add_bound",  siren_filler_add_bound, MRB_ARGS_REQ(2));
  mrb_define_method(mrb, rclass, "add",        siren_filler_add,       MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1));
  mrb_define_method(mrb, rclass, "build",      siren_filler_build,     MRB_ARGS_NONE());
  mrb_define_method(mrb, rclass, "done?",      siren_filler_is_done,   MRB_ARGS_NONE());
  mrb_define_method(mrb, rclass, "face",       siren_filler_face,      MRB_ARGS_NONE());
  mrb_define_method(mrb, rclass, "g0error",    siren_filler_g0error,   MRB_ARGS_OPT(1));
  mrb_define_method(mrb, rclass, "g1error",    siren_filler_g1error,   MRB_ARGS_OPT(1));
  mrb_define_method(mrb, rclass, "g2error",    siren_filler_g2error,   MRB_ARGS_OPT(1));
  return true;
}

mrb_value siren_filler_init(mrb_state* mrb, mrb_value self)
{
  mrb_int degree, nbptsoncur, nbiter;
  mrb_bool anisotropie;
  mrb_float tol2d, tol3d, tolang, tolcurv;
  mrb_int maxdeg, maxsegs;
  int argc = mrb_get_args(mrb, "|iiibffffii",
      &degree, &nbptsoncur, &nbiter, &anisotropie,
      &tol2d, &tol3d, &tolang, &tolcurv, &maxdeg, &maxsegs);

  void* p = mrb_malloc(mrb, sizeof(BRepFill_Filling));
  BRepFill_Filling* inner = NULL;

  switch (argc) {
    case 1:
      inner = new(p) BRepFill_Filling(degree);
      break;
    case 2:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur);
      break;
    case 3:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter);
      break;
    case 4:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie);
      break;
    case 5:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie,
          tol2d);
      break;
    case 6:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie,
          tol2d, tol3d);
      break;
    case 7:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie,
          tol2d, tol3d, tolang);
      break;
    case 8:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie,
          tol2d, tol3d, tolang, tolcurv);
      break;
    case 9:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie,
          tol2d, tol3d, tolang, tolcurv, maxdeg);
      break;
    case 10:
      inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie,
          tol2d, tol3d, tolang, tolcurv, maxdeg, maxsegs);
      break;
    default:
      inner = new(p) BRepFill_Filling();
      break;
  }

  DATA_PTR(self)  = inner;
  DATA_TYPE(self) = &siren_filler_type;
  return self;
}

void siren_filler_final(mrb_state* mrb, void* p)
{
  BRepFill_Filling* pp = static_cast<BRepFill_Filling*>(p);
  mrb_free(mrb, pp);
}

mrb_value siren_filler_add_bound(mrb_state* mrb, mrb_value self)
{
  mrb_value edge;
  mrb_int order;
  int argc = mrb_get_args(mrb, "oi", &edge, &order);
  TopoDS_Shape* s = siren_shape_get(mrb, edge);
  TopoDS_Edge e = TopoDS::Edge(*s);
  siren_filler_get(mrb, self)->Add(e, (GeomAbs_Shape)order,
      /* IsBound= */ Standard_True);
  return mrb_nil_value();
}

mrb_value siren_filler_add(mrb_state* mrb, mrb_value self)
{
  mrb_value obj;
  mrb_int order;
  int argc = mrb_get_args(mrb, "o|i", &obj, &order);
  if (argc == 2) {
    TopoDS_Shape* s = siren_shape_get(mrb, obj);
    TopoDS_Edge e = TopoDS::Edge(*s);
    siren_filler_get(mrb, self)->Add(e, (GeomAbs_Shape)order,
        /* IsBound= */ Standard_False);
  }
  else {
    gp_Pnt pnt = siren_ary_to_pnt(mrb, obj);
    siren_filler_get(mrb, self)->Add(pnt);
  }
  return mrb_nil_value();
}

mrb_value siren_filler_build(mrb_state* mrb, mrb_value self)
{
  siren_filler_get(mrb, self)->Build();
  return mrb_nil_value();
}

mrb_value siren_filler_is_done(mrb_state* mrb, mrb_value self)
{
  return siren_filler_get(mrb, self)->IsDone() == Standard_True ?
    mrb_true_value() : mrb_false_value();
}

mrb_value siren_filler_face(mrb_state* mrb, mrb_value self)
{
  TopoDS_Face f = siren_filler_get(mrb, self)->Face();
  return siren_shape_new(mrb, f);
}

mrb_value siren_filler_g0error(mrb_state* mrb, mrb_value self)
{
  mrb_int index;
  int argc = mrb_get_args(mrb, "|i", &index);
  Standard_Real value;
  if (argc) {
    value = siren_filler_get(mrb, self)->G0Error(index);
  }
  else {
    value = siren_filler_get(mrb, self)->G0Error();
  }
  return mrb_float_value(mrb, value);
}

mrb_value siren_filler_g1error(mrb_state* mrb, mrb_value self)
{
  mrb_int index;
  int argc = mrb_get_args(mrb, "|i", &index);
  Standard_Real value;
  if (argc) {
    value = siren_filler_get(mrb, self)->G1Error(index);
  }
  else {
    value = siren_filler_get(mrb, self)->G1Error();
  }
  return mrb_float_value(mrb, value);
}

mrb_value siren_filler_g2error(mrb_state* mrb, mrb_value self)
{
  mrb_int index;
  int argc = mrb_get_args(mrb, "|i", &index);
  Standard_Real value;
  if (argc) {
    value = siren_filler_get(mrb, self)->G2Error(index);
  }
  else {
    value = siren_filler_get(mrb, self)->G2Error();
  }
  return mrb_float_value(mrb, value);
}

<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <string>
#include <map>
#include <set>

// Loriano: let's try Armadillo quick code
#include <armadillo>
#include <cassert>
#include <sys/stat.h>

#include <getopt.h>
#include <unistd.h>
#include <alloca.h>

#include <pcafitter_private.hpp>

// lstorchi: basi code to fit tracks, using the PCA constants generated
//           by the related generatepca

namespace
{
  bool file_exists(const std::string& filename)
  {
    struct stat buf;
    if (stat(filename.c_str(), &buf) != -1)
      return true;

    return false;
  }
}

void build_and_compare (arma::mat & paramslt, arma::mat & coordslt,
     arma::mat & cmtx, arma::rowvec & q, bool verbose)
{
  double * oneoverptcmp, * phicmp, * etacmp, * z0cmp, * d0cmp;
  oneoverptcmp = new double [(int)coordslt.n_rows];
  phicmp = new double [(int)coordslt.n_rows];
  etacmp = new double [(int)coordslt.n_rows];
  z0cmp = new double [(int)coordslt.n_rows];
  d0cmp = new double [(int)coordslt.n_rows];
  pcafitter::computeparameters (cmtx, q, coordslt, oneoverptcmp,
      phicmp, etacmp, z0cmp, d0cmp);

  arma::running_stat<double> pc[PARAMDIM];
  for (int i=0; i<(int)coordslt.n_rows; ++i)
  {
    pc[PTIDX](fabs(oneoverptcmp[i] - paramslt(i, PTIDX))/
        (fabs(oneoverptcmp[i] + paramslt(i, PTIDX))/2.0));
    pc[PHIIDX](fabs(phicmp[i] - paramslt(i, PHIIDX))/
        (fabs(phicmp[i] + paramslt(i, PHIIDX))/2.0));
    pc[TETHAIDX](fabs(etacmp[i] - paramslt(i, TETHAIDX))/
        (fabs(etacmp[i] + paramslt(i, TETHAIDX))/2.0));
    pc[D0IDX](fabs(d0cmp[i] - paramslt(i, D0IDX))/
        (fabs(d0cmp[i] + paramslt(i, D0IDX))/2.0));
    pc[Z0IDX](fabs(z0cmp[i] - paramslt(i, Z0IDX))/
        (fabs(z0cmp[i] + paramslt(i, Z0IDX))/2.0));

    if (verbose)
    {
      std::cout << "For track : " << i+1 << std::endl;
      std::cout << " 1/pt         cmpt " << oneoverptcmp[i] << std::endl;
      std::cout << " 1/pt         calc " << paramslt(i, PTIDX) << std::endl;
      std::cout << " phi          cmpt " << phicmp[i] << std::endl;
      std::cout << " phi          calc " << paramslt(i, PHIIDX) << std::endl;
      std::cout << " cot(tetha/2) cmpt " << etacmp[i] << std::endl;
      std::cout << " cot(tetha/2) calc " << paramslt(i, TETHAIDX) << std::endl;
      std::cout << " d0           cmpt " << d0cmp[i] << std::endl;
      std::cout << " d0           calc " << paramslt(i, D0IDX) << std::endl;
      std::cout << " z0           cmpt " << z0cmp[i] << std::endl;
      std::cout << " z0           calc " << paramslt(i, Z0IDX) << std::endl;
    }
  }

  for (int i=0; i<PARAMDIM; ++i)
     std::cout << "For " << pcafitter::paramidxtostring(i) << " error " <<
       100.0*pc[i].mean() << " " << 100.0*pc[i].stddev() << std::endl;

  delete [] oneoverptcmp;
  delete [] phicmp;
  delete [] etacmp;
  delete [] z0cmp;
  delete [] d0cmp;
}

void usage (char * name)
{
  std::cerr << "usage: " << name << " [options] coordinatesfile " << std::endl;
  std::cerr << std::endl;
  std::cerr << " -h, --help               : display this help and exit" << std::endl;
  std::cerr << " -V, --verbose            : verbose option on" << std::endl;
  std::cerr << " -v, --version            : print version and exit" << std::endl;
  std::cerr << " -c, --cmtx=[fillename]   : CMTX filename [default is c.bin]" << std::endl;
  std::cerr << " -q, --qvct=[fillename]   : QVCT filename [default is q.bin]" << std::endl;
  std::cerr << " -s, --subsector=[subsec] : by default use values of the bigger subsector" << std::endl;
  std::cerr << "                            with this option you can speficy to perform " << std::endl;
  std::cerr << "                            prediction for subsector subsec " << std::endl;
  std::cerr << " -l, --subladder=[subld]  : by default use values of the bigger subladder " << std::endl;
  std::cerr << "                            with this option you can speficy to perform " << std::endl;
  std::cerr << "                            prediction for subladder subld " << std::endl;
  std::cerr << " -a, --all-subsectors     : perform the fitting for all subsectors" << std::endl;
  std::cerr << " -r, --all-subladders     : perform the fitting for all subladders" << std::endl;

  exit(1);
}

int main (int argc, char ** argv)
{
  std::string qfname = "q.bin";
  std::string cfname = "c.bin";
  std::string subsec = "";
  std::string sublad = "";
  bool verbose = false;
  bool useallsubsectors = false;
  bool useallsubladders = false;

  while (1)
  {
    int c, option_index;
    static struct option long_options[] = {
      {"help", 0, NULL, 'h'},
      {"cmtx", 1, NULL, 'c'},
      {"qvct", 1, NULL, 'q'},
      {"subsector", 1, NULL, 's'},
      {"subladder", 1, NULL, 'l'},
      {"verbose", 0, NULL, 'V'},
      {"version", 0, NULL, 'v'},
      {"all-subsectors", 0, NULL, 'a'},
      {"all-subladders", 0, NULL, 'r'},
      {0, 0, 0, 0}
    };

    c = getopt_long (argc, argv, "arvhVc:q:s:l:", long_options, &option_index);

    if (c == -1)
      break;

    switch (c)
    {
      case 'a':
        useallsubsectors = true;
        break;
      case 'r':
        useallsubladders = true;
        break;
      case 'V':
        verbose = true;
        break;
      case 'v':
        std::cout << "Version: " << pcafitter::get_version_string() << std::endl;
        exit(1);
        break;
      case 'h':
        usage (argv[0]);
        break;
      case 's':
        subsec = optarg;
        break;
      case 'l':
        sublad = optarg;
        break;
      case'c':
        cfname = optarg;
        break;
      case 'q':
        qfname = optarg;
        break;
      default:
        usage (argv[0]);
        break;
    }
  }

  if (optind >= argc)
    usage (argv[0]);

  if (useallsubladders && useallsubsectors)
    usage (argv[0]);

  char * filename = (char *) alloca (strlen(argv[optind]) + 1);
  strcpy (filename, argv[optind]);

  // leggere file coordinate tracce e file costanti PCA
  // N righe di 9 double sono le coordinate
  // matrice C e vettore q sono le costanti

  arma::mat cmtx;
  arma::rowvec q;

  std::cout << "Reading data from " << filename << " file " << std::endl;
  int num_of_line = pcafitter::numofline(filename);
  std::cout << "file has " << num_of_line << " line " << std::endl;
  int num_of_ent = (num_of_line-1)/ENTDIM;
  std::cout << "file has " << num_of_ent << " entries " << std::endl;

  arma::mat layer, ladder, module, coord, param;
  layer.set_size(num_of_ent,COORDIM);
  ladder.set_size(num_of_ent,COORDIM);
  module.set_size(num_of_ent,COORDIM);
  coord.set_size(num_of_ent,DIMPERCOORD*COORDIM);
  param.set_size(num_of_ent,PARAMDIM);

  std::map<std::string, int> subsectors, subladders;
  std::vector<std::string> subladderslist, subsectorslist;

  // leggere file coordinate tracce simulate plus parametri
  if (!file_exists(filename))
  {
    std::cerr << "Inout file does not exist" << std::endl;
    return 1;
  }

  pcafitter::readingfromfile (filename, param, coord,
      layer, ladder, module, subsectors, subladders,
      subsectorslist, subladderslist, num_of_ent);

  if (!useallsubsectors && !useallsubladders)
  {
    std::cout << "Read constant from files (" << cfname <<
      " and " << qfname << ")" << std::endl;
    if (!file_exists(cfname) || !file_exists(qfname))
    {
      std::cerr << "Constants file does not exist" << std::endl;
      return 1;
    }
    pcafitter::readarmmat(cfname.c_str(), cmtx);
    pcafitter::readarmvct(qfname.c_str(), q);

    if ((subsec == "") && (sublad == ""))
    {
      int maxnumber;

      std::cout << "Looking for bigger subsector" << std::endl;
      std::cout << "We  found " << subsectors.size() <<
        " subsectors " << std::endl;

      pcafitter::select_bigger_sub (subsectors, verbose,
          maxnumber, subsec);

      std::cout << "Selected subsector " << subsec <<
        " numevt: " << maxnumber << std::endl;

      std::cout << "Looking for bigger subladder" << std::endl;
      std::cout << "We  found " << subladders.size() <<
        " subladders " << std::endl;

      pcafitter::select_bigger_sub (subladders, verbose,
          maxnumber, sublad);

      std::cout << "Selected subladder " << sublad << " numevt: "
        << maxnumber << std::endl;
    }

    if (subsec != "")
    {
      arma::mat paramslt, coordslt;

      std::cout << "Using subsector " << subsec << std::endl;

      pcafitter::extract_sub (subsectorslist,
          subsec, param, coord, paramslt,
          coordslt);

      build_and_compare (paramslt, coordslt, cmtx, q, verbose);
    }

    if (sublad != "")
    {
      arma::mat paramslt, coordslt;

      std::cout << "Using subladder " << sublad << std::endl;

      pcafitter::extract_sub (subladderslist,
          sublad, param, coord, paramslt,
          coordslt);

      build_and_compare (paramslt, coordslt, cmtx, q, verbose);
    }
  }
  else
  {
    assert(useallsubladders != useallsubsectors);
    std::set<std::string> sectrorset;

    std::vector<std::string> * listtouse = NULL;

    if (useallsubsectors)
    {
      std::vector<std::string>::const_iterator selecteds =
        subsectorslist.begin();
      for (; selecteds != subsectorslist.end(); ++selecteds)
        sectrorset.insert(*selecteds);

      listtouse = &subsectorslist;
    }
    else if (useallsubladders)
    {
      std::vector<std::string>::const_iterator selecteds =
        subladderslist.begin();
      for (; selecteds != subladderslist.end(); ++selecteds)
        sectrorset.insert(*selecteds);

      listtouse = &subladderslist;
    }
    else
      usage(argv[0]);

    std::set<std::string>::const_iterator selected =
      sectrorset.begin();
    for (; selected != sectrorset.end(); ++selected)
    {
      std::ostringstream cfname, qfname;
      cfname << "c." << *selected << ".bin";
      qfname << "q." << *selected << ".bin";

      if (file_exists(cfname.str()) && file_exists(qfname.str()))
      {
        std::cout << "Perfom fitting for " << *selected << std::endl;

        arma::mat paramslt, coordslt;

        pcafitter::extract_sub (*listtouse,
            *selected, param, coord, paramslt,
            coordslt);

        build_and_compare (paramslt, coordslt, cmtx, q, verbose);
      }
    }

    // TODO
  }

  return 0;
}
<commit_msg>fitting is now perfomed for all subtower and so on ..<commit_after>#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <string>
#include <map>
#include <set>

// Loriano: let's try Armadillo quick code
#include <armadillo>
#include <cassert>
#include <sys/stat.h>

#include <getopt.h>
#include <unistd.h>
#include <alloca.h>

#include <pcafitter_private.hpp>

// lstorchi: basi code to fit tracks, using the PCA constants generated
//           by the related generatepca

namespace
{
  bool file_exists(const std::string& filename)
  {
    struct stat buf;
    if (stat(filename.c_str(), &buf) != -1)
      return true;

    return false;
  }
}

void build_and_compare (arma::mat & paramslt, arma::mat & coordslt,
     arma::mat & cmtx, arma::rowvec & q, bool verbose)
{
  double * oneoverptcmp, * phicmp, * etacmp, * z0cmp, * d0cmp;
  oneoverptcmp = new double [(int)coordslt.n_rows];
  phicmp = new double [(int)coordslt.n_rows];
  etacmp = new double [(int)coordslt.n_rows];
  z0cmp = new double [(int)coordslt.n_rows];
  d0cmp = new double [(int)coordslt.n_rows];
  pcafitter::computeparameters (cmtx, q, coordslt, oneoverptcmp,
      phicmp, etacmp, z0cmp, d0cmp);

  arma::running_stat<double> pc[PARAMDIM];
  for (int i=0; i<(int)coordslt.n_rows; ++i)
  {
    pc[PTIDX](fabs(oneoverptcmp[i] - paramslt(i, PTIDX))/
        (fabs(oneoverptcmp[i] + paramslt(i, PTIDX))/2.0));
    pc[PHIIDX](fabs(phicmp[i] - paramslt(i, PHIIDX))/
        (fabs(phicmp[i] + paramslt(i, PHIIDX))/2.0));
    pc[TETHAIDX](fabs(etacmp[i] - paramslt(i, TETHAIDX))/
        (fabs(etacmp[i] + paramslt(i, TETHAIDX))/2.0));
    pc[D0IDX](fabs(d0cmp[i] - paramslt(i, D0IDX))/
        (fabs(d0cmp[i] + paramslt(i, D0IDX))/2.0));
    pc[Z0IDX](fabs(z0cmp[i] - paramslt(i, Z0IDX))/
        (fabs(z0cmp[i] + paramslt(i, Z0IDX))/2.0));

    if (verbose)
    {
      std::cout << "For track : " << i+1 << std::endl;
      std::cout << " 1/pt         cmpt " << oneoverptcmp[i] << std::endl;
      std::cout << " 1/pt         calc " << paramslt(i, PTIDX) << std::endl;
      std::cout << " phi          cmpt " << phicmp[i] << std::endl;
      std::cout << " phi          calc " << paramslt(i, PHIIDX) << std::endl;
      std::cout << " cot(tetha/2) cmpt " << etacmp[i] << std::endl;
      std::cout << " cot(tetha/2) calc " << paramslt(i, TETHAIDX) << std::endl;
      std::cout << " d0           cmpt " << d0cmp[i] << std::endl;
      std::cout << " d0           calc " << paramslt(i, D0IDX) << std::endl;
      std::cout << " z0           cmpt " << z0cmp[i] << std::endl;
      std::cout << " z0           calc " << paramslt(i, Z0IDX) << std::endl;
    }
  }

  for (int i=0; i<PARAMDIM; ++i)
     std::cout << "For " << pcafitter::paramidxtostring(i) << " error " <<
       100.0*pc[i].mean() << " " << 100.0*pc[i].stddev() << std::endl;

  delete [] oneoverptcmp;
  delete [] phicmp;
  delete [] etacmp;
  delete [] z0cmp;
  delete [] d0cmp;
}

void usage (char * name)
{
  std::cerr << "usage: " << name << " [options] coordinatesfile " << std::endl;
  std::cerr << std::endl;
  std::cerr << " -h, --help               : display this help and exit" << std::endl;
  std::cerr << " -V, --verbose            : verbose option on" << std::endl;
  std::cerr << " -v, --version            : print version and exit" << std::endl;
  std::cerr << " -c, --cmtx=[fillename]   : CMTX filename [default is c.bin]" << std::endl;
  std::cerr << " -q, --qvct=[fillename]   : QVCT filename [default is q.bin]" << std::endl;
  std::cerr << " -s, --subsector=[subsec] : by default use values of the bigger subsector" << std::endl;
  std::cerr << "                            with this option you can speficy to perform " << std::endl;
  std::cerr << "                            prediction for subsector subsec " << std::endl;
  std::cerr << " -l, --subladder=[subld]  : by default use values of the bigger subladder " << std::endl;
  std::cerr << "                            with this option you can speficy to perform " << std::endl;
  std::cerr << "                            prediction for subladder subld " << std::endl;
  std::cerr << " -a, --all-subsectors     : perform the fitting for all subsectors" << std::endl;
  std::cerr << " -r, --all-subladders     : perform the fitting for all subladders" << std::endl;

  exit(1);
}

int main (int argc, char ** argv)
{
  std::string qfname = "q.bin";
  std::string cfname = "c.bin";
  std::string subsec = "";
  std::string sublad = "";
  bool verbose = false;
  bool useallsubsectors = false;
  bool useallsubladders = false;

  while (1)
  {
    int c, option_index;
    static struct option long_options[] = {
      {"help", 0, NULL, 'h'},
      {"cmtx", 1, NULL, 'c'},
      {"qvct", 1, NULL, 'q'},
      {"subsector", 1, NULL, 's'},
      {"subladder", 1, NULL, 'l'},
      {"verbose", 0, NULL, 'V'},
      {"version", 0, NULL, 'v'},
      {"all-subsectors", 0, NULL, 'a'},
      {"all-subladders", 0, NULL, 'r'},
      {0, 0, 0, 0}
    };

    c = getopt_long (argc, argv, "arvhVc:q:s:l:", long_options, &option_index);

    if (c == -1)
      break;

    switch (c)
    {
      case 'a':
        useallsubsectors = true;
        break;
      case 'r':
        useallsubladders = true;
        break;
      case 'V':
        verbose = true;
        break;
      case 'v':
        std::cout << "Version: " << pcafitter::get_version_string() << std::endl;
        exit(1);
        break;
      case 'h':
        usage (argv[0]);
        break;
      case 's':
        subsec = optarg;
        break;
      case 'l':
        sublad = optarg;
        break;
      case'c':
        cfname = optarg;
        break;
      case 'q':
        qfname = optarg;
        break;
      default:
        usage (argv[0]);
        break;
    }
  }

  if (optind >= argc)
    usage (argv[0]);

  if (useallsubladders && useallsubsectors)
    usage (argv[0]);

  char * filename = (char *) alloca (strlen(argv[optind]) + 1);
  strcpy (filename, argv[optind]);

  // leggere file coordinate tracce e file costanti PCA
  // N righe di 9 double sono le coordinate
  // matrice C e vettore q sono le costanti

  arma::mat cmtx;
  arma::rowvec q;

  std::cout << "Reading data from " << filename << " file " << std::endl;
  int num_of_line = pcafitter::numofline(filename);
  std::cout << "file has " << num_of_line << " line " << std::endl;
  int num_of_ent = (num_of_line-1)/ENTDIM;
  std::cout << "file has " << num_of_ent << " entries " << std::endl;

  arma::mat layer, ladder, module, coord, param;
  layer.set_size(num_of_ent,COORDIM);
  ladder.set_size(num_of_ent,COORDIM);
  module.set_size(num_of_ent,COORDIM);
  coord.set_size(num_of_ent,DIMPERCOORD*COORDIM);
  param.set_size(num_of_ent,PARAMDIM);

  std::map<std::string, int> subsectors, subladders;
  std::vector<std::string> subladderslist, subsectorslist;

  // leggere file coordinate tracce simulate plus parametri
  if (!file_exists(filename))
  {
    std::cerr << "Inout file does not exist" << std::endl;
    return 1;
  }

  pcafitter::readingfromfile (filename, param, coord,
      layer, ladder, module, subsectors, subladders,
      subsectorslist, subladderslist, num_of_ent);

  if (!useallsubsectors && !useallsubladders)
  {
    std::cout << "Read constant from files (" << cfname <<
      " and " << qfname << ")" << std::endl;
    if (!file_exists(cfname) || !file_exists(qfname))
    {
      std::cerr << "Constants file does not exist" << std::endl;
      return 1;
    }
    pcafitter::readarmmat(cfname.c_str(), cmtx);
    pcafitter::readarmvct(qfname.c_str(), q);

    if ((subsec == "") && (sublad == ""))
    {
      int maxnumber;

      std::cout << "Looking for bigger subsector" << std::endl;
      std::cout << "We  found " << subsectors.size() <<
        " subsectors " << std::endl;

      pcafitter::select_bigger_sub (subsectors, verbose,
          maxnumber, subsec);

      std::cout << "Selected subsector " << subsec <<
        " numevt: " << maxnumber << std::endl;

      std::cout << "Looking for bigger subladder" << std::endl;
      std::cout << "We  found " << subladders.size() <<
        " subladders " << std::endl;

      pcafitter::select_bigger_sub (subladders, verbose,
          maxnumber, sublad);

      std::cout << "Selected subladder " << sublad << " numevt: "
        << maxnumber << std::endl;
    }

    if (subsec != "")
    {
      arma::mat paramslt, coordslt;

      std::cout << "Using subsector " << subsec << std::endl;

      pcafitter::extract_sub (subsectorslist,
          subsec, param, coord, paramslt,
          coordslt);

      build_and_compare (paramslt, coordslt, cmtx, q, verbose);
    }

    if (sublad != "")
    {
      arma::mat paramslt, coordslt;

      std::cout << "Using subladder " << sublad << std::endl;

      pcafitter::extract_sub (subladderslist,
          sublad, param, coord, paramslt,
          coordslt);

      build_and_compare (paramslt, coordslt, cmtx, q, verbose);
    }
  }
  else
  {
    assert(useallsubladders != useallsubsectors);
    std::set<std::string> sectrorset;

    std::vector<std::string> * listtouse = NULL;

    if (useallsubsectors)
    {
      std::vector<std::string>::const_iterator selecteds =
        subsectorslist.begin();
      for (; selecteds != subsectorslist.end(); ++selecteds)
        sectrorset.insert(*selecteds);

      listtouse = &subsectorslist;
    }
    else if (useallsubladders)
    {
      std::vector<std::string>::const_iterator selecteds =
        subladderslist.begin();
      for (; selecteds != subladderslist.end(); ++selecteds)
        sectrorset.insert(*selecteds);

      listtouse = &subladderslist;
    }
    else
      usage(argv[0]);

    std::set<std::string>::const_iterator selected =
      sectrorset.begin();
    for (; selected != sectrorset.end(); ++selected)
    {
      std::ostringstream cfname, qfname;
      cfname << "c." << *selected << ".bin";
      qfname << "q." << *selected << ".bin";

      if (file_exists(cfname.str()) && file_exists(qfname.str()))
      {
        std::cout << "Perfom fitting for " << *selected << std::endl;

        std::cout << "Read constants " << std::endl;
        pcafitter::readarmmat(cfname.str().c_str(), cmtx);
        pcafitter::readarmvct(qfname.str().c_str(), q);

        arma::mat paramslt, coordslt;

        pcafitter::extract_sub (*listtouse,
            *selected, param, coord, paramslt,
            coordslt);

        build_and_compare (paramslt, coordslt, cmtx, q, verbose);
      }
    }

    // TODO
  }

  return 0;
}
<|endoftext|>


<commit_before>#ifndef KMC_KLANG_EITHER_HPP
#define KMC_KLANG_EITHER_HPP

#include <boost/optional.hpp>

namespace klang {

using optional = boost::optional;

struct LeftTag {} left_tag;
struct RightTag {} right_tag;

template <typename Left, typename Right>
class Either {
 public:
  Either(const Right& right);
  Either(Right&& right);
  Either(LeftTag, const Left& left);
  Either(LeftTag, Left&& left);
  Either(RightTag , const Right& right);
  Either(RightTag, Right&& right);
  Either(const Either& either);
  Either(Either&& either);
  Either& operator=(const Either& either);
  Either& operator=(Either&& either);
  Either& operator=(const Right& right);
  Either& operator=(Right&& right);
  bool is_left() const;
  bool is_right() const;
  const Left& left_value() const;
  const Right& right_value() const;
  explicit operator bool() const;
  const Right& operator*() const;
  const Right* operator->() const;
 private:
  optional<Left> left_;
  optional<Right> right_;
};

template <typename Left, typename Right, typename E = Either<Left, Right> >
bool operator==(const E& lhs, const E& rhs);

template <typename Left, typename Right, typename E = Either<Left, Right> >
bool operator<(const E& lhs, const E& rhs);

}  // namespace klang

#endif  // KMC_KLANG_EITHER_HPP
<commit_msg>Fix interface of Either<commit_after>#ifndef KMC_KLANG_EITHER_HPP
#define KMC_KLANG_EITHER_HPP

#include <boost/optional.hpp>

namespace klang {

template <typename T>
using optional = boost::optional<T>;

struct LeftTag {} left_tag;
struct RightTag {} right_tag;

template <typename Left, typename Right>
class Either {
 public:
  Either(const Right& right);
  Either(Right&& right);
  Either(LeftTag, const Left& left);
  Either(LeftTag, Left&& left);
  Either(RightTag , const Right& right);
  Either(RightTag, Right&& right);
  Either(const Either& either);
  Either(Either&& either);
  Either& operator=(const Either& either);
  Either& operator=(Either&& either);
  void swap(Either& that);
  bool is_left() const;
  bool is_right() const;
  const Left& left_value() const;
  const Right& right_value() const;
  explicit operator bool() const;
  const Right& operator*() const&;
  Right& operator*() &;
  Right&& operator*() &&;
  const Right* operator->() const;
  Right* operator->();
 private:
  optional<Left> left_;
  optional<Right> right_;
};

template <typename Left, typename Right, typename E = Either<Left, Right> >
bool operator==(const E& lhs, const E& rhs);

template <typename Left, typename Right, typename E = Either<Left, Right> >
bool operator<(const E& lhs, const E& rhs);

template <typename Left, typename Right, typename E = Either<Left, Right> >
void swap(E& lhs, E& rhs);

}  // namespace klang

#endif  // KMC_KLANG_EITHER_HPP
<|endoftext|>


<commit_before>#pragma once

#include <string>
#include "cpp_syntax_highlighting.hpp"
#include "tags.hpp"
#include "snippets.h"

enum class markdown_types
{
	eof,
	text,
	inline_code
};

struct markdown_token
{
	std::string content;
	markdown_types type;
};

template <class RandomAccessIterator>
std::string find_next_paragraph(RandomAccessIterator begin,
                                RandomAccessIterator end)
{
	return std::string(begin, std::find_if(begin + 1, end, is_line_end));
}

template <class RandomAccessIterator>
markdown_token find_next_mark_down_token(RandomAccessIterator &begin,
                                         RandomAccessIterator end)
{
	if (begin == end)
	{
		return {"", markdown_types::eof};
	}
	if (*begin == '`')
	{
		begin += 1;
		return {std::string(begin, std::find_if(begin + 1, end,
		                                        [](char c)
		                                        {
			                                        return c == '`';
			                                    })),
		        markdown_types::inline_code};
	}
	return {std::string(begin, std::find_if(begin + 1, end,
	                                        [](char c)
	                                        {
		                                        return c == '`';

		                                    })),
	        markdown_types::text};
}

auto compile_paragraph(std::string source)
{
	return Si::html::dynamic([source =
	                              std::move(source)](Si::html::code_sink & sink)
	                         {
		                         auto i = source.begin();
		                         for (;;)
		                         {
			                         markdown_token token =
			                             find_next_mark_down_token(
			                                 i, source.end());
			                         switch (token.type)
			                         {
			                         case markdown_types::eof:
				                         return;
			                         case markdown_types::inline_code:
				                         inline_code(token.content)
				                             .generate(sink);
				                         i += 1;
				                         break;
			                         case markdown_types::text:
				                         if (!(token.content.size() == 1 &&
				                               is_line_end(token.content[0])))
				                         {
					                         Si::html::text(token.content)
					                             .generate(sink);
				                         }
			                         }
			                         i += token.content.size();
		                         }
		                     });
}

auto compile(std::string source)
{
	return Si::html::dynamic([source =
	                              std::move(source)](Si::html::code_sink & sink)
	                         {
		                         auto i = source.begin();
		                         for (;;)
		                         {
			                         std::string paragraph =
			                             find_next_paragraph(i, source.end());
			                         if (paragraph.size() == 0)
			                         {
				                         return;
			                         }

			                         Si::html::tag("p",
			                                       compile_paragraph(paragraph))
			                             .generate(sink);
			                         i += paragraph.size();
		                         }

		                     });
}<commit_msg>avoid out-of-bounds string access<commit_after>#pragma once

#include <string>
#include "cpp_syntax_highlighting.hpp"
#include "tags.hpp"
#include "snippets.h"

enum class markdown_types
{
	eof,
	text,
	inline_code
};

struct markdown_token
{
	std::string content;
	markdown_types type;
};

template <class RandomAccessIterator>
std::string find_next_paragraph(RandomAccessIterator begin,
                                RandomAccessIterator end)
{
	if (begin == end)
	{
		return "";
	}
	return std::string(begin, std::find_if(begin + 1, end, is_line_end));
}

template <class RandomAccessIterator>
markdown_token find_next_mark_down_token(RandomAccessIterator &begin,
                                         RandomAccessIterator end)
{
	if (begin == end)
	{
		return {"", markdown_types::eof};
	}
	if (*begin == '`')
	{
		begin += 1;
		return {std::string(begin, std::find_if(begin + 1, end,
		                                        [](char c)
		                                        {
			                                        return c == '`';
			                                    })),
		        markdown_types::inline_code};
	}
	return {std::string(begin, std::find_if(begin + 1, end,
	                                        [](char c)
	                                        {
		                                        return c == '`';

		                                    })),
	        markdown_types::text};
}

auto compile_paragraph(std::string source)
{
	return Si::html::dynamic([source =
	                              std::move(source)](Si::html::code_sink & sink)
	                         {
		                         auto i = source.begin();
		                         for (;;)
		                         {
			                         markdown_token token =
			                             find_next_mark_down_token(
			                                 i, source.end());
			                         switch (token.type)
			                         {
			                         case markdown_types::eof:
				                         return;
			                         case markdown_types::inline_code:
				                         inline_code(token.content)
				                             .generate(sink);
				                         i += 1;
				                         break;
			                         case markdown_types::text:
				                         if (!(token.content.size() == 1 &&
				                               is_line_end(token.content[0])))
				                         {
					                         Si::html::text(token.content)
					                             .generate(sink);
				                         }
			                         }
			                         i += token.content.size();
		                         }
		                     });
}

auto compile(std::string source)
{
	return Si::html::dynamic([source =
	                              std::move(source)](Si::html::code_sink & sink)
	                         {
		                         auto i = source.begin();
		                         for (;;)
		                         {
			                         std::string paragraph =
			                             find_next_paragraph(i, source.end());
			                         if (paragraph.size() == 0)
			                         {
				                         return;
			                         }

			                         Si::html::tag("p",
			                                       compile_paragraph(paragraph))
			                             .generate(sink);
			                         i += paragraph.size();
		                         }

		                     });
}<|endoftext|>