<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/initfiles/p9_fbc_ioe_dl_scom.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include "p9_fbc_ioe_dl_scom.H"
#include <stdint.h>
#include <stddef.h>
#include <fapi2.H>

using namespace fapi2;

constexpr uint64_t literal_0xE00 = 0xE00;
constexpr uint64_t literal_0x0000 = 0x0000;
constexpr uint64_t literal_0x0 = 0x0;
constexpr uint64_t literal_0b11 = 0b11;

fapi2::ReturnCode p9_fbc_ioe_dl_scom(const fapi2::Target<fapi2::TARGET_TYPE_XBUS>& TGT0,
                                     const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& TGT1)
{
    {
        fapi2::ATTR_EC_Type   l_chip_ec;
        fapi2::ATTR_NAME_Type l_chip_id;
        FAPI_TRY(FAPI_ATTR_GET_PRIVILEGED(fapi2::ATTR_NAME, TGT1, l_chip_id));
        FAPI_TRY(FAPI_ATTR_GET_PRIVILEGED(fapi2::ATTR_EC, TGT1, l_chip_ec));
        fapi2::buffer<uint64_t> l_scom_buffer;
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x601180aull, l_scom_buffer ));

            constexpr auto l_PB_IOE_LL1_CONFIG_LINK_PAIR_ON = 0x1;
            l_scom_buffer.insert<0, 1, 63, uint64_t>(l_PB_IOE_LL1_CONFIG_LINK_PAIR_ON );
            constexpr auto l_PB_IOE_LL1_CONFIG_CRC_LANE_ID_ON = 0x1;
            l_scom_buffer.insert<2, 1, 63, uint64_t>(l_PB_IOE_LL1_CONFIG_CRC_LANE_ID_ON );
            FAPI_TRY(fapi2::putScom(TGT0, 0x601180aull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011818ull, l_scom_buffer ));

            l_scom_buffer.insert<8, 3, 61, uint64_t>(literal_0xE00 );
            l_scom_buffer.insert<32, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<48, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<4, 4, 60, uint64_t>(literal_0x0 );
            l_scom_buffer.insert<0, 4, 60, uint64_t>(literal_0x0 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011818ull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011819ull, l_scom_buffer ));

            if (((l_chip_id == 0x5) && (l_chip_ec == 0x10)) )
            {
                l_scom_buffer.insert<8, 2, 62, uint64_t>(literal_0b11 );
            }
            else if (((l_chip_id == 0x5) && (l_chip_ec == 0x20)) )
            {
                l_scom_buffer.insert<8, 3, 61, uint64_t>(literal_0b11 );
            }

            l_scom_buffer.insert<32, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<48, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<4, 4, 60, uint64_t>(literal_0x0 );
            l_scom_buffer.insert<0, 4, 60, uint64_t>(literal_0x0 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011819ull, l_scom_buffer));
        }

    };
fapi_try_exit:
    return fapi2::current_err;
}
<commit_msg>P9 Cumulus InitCompiler supportis - Part 3<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/initfiles/p9_fbc_ioe_dl_scom.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include "p9_fbc_ioe_dl_scom.H"
#include <stdint.h>
#include <stddef.h>
#include <fapi2.H>

using namespace fapi2;

constexpr uint64_t literal_0xE00 = 0xE00;
constexpr uint64_t literal_0x0000 = 0x0000;
constexpr uint64_t literal_0x0 = 0x0;
constexpr uint64_t literal_0b11 = 0b11;

fapi2::ReturnCode p9_fbc_ioe_dl_scom(const fapi2::Target<fapi2::TARGET_TYPE_XBUS>& TGT0,
                                     const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& TGT1)
{
    {
        fapi2::ATTR_EC_Type   l_chip_ec;
        fapi2::ATTR_NAME_Type l_chip_id;
        FAPI_TRY(FAPI_ATTR_GET_PRIVILEGED(fapi2::ATTR_NAME, TGT1, l_chip_id));
        FAPI_TRY(FAPI_ATTR_GET_PRIVILEGED(fapi2::ATTR_EC, TGT1, l_chip_ec));
        fapi2::buffer<uint64_t> l_scom_buffer;
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x601180aull, l_scom_buffer ));

            constexpr auto l_PB_IOE_LL1_CONFIG_LINK_PAIR_ON = 0x1;
            l_scom_buffer.insert<0, 1, 63, uint64_t>(l_PB_IOE_LL1_CONFIG_LINK_PAIR_ON );
            constexpr auto l_PB_IOE_LL1_CONFIG_CRC_LANE_ID_ON = 0x1;
            l_scom_buffer.insert<2, 1, 63, uint64_t>(l_PB_IOE_LL1_CONFIG_CRC_LANE_ID_ON );
            FAPI_TRY(fapi2::putScom(TGT0, 0x601180aull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011818ull, l_scom_buffer ));

            l_scom_buffer.insert<8, 3, 61, uint64_t>(literal_0xE00 );
            l_scom_buffer.insert<32, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<48, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<4, 4, 60, uint64_t>(literal_0x0 );
            l_scom_buffer.insert<0, 4, 60, uint64_t>(literal_0x0 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011818ull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011819ull, l_scom_buffer ));

            if (((l_chip_id == 0x5) && (l_chip_ec == 0x10)) )
            {
                l_scom_buffer.insert<8, 2, 62, uint64_t>(literal_0b11 );
            }
            else if (((l_chip_id == 0x5) && (l_chip_ec == 0x20)) || ((l_chip_id == 0x6) && (l_chip_ec == 0x10)) )
            {
                l_scom_buffer.insert<8, 3, 61, uint64_t>(literal_0b11 );
            }

            l_scom_buffer.insert<32, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<48, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<4, 4, 60, uint64_t>(literal_0x0 );
            l_scom_buffer.insert<0, 4, 60, uint64_t>(literal_0x0 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011819ull, l_scom_buffer));
        }

    };
fapi_try_exit:
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_revert_sbe_mcs_setup.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file p9_revert_sbe_mcs_setup.C
/// @brief Revert MC configuration applied by SBE (FAPI2)

///
/// @author Joe McGill <jmcgill@us.ibm.com>
///

//
// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com>
// *HWP FW Owner: Thi Tran <thi@us.ibm.com>
// *HWP Team: Nest
// *HWP Level: 2
// *HWP Consumed by: HB
//

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <p9_revert_sbe_mcs_setup.H>
#include <p9_perv_scom_addresses.H>
#include <p9_mc_scom_addresses.H>
#include <p9_mc_scom_addresses_fld.H>

//------------------------------------------------------------------------------
// Constant definitions
//------------------------------------------------------------------------------

// MCS target type constants
const uint8_t NUM_MCS_TARGETS = 4;

const uint64_t MCS_CPLT_CTRL1_ARR[NUM_MCS_TARGETS] =
{
    PERV_N3_CPLT_CTRL1,
    PERV_N3_CPLT_CTRL1,
    PERV_N1_CPLT_CTRL1,
    PERV_N1_CPLT_CTRL1
};

const uint64_t MCS_CPLT_CTRL1_BIT_ARR[NUM_MCS_TARGETS] =
{
    10,
    10,
    9,
    9
};

const uint64_t MCS_MCFGP_ARR[NUM_MCS_TARGETS] =
{
    MCS_0_MCFGP,
    MCS_1_MCFGP,
    MCS_2_MCFGP,
    MCS_3_MCFGP
};
const uint64_t MCS_MCMODE1_ARR[NUM_MCS_TARGETS] =
{
    MCS_0_MCMODE1,
    MCS_1_MCMODE1,
    MCS_2_MCMODE1,
    MCS_3_MCMODE1
};
const uint64_t MCS_MCFIRMASK_OR_ARR[NUM_MCS_TARGETS] =
{
    MCS_0_MCFIRMASK_OR,
    MCS_1_MCFIRMASK_OR,
    MCS_2_MCFIRMASK_OR,
    MCS_3_MCFIRMASK_OR
};

//------------------------------------------------------------------------------
// Function definitions
//------------------------------------------------------------------------------

// helper function for MCS target type
fapi2::ReturnCode
revert_mcs_hb_dcbz_config(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
                          const uint8_t i_mcs)
{
    FAPI_DBG("Start");
    fapi2::buffer<uint64_t> l_cplt_ctrl1;
    fapi2::buffer<uint64_t> l_mcfgp;
    fapi2::buffer<uint64_t> l_mcmode1;
    fapi2::buffer<uint64_t> l_mcfirmask;

    FAPI_TRY(fapi2::getScom(i_target, MCS_CPLT_CTRL1_ARR[i_mcs], l_cplt_ctrl1),
             "Error from getscom (CPLT_CTRL1)");

    if (!l_cplt_ctrl1.getBit(MCS_CPLT_CTRL1_BIT_ARR[i_mcs]))
    {
        // MCFGP -- mark BAR invalid & reset grouping configuration fields
        FAPI_TRY(fapi2::getScom(i_target, MCS_MCFGP_ARR[i_mcs], l_mcfgp),
                 "Error from getScom (MCS%d_MCFGP)", i_mcs);
        l_mcfgp.clearBit<MCS_MCFGP_VALID>();
        l_mcfgp.clearBit<MCS_MCFGP_MC_CHANNELS_PER_GROUP,
                         MCS_MCFGP_MC_CHANNELS_PER_GROUP_LEN>();
        l_mcfgp.clearBit<MCS_MCFGP_CHANNEL_0_GROUP_MEMBER_IDENTIFICATION,
                         MCS_MCFGP_CHANNEL_0_GROUP_MEMBER_IDENTIFICATION_LEN>();
        l_mcfgp.clearBit<MCS_MCFGP_GROUP_SIZE, MCS_MCFGP_GROUP_SIZE_LEN>();
        FAPI_TRY(fapi2::putScom(i_target, MCS_MCFGP_ARR[i_mcs], l_mcfgp),
                 "Error from putScom (MCS%d_MCFGP)", i_mcs);

        // MCMODE1 -- enable speculation
        FAPI_TRY(fapi2::getScom(i_target, MCS_MCMODE1_ARR[i_mcs], l_mcmode1),
                 "Error from getScom (MCS%d_MCMODE1)", i_mcs);
        l_mcmode1.clearBit<MCS_MCMODE1_DISABLE_ALL_SPEC_OPS>();
        l_mcmode1.clearBit<MCS_MCMODE1_DISABLE_SPEC_OP,
                           MCS_MCMODE1_DISABLE_SPEC_OP_LEN>();
        FAPI_TRY(fapi2::putScom(i_target, MCS_MCMODE1_ARR[i_mcs], l_mcmode1),
                 "Error from putScom (MCS%d_MCMODE1)", i_mcs);

        // Re-mask MCFIR. We want to ensure all MCSs are masked
        // until the BARs are opened later during IPL.
        l_mcfirmask.flush<1>();
        FAPI_TRY(fapi2::putScom(i_target, MCS_MCFIRMASK, l_mcfirmask),
                 "Error from putScom (MCS_MCFIRMASK)");
    }

fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}

// helper function for MI target type
fapi2::ReturnCode
revert_mi_hb_dcbz_config(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_DBG("Start");

    // TODO: implement for Cumulus/MI target type
    (void) i_target;
    goto fapi_try_exit;

fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}

// HWP entry point
fapi2::ReturnCode
p9_revert_sbe_mcs_setup(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_INF("Start");

    fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
    fapi2::ATTR_SYSTEM_IPL_PHASE_Type l_ipl_phase;
    auto l_mcs_chiplets = i_target.getChildren<fapi2::TARGET_TYPE_MCS>(fapi2::TARGET_STATE_PRESENT);

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_SYSTEM_IPL_PHASE, FAPI_SYSTEM, l_ipl_phase),
             "Error from FAPI_ATTR_GET (ATTR_SYSTEM_IPL_PHASE)");

    if (l_ipl_phase == fapi2::ENUM_ATTR_SYSTEM_IPL_PHASE_CHIP_CONTAINED)
    {
        FAPI_INF("Leaving MC BAR configured for chip contained execution");
        goto fapi_try_exit;
    }

    if (l_mcs_chiplets.size())
    {
        for (uint8_t l_mcs = 0; l_mcs < NUM_MCS_TARGETS; l_mcs++)
        {
            FAPI_TRY(revert_mcs_hb_dcbz_config(i_target, l_mcs),
                     "Error from revert_mcs_hb_dcbz_config");
        }
    }
    else
    {
        FAPI_TRY(revert_mi_hb_dcbz_config(i_target),
                 "Error from revert_mi_hb_dcbz_config");
    }

fapi_try_exit:
    FAPI_INF("End");
    return fapi2::current_err;
}
<commit_msg>p9_revert_sbe_mcs_setup - Fix incorrect unmask reg addr<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_revert_sbe_mcs_setup.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file p9_revert_sbe_mcs_setup.C
/// @brief Revert MC configuration applied by SBE (FAPI2)

///
/// @author Joe McGill <jmcgill@us.ibm.com>
///

//
// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com>
// *HWP FW Owner: Thi Tran <thi@us.ibm.com>
// *HWP Team: Nest
// *HWP Level: 2
// *HWP Consumed by: HB
//

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <p9_revert_sbe_mcs_setup.H>
#include <p9_perv_scom_addresses.H>
#include <p9_mc_scom_addresses.H>
#include <p9_mc_scom_addresses_fld.H>

