<commit_before>// Copyright (c) 2013-2019 Feathercoin developers
// Copyright (c) 2011-2013 PPCoin developers
// Copyright (c) 2013 Primecoin developers
// Distributed under conditional MIT/X11 software license,
// see the accompanying file COPYING
//
// The synchronized checkpoint system is first developed by Sunny King for
// ppcoin network in 2012, giving cryptocurrency developers a tool to gain
// additional network protection against 51% attack.
//
// Primecoin also adopts this security mechanism, and the enforcement of
// checkpoints is explicitly granted by user, thus granting only temporary
// consensual central control to developer at the threats of 51% attack.
//
// Concepts
//
// In the network there can be a privileged node known as 'checkpoint master'.
// This node can send out checkpoint messages signed by the checkpoint master
// key. Each checkpoint is a block hash, representing a block on the blockchain
// that the network should reach consensus on.
//
// Besides verifying signatures of checkpoint messages, each node also verifies
// the consistency of the checkpoints. If a conflicting checkpoint is received,
// it means either the checkpoint master key is compromised, or there is an
// operator mistake. In this situation the node would discard the conflicting
// checkpoint message and display a warning message. This precaution controls
// the damage to network caused by operator mistake or compromised key.
//
// Operations
//
// Any node can be turned into checkpoint master by setting the 'checkpointkey'
// configuration parameter with the private key of the checkpoint master key.
// Operator should exercise caution such that at any moment there is at most
// one node operating as checkpoint master. When switching master node, the
// recommended procedure is to shutdown the master node and restart as
// regular node, note down the current checkpoint by 'getcheckpoint', then
// compare to the checkpoint at the new node to be upgraded to master node.
// When the checkpoint on both nodes match then it is safe to switch the new
// node to checkpoint master.
//
// The configuration parameter 'checkpointdepth' specifies how many blocks
// should the checkpoints lag behind the latest block in auto checkpoint mode.
// A depth of 5 is the minimum auto checkpoint policy and offers the greatest
// protection against 51% attack.
//

#include <checkpointsync.h>

#include <chainparams.h>
#include <key_io.h>
#include <logging.h>
#include <netmessagemaker.h>
#include <txdb.h>
#include <validation.h>

// Synchronized checkpoint (centrally broadcasted)
std::string CSyncCheckpoint::strMasterPrivKey;
uint256 hashSyncCheckpoint;
static uint256 hashPendingCheckpoint;
CSyncCheckpoint checkpointMessage;
static CSyncCheckpoint checkpointMessagePending;

// Only descendant of current sync-checkpoint is allowed
bool ValidateSyncCheckpoint(uint256 hashCheckpoint)
{
    CBlockIndex* pindexSyncCheckpoint;
    CBlockIndex* pindexCheckpointRecv;

    {
        LOCK(cs_main);

        if (!::BlockIndex().count(hashSyncCheckpoint))
            return error("%s: block index missing for current sync-checkpoint %s", __func__, hashSyncCheckpoint.ToString());
        if (!::BlockIndex().count(hashCheckpoint))
            return error("%s: block index missing for received sync-checkpoint %s", __func__, hashCheckpoint.ToString());

        pindexSyncCheckpoint = ::BlockIndex()[hashSyncCheckpoint];
        pindexCheckpointRecv = ::BlockIndex()[hashCheckpoint];
    }

    if (pindexCheckpointRecv->nHeight <= pindexSyncCheckpoint->nHeight)
    {
        // Received an older checkpoint, trace back from current checkpoint
        // to the same height of the received checkpoint to verify
        // that current checkpoint should be a descendant block
        CBlockIndex* pindex = pindexSyncCheckpoint;
        while (pindex->nHeight > pindexCheckpointRecv->nHeight)
            if (!(pindex = pindex->pprev))
                return error("%s: pprev1 null - block index structure failure", __func__);
        if (pindex->GetBlockHash() != hashCheckpoint)
        {
            return error("%s: new sync-checkpoint %s is conflicting with current sync-checkpoint %s", __func__, hashCheckpoint.ToString(), hashSyncCheckpoint.ToString());
        }
        return false; // ignore older checkpoint
    }

    // Received checkpoint should be a descendant block of the current
    // checkpoint. Trace back to the same height of current checkpoint
    // to verify.
    CBlockIndex* pindex = pindexCheckpointRecv;
    while (pindex->nHeight > pindexSyncCheckpoint->nHeight)
        if (!(pindex = pindex->pprev))
            return error("%s: pprev2 null - block index structure failure", __func__);

    if (pindex->GetBlockHash() != hashSyncCheckpoint)
    {
        return error("%s: new sync-checkpoint %s is not a descendant of current sync-checkpoint %s", __func__, hashCheckpoint.ToString(), hashSyncCheckpoint.ToString());
    }
    return true;
}

bool WriteSyncCheckpoint(const uint256& hashCheckpoint)
{
    if (!pblocktree->WriteSyncCheckpoint(hashCheckpoint))
        return error("%s: failed to write to txdb sync checkpoint %s", __func__, hashCheckpoint.ToString());

    ::ChainstateActive().ForceFlushStateToDisk();
    hashSyncCheckpoint = hashCheckpoint;
    return true;
}

bool AcceptPendingSyncCheckpoint()
{
    LOCK(cs_main);
    bool havePendingCheckpoint = hashPendingCheckpoint != uint256() && ::BlockIndex().count(hashPendingCheckpoint);
    if (!havePendingCheckpoint)
        return false;

    if (!ValidateSyncCheckpoint(hashPendingCheckpoint))
    {
        hashPendingCheckpoint = uint256();
        checkpointMessagePending.SetNull();
        return false;
    }

    if (!::ChainActive().Contains(::BlockIndex()[hashPendingCheckpoint]))
        return false;

    if (!WriteSyncCheckpoint(hashPendingCheckpoint)) {
        return error("%s: failed to write sync checkpoint %s", __func__, hashPendingCheckpoint.ToString());
    }

    hashPendingCheckpoint = uint256();
    checkpointMessage = checkpointMessagePending;
    checkpointMessagePending.SetNull();

    // Relay the checkpoint
    if (g_connman && !checkpointMessage.IsNull())
    {
        g_connman->ForEachNode([](CNode* pnode) {
            if (pnode->supportACPMessages)
                checkpointMessage.RelayTo(pnode);
        });
    }

    return true;
}

// Automatically select a suitable sync-checkpoint
uint256 AutoSelectSyncCheckpoint()
{
    // Search backward for a block with specified depth policy
    const CBlockIndex *pindex = ::ChainActive().Tip();
    while (pindex->pprev && pindex->nHeight + gArgs.GetArg("-checkpointdepth", DEFAULT_AUTOCHECKPOINT) > ::ChainActive().Tip()->nHeight)
        pindex = pindex->pprev;
    return pindex->GetBlockHash();
}

// Check against synchronized checkpoint
bool CheckSyncCheckpoint(const uint256 hashBlock, const int nHeight)
{
    LOCK(cs_main);

    // Genesis block
    if (nHeight == 0) {
        return true;
    }

    // Checkpoint on default
    if (hashSyncCheckpoint == uint256()) {
        return true;
    }

    // sync-checkpoint should always be accepted block
    assert(::BlockIndex().count(hashSyncCheckpoint));
    const CBlockIndex* pindexSync = ::BlockIndex()[hashSyncCheckpoint];

    if (nHeight > pindexSync->nHeight)
    {
        // Trace back to same height as sync-checkpoint
        const CBlockIndex* pindex = ::ChainActive().Tip();
        while (pindex->nHeight > pindexSync->nHeight)
            if (!(pindex = pindex->pprev))
                return error("%s: pprev null - block index structure failure", __func__);
        if (pindex->nHeight < pindexSync->nHeight || pindex->GetBlockHash() != hashSyncCheckpoint)
            return false; // only descendant of sync-checkpoint can pass check
    }
    if (nHeight == pindexSync->nHeight && hashBlock != hashSyncCheckpoint)
        return error("%s: Same height with sync-checkpoint", __func__);
    if (nHeight < pindexSync->nHeight && !::BlockIndex().count(hashBlock))
        return error("%s: Lower height than sync-checkpoint", __func__);
    return true;
}

// Reset synchronized checkpoint to the genesis block
bool ResetSyncCheckpoint()
{
    LOCK(cs_main);

    if (!WriteSyncCheckpoint(Params().GetConsensus().hashGenesisBlock))
        return error("%s: failed to reset sync checkpoint to genesis block", __func__);

    return true;
}

// Verify sync checkpoint master pubkey and reset sync checkpoint if changed
bool CheckCheckpointPubKey()
{
    std::string strPubKey = "";
    std::string strMasterPubKey = Params().GetConsensus().checkpointPubKey;

    if (!pblocktree->ReadCheckpointPubKey(strPubKey) || strPubKey != strMasterPubKey)
    {
        // write checkpoint master key to db
        if (!ResetSyncCheckpoint())
            return error("%s: failed to reset sync-checkpoint", __func__);
        if (!pblocktree->WriteCheckpointPubKey(strMasterPubKey))
            return error("%s: failed to write new checkpoint master key to db", __func__);
        ::ChainstateActive().ForceFlushStateToDisk();
    }

    return true;
}

bool SetCheckpointPrivKey(std::string strPrivKey)
{
    CKey key = DecodeSecret(strPrivKey);
    if (!key.IsValid())
        return false;

    CSyncCheckpoint::strMasterPrivKey = strPrivKey;
    return true;
}

bool SendSyncCheckpoint(uint256 hashCheckpoint)
{
    // P2P disabled
    if (!g_connman)
        return true;

    // No connections
    if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
        return true;

    // Do not send dummy checkpoint
    if (hashCheckpoint == uint256())
        return true;

    CSyncCheckpoint checkpoint;
    checkpoint.hashCheckpoint = hashCheckpoint;
    CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION);
    sMsg << static_cast<CUnsignedSyncCheckpoint>(checkpoint);
    checkpoint.vchMsg = std::vector<unsigned char>(sMsg.begin(), sMsg.end());

    if (CSyncCheckpoint::strMasterPrivKey.empty())
        return error("%s: Checkpoint master key unavailable.", __func__);

    CKey key = DecodeSecret(CSyncCheckpoint::strMasterPrivKey);
    if (!key.IsValid())
        return error("%s: Checkpoint master key invalid", __func__);

    if (!key.Sign(Hash(checkpoint.vchMsg.begin(), checkpoint.vchMsg.end()), checkpoint.vchSig))
        return error("%s: Unable to sign checkpoint, check private key?", __func__);

    if(!checkpoint.ProcessSyncCheckpoint())
        return error("%s: Failed to process checkpoint.", __func__);

    // Relay checkpoint
    g_connman->ForEachNode([checkpoint](CNode* pnode) {
        checkpoint.RelayTo(pnode);
    });

    return true;
}

