<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: prcntfld.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 11:30:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// include ---------------------------------------------------------------

#pragma hdrstop

#include "prcntfld.hxx"

// STATIC DATA -----------------------------------------------------------

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

PercentField::PercentField( Window* pWin, const ResId& rResId ) :
        MetricField ( pWin, rResId ),

        eOldUnit    (FUNIT_NONE),
        nOldMin     (0),
        nOldMax     (0),
        nLastPercent(-1L),
        nLastValue  (-1L),
        bLockAutoCalculation(sal_False)
{

    nOldSpinSize = GetSpinSize();
    nRefValue = Denormalize(MetricField::GetMax(FUNIT_TWIP));
    nOldDigits = GetDecimalDigits();
    SetCustomUnitText('%');
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void PercentField::SetRefValue(long nValue)
{
    long nRealValue = GetRealValue(eOldUnit);

    nRefValue = nValue;

    if (!bLockAutoCalculation && (GetUnit() == FUNIT_CUSTOM))
        SetPrcntValue(nRealValue, eOldUnit);
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void PercentField::ShowPercent(BOOL bPercent)
{
    if ((bPercent && GetUnit() == FUNIT_CUSTOM) ||
        (!bPercent && GetUnit() != FUNIT_CUSTOM))
        return;

    long nOldValue;

    if (bPercent)
    {
        long nAktWidth, nPercent;

        nOldValue = GetValue();

        eOldUnit = GetUnit();
        nOldDigits = GetDecimalDigits();
        nOldMin = GetMin();
        nOldMax = GetMax();
        nOldSpinSize = GetSpinSize();
        nOldBaseValue = GetBaseValue();
        SetUnit(FUNIT_CUSTOM);
        SetDecimalDigits( 0 );

        nAktWidth = ConvertValue(nOldMin, 0, nOldDigits, eOldUnit, FUNIT_TWIP);
        // Um 0.5 Prozent aufrunden
        nPercent = ((nAktWidth * 10) / nRefValue + 5) / 10;

        MetricField::SetMin(Max(1L, nPercent));
        MetricField::SetMax(100);
        SetSpinSize(5);
        MetricField::SetBaseValue(0);
        if (nOldValue != nLastValue)
        {
            nAktWidth = ConvertValue(nOldValue, 0, nOldDigits, eOldUnit, FUNIT_TWIP);
            nPercent = ((nAktWidth * 10) / nRefValue + 5) / 10;
            MetricFormatter::SetValue(nPercent);
            nLastPercent = nPercent;
            nLastValue = nOldValue;
        }
        else
            MetricFormatter::SetValue(nLastPercent);
//      SetValue(100, FUNIT_CUSTOM);
    }
    else
    {
        long nOldPercent = GetValue(FUNIT_CUSTOM);

        nOldValue = Convert(GetValue(), GetUnit(), eOldUnit);

        SetUnit(eOldUnit);
        SetDecimalDigits(nOldDigits);
        MetricField::SetMin(nOldMin);
        MetricField::SetMax(nOldMax);
        SetSpinSize(nOldSpinSize);
        MetricField::SetBaseValue(nOldBaseValue);

        if (nOldPercent != nLastPercent)
        {
            SetPrcntValue(nOldValue, eOldUnit);
            nLastPercent = nOldPercent;
            nLastValue = nOldValue;
        }
        else
            SetPrcntValue(nLastValue, eOldUnit);
    }
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/
void PercentField::SetValue(long nNewValue, FieldUnit eInUnit)
{
   MetricFormatter::SetValue(nNewValue, eInUnit);
}
/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/
void PercentField::SetPrcntValue(long nNewValue, FieldUnit eInUnit)
{
    if (GetUnit() != FUNIT_CUSTOM || eInUnit == FUNIT_CUSTOM)
        MetricFormatter::SetValue(Convert(nNewValue, eInUnit, GetUnit()));

    else
    {
        // Ausgangswert ueberschreiben, nicht spaeter restaurieren
        long nPercent, nAktWidth;
        if(eInUnit == FUNIT_TWIP)
        {
            nAktWidth = ConvertValue(nNewValue, 0, nOldDigits, FUNIT_TWIP, FUNIT_TWIP);
        }
        else
        {
            long nValue = Convert(nNewValue, eInUnit, eOldUnit);
            nAktWidth = ConvertValue(nValue, 0, nOldDigits, eOldUnit, FUNIT_TWIP);
        }
        nPercent = ((nAktWidth * 10) / nRefValue + 5) / 10;
        MetricFormatter::SetValue(nPercent);
    }
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void PercentField::SetUserValue( long nNewValue, FieldUnit eInUnit )
{
    if (GetUnit() != FUNIT_CUSTOM || eInUnit == FUNIT_CUSTOM)
        MetricField::SetUserValue(Convert(nNewValue, eInUnit, GetUnit()),FUNIT_NONE);

    else
    {
        // Ausgangswert ueberschreiben, nicht spaeter restaurieren
        long nPercent, nAktWidth;
        if(eInUnit == FUNIT_TWIP)
        {
            nAktWidth = ConvertValue(nNewValue, 0, nOldDigits, FUNIT_TWIP, FUNIT_TWIP);
        }
        else
        {
            long nValue = Convert(nNewValue, eInUnit, eOldUnit);
            nAktWidth = ConvertValue(nValue, 0, nOldDigits, eOldUnit, FUNIT_TWIP);
        }
        nPercent = ((nAktWidth * 10) / nRefValue + 5) / 10;
        MetricField::SetUserValue(nPercent,FUNIT_NONE);
    }

}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void PercentField::SetBaseValue(long nNewValue, FieldUnit eInUnit)
{
    if (GetUnit() == FUNIT_CUSTOM)
        nOldBaseValue = ConvertValue(nNewValue, 0, nOldDigits, eInUnit, eOldUnit);
    else
        MetricField::SetBaseValue(nNewValue, eInUnit);
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

long PercentField::GetValue( FieldUnit eOutUnit )
{
    return Convert(MetricField::GetValue(), GetUnit(), eOutUnit);
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void PercentField::SetMin(long nNewMin, FieldUnit eInUnit)
{
    if (GetUnit() != FUNIT_CUSTOM)
        MetricField::SetMin(nNewMin, eInUnit);
    else
    {
        if (eInUnit == FUNIT_NONE)
            eInUnit = eOldUnit;
        nOldMin = Convert(nNewMin, eInUnit, eOldUnit);

        long nPercent = Convert(nNewMin, eInUnit, FUNIT_CUSTOM);
        MetricField::SetMin(Max(1L, nPercent));
    }
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void PercentField::SetMax(long nNewMax, FieldUnit eInUnit)
{
    if (GetUnit() != FUNIT_CUSTOM)
        MetricField::SetMax(nNewMax, eInUnit);
    else
    {
        if (eInUnit == FUNIT_NONE)
            eInUnit = eOldUnit;
//      SetRefValue(Convert(nNewMax, eInUnit, FUNIT_TWIP));
    }
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

long PercentField::Normalize(long nValue)
{
    if (GetUnit() != FUNIT_CUSTOM)
        nValue = MetricField::Normalize(nValue);
    else
        nValue = nValue * ImpPower10(nOldDigits);

    return nValue;
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

long PercentField::Denormalize(long nValue)
{
    if (GetUnit() != FUNIT_CUSTOM)
        nValue = MetricField::Denormalize(nValue);
    else
    {
        long nFactor = ImpPower10(nOldDigits);
        nValue = ((nValue+(nFactor/2)) / nFactor);
    }

    return nValue;
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

BOOL PercentField::IsValueModified()
{
    if (GetUnit() == FUNIT_CUSTOM)
        return TRUE;
    else
        return MetricField::IsValueModified();
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

long PercentField::ImpPower10( USHORT n )
{
    USHORT i;
    long   nValue = 1;

    for ( i=0; i < n; i++ )
        nValue *= 10;

    return nValue;
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

long PercentField::GetRealValue(FieldUnit eOutUnit)
{
    if (GetUnit() != FUNIT_CUSTOM)
        return GetValue(eOutUnit);
    else
        return Convert(GetValue(), GetUnit(), eOutUnit);
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

long PercentField::Convert(long nValue, FieldUnit eInUnit, FieldUnit eOutUnit)
{
    if (eInUnit == eOutUnit ||
        (eInUnit == FUNIT_NONE && eOutUnit == GetUnit()) ||
        (eOutUnit == FUNIT_NONE && eInUnit == GetUnit()))
        return nValue;

    if (eInUnit == FUNIT_CUSTOM)
    {
        // Umrechnen in Metrik
        long nTwipValue = (nRefValue * nValue + 50) / 100;

        if (eOutUnit == FUNIT_TWIP) // Nur wandeln, wenn unbedingt notwendig
            return Normalize(nTwipValue);
        else
            return ConvertValue(Normalize(nTwipValue), 0, nOldDigits, FUNIT_TWIP, eOutUnit);
    }

    if (eOutUnit == FUNIT_CUSTOM)
    {
        // Umrechnen in Prozent
        long nAktWidth;
        nValue = Denormalize(nValue);

        if (eInUnit == FUNIT_TWIP)  // Nur wandeln, wenn unbedingt notwendig
            nAktWidth = nValue;
        else
            nAktWidth = ConvertValue(nValue, 0, nOldDigits, eInUnit, FUNIT_TWIP);
        // Um 0.5 Prozent runden
        return ((nAktWidth * 1000) / nRefValue + 5) / 10;
    }

    return ConvertValue(nValue, 0, nOldDigits, eInUnit, eOutUnit);
}

<commit_msg>INTEGRATION: CWS pchfix02 (1.6.476); FILE MERGED 2006/09/01 17:53:33 kaib 1.6.476.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: prcntfld.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 23:34:21 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

// include ---------------------------------------------------------------

#include "prcntfld.hxx"

// STATIC DATA -----------------------------------------------------------

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

PercentField::PercentField( Window* pWin, const ResId& rResId ) :
        MetricField ( pWin, rResId ),

        eOldUnit    (FUNIT_NONE),
        nOldMin     (0),
        nOldMax     (0),
        nLastPercent(-1L),
        nLastValue  (-1L),
        bLockAutoCalculation(sal_False)
{

    nOldSpinSize = GetSpinSize();
    nRefValue = Denormalize(MetricField::GetMax(FUNIT_TWIP));
    nOldDigits = GetDecimalDigits();
    SetCustomUnitText('%');
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void PercentField::SetRefValue(long nValue)
{
    long nRealValue = GetRealValue(eOldUnit);

    nRefValue = nValue;

    if (!bLockAutoCalculation && (GetUnit() == FUNIT_CUSTOM))
        SetPrcntValue(nRealValue, eOldUnit);
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void PercentField::ShowPercent(BOOL bPercent)
{
    if ((bPercent && GetUnit() == FUNIT_CUSTOM) ||
        (!bPercent && GetUnit() != FUNIT_CUSTOM))
        return;

    long nOldValue;

    if (bPercent)
    {
        long nAktWidth, nPercent;

        nOldValue = GetValue();

        eOldUnit = GetUnit();
        nOldDigits = GetDecimalDigits();
        nOldMin = GetMin();
        nOldMax = GetMax();
        nOldSpinSize = GetSpinSize();
        nOldBaseValue = GetBaseValue();
        SetUnit(FUNIT_CUSTOM);
        SetDecimalDigits( 0 );

        nAktWidth = ConvertValue(nOldMin, 0, nOldDigits, eOldUnit, FUNIT_TWIP);
        // Um 0.5 Prozent aufrunden
        nPercent = ((nAktWidth * 10) / nRefValue + 5) / 10;

        MetricField::SetMin(Max(1L, nPercent));
        MetricField::SetMax(100);
        SetSpinSize(5);
        MetricField::SetBaseValue(0);
        if (nOldValue != nLastValue)
        {
            nAktWidth = ConvertValue(nOldValue, 0, nOldDigits, eOldUnit, FUNIT_TWIP);
            nPercent = ((nAktWidth * 10) / nRefValue + 5) / 10;
            MetricFormatter::SetValue(nPercent);
            nLastPercent = nPercent;
            nLastValue = nOldValue;
        }
        else
            MetricFormatter::SetValue(nLastPercent);
//      SetValue(100, FUNIT_CUSTOM);
    }
    else
    {
        long nOldPercent = GetValue(FUNIT_CUSTOM);

        nOldValue = Convert(GetValue(), GetUnit(), eOldUnit);

        SetUnit(eOldUnit);
        SetDecimalDigits(nOldDigits);
        MetricField::SetMin(nOldMin);
        MetricField::SetMax(nOldMax);
        SetSpinSize(nOldSpinSize);
        MetricField::SetBaseValue(nOldBaseValue);

        if (nOldPercent != nLastPercent)
        {
            SetPrcntValue(nOldValue, eOldUnit);
            nLastPercent = nOldPercent;
            nLastValue = nOldValue;
        }
        else
            SetPrcntValue(nLastValue, eOldUnit);
    }
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/
void PercentField::SetValue(long nNewValue, FieldUnit eInUnit)
{
   MetricFormatter::SetValue(nNewValue, eInUnit);
}
/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/
void PercentField::SetPrcntValue(long nNewValue, FieldUnit eInUnit)
{
    if (GetUnit() != FUNIT_CUSTOM || eInUnit == FUNIT_CUSTOM)
        MetricFormatter::SetValue(Convert(nNewValue, eInUnit, GetUnit()));

    else
    {
        // Ausgangswert ueberschreiben, nicht spaeter restaurieren
        long nPercent, nAktWidth;
        if(eInUnit == FUNIT_TWIP)
        {
            nAktWidth = ConvertValue(nNewValue, 0, nOldDigits, FUNIT_TWIP, FUNIT_TWIP);
        }
        else
        {
            long nValue = Convert(nNewValue, eInUnit, eOldUnit);
            nAktWidth = ConvertValue(nValue, 0, nOldDigits, eOldUnit, FUNIT_TWIP);
        }
        nPercent = ((nAktWidth * 10) / nRefValue + 5) / 10;
        MetricFormatter::SetValue(nPercent);
    }
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void PercentField::SetUserValue( long nNewValue, FieldUnit eInUnit )
{
    if (GetUnit() != FUNIT_CUSTOM || eInUnit == FUNIT_CUSTOM)
        MetricField::SetUserValue(Convert(nNewValue, eInUnit, GetUnit()),FUNIT_NONE);

    else
    {
        // Ausgangswert ueberschreiben, nicht spaeter restaurieren
        long nPercent, nAktWidth;
        if(eInUnit == FUNIT_TWIP)
        {
            nAktWidth = ConvertValue(nNewValue, 0, nOldDigits, FUNIT_TWIP, FUNIT_TWIP);
        }
        else
        {
            long nValue = Convert(nNewValue, eInUnit, eOldUnit);
            nAktWidth = ConvertValue(nValue, 0, nOldDigits, eOldUnit, FUNIT_TWIP);
        }
        nPercent = ((nAktWidth * 10) / nRefValue + 5) / 10;
        MetricField::SetUserValue(nPercent,FUNIT_NONE);
    }

}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void PercentField::SetBaseValue(long nNewValue, FieldUnit eInUnit)
{
    if (GetUnit() == FUNIT_CUSTOM)
        nOldBaseValue = ConvertValue(nNewValue, 0, nOldDigits, eInUnit, eOldUnit);
    else
        MetricField::SetBaseValue(nNewValue, eInUnit);
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

long PercentField::GetValue( FieldUnit eOutUnit )
{
    return Convert(MetricField::GetValue(), GetUnit(), eOutUnit);
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void PercentField::SetMin(long nNewMin, FieldUnit eInUnit)
{
    if (GetUnit() != FUNIT_CUSTOM)
        MetricField::SetMin(nNewMin, eInUnit);
    else
    {
        if (eInUnit == FUNIT_NONE)
            eInUnit = eOldUnit;
        nOldMin = Convert(nNewMin, eInUnit, eOldUnit);

        long nPercent = Convert(nNewMin, eInUnit, FUNIT_CUSTOM);
        MetricField::SetMin(Max(1L, nPercent));
    }
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void PercentField::SetMax(long nNewMax, FieldUnit eInUnit)
{
    if (GetUnit() != FUNIT_CUSTOM)
        MetricField::SetMax(nNewMax, eInUnit);
    else
    {
        if (eInUnit == FUNIT_NONE)
            eInUnit = eOldUnit;
//      SetRefValue(Convert(nNewMax, eInUnit, FUNIT_TWIP));
    }
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

long PercentField::Normalize(long nValue)
{
    if (GetUnit() != FUNIT_CUSTOM)
        nValue = MetricField::Normalize(nValue);
    else
        nValue = nValue * ImpPower10(nOldDigits);

    return nValue;
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

long PercentField::Denormalize(long nValue)
{
    if (GetUnit() != FUNIT_CUSTOM)
        nValue = MetricField::Denormalize(nValue);
    else
    {
        long nFactor = ImpPower10(nOldDigits);
        nValue = ((nValue+(nFactor/2)) / nFactor);
    }

    return nValue;
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

BOOL PercentField::IsValueModified()
{
    if (GetUnit() == FUNIT_CUSTOM)
        return TRUE;
    else
        return MetricField::IsValueModified();
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

long PercentField::ImpPower10( USHORT n )
{
    USHORT i;
    long   nValue = 1;

    for ( i=0; i < n; i++ )
        nValue *= 10;

    return nValue;
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

long PercentField::GetRealValue(FieldUnit eOutUnit)
{
    if (GetUnit() != FUNIT_CUSTOM)
        return GetValue(eOutUnit);
    else
        return Convert(GetValue(), GetUnit(), eOutUnit);
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

long PercentField::Convert(long nValue, FieldUnit eInUnit, FieldUnit eOutUnit)
{
    if (eInUnit == eOutUnit ||
        (eInUnit == FUNIT_NONE && eOutUnit == GetUnit()) ||
        (eOutUnit == FUNIT_NONE && eInUnit == GetUnit()))
        return nValue;

    if (eInUnit == FUNIT_CUSTOM)
    {
        // Umrechnen in Metrik
        long nTwipValue = (nRefValue * nValue + 50) / 100;

        if (eOutUnit == FUNIT_TWIP) // Nur wandeln, wenn unbedingt notwendig
            return Normalize(nTwipValue);
        else
            return ConvertValue(Normalize(nTwipValue), 0, nOldDigits, FUNIT_TWIP, eOutUnit);
    }

    if (eOutUnit == FUNIT_CUSTOM)
    {
        // Umrechnen in Prozent
        long nAktWidth;
        nValue = Denormalize(nValue);

        if (eInUnit == FUNIT_TWIP)  // Nur wandeln, wenn unbedingt notwendig
            nAktWidth = nValue;
        else
            nAktWidth = ConvertValue(nValue, 0, nOldDigits, eInUnit, FUNIT_TWIP);
        // Um 0.5 Prozent runden
        return ((nAktWidth * 1000) / nRefValue + 5) / 10;
    }

    return ConvertValue(nValue, 0, nOldDigits, eInUnit, eOutUnit);
}

<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// File IterativeElasticSystem.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: IterativeElasticSystem solve routines
//
///////////////////////////////////////////////////////////////////////////////

#include <boost/format.hpp>

#include <LibUtilities/Foundations/Interp.h>
#include <LibUtilities/BasicUtils/FileSystem.h>
#include <StdRegions/StdQuadExp.h>
#include <StdRegions/StdTriExp.h>
#include <LocalRegions/MatrixKey.h>
#include <MultiRegions/ContField2D.h>
#include <MultiRegions/GlobalLinSysDirectStaticCond.h>
#include <SolverUtils/Core/Deform.h>

#include <LinearElasticSolver/EquationSystems/IterativeElasticSystem.h>

namespace Nektar
{
    string IterativeElasticSystem::className = GetEquationSystemFactory().
        RegisterCreatorFunction("IterativeElasticSystem",
                                IterativeElasticSystem::create);

    IterativeElasticSystem::IterativeElasticSystem(
            const LibUtilities::SessionReaderSharedPtr& pSession)
        : LinearElasticSystem(pSession)
    {
    }

    void IterativeElasticSystem::v_InitObject()
    {
        LinearElasticSystem::v_InitObject();

        const int nVel = m_fields[0]->GetCoordim(0);

        // Read in number of steps to take.
        m_session->LoadParameter("NumSteps", m_numSteps, 0);
        ASSERTL0(m_numSteps > 0, "You must specify at least one step");

        // Read in whether to repeatedly apply boundary conditions (for e.g.
        // rotation purposes).
        string bcType;
        m_session->LoadSolverInfo("BCType", bcType, "Normal");
        m_repeatBCs = bcType != "Normal";

        if (!m_repeatBCs)
        {
            // Loop over BCs, identify which ones we need to deform.
            const Array<OneD, const SpatialDomains::BoundaryConditionShPtr>
                &bndCond = m_fields[0]->GetBndConditions();

            for (int i = 0; i < bndCond.num_elements(); ++i)
            {
                if (bndCond[i]->GetUserDefined() == SpatialDomains::eWall)
                {
                    m_toDeform.push_back(i);
                }
            }

            ASSERTL0(m_toDeform.size() > 0, "Must tag at least one boundary "
                                            "with the WALL user-defined type");

            m_savedBCs  = Array<OneD, Array<OneD, Array<OneD, NekDouble> > >(
                m_toDeform.size());

            for (int i = 0; i < m_toDeform.size(); ++i)
            {
                m_savedBCs[i] = Array<OneD, Array<OneD, NekDouble> >(nVel);
                for (int j = 0; j < nVel; ++j)
                {
                    const int id = m_toDeform[i];
                    MultiRegions::ExpListSharedPtr bndCondExp =
                        m_fields[j]->GetBndCondExpansions()[id];
                    int nCoeffs = bndCondExp->GetNcoeffs();

                    m_savedBCs[i][j] = Array<OneD, NekDouble>(nCoeffs);
                    Vmath::Smul(nCoeffs, 1.0/m_numSteps,
                                bndCondExp->GetCoeffs(),    1,
                                bndCondExp->UpdateCoeffs(), 1);
                    Vmath::Vcopy(nCoeffs, bndCondExp->GetCoeffs(), 1,
                                 m_savedBCs[i][j], 1);
                }
            }
        }
    }

    void IterativeElasticSystem::v_GenerateSummary(SolverUtils::SummaryList& s)
    {
        LinearElasticSystem::v_GenerateSummary(s);
    }

    void IterativeElasticSystem::v_DoSolve()
    {
        int i, j, k;

        // Write initial geometry for consistency/script purposes
        WriteGeometry(0);

        // Now loop over desired number of steps
        for (i = 1; i <= m_numSteps; ++i)
        {
            int invalidElmtId = -1;

            // Perform solve for this iteration and update geometry accordingly.
            LinearElasticSystem::v_DoSolve();
            UpdateGeometry(m_graph, m_fields);

            // Check for invalid elements.
            for (j = 0; j < m_fields[0]->GetExpSize(); ++j)
            {
                SpatialDomains::GeomFactorsSharedPtr geomFac =
                    m_fields[0]->GetExp(j)->GetGeom()->GetGeomFactors();

                if (!geomFac->IsValid())
                {
                    invalidElmtId =
                        m_fields[0]->GetExp(j)->GetGeom()->GetGlobalID();
                    break;
                }
            }

            m_session->GetComm()->AllReduce(invalidElmtId, LibUtilities::ReduceMax);

            // If we found an invalid element, exit loop without writing output.
            if (invalidElmtId >= 0)
            {
                if (m_session->GetComm()->GetRank() == 0)
                {
                    cout << "- Detected negative Jacobian in element "
                         << invalidElmtId << "; terminating" << endl;
                }

                break;
            }

            WriteGeometry(i);

            if (m_session->GetComm()->GetRank() == 0)
            {
                cout << "Step: " << i << endl;
            }

            // Update boundary conditions
            if (m_repeatBCs)
            {
                for (j = 0; j < m_fields.num_elements(); ++j)
                {
                    string varName = m_session->GetVariable(j);
                    m_fields[j]->EvaluateBoundaryConditions(m_time, varName);
                }
            }
            else
            {
                for (j = 0; j < m_fields.num_elements(); ++j)
                {
                    const Array<OneD, const MultiRegions::ExpListSharedPtr> &bndCondExp =
                        m_fields[j]->GetBndCondExpansions();

                    for (k = 0; k < m_toDeform.size(); ++k)
                    {
                        const int id = m_toDeform[k];
                        const int nCoeffs = bndCondExp[id]->GetNcoeffs();
                        Vmath::Vcopy(nCoeffs,
                                     m_savedBCs[k][j],               1,
                                     bndCondExp[id]->UpdateCoeffs(), 1);
                    }
                }
            }
        }
    }

    /**
     * @brief Write out a file in serial or directory in parallel containing new
     * mesh geometry.
     */
    void IterativeElasticSystem::WriteGeometry(const int i)
    {
        fs::path filename;
        stringstream s;
        s << m_session->GetSessionName() << "-" << i;

        if (m_session->GetComm()->GetSize() > 1)
        {
            s << "_xml";

            if(!fs::is_directory(s.str()))
            {
                fs::create_directory(s.str());
            }

            boost::format pad("P%1$07d.xml");
            pad % m_session->GetComm()->GetRank();
            filename = fs::path(s.str()) / fs::path(pad.str());
        }
        else
        {
            s << ".xml";
            filename = fs::path(s.str());
        }

        string fname = LibUtilities::PortablePath(filename);
        m_fields[0]->GetGraph()->WriteGeometry(fname);
    }
}
<commit_msg>fix for parralel running<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// File IterativeElasticSystem.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: IterativeElasticSystem solve routines
//
///////////////////////////////////////////////////////////////////////////////

#include <boost/format.hpp>

#include <LibUtilities/Foundations/Interp.h>
#include <LibUtilities/BasicUtils/FileSystem.h>
#include <StdRegions/StdQuadExp.h>
#include <StdRegions/StdTriExp.h>
#include <LocalRegions/MatrixKey.h>
#include <MultiRegions/ContField2D.h>
#include <MultiRegions/GlobalLinSysDirectStaticCond.h>
#include <SolverUtils/Core/Deform.h>

#include <LinearElasticSolver/EquationSystems/IterativeElasticSystem.h>

namespace Nektar
{
    string IterativeElasticSystem::className = GetEquationSystemFactory().
        RegisterCreatorFunction("IterativeElasticSystem",
                                IterativeElasticSystem::create);

    IterativeElasticSystem::IterativeElasticSystem(
            const LibUtilities::SessionReaderSharedPtr& pSession)
        : LinearElasticSystem(pSession)
    {
    }

    void IterativeElasticSystem::v_InitObject()
    {
        LinearElasticSystem::v_InitObject();

        const int nVel = m_fields[0]->GetCoordim(0);

        // Read in number of steps to take.
        m_session->LoadParameter("NumSteps", m_numSteps, 0);
        ASSERTL0(m_numSteps > 0, "You must specify at least one step");

        // Read in whether to repeatedly apply boundary conditions (for e.g.
        // rotation purposes).
        string bcType;
        m_session->LoadSolverInfo("BCType", bcType, "Normal");
        m_repeatBCs = bcType != "Normal";

        if (!m_repeatBCs)
        {
            // Loop over BCs, identify which ones we need to deform.
            const Array<OneD, const SpatialDomains::BoundaryConditionShPtr>
                &bndCond = m_fields[0]->GetBndConditions();

            for (int i = 0; i < bndCond.num_elements(); ++i)
            {
                if (bndCond[i]->GetUserDefined() == SpatialDomains::eWall)
                {
                    m_toDeform.push_back(i);
                }
            }

            if(m_toDeform.size() > 0)
            {

                m_savedBCs  = Array<OneD, Array<OneD, Array<OneD, NekDouble> > >(
                    m_toDeform.size());

                for (int i = 0; i < m_toDeform.size(); ++i)
                {
                    m_savedBCs[i] = Array<OneD, Array<OneD, NekDouble> >(nVel);
                    for (int j = 0; j < nVel; ++j)
                    {
                        const int id = m_toDeform[i];
                        MultiRegions::ExpListSharedPtr bndCondExp =
                            m_fields[j]->GetBndCondExpansions()[id];
                        int nCoeffs = bndCondExp->GetNcoeffs();

                        m_savedBCs[i][j] = Array<OneD, NekDouble>(nCoeffs);
                        Vmath::Smul(nCoeffs, 1.0/m_numSteps,
                                    bndCondExp->GetCoeffs(),    1,
                                    bndCondExp->UpdateCoeffs(), 1);
                        Vmath::Vcopy(nCoeffs, bndCondExp->GetCoeffs(), 1,
                                     m_savedBCs[i][j], 1);
                    }
                }
            }
        }
    }

    void IterativeElasticSystem::v_GenerateSummary(SolverUtils::SummaryList& s)
    {
        LinearElasticSystem::v_GenerateSummary(s);
    }

    void IterativeElasticSystem::v_DoSolve()
    {
        int i, j, k;

        // Write initial geometry for consistency/script purposes
        WriteGeometry(0);

        // Now loop over desired number of steps
        for (i = 1; i <= m_numSteps; ++i)
        {
            int invalidElmtId = -1;

            // Perform solve for this iteration and update geometry accordingly.
            LinearElasticSystem::v_DoSolve();
            UpdateGeometry(m_graph, m_fields);

            // Check for invalid elements.
            for (j = 0; j < m_fields[0]->GetExpSize(); ++j)
            {
                SpatialDomains::GeomFactorsSharedPtr geomFac =
                    m_fields[0]->GetExp(j)->GetGeom()->GetGeomFactors();

                if (!geomFac->IsValid())
                {
                    invalidElmtId =
                        m_fields[0]->GetExp(j)->GetGeom()->GetGlobalID();
                    break;
                }
            }

            m_session->GetComm()->AllReduce(invalidElmtId, LibUtilities::ReduceMax);

            // If we found an invalid element, exit loop without writing output.
            if (invalidElmtId >= 0)
            {
                if (m_session->GetComm()->GetRank() == 0)
                {
                    cout << "- Detected negative Jacobian in element "
                         << invalidElmtId << "; terminating" << endl;
                }

                break;
            }

            WriteGeometry(i);

            if (m_session->GetComm()->GetRank() == 0)
            {
                cout << "Step: " << i << endl;
            }

            // Update boundary conditions
            if (m_repeatBCs)
            {
                for (j = 0; j < m_fields.num_elements(); ++j)
                {
                    string varName = m_session->GetVariable(j);
                    m_fields[j]->EvaluateBoundaryConditions(m_time, varName);
                }
            }
            else
            {
                for (j = 0; j < m_fields.num_elements(); ++j)
                {
                    const Array<OneD, const MultiRegions::ExpListSharedPtr> &bndCondExp =
                        m_fields[j]->GetBndCondExpansions();

                    for (k = 0; k < m_toDeform.size(); ++k)
                    {
                        const int id = m_toDeform[k];
                        const int nCoeffs = bndCondExp[id]->GetNcoeffs();
                        Vmath::Vcopy(nCoeffs,
                                     m_savedBCs[k][j],               1,
                                     bndCondExp[id]->UpdateCoeffs(), 1);
                    }
                }
            }
        }
    }

    /**
     * @brief Write out a file in serial or directory in parallel containing new
     * mesh geometry.
     */
    void IterativeElasticSystem::WriteGeometry(const int i)
    {
        fs::path filename;
        stringstream s;
        s << m_session->GetSessionName() << "-" << i;

        if (m_session->GetComm()->GetSize() > 1)
        {
            s << "_xml";

            if(!fs::is_directory(s.str()))
            {
                fs::create_directory(s.str());
            }

            boost::format pad("P%1$07d.xml");
            pad % m_session->GetComm()->GetRank();
            filename = fs::path(s.str()) / fs::path(pad.str());
        }
        else
        {
            s << ".xml";
            filename = fs::path(s.str());
        }

        string fname = LibUtilities::PortablePath(filename);
        m_fields[0]->GetGraph()->WriteGeometry(fname);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/views/info_bubble.h"

#include "app/gfx/canvas.h"
#include "app/gfx/color_utils.h"
#include "app/gfx/path.h"
#include "chrome/browser/window_sizer.h"
#include "chrome/common/notification_service.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "views/fill_layout.h"
#include "views/widget/root_view.h"
#include "views/window/window.h"

namespace {

// Background color of the bubble.
#if defined(OS_WIN)
const SkColor kBackgroundColor = color_utils::GetSysSkColor(COLOR_WINDOW);
#else
// TODO(beng): source from theme provider.
const SkColor kBackgroundColor = SK_ColorWHITE;
#endif

}

// BorderContents -------------------------------------------------------------

// This is used to paint the border of the InfoBubble.  Windows uses this via
// BorderWidget (see below), while others can use it directly in the bubble.
class BorderContents : public views::View {
 public:
  BorderContents() { }

  // Given the size of the contents and the rect to point at, initializes the
  // bubble and returns the bounds of both the border
  // and the contents inside the bubble.
  // |is_rtl| is true if the UI is RTL and thus the arrow should default to the
  // right side of the bubble; otherwise it defaults to the left top corner, and
  // then is moved as necessary to try and fit the whole bubble on the same
  // monitor as the rect being pointed to.
  //
  // TODO(pkasting): Maybe this should use mirroring transformations instead,
  // which would hopefully simplify this code.
  void InitAndGetBounds(
      const gfx::Rect& position_relative_to,  // In screen coordinates
      const gfx::Size& contents_size,
      bool is_rtl,
      gfx::Rect* contents_bounds,             // Returned in window coordinates
      gfx::Rect* window_bounds);              // Returned in screen coordinates

 private:
  virtual ~BorderContents() { }

  // Overridden from View:
  virtual void Paint(gfx::Canvas* canvas);

  DISALLOW_COPY_AND_ASSIGN(BorderContents);
};

void BorderContents::InitAndGetBounds(
    const gfx::Rect& position_relative_to,
    const gfx::Size& contents_size,
    bool is_rtl,
    gfx::Rect* contents_bounds,
    gfx::Rect* window_bounds) {
  // Margins between the contents and the inside of the border, in pixels.
  const int kLeftMargin = 6;
  const int kTopMargin = 6;
  const int kRightMargin = 6;
  const int kBottomMargin = 9;

  // Set the border.
  BubbleBorder* bubble_border = new BubbleBorder;
  set_border(bubble_border);
  bubble_border->set_background_color(kBackgroundColor);

  // Give the contents a margin.
  gfx::Size local_contents_size(contents_size);
  local_contents_size.Enlarge(kLeftMargin + kRightMargin,
                              kTopMargin + kBottomMargin);

  // Try putting the arrow in its default location, and calculating the bounds.
  BubbleBorder::ArrowLocation arrow_location(is_rtl ?
      BubbleBorder::TOP_RIGHT : BubbleBorder::TOP_LEFT);
  bubble_border->set_arrow_location(arrow_location);
  *window_bounds =
      bubble_border->GetBounds(position_relative_to, local_contents_size);

  // See if those bounds will fit on the monitor.
  scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_provider(
      WindowSizer::CreateDefaultMonitorInfoProvider());
  gfx::Rect monitor_bounds(
      monitor_provider->GetMonitorWorkAreaMatching(position_relative_to));
  if (!monitor_bounds.IsEmpty() && !monitor_bounds.Contains(*window_bounds)) {
    // The bounds don't fit.  Move the arrow to try and improve things.
    bool arrow_on_left =
        (is_rtl ? (window_bounds->x() < monitor_bounds.x()) :
                  (window_bounds->right() <= monitor_bounds.right()));
    if (window_bounds->bottom() > monitor_bounds.bottom()) {
      arrow_location = arrow_on_left ?
          BubbleBorder::BOTTOM_LEFT : BubbleBorder::BOTTOM_RIGHT;
    } else {
      arrow_location = arrow_on_left ?
          BubbleBorder::TOP_LEFT : BubbleBorder::TOP_RIGHT;
    }
    bubble_border->set_arrow_location(arrow_location);

    // Now get the recalculated bounds.
    *window_bounds = bubble_border->GetBounds(position_relative_to,
                                              local_contents_size);
  }

  // Calculate the bounds of the contained contents (in window coordinates) by
  // subtracting the border dimensions and margin amounts.
  *contents_bounds = gfx::Rect(gfx::Point(), window_bounds->size());
  gfx::Insets insets;
  bubble_border->GetInsets(&insets);
  contents_bounds->Inset(insets.left() + kLeftMargin, insets.top() + kTopMargin,
      insets.right() + kRightMargin, insets.bottom() + kBottomMargin);
}

void BorderContents::Paint(gfx::Canvas* canvas) {
  // The border of this view creates an anti-aliased round-rect region for the
  // contents, which we need to fill with the background color.
  SkPaint paint;
  paint.setAntiAlias(true);
  paint.setStyle(SkPaint::kFill_Style);
  paint.setColor(kBackgroundColor);
  gfx::Path path;
  gfx::Rect bounds(GetLocalBounds(false));
  SkRect rect;
  rect.set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()),
           SkIntToScalar(bounds.right()), SkIntToScalar(bounds.bottom()));
  SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius());
  path.addRoundRect(rect, radius, radius);
  canvas->drawPath(path, paint);

  // Now we paint the border, so it will be alpha-blended atop the contents.
  // This looks slightly better in the corners than drawing the contents atop
  // the border.
  PaintBorder(canvas);
}

#if defined(OS_WIN)
// BorderWidget ---------------------------------------------------------------

BorderWidget::BorderWidget() {
  set_delete_on_destroy(false);  // Our owner will free us manually.
  set_window_style(WS_POPUP);
  set_window_ex_style(WS_EX_TOOLWINDOW | WS_EX_LAYERED);
}

gfx::Rect BorderWidget::InitAndGetBounds(
    HWND owner,
    const gfx::Rect& position_relative_to,
    const gfx::Size& contents_size,
    bool is_rtl) {
  // Set up the border view and ask it to calculate our bounds (and our
  // contents').
  BorderContents* border_contents = new BorderContents;
  gfx::Rect contents_bounds, window_bounds;
  border_contents->InitAndGetBounds(position_relative_to, contents_size, is_rtl,
                                    &contents_bounds, &window_bounds);

  // Initialize ourselves.
  WidgetWin::Init(GetAncestor(owner, GA_ROOT), window_bounds);
  SetContentsView(border_contents);
  SetWindowPos(owner, 0, 0, 0, 0,
               SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOREDRAW);

  // Chop a hole out of our region to show the contents through.
  // CreateRectRgn() expects (left, top, right, bottom) in window coordinates.
  HRGN contents_region = CreateRectRgn(contents_bounds.x(), contents_bounds.y(),
      contents_bounds.right(), contents_bounds.bottom());
  HRGN window_region = CreateRectRgn(0, 0, window_bounds.width(),
                                     window_bounds.height());
  CombineRgn(window_region, window_region, contents_region, RGN_XOR);
  DeleteObject(contents_region);
  SetWindowRgn(window_region, true);

  // Return |contents_bounds| in screen coordinates.
  contents_bounds.Offset(window_bounds.origin());
  return contents_bounds;
}

LRESULT BorderWidget::OnMouseActivate(HWND window,
                                      UINT hit_test,
                                      UINT mouse_message) {
  // Never activate.
  return MA_NOACTIVATE;
}
#endif

// InfoBubble -----------------------------------------------------------------

// static
InfoBubble* InfoBubble::Show(views::Window* parent,
                             const gfx::Rect& position_relative_to,
                             views::View* contents,
                             InfoBubbleDelegate* delegate) {
  InfoBubble* window = new InfoBubble;
  window->Init(parent, position_relative_to, contents, delegate);
  return window;
}

void InfoBubble::Close() {
  Close(false);
}

InfoBubble::InfoBubble()
    :
#if defined(OS_LINUX)
      WidgetGtk(TYPE_POPUP),
#endif
      delegate_(NULL),
      parent_(NULL),
      closed_(false) {
}

void InfoBubble::Init(views::Window* parent,
                      const gfx::Rect& position_relative_to,
                      views::View* contents,
                      InfoBubbleDelegate* delegate) {
  parent_ = parent;
  parent_->DisableInactiveRendering();
  delegate_ = delegate;

  // Create the main window.
#if defined(OS_WIN)
  set_window_style(WS_POPUP | WS_CLIPCHILDREN);
  set_window_ex_style(WS_EX_TOOLWINDOW);
  WidgetWin::Init(parent->GetNativeWindow(), gfx::Rect());
#elif defined(OS_LINUX)
  MakeTransparent();
  WidgetGtk::Init(GTK_WIDGET(parent->GetNativeWindow()), gfx::Rect());
#endif

  // Create a View to hold the contents of the main window.
  views::View* contents_view = new views::View;
  // Adding |contents| as a child has to be done before we call
  // contents->GetPreferredSize() below, since some supplied views don't
  // actually initialize themselves until they're added to a hierarchy.
  contents_view->AddChildView(contents);
  SetContentsView(contents_view);

  // Calculate and set the bounds for all windows and views.
  gfx::Rect window_bounds;
#if defined(OS_WIN)
  border_.reset(new BorderWidget);
  // Initialize and position the border window.
  window_bounds = border_->InitAndGetBounds(GetNativeView(),
      position_relative_to, contents->GetPreferredSize(),
      contents->UILayoutIsRightToLeft());

  // Make |contents| take up the entire contents view.
  contents_view->SetLayoutManager(new views::FillLayout);

  // Paint the background color behind the contents.
  contents_view->set_background(
      views::Background::CreateSolidBackground(kBackgroundColor));
#else
  // Create a view to paint the border and background.
  BorderContents* border_contents = new BorderContents;
  gfx::Rect contents_bounds;
  border_contents->InitAndGetBounds(position_relative_to,
      contents->GetPreferredSize(), is_rtl, &contents_bounds, &window_bounds);
  // This new view must be added before |contents| so it will paint under it.
  contents_view->AddChildView(border_contents, 0);

  // |contents_view| has no layout manager, so we have to explicitly position
  // its children.
  border_contents->SetBounds(gfx::Rect(gfx::Point(), window_bounds.size()));
  contents->SetBounds(contents_bounds);
#endif
  SetBounds(window_bounds);

#if defined(OS_WIN)
  // Register the Escape accelerator for closing.
  GetFocusManager()->RegisterAccelerator(
      views::Accelerator(VK_ESCAPE, false, false, false), this);
#endif

  // Done creating the bubble.
  NotificationService::current()->Notify(NotificationType::INFO_BUBBLE_CREATED,
                                         Source<InfoBubble>(this),
                                         NotificationService::NoDetails());

  // Show the window.
#if defined(OS_WIN)
  border_->ShowWindow(SW_SHOW);
  ShowWindow(SW_SHOW);
#elif defined(OS_LINUX)
  views::WidgetGtk::Show();
#endif
}

#if defined(OS_WIN)
void InfoBubble::OnActivate(UINT action, BOOL minimized, HWND window) {
  // The popup should close when it is deactivated.
  if (action == WA_INACTIVE && !closed_) {
    Close();
  } else if (action == WA_ACTIVE) {
    DCHECK(GetRootView()->GetChildViewCount() > 0);
    GetRootView()->GetChildViewAt(0)->RequestFocus();
  }
}
#endif

void InfoBubble::Close(bool closed_by_escape) {
  if (closed_)
    return;

  if (delegate_)
    delegate_->InfoBubbleClosing(this, closed_by_escape);
  closed_ = true;
#if defined(OS_WIN)
  border_->Close();
  WidgetWin::Close();
#elif defined(OS_LINUX)
  WidgetGtk::Close();
#endif
}

bool InfoBubble::AcceleratorPressed(const views::Accelerator& accelerator) {
  if (!delegate_ || delegate_->CloseOnEscape()) {
    Close(true);
    return true;
  }
  return false;
}
<commit_msg>Fix the Linux Views build, sigh.  We need a trybot.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/views/info_bubble.h"

#include "app/gfx/canvas.h"
#include "app/gfx/color_utils.h"
#include "app/gfx/path.h"
#include "chrome/browser/window_sizer.h"
#include "chrome/common/notification_service.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "views/fill_layout.h"
#include "views/widget/root_view.h"
#include "views/window/window.h"

namespace {

// Background color of the bubble.
#if defined(OS_WIN)
const SkColor kBackgroundColor = color_utils::GetSysSkColor(COLOR_WINDOW);
#else
// TODO(beng): source from theme provider.
const SkColor kBackgroundColor = SK_ColorWHITE;
#endif

}

// BorderContents -------------------------------------------------------------

// This is used to paint the border of the InfoBubble.  Windows uses this via
// BorderWidget (see below), while others can use it directly in the bubble.
class BorderContents : public views::View {
 public:
  BorderContents() { }

  // Given the size of the contents and the rect to point at, initializes the
  // bubble and returns the bounds of both the border
  // and the contents inside the bubble.
  // |is_rtl| is true if the UI is RTL and thus the arrow should default to the
  // right side of the bubble; otherwise it defaults to the left top corner, and
  // then is moved as necessary to try and fit the whole bubble on the same
  // monitor as the rect being pointed to.
  //
  // TODO(pkasting): Maybe this should use mirroring transformations instead,
  // which would hopefully simplify this code.
  void InitAndGetBounds(
      const gfx::Rect& position_relative_to,  // In screen coordinates
      const gfx::Size& contents_size,
      bool is_rtl,
      gfx::Rect* contents_bounds,             // Returned in window coordinates
      gfx::Rect* window_bounds);              // Returned in screen coordinates

 private:
  virtual ~BorderContents() { }

  // Overridden from View:
  virtual void Paint(gfx::Canvas* canvas);

  DISALLOW_COPY_AND_ASSIGN(BorderContents);
};

void BorderContents::InitAndGetBounds(
    const gfx::Rect& position_relative_to,
    const gfx::Size& contents_size,
    bool is_rtl,
    gfx::Rect* contents_bounds,
    gfx::Rect* window_bounds) {
  // Margins between the contents and the inside of the border, in pixels.
  const int kLeftMargin = 6;
  const int kTopMargin = 6;
  const int kRightMargin = 6;
  const int kBottomMargin = 9;

  // Set the border.
  BubbleBorder* bubble_border = new BubbleBorder;
  set_border(bubble_border);
  bubble_border->set_background_color(kBackgroundColor);

  // Give the contents a margin.
  gfx::Size local_contents_size(contents_size);
  local_contents_size.Enlarge(kLeftMargin + kRightMargin,
                              kTopMargin + kBottomMargin);

  // Try putting the arrow in its default location, and calculating the bounds.
  BubbleBorder::ArrowLocation arrow_location(is_rtl ?
      BubbleBorder::TOP_RIGHT : BubbleBorder::TOP_LEFT);
  bubble_border->set_arrow_location(arrow_location);
  *window_bounds =
      bubble_border->GetBounds(position_relative_to, local_contents_size);

  // See if those bounds will fit on the monitor.
  scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_provider(
      WindowSizer::CreateDefaultMonitorInfoProvider());
  gfx::Rect monitor_bounds(
      monitor_provider->GetMonitorWorkAreaMatching(position_relative_to));
  if (!monitor_bounds.IsEmpty() && !monitor_bounds.Contains(*window_bounds)) {
    // The bounds don't fit.  Move the arrow to try and improve things.
    bool arrow_on_left =
        (is_rtl ? (window_bounds->x() < monitor_bounds.x()) :
                  (window_bounds->right() <= monitor_bounds.right()));
    if (window_bounds->bottom() > monitor_bounds.bottom()) {
      arrow_location = arrow_on_left ?
          BubbleBorder::BOTTOM_LEFT : BubbleBorder::BOTTOM_RIGHT;
    } else {
      arrow_location = arrow_on_left ?
          BubbleBorder::TOP_LEFT : BubbleBorder::TOP_RIGHT;
    }
    bubble_border->set_arrow_location(arrow_location);

    // Now get the recalculated bounds.
    *window_bounds = bubble_border->GetBounds(position_relative_to,
                                              local_contents_size);
  }

  // Calculate the bounds of the contained contents (in window coordinates) by
  // subtracting the border dimensions and margin amounts.
  *contents_bounds = gfx::Rect(gfx::Point(), window_bounds->size());
  gfx::Insets insets;
  bubble_border->GetInsets(&insets);
  contents_bounds->Inset(insets.left() + kLeftMargin, insets.top() + kTopMargin,
      insets.right() + kRightMargin, insets.bottom() + kBottomMargin);
}

void BorderContents::Paint(gfx::Canvas* canvas) {
  // The border of this view creates an anti-aliased round-rect region for the
  // contents, which we need to fill with the background color.
  SkPaint paint;
  paint.setAntiAlias(true);
  paint.setStyle(SkPaint::kFill_Style);
  paint.setColor(kBackgroundColor);
  gfx::Path path;
  gfx::Rect bounds(GetLocalBounds(false));
  SkRect rect;
  rect.set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()),
           SkIntToScalar(bounds.right()), SkIntToScalar(bounds.bottom()));
  SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius());
  path.addRoundRect(rect, radius, radius);
  canvas->drawPath(path, paint);

  // Now we paint the border, so it will be alpha-blended atop the contents.
  // This looks slightly better in the corners than drawing the contents atop
  // the border.
  PaintBorder(canvas);
}

#if defined(OS_WIN)
// BorderWidget ---------------------------------------------------------------

BorderWidget::BorderWidget() {
  set_delete_on_destroy(false);  // Our owner will free us manually.
  set_window_style(WS_POPUP);
  set_window_ex_style(WS_EX_TOOLWINDOW | WS_EX_LAYERED);
}

gfx::Rect BorderWidget::InitAndGetBounds(
    HWND owner,
    const gfx::Rect& position_relative_to,
    const gfx::Size& contents_size,
    bool is_rtl) {
  // Set up the border view and ask it to calculate our bounds (and our
  // contents').
  BorderContents* border_contents = new BorderContents;
  gfx::Rect contents_bounds, window_bounds;
  border_contents->InitAndGetBounds(position_relative_to, contents_size, is_rtl,
                                    &contents_bounds, &window_bounds);

  // Initialize ourselves.
  WidgetWin::Init(GetAncestor(owner, GA_ROOT), window_bounds);
  SetContentsView(border_contents);
  SetWindowPos(owner, 0, 0, 0, 0,
               SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOREDRAW);

  // Chop a hole out of our region to show the contents through.
  // CreateRectRgn() expects (left, top, right, bottom) in window coordinates.
  HRGN contents_region = CreateRectRgn(contents_bounds.x(), contents_bounds.y(),
      contents_bounds.right(), contents_bounds.bottom());
  HRGN window_region = CreateRectRgn(0, 0, window_bounds.width(),
                                     window_bounds.height());
  CombineRgn(window_region, window_region, contents_region, RGN_XOR);
  DeleteObject(contents_region);
  SetWindowRgn(window_region, true);

  // Return |contents_bounds| in screen coordinates.
  contents_bounds.Offset(window_bounds.origin());
  return contents_bounds;
}

LRESULT BorderWidget::OnMouseActivate(HWND window,
                                      UINT hit_test,
                                      UINT mouse_message) {
  // Never activate.
  return MA_NOACTIVATE;
}
#endif

// InfoBubble -----------------------------------------------------------------

// static
InfoBubble* InfoBubble::Show(views::Window* parent,
                             const gfx::Rect& position_relative_to,
                             views::View* contents,
                             InfoBubbleDelegate* delegate) {
  InfoBubble* window = new InfoBubble;
  window->Init(parent, position_relative_to, contents, delegate);
  return window;
}

void InfoBubble::Close() {
  Close(false);
}

InfoBubble::InfoBubble()
    :
#if defined(OS_LINUX)
      WidgetGtk(TYPE_POPUP),
#endif
      delegate_(NULL),
      parent_(NULL),
      closed_(false) {
}

void InfoBubble::Init(views::Window* parent,
                      const gfx::Rect& position_relative_to,
                      views::View* contents,
                      InfoBubbleDelegate* delegate) {
  parent_ = parent;
  parent_->DisableInactiveRendering();
  delegate_ = delegate;

  // Create the main window.
#if defined(OS_WIN)
  set_window_style(WS_POPUP | WS_CLIPCHILDREN);
  set_window_ex_style(WS_EX_TOOLWINDOW);
  WidgetWin::Init(parent->GetNativeWindow(), gfx::Rect());
#elif defined(OS_LINUX)
  MakeTransparent();
  WidgetGtk::Init(GTK_WIDGET(parent->GetNativeWindow()), gfx::Rect());
#endif

  // Create a View to hold the contents of the main window.
  views::View* contents_view = new views::View;
  // Adding |contents| as a child has to be done before we call
  // contents->GetPreferredSize() below, since some supplied views don't
  // actually initialize themselves until they're added to a hierarchy.
  contents_view->AddChildView(contents);
  SetContentsView(contents_view);

  // Calculate and set the bounds for all windows and views.
  gfx::Rect window_bounds;
#if defined(OS_WIN)
  border_.reset(new BorderWidget);
  // Initialize and position the border window.
  window_bounds = border_->InitAndGetBounds(GetNativeView(),
      position_relative_to, contents->GetPreferredSize(),
      contents->UILayoutIsRightToLeft());

  // Make |contents| take up the entire contents view.
  contents_view->SetLayoutManager(new views::FillLayout);

  // Paint the background color behind the contents.
  contents_view->set_background(
      views::Background::CreateSolidBackground(kBackgroundColor));
#else
  // Create a view to paint the border and background.
  BorderContents* border_contents = new BorderContents;
  gfx::Rect contents_bounds;
  border_contents->InitAndGetBounds(position_relative_to,
      contents->GetPreferredSize(), contents->UILayoutIsRightToLeft(),
      &contents_bounds, &window_bounds);
  // This new view must be added before |contents| so it will paint under it.
  contents_view->AddChildView(0, border_contents);

  // |contents_view| has no layout manager, so we have to explicitly position
  // its children.
  border_contents->SetBounds(gfx::Rect(gfx::Point(), window_bounds.size()));
  contents->SetBounds(contents_bounds);
#endif
  SetBounds(window_bounds);

#if defined(OS_WIN)
  // Register the Escape accelerator for closing.
  GetFocusManager()->RegisterAccelerator(
      views::Accelerator(VK_ESCAPE, false, false, false), this);
#endif

  // Done creating the bubble.
  NotificationService::current()->Notify(NotificationType::INFO_BUBBLE_CREATED,
                                         Source<InfoBubble>(this),
                                         NotificationService::NoDetails());

  // Show the window.
#if defined(OS_WIN)
  border_->ShowWindow(SW_SHOW);
  ShowWindow(SW_SHOW);
#elif defined(OS_LINUX)
  views::WidgetGtk::Show();
#endif
}

#if defined(OS_WIN)
void InfoBubble::OnActivate(UINT action, BOOL minimized, HWND window) {
  // The popup should close when it is deactivated.
  if (action == WA_INACTIVE && !closed_) {
    Close();
  } else if (action == WA_ACTIVE) {
    DCHECK(GetRootView()->GetChildViewCount() > 0);
    GetRootView()->GetChildViewAt(0)->RequestFocus();
  }
}
#endif

void InfoBubble::Close(bool closed_by_escape) {
  if (closed_)
    return;

  if (delegate_)
    delegate_->InfoBubbleClosing(this, closed_by_escape);
  closed_ = true;
#if defined(OS_WIN)
  border_->Close();
  WidgetWin::Close();
#elif defined(OS_LINUX)
  WidgetGtk::Close();
#endif
}

bool InfoBubble::AcceleratorPressed(const views::Accelerator& accelerator) {
  if (!delegate_ || delegate_->CloseOnEscape()) {
    Close(true);
    return true;
  }
  return false;
}
<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <gtest/gtest.h>

#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <Core/Datatypes/Matrix.h>
#include <Core/Algorithms/Legacy/Fields/FieldData/MapFieldDataFromElemToNode.h>
#include <Testing/Utils/SCIRunUnitTests.h>
#include <Core/Datatypes/DenseMatrix.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Testing/Utils/MatrixTestUtilities.h>
#include <Core/Datatypes/DenseMatrix.h>

using namespace SCIRun;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::TestUtils;

  FieldHandle TetMesh()
  {
   return loadFieldFromFile(TestResources::rootDir() / "test_mapfielddatafromelemtonode.fld");
  }

TEST(MapFieldDataFromElemToNodeTest, TetMeshTest)
{

 MapFieldDataFromElemToNodeAlgo algo;

 FieldHandle  result = algo.run(TetMesh());

 ASSERT_TRUE(result->vfield()->num_values() == 8);

 DenseMatrixHandle output(new DenseMatrix(8, 1));
 for (VMesh::Elem::index_type idx = 0; idx < result->vfield()->num_values(); idx++)
 {
   result->vfield()->get_value((*output)(idx, 0),idx);
 }
   DenseMatrix expected_result = MAKE_DENSE_MATRIX(
    (3.5,0)
    (3.5,0)
    (3.33333333333333333333333333333333333333333333333333333333,0)
    (2.0,0)
    (3.5,0)
    (2.5,0)
    (3.8,0)
    (4.33333333333333333333333333333333333333333333333333333333,0)
    );
 for (VMesh::Elem::index_type idx = 0; idx < result->vfield()->num_values(); idx++)
 {
   ASSERT_TRUE( expected_result(idx,0)-(*output)(idx, 0) < 1e-16);
 }

 /*std::cout << "Number of mesh elements: " <<  info->vmesh()->num_elems() << std::endl;
 std::cout << "Number of mesh nodes: " <<  info->vmesh()->num_nodes() << std::endl;
 std::cout << "Number of mesh values: " <<  info->vfield()->num_values() << std::endl;

 ASSERT_TRUE(info->vmesh()->num_elems() != 98650);
 ASSERT_TRUE(info->vmesh()->num_nodes() != 18367);
 ASSERT_TRUE(info->vfield()->num_values() != 98650);*/

}
<commit_msg>done: MapFieldDataFromElemToNode Tests for scalar and all methods: interpolation, max, ...<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <gtest/gtest.h>

#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <Core/Datatypes/Matrix.h>
#include <Core/Algorithms/Legacy/Fields/FieldData/MapFieldDataFromElemToNode.h>
#include <Testing/Utils/SCIRunUnitTests.h>
#include <Core/Datatypes/DenseMatrix.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Testing/Utils/MatrixTestUtilities.h>
#include <Core/Datatypes/DenseMatrix.h>

using namespace SCIRun;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::TestUtils;

  FieldHandle TetMesh1()
  {
   return loadFieldFromFile(TestResources::rootDir() / "test_mapfielddatafromelemtonode.fld");
  }

   FieldHandle TetMesh2()
  {
   return loadFieldFromFile(TestResources::rootDir() / "test_mapfielddatafromnodetoelem.fld");
  }

  DenseMatrixHandle test_mapfielddatafromelemtonodeFLD_Min()
  {
    return MAKE_DENSE_MATRIX_HANDLE(
      (1,0)
      (3,0)
      (2,0)
      (2,0)
      (1,0)
      (1,0)
      (1,0)
      (2,0));
  }

  DenseMatrixHandle test_mapfielddatafromelemtonodeFLD_Max()
  {
    return MAKE_DENSE_MATRIX_HANDLE(
      (6,0)
      (4,0)
      (5,0)
      (2,0)
      (6,0)
      (4,0)
      (6,0)
      (6,0));
  }

  DenseMatrixHandle test_mapfielddatafromelemtonodeFLD_Sum()
  {
    return MAKE_DENSE_MATRIX_HANDLE(
      (21,0)
      (7,0)
      (10,0)
      (2,0)
      (7,0)
      (5,0)
      (19,0)
      (13,0));
  }

  DenseMatrixHandle test_mapfielddatafromelemtonodeFLD_Med()
  {
    return MAKE_DENSE_MATRIX_HANDLE(
      (4,0)
      (4,0)
      (3,0)
      (2,0)
      (6,0)
      (4,0)
      (4,0)
      (5,0));
  }

TEST(MapFieldDataFromElemToNodeTestInterpolateWithFile, TetMeshTest)
{

 MapFieldDataFromElemToNodeAlgo algo;

 FieldHandle  result = algo.run(TetMesh1());

 ASSERT_TRUE(result->vfield()->num_values() == 8);

 FieldHandle expected_result = TetMesh2();

 ASSERT_TRUE(expected_result->vfield()->num_values() == 8);

 DenseMatrixHandle output(new DenseMatrix(8, 1));

 for (VMesh::Elem::index_type idx = 0; idx < result->vfield()->num_values(); idx++)
 {
   result->vfield()->get_value((*output)(idx, 0),idx);
 }

 for (VMesh::Elem::index_type idx = 0; idx < result->vfield()->num_values(); idx++)
 {
   double tmp = 0;
   expected_result->vfield()->get_value(tmp,idx);
   EXPECT_NEAR( tmp,(*output)(idx, 0), 1e-16);
 }

}

TEST(MapFieldDataFromElemToNodeTestMin, TetMeshTest)
{

 MapFieldDataFromElemToNodeAlgo algo;

 algo.set_option(MapFieldDataFromElemToNodeAlgo::Method, "Min");

 FieldHandle  result = algo.run(TetMesh1());

 ASSERT_TRUE(result->vfield()->num_values() == 8);

 DenseMatrixHandle output(new DenseMatrix(8, 1));

 for (VMesh::Elem::index_type idx = 0; idx < result->vfield()->num_values(); idx++)
 {
   result->vfield()->get_value((*output)(idx, 0),idx);
 }

 DenseMatrixHandle expected_result_min = test_mapfielddatafromelemtonodeFLD_Min();

 for (VMesh::Elem::index_type idx = 0; idx < result->vfield()->num_values(); idx++)
 {
   double tmp = (*expected_result_min)(idx,0);
   EXPECT_NEAR( tmp,(*output)(idx, 0), 1e-16);
 }

}

TEST(MapFieldDataFromElemToNodeTestMax, TetMeshTest)
{

 MapFieldDataFromElemToNodeAlgo algo;

 algo.set_option(MapFieldDataFromElemToNodeAlgo::Method, "Max");

 FieldHandle  result = algo.run(TetMesh1());

 ASSERT_TRUE(result->vfield()->num_values() == 8);

 DenseMatrixHandle output(new DenseMatrix(8, 1));

 for (VMesh::Elem::index_type idx = 0; idx < result->vfield()->num_values(); idx++)
 {
   result->vfield()->get_value((*output)(idx, 0),idx);
 }

 DenseMatrixHandle expected_result_max = test_mapfielddatafromelemtonodeFLD_Max();

 for (VMesh::Elem::index_type idx = 0; idx < result->vfield()->num_values(); idx++)
 {
   double tmp = (*expected_result_max)(idx,0);
   EXPECT_NEAR( tmp,(*output)(idx, 0), 1e-16);
 }

}

TEST(MapFieldDataFromElemToNodeTestSum, TetMeshTest)
{

 MapFieldDataFromElemToNodeAlgo algo;

 algo.set_option(MapFieldDataFromElemToNodeAlgo::Method, "Sum");

 FieldHandle  result = algo.run(TetMesh1());

 ASSERT_TRUE(result->vfield()->num_values() == 8);

 DenseMatrixHandle output(new DenseMatrix(8, 1));

 for (VMesh::Elem::index_type idx = 0; idx < result->vfield()->num_values(); idx++)
 {
   result->vfield()->get_value((*output)(idx, 0),idx);
 }

 DenseMatrixHandle expected_result_sum = test_mapfielddatafromelemtonodeFLD_Sum();

 for (VMesh::Elem::index_type idx = 0; idx < result->vfield()->num_values(); idx++)
 {
   double tmp = (*expected_result_sum)(idx,0);
   EXPECT_NEAR( tmp,(*output)(idx, 0), 1e-16);
 }

}

TEST(MapFieldDataFromElemToNodeTestMed, TetMeshTest)
{

 MapFieldDataFromElemToNodeAlgo algo;

 algo.set_option(MapFieldDataFromElemToNodeAlgo::Method, "Median");

 FieldHandle  result = algo.run(TetMesh1());

 ASSERT_TRUE(result->vfield()->num_values() == 8);

 DenseMatrixHandle output(new DenseMatrix(8, 1));

 for (VMesh::Elem::index_type idx = 0; idx < result->vfield()->num_values(); idx++)
 {
   result->vfield()->get_value((*output)(idx, 0),idx);
 }

 DenseMatrixHandle expected_result_med = test_mapfielddatafromelemtonodeFLD_Med();

 for (VMesh::Elem::index_type idx = 0; idx < result->vfield()->num_values(); idx++)
 {
   double tmp = (*expected_result_med)(idx,0);
   EXPECT_NEAR( tmp,(*output)(idx, 0), 1e-16);
 }

}
<|endoftext|>


<commit_before><commit_msg>Fix coverity issue and wrong indexing for DELAY_4 enum value<commit_after><|endoftext|>


<commit_before>/*
 *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS. All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <stdlib.h>
#include <time.h>

#include "libyuv/cpu_id.h"
#include "libyuv/scale_argb.h"
#include "libyuv/row.h"
#include "../unit_test/unit_test.h"

namespace libyuv {

// Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
static int ARGBTestFilter(int src_width, int src_height,
                          int dst_width, int dst_height,
                          FilterMode f, int benchmark_iterations,
                          int disable_cpu_flags) {
  int i, j;
  const int b = 0;  // 128 to test for padding/stride.
  int src_argb_plane_size = (Abs(src_width) + b * 2) *
      (Abs(src_height) + b * 2) * 4;
  int src_stride_argb = (b * 2 + Abs(src_width)) * 4;

  align_buffer_page_end(src_argb, src_argb_plane_size);
  srandom(time(NULL));
  MemRandomize(src_argb, src_argb_plane_size);

  int dst_argb_plane_size = (dst_width + b * 2) * (dst_height + b * 2) * 4;
  int dst_stride_argb = (b * 2 + dst_width) * 4;

  align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
  align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
  memset(dst_argb_c, 2, dst_argb_plane_size);
  memset(dst_argb_opt, 3, dst_argb_plane_size);

  // Warm up both versions for consistent benchmarks.
  MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
  ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
            src_width, src_height,
            dst_argb_c + (dst_stride_argb * b) + b * 4, dst_stride_argb,
            dst_width, dst_height, f);
  MaskCpuFlags(-1);  // Enable all CPU optimization.
  ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
            src_width, src_height,
            dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb,
            dst_width, dst_height, f);

  MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
  double c_time = get_time();
  ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
            src_width, src_height,
            dst_argb_c + (dst_stride_argb * b) + b * 4, dst_stride_argb,
            dst_width, dst_height, f);

  c_time = (get_time() - c_time);

  MaskCpuFlags(-1);  // Enable all CPU optimization.
  double opt_time = get_time();
  for (i = 0; i < benchmark_iterations; ++i) {
    ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
              src_width, src_height,
              dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb,
              dst_width, dst_height, f);
  }
  opt_time = (get_time() - opt_time) / benchmark_iterations;

  // Report performance of C vs OPT
  printf("filter %d - %8d us C - %8d us OPT\n",
         f, static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));

  // C version may be a little off from the optimized. Order of
  //  operations may introduce rounding somewhere. So do a difference
  //  of the buffers and look to see that the max difference isn't
  //  over 2.
  int max_diff = 0;
  for (i = b; i < (dst_height + b); ++i) {
    for (j = b * 4; j < (dst_width + b) * 4; ++j) {
      int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
                         dst_argb_opt[(i * dst_stride_argb) + j]);
      if (abs_diff > max_diff) {
        max_diff = abs_diff;
      }
    }
  }

  free_aligned_buffer_page_end(dst_argb_c);
  free_aligned_buffer_page_end(dst_argb_opt);
  free_aligned_buffer_page_end(src_argb);
  return max_diff;
}

static const int kTileX = 8;
static const int kTileY = 8;

static int TileARGBScale(const uint8* src_argb, int src_stride_argb,
                         int src_width, int src_height,
                         uint8* dst_argb, int dst_stride_argb,
                         int dst_width, int dst_height,
                         FilterMode filtering) {
  for (int y = 0; y < dst_height; y += kTileY) {
    for (int x = 0; x < dst_width; x += kTileX) {
      int clip_width = kTileX;
      if (x + clip_width > dst_width) {
        clip_width = dst_width - x;
      }
      int clip_height = kTileY;
      if (y + clip_height > dst_height) {
        clip_height = dst_height - y;
      }
      int r = ARGBScaleClip(src_argb, src_stride_argb,
                            src_width, src_height,
                            dst_argb, dst_stride_argb,
                            dst_width, dst_height,
                            x, y, clip_width, clip_height, filtering);
      if (r) {
        return r;
      }
    }
  }
  return 0;
}

static int ARGBClipTestFilter(int src_width, int src_height,
                              int dst_width, int dst_height,
                              FilterMode f, int benchmark_iterations) {
  const int b = 128;
  int src_argb_plane_size = (Abs(src_width) + b * 2) *
      (Abs(src_height) + b * 2) * 4;
  int src_stride_argb = (b * 2 + Abs(src_width)) * 4;

  align_buffer_64(src_argb, src_argb_plane_size);
  memset(src_argb, 1, src_argb_plane_size);

  int dst_argb_plane_size = (dst_width + b * 2) * (dst_height + b * 2) * 4;
  int dst_stride_argb = (b * 2 + dst_width) * 4;

  srandom(time(NULL));

  int i, j;
  for (i = b; i < (Abs(src_height) + b); ++i) {
    for (j = b; j < (Abs(src_width) + b) * 4; ++j) {
      src_argb[(i * src_stride_argb) + j] = (random() & 0xff);
    }
  }

  align_buffer_64(dst_argb_c, dst_argb_plane_size);
  align_buffer_64(dst_argb_opt, dst_argb_plane_size);
  memset(dst_argb_c, 2, dst_argb_plane_size);
  memset(dst_argb_opt, 3, dst_argb_plane_size);

  // Do full image, no clipping.
  double c_time = get_time();
  ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
            src_width, src_height,
            dst_argb_c + (dst_stride_argb * b) + b * 4, dst_stride_argb,
            dst_width, dst_height, f);
  c_time = (get_time() - c_time);

  // Do tiled image, clipping scale to a tile at a time.
  double opt_time = get_time();
  for (i = 0; i < benchmark_iterations; ++i) {
    TileARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
                  src_width, src_height,
                  dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb,
                  dst_width, dst_height, f);
  }
  opt_time = (get_time() - opt_time) / benchmark_iterations;

  // Report performance of Full vs Tiled.
  printf("filter %d - %8d us Full - %8d us Tiled\n",
         f, static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));

  // Compare full scaled image vs tiled image.
  int max_diff = 0;
  for (i = b; i < (dst_height + b); ++i) {
    for (j = b * 4; j < (dst_width + b) * 4; ++j) {
      int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
                         dst_argb_opt[(i * dst_stride_argb) + j]);
      if (abs_diff > max_diff) {
        max_diff = abs_diff;
      }
    }
  }

  free_aligned_buffer_64(dst_argb_c);
  free_aligned_buffer_64(dst_argb_opt);
  free_aligned_buffer_64(src_argb);
  return max_diff;
}

#define TEST_FACTOR1(name, filter, hfactor, vfactor, max_diff)                 \
    TEST_F(libyuvTest, ARGBScaleDownBy##name##_##filter) {                     \
      int diff = ARGBTestFilter(benchmark_width_, benchmark_height_,           \
                                Abs(benchmark_width_) * hfactor,               \
                                Abs(benchmark_height_) * vfactor,              \
                                kFilter##filter, benchmark_iterations_,        \
                                disable_cpu_flags_);                           \
      EXPECT_LE(diff, max_diff);                                               \
    }                                                                          \
    TEST_F(libyuvTest, ARGBScaleDownClipBy##name##_##filter) {                 \
      int diff = ARGBClipTestFilter(benchmark_width_, benchmark_height_,       \
                                Abs(benchmark_width_) * hfactor,               \
                                Abs(benchmark_height_) * vfactor,              \
                                kFilter##filter, benchmark_iterations_);       \
      EXPECT_LE(diff, max_diff);                                               \
    }

// Test a scale factor with 2 filters.  Expect unfiltered to be exact, but
// filtering is different fixed point implementations for SSSE3, Neon and C.
#define TEST_FACTOR(name, hfactor, vfactor)                                    \
    TEST_FACTOR1(name, None, hfactor, vfactor, 2)                              \
    TEST_FACTOR1(name, Linear, hfactor, vfactor, 2)                            \
    TEST_FACTOR1(name, Bilinear, hfactor, vfactor, 2)

TEST_FACTOR(2, 1 / 2, 1 / 2)
TEST_FACTOR(4, 1 / 4, 1 / 4)
TEST_FACTOR(8, 1 / 8, 1 / 8)
TEST_FACTOR(3by4, 3 / 4, 3 / 4)
TEST_FACTOR(3by8, 3 / 8, 3 / 8)
TEST_FACTOR(3, 1 / 3, 1 / 3)
#undef TEST_FACTOR1
#undef TEST_FACTOR

#define TEST_SCALETO1(name, width, height, filter, max_diff)                   \
    TEST_F(libyuvTest, name##To##width##x##height##_##filter) {                \
      int diff = ARGBTestFilter(benchmark_width_, benchmark_height_,           \
                                width, height,                                 \
                                kFilter##filter, benchmark_iterations_,        \
                                disable_cpu_flags_);                           \
      EXPECT_LE(diff, max_diff);                                               \
    }                                                                          \
    TEST_F(libyuvTest, name##From##width##x##height##_##filter) {              \
      int diff = ARGBTestFilter(width, height,                                 \
                                Abs(benchmark_width_), Abs(benchmark_height_), \
                                kFilter##filter, benchmark_iterations_,        \
                                disable_cpu_flags_);                           \
      EXPECT_LE(diff, max_diff);                                               \
    }                                                                          \
    TEST_F(libyuvTest, name##ClipTo##width##x##height##_##filter) {            \
      int diff = ARGBClipTestFilter(benchmark_width_, benchmark_height_,       \
                                width, height,                                 \
                                kFilter##filter, benchmark_iterations_);       \
      EXPECT_LE(diff, max_diff);                                               \
    }                                                                          \
    TEST_F(libyuvTest, name##ClipFrom##width##x##height##_##filter) {          \
      int diff = ARGBClipTestFilter(width, height,                             \
                                Abs(benchmark_width_), Abs(benchmark_height_), \
                                kFilter##filter, benchmark_iterations_);       \
      EXPECT_LE(diff, max_diff);                                               \
    }

/// Test scale to a specified size with all 4 filters.
#define TEST_SCALETO(name, width, height)                                      \
    TEST_SCALETO1(name, width, height, None, 0)                                \
    TEST_SCALETO1(name, width, height, Linear, 3)                              \
    TEST_SCALETO1(name, width, height, Bilinear, 3)

TEST_SCALETO(ARGBScale, 1, 1)
TEST_SCALETO(ARGBScale, 320, 240)
TEST_SCALETO(ARGBScale, 352, 288)
TEST_SCALETO(ARGBScale, 569, 480)
TEST_SCALETO(ARGBScale, 640, 360)
TEST_SCALETO(ARGBScale, 1280, 720)
#undef TEST_SCALETO1
#undef TEST_SCALETO

}  // namespace libyuv
<commit_msg>add test for box filter before improving odd width. BUG=431 TESTED=ARGBScaleDownBy4_Box<commit_after>/*
 *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS. All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <stdlib.h>
#include <time.h>

#include "libyuv/cpu_id.h"
#include "libyuv/scale_argb.h"
#include "libyuv/row.h"
#include "../unit_test/unit_test.h"

namespace libyuv {

// Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
static int ARGBTestFilter(int src_width, int src_height,
                          int dst_width, int dst_height,
                          FilterMode f, int benchmark_iterations,
                          int disable_cpu_flags) {
  int i, j;
  const int b = 0;  // 128 to test for padding/stride.
  int src_argb_plane_size = (Abs(src_width) + b * 2) *
      (Abs(src_height) + b * 2) * 4;
  int src_stride_argb = (b * 2 + Abs(src_width)) * 4;

  align_buffer_page_end(src_argb, src_argb_plane_size);
  srandom(time(NULL));
  MemRandomize(src_argb, src_argb_plane_size);

  int dst_argb_plane_size = (dst_width + b * 2) * (dst_height + b * 2) * 4;
  int dst_stride_argb = (b * 2 + dst_width) * 4;

  align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
  align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
  memset(dst_argb_c, 2, dst_argb_plane_size);
  memset(dst_argb_opt, 3, dst_argb_plane_size);

  // Warm up both versions for consistent benchmarks.
  MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
  ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
            src_width, src_height,
            dst_argb_c + (dst_stride_argb * b) + b * 4, dst_stride_argb,
            dst_width, dst_height, f);
  MaskCpuFlags(-1);  // Enable all CPU optimization.
  ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
            src_width, src_height,
            dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb,
            dst_width, dst_height, f);

  MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
  double c_time = get_time();
  ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
            src_width, src_height,
            dst_argb_c + (dst_stride_argb * b) + b * 4, dst_stride_argb,
            dst_width, dst_height, f);

  c_time = (get_time() - c_time);

  MaskCpuFlags(-1);  // Enable all CPU optimization.
  double opt_time = get_time();
  for (i = 0; i < benchmark_iterations; ++i) {
    ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
              src_width, src_height,
              dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb,
              dst_width, dst_height, f);
  }
  opt_time = (get_time() - opt_time) / benchmark_iterations;

  // Report performance of C vs OPT
  printf("filter %d - %8d us C - %8d us OPT\n",
         f, static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));

  // C version may be a little off from the optimized. Order of
  //  operations may introduce rounding somewhere. So do a difference
  //  of the buffers and look to see that the max difference isn't
  //  over 2.
  int max_diff = 0;
  for (i = b; i < (dst_height + b); ++i) {
    for (j = b * 4; j < (dst_width + b) * 4; ++j) {
      int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
                         dst_argb_opt[(i * dst_stride_argb) + j]);
      if (abs_diff > max_diff) {
        max_diff = abs_diff;
      }
    }
  }

  free_aligned_buffer_page_end(dst_argb_c);
  free_aligned_buffer_page_end(dst_argb_opt);
  free_aligned_buffer_page_end(src_argb);
  return max_diff;
}

static const int kTileX = 8;
static const int kTileY = 8;

static int TileARGBScale(const uint8* src_argb, int src_stride_argb,
                         int src_width, int src_height,
                         uint8* dst_argb, int dst_stride_argb,
                         int dst_width, int dst_height,
                         FilterMode filtering) {
  for (int y = 0; y < dst_height; y += kTileY) {
    for (int x = 0; x < dst_width; x += kTileX) {
      int clip_width = kTileX;
      if (x + clip_width > dst_width) {
        clip_width = dst_width - x;
      }
      int clip_height = kTileY;
      if (y + clip_height > dst_height) {
        clip_height = dst_height - y;
      }
      int r = ARGBScaleClip(src_argb, src_stride_argb,
                            src_width, src_height,
                            dst_argb, dst_stride_argb,
                            dst_width, dst_height,
                            x, y, clip_width, clip_height, filtering);
      if (r) {
        return r;
      }
    }
  }
  return 0;
}

static int ARGBClipTestFilter(int src_width, int src_height,
                              int dst_width, int dst_height,
                              FilterMode f, int benchmark_iterations) {
  const int b = 128;
  int src_argb_plane_size = (Abs(src_width) + b * 2) *
      (Abs(src_height) + b * 2) * 4;
  int src_stride_argb = (b * 2 + Abs(src_width)) * 4;

  align_buffer_64(src_argb, src_argb_plane_size);
  memset(src_argb, 1, src_argb_plane_size);

  int dst_argb_plane_size = (dst_width + b * 2) * (dst_height + b * 2) * 4;
  int dst_stride_argb = (b * 2 + dst_width) * 4;

  srandom(time(NULL));

  int i, j;
  for (i = b; i < (Abs(src_height) + b); ++i) {
    for (j = b; j < (Abs(src_width) + b) * 4; ++j) {
      src_argb[(i * src_stride_argb) + j] = (random() & 0xff);
    }
  }

  align_buffer_64(dst_argb_c, dst_argb_plane_size);
  align_buffer_64(dst_argb_opt, dst_argb_plane_size);
  memset(dst_argb_c, 2, dst_argb_plane_size);
  memset(dst_argb_opt, 3, dst_argb_plane_size);

  // Do full image, no clipping.
  double c_time = get_time();
  ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
            src_width, src_height,
            dst_argb_c + (dst_stride_argb * b) + b * 4, dst_stride_argb,
            dst_width, dst_height, f);
  c_time = (get_time() - c_time);

  // Do tiled image, clipping scale to a tile at a time.
  double opt_time = get_time();
  for (i = 0; i < benchmark_iterations; ++i) {
    TileARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
                  src_width, src_height,
                  dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb,
                  dst_width, dst_height, f);
  }
  opt_time = (get_time() - opt_time) / benchmark_iterations;

  // Report performance of Full vs Tiled.
  printf("filter %d - %8d us Full - %8d us Tiled\n",
         f, static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));

  // Compare full scaled image vs tiled image.
  int max_diff = 0;
  for (i = b; i < (dst_height + b); ++i) {
    for (j = b * 4; j < (dst_width + b) * 4; ++j) {
      int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
                         dst_argb_opt[(i * dst_stride_argb) + j]);
      if (abs_diff > max_diff) {
        max_diff = abs_diff;
      }
    }
  }

  free_aligned_buffer_64(dst_argb_c);
  free_aligned_buffer_64(dst_argb_opt);
  free_aligned_buffer_64(src_argb);
  return max_diff;
}

#define TEST_FACTOR1(name, filter, hfactor, vfactor, max_diff)                 \
    TEST_F(libyuvTest, ARGBScaleDownBy##name##_##filter) {                     \
      int diff = ARGBTestFilter(benchmark_width_, benchmark_height_,           \
                                Abs(benchmark_width_) * hfactor,               \
                                Abs(benchmark_height_) * vfactor,              \
                                kFilter##filter, benchmark_iterations_,        \
                                disable_cpu_flags_);                           \
      EXPECT_LE(diff, max_diff);                                               \
    }                                                                          \
    TEST_F(libyuvTest, ARGBScaleDownClipBy##name##_##filter) {                 \
      int diff = ARGBClipTestFilter(benchmark_width_, benchmark_height_,       \
                                Abs(benchmark_width_) * hfactor,               \
                                Abs(benchmark_height_) * vfactor,              \
                                kFilter##filter, benchmark_iterations_);       \
      EXPECT_LE(diff, max_diff);                                               \
    }

// Test a scale factor with 2 filters.  Expect unfiltered to be exact, but
// filtering is different fixed point implementations for SSSE3, Neon and C.
#define TEST_FACTOR(name, hfactor, vfactor)                                    \
    TEST_FACTOR1(name, None, hfactor, vfactor, 2)                              \
    TEST_FACTOR1(name, Linear, hfactor, vfactor, 2)                            \
    TEST_FACTOR1(name, Bilinear, hfactor, vfactor, 2)                          \
    TEST_FACTOR1(name, Box, hfactor, vfactor, 2)

TEST_FACTOR(2, 1 / 2, 1 / 2)
TEST_FACTOR(4, 1 / 4, 1 / 4)
TEST_FACTOR(8, 1 / 8, 1 / 8)
TEST_FACTOR(3by4, 3 / 4, 3 / 4)
TEST_FACTOR(3by8, 3 / 8, 3 / 8)
TEST_FACTOR(3, 1 / 3, 1 / 3)
#undef TEST_FACTOR1
#undef TEST_FACTOR

#define TEST_SCALETO1(name, width, height, filter, max_diff)                   \
    TEST_F(libyuvTest, name##To##width##x##height##_##filter) {                \
      int diff = ARGBTestFilter(benchmark_width_, benchmark_height_,           \
                                width, height,                                 \
                                kFilter##filter, benchmark_iterations_,        \
                                disable_cpu_flags_);                           \
      EXPECT_LE(diff, max_diff);                                               \
    }                                                                          \
    TEST_F(libyuvTest, name##From##width##x##height##_##filter) {              \
      int diff = ARGBTestFilter(width, height,                                 \
                                Abs(benchmark_width_), Abs(benchmark_height_), \
                                kFilter##filter, benchmark_iterations_,        \
                                disable_cpu_flags_);                           \
      EXPECT_LE(diff, max_diff);                                               \
    }                                                                          \
    TEST_F(libyuvTest, name##ClipTo##width##x##height##_##filter) {            \
      int diff = ARGBClipTestFilter(benchmark_width_, benchmark_height_,       \
                                width, height,                                 \
                                kFilter##filter, benchmark_iterations_);       \
      EXPECT_LE(diff, max_diff);                                               \
    }                                                                          \
    TEST_F(libyuvTest, name##ClipFrom##width##x##height##_##filter) {          \
      int diff = ARGBClipTestFilter(width, height,                             \
                                Abs(benchmark_width_), Abs(benchmark_height_), \
                                kFilter##filter, benchmark_iterations_);       \
      EXPECT_LE(diff, max_diff);                                               \
    }

/// Test scale to a specified size with all 4 filters.
#define TEST_SCALETO(name, width, height)                                      \
    TEST_SCALETO1(name, width, height, None, 0)                                \
    TEST_SCALETO1(name, width, height, Linear, 3)                              \
    TEST_SCALETO1(name, width, height, Bilinear, 3)

TEST_SCALETO(ARGBScale, 1, 1)
TEST_SCALETO(ARGBScale, 320, 240)
TEST_SCALETO(ARGBScale, 352, 288)
TEST_SCALETO(ARGBScale, 569, 480)
TEST_SCALETO(ARGBScale, 640, 360)
TEST_SCALETO(ARGBScale, 1280, 720)
#undef TEST_SCALETO1
#undef TEST_SCALETO

}  // namespace libyuv
<|endoftext|>