//------------------------------------------------------------------------------
// Constant definitions
//------------------------------------------------------------------------------

// MCS target type constants
const uint8_t NUM_MCS_TARGETS = 4;

const uint64_t MCS_CPLT_CTRL1_ARR[NUM_MCS_TARGETS] =
{
    PERV_N3_CPLT_CTRL1,
    PERV_N3_CPLT_CTRL1,
    PERV_N1_CPLT_CTRL1,
    PERV_N1_CPLT_CTRL1
};

const uint64_t MCS_CPLT_CTRL1_BIT_ARR[NUM_MCS_TARGETS] =
{
    10,
    10,
    9,
    9
};

const uint64_t MCS_MCFGP_ARR[NUM_MCS_TARGETS] =
{
    MCS_0_MCFGP,
    MCS_1_MCFGP,
    MCS_2_MCFGP,
    MCS_3_MCFGP
};
const uint64_t MCS_MCMODE1_ARR[NUM_MCS_TARGETS] =
{
    MCS_0_MCMODE1,
    MCS_1_MCMODE1,
    MCS_2_MCMODE1,
    MCS_3_MCMODE1
};
const uint64_t MCS_MCFIRMASK_OR_ARR[NUM_MCS_TARGETS] =
{
    MCS_0_MCFIRMASK_OR,
    MCS_1_MCFIRMASK_OR,
    MCS_2_MCFIRMASK_OR,
    MCS_3_MCFIRMASK_OR
};

//------------------------------------------------------------------------------
// Function definitions
//------------------------------------------------------------------------------

// helper function for MCS target type
fapi2::ReturnCode
revert_mcs_hb_dcbz_config(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
                          const uint8_t i_mcs)
{
    FAPI_DBG("Start");
    fapi2::buffer<uint64_t> l_cplt_ctrl1;
    fapi2::buffer<uint64_t> l_mcfgp;
    fapi2::buffer<uint64_t> l_mcmode1;
    fapi2::buffer<uint64_t> l_mcfirmask;

    FAPI_TRY(fapi2::getScom(i_target, MCS_CPLT_CTRL1_ARR[i_mcs], l_cplt_ctrl1),
             "Error from getscom (CPLT_CTRL1)");

    if (!l_cplt_ctrl1.getBit(MCS_CPLT_CTRL1_BIT_ARR[i_mcs]))
    {
        // MCFGP -- mark BAR invalid & reset grouping configuration fields
        FAPI_TRY(fapi2::getScom(i_target, MCS_MCFGP_ARR[i_mcs], l_mcfgp),
                 "Error from getScom (MCS%d_MCFGP)", i_mcs);
        l_mcfgp.clearBit<MCS_MCFGP_VALID>();
        l_mcfgp.clearBit<MCS_MCFGP_MC_CHANNELS_PER_GROUP,
                         MCS_MCFGP_MC_CHANNELS_PER_GROUP_LEN>();
        l_mcfgp.clearBit<MCS_MCFGP_CHANNEL_0_GROUP_MEMBER_IDENTIFICATION,
                         MCS_MCFGP_CHANNEL_0_GROUP_MEMBER_IDENTIFICATION_LEN>();
        l_mcfgp.clearBit<MCS_MCFGP_GROUP_SIZE, MCS_MCFGP_GROUP_SIZE_LEN>();
        FAPI_TRY(fapi2::putScom(i_target, MCS_MCFGP_ARR[i_mcs], l_mcfgp),
                 "Error from putScom (MCS%d_MCFGP)", i_mcs);

        // MCMODE1 -- enable speculation
        FAPI_TRY(fapi2::getScom(i_target, MCS_MCMODE1_ARR[i_mcs], l_mcmode1),
                 "Error from getScom (MCS%d_MCMODE1)", i_mcs);
        l_mcmode1.clearBit<MCS_MCMODE1_DISABLE_ALL_SPEC_OPS>();
        l_mcmode1.clearBit<MCS_MCMODE1_DISABLE_SPEC_OP,
                           MCS_MCMODE1_DISABLE_SPEC_OP_LEN>();
        FAPI_TRY(fapi2::putScom(i_target, MCS_MCMODE1_ARR[i_mcs], l_mcmode1),
                 "Error from putScom (MCS%d_MCMODE1)", i_mcs);

        // Re-mask MCFIR. We want to ensure all MCSs are masked
        // until the BARs are opened later during IPL.
        l_mcfirmask.flush<1>();
        FAPI_TRY(fapi2::putScom(i_target, MCS_MCFIRMASK_OR_ARR[i_mcs], l_mcfirmask),
                 "Error from putScom (MCS%d_MCFIRMASK_OR)", i_mcs);
    }

fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}

// helper function for MI target type
fapi2::ReturnCode
revert_mi_hb_dcbz_config(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_DBG("Start");

    // TODO: implement for Cumulus/MI target type
    (void) i_target;
    goto fapi_try_exit;

fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}

// HWP entry point
fapi2::ReturnCode
p9_revert_sbe_mcs_setup(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_INF("Start");

    fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
    fapi2::ATTR_SYSTEM_IPL_PHASE_Type l_ipl_phase;
    auto l_mcs_chiplets = i_target.getChildren<fapi2::TARGET_TYPE_MCS>(fapi2::TARGET_STATE_PRESENT);

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_SYSTEM_IPL_PHASE, FAPI_SYSTEM, l_ipl_phase),
             "Error from FAPI_ATTR_GET (ATTR_SYSTEM_IPL_PHASE)");

    if (l_ipl_phase == fapi2::ENUM_ATTR_SYSTEM_IPL_PHASE_CHIP_CONTAINED)
    {
        FAPI_INF("Leaving MC BAR configured for chip contained execution");
        goto fapi_try_exit;
    }

    if (l_mcs_chiplets.size())
    {
        for (uint8_t l_mcs = 0; l_mcs < NUM_MCS_TARGETS; l_mcs++)
        {
            FAPI_TRY(revert_mcs_hb_dcbz_config(i_target, l_mcs),
                     "Error from revert_mcs_hb_dcbz_config");
        }
    }
    else
    {
        FAPI_TRY(revert_mi_hb_dcbz_config(i_target),
                 "Error from revert_mi_hb_dcbz_config");
    }

fapi_try_exit:
    FAPI_INF("End");
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>//
//  Video.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 12/10/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "Video.hpp"

using namespace Oric;

namespace {
	const unsigned int PAL50VSyncStartPosition = 256*64;
	const unsigned int PAL60VSyncStartPosition = 234*64;
	const unsigned int PAL50VSyncEndPosition = 259*64;
	const unsigned int PAL60VSyncEndPosition = 238*64;
	const unsigned int PAL50Period = 312*64;
	const unsigned int PAL60Period = 262*64;
}

VideoOutput::VideoOutput(uint8_t *memory) :
		ram_(memory),
		frame_counter_(0), counter_(0),
		is_graphics_mode_(false),
		character_set_base_address_(0xb400),
		v_sync_start_position_(PAL50VSyncStartPosition), v_sync_end_position_(PAL50VSyncEndPosition),
		counter_period_(PAL50Period), next_frame_is_sixty_hertz_(false),
		crt_(new Outputs::CRT::CRT(64*6, 6, Outputs::CRT::DisplayType::PAL50, 2)) {
	crt_->set_rgb_sampling_function(
		"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
		"{"
			"uint texValue = texture(sampler, coordinate).r;"
			"return vec3( uvec3(texValue) & uvec3(4u, 2u, 1u));"
		"}");
	crt_->set_composite_sampling_function(
		"float composite_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate, float phase, float amplitude)"
		"{"
			"uint texValue = uint(dot(texture(sampler, coordinate).rg, uvec2(1, 256)));"
			"uint iPhase = uint((phase + 3.141592654 + 0.39269908175) * 2.0 / 3.141592654) & 3u;"
			"texValue = (texValue >> (4u*(3u - iPhase))) & 15u;"
			"return (float(texValue) - 4.0) / 20.0;"
		"}"
	);
	crt_->set_composite_function_type(Outputs::CRT::CRT::CompositeSourceType::DiscreteFourSamplesPerCycle, 0.0f);

	set_output_device(Outputs::CRT::Television);
	crt_->set_visible_area(crt_->get_rect_for_area(50, 224, 16 * 6, 40 * 6, 4.0f / 3.0f));
}

void VideoOutput::set_output_device(Outputs::CRT::OutputDevice output_device) {
	output_device_ = output_device;
	crt_->set_output_device(output_device);
}

void VideoOutput::set_colour_rom(const std::vector<uint8_t> &rom) {
	for(size_t c = 0; c < 8; c++) {
		size_t index = (c << 2);
		uint16_t rom_value = (uint16_t)(((uint16_t)rom[index] << 8) | (uint16_t)rom[index+1]);
		rom_value = (rom_value & 0xff00) | ((rom_value >> 4)&0x000f) | ((rom_value << 4)&0x00f0);
		colour_forms_[c] = rom_value;
	}

	// check for big endianness and byte swap if required
	uint16_t test_value = 0x0001;
	if(*(uint8_t *)&test_value != 0x01) {
		for(size_t c = 0; c < 8; c++) {
			colour_forms_[c] = (uint16_t)((colour_forms_[c] >> 8) | (colour_forms_[c] << 8));
		}
	}
}

std::shared_ptr<Outputs::CRT::CRT> VideoOutput::get_crt() {
	return crt_;
}

void VideoOutput::run_for(const Cycles cycles) {
	// Vertical: 0–39: pixels; otherwise blank; 48–53 sync, 54–56 colour burst
	// Horizontal: 0–223: pixels; otherwise blank; 256–259 sync

#define clamp(action)	\
	if(cycles_run_for <= number_of_cycles) { action; } else cycles_run_for = number_of_cycles;

	int number_of_cycles = cycles.as_int();
	while(number_of_cycles) {
		int h_counter = counter_ & 63;
		int cycles_run_for = 0;

		if(counter_ >= v_sync_start_position_ && counter_ < v_sync_end_position_) {
			// this is a sync line
			cycles_run_for = v_sync_end_position_ - counter_;
			clamp(crt_->output_sync((unsigned int)(v_sync_end_position_ - v_sync_start_position_) * 6));
		} else if(counter_ < 224*64 && h_counter < 40) {
			// this is a pixel line
			if(!h_counter) {
				ink_ = 0x7;
				paper_ = 0x0;
				use_alternative_character_set_ = use_double_height_characters_ = blink_text_ = false;
				set_character_set_base_address();
				pixel_target_ = (uint16_t *)crt_->allocate_write_area(240);

				if(!counter_) {
					frame_counter_++;

					v_sync_start_position_ = next_frame_is_sixty_hertz_ ? PAL60VSyncStartPosition : PAL50VSyncStartPosition;
					v_sync_end_position_ = next_frame_is_sixty_hertz_ ? PAL60VSyncEndPosition : PAL50VSyncEndPosition;
					counter_period_ = next_frame_is_sixty_hertz_ ? PAL60Period : PAL50Period;
				}
			}

			cycles_run_for = std::min(40 - h_counter, number_of_cycles);
			int columns = cycles_run_for;
			int pixel_base_address = 0xa000 + (counter_ >> 6) * 40;
			int character_base_address = 0xbb80 + (counter_ >> 9) * 40;
			uint8_t blink_mask = (blink_text_ && (frame_counter_&32)) ? 0x00 : 0xff;

			while(columns--) {
				uint8_t pixels, control_byte;

				if(is_graphics_mode_ && counter_ < 200*64) {
					control_byte = pixels = ram_[pixel_base_address + h_counter];
				} else {
					int address = character_base_address + h_counter;
					control_byte = ram_[address];
					int line = use_double_height_characters_ ? ((counter_ >> 7) & 7) : ((counter_ >> 6) & 7);
					pixels = ram_[character_set_base_address_ + (control_byte&127) * 8 + line];
				}

				uint8_t inverse_mask = (control_byte & 0x80) ? 0x7 : 0x0;
				pixels &= blink_mask;

				if(control_byte & 0x60) {
					if(pixel_target_) {
						uint16_t colours[2];
						if(output_device_ == Outputs::CRT::Monitor) {
							colours[0] = (uint8_t)(paper_ ^ inverse_mask);
							colours[1] = (uint8_t)(ink_ ^ inverse_mask);
						} else {
							colours[0] = colour_forms_[paper_ ^ inverse_mask];
							colours[1] = colour_forms_[ink_ ^ inverse_mask];
						}
						pixel_target_[0] = colours[(pixels >> 5)&1];
						pixel_target_[1] = colours[(pixels >> 4)&1];
						pixel_target_[2] = colours[(pixels >> 3)&1];
						pixel_target_[3] = colours[(pixels >> 2)&1];
						pixel_target_[4] = colours[(pixels >> 1)&1];
						pixel_target_[5] = colours[(pixels >> 0)&1];
					}
				} else {
					switch(control_byte & 0x1f) {
						case 0x00:		ink_ = 0x0;	break;
						case 0x01:		ink_ = 0x4;	break;
						case 0x02:		ink_ = 0x2;	break;
						case 0x03:		ink_ = 0x6;	break;
						case 0x04:		ink_ = 0x1;	break;
						case 0x05:		ink_ = 0x5;	break;
						case 0x06:		ink_ = 0x3;	break;
						case 0x07:		ink_ = 0x7;	break;

						case 0x08:	case 0x09:	case 0x0a: case 0x0b:
						case 0x0c:	case 0x0d:	case 0x0e: case 0x0f:
							use_alternative_character_set_ = (control_byte&1);
							use_double_height_characters_ = (control_byte&2);
							blink_text_ = (control_byte&4);
							set_character_set_base_address();
						break;

						case 0x10:		paper_ = 0x0;	break;
						case 0x11:		paper_ = 0x4;	break;
						case 0x12:		paper_ = 0x2;	break;
						case 0x13:		paper_ = 0x6;	break;
						case 0x14:		paper_ = 0x1;	break;
						case 0x15:		paper_ = 0x5;	break;
						case 0x16:		paper_ = 0x3;	break;
						case 0x17:		paper_ = 0x7;	break;

						case 0x18: case 0x19: case 0x1a: case 0x1b:
						case 0x1c: case 0x1d: case 0x1e: case 0x1f:
							is_graphics_mode_ = (control_byte & 4);
							next_frame_is_sixty_hertz_ = !(control_byte & 2);
						break;

						default: break;
					}
					if(pixel_target_) {
						pixel_target_[0] = pixel_target_[1] =
						pixel_target_[2] = pixel_target_[3] =
						pixel_target_[4] = pixel_target_[5] =
							(output_device_ == Outputs::CRT::Monitor) ? paper_ ^ inverse_mask : colour_forms_[paper_ ^ inverse_mask];
					}
				}
				if(pixel_target_) pixel_target_ += 6;
				h_counter++;
			}

			if(h_counter == 40) {
				crt_->output_data(40 * 6, 1);
			}
		} else {
			// this is a blank line (or the equivalent part of a pixel line)
			if(h_counter < 48) {
				cycles_run_for = 48 - h_counter;
				clamp(
					int period = (counter_ < 224*64) ? 8 : 48;
					crt_->output_blank((unsigned int)period * 6);
				);
			} else if(h_counter < 54) {
				cycles_run_for = 54 - h_counter;
				clamp(crt_->output_sync(6 * 6));
			} else if(h_counter < 56) {
				cycles_run_for = 56 - h_counter;
				clamp(crt_->output_default_colour_burst(2 * 6));
			} else {
				cycles_run_for = 64 - h_counter;
				clamp(crt_->output_blank(8 * 6));
			}
		}

		counter_ = (counter_ + cycles_run_for)%counter_period_;
		number_of_cycles -= cycles_run_for;
	}
}