void CUnsignedSyncCheckpoint::SetNull()
{
    nVersion = 1;
    hashCheckpoint = uint256();
}

std::string CUnsignedSyncCheckpoint::ToString() const
{
    return strprintf(
            "CSyncCheckpoint(\n"
            "    nVersion       = %d\n"
            "    hashCheckpoint = %s\n"
            ")\n",
        nVersion,
        hashCheckpoint.ToString());
}

CSyncCheckpoint::CSyncCheckpoint()
{
    SetNull();
}

void CSyncCheckpoint::SetNull()
{
    CUnsignedSyncCheckpoint::SetNull();
    vchMsg.clear();
    vchSig.clear();
}

bool CSyncCheckpoint::IsNull() const
{
    return (hashCheckpoint == uint256());
}

uint256 CSyncCheckpoint::GetHash() const
{
    return Hash(this->vchMsg.begin(), this->vchMsg.end());
}

void CSyncCheckpoint::RelayTo(CNode* pfrom) const
{
    if (g_connman && pfrom->hashCheckpointKnown != hashCheckpoint && pfrom->supportACPMessages)
    {
        pfrom->hashCheckpointKnown = hashCheckpoint;
        g_connman->PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::CHECKPOINT, *this));
    }
}

// Verify signature of sync-checkpoint message
bool CSyncCheckpoint::CheckSignature()
{
    std::string strMasterPubKey = Params().GetConsensus().checkpointPubKey;
    CPubKey key(ParseHex(strMasterPubKey));
    if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
        return error("%s: verify signature failed", __func__);

    // Now unserialize the data
    CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
    sMsg >> *static_cast<CUnsignedSyncCheckpoint*>(this);
    return true;
}

// Process synchronized checkpoint
bool CSyncCheckpoint::ProcessSyncCheckpoint()
{
    if (!CheckSignature())
        return false;

    LOCK(cs_main);

    if (!::BlockIndex().count(hashCheckpoint) || !::ChainActive().Contains(::BlockIndex()[hashCheckpoint]))
    {
        // We haven't received the checkpoint chain, keep the checkpoint as pending
        hashPendingCheckpoint = hashCheckpoint;
        checkpointMessagePending = *this;
        LogPrintf("%s: pending for sync-checkpoint %s\n", __func__, hashCheckpoint.ToString());

        return false;
    }

    if (!ValidateSyncCheckpoint(hashCheckpoint))
        return false;

    if (!WriteSyncCheckpoint(hashCheckpoint)) {
        return error("%s: failed to write sync checkpoint %s\n", __func__, hashCheckpoint.ToString());
    }

    checkpointMessage = *this;
    hashPendingCheckpoint = uint256();
    checkpointMessagePending.SetNull();

    return true;
}
<commit_msg>Checkpoint sync do not force flush to disk<commit_after>// Copyright (c) 2013-2019 Feathercoin developers
// Copyright (c) 2011-2013 PPCoin developers
// Copyright (c) 2013 Primecoin developers
// Distributed under conditional MIT/X11 software license,
// see the accompanying file COPYING
//
// The synchronized checkpoint system is first developed by Sunny King for
// ppcoin network in 2012, giving cryptocurrency developers a tool to gain
// additional network protection against 51% attack.
//
// Primecoin also adopts this security mechanism, and the enforcement of
// checkpoints is explicitly granted by user, thus granting only temporary
// consensual central control to developer at the threats of 51% attack.
//
// Concepts
//
// In the network there can be a privileged node known as 'checkpoint master'.
// This node can send out checkpoint messages signed by the checkpoint master
// key. Each checkpoint is a block hash, representing a block on the blockchain
// that the network should reach consensus on.
//
// Besides verifying signatures of checkpoint messages, each node also verifies
// the consistency of the checkpoints. If a conflicting checkpoint is received,
// it means either the checkpoint master key is compromised, or there is an
// operator mistake. In this situation the node would discard the conflicting
// checkpoint message and display a warning message. This precaution controls
// the damage to network caused by operator mistake or compromised key.
//
// Operations
//
// Any node can be turned into checkpoint master by setting the 'checkpointkey'
// configuration parameter with the private key of the checkpoint master key.
// Operator should exercise caution such that at any moment there is at most
// one node operating as checkpoint master. When switching master node, the
// recommended procedure is to shutdown the master node and restart as
// regular node, note down the current checkpoint by 'getcheckpoint', then
// compare to the checkpoint at the new node to be upgraded to master node.
// When the checkpoint on both nodes match then it is safe to switch the new
// node to checkpoint master.
//
// The configuration parameter 'checkpointdepth' specifies how many blocks
// should the checkpoints lag behind the latest block in auto checkpoint mode.
// A depth of 5 is the minimum auto checkpoint policy and offers the greatest
// protection against 51% attack.
//

#include <checkpointsync.h>

#include <chainparams.h>
#include <key_io.h>
#include <logging.h>
#include <netmessagemaker.h>
#include <txdb.h>
#include <validation.h>

// Synchronized checkpoint (centrally broadcasted)
std::string CSyncCheckpoint::strMasterPrivKey;
uint256 hashSyncCheckpoint;
static uint256 hashPendingCheckpoint;
CSyncCheckpoint checkpointMessage;
static CSyncCheckpoint checkpointMessagePending;

// Only descendant of current sync-checkpoint is allowed
bool ValidateSyncCheckpoint(uint256 hashCheckpoint)
{
    CBlockIndex* pindexSyncCheckpoint;
    CBlockIndex* pindexCheckpointRecv;

    {
        LOCK(cs_main);

        if (!::BlockIndex().count(hashSyncCheckpoint))
            return error("%s: block index missing for current sync-checkpoint %s", __func__, hashSyncCheckpoint.ToString());
        if (!::BlockIndex().count(hashCheckpoint))
            return error("%s: block index missing for received sync-checkpoint %s", __func__, hashCheckpoint.ToString());

        pindexSyncCheckpoint = ::BlockIndex()[hashSyncCheckpoint];
        pindexCheckpointRecv = ::BlockIndex()[hashCheckpoint];
    }

    if (pindexCheckpointRecv->nHeight <= pindexSyncCheckpoint->nHeight)
    {
        // Received an older checkpoint, trace back from current checkpoint
        // to the same height of the received checkpoint to verify
        // that current checkpoint should be a descendant block
        CBlockIndex* pindex = pindexSyncCheckpoint;
        while (pindex->nHeight > pindexCheckpointRecv->nHeight)
            if (!(pindex = pindex->pprev))
                return error("%s: pprev1 null - block index structure failure", __func__);
        if (pindex->GetBlockHash() != hashCheckpoint)
        {
            return error("%s: new sync-checkpoint %s is conflicting with current sync-checkpoint %s", __func__, hashCheckpoint.ToString(), hashSyncCheckpoint.ToString());
        }
        return false; // ignore older checkpoint
    }

    // Received checkpoint should be a descendant block of the current
    // checkpoint. Trace back to the same height of current checkpoint
    // to verify.
    CBlockIndex* pindex = pindexCheckpointRecv;
    while (pindex->nHeight > pindexSyncCheckpoint->nHeight)
        if (!(pindex = pindex->pprev))
            return error("%s: pprev2 null - block index structure failure", __func__);

    if (pindex->GetBlockHash() != hashSyncCheckpoint)
    {
        return error("%s: new sync-checkpoint %s is not a descendant of current sync-checkpoint %s", __func__, hashCheckpoint.ToString(), hashSyncCheckpoint.ToString());
    }
    return true;
}

bool WriteSyncCheckpoint(const uint256& hashCheckpoint)
{
    if (!pblocktree->WriteSyncCheckpoint(hashCheckpoint))
        return error("%s: failed to write to txdb sync checkpoint %s", __func__, hashCheckpoint.ToString());

    hashSyncCheckpoint = hashCheckpoint;
    return true;
}

bool AcceptPendingSyncCheckpoint()
{
    LOCK(cs_main);
    bool havePendingCheckpoint = hashPendingCheckpoint != uint256() && ::BlockIndex().count(hashPendingCheckpoint);
    if (!havePendingCheckpoint)
        return false;

    if (!ValidateSyncCheckpoint(hashPendingCheckpoint))
    {
        hashPendingCheckpoint = uint256();
        checkpointMessagePending.SetNull();
        return false;
    }

    if (!::ChainActive().Contains(::BlockIndex()[hashPendingCheckpoint]))
        return false;

    if (!WriteSyncCheckpoint(hashPendingCheckpoint)) {
        return error("%s: failed to write sync checkpoint %s", __func__, hashPendingCheckpoint.ToString());
    }

    hashPendingCheckpoint = uint256();
    checkpointMessage = checkpointMessagePending;
    checkpointMessagePending.SetNull();

    // Relay the checkpoint
    if (g_connman && !checkpointMessage.IsNull())
    {
        g_connman->ForEachNode([](CNode* pnode) {
            if (pnode->supportACPMessages)
                checkpointMessage.RelayTo(pnode);
        });
    }

    return true;
}

// Automatically select a suitable sync-checkpoint
uint256 AutoSelectSyncCheckpoint()
{
    // Search backward for a block with specified depth policy
    const CBlockIndex *pindex = ::ChainActive().Tip();
    while (pindex->pprev && pindex->nHeight + gArgs.GetArg("-checkpointdepth", DEFAULT_AUTOCHECKPOINT) > ::ChainActive().Tip()->nHeight)
        pindex = pindex->pprev;
    return pindex->GetBlockHash();
}

// Check against synchronized checkpoint
bool CheckSyncCheckpoint(const uint256 hashBlock, const int nHeight)
{
    LOCK(cs_main);

    // Genesis block
    if (nHeight == 0) {
        return true;
    }

    // Checkpoint on default
    if (hashSyncCheckpoint == uint256()) {
        return true;
    }

    // sync-checkpoint should always be accepted block
    assert(::BlockIndex().count(hashSyncCheckpoint));
    const CBlockIndex* pindexSync = ::BlockIndex()[hashSyncCheckpoint];

    if (nHeight > pindexSync->nHeight)
    {
        // Trace back to same height as sync-checkpoint
        const CBlockIndex* pindex = ::ChainActive().Tip();
        while (pindex->nHeight > pindexSync->nHeight)
            if (!(pindex = pindex->pprev))
                return error("%s: pprev null - block index structure failure", __func__);
        if (pindex->nHeight < pindexSync->nHeight || pindex->GetBlockHash() != hashSyncCheckpoint)
            return false; // only descendant of sync-checkpoint can pass check
    }
    if (nHeight == pindexSync->nHeight && hashBlock != hashSyncCheckpoint)
        return error("%s: Same height with sync-checkpoint", __func__);
    if (nHeight < pindexSync->nHeight && !::BlockIndex().count(hashBlock))
        return error("%s: Lower height than sync-checkpoint", __func__);
    return true;
}

// Reset synchronized checkpoint to the genesis block
bool ResetSyncCheckpoint()
{
    LOCK(cs_main);

    if (!WriteSyncCheckpoint(Params().GetConsensus().hashGenesisBlock))
        return error("%s: failed to reset sync checkpoint to genesis block", __func__);

    return true;
}

// Verify sync checkpoint master pubkey and reset sync checkpoint if changed
bool CheckCheckpointPubKey()
{
    std::string strPubKey = "";
    std::string strMasterPubKey = Params().GetConsensus().checkpointPubKey;

    if (!pblocktree->ReadCheckpointPubKey(strPubKey) || strPubKey != strMasterPubKey)
    {
        // write checkpoint master key to db
        if (!ResetSyncCheckpoint())
            return error("%s: failed to reset sync-checkpoint", __func__);
        if (!pblocktree->WriteCheckpointPubKey(strMasterPubKey))
            return error("%s: failed to write new checkpoint master key to db", __func__);
    }

    return true;
}

bool SetCheckpointPrivKey(std::string strPrivKey)
{
    CKey key = DecodeSecret(strPrivKey);
    if (!key.IsValid())
        return false;

    CSyncCheckpoint::strMasterPrivKey = strPrivKey;
    return true;
}

bool SendSyncCheckpoint(uint256 hashCheckpoint)
{
    // P2P disabled
    if (!g_connman)
        return true;

    // No connections
    if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
        return true;

    // Do not send dummy checkpoint
    if (hashCheckpoint == uint256())
        return true;

    CSyncCheckpoint checkpoint;
    checkpoint.hashCheckpoint = hashCheckpoint;
    CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION);
    sMsg << static_cast<CUnsignedSyncCheckpoint>(checkpoint);
    checkpoint.vchMsg = std::vector<unsigned char>(sMsg.begin(), sMsg.end());

    if (CSyncCheckpoint::strMasterPrivKey.empty())
        return error("%s: Checkpoint master key unavailable.", __func__);

    CKey key = DecodeSecret(CSyncCheckpoint::strMasterPrivKey);
    if (!key.IsValid())
        return error("%s: Checkpoint master key invalid", __func__);

    if (!key.Sign(Hash(checkpoint.vchMsg.begin(), checkpoint.vchMsg.end()), checkpoint.vchSig))
        return error("%s: Unable to sign checkpoint, check private key?", __func__);

    if(!checkpoint.ProcessSyncCheckpoint())
        return error("%s: Failed to process checkpoint.", __func__);

    // Relay checkpoint
    g_connman->ForEachNode([checkpoint](CNode* pnode) {
        checkpoint.RelayTo(pnode);
    });

    return true;
}

void CUnsignedSyncCheckpoint::SetNull()
{
    nVersion = 1;
    hashCheckpoint = uint256();
}

std::string CUnsignedSyncCheckpoint::ToString() const
{
    return strprintf(
            "CSyncCheckpoint(\n"
            "    nVersion       = %d\n"
            "    hashCheckpoint = %s\n"
            ")\n",
        nVersion,
        hashCheckpoint.ToString());
}

CSyncCheckpoint::CSyncCheckpoint()
{
    SetNull();
}

void CSyncCheckpoint::SetNull()
{
    CUnsignedSyncCheckpoint::SetNull();
    vchMsg.clear();
    vchSig.clear();
}

bool CSyncCheckpoint::IsNull() const
{
    return (hashCheckpoint == uint256());
}

uint256 CSyncCheckpoint::GetHash() const
{
    return Hash(this->vchMsg.begin(), this->vchMsg.end());
}

void CSyncCheckpoint::RelayTo(CNode* pfrom) const
{
    if (g_connman && pfrom->hashCheckpointKnown != hashCheckpoint && pfrom->supportACPMessages)
    {
        pfrom->hashCheckpointKnown = hashCheckpoint;
        g_connman->PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::CHECKPOINT, *this));
    }
}

// Verify signature of sync-checkpoint message
bool CSyncCheckpoint::CheckSignature()
{
    std::string strMasterPubKey = Params().GetConsensus().checkpointPubKey;
    CPubKey key(ParseHex(strMasterPubKey));
    if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
        return error("%s: verify signature failed", __func__);

    // Now unserialize the data
    CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
    sMsg >> *static_cast<CUnsignedSyncCheckpoint*>(this);
    return true;
}

// Process synchronized checkpoint
bool CSyncCheckpoint::ProcessSyncCheckpoint()
{
    if (!CheckSignature())
        return false;

    LOCK(cs_main);

    if (!::BlockIndex().count(hashCheckpoint) || !::ChainActive().Contains(::BlockIndex()[hashCheckpoint]))
    {
        // We haven't received the checkpoint chain, keep the checkpoint as pending
        hashPendingCheckpoint = hashCheckpoint;
        checkpointMessagePending = *this;
        LogPrintf("%s: pending for sync-checkpoint %s\n", __func__, hashCheckpoint.ToString());

        return false;
    }

    if (!ValidateSyncCheckpoint(hashCheckpoint))
        return false;

    if (!WriteSyncCheckpoint(hashCheckpoint)) {
        return error("%s: failed to write sync checkpoint %s\n", __func__, hashCheckpoint.ToString());
    }

    checkpointMessage = *this;
    hashPendingCheckpoint = uint256();
    checkpointMessagePending.SetNull();

    return true;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: fuconcs.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-03-29 15:27:41 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "fuconcs.hxx"

#ifndef _SVDPAGV_HXX //autogen
#include <svx/svdpagv.hxx>
#endif

#pragma hdrstop

#include <svx/svxids.hrc>
#include <svx/dialogs.hrc>
#include <svx/dialmgr.hxx>

#include "app.hrc"
#ifndef _AEITEM_HXX //autogen
#include <svtools/aeitem.hxx>
#endif

#ifndef _SVX_XLNSTWIT_HXX //autogen
#include <svx/xlnstwit.hxx>
#endif
#ifndef _SVX_XLNEDWIT_HXX //autogen
#include <svx/xlnedwit.hxx>
#endif
#ifndef _SVX_XLNEDIT_HXX //autogen
#include <svx/xlnedit.hxx>
#endif
#ifndef _SVX_XLNSTIT_HXX //autogen
#include <svx/xlnstit.hxx>
#endif
#ifndef _SVX_XLNWTIT_HXX //autogen
#include <svx/xlnwtit.hxx>
#endif
#ifndef _SFXVIEWFRM_HXX //autogen
#include <sfx2/viewfrm.hxx>
#endif
#ifndef _SDTMFITM_HXX //autogen
#include <svx/sdtmfitm.hxx>
#endif
#ifndef _SXEKITM_HXX //autogen
#include <svx/sxekitm.hxx>
#endif
#ifndef _SDERITM_HXX //autogen
#include <svx/sderitm.hxx>
#endif
#ifndef _SFXDISPATCH_HXX //autogen
#include <sfx2/dispatch.hxx>
#endif
#ifndef _SVDOPATH_HXX //autogen
#include <svx/svdopath.hxx>
#endif
#ifndef _SVDOCIRC_HXX //autogen
#include <svx/svdocirc.hxx>
#endif
#ifndef _SFXINTITEM_HXX //autogen
#include <svtools/intitem.hxx>
#endif
#ifndef _SFXREQUEST_HXX //autogen
#include <sfx2/request.hxx>
#endif
#ifndef _EEITEMID_HXX
#include <svx/eeitemid.hxx>
#endif
#ifndef _SVX_ADJITEM_HXX
#include <svx/adjitem.hxx>
#endif
#ifndef _XTABLE_HXX
#include <svx/xtable.hxx>
#endif
#ifndef _SDASITM_HXX
#include <svx/sdasitm.hxx>
#endif
#ifndef _SVX_TBXCUSTOMSHAPES_HXX
#include <svx/tbxcustomshapes.hxx>
#endif
#ifndef _SVDOASHP_HXX
#include <svx/svdoashp.hxx>
#endif
#ifndef _SDTAGITM_HXX
#include <svx/sdtagitm.hxx>
#endif

// #88751#
#ifndef _SVDCAPT_HXX
#include <svx/svdocapt.hxx>
#endif

// #97016#
#ifndef _SVDOMEAS_HXX
#include <svx/svdomeas.hxx>
#endif

#ifndef SD_VIEW_SHELL_HXX
#include "ViewShell.hxx"
#endif
#ifndef SD_OBJECT_BAR_MANAGER_HXX
#include "ObjectBarManager.hxx"
#endif
// #109583#
#ifndef _SVX_WRITINGMODEITEM_HXX
#include <svx/writingmodeitem.hxx>
#endif
#ifndef _GALLERY_HXX_
#include <svx/gallery.hxx>
#endif
#ifndef _SFXITEMPOOL_HXX
#include <svtools/itempool.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#include "sdresid.hxx"
#ifndef SD_VIEW_HXX
#include "View.hxx"
#endif
#include "sdpage.hxx"
#ifndef SD_WINDOW_HXX
#include "Window.hxx"
#endif
#include "stlpool.hxx"
#include "drawdoc.hxx"
#include "res_bmp.hrc"
#include "glob.hrc"

namespace sd {

TYPEINIT1( FuConstructCustomShape, FuConstruct );

/*************************************************************************
|*
|* Konstruktor
|*
\************************************************************************/

FuConstructCustomShape::FuConstructCustomShape (
        ViewShell*          pViewSh,
        ::sd::Window*       pWin,
        ::sd::View*         pView,
        SdDrawDocument*     pDoc,
        SfxRequest&         rReq ) :
    FuConstruct(pViewSh, pWin, pView, pDoc, rReq)
{
    const SfxItemSet* pArgs = rReq.GetArgs();
    if ( pArgs )
    {
        const SfxStringItem& rItm = (const SfxStringItem&)pArgs->Get( rReq.GetSlot() );
        aCustomShape = rItm.GetValue();
    }
    pViewShell->GetObjectBarManager().SwitchObjectBar( RID_DRAW_OBJ_TOOLBOX );
}

/*************************************************************************
|*
|* Destruktor
|*
\************************************************************************/

FuConstructCustomShape::~FuConstructCustomShape()
{
}

/*************************************************************************
|*
|* MouseButtonDown-event
|*
\************************************************************************/

BOOL FuConstructCustomShape::MouseButtonDown(const MouseEvent& rMEvt)
{
    BOOL bReturn = FuConstruct::MouseButtonDown(rMEvt);

    if ( rMEvt.IsLeft() && !pView->IsAction() )
    {
        Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );

        pWindow->CaptureMouse();
        USHORT nDrgLog = USHORT ( pWindow->PixelToLogic(Size(DRGPIX,0)).Width() );

        pView->BegCreateObj(aPnt, (OutputDevice*) NULL, nDrgLog);

        SdrObject* pObj = pView->GetCreateObj();
        if ( pObj )
        {
            SetAttributes( pObj );
            sal_Bool bForceFillStyle = sal_True;
            sal_Bool bForceNoFillStyle = sal_False;
            if ( ((SdrObjCustomShape*)pObj)->UseNoFillStyle() )
            {
                bForceFillStyle = sal_False;
                bForceNoFillStyle = sal_True;
            }
            SfxItemSet aAttr(pDoc->GetPool());
            SetStyleSheet( aAttr, pObj, bForceFillStyle, bForceNoFillStyle );
            pObj->SetMergedItemSet(aAttr);
        }
    }

    return bReturn;
}

/*************************************************************************
|*
|* MouseMove-event
|*
\************************************************************************/

BOOL FuConstructCustomShape::MouseMove(const MouseEvent& rMEvt)
{
    return FuConstruct::MouseMove(rMEvt);
}

/*************************************************************************
|*
|* MouseButtonUp-event
|*
\************************************************************************/

BOOL FuConstructCustomShape::MouseButtonUp(const MouseEvent& rMEvt)
{
    sal_Bool bReturn(sal_False);

    if(pView->IsCreateObj() && rMEvt.IsLeft())
    {
        SdrObject* pObj = pView->GetCreateObj();
        if( pObj && pView->EndCreateObj( SDRCREATE_FORCEEND ) )
        {
            bReturn = sal_True;
        }
    }
    bReturn = FuConstruct::MouseButtonUp (rMEvt) || bReturn;

    if (!bPermanent)
        pViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SFX_CALLMODE_ASYNCHRON);

    return bReturn;
}