void VideoOutput::set_character_set_base_address() {
	if(is_graphics_mode_) character_set_base_address_ = use_alternative_character_set_ ? 0x9c00 : 0x9800;
	else character_set_base_address_ = use_alternative_character_set_ ? 0xb800 : 0xb400;
}
<commit_msg>Updates clipped area per latest CRT response to vertical sync.<commit_after>//
//  Video.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 12/10/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "Video.hpp"

using namespace Oric;

namespace {
	const unsigned int PAL50VSyncStartPosition = 256*64;
	const unsigned int PAL60VSyncStartPosition = 234*64;
	const unsigned int PAL50VSyncEndPosition = 259*64;
	const unsigned int PAL60VSyncEndPosition = 238*64;
	const unsigned int PAL50Period = 312*64;
	const unsigned int PAL60Period = 262*64;
}

VideoOutput::VideoOutput(uint8_t *memory) :
		ram_(memory),
		frame_counter_(0), counter_(0),
		is_graphics_mode_(false),
		character_set_base_address_(0xb400),
		v_sync_start_position_(PAL50VSyncStartPosition), v_sync_end_position_(PAL50VSyncEndPosition),
		counter_period_(PAL50Period), next_frame_is_sixty_hertz_(false),
		crt_(new Outputs::CRT::CRT(64*6, 6, Outputs::CRT::DisplayType::PAL50, 2)) {
	crt_->set_rgb_sampling_function(
		"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
		"{"
			"uint texValue = texture(sampler, coordinate).r;"
			"return vec3( uvec3(texValue) & uvec3(4u, 2u, 1u));"
		"}");
	crt_->set_composite_sampling_function(
		"float composite_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate, float phase, float amplitude)"
		"{"
			"uint texValue = uint(dot(texture(sampler, coordinate).rg, uvec2(1, 256)));"
			"uint iPhase = uint((phase + 3.141592654 + 0.39269908175) * 2.0 / 3.141592654) & 3u;"
			"texValue = (texValue >> (4u*(3u - iPhase))) & 15u;"
			"return (float(texValue) - 4.0) / 20.0;"
		"}"
	);
	crt_->set_composite_function_type(Outputs::CRT::CRT::CompositeSourceType::DiscreteFourSamplesPerCycle, 0.0f);

	set_output_device(Outputs::CRT::Television);
	crt_->set_visible_area(crt_->get_rect_for_area(53, 224, 16 * 6, 40 * 6, 4.0f / 3.0f));
}

void VideoOutput::set_output_device(Outputs::CRT::OutputDevice output_device) {
	output_device_ = output_device;
	crt_->set_output_device(output_device);
}

void VideoOutput::set_colour_rom(const std::vector<uint8_t> &rom) {
	for(size_t c = 0; c < 8; c++) {
		size_t index = (c << 2);
		uint16_t rom_value = (uint16_t)(((uint16_t)rom[index] << 8) | (uint16_t)rom[index+1]);
		rom_value = (rom_value & 0xff00) | ((rom_value >> 4)&0x000f) | ((rom_value << 4)&0x00f0);
		colour_forms_[c] = rom_value;
	}

	// check for big endianness and byte swap if required
	uint16_t test_value = 0x0001;
	if(*(uint8_t *)&test_value != 0x01) {
		for(size_t c = 0; c < 8; c++) {
			colour_forms_[c] = (uint16_t)((colour_forms_[c] >> 8) | (colour_forms_[c] << 8));
		}
	}
}

std::shared_ptr<Outputs::CRT::CRT> VideoOutput::get_crt() {
	return crt_;
}

void VideoOutput::run_for(const Cycles cycles) {
	// Vertical: 0–39: pixels; otherwise blank; 48–53 sync, 54–56 colour burst
	// Horizontal: 0–223: pixels; otherwise blank; 256–259 sync

#define clamp(action)	\
	if(cycles_run_for <= number_of_cycles) { action; } else cycles_run_for = number_of_cycles;

	int number_of_cycles = cycles.as_int();
	while(number_of_cycles) {
		int h_counter = counter_ & 63;
		int cycles_run_for = 0;

		if(counter_ >= v_sync_start_position_ && counter_ < v_sync_end_position_) {
			// this is a sync line
			cycles_run_for = v_sync_end_position_ - counter_;
			clamp(crt_->output_sync((unsigned int)(v_sync_end_position_ - v_sync_start_position_) * 6));
		} else if(counter_ < 224*64 && h_counter < 40) {
			// this is a pixel line
			if(!h_counter) {
				ink_ = 0x7;
				paper_ = 0x0;
				use_alternative_character_set_ = use_double_height_characters_ = blink_text_ = false;
				set_character_set_base_address();
				pixel_target_ = (uint16_t *)crt_->allocate_write_area(240);

				if(!counter_) {
					frame_counter_++;

					v_sync_start_position_ = next_frame_is_sixty_hertz_ ? PAL60VSyncStartPosition : PAL50VSyncStartPosition;
					v_sync_end_position_ = next_frame_is_sixty_hertz_ ? PAL60VSyncEndPosition : PAL50VSyncEndPosition;
					counter_period_ = next_frame_is_sixty_hertz_ ? PAL60Period : PAL50Period;
				}
			}

			cycles_run_for = std::min(40 - h_counter, number_of_cycles);
			int columns = cycles_run_for;
			int pixel_base_address = 0xa000 + (counter_ >> 6) * 40;
			int character_base_address = 0xbb80 + (counter_ >> 9) * 40;
			uint8_t blink_mask = (blink_text_ && (frame_counter_&32)) ? 0x00 : 0xff;

			while(columns--) {
				uint8_t pixels, control_byte;

				if(is_graphics_mode_ && counter_ < 200*64) {
					control_byte = pixels = ram_[pixel_base_address + h_counter];
				} else {
					int address = character_base_address + h_counter;
					control_byte = ram_[address];
					int line = use_double_height_characters_ ? ((counter_ >> 7) & 7) : ((counter_ >> 6) & 7);
					pixels = ram_[character_set_base_address_ + (control_byte&127) * 8 + line];
				}

				uint8_t inverse_mask = (control_byte & 0x80) ? 0x7 : 0x0;
				pixels &= blink_mask;

				if(control_byte & 0x60) {
					if(pixel_target_) {
						uint16_t colours[2];
						if(output_device_ == Outputs::CRT::Monitor) {
							colours[0] = (uint8_t)(paper_ ^ inverse_mask);
							colours[1] = (uint8_t)(ink_ ^ inverse_mask);
						} else {
							colours[0] = colour_forms_[paper_ ^ inverse_mask];
							colours[1] = colour_forms_[ink_ ^ inverse_mask];
						}
						pixel_target_[0] = colours[(pixels >> 5)&1];
						pixel_target_[1] = colours[(pixels >> 4)&1];
						pixel_target_[2] = colours[(pixels >> 3)&1];
						pixel_target_[3] = colours[(pixels >> 2)&1];
						pixel_target_[4] = colours[(pixels >> 1)&1];
						pixel_target_[5] = colours[(pixels >> 0)&1];
					}
				} else {
					switch(control_byte & 0x1f) {
						case 0x00:		ink_ = 0x0;	break;
						case 0x01:		ink_ = 0x4;	break;
						case 0x02:		ink_ = 0x2;	break;
						case 0x03:		ink_ = 0x6;	break;
						case 0x04:		ink_ = 0x1;	break;
						case 0x05:		ink_ = 0x5;	break;
						case 0x06:		ink_ = 0x3;	break;
						case 0x07:		ink_ = 0x7;	break;

						case 0x08:	case 0x09:	case 0x0a: case 0x0b:
						case 0x0c:	case 0x0d:	case 0x0e: case 0x0f:
							use_alternative_character_set_ = (control_byte&1);
							use_double_height_characters_ = (control_byte&2);
							blink_text_ = (control_byte&4);
							set_character_set_base_address();
						break;

						case 0x10:		paper_ = 0x0;	break;
						case 0x11:		paper_ = 0x4;	break;
						case 0x12:		paper_ = 0x2;	break;
						case 0x13:		paper_ = 0x6;	break;
						case 0x14:		paper_ = 0x1;	break;
						case 0x15:		paper_ = 0x5;	break;
						case 0x16:		paper_ = 0x3;	break;
						case 0x17:		paper_ = 0x7;	break;

						case 0x18: case 0x19: case 0x1a: case 0x1b:
						case 0x1c: case 0x1d: case 0x1e: case 0x1f:
							is_graphics_mode_ = (control_byte & 4);
							next_frame_is_sixty_hertz_ = !(control_byte & 2);
						break;

						default: break;
					}
					if(pixel_target_) {
						pixel_target_[0] = pixel_target_[1] =
						pixel_target_[2] = pixel_target_[3] =
						pixel_target_[4] = pixel_target_[5] =
							(output_device_ == Outputs::CRT::Monitor) ? paper_ ^ inverse_mask : colour_forms_[paper_ ^ inverse_mask];
					}
				}
				if(pixel_target_) pixel_target_ += 6;
				h_counter++;
			}

			if(h_counter == 40) {
				crt_->output_data(40 * 6, 1);
			}
		} else {
			// this is a blank line (or the equivalent part of a pixel line)
			if(h_counter < 48) {
				cycles_run_for = 48 - h_counter;
				clamp(
					int period = (counter_ < 224*64) ? 8 : 48;
					crt_->output_blank((unsigned int)period * 6);
				);
			} else if(h_counter < 54) {
				cycles_run_for = 54 - h_counter;
				clamp(crt_->output_sync(6 * 6));
			} else if(h_counter < 56) {
				cycles_run_for = 56 - h_counter;
				clamp(crt_->output_default_colour_burst(2 * 6));
			} else {
				cycles_run_for = 64 - h_counter;
				clamp(crt_->output_blank(8 * 6));
			}
		}

		counter_ = (counter_ + cycles_run_for)%counter_period_;
		number_of_cycles -= cycles_run_for;
	}
}

void VideoOutput::set_character_set_base_address() {
	if(is_graphics_mode_) character_set_base_address_ = use_alternative_character_set_ ? 0x9c00 : 0x9800;
	else character_set_base_address_ = use_alternative_character_set_ ? 0xb800 : 0xb400;
}
<|endoftext|>


<commit_before>/*
 * fits.cpp
 *
 *  Created on: Jun 19, 2012
 *      Author: mpetkova
 */

#ifdef WITH_MOKA

#include <MOKAfits.h>
#include <CCfits/CCfits>

using namespace CCfits;

void getDims(std::string fn
	     ,int *nx
	     ,int *ny){

	try{
		std::auto_ptr<FITS> ff(new FITS (fn, Read));

		PHDU *h0=&ff->pHDU();

		*nx=h0->axis(0);
		*ny=h0->axis(1);
	}
	catch(FITS::CantOpen){
		std::cout << "can not open " << fn << std::endl;
		exit(1);
	}
}

/*
 * reads in the fits file for the MOKA map and saves it in the structure map
 */
void readImage(std::string fn
		,std::valarray<float> *convergence
		,std::valarray<float> *alpha1
		,std::valarray<float> *alpha2
		,std::valarray<float> *gamma1
		,std::valarray<float> *gamma2
	       ,struct LensHalo *LH){

	int nx,ny;

	std::auto_ptr<FITS> ff(new FITS (fn, Read));

	PHDU *h0=&ff->pHDU();

	nx=h0->axis(0);
	ny=h0->axis(1);

	h0->read(*convergence);

	h0->readKey ("SIDEL",LH->boxlarcsec);
	h0->readKey ("SIDEL2",LH->boxlMpc);
	h0->readKey ("ZLENS",LH->zl);
	h0->readKey ("ZSOURCE",LH->zs);
	h0->readKey ("OMEGA",LH->omegam);
	h0->readKey ("LAMBDA",LH->omegal);
	h0->readKey ("H",LH->h);
	h0->readKey ("W",LH->wq);
	h0->readKey ("MSTAR",LH->mstar);
	h0->readKey ("MVIR",LH->m);
	h0->readKey ("CONCENTRATION",LH->c);
	h0->readKey ("DL",LH->DL);
	h0->readKey ("DLS",LH->DLS);
	h0->readKey ("DS",LH->DS);

	ExtHDU &h1=ff->extension(1);
	h1.read(*alpha1);
	ExtHDU &h2=ff->extension(2);
	h2.read(*alpha2);
	ExtHDU &h3=ff->extension(3);
	h3.read(*gamma1);
	ExtHDU &h4=ff->extension(4);
	h4.read(*gamma2);

	std::cout << *h0 << h1 << h2 << h3  << h4 << std::endl;
}

/*
 * write the fits file of the new MOKA map from the structure map
 */
void writeImage(std::string filename
		,std::valarray<float> convergence
		,std::valarray<float> gamma1
		,std::valarray<float> gamma2
		,std::valarray<float> gamma3
		,int nx
		,int ny
		,struct LensHalo LH){

	long naxis=2;
	long naxes[2]={nx,ny};

	std::auto_ptr<FITS> fout(0);

	try{
		fout.reset(new FITS(filename,FLOAT_IMG,naxis,naxes));
	}
	catch(FITS::CantCreate){
		exit(1);
	}

	std::vector<long> naxex(2);
	naxex[0]=nx;
	naxex[1]=ny;

	PHDU *phout=&fout->pHDU();

	phout->write( 1,nx*ny,convergence );

	phout->addKey ("SIDEL",LH.boxlarcsec,"arcsec");
	phout->addKey ("SIDEL2",LH.boxlMpc,"Mpc/h");
	phout->addKey ("ZLENS",LH.zl,"lens redshift");
	phout->addKey ("ZSOURCE",LH.zs, "source redshift");
	phout->addKey ("OMEGA",LH.omegam,"omega matter");
	phout->addKey ("LAMBDA",LH.omegal,"omega lamda");
	phout->addKey ("H",LH.h,"hubble/100");
	phout->addKey ("W",LH.wq,"dark energy equation of state parameter");
	phout->addKey ("MSTAR",LH.mstar,"stellar mass of the BCG in Msun/h");
	phout->addKey ("MVIR",LH.m,"virial mass of the halo in Msun/h");
	phout->addKey ("CONCENTRATION",LH.c,"NFW concentration");
	phout->addKey ("DL",LH.DL,"Mpc/h");
	phout->addKey ("DLS",LH.DLS,"Mpc/h");
	phout->addKey ("DS",LH.DS,"Mpc/h");

	ExtHDU *eh1=fout->addImage("gamma1", FLOAT_IMG, naxex);
	eh1->write(1,nx*ny,gamma1);
	ExtHDU *eh2=fout->addImage("gamma2", FLOAT_IMG, naxex);
	eh2->write(1,nx*ny,gamma2);
	ExtHDU *eh3=fout->addImage("gamma3", FLOAT_IMG, naxex);
	eh3->write(1,nx*ny,gamma3);

	std::cout << *phout << std::endl;

}

/*
 * routine used by fof to link nearby grid cell points
 */

void make_friendship(int ii,int ji,int np,std:: vector<int> &friends, std:: vector<double> &pointdist){
  for(int jj=0;jj<np;jj++){
    if(friends[ji+np*jj]!=0){
      if(friends[ji+np*jj]<0){
	friends[ii+np*jj]=-(ii+1);
      }
      else{
	friends[ii+np*jj]=(ii+1);
      }
      friends[ji+np*jj]=0;
    }
  }
  friends[ii+np*ji]=-(ii+1);
}

/*
 * given a a set of grid points xci and yci and an interpixeld distance l return the id of the
 * fof group of each cell point
 */

int fof(double l,std:: vector<double> xci, std:: vector<double> yci, std:: vector<int> &groupid){
  int np = xci.size();
  std:: vector<int> friends(np*np);
  std:: vector<double> pointdist(np*np);
  for(int ii = 0;ii<np; ii++) for(int ji = 0;ji<np; ji++){
      pointdist[ii+np*ji] = sqrt( pow(xci[ii] - xci[ji],2) + pow(yci[ii] - yci[ji],2));
      groupid[ii] = 0;
      friends[ii+np*ji]=0;
    }
  for(int ii=0;ii<np;ii++) for(int ji = 0;ji<np; ji++){
      // consider as friends grid points less distant than 1.5 x l
      if(pointdist[ii+np*ji]<=1.5*l) friends[ii+np*ji] = ii+1;
    }
  for(int ii=0;ii<np;ii++){
    int r = 0;
    while(r==0){
      r=1;
      for(int ji=0;ji<np;ji++){
	if(friends[ii+np*ji]>0){
	  if(ii!=ji){
	    make_friendship(ii,ji,np,friends,pointdist);
	    r=0;
	  }
	}
      }
    }
  }
  for(int ii=0;ii<np;ii++){
    int p=0;
    for(int ji=0;ji<np;ji++){
      if(friends[ji+np*ii]!=0) p++;
      if(p==2){
	std:: cout << ji << "  " << ii << ":  "  << friends[ji+np*ii] << "  " << friends[ii+np*ji] << std:: endl;
	exit(1);
      }
    }
  }
  // count the particles in each group
  int kt = 0;
  int ng= 0;
  for(int ii=0;ii<np;ii++){
    int k = 0;
    for(int ji=0;ji<np;ji++){
      if(friends[ii+np*ji]!=0){
	k++;
	groupid[ji]=ii+1;
      }
    }
    if(k>0){
      ng++;
    }
    kt = kt + k;
  }
  if(kt != np){
    std:: cout << " number of screaned particles : " << kt << std:: endl;
    std:: cout << " differes from the number of particles : " << np << std:: endl;
    std:: cout << " number of group found : " << ng << std:: endl;
    std:: cout << "     " << std:: endl;
    std:: cout << " I will STOP here!!! " << std:: endl;
    exit(1);
  }
  /* Make a histogram of the data */
  std::vector< int > histogram(np,0);
  std::vector< int >::iterator it = groupid.begin();
  while(it != groupid.end()) histogram[*it++]++;
  int mode = std::max_element(histogram.begin(),histogram.end()) - histogram.begin();
  return mode;
}

#endif
<commit_msg>check if noisy fits file exists...if so it stop<commit_after>/*
 * fits.cpp
 *
 *  Created on: Jun 19, 2012
 *      Author: mpetkova
 */

#ifdef WITH_MOKA

#include <MOKAfits.h>
#include <fstream>
#include <CCfits/CCfits>

using namespace CCfits;

void getDims(std::string fn
	     ,int *nx
	     ,int *ny){

	try{
		std::auto_ptr<FITS> ff(new FITS (fn, Read));

		PHDU *h0=&ff->pHDU();

		*nx=h0->axis(0);
		*ny=h0->axis(1);
	}
	catch(FITS::CantOpen){
		std::cout << "can not open " << fn << std::endl;
		exit(1);
	}
}

/*
 * reads in the fits file for the MOKA map and saves it in the structure map
 */
void readImage(std::string fn
		,std::valarray<float> *convergence
		,std::valarray<float> *alpha1
		,std::valarray<float> *alpha2
		,std::valarray<float> *gamma1
		,std::valarray<float> *gamma2
	       ,struct LensHalo *LH){

	int nx,ny;

	std:: cout << " reading MOKA file: " << fn << std:: endl;

	std::ostringstream checkfout;
	checkfout << fn << "_noisy.fits";
	std:: string checkfilenameout = checkfout.str();
	std:: ifstream checkfileout;
	checkfileout.open(checkfilenameout.c_str());
	if(checkfileout.is_open()){
	  std:: cout << checkfilenameout << " exists I will STOP here " << std:: endl;
	  std:: cout << "     halo already processed! " << std:: endl;
	  exit(1);
	}

	std::auto_ptr<FITS> ff(new FITS (fn, Read));

	PHDU *h0=&ff->pHDU();

	nx=h0->axis(0);
	ny=h0->axis(1);

	h0->read(*convergence);

	h0->readKey ("SIDEL",LH->boxlarcsec);
	h0->readKey ("SIDEL2",LH->boxlMpc);
	h0->readKey ("ZLENS",LH->zl);
	h0->readKey ("ZSOURCE",LH->zs);
	h0->readKey ("OMEGA",LH->omegam);
	h0->readKey ("LAMBDA",LH->omegal);
	h0->readKey ("H",LH->h);
	h0->readKey ("W",LH->wq);
	h0->readKey ("MSTAR",LH->mstar);
	h0->readKey ("MVIR",LH->m);
	h0->readKey ("CONCENTRATION",LH->c);
	h0->readKey ("DL",LH->DL);
	h0->readKey ("DLS",LH->DLS);
	h0->readKey ("DS",LH->DS);

	ExtHDU &h1=ff->extension(1);
	h1.read(*alpha1);
	ExtHDU &h2=ff->extension(2);
	h2.read(*alpha2);
	ExtHDU &h3=ff->extension(3);
	h3.read(*gamma1);
	ExtHDU &h4=ff->extension(4);
	h4.read(*gamma2);

	std::cout << *h0 << h1 << h2 << h3  << h4 << std::endl;
}

/*
 * write the fits file of the new MOKA map from the structure map
 */
void writeImage(std::string filename
		,std::valarray<float> convergence
		,std::valarray<float> gamma1
		,std::valarray<float> gamma2
		,std::valarray<float> gamma3
		,int nx
		,int ny
		,struct LensHalo LH){

	long naxis=2;
	long naxes[2]={nx,ny};

	std::auto_ptr<FITS> fout(0);

	try{
		fout.reset(new FITS(filename,FLOAT_IMG,naxis,naxes));
	}
	catch(FITS::CantCreate){
		exit(1);
	}

	std::vector<long> naxex(2);
	naxex[0]=nx;
	naxex[1]=ny;

	PHDU *phout=&fout->pHDU();

	phout->write( 1,nx*ny,convergence );

	phout->addKey ("SIDEL",LH.boxlarcsec,"arcsec");
	phout->addKey ("SIDEL2",LH.boxlMpc,"Mpc/h");
	phout->addKey ("ZLENS",LH.zl,"lens redshift");
	phout->addKey ("ZSOURCE",LH.zs, "source redshift");
	phout->addKey ("OMEGA",LH.omegam,"omega matter");
	phout->addKey ("LAMBDA",LH.omegal,"omega lamda");
	phout->addKey ("H",LH.h,"hubble/100");
	phout->addKey ("W",LH.wq,"dark energy equation of state parameter");
	phout->addKey ("MSTAR",LH.mstar,"stellar mass of the BCG in Msun/h");
	phout->addKey ("MVIR",LH.m,"virial mass of the halo in Msun/h");
	phout->addKey ("CONCENTRATION",LH.c,"NFW concentration");
	phout->addKey ("DL",LH.DL,"Mpc/h");
	phout->addKey ("DLS",LH.DLS,"Mpc/h");
	phout->addKey ("DS",LH.DS,"Mpc/h");

	ExtHDU *eh1=fout->addImage("gamma1", FLOAT_IMG, naxex);
	eh1->write(1,nx*ny,gamma1);
	ExtHDU *eh2=fout->addImage("gamma2", FLOAT_IMG, naxex);
	eh2->write(1,nx*ny,gamma2);
	ExtHDU *eh3=fout->addImage("gamma3", FLOAT_IMG, naxex);
	eh3->write(1,nx*ny,gamma3);

	std::cout << *phout << std::endl;

}

/*
 * routine used by fof to link nearby grid cell points
 */

void make_friendship(int ii,int ji,int np,std:: vector<int> &friends, std:: vector<double> &pointdist){
  for(int jj=0;jj<np;jj++){
    if(friends[ji+np*jj]!=0){
      if(friends[ji+np*jj]<0){
	friends[ii+np*jj]=-(ii+1);
      }
      else{
	friends[ii+np*jj]=(ii+1);
      }
      friends[ji+np*jj]=0;
    }
  }
  friends[ii+np*ji]=-(ii+1);
}

/*
 * given a a set of grid points xci and yci and an interpixeld distance l return the id of the
 * fof group of each cell point
 */