/*************************************************************************
|*
|* Tastaturereignisse bearbeiten
|*
|* Wird ein KeyEvent bearbeitet, so ist der Return-Wert TRUE, andernfalls
|* FALSE.
|*
\************************************************************************/

BOOL FuConstructCustomShape::KeyInput(const KeyEvent& rKEvt)
{
    BOOL bReturn = FuConstruct::KeyInput(rKEvt);
    return(bReturn);
}

/*************************************************************************
|*
|* Function aktivieren
|*
\************************************************************************/

void FuConstructCustomShape::Activate()
{
    pView->SetCurrentObj( OBJ_CUSTOMSHAPE );
    FuConstruct::Activate();
}

/*************************************************************************
|*
|* Attribute fuer das zu erzeugende Objekt setzen
|*
\************************************************************************/

void FuConstructCustomShape::SetAttributes( SdrObject* pObj )
{
    sal_Bool bAttributesAppliedFromGallery = sal_False;

    if ( GalleryExplorer::GetSdrObjCount( GALLERY_THEME_POWERPOINT ) )
    {
        std::vector< rtl::OUString > aObjList;
        if ( GalleryExplorer::FillObjListTitle( GALLERY_THEME_POWERPOINT, aObjList ) )
        {
            sal_uInt16 i;
            for ( i = 0; i < aObjList.size(); i++ )
            {
                if ( aObjList[ i ].equalsIgnoreAsciiCase( aCustomShape ) )
                {
                    FmFormModel aFormModel;
                    SfxItemPool& rPool = aFormModel.GetItemPool();
                    rPool.FreezeIdRanges();
                    if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT, i, &aFormModel ) )
                    {
                        const SdrObject* pSourceObj = aFormModel.GetPage( 0 )->GetObj( 0 );
                        if( pSourceObj )
                        {
                            const SfxItemSet& rSource = pSourceObj->GetMergedItemSet();
                            SfxItemSet aDest( pObj->GetModel()->GetItemPool(),              // ranges from SdrAttrObj
                            SDRATTR_START, SDRATTR_SHADOW_LAST,
                            SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
                            SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION,
                            // Graphic Attributes
                            SDRATTR_GRAF_FIRST, SDRATTR_GRAF_LAST,
                            // 3d Properties
                            SDRATTR_3D_FIRST, SDRATTR_3D_LAST,
                            // CustomShape properties
                            SDRATTR_CUSTOMSHAPE_FIRST, SDRATTR_CUSTOMSHAPE_LAST,
                            // range from SdrTextObj
                            EE_ITEMS_START, EE_ITEMS_END,
                            // end
                            0, 0);
                            aDest.Set( rSource );
                            pObj->SetMergedItemSet( aDest );
                            sal_Int32 nAngle = pSourceObj->GetRotateAngle();
                            if ( nAngle )
                            {
                                double a = nAngle * F_PI18000;
                                pObj->NbcRotate( pObj->GetSnapRect().Center(), nAngle, sin( a ), cos( a ) );
                            }
                            bAttributesAppliedFromGallery = sal_True;

/*
                            com::sun::star::uno::Any aAny;
                            if ( ((SdrCustomShapeGeometryItem&)pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY )).QueryValue( aAny ) )
                            {
                                aGeometryItem.PutValue( aAny );
                                pObj->SetMergedItem( aGeometryItem );
                                bAttributesAppliedFromGallery = sal_True;
                            }
*/
                        }
                    }
                    break;
                }
            }
        }
    }
    if ( !bAttributesAppliedFromGallery )
    {
        pObj->SetMergedItem( SvxAdjustItem( SVX_ADJUST_CENTER ) );
        pObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) );
        pObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) );
        pObj->SetMergedItem( SdrTextAutoGrowHeightItem( sal_False ) );
        ((SdrObjCustomShape*)pObj)->MergeDefaultAttributes( &aCustomShape );
    }
}

// #97016#
SdrObject* FuConstructCustomShape::CreateDefaultObject(const sal_uInt16 nID, const Rectangle& rRectangle)
{
    SdrObject* pObj = SdrObjFactory::MakeNewObject(
        pView->GetCurrentObjInventor(), pView->GetCurrentObjIdentifier(),
        0L, pDoc);

    if( pObj )
    {
        Rectangle aRect( rRectangle );
        if ( doConstructOrthogonal() )
            ImpForceQuadratic( aRect );
        pObj->SetLogicRect( aRect );
        SetAttributes( pObj );
        SfxItemSet aAttr(pDoc->GetPool());
        SetStyleSheet(aAttr, pObj);
        pObj->SetMergedItemSet(aAttr);
    }
    return pObj;
}

// #i33136#
bool FuConstructCustomShape::doConstructOrthogonal() const
{
    return SdrObjCustomShape::doConstructOrthogonal(aCustomShape);
}

} // end of namespace sd
<commit_msg>INTEGRATION: CWS sj21 (1.7.92); FILE MERGED 2005/06/24 14:47:54 sj 1.7.92.1: #i50423# fixed crash if inserting customshapes (ReadOnly of the gallery theme may not been set though the file can't be written (because of security reasons))<commit_after>/*************************************************************************
 *
 *  $RCSfile: fuconcs.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: kz $ $Date: 2005-07-12 13:28:41 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "fuconcs.hxx"

#ifndef _SVDPAGV_HXX //autogen
#include <svx/svdpagv.hxx>
#endif

#pragma hdrstop

#include <svx/svxids.hrc>
#include <svx/dialogs.hrc>
#include <svx/dialmgr.hxx>

#include "app.hrc"
#ifndef _AEITEM_HXX //autogen
#include <svtools/aeitem.hxx>
#endif

#ifndef _SVX_XLNSTWIT_HXX //autogen
#include <svx/xlnstwit.hxx>
#endif
#ifndef _SVX_XLNEDWIT_HXX //autogen
#include <svx/xlnedwit.hxx>
#endif
#ifndef _SVX_XLNEDIT_HXX //autogen
#include <svx/xlnedit.hxx>
#endif
#ifndef _SVX_XLNSTIT_HXX //autogen
#include <svx/xlnstit.hxx>
#endif
#ifndef _SVX_XLNWTIT_HXX //autogen
#include <svx/xlnwtit.hxx>
#endif
#ifndef _SFXVIEWFRM_HXX //autogen
#include <sfx2/viewfrm.hxx>
#endif
#ifndef _SDTMFITM_HXX //autogen
#include <svx/sdtmfitm.hxx>
#endif
#ifndef _SXEKITM_HXX //autogen
#include <svx/sxekitm.hxx>
#endif
#ifndef _SDERITM_HXX //autogen
#include <svx/sderitm.hxx>
#endif
#ifndef _SFXDISPATCH_HXX //autogen
#include <sfx2/dispatch.hxx>
#endif
#ifndef _SVDOPATH_HXX //autogen
#include <svx/svdopath.hxx>
#endif
#ifndef _SVDOCIRC_HXX //autogen
#include <svx/svdocirc.hxx>
#endif
#ifndef _SFXINTITEM_HXX //autogen
#include <svtools/intitem.hxx>
#endif
#ifndef _SFXREQUEST_HXX //autogen
#include <sfx2/request.hxx>
#endif
#ifndef _EEITEMID_HXX
#include <svx/eeitemid.hxx>
#endif
#ifndef _SVX_ADJITEM_HXX
#include <svx/adjitem.hxx>
#endif
#ifndef _XTABLE_HXX
#include <svx/xtable.hxx>
#endif
#ifndef _SDASITM_HXX
#include <svx/sdasitm.hxx>
#endif
#ifndef _SVX_TBXCUSTOMSHAPES_HXX
#include <svx/tbxcustomshapes.hxx>
#endif
#ifndef _SVDOASHP_HXX
#include <svx/svdoashp.hxx>
#endif
#ifndef _SDTAGITM_HXX
#include <svx/sdtagitm.hxx>
#endif

// #88751#
#ifndef _SVDCAPT_HXX
#include <svx/svdocapt.hxx>
#endif

// #97016#
#ifndef _SVDOMEAS_HXX
#include <svx/svdomeas.hxx>
#endif

#ifndef SD_VIEW_SHELL_HXX
#include "ViewShell.hxx"
#endif
#ifndef SD_OBJECT_BAR_MANAGER_HXX
#include "ObjectBarManager.hxx"
#endif
// #109583#
#ifndef _SVX_WRITINGMODEITEM_HXX
#include <svx/writingmodeitem.hxx>
#endif
#ifndef _GALLERY_HXX_
#include <svx/gallery.hxx>
#endif
#ifndef _SFXITEMPOOL_HXX
#include <svtools/itempool.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#include "sdresid.hxx"
#ifndef SD_VIEW_HXX
#include "View.hxx"
#endif
#include "sdpage.hxx"
#ifndef SD_WINDOW_HXX
#include "Window.hxx"
#endif
#include "stlpool.hxx"
#include "drawdoc.hxx"
#include "res_bmp.hrc"
#include "glob.hrc"