int fof(double l,std:: vector<double> xci, std:: vector<double> yci, std:: vector<int> &groupid){
  int np = xci.size();
  std:: vector<int> friends(np*np);
  std:: vector<double> pointdist(np*np);
  for(int ii = 0;ii<np; ii++) for(int ji = 0;ji<np; ji++){
      pointdist[ii+np*ji] = sqrt( pow(xci[ii] - xci[ji],2) + pow(yci[ii] - yci[ji],2));
      groupid[ii] = 0;
      friends[ii+np*ji]=0;
    }
  for(int ii=0;ii<np;ii++) for(int ji = 0;ji<np; ji++){
      // consider as friends grid points less distant than 1.5 x l
      if(pointdist[ii+np*ji]<=1.5*l) friends[ii+np*ji] = ii+1;
    }
  for(int ii=0;ii<np;ii++){
    int r = 0;
    while(r==0){
      r=1;
      for(int ji=0;ji<np;ji++){
	if(friends[ii+np*ji]>0){
	  if(ii!=ji){
	    make_friendship(ii,ji,np,friends,pointdist);
	    r=0;
	  }
	}
      }
    }
  }
  for(int ii=0;ii<np;ii++){
    int p=0;
    for(int ji=0;ji<np;ji++){
      if(friends[ji+np*ii]!=0) p++;
      if(p==2){
	std:: cout << ji << "  " << ii << ":  "  << friends[ji+np*ii] << "  " << friends[ii+np*ji] << std:: endl;
	exit(1);
      }
    }
  }
  // count the particles in each group
  int kt = 0;
  int ng= 0;
  for(int ii=0;ii<np;ii++){
    int k = 0;
    for(int ji=0;ji<np;ji++){
      if(friends[ii+np*ji]!=0){
	k++;
	groupid[ji]=ii+1;
      }
    }
    if(k>0){
      ng++;
    }
    kt = kt + k;
  }
  if(kt != np){
    std:: cout << " number of screaned particles : " << kt << std:: endl;
    std:: cout << " differes from the number of particles : " << np << std:: endl;
    std:: cout << " number of group found : " << ng << std:: endl;
    std:: cout << "     " << std:: endl;
    std:: cout << " I will STOP here!!! " << std:: endl;
    exit(1);
  }
  /* Make a histogram of the data */
  std::vector< int > histogram(np,0);
  std::vector< int >::iterator it = groupid.begin();
  while(it != groupid.end()) histogram[*it++]++;
  int mode = std::max_element(histogram.begin(),histogram.end()) - histogram.begin();
  return mode;
}

#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 * ctrl_text.cpp
 *****************************************************************************
 * Copyright (C) 2003 the VideoLAN team
 * $Id$
 *
 * Authors: Cyril Deguet     <asmax@via.ecp.fr>
 *          Olivier Teulière <ipkiss@via.ecp.fr>
 *          Erwan Tulou      <erwan10 At videolan Dot org<
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "ctrl_text.hpp"
#include "../events/evt_generic.hpp"
#include "../events/evt_mouse.hpp"
#include "../src/generic_bitmap.hpp"
#include "../src/generic_font.hpp"
#include "../src/os_factory.hpp"
#include "../src/os_graphics.hpp"
#include "../src/os_timer.hpp"
#include "../utils/position.hpp"
#include "../utils/ustring.hpp"
#include "../utils/var_text.hpp"

#define MOVING_TEXT_STEP 1
#define MOVING_TEXT_DELAY 30
#define SEPARATOR_STRING "   "

CtrlText::CtrlText( intf_thread_t *pIntf, VarText &rVariable,
                    const GenericFont &rFont, const UString &rHelp,
                    uint32_t color, VarBool *pVisible, VarBool *pFocus,
                    Scrolling_t scrollMode, Align_t alignment ):
    CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ),
    m_rVariable( rVariable ), m_cmdToManual( this ),
    m_cmdManualMoving( this ), m_cmdManualStill( this ),
    m_cmdMove( this ), m_pEvt( NULL ), m_rFont( rFont ),
    m_color( color ), m_scrollMode( scrollMode ), m_alignment( alignment ),
    m_pFocus( pFocus), m_pImg( NULL ), m_pImgDouble( NULL ),
    m_pCurrImg( NULL ), m_xPos( 0 ), m_xOffset( 0 ),
    m_cmdUpdateText( this )
{
    m_pTimer = OSFactory::instance( pIntf )->createOSTimer( m_cmdUpdateText );

    // States
    m_fsm.addState( "still" );
    m_fsm.addState( "moving" );
    m_fsm.addState( "manual1" );
    m_fsm.addState( "manual2" );
    m_fsm.addState( "outStill" );
    m_fsm.addState( "outMoving" );

    // Transitions
    m_fsm.addTransition( "still", "leave", "outStill" );
    m_fsm.addTransition( "outStill", "enter", "still" );
    if( m_scrollMode == kManual )
    {
        m_fsm.addTransition( "still", "mouse:left:down", "manual1",
                             &m_cmdToManual );
        m_fsm.addTransition( "manual1", "mouse:left:up", "still",
                             &m_cmdManualStill );
        m_fsm.addTransition( "manual1", "motion", "manual1", &m_cmdMove );
    }
    else if( m_scrollMode == kAutomatic )
    {
        m_fsm.addTransition( "still", "mouse:left:down", "manual1",
                             &m_cmdToManual );
        m_fsm.addTransition( "manual1", "mouse:left:up", "moving",
                             &m_cmdManualMoving );
        m_fsm.addTransition( "moving", "mouse:left:down", "manual2",
                             &m_cmdToManual );
        m_fsm.addTransition( "manual2", "mouse:left:up", "still",
                             &m_cmdManualStill );
        m_fsm.addTransition( "manual1", "motion", "manual1", &m_cmdMove );
        m_fsm.addTransition( "manual2", "motion", "manual2", &m_cmdMove );
        m_fsm.addTransition( "moving", "leave", "outMoving" );
        m_fsm.addTransition( "outMoving", "enter", "moving" );
    }

    // Initial state
    m_fsm.setState( (m_scrollMode != kAutomatic) ? "outStill" : "outMoving" );

    // Observe the variable
    m_rVariable.addObserver( this );

    // initialize pictures
    setPictures( m_rVariable.get() );
}

CtrlText::~CtrlText()
{
    m_rVariable.delObserver( this );
    delete m_pTimer;
    delete m_pImg;
    delete m_pImgDouble;
}

void CtrlText::handleEvent( EvtGeneric &rEvent )
{
    // Save the event to use it in callbacks
    m_pEvt = &rEvent;

    m_fsm.handleTransition( rEvent.getAsString() );
}

bool CtrlText::mouseOver( int x, int y ) const
{
    if( !m_pFocus->get() )
        return false;

    if( m_pCurrImg )
    {
        // We have 3 different ways of deciding when to return true here:
        //  1) the mouse is exactly over the text (so if you click between two
        //     letters, the text control doesn't catch the event)
        //  2) the mouse is over the rectangle of the control
        //  3) the mouse is over the rectangle of the visible text
        // I don't know which one is the best...
#if 0
        return( x >= 0 && x < getPosition()->getWidth()
             && m_pCurrImg->hit( x - m_xPos, y ) );
#endif
#if 1
        return( x >= 0 && x < getPosition()->getWidth()
             && y >= 0 && y < getPosition()->getHeight() );
#endif
#if 0
        return( x >= 0 && x < getPosition()->getWidth()
             && y >= 0 && y < getPosition()->getHeight()
             && x < m_pCurrImg->getWidth() && x < m_pCurrImg->getHeight() );
#endif
    }
    else
    {
        return false;
    }
}

void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{
    rect clip( xDest, yDest, w, h );
    const Position *pPos = getPosition();
    if( m_pCurrImg )
    {
        // Compute the dimensions to draw
        int width = min( m_pCurrImg->getWidth() + m_xPos,
                         getPosition()->getWidth() );
        int height = min( m_pCurrImg->getHeight(), getPosition()->getHeight() );
        // Draw the current image
        if( width > 0 && height > 0 )
        {
            int offset = 0;
            if( m_alignment == kLeft )
            {
                // We align to the left
                offset = 0;
            }
            else if( m_alignment == kRight &&
                     width < getPosition()->getWidth() )

            {
                // The text is shorter than the width of the control, so we
                // can align it to the right
                offset = getPosition()->getWidth() - width;
            }
            else if( m_alignment == kCenter &&
                     width < getPosition()->getWidth() )
            {
                // The text is shorter than the width of the control, so we
                // can center it
                offset = (getPosition()->getWidth() - width) / 2;
            }
            rect region( pPos->getLeft() + offset,
                         pPos->getTop(), width, height );
            rect inter;
            if( rect::intersect( region, clip, &inter ) )
                rImage.drawBitmap( *m_pCurrImg, -m_xPos + inter.x - region.x,
                                   inter.y - region.y,
                                   inter.x, inter.y,
                                   inter.width, inter.height, true );
        }
    }
}

void CtrlText::setText( const UString &rText, uint32_t color )
{
    // Change the color
    if( color != 0xFFFFFFFF )
    {
        m_color = color;
    }

    // Change the text
    m_rVariable.set( rText );
}

void CtrlText::onUpdate( Subject<VarText> &rVariable, void* arg )
{
    (void)rVariable; (void)arg;
    if( isVisible() )
    {
        setPictures( m_rVariable.get() );
        updateContext();
        notifyLayout( getPosition()->getWidth(), getPosition()->getHeight() );
    }
}

void CtrlText::onUpdate( Subject<VarBool> &rVariable, void *arg  )
{
    (void)arg;
    // Visibility changed
    if( &rVariable == m_pVisible )
    {
        if( isVisible() )
        {
            setPictures( m_rVariable.get() );
            updateContext();
            notifyLayout( getPosition()->getWidth(), getPosition()->getHeight() );
        }
    }
}

void CtrlText::setPictures( const UString &rText )
{
    // reset the images ('normal' and 'double') from the text
    // 'Normal' image
    delete m_pImg;
    m_pImg = m_rFont.drawString( rText, m_color );
    if( !m_pImg )
        return;

    // 'Double' image
    const UString doubleStringWithSep = rText + SEPARATOR_STRING + rText;
    delete m_pImgDouble;
    m_pImgDouble = m_rFont.drawString( doubleStringWithSep, m_color );
}

void CtrlText::updateContext()
{
    if( !m_pImg || !getPosition() )
        return;

    if( m_pImg->getWidth() < getPosition()->getWidth() )
    {
        m_pCurrImg = m_pImg;

        // When the control becomes wide enough for the text to display,
        // make sure to stop any scrolling effect
        m_pTimer->stop();
        m_xPos = 0;
    }
    else
    {
        m_pCurrImg = m_pImgDouble;
    }

    // If the control is in the moving state,
    // automatically start or stop the timer accordingly
    const string &rState = m_fsm.getState();
    if( rState == "moving" || rState == "outMoving" )
    {
        if( m_pCurrImg == m_pImgDouble )
        {
            m_pTimer->start( MOVING_TEXT_DELAY, false );
        }
        else
        {
            m_pTimer->stop();
        }
    }

    // compute alignment
    if( m_alignment == kRight &&
        getPosition()->getWidth() < m_pImg->getWidth() )
    {
        m_xPos = getPosition()->getWidth() - m_pImg->getWidth();
    }
    else if( m_alignment == kCenter &&
             getPosition()->getWidth() < m_pImg->getWidth() )
    {
        m_xPos = (getPosition()->getWidth() - m_pImg->getWidth()) / 2;
    }
    else
    {
        m_xPos = 0;
    }
}

void CtrlText::onPositionChange()
{
    updateContext();
}

void CtrlText::onResize()
{
    updateContext();
}

void CtrlText::CmdToManual::execute()
{
    EvtMouse *pEvtMouse = (EvtMouse*)m_pParent->m_pEvt;

    // Compute the offset
    m_pParent->m_xOffset = pEvtMouse->getXPos() - m_pParent->m_xPos;

    m_pParent->m_pTimer->stop();
    m_pParent->captureMouse();
}

void CtrlText::CmdManualMoving::execute()
{
    m_pParent->releaseMouse();

    // Start the automatic movement, but only if the text is wider than the
    // control and if the control can scroll (either in manual or automatic
    // mode)
    if( m_pParent->m_pCurrImg &&
        m_pParent->m_pCurrImg == m_pParent->m_pImgDouble )
    {
        m_pParent->m_pTimer->start( MOVING_TEXT_DELAY, false );
    }
}

void CtrlText::CmdManualStill::execute()
{
    m_pParent->releaseMouse();
}

void CtrlText::CmdMove::execute()
{
    EvtMouse *pEvtMouse = (EvtMouse*)m_pParent->m_pEvt;

    // Move text only when it is larger than the control
    if( m_pParent->m_pCurrImg &&
        m_pParent->m_pCurrImg == m_pParent->m_pImgDouble )
    {
        // Compute the new position of the left side, and make sure it is
        // in the correct range
        m_pParent->m_xPos = (pEvtMouse->getXPos() - m_pParent->m_xOffset);
        m_pParent->adjust( m_pParent->m_xPos );

        m_pParent->notifyLayout( m_pParent->getPosition()->getWidth(),
                                 m_pParent->getPosition()->getHeight() );
    }
}