namespace sd {

TYPEINIT1( FuConstructCustomShape, FuConstruct );

/*************************************************************************
|*
|* Konstruktor
|*
\************************************************************************/

FuConstructCustomShape::FuConstructCustomShape (
        ViewShell*          pViewSh,
        ::sd::Window*       pWin,
        ::sd::View*         pView,
        SdDrawDocument*     pDoc,
        SfxRequest&         rReq ) :
    FuConstruct(pViewSh, pWin, pView, pDoc, rReq)
{
    const SfxItemSet* pArgs = rReq.GetArgs();
    if ( pArgs )
    {
        const SfxStringItem& rItm = (const SfxStringItem&)pArgs->Get( rReq.GetSlot() );
        aCustomShape = rItm.GetValue();
    }
    pViewShell->GetObjectBarManager().SwitchObjectBar( RID_DRAW_OBJ_TOOLBOX );
}

/*************************************************************************
|*
|* Destruktor
|*
\************************************************************************/

FuConstructCustomShape::~FuConstructCustomShape()
{
}

/*************************************************************************
|*
|* MouseButtonDown-event
|*
\************************************************************************/

BOOL FuConstructCustomShape::MouseButtonDown(const MouseEvent& rMEvt)
{
    BOOL bReturn = FuConstruct::MouseButtonDown(rMEvt);

    if ( rMEvt.IsLeft() && !pView->IsAction() )
    {
        Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );

        pWindow->CaptureMouse();
        USHORT nDrgLog = USHORT ( pWindow->PixelToLogic(Size(DRGPIX,0)).Width() );

        pView->BegCreateObj(aPnt, (OutputDevice*) NULL, nDrgLog);

        SdrObject* pObj = pView->GetCreateObj();
        if ( pObj )
        {
            SetAttributes( pObj );
            sal_Bool bForceFillStyle = sal_True;
            sal_Bool bForceNoFillStyle = sal_False;
            if ( ((SdrObjCustomShape*)pObj)->UseNoFillStyle() )
            {
                bForceFillStyle = sal_False;
                bForceNoFillStyle = sal_True;
            }
            SfxItemSet aAttr(pDoc->GetPool());
            SetStyleSheet( aAttr, pObj, bForceFillStyle, bForceNoFillStyle );
            pObj->SetMergedItemSet(aAttr);
        }
    }

    return bReturn;
}

/*************************************************************************
|*
|* MouseMove-event
|*
\************************************************************************/

BOOL FuConstructCustomShape::MouseMove(const MouseEvent& rMEvt)
{
    return FuConstruct::MouseMove(rMEvt);
}

/*************************************************************************
|*
|* MouseButtonUp-event
|*
\************************************************************************/

BOOL FuConstructCustomShape::MouseButtonUp(const MouseEvent& rMEvt)
{
    sal_Bool bReturn(sal_False);

    if(pView->IsCreateObj() && rMEvt.IsLeft())
    {
        SdrObject* pObj = pView->GetCreateObj();
        if( pObj && pView->EndCreateObj( SDRCREATE_FORCEEND ) )
        {
            bReturn = sal_True;
        }
    }
    bReturn = FuConstruct::MouseButtonUp (rMEvt) || bReturn;

    if (!bPermanent)
        pViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SFX_CALLMODE_ASYNCHRON);

    return bReturn;
}

/*************************************************************************
|*
|* Tastaturereignisse bearbeiten
|*
|* Wird ein KeyEvent bearbeitet, so ist der Return-Wert TRUE, andernfalls
|* FALSE.
|*
\************************************************************************/

BOOL FuConstructCustomShape::KeyInput(const KeyEvent& rKEvt)
{
    BOOL bReturn = FuConstruct::KeyInput(rKEvt);
    return(bReturn);
}

/*************************************************************************
|*
|* Function aktivieren
|*
\************************************************************************/

void FuConstructCustomShape::Activate()
{
    pView->SetCurrentObj( OBJ_CUSTOMSHAPE );
    FuConstruct::Activate();
}

/*************************************************************************
|*
|* Attribute fuer das zu erzeugende Objekt setzen
|*
\************************************************************************/

void FuConstructCustomShape::SetAttributes( SdrObject* pObj )
{
    sal_Bool bAttributesAppliedFromGallery = sal_False;

    if ( GalleryExplorer::GetSdrObjCount( GALLERY_THEME_POWERPOINT ) )
    {
        std::vector< rtl::OUString > aObjList;
        if ( GalleryExplorer::FillObjListTitle( GALLERY_THEME_POWERPOINT, aObjList ) )
        {
            sal_uInt16 i;
            for ( i = 0; i < aObjList.size(); i++ )
            {
                if ( aObjList[ i ].equalsIgnoreAsciiCase( aCustomShape ) )
                {
                    FmFormModel aFormModel;
                    SfxItemPool& rPool = aFormModel.GetItemPool();
                    rPool.FreezeIdRanges();
                    if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT, i, &aFormModel ) )
                    {
                        const SdrPage* pPage = aFormModel.GetPage( 0 );
                        if ( pPage )
                        {
                            const SdrObject* pSourceObj = pPage->GetObj( 0 );
                            if( pSourceObj )
                            {
                                const SfxItemSet& rSource = pSourceObj->GetMergedItemSet();
                                SfxItemSet aDest( pObj->GetModel()->GetItemPool(),              // ranges from SdrAttrObj
                                SDRATTR_START, SDRATTR_SHADOW_LAST,
                                SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
                                SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION,
                                // Graphic Attributes
                                SDRATTR_GRAF_FIRST, SDRATTR_GRAF_LAST,
                                // 3d Properties
                                SDRATTR_3D_FIRST, SDRATTR_3D_LAST,
                                // CustomShape properties
                                SDRATTR_CUSTOMSHAPE_FIRST, SDRATTR_CUSTOMSHAPE_LAST,
                                // range from SdrTextObj
                                EE_ITEMS_START, EE_ITEMS_END,
                                // end
                                0, 0);
                                aDest.Set( rSource );
                                pObj->SetMergedItemSet( aDest );
                                sal_Int32 nAngle = pSourceObj->GetRotateAngle();
                                if ( nAngle )
                                {
                                    double a = nAngle * F_PI18000;
                                    pObj->NbcRotate( pObj->GetSnapRect().Center(), nAngle, sin( a ), cos( a ) );
                                }
                                bAttributesAppliedFromGallery = sal_True;

    /*
                                com::sun::star::uno::Any aAny;
                                if ( ((SdrCustomShapeGeometryItem&)pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY )).QueryValue( aAny ) )
                                {
                                    aGeometryItem.PutValue( aAny );
                                    pObj->SetMergedItem( aGeometryItem );
                                    bAttributesAppliedFromGallery = sal_True;
                                }
    */
                            }
                        }
                    }
                    break;
                }
            }
        }
    }
    if ( !bAttributesAppliedFromGallery )
    {
        pObj->SetMergedItem( SvxAdjustItem( SVX_ADJUST_CENTER ) );
        pObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) );
        pObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) );
        pObj->SetMergedItem( SdrTextAutoGrowHeightItem( sal_False ) );
        ((SdrObjCustomShape*)pObj)->MergeDefaultAttributes( &aCustomShape );
    }
}

// #97016#
SdrObject* FuConstructCustomShape::CreateDefaultObject(const sal_uInt16 nID, const Rectangle& rRectangle)
{
    SdrObject* pObj = SdrObjFactory::MakeNewObject(
        pView->GetCurrentObjInventor(), pView->GetCurrentObjIdentifier(),
        0L, pDoc);

    if( pObj )
    {
        Rectangle aRect( rRectangle );
        if ( doConstructOrthogonal() )
            ImpForceQuadratic( aRect );
        pObj->SetLogicRect( aRect );
        SetAttributes( pObj );
        SfxItemSet aAttr(pDoc->GetPool());
        SetStyleSheet(aAttr, pObj);
        pObj->SetMergedItemSet(aAttr);
    }
    return pObj;
}

// #i33136#
bool FuConstructCustomShape::doConstructOrthogonal() const
{
    return SdrObjCustomShape::doConstructOrthogonal(aCustomShape);
}

} // end of namespace sd
<|endoftext|>


<commit_before>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbWrapperApplicationFactory.h"

#include "otbMultiToMonoChannelExtractROI.h"
#include "otbGenericRSResampleImageFilter.h"
#include "otbBCOInterpolateImageFunction.h"
#include "otbSimpleRcsPanSharpeningFusionImageFilter.h"
#include "itkFixedArray.h"

// Elevation handler
#include "otbWrapperElevationParametersHandler.h"

#include "otbPleiadesPToXSAffineTransformCalculator.h"

namespace otb
{
namespace Wrapper
{
class BundleToPerfectSensor : public Application
{
public:
  /** Standard class typedefs. */
  typedef BundleToPerfectSensor         Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(BundleToPerfectSensor, otb::Application);

private:

  void DoInit()
  {
    SetName("BundleToPerfectSensor");
    SetDescription("Perform P+XS pansharpening");

    // Documentation
    SetDocName("Bundle to perfect sensor");
    SetDocLongDescription("This application performs P+XS pansharpening. The default mode use Pan and XS sensor models to estimate the transformation to superimpose XS over Pan before the fusion (\"default mode\"). The application provides also a PHR mode for Pleiades images which does not use sensor models as Pan and XS products are already coregistered but only estimate an affine transformation to superimpose XS over the Pan.Note that this option is automatically activated in case Pleiades images are detected as input.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");

    AddDocTag(Tags::Geometry);
    AddDocTag(Tags::Pansharpening);

    AddParameter(ParameterType_InputImage,   "inp",   "Input PAN Image");
    SetParameterDescription("inp"," Input panchromatic image.");
    AddParameter(ParameterType_InputImage,   "inxs",  "Input XS Image");
    SetParameterDescription("inxs"," Input XS image.");

    // Elevation
    ElevationParametersHandler::AddElevationParameters(this, "elev");

    // Superposition mode
    AddParameter(ParameterType_Choice,"mode", "Mode");
    SetParameterDescription("mode", "Superimposition mode");

    AddChoice("mode.default", "Default mode");
    SetParameterDescription("mode.default", "Default superimposition mode : "
      "uses any projection reference or sensor model found in the images");

    AddChoice("mode.phr", "Pleiades mode");
    SetParameterDescription("mode.phr", "Pleiades superimposition mode, "
      "designed for the case of a P+XS bundle in SENSOR geometry. It uses"
      " a simple transform on the XS image : a scaling and a residual "
      "translation.");

    AddParameter(ParameterType_Float,        "lms",   "Spacing of the deformation field");
    SetParameterDescription("lms"," Spacing of the deformation field. Default is 10 times the PAN image spacing.");
    AddParameter(ParameterType_OutputImage,  "out",   "Output image");
    SetParameterDescription("out"," Output image.");
    AddRAMParameter();

    MandatoryOff("lms");

    // Doc example parameter settings
    SetDocExampleParameterValue("inp", "QB_Toulouse_Ortho_PAN.tif");
    SetDocExampleParameterValue("inxs", "QB_Toulouse_Ortho_XS.tif");
    SetDocExampleParameterValue("out", "BundleToPerfectSensor.png uchar");

  }

  void DoUpdateParameters()
  {
    if(!HasUserValue("mode") && HasValue("inp") && HasValue("inxs") && otb::PleiadesPToXSAffineTransformCalculator::CanCompute(GetParameterImage("inp"),GetParameterImage("inxs")))
      {
      otbAppLogWARNING("Forcing PHR mode with PHR data. You need to add \"-mode default\" to force the default mode with PHR images.");
      SetParameterString("mode","phr");
      }
  }

  void DoExecute()
  {
    FloatVectorImageType* panchroV = GetParameterImage("inp");
    FloatVectorImageType* xs = GetParameterImage("inxs");

    if ( panchroV->GetNumberOfComponentsPerPixel() != 1 )
      {
      itkExceptionMacro(<< "The panchromatic image must be a single channel image")
      }

    // Transform the PAN image to otb::Image
    typedef otb::Image<FloatVectorImageType::InternalPixelType> FloatImageType;
    typedef otb::MultiToMonoChannelExtractROI<float,float> ExtractFilterType;

    ExtractFilterType::Pointer channelSelect = ExtractFilterType::New();
    m_Ref.push_back(channelSelect.GetPointer());
    channelSelect->SetChannel(1);
    channelSelect->SetInput(panchroV);
    channelSelect->UpdateOutputInformation();
    FloatImageType::Pointer panchro = channelSelect->GetOutput();

    typedef otb::BCOInterpolateImageFunction<FloatVectorImageType> InterpolatorType;
    typedef otb::GenericRSResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  ResamplerType;
    typedef otb::StreamingResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  BasicResamplerType;
    typedef otb::SimpleRcsPanSharpeningFusionImageFilter<FloatImageType, FloatVectorImageType, FloatVectorImageType> FusionFilterType;

    // Resample filter
    ResamplerType::Pointer    resampler = ResamplerType::New();
    m_Ref.push_back(resampler.GetPointer());

    BasicResamplerType::Pointer basicResampler = BasicResamplerType::New();
    m_Ref.push_back(basicResampler.GetPointer());

    InterpolatorType::Pointer interpolator = InterpolatorType::New();
    resampler->SetInterpolator(interpolator);
    basicResampler->SetInterpolator(interpolator);

    // Fusion filter
    FusionFilterType::Pointer  fusionFilter = FusionFilterType::New();
    m_Ref.push_back(fusionFilter.GetPointer());
    fusionFilter->SetPanInput(panchro);

    // Setup the DEM Handler
    otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev");

    // Set up output image informations
    FloatVectorImageType::SpacingType spacing = panchro->GetSpacing();
    FloatVectorImageType::IndexType   start = panchro->GetLargestPossibleRegion().GetIndex();
    FloatVectorImageType::SizeType    size = panchro->GetLargestPossibleRegion().GetSize();
    FloatVectorImageType::PointType   origin = panchro->GetOrigin();

    FloatVectorImageType::PixelType defaultValue;
    itk::NumericTraits<FloatVectorImageType::PixelType>::SetLength(defaultValue, xs->GetNumberOfComponentsPerPixel());

    if(GetParameterString("mode") == "default")
      {
      otbAppLogINFO("Using the default mode");
      if(IsParameterEnabled("lms") && HasValue("lms"))
        {
        double defScalarSpacing = GetParameterFloat("lms");
        otbAppLogINFO(<< "Generating coarse deformation field (spacing="<<defScalarSpacing<<")" << std::endl);
        FloatVectorImageType::SpacingType defSpacing;

        defSpacing[0] = defScalarSpacing;
        defSpacing[1] = defScalarSpacing;

        resampler->SetDisplacementFieldSpacing(defSpacing);
        }
      else
        {
        FloatVectorImageType::SpacingType defSpacing;
        defSpacing[0]=10*spacing[0];
        defSpacing[1]=10*spacing[1];
        resampler->SetDisplacementFieldSpacing(defSpacing);
        }

      resampler->SetInput(xs);
      resampler->SetOutputOrigin(origin);
      resampler->SetOutputSpacing(spacing);
      resampler->SetOutputSize(size);
      resampler->SetOutputStartIndex(start);
      resampler->SetOutputKeywordList(panchro->GetImageKeywordlist());
      resampler->SetOutputProjectionRef(panchro->GetProjectionRef());
      resampler->SetEdgePaddingValue(defaultValue);
      fusionFilter->SetXsInput(resampler->GetOutput());
      }
    else if(GetParameterString("mode")=="phr")
      {
      otbAppLogINFO("Using the PHR mode");

      otb::PleiadesPToXSAffineTransformCalculator::TransformType::Pointer transform
        = otb::PleiadesPToXSAffineTransformCalculator::Compute(panchro, xs);

      basicResampler->SetInput(xs);
      basicResampler->SetTransform(transform);
      basicResampler->SetOutputOrigin(origin);
      basicResampler->SetOutputSpacing(spacing);
      basicResampler->SetOutputSize(size);
      basicResampler->SetOutputStartIndex(start);
      basicResampler->SetEdgePaddingValue(defaultValue);

      fusionFilter->SetXsInput(basicResampler->GetOutput());

      // Set the profRef & Keywordlist from Pan into the resampled XS image
      basicResampler->UpdateOutputInformation();
      itk::MetaDataDictionary& dict = basicResampler->GetOutput()->GetMetaDataDictionary();
      itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey,
                                            panchro->GetProjectionRef());
      itk::EncapsulateMetaData<ImageKeywordlist>(dict, MetaDataKey::OSSIMKeywordlistKey,
                                                 panchro->GetImageKeywordlist());
      }
    else
      {
      otbAppLogWARNING("Unknown mode");
      }

    SetParameterOutputImage("out", fusionFilter->GetOutput());
  }

  std::vector<itk::ProcessObject::Pointer> m_Ref;

};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::BundleToPerfectSensor)
<commit_msg>WRG: Fixing shadowed typedef declaration warning<commit_after>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbWrapperApplicationFactory.h"

#include "otbMultiToMonoChannelExtractROI.h"
#include "otbGenericRSResampleImageFilter.h"
#include "otbBCOInterpolateImageFunction.h"
#include "otbSimpleRcsPanSharpeningFusionImageFilter.h"
#include "itkFixedArray.h"

// Elevation handler
#include "otbWrapperElevationParametersHandler.h"

#include "otbPleiadesPToXSAffineTransformCalculator.h"

namespace otb
{
namespace Wrapper
{
class BundleToPerfectSensor : public Application
{
public:
  /** Standard class typedefs. */
  typedef BundleToPerfectSensor         Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(BundleToPerfectSensor, otb::Application);

private:

  void DoInit()
  {
    SetName("BundleToPerfectSensor");
    SetDescription("Perform P+XS pansharpening");

    // Documentation
    SetDocName("Bundle to perfect sensor");
    SetDocLongDescription("This application performs P+XS pansharpening. The default mode use Pan and XS sensor models to estimate the transformation to superimpose XS over Pan before the fusion (\"default mode\"). The application provides also a PHR mode for Pleiades images which does not use sensor models as Pan and XS products are already coregistered but only estimate an affine transformation to superimpose XS over the Pan.Note that this option is automatically activated in case Pleiades images are detected as input.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");

    AddDocTag(Tags::Geometry);
    AddDocTag(Tags::Pansharpening);

    AddParameter(ParameterType_InputImage,   "inp",   "Input PAN Image");
    SetParameterDescription("inp"," Input panchromatic image.");
    AddParameter(ParameterType_InputImage,   "inxs",  "Input XS Image");
    SetParameterDescription("inxs"," Input XS image.");

    // Elevation
    ElevationParametersHandler::AddElevationParameters(this, "elev");

    // Superposition mode
    AddParameter(ParameterType_Choice,"mode", "Mode");
    SetParameterDescription("mode", "Superimposition mode");

    AddChoice("mode.default", "Default mode");
    SetParameterDescription("mode.default", "Default superimposition mode : "
      "uses any projection reference or sensor model found in the images");

    AddChoice("mode.phr", "Pleiades mode");
    SetParameterDescription("mode.phr", "Pleiades superimposition mode, "
      "designed for the case of a P+XS bundle in SENSOR geometry. It uses"
      " a simple transform on the XS image : a scaling and a residual "
      "translation.");

    AddParameter(ParameterType_Float,        "lms",   "Spacing of the deformation field");
    SetParameterDescription("lms"," Spacing of the deformation field. Default is 10 times the PAN image spacing.");
    AddParameter(ParameterType_OutputImage,  "out",   "Output image");
    SetParameterDescription("out"," Output image.");
    AddRAMParameter();

    MandatoryOff("lms");

    // Doc example parameter settings
    SetDocExampleParameterValue("inp", "QB_Toulouse_Ortho_PAN.tif");
    SetDocExampleParameterValue("inxs", "QB_Toulouse_Ortho_XS.tif");
    SetDocExampleParameterValue("out", "BundleToPerfectSensor.png uchar");

  }

  void DoUpdateParameters()
  {
    if(!HasUserValue("mode") && HasValue("inp") && HasValue("inxs") && otb::PleiadesPToXSAffineTransformCalculator::CanCompute(GetParameterImage("inp"),GetParameterImage("inxs")))
      {
      otbAppLogWARNING("Forcing PHR mode with PHR data. You need to add \"-mode default\" to force the default mode with PHR images.");
      SetParameterString("mode","phr");
      }
  }