void CtrlText::CmdUpdateText::execute()
{
    m_pParent->m_xPos -= MOVING_TEXT_STEP;
    m_pParent->adjust( m_pParent->m_xPos );

    m_pParent->notifyLayout( m_pParent->getPosition()->getWidth(),
                             m_pParent->getPosition()->getHeight() );
}

void CtrlText::adjust( int &position )
{
    if( !m_pImg || !m_pImgDouble )
        return;

    // {m_pImgDouble->getWidth() - m_pImg->getWidth()} is the period of the
    // bitmap; remember that the string used to generate m_pImgDouble is of the
    // form: "foo  foo", the number of spaces being a parameter
    position %= m_pImgDouble->getWidth() - m_pImg->getWidth();
    if( position > 0 )
    {
        position -= m_pImgDouble->getWidth() - m_pImg->getWidth();
    }
}

<commit_msg>skins2: fix forgotten notify in text control<commit_after>/*****************************************************************************
 * ctrl_text.cpp
 *****************************************************************************
 * Copyright (C) 2003 the VideoLAN team
 * $Id$
 *
 * Authors: Cyril Deguet     <asmax@via.ecp.fr>
 *          Olivier Teulière <ipkiss@via.ecp.fr>
 *          Erwan Tulou      <erwan10 At videolan Dot org<
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "ctrl_text.hpp"
#include "../events/evt_generic.hpp"
#include "../events/evt_mouse.hpp"
#include "../src/generic_bitmap.hpp"
#include "../src/generic_font.hpp"
#include "../src/os_factory.hpp"
#include "../src/os_graphics.hpp"
#include "../src/os_timer.hpp"
#include "../utils/position.hpp"
#include "../utils/ustring.hpp"
#include "../utils/var_text.hpp"

#define MOVING_TEXT_STEP 1
#define MOVING_TEXT_DELAY 30
#define SEPARATOR_STRING "   "

CtrlText::CtrlText( intf_thread_t *pIntf, VarText &rVariable,
                    const GenericFont &rFont, const UString &rHelp,
                    uint32_t color, VarBool *pVisible, VarBool *pFocus,
                    Scrolling_t scrollMode, Align_t alignment ):
    CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ),
    m_rVariable( rVariable ), m_cmdToManual( this ),
    m_cmdManualMoving( this ), m_cmdManualStill( this ),
    m_cmdMove( this ), m_pEvt( NULL ), m_rFont( rFont ),
    m_color( color ), m_scrollMode( scrollMode ), m_alignment( alignment ),
    m_pFocus( pFocus), m_pImg( NULL ), m_pImgDouble( NULL ),
    m_pCurrImg( NULL ), m_xPos( 0 ), m_xOffset( 0 ),
    m_cmdUpdateText( this )
{
    m_pTimer = OSFactory::instance( pIntf )->createOSTimer( m_cmdUpdateText );

    // States
    m_fsm.addState( "still" );
    m_fsm.addState( "moving" );
    m_fsm.addState( "manual1" );
    m_fsm.addState( "manual2" );
    m_fsm.addState( "outStill" );
    m_fsm.addState( "outMoving" );

    // Transitions
    m_fsm.addTransition( "still", "leave", "outStill" );
    m_fsm.addTransition( "outStill", "enter", "still" );
    if( m_scrollMode == kManual )
    {
        m_fsm.addTransition( "still", "mouse:left:down", "manual1",
                             &m_cmdToManual );
        m_fsm.addTransition( "manual1", "mouse:left:up", "still",
                             &m_cmdManualStill );
        m_fsm.addTransition( "manual1", "motion", "manual1", &m_cmdMove );
    }
    else if( m_scrollMode == kAutomatic )
    {
        m_fsm.addTransition( "still", "mouse:left:down", "manual1",
                             &m_cmdToManual );
        m_fsm.addTransition( "manual1", "mouse:left:up", "moving",
                             &m_cmdManualMoving );
        m_fsm.addTransition( "moving", "mouse:left:down", "manual2",
                             &m_cmdToManual );
        m_fsm.addTransition( "manual2", "mouse:left:up", "still",
                             &m_cmdManualStill );
        m_fsm.addTransition( "manual1", "motion", "manual1", &m_cmdMove );
        m_fsm.addTransition( "manual2", "motion", "manual2", &m_cmdMove );
        m_fsm.addTransition( "moving", "leave", "outMoving" );
        m_fsm.addTransition( "outMoving", "enter", "moving" );
    }

    // Initial state
    m_fsm.setState( (m_scrollMode != kAutomatic) ? "outStill" : "outMoving" );

    // Observe the variable
    m_rVariable.addObserver( this );

    // initialize pictures
    setPictures( m_rVariable.get() );
}

CtrlText::~CtrlText()
{
    m_rVariable.delObserver( this );
    delete m_pTimer;
    delete m_pImg;
    delete m_pImgDouble;
}

void CtrlText::handleEvent( EvtGeneric &rEvent )
{
    // Save the event to use it in callbacks
    m_pEvt = &rEvent;

    m_fsm.handleTransition( rEvent.getAsString() );
}

bool CtrlText::mouseOver( int x, int y ) const
{
    if( !m_pFocus->get() )
        return false;

    if( m_pCurrImg )
    {
        // We have 3 different ways of deciding when to return true here:
        //  1) the mouse is exactly over the text (so if you click between two
        //     letters, the text control doesn't catch the event)
        //  2) the mouse is over the rectangle of the control
        //  3) the mouse is over the rectangle of the visible text
        // I don't know which one is the best...
#if 0
        return( x >= 0 && x < getPosition()->getWidth()
             && m_pCurrImg->hit( x - m_xPos, y ) );
#endif
#if 1
        return( x >= 0 && x < getPosition()->getWidth()
             && y >= 0 && y < getPosition()->getHeight() );
#endif
#if 0
        return( x >= 0 && x < getPosition()->getWidth()
             && y >= 0 && y < getPosition()->getHeight()
             && x < m_pCurrImg->getWidth() && x < m_pCurrImg->getHeight() );
#endif
    }
    else
    {
        return false;
    }
}

void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{
    rect clip( xDest, yDest, w, h );
    const Position *pPos = getPosition();
    if( m_pCurrImg )
    {
        // Compute the dimensions to draw
        int width = min( m_pCurrImg->getWidth() + m_xPos,
                         getPosition()->getWidth() );
        int height = min( m_pCurrImg->getHeight(), getPosition()->getHeight() );
        // Draw the current image
        if( width > 0 && height > 0 )
        {
            int offset = 0;
            if( m_alignment == kLeft )
            {
                // We align to the left
                offset = 0;
            }
            else if( m_alignment == kRight &&
                     width < getPosition()->getWidth() )

            {
                // The text is shorter than the width of the control, so we
                // can align it to the right
                offset = getPosition()->getWidth() - width;
            }
            else if( m_alignment == kCenter &&
                     width < getPosition()->getWidth() )
            {
                // The text is shorter than the width of the control, so we
                // can center it
                offset = (getPosition()->getWidth() - width) / 2;
            }
            rect region( pPos->getLeft() + offset,
                         pPos->getTop(), width, height );
            rect inter;
            if( rect::intersect( region, clip, &inter ) )
                rImage.drawBitmap( *m_pCurrImg, -m_xPos + inter.x - region.x,
                                   inter.y - region.y,
                                   inter.x, inter.y,
                                   inter.width, inter.height, true );
        }
    }
}

void CtrlText::setText( const UString &rText, uint32_t color )
{
    // Change the color
    if( color != 0xFFFFFFFF )
    {
        m_color = color;
    }

    // Change the text
    m_rVariable.set( rText );
}

void CtrlText::onUpdate( Subject<VarText> &rVariable, void* arg )
{
    (void)rVariable; (void)arg;
    if( isVisible() )
    {
        setPictures( m_rVariable.get() );
        updateContext();
        notifyLayout( getPosition()->getWidth(), getPosition()->getHeight() );
    }
}

void CtrlText::onUpdate( Subject<VarBool> &rVariable, void *arg  )
{
    (void)arg;
    // Visibility changed
    if( &rVariable == m_pVisible )
    {
        if( isVisible() )
        {
            setPictures( m_rVariable.get() );
            updateContext();
        }

        // notify in any case
        notifyLayout( getPosition()->getWidth(), getPosition()->getHeight() );
    }
}

void CtrlText::setPictures( const UString &rText )
{
    // reset the images ('normal' and 'double') from the text
    // 'Normal' image
    delete m_pImg;
    m_pImg = m_rFont.drawString( rText, m_color );
    if( !m_pImg )
        return;

    // 'Double' image
    const UString doubleStringWithSep = rText + SEPARATOR_STRING + rText;
    delete m_pImgDouble;
    m_pImgDouble = m_rFont.drawString( doubleStringWithSep, m_color );
}

void CtrlText::updateContext()
{
    if( !m_pImg || !getPosition() )
        return;

    if( m_pImg->getWidth() < getPosition()->getWidth() )
    {
        m_pCurrImg = m_pImg;

        // When the control becomes wide enough for the text to display,
        // make sure to stop any scrolling effect
        m_pTimer->stop();
        m_xPos = 0;
    }
    else
    {
        m_pCurrImg = m_pImgDouble;
    }

    // If the control is in the moving state,
    // automatically start or stop the timer accordingly
    const string &rState = m_fsm.getState();
    if( rState == "moving" || rState == "outMoving" )
    {
        if( m_pCurrImg == m_pImgDouble )
        {
            m_pTimer->start( MOVING_TEXT_DELAY, false );
        }
        else
        {
            m_pTimer->stop();
        }
    }

    // compute alignment
    if( m_alignment == kRight &&
        getPosition()->getWidth() < m_pImg->getWidth() )
    {
        m_xPos = getPosition()->getWidth() - m_pImg->getWidth();
    }
    else if( m_alignment == kCenter &&
             getPosition()->getWidth() < m_pImg->getWidth() )
    {
        m_xPos = (getPosition()->getWidth() - m_pImg->getWidth()) / 2;
    }
    else
    {
        m_xPos = 0;
    }
}

void CtrlText::onPositionChange()
{
    updateContext();
}

void CtrlText::onResize()
{
    updateContext();
}

void CtrlText::CmdToManual::execute()
{
    EvtMouse *pEvtMouse = (EvtMouse*)m_pParent->m_pEvt;

    // Compute the offset
    m_pParent->m_xOffset = pEvtMouse->getXPos() - m_pParent->m_xPos;

    m_pParent->m_pTimer->stop();
    m_pParent->captureMouse();
}

void CtrlText::CmdManualMoving::execute()
{
    m_pParent->releaseMouse();

    // Start the automatic movement, but only if the text is wider than the
    // control and if the control can scroll (either in manual or automatic
    // mode)
    if( m_pParent->m_pCurrImg &&
        m_pParent->m_pCurrImg == m_pParent->m_pImgDouble )
    {
        m_pParent->m_pTimer->start( MOVING_TEXT_DELAY, false );
    }
}

void CtrlText::CmdManualStill::execute()
{
    m_pParent->releaseMouse();
}

void CtrlText::CmdMove::execute()
{
    EvtMouse *pEvtMouse = (EvtMouse*)m_pParent->m_pEvt;

    // Move text only when it is larger than the control
    if( m_pParent->m_pCurrImg &&
        m_pParent->m_pCurrImg == m_pParent->m_pImgDouble )
    {
        // Compute the new position of the left side, and make sure it is
        // in the correct range
        m_pParent->m_xPos = (pEvtMouse->getXPos() - m_pParent->m_xOffset);
        m_pParent->adjust( m_pParent->m_xPos );

        m_pParent->notifyLayout( m_pParent->getPosition()->getWidth(),
                                 m_pParent->getPosition()->getHeight() );
    }
}

void CtrlText::CmdUpdateText::execute()
{
    m_pParent->m_xPos -= MOVING_TEXT_STEP;
    m_pParent->adjust( m_pParent->m_xPos );

    m_pParent->notifyLayout( m_pParent->getPosition()->getWidth(),
                             m_pParent->getPosition()->getHeight() );
}

void CtrlText::adjust( int &position )
{
    if( !m_pImg || !m_pImgDouble )
        return;

    // {m_pImgDouble->getWidth() - m_pImg->getWidth()} is the period of the
    // bitmap; remember that the string used to generate m_pImgDouble is of the
    // form: "foo  foo", the number of spaces being a parameter
    position %= m_pImgDouble->getWidth() - m_pImg->getWidth();
    if( position > 0 )
    {
        position -= m_pImgDouble->getWidth() - m_pImg->getWidth();
    }
}

<|endoftext|>


<commit_before>/*  This file is part of Text Fairy.

 Text Fairy is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 Text Fairy 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with Text Fairy.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * pageseg.cpp
 *
 *  Created on: Mar 1, 2012
 *      Author: renard
 */

#include "pageseg.h"

using namespace std;

l_int32 renderTransformedBoxa(PIX *pixt, BOXA *boxa, l_int32 i) {
	l_int32 j, n, rval, gval, bval;
	BOX *box;

	n = boxaGetCount(boxa);
	rval = (1413 * i) % 256;
	gval = (4917 * i) % 256;
	bval = (7341 * i) % 256;
	for (j = 0; j < n; j++) {
		box = boxaGetBox(boxa, j, L_CLONE);
		pixRenderHashBoxArb(pixt, box, 10, 3, i % 4, 1, rval, gval, bval);
		boxDestroy(&box);
	}
	return 0;
}

l_int32 getMedianComponentHeight(Pix* pixtl, bool debug) {
	ostringstream s;
	Pixa* comp;
	Boxa* tl = pixConnComp(pixtl, &comp, 4);
	NUMA* na = pixaCountPixels(comp);

	Box* b;
	int n = boxaGetCount(tl);
	float cc = 0;
	for (int i = 0; i < n; i++) {
		b = boxaGetBox(tl, i, L_CLONE);
		float c;
		numaGetFValue(na, i, &c);
		c /= b->w;
		numaSetValue(na, i, c);
		cc += c;
		boxDestroy(&b);
	}
	if (n > 0) {
		cc /= n;
	}

	float median = 0;
	numaGetRankValue(na, 0.75, &median);
	//numaGetMedian(na, &median);
	numaDestroy(&na);
	pixaDestroy(&comp);
	boxaDestroy(&tl);
	if (debug) {
		std::cout << "average: " << cc << "\n" << "median: " << median << "\n";
	}
	return median;
}

void growTextBounds(Boxa* textBounds) {
	int n = boxaGetCount(textBounds);
	BOX *box;
	for (int j = 0; j < n; j++) {
		box = boxaGetBox(textBounds, j, L_CLONE);
		boxAdjustSides(box,box,-5,5,-5,5);
		boxDestroy(&box);
	}
}

Pixa* pagesegGetColumns(Pix* pixtext, bool debug) {
	ostringstream s;
	PIX *pixb, *pixBinary;
	if (debug) {
		startTimer();
	}
	int w = pixGetHeight(pixtext);

	s << "o1.20+c5.20+d10.5+o1." << w / 10;

	/*remove long vertical lines*/
	Pix* pixvl = pixMorphCompSequence(pixtext, s.str().c_str(), 0);
	pixSetMasked(pixtext, pixvl, 0);
	pixDestroy(&pixvl);

	pixBinary = pixReduceRankBinaryCascade(pixtext, 1, 0, 0, 0);

	/*remove long horizontal lines*/
	Pix* pixhl = pixMorphCompSequence(pixBinary, "o70.1+c20.5+d5.10", 0);
	pixSetMasked(pixBinary, pixhl, 0);
	pixDestroy(&pixhl);

	pixb = pixInvert(NULL, pixBinary);

	/*create vertical whitespace mask*/
	//Pix *pixvws = pixMorphCompSequence(pixb, "o1.100+c2.1+o7.1+c7.10+c1.50", 0);
	Pix *pixvws = pixMorphCompSequence(pixb, "o1.100+c2.1+o7.1+c7.10", 0);

	/* Three steps to getting text line mask:
	 *   (1) close the characters and words in the textlines
	 *   (2) open the vertical whitespace corridors back up
	 *   (3) small opening to remove noise    */
	pixCloseSafeBrick(pixBinary, pixBinary, 60, 1);
	pixDisplay(pixBinary,0,0);
	pixSubtract(pixBinary, pixBinary, pixvws);
	pixOpenBrick(pixBinary, pixBinary, 1, 3);
	Pix* pixtl = pixMorphCompSequence(pixBinary, "o1.3+o25.1", 0);
	pixDestroy(&pixBinary);

	/*make a guess at the text size*/
	int ts = getMedianComponentHeight(pixtl, debug);
	pixBinary = pixtl;

	/*close inter word spacing*/
	pixCloseBrick(pixtl, pixtl, ts * 2, 1);
	pixOpenBrick(pixvws, pixvws, ts * 1.2, 1);

	/*make a guess at the line spacing*/
	/*create components for vertical white space between text lines */
	s.str("");
	s << "c1." << ts * 3;
	Pix* pixls = pixMorphCompSequence(pixtl, s.str().c_str(), 0);
	pixSubtract(pixls, pixls, pixtl);
	/*small opening to remove noise*/
	pixOpenBrick(pixls, pixls, 2, 2);
	int ls = getMedianComponentHeight(pixls, debug);
	pixDestroy(&pixls);

	/*create horizontal whitespace mask*/
	s.str("");
	s << "o50.1";
	Pix *pixhws = pixMorphCompSequence(pixb, s.str().c_str(), 0);
	pixDestroy(&pixb);
	//	pixOpenBrick(pixhws, pixhws, 1, ls * 1.6);
	pixOpenBrick(pixhws, pixhws, 1, ls * 1.5);

	/* Join pixels vertically to make a textblock mask */
	s.str("");
	s << "c" << ts << "." << ts * 8 << "+ o4.1";
	pixb = pixBinary;
	pixBinary = pixMorphSequence(pixb, s.str().c_str(), 0);
	pixDestroy(&pixb);
	pixSubtract(pixBinary, pixBinary, pixhws);
	pixDestroy(&pixhws);

	/* Solidify the textblock mask and remove noise:
	 *   (1) For each cc, close the blocks and dilate slightly to form a solid mask.
	 *   (2) Small horizontal closing between components.
	 *   (3) Open the white space between columns, again.
	 *   (4) Remove small components. */
	s.str("");
	s << "c" << ts << "." << ts << "+d3.3";
	Pix* pixt2 = pixMorphSequenceByComponent(pixBinary, s.str().c_str(), 8, 0, 0, NULL);
	pixDestroy(&pixBinary);
	pixCloseSafeBrick(pixt2, pixt2, 10, 1);
	pixSubtract(pixt2, pixt2, pixvws);

	Pix* pixd = pixSelectBySize(pixt2, ts * 5, ts, 4, L_SELECT_IF_EITHER, L_SELECT_IF_GTE, NULL);
	pixDestroy(&pixvws);
	pixDestroy(&pixt2);

	/*separate connected columns*/
	//	s.str("");
	//	s<<"c1.30"<<"+o1."<<ts*20;
	//	Pix* pixsep = pixMorphSequenceByComponent(pixd,"c1.30+o1.130",4,ts,ts*10,NULL);
	//	Pix* pixsep2 = pixMorphCompSequence(pixsep,"c50.1",0);
	//	pixSubtract(pixsep2,pixsep2,pixsep);
	//	pixDestroy(&pixsep);
	//	pixSubtract(pixd,pixd,pixsep2);
	//	pixDestroy(&pixsep2);
	/* Expand mask to full resolution, and do filling or
	 * small dilations for better coverage. */
	pixBinary = pixExpandReplicate(pixd, 2);
	pixDestroy(&pixd);
	pixDilateBrick(pixBinary, pixBinary, 3, 3);

	Boxa* boxatext = pixConnCompBB(pixBinary, 8);

	//growTextBounds(boxatext);

	pixDestroy(&pixBinary);
	Pixa* pixaText = pixaCreateFromBoxa(pixtext, boxatext, NULL);
	boxaDestroy(&boxatext);
	if (debug) {
		Pix* pixdisplay = pixaDisplay(pixaText, 0, 0);
		pixDisplay(pixdisplay, 0, 0);
		std::cout << "pagesegmentation took: " << stopTimer() << std::endl;
	}
	return pixaText;
}

void segmentComplexLayout(Pix* pixOrg,Pix* pixhm, Pix* pixb, Pixa** pixaImage, Pixa** pixaText,void(*callback) (const Pix*), bool debug) {
	ostringstream debugstring;

	if (debug) {
		startTimer();
	}

	if (debug) {
		debugstring << "Image-Text separation: " << stopTimer() << std::endl;
		startTimer();
	}
	/*create preview image*/
	Pix* pixpreview = NULL;
	if (pixhm != NULL) {
		Pix* pixb2 = pixReduceBinary2(pixb, NULL);
		Pix* pixhm2 = pixReduceBinary2(pixhm, NULL);
		Pix* pixtext32 = pixConvertTo32(pixb2);
		Pix* pixOrg2 = pixScale(pixOrg, 0.5, 0.5);
		pixDestroy(&pixb2);
		pixInvert(pixhm2, pixhm2);
		pixPaintThroughMask(pixOrg2, pixhm2, 0, 0, 0);
		pixDestroy(&pixhm2);
		Pix* pixmask = pixConvertTo1(pixOrg2, 1);
		pixCombineMasked(pixOrg2, pixtext32, pixmask);
		pixDestroy(&pixmask);
		pixDestroy(&pixtext32);
		pixpreview = pixOrg2;
	} else {
		Pix* pixb2 = pixReduceBinary2(pixb, NULL);
		Pix* pixtext32 = pixConvertTo32(pixb2);
		pixDestroy(&pixb2);
		pixpreview = pixtext32;
	}

	if (debug) {
		debugstring << "Preview-Image generation: " << stopTimer() << std::endl;
	}

	callback(pixpreview);

	if (debug) {
		startTimer();

	}
	*pixaText = pagesegGetColumns(pixb, false);
	pixDestroy(&pixb);

	if (pixhm != NULL) {
		Boxa* boxa = pixConnCompBB(pixhm, 8);
		*pixaImage = pixaCreateFromBoxa(pixOrg, boxa, NULL);
		boxaDestroy(&boxa);
		pixDestroy(&pixhm);
	} else {
		*pixaImage = NULL;
	}

	if (debug) {
		debugstring << "Page Segmentation: " << stopTimer() << std::endl;
		printf("%s",debugstring.str().c_str());
	}
}

void extractImages(Pix* pixOrg, Pix** pixhm, Pix** pixg) {

	/*do a quick and dirty binarization*/
	/* Convert the RGB image to grayscale. */
	//*pixg = pixConvertRGBToGrayFast(pixOrg);
	int depth = pixGetDepth(pixOrg);
	if (depth == 32) {
		*pixg = pixConvertRGBToLuminance(pixOrg);
	} else {
		*pixg = pixOrg;
	}

	ostringstream s;
	int width = pixGetWidth(*pixg);
	int scale = 1;
	if (width > 512 && width < 2048) {
		scale = 2;
	} else if (width > 2048) {
		scale = 4;
	}

	Pix* pixsgc = pixScaleGrayRank2(*pixg, scale);

	//Pix* pixb2 = pixMaskedThreshOnBackgroundNorm(pixsgc,NULL,10,15,25,10,2,2,0.1,NULL);
	Pix* pixb2 = pixOtsuThreshOnBackgroundNorm(pixsgc, NULL, 20, 30, 100, 100, 250, 2, 2, 0.43, NULL);
	//Pix* pixb2 = pixOtsuThreshOnBackgroundNorm(pixsgc, NULL, 20, 30, 100, 100, 200, 8, 8, 0.1, NULL);
	pixDestroy(&pixsgc);

	/*find 'colourful' pixels*/
//	Pix* pixColOrg = pixScaleByIntSubsampling(pixOrg,4);
//	pixGetAverageMaskedRGB(pixColOrg,NULL,0,0,1, L_MEAN_ABSVAL,&r,&g,&b);
//	Pix* pixcol = pixColorMagnitude(pixColOrg,abs(r),abs(g),abs(b),L_MAX_DIFF_FROM_AVERAGE_2);
//	pixDestroy(&pixColOrg);
//	pixInvert(pixcol,pixcol);
//	Pix *pixmask2 =   pixOtsuThreshOnBackgroundNorm(pixcol, NULL, 20, 30, 20, 100, 200, 0, 0, 0.1, NULL);
//
//	pixDestroy(&pixcol);
//	Pix* pixmask = pixExpandBinaryPower2(pixmask2,2);
//	pixDestroy(&pixmask2);
//	pixOr(pixb2,pixb2,pixmask);
//	pixDestroy(&pixmask);
	/*create image mask*/
	/* Get seed for halftone parts */
	Pix* pixt1 = pixReduceRankBinaryCascade(pixb2, 4, 4, 3, 0);
	Pix* pixt2 = pixOpenBrick(NULL, pixt1, 3, 3);
	int hasNoImages;
	pixZero(pixt2, &hasNoImages);
	if (!hasNoImages) {
		Pix* pixhs = pixExpandBinaryPower2(pixt2, 8);

		pixDestroy(&pixt1);
		pixDestroy(&pixt2);
		/* Get mask for connected regions */
		Pix* pixm = pixCloseSafeBrick(NULL, pixb2, 4, 4);
		/* Fill seed into mask to get halftone mask */
		Pix* pixhm1 = pixSeedfillBinary(NULL, pixhs, pixm, 4);
		pixDestroy(&pixhs);
		pixDestroy(&pixm);
		/*expand mask*/
		pixCloseBrickDwa(pixhm1, pixhm1, 30, 30);
		Pix* pixhm2 = pixFillClosedBorders(pixhm1, 4);
		pixDestroy(&pixhm1);
		*pixhm = pixExpandBinaryPower2(pixhm2, 2);
		pixDestroy(&pixhm2);
	} else {
		*pixhm = NULL;
		pixDestroy(&pixt1);
		pixDestroy(&pixt2);
	}
	pixDestroy(&pixb2);
}

<commit_msg>theoretically i could use the binary image to mask the text areas so that each column does not contain text from adjactend columns<commit_after>/*  This file is part of Text Fairy.

 Text Fairy is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 Text Fairy 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with Text Fairy.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * pageseg.cpp
 *
 *  Created on: Mar 1, 2012
 *      Author: renard
 */

#include "pageseg.h"

using namespace std;