  void DoExecute()
  {
    FloatVectorImageType* panchroV = GetParameterImage("inp");
    FloatVectorImageType* xs = GetParameterImage("inxs");

    if ( panchroV->GetNumberOfComponentsPerPixel() != 1 )
      {
      itkExceptionMacro(<< "The panchromatic image must be a single channel image")
      }

    // Transform the PAN image to otb::Image
    typedef otb::Image<FloatVectorImageType::InternalPixelType> InternalImageType;
    typedef otb::MultiToMonoChannelExtractROI<float,float> ExtractFilterType;

    ExtractFilterType::Pointer channelSelect = ExtractFilterType::New();
    m_Ref.push_back(channelSelect.GetPointer());
    channelSelect->SetChannel(1);
    channelSelect->SetInput(panchroV);
    channelSelect->UpdateOutputInformation();
    InternalImageType::Pointer panchro = channelSelect->GetOutput();

    typedef otb::BCOInterpolateImageFunction<FloatVectorImageType> InterpolatorType;
    typedef otb::GenericRSResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  ResamplerType;
    typedef otb::StreamingResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  BasicResamplerType;
    typedef otb::SimpleRcsPanSharpeningFusionImageFilter<InternalImageType, FloatVectorImageType, FloatVectorImageType> FusionFilterType;

    // Resample filter
    ResamplerType::Pointer    resampler = ResamplerType::New();
    m_Ref.push_back(resampler.GetPointer());

    BasicResamplerType::Pointer basicResampler = BasicResamplerType::New();
    m_Ref.push_back(basicResampler.GetPointer());

    InterpolatorType::Pointer interpolator = InterpolatorType::New();
    resampler->SetInterpolator(interpolator);
    basicResampler->SetInterpolator(interpolator);

    // Fusion filter
    FusionFilterType::Pointer  fusionFilter = FusionFilterType::New();
    m_Ref.push_back(fusionFilter.GetPointer());
    fusionFilter->SetPanInput(panchro);

    // Setup the DEM Handler
    otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev");

    // Set up output image informations
    FloatVectorImageType::SpacingType spacing = panchro->GetSpacing();
    FloatVectorImageType::IndexType   start = panchro->GetLargestPossibleRegion().GetIndex();
    FloatVectorImageType::SizeType    size = panchro->GetLargestPossibleRegion().GetSize();
    FloatVectorImageType::PointType   origin = panchro->GetOrigin();

    FloatVectorImageType::PixelType defaultValue;
    itk::NumericTraits<FloatVectorImageType::PixelType>::SetLength(defaultValue, xs->GetNumberOfComponentsPerPixel());

    if(GetParameterString("mode") == "default")
      {
      otbAppLogINFO("Using the default mode");
      if(IsParameterEnabled("lms") && HasValue("lms"))
        {
        double defScalarSpacing = GetParameterFloat("lms");
        otbAppLogINFO(<< "Generating coarse deformation field (spacing="<<defScalarSpacing<<")" << std::endl);
        FloatVectorImageType::SpacingType defSpacing;

        defSpacing[0] = defScalarSpacing;
        defSpacing[1] = defScalarSpacing;

        resampler->SetDisplacementFieldSpacing(defSpacing);
        }
      else
        {
        FloatVectorImageType::SpacingType defSpacing;
        defSpacing[0]=10*spacing[0];
        defSpacing[1]=10*spacing[1];
        resampler->SetDisplacementFieldSpacing(defSpacing);
        }

      resampler->SetInput(xs);
      resampler->SetOutputOrigin(origin);
      resampler->SetOutputSpacing(spacing);
      resampler->SetOutputSize(size);
      resampler->SetOutputStartIndex(start);
      resampler->SetOutputKeywordList(panchro->GetImageKeywordlist());
      resampler->SetOutputProjectionRef(panchro->GetProjectionRef());
      resampler->SetEdgePaddingValue(defaultValue);
      fusionFilter->SetXsInput(resampler->GetOutput());
      }
    else if(GetParameterString("mode")=="phr")
      {
      otbAppLogINFO("Using the PHR mode");

      otb::PleiadesPToXSAffineTransformCalculator::TransformType::Pointer transform
        = otb::PleiadesPToXSAffineTransformCalculator::Compute(panchro, xs);

      basicResampler->SetInput(xs);
      basicResampler->SetTransform(transform);
      basicResampler->SetOutputOrigin(origin);
      basicResampler->SetOutputSpacing(spacing);
      basicResampler->SetOutputSize(size);
      basicResampler->SetOutputStartIndex(start);
      basicResampler->SetEdgePaddingValue(defaultValue);

      fusionFilter->SetXsInput(basicResampler->GetOutput());

      // Set the profRef & Keywordlist from Pan into the resampled XS image
      basicResampler->UpdateOutputInformation();
      itk::MetaDataDictionary& dict = basicResampler->GetOutput()->GetMetaDataDictionary();
      itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey,
                                            panchro->GetProjectionRef());
      itk::EncapsulateMetaData<ImageKeywordlist>(dict, MetaDataKey::OSSIMKeywordlistKey,
                                                 panchro->GetImageKeywordlist());
      }
    else
      {
      otbAppLogWARNING("Unknown mode");
      }

    SetParameterOutputImage("out", fusionFilter->GetOutput());
  }

  std::vector<itk::ProcessObject::Pointer> m_Ref;

};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::BundleToPerfectSensor)
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011, British Broadcasting Corporation
 * All Rights Reserved.
 *
 * Author: Philip de Nier
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the British Broadcasting Corporation nor the names
 *       of its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <cstring>

#include <bmx/writer_helper/AVCIWriterHelper.h>
#include <bmx/BMXException.h>
#include <bmx/Logging.h>

using namespace std;
using namespace bmx;

AVCIWriterHelper::AVCIWriterHelper()
{
    mMode = AVCI_PASS_MODE;
    mHeader = 0;
    mSampleCount = 0;
    mFirstFrameHeader = false;
    mSecondFrameHeader = false;

    BMX_ASSERT(sizeof(AVCI_FILLER) == sizeof(AVCI_ACCESS_UNIT_DELIMITER));
}

AVCIWriterHelper::~AVCIWriterHelper()
{
    delete [] mHeader;
}

void AVCIWriterHelper::SetMode(AVCIMode mode)
{
    mMode = mode;
}

void AVCIWriterHelper::SetHeader(const unsigned char *data, uint32_t size)
{
    BMX_CHECK(size == AVCI_HEADER_SIZE);

    if (!mHeader)
        mHeader = new unsigned char[AVCI_HEADER_SIZE];

    memcpy(mHeader, data, AVCI_HEADER_SIZE);
}

uint32_t AVCIWriterHelper::ProcessFrame(const unsigned char *data, uint32_t size,
                                        const CDataBuffer **data_array, uint32_t *array_size)
{
    mEssenceParser.ParseFrameInfo(data, size);
    bool have_header = mEssenceParser.HaveSequenceParameterSet();

    uint32_t output_frame_size = 0;
    switch (mMode)
    {
        case AVCI_PASS_MODE:
            output_frame_size = PassFrame(data, size, array_size);
            break;
        case AVCI_NO_FRAME_HEADER_MODE:
            if (have_header)
                output_frame_size = StripFrameHeader(data, size, array_size);
            else
                output_frame_size = PassFrame(data, size, array_size);
            break;
        case AVCI_NO_OR_ALL_FRAME_HEADER_MODE:
            if (have_header) {
                if (mSampleCount == 0) {
                    mFirstFrameHeader = true;
                    SetHeader(data, AVCI_HEADER_SIZE);
                }

                if (mFirstFrameHeader)
                    output_frame_size = PassFrame(data, size, array_size);
                else
                    output_frame_size = StripFrameHeader(data, size, array_size);
            } else {
                if (mFirstFrameHeader)
                    output_frame_size = PrependFrameHeader(data, size, array_size);
                else
                    output_frame_size = PassFrame(data, size, array_size);
            }
            break;
        case AVCI_FIRST_FRAME_HEADER_MODE:
            if (have_header) {
                if (mSampleCount == 0) {
                    output_frame_size = PassFrame(data, size, array_size);
                    SetHeader(data, AVCI_HEADER_SIZE);
                } else {
                    output_frame_size = StripFrameHeader(data, size, array_size);
                }
            } else {
                if (mSampleCount == 0) {
                    if (!mHeader) {
                        BMX_EXCEPTION(("Missing AVCI header sets in first frame"));
                    }
                    output_frame_size = PrependFrameHeader(data, size, array_size);
                } else {
                    output_frame_size = PassFrame(data, size, array_size);
                }
            }
            break;
        case AVCI_FIRST_OR_ALL_FRAME_HEADER_MODE:
            if (have_header) {
                if (mSampleCount == 0) {
                    output_frame_size = PassFrame(data, size, array_size);
                    SetHeader(data, AVCI_HEADER_SIZE);
                } else if (mSampleCount == 1) {
                    mSecondFrameHeader = true;
                    output_frame_size = PassFrame(data, size, array_size);
                } else {
                    if (mSecondFrameHeader)
                        output_frame_size = PassFrame(data, size, array_size);
                    else
                        output_frame_size = StripFrameHeader(data, size, array_size);
                }
            } else {
                if (mSampleCount == 0) {
                    if (!mHeader) {
                        BMX_EXCEPTION(("Missing AVCI header sets in first frame"));
                    }
                    output_frame_size = PrependFrameHeader(data, size, array_size);
                } else if (mSampleCount == 1) {
                    mSecondFrameHeader = false;
                    output_frame_size = PassFrame(data, size, array_size);
                } else if (mSecondFrameHeader) {
                    output_frame_size = PrependFrameHeader(data, size, array_size);
                } else {
                    output_frame_size = PassFrame(data, size, array_size);
                }
            }
            break;
        case AVCI_ALL_FRAME_HEADER_MODE:
            if (have_header) {
                if (mSampleCount == 0)
                    SetHeader(data, AVCI_HEADER_SIZE);
                output_frame_size = PassFrame(data, size, array_size);
            } else {
                if (!mHeader) {
                    BMX_EXCEPTION(("Missing AVCI header sets in first frame"));
                }
                output_frame_size = PrependFrameHeader(data, size, array_size);
            }
            break;
    }

    mSampleCount++;

    *data_array = mDataArray;
    return output_frame_size;
}

uint32_t AVCIWriterHelper::PassFrame(const unsigned char *data, uint32_t size, uint32_t *array_size)
{
    // ensure frame starts with access unit delimiter
    if (memcmp(data, AVCI_ACCESS_UNIT_DELIMITER, sizeof(AVCI_ACCESS_UNIT_DELIMITER)) == 0) {
        mDataArray[0].data = (unsigned char*)data;
        mDataArray[0].size = size;
        *array_size = 1;
    } else if (memcmp(data, AVCI_FILLER, sizeof(AVCI_FILLER)) == 0) {
        mDataArray[0].data = (unsigned char*)AVCI_ACCESS_UNIT_DELIMITER;
        mDataArray[0].size = sizeof(AVCI_ACCESS_UNIT_DELIMITER);
        mDataArray[1].data = (unsigned char*)(data + sizeof(AVCI_ACCESS_UNIT_DELIMITER));
        mDataArray[1].size = size - sizeof(AVCI_ACCESS_UNIT_DELIMITER);
        *array_size = 2;
    } else {
        BMX_EXCEPTION(("AVCI frame does not start with access unit delimiter or filler"));
    }

    return size;
}

uint32_t AVCIWriterHelper::StripFrameHeader(const unsigned char *data, uint32_t size, uint32_t *array_size)
{
    // strip header and ensure frame starts with access unit delimiter
    if (memcmp(data + AVCI_HEADER_SIZE, AVCI_ACCESS_UNIT_DELIMITER, sizeof(AVCI_ACCESS_UNIT_DELIMITER)) == 0) {
        mDataArray[0].data = (unsigned char*)(data + AVCI_HEADER_SIZE);
        mDataArray[0].size = size - AVCI_HEADER_SIZE;
        *array_size = 1;
    } else if (memcmp(data + AVCI_HEADER_SIZE, AVCI_FILLER, sizeof(AVCI_FILLER)) == 0) {
        mDataArray[0].data = (unsigned char*)AVCI_ACCESS_UNIT_DELIMITER;
        mDataArray[0].size = sizeof(AVCI_ACCESS_UNIT_DELIMITER);
        mDataArray[1].data = (unsigned char*)(data + AVCI_HEADER_SIZE + sizeof(AVCI_ACCESS_UNIT_DELIMITER));
        mDataArray[1].size = size - AVCI_HEADER_SIZE - sizeof(AVCI_ACCESS_UNIT_DELIMITER);
        *array_size = 2;
    } else {
        BMX_EXCEPTION(("Failed to strip AVCI header because filler or access unit delimiter "
                      "not found at offset %u", AVCI_HEADER_SIZE));
    }

    return size - AVCI_HEADER_SIZE;
}

uint32_t AVCIWriterHelper::PrependFrameHeader(const unsigned char *data, uint32_t size, uint32_t *array_size)
{
    // prepend header and replace access unit delimiter with filler
    BMX_ASSERT(mHeader);
    if (memcmp(data, AVCI_ACCESS_UNIT_DELIMITER, sizeof(AVCI_ACCESS_UNIT_DELIMITER)) == 0) {
        mDataArray[0].data = mHeader;
        mDataArray[0].size = AVCI_HEADER_SIZE;
        mDataArray[1].data = (unsigned char*)AVCI_FILLER;
        mDataArray[1].size = sizeof(AVCI_FILLER);
        mDataArray[2].data = (unsigned char*)(data + sizeof(AVCI_FILLER));
        mDataArray[2].size = size - sizeof(AVCI_FILLER);
        *array_size = 3;
    } else {
        mDataArray[0].data = mHeader;
        mDataArray[0].size = AVCI_HEADER_SIZE;
        mDataArray[1].data = (unsigned char*)data;
        mDataArray[1].size = size;
        *array_size = 2;
    }

    return size + AVCI_HEADER_SIZE;
}
<commit_msg>avci helper: use define to ensure correct header set logic<commit_after>/*
 * Copyright (C) 2011, British Broadcasting Corporation
 * All Rights Reserved.
 *
 * Author: Philip de Nier
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the British Broadcasting Corporation nor the names
 *       of its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <cstring>

#include <bmx/writer_helper/AVCIWriterHelper.h>
#include <bmx/BMXException.h>
#include <bmx/Logging.h>

using namespace std;
using namespace bmx;

// Client code relies on this logic. This allows a client to set provisional header data
// and this header data is overwritten if the first input frame contains header data
#define SET_HEADER_ENABLED  mSampleCount == 0

AVCIWriterHelper::AVCIWriterHelper()
{
    mMode = AVCI_PASS_MODE;
    mHeader = 0;
    mSampleCount = 0;
    mFirstFrameHeader = false;
    mSecondFrameHeader = false;

    BMX_ASSERT(sizeof(AVCI_FILLER) == sizeof(AVCI_ACCESS_UNIT_DELIMITER));
}

AVCIWriterHelper::~AVCIWriterHelper()
{
    delete [] mHeader;
}

void AVCIWriterHelper::SetMode(AVCIMode mode)
{
    mMode = mode;
}

void AVCIWriterHelper::SetHeader(const unsigned char *data, uint32_t size)
{
    BMX_CHECK(size == AVCI_HEADER_SIZE);

    if (!mHeader)
        mHeader = new unsigned char[AVCI_HEADER_SIZE];

    memcpy(mHeader, data, AVCI_HEADER_SIZE);
}

uint32_t AVCIWriterHelper::ProcessFrame(const unsigned char *data, uint32_t size,
                                        const CDataBuffer **data_array, uint32_t *array_size)
{
    mEssenceParser.ParseFrameInfo(data, size);
    bool have_header = mEssenceParser.HaveSequenceParameterSet();

    uint32_t output_frame_size = 0;
    switch (mMode)
    {
        case AVCI_PASS_MODE:
            output_frame_size = PassFrame(data, size, array_size);
            break;
        case AVCI_NO_FRAME_HEADER_MODE:
            if (have_header)
                output_frame_size = StripFrameHeader(data, size, array_size);
            else
                output_frame_size = PassFrame(data, size, array_size);
            break;
        case AVCI_NO_OR_ALL_FRAME_HEADER_MODE:
            if (have_header) {
                if (SET_HEADER_ENABLED) {
                    mFirstFrameHeader = true;
                    SetHeader(data, AVCI_HEADER_SIZE);
                }

                if (mFirstFrameHeader)
                    output_frame_size = PassFrame(data, size, array_size);
                else
                    output_frame_size = StripFrameHeader(data, size, array_size);
            } else {
                if (mFirstFrameHeader)
                    output_frame_size = PrependFrameHeader(data, size, array_size);
                else
                    output_frame_size = PassFrame(data, size, array_size);
            }
            break;
        case AVCI_FIRST_FRAME_HEADER_MODE:
            if (have_header) {
                if (SET_HEADER_ENABLED) {
                    output_frame_size = PassFrame(data, size, array_size);
                    SetHeader(data, AVCI_HEADER_SIZE);
                } else {
                    output_frame_size = StripFrameHeader(data, size, array_size);
                }
            } else {
                if (mSampleCount == 0) {
                    if (!mHeader) {
                        BMX_EXCEPTION(("Missing AVCI header sets in first frame"));
                    }
                    output_frame_size = PrependFrameHeader(data, size, array_size);
                } else {
                    output_frame_size = PassFrame(data, size, array_size);
                }
            }
            break;
        case AVCI_FIRST_OR_ALL_FRAME_HEADER_MODE:
            if (have_header) {
                if (SET_HEADER_ENABLED) {
                    output_frame_size = PassFrame(data, size, array_size);
                    SetHeader(data, AVCI_HEADER_SIZE);
                } else if (mSampleCount == 1) {
                    mSecondFrameHeader = true;
                    output_frame_size = PassFrame(data, size, array_size);
                } else {
                    if (mSecondFrameHeader)
                        output_frame_size = PassFrame(data, size, array_size);
                    else
                        output_frame_size = StripFrameHeader(data, size, array_size);
                }
            } else {
                if (mSampleCount == 0) {
                    if (!mHeader) {
                        BMX_EXCEPTION(("Missing AVCI header sets in first frame"));
                    }
                    output_frame_size = PrependFrameHeader(data, size, array_size);
                } else if (mSampleCount == 1) {
                    mSecondFrameHeader = false;
                    output_frame_size = PassFrame(data, size, array_size);
                } else if (mSecondFrameHeader) {
                    output_frame_size = PrependFrameHeader(data, size, array_size);
                } else {
                    output_frame_size = PassFrame(data, size, array_size);
                }
            }
            break;
        case AVCI_ALL_FRAME_HEADER_MODE:
            if (have_header) {
                if (SET_HEADER_ENABLED)
                    SetHeader(data, AVCI_HEADER_SIZE);
                output_frame_size = PassFrame(data, size, array_size);
            } else {
                if (!mHeader) {
                    BMX_EXCEPTION(("Missing AVCI header sets in first frame"));
                }
                output_frame_size = PrependFrameHeader(data, size, array_size);
            }
            break;
    }

    mSampleCount++;

    *data_array = mDataArray;
    return output_frame_size;
}

uint32_t AVCIWriterHelper::PassFrame(const unsigned char *data, uint32_t size, uint32_t *array_size)
{
    // ensure frame starts with access unit delimiter
    if (memcmp(data, AVCI_ACCESS_UNIT_DELIMITER, sizeof(AVCI_ACCESS_UNIT_DELIMITER)) == 0) {
        mDataArray[0].data = (unsigned char*)data;
        mDataArray[0].size = size;
        *array_size = 1;
    } else if (memcmp(data, AVCI_FILLER, sizeof(AVCI_FILLER)) == 0) {
        mDataArray[0].data = (unsigned char*)AVCI_ACCESS_UNIT_DELIMITER;
        mDataArray[0].size = sizeof(AVCI_ACCESS_UNIT_DELIMITER);
        mDataArray[1].data = (unsigned char*)(data + sizeof(AVCI_ACCESS_UNIT_DELIMITER));
        mDataArray[1].size = size - sizeof(AVCI_ACCESS_UNIT_DELIMITER);
        *array_size = 2;
    } else {
        BMX_EXCEPTION(("AVCI frame does not start with access unit delimiter or filler"));
    }

    return size;
}

uint32_t AVCIWriterHelper::StripFrameHeader(const unsigned char *data, uint32_t size, uint32_t *array_size)
{
    // strip header and ensure frame starts with access unit delimiter
    if (memcmp(data + AVCI_HEADER_SIZE, AVCI_ACCESS_UNIT_DELIMITER, sizeof(AVCI_ACCESS_UNIT_DELIMITER)) == 0) {
        mDataArray[0].data = (unsigned char*)(data + AVCI_HEADER_SIZE);
        mDataArray[0].size = size - AVCI_HEADER_SIZE;
        *array_size = 1;
    } else if (memcmp(data + AVCI_HEADER_SIZE, AVCI_FILLER, sizeof(AVCI_FILLER)) == 0) {
        mDataArray[0].data = (unsigned char*)AVCI_ACCESS_UNIT_DELIMITER;
        mDataArray[0].size = sizeof(AVCI_ACCESS_UNIT_DELIMITER);
        mDataArray[1].data = (unsigned char*)(data + AVCI_HEADER_SIZE + sizeof(AVCI_ACCESS_UNIT_DELIMITER));
        mDataArray[1].size = size - AVCI_HEADER_SIZE - sizeof(AVCI_ACCESS_UNIT_DELIMITER);
        *array_size = 2;
    } else {
        BMX_EXCEPTION(("Failed to strip AVCI header because filler or access unit delimiter "
                      "not found at offset %u", AVCI_HEADER_SIZE));
    }

    return size - AVCI_HEADER_SIZE;
}

uint32_t AVCIWriterHelper::PrependFrameHeader(const unsigned char *data, uint32_t size, uint32_t *array_size)
{
    // prepend header and replace access unit delimiter with filler
    BMX_ASSERT(mHeader);
    if (memcmp(data, AVCI_ACCESS_UNIT_DELIMITER, sizeof(AVCI_ACCESS_UNIT_DELIMITER)) == 0) {
        mDataArray[0].data = mHeader;
        mDataArray[0].size = AVCI_HEADER_SIZE;
        mDataArray[1].data = (unsigned char*)AVCI_FILLER;
        mDataArray[1].size = sizeof(AVCI_FILLER);
        mDataArray[2].data = (unsigned char*)(data + sizeof(AVCI_FILLER));
        mDataArray[2].size = size - sizeof(AVCI_FILLER);
        *array_size = 3;
    } else {
        mDataArray[0].data = mHeader;
        mDataArray[0].size = AVCI_HEADER_SIZE;
        mDataArray[1].data = (unsigned char*)data;
        mDataArray[1].size = size;
        *array_size = 2;
    }

    return size + AVCI_HEADER_SIZE;
}
<|endoftext|>