l_int32 renderTransformedBoxa(PIX *pixt, BOXA *boxa, l_int32 i) {
	l_int32 j, n, rval, gval, bval;
	BOX *box;

	n = boxaGetCount(boxa);
	rval = (1413 * i) % 256;
	gval = (4917 * i) % 256;
	bval = (7341 * i) % 256;
	for (j = 0; j < n; j++) {
		box = boxaGetBox(boxa, j, L_CLONE);
		pixRenderHashBoxArb(pixt, box, 10, 3, i % 4, 1, rval, gval, bval);
		boxDestroy(&box);
	}
	return 0;
}

l_int32 getMedianComponentHeight(Pix* pixtl, bool debug) {
	ostringstream s;
	Pixa* comp;
	Boxa* tl = pixConnComp(pixtl, &comp, 4);
	NUMA* na = pixaCountPixels(comp);

	Box* b;
	int n = boxaGetCount(tl);
	float cc = 0;
	for (int i = 0; i < n; i++) {
		b = boxaGetBox(tl, i, L_CLONE);
		float c;
		numaGetFValue(na, i, &c);
		c /= b->w;
		numaSetValue(na, i, c);
		cc += c;
		boxDestroy(&b);
	}
	if (n > 0) {
		cc /= n;
	}

	float median = 0;
	numaGetRankValue(na, 0.75, &median);
	//numaGetMedian(na, &median);
	numaDestroy(&na);
	pixaDestroy(&comp);
	boxaDestroy(&tl);
	if (debug) {
		std::cout << "average: " << cc << "\n" << "median: " << median << "\n";
	}
	return median;
}

void growTextBounds(Boxa* textBounds) {
	int n = boxaGetCount(textBounds);
	BOX *box;
	for (int j = 0; j < n; j++) {
		box = boxaGetBox(textBounds, j, L_CLONE);
		boxAdjustSides(box,box,-5,5,-5,5);
		boxDestroy(&box);
	}
}

Pixa* pagesegGetColumns(Pix* pixtext, bool debug) {
	ostringstream s;
	PIX *pixb, *pixBinary;
	if (debug) {
		startTimer();
	}
	int w = pixGetHeight(pixtext);

	s << "o1.20+c5.20+d10.5+o1." << w / 10;

	/*remove long vertical lines*/
	Pix* pixvl = pixMorphCompSequence(pixtext, s.str().c_str(), 0);
	pixSetMasked(pixtext, pixvl, 0);
	pixDestroy(&pixvl);

	pixBinary = pixReduceRankBinaryCascade(pixtext, 1, 0, 0, 0);

	/*remove long horizontal lines*/
	Pix* pixhl = pixMorphCompSequence(pixBinary, "o70.1+c20.5+d5.10", 0);
	pixSetMasked(pixBinary, pixhl, 0);
	pixDestroy(&pixhl);

	pixb = pixInvert(NULL, pixBinary);

	/*create vertical whitespace mask*/
	//Pix *pixvws = pixMorphCompSequence(pixb, "o1.100+c2.1+o7.1+c7.10+c1.50", 0);
	Pix *pixvws = pixMorphCompSequence(pixb, "o1.100+c2.1+o7.1+c7.10", 0);

	/* Three steps to getting text line mask:
	 *   (1) close the characters and words in the textlines
	 *   (2) open the vertical whitespace corridors back up
	 *   (3) small opening to remove noise    */
	pixCloseSafeBrick(pixBinary, pixBinary, 60, 1);
	pixDisplay(pixBinary,0,0);
	pixSubtract(pixBinary, pixBinary, pixvws);
	pixOpenBrick(pixBinary, pixBinary, 1, 3);
	Pix* pixtl = pixMorphCompSequence(pixBinary, "o1.3+o25.1", 0);
	pixDestroy(&pixBinary);

	/*make a guess at the text size*/
	int ts = getMedianComponentHeight(pixtl, debug);
	pixBinary = pixtl;

	/*close inter word spacing*/
	pixCloseBrick(pixtl, pixtl, ts * 2, 1);
	pixOpenBrick(pixvws, pixvws, ts * 1.2, 1);

	/*make a guess at the line spacing*/
	/*create components for vertical white space between text lines */
	s.str("");
	s << "c1." << ts * 3;
	Pix* pixls = pixMorphCompSequence(pixtl, s.str().c_str(), 0);
	pixSubtract(pixls, pixls, pixtl);
	/*small opening to remove noise*/
	pixOpenBrick(pixls, pixls, 2, 2);
	int ls = getMedianComponentHeight(pixls, debug);
	pixDestroy(&pixls);

	/*create horizontal whitespace mask*/
	s.str("");
	s << "o50.1";
	Pix *pixhws = pixMorphCompSequence(pixb, s.str().c_str(), 0);
	pixDestroy(&pixb);
	//	pixOpenBrick(pixhws, pixhws, 1, ls * 1.6);
	pixOpenBrick(pixhws, pixhws, 1, ls * 1.5);

	/* Join pixels vertically to make a textblock mask */
	s.str("");
	s << "c" << ts << "." << ts * 8 << "+ o4.1";
	pixb = pixBinary;
	pixBinary = pixMorphSequence(pixb, s.str().c_str(), 0);
	pixDestroy(&pixb);
	pixSubtract(pixBinary, pixBinary, pixhws);
	pixDestroy(&pixhws);

	/* Solidify the textblock mask and remove noise:
	 *   (1) For each cc, close the blocks and dilate slightly to form a solid mask.
	 *   (2) Small horizontal closing between components.
	 *   (3) Open the white space between columns, again.
	 *   (4) Remove small components. */
	s.str("");
	s << "c" << ts << "." << ts << "+d3.3";
	Pix* pixt2 = pixMorphSequenceByComponent(pixBinary, s.str().c_str(), 8, 0, 0, NULL);
	pixDestroy(&pixBinary);
	pixCloseSafeBrick(pixt2, pixt2, 10, 1);
	pixSubtract(pixt2, pixt2, pixvws);

	Pix* pixd = pixSelectBySize(pixt2, ts * 5, ts, 4, L_SELECT_IF_EITHER, L_SELECT_IF_GTE, NULL);
	pixDestroy(&pixvws);
	pixDestroy(&pixt2);

	/*separate connected columns*/
	//	s.str("");
	//	s<<"c1.30"<<"+o1."<<ts*20;
	//	Pix* pixsep = pixMorphSequenceByComponent(pixd,"c1.30+o1.130",4,ts,ts*10,NULL);
	//	Pix* pixsep2 = pixMorphCompSequence(pixsep,"c50.1",0);
	//	pixSubtract(pixsep2,pixsep2,pixsep);
	//	pixDestroy(&pixsep);
	//	pixSubtract(pixd,pixd,pixsep2);
	//	pixDestroy(&pixsep2);
	/* Expand mask to full resolution, and do filling or
	 * small dilations for better coverage. */
	pixBinary = pixExpandReplicate(pixd, 2);
	pixDestroy(&pixd);
	pixDilateBrick(pixBinary, pixBinary, 3, 3);

	Boxa* boxatext = pixConnCompBB(pixBinary, 8);
	//growTextBounds(boxatext);
	Pixa* pixaText = pixaCreateFromBoxa(pixtext, boxatext, NULL);
	//substract
	pixDestroy(&pixBinary);
	boxaDestroy(&boxatext);
	if (debug) {
		Pix* pixdisplay = pixaDisplay(pixaText, 0, 0);
		pixDisplay(pixdisplay, 0, 0);
		std::cout << "pagesegmentation took: " << stopTimer() << std::endl;
	}
	return pixaText;
}

void segmentComplexLayout(Pix* pixOrg,Pix* pixhm, Pix* pixb, Pixa** pixaImage, Pixa** pixaText,void(*callback) (const Pix*), bool debug) {
	ostringstream debugstring;

	if (debug) {
		startTimer();
	}

	if (debug) {
		debugstring << "Image-Text separation: " << stopTimer() << std::endl;
		startTimer();
	}
	/*create preview image*/
	Pix* pixpreview = NULL;
	if (pixhm != NULL) {
		Pix* pixb2 = pixReduceBinary2(pixb, NULL);
		Pix* pixhm2 = pixReduceBinary2(pixhm, NULL);
		Pix* pixtext32 = pixConvertTo32(pixb2);
		Pix* pixOrg2 = pixScale(pixOrg, 0.5, 0.5);
		pixDestroy(&pixb2);
		pixInvert(pixhm2, pixhm2);
		pixPaintThroughMask(pixOrg2, pixhm2, 0, 0, 0);
		pixDestroy(&pixhm2);
		Pix* pixmask = pixConvertTo1(pixOrg2, 1);
		pixCombineMasked(pixOrg2, pixtext32, pixmask);
		pixDestroy(&pixmask);
		pixDestroy(&pixtext32);
		pixpreview = pixOrg2;
	} else {
		Pix* pixb2 = pixReduceBinary2(pixb, NULL);
		Pix* pixtext32 = pixConvertTo32(pixb2);
		pixDestroy(&pixb2);
		pixpreview = pixtext32;
	}

	if (debug) {
		debugstring << "Preview-Image generation: " << stopTimer() << std::endl;
	}

	callback(pixpreview);

	if (debug) {
		startTimer();

	}
	*pixaText = pagesegGetColumns(pixb, false);
	pixDestroy(&pixb);

	if (pixhm != NULL) {
		Boxa* boxa = pixConnCompBB(pixhm, 8);
		*pixaImage = pixaCreateFromBoxa(pixOrg, boxa, NULL);
		boxaDestroy(&boxa);
		pixDestroy(&pixhm);
	} else {
		*pixaImage = NULL;
	}

	if (debug) {
		debugstring << "Page Segmentation: " << stopTimer() << std::endl;
		printf("%s",debugstring.str().c_str());
	}
}

void extractImages(Pix* pixOrg, Pix** pixhm, Pix** pixg) {

	/*do a quick and dirty binarization*/
	/* Convert the RGB image to grayscale. */
	//*pixg = pixConvertRGBToGrayFast(pixOrg);
	int depth = pixGetDepth(pixOrg);
	if (depth == 32) {
		*pixg = pixConvertRGBToLuminance(pixOrg);
	} else {
		*pixg = pixOrg;
	}

	ostringstream s;
	int width = pixGetWidth(*pixg);
	int scale = 1;
	if (width > 512 && width < 2048) {
		scale = 2;
	} else if (width > 2048) {
		scale = 4;
	}

	Pix* pixsgc = pixScaleGrayRank2(*pixg, scale);

	//Pix* pixb2 = pixMaskedThreshOnBackgroundNorm(pixsgc,NULL,10,15,25,10,2,2,0.1,NULL);
	Pix* pixb2 = pixOtsuThreshOnBackgroundNorm(pixsgc, NULL, 20, 30, 100, 100, 250, 2, 2, 0.43, NULL);
	//Pix* pixb2 = pixOtsuThreshOnBackgroundNorm(pixsgc, NULL, 20, 30, 100, 100, 200, 8, 8, 0.1, NULL);
	pixDestroy(&pixsgc);

	/*find 'colourful' pixels*/
//	Pix* pixColOrg = pixScaleByIntSubsampling(pixOrg,4);
//	pixGetAverageMaskedRGB(pixColOrg,NULL,0,0,1, L_MEAN_ABSVAL,&r,&g,&b);
//	Pix* pixcol = pixColorMagnitude(pixColOrg,abs(r),abs(g),abs(b),L_MAX_DIFF_FROM_AVERAGE_2);
//	pixDestroy(&pixColOrg);
//	pixInvert(pixcol,pixcol);
//	Pix *pixmask2 =   pixOtsuThreshOnBackgroundNorm(pixcol, NULL, 20, 30, 20, 100, 200, 0, 0, 0.1, NULL);
//
//	pixDestroy(&pixcol);
//	Pix* pixmask = pixExpandBinaryPower2(pixmask2,2);
//	pixDestroy(&pixmask2);
//	pixOr(pixb2,pixb2,pixmask);
//	pixDestroy(&pixmask);
	/*create image mask*/
	/* Get seed for halftone parts */
	Pix* pixt1 = pixReduceRankBinaryCascade(pixb2, 4, 4, 3, 0);
	Pix* pixt2 = pixOpenBrick(NULL, pixt1, 3, 3);
	int hasNoImages;
	pixZero(pixt2, &hasNoImages);
	if (!hasNoImages) {
		Pix* pixhs = pixExpandBinaryPower2(pixt2, 8);

		pixDestroy(&pixt1);
		pixDestroy(&pixt2);
		/* Get mask for connected regions */
		Pix* pixm = pixCloseSafeBrick(NULL, pixb2, 4, 4);
		/* Fill seed into mask to get halftone mask */
		Pix* pixhm1 = pixSeedfillBinary(NULL, pixhs, pixm, 4);
		pixDestroy(&pixhs);
		pixDestroy(&pixm);
		/*expand mask*/
		pixCloseBrickDwa(pixhm1, pixhm1, 30, 30);
		Pix* pixhm2 = pixFillClosedBorders(pixhm1, 4);
		pixDestroy(&pixhm1);
		*pixhm = pixExpandBinaryPower2(pixhm2, 2);
		pixDestroy(&pixhm2);
	} else {
		*pixhm = NULL;
		pixDestroy(&pixt1);
		pixDestroy(&pixt2);
	}
	pixDestroy(&pixb2);
}

<|endoftext|>