<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pagectrl.cxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: obo $ $Date: 2006-10-12 12:24:08 $
 *
 *  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_svx.hxx"

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

#define ITEMID_BOX          0
#define ITEMID_FRAMEDIR     0
#ifndef _SV_BITMAP_HXX
#include <vcl/bitmap.hxx>
#endif
#ifndef _SVX_FRMDIRITEM_HXX
#include <frmdiritem.hxx>
#endif
#include "pageitem.hxx"
#include "pagectrl.hxx"
#include "boxitem.hxx"

#include <algorithm>

// struct PageWindow_Impl ------------------------------------------------

struct PageWindow_Impl
{
    SvxBoxItem*     pBorder;
    Bitmap          aBitmap;
    FASTBOOL        bBitmap;
    sal_Bool        bResetBackground;
    sal_Bool        bFrameDirection;
    sal_Int32       nFrameDirection;

    PageWindow_Impl() :
        pBorder(0),
        bBitmap(FALSE),
        bResetBackground(sal_False),
        bFrameDirection(sal_False),
        nFrameDirection(0) {}

    void        EnableFrameDirection(sal_Bool bEnable){bFrameDirection = bEnable;}
    void        SetFrameDirection(sal_Int32 nDirection){nFrameDirection = nDirection;}

};

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

#define CELL_WIDTH      1600L
#define CELL_HEIGHT      800L

// class SvxPageWindow ---------------------------------------------------

SvxPageWindow::SvxPageWindow( Window* pParent, const ResId& rId ) :

    Window( pParent, rId ),

    nTop        ( 0 ),
    nBottom     ( 0 ),
    nLeft       ( 0 ),
    nRight      ( 0 ),
    aColor      ( COL_TRANSPARENT ),
    nHdLeft     ( 0 ),
    nHdRight    ( 0 ),
    nHdDist     ( 0 ),
    nHdHeight   ( 0 ),
    aHdColor    ( COL_TRANSPARENT ),
    pHdBorder   ( 0 ),
    nFtLeft     ( 0 ),
    nFtRight    ( 0 ),
    nFtDist     ( 0 ),
    nFtHeight   ( 0 ),
    aFtColor    ( COL_TRANSPARENT ),
    pFtBorder   ( 0 ),
    bFooter     ( FALSE ),
    bHeader     ( FALSE ),
    bTable      ( FALSE ),
    bHorz       ( FALSE ),
    bVert       ( FALSE ),
    eUsage      ( SVX_PAGE_ALL )

{
    pImpl = new PageWindow_Impl;

    // defaultmaessing in Twips rechnen
    SetMapMode( MapMode( MAP_TWIP ) );
    aWinSize = GetOutputSizePixel();
    aWinSize.Height() -= 4;
    aWinSize.Width() -= 4;

    aWinSize = PixelToLogic( aWinSize );
    SetBackground();
}

// -----------------------------------------------------------------------

SvxPageWindow::~SvxPageWindow()
{
    delete pImpl;
    delete pHdBorder;
    delete pFtBorder;
}

// -----------------------------------------------------------------------

void __EXPORT SvxPageWindow::Paint( const Rectangle& )
{
    Fraction aXScale( aWinSize.Width(), std::max( (long) (aSize.Width() * 2 + aSize.Width() / 8), 1L ) );
    Fraction aYScale( aWinSize.Height(), std::max( aSize.Height(), 1L ) );
    MapMode aMapMode( GetMapMode() );

    if ( aYScale < aXScale )
    {
        aMapMode.SetScaleX( aYScale );
        aMapMode.SetScaleY( aYScale );
    }
    else
    {
        aMapMode.SetScaleX( aXScale );
        aMapMode.SetScaleY( aXScale );
    }
    SetMapMode( aMapMode );
    Size aSz( PixelToLogic( GetSizePixel() ) );
    long nYPos = ( aSz.Height() - aSize.Height() ) / 2;

    if ( eUsage == SVX_PAGE_ALL )
    {
        // alle Seiten gleich -> eine Seite malen
        if ( aSize.Width() > aSize.Height() )
        {
            // Querformat in gleicher Gr"osse zeichnen
            Fraction aX = aMapMode.GetScaleX();
            Fraction aY = aMapMode.GetScaleY();
            Fraction a2( 1.5 );
            aX *= a2;
            aY *= a2;
            aMapMode.SetScaleX( aX );
            aMapMode.SetScaleY( aY );
            SetMapMode( aMapMode );
            aSz = PixelToLogic( GetSizePixel() );
            nYPos = ( aSz.Height() - aSize.Height() ) / 2;
            long nXPos = ( aSz.Width() - aSize.Width() ) / 2;
            DrawPage( Point( nXPos, nYPos ), TRUE, TRUE );
        }
        else
            // Hochformat
            DrawPage( Point( ( aSz.Width() - aSize.Width() ) / 2, nYPos ), TRUE, TRUE );
    }
    else
    {
        // Linke und rechte Seite unterschiedlich -> ggf. zwei Seiten malen
        DrawPage( Point( 0, nYPos ), FALSE, (BOOL)( eUsage & SVX_PAGE_LEFT ) );
        DrawPage( Point( aSize.Width() + aSize.Width() / 8, nYPos ), TRUE,
                  (BOOL)( eUsage & SVX_PAGE_RIGHT ) );
    }
}

// -----------------------------------------------------------------------
void SvxPageWindow::DrawPage( const Point& rOrg, const BOOL bSecond, const BOOL bEnabled )
{
    const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
    const Color& rFieldColor = rStyleSettings.GetFieldColor();
    const Color& rFieldTextColor = rStyleSettings.GetFieldTextColor();
    const Color& rDisableColor = rStyleSettings.GetDisableColor();
    const Color& rDlgColor = rStyleSettings.GetDialogColor();

    // background
    if(!bSecond || pImpl->bResetBackground)
    {
        SetLineColor( Color(COL_TRANSPARENT) );
        SetFillColor( rDlgColor );
        Size winSize(GetOutputSize());
        DrawRect( Rectangle( Point(0,0), winSize ) );

        if ( pImpl->bResetBackground )
            pImpl->bResetBackground = sal_False;
    }
    SetLineColor( rFieldTextColor );
    // Schatten
    Size aTempSize = aSize;
    // Seite
    if ( !bEnabled )
    {
        SetFillColor( rDisableColor );
        DrawRect( Rectangle( rOrg, aTempSize ) );
        return;
    }
    SetFillColor( rFieldColor );
    DrawRect( Rectangle( rOrg, aTempSize ) );

    // Border Top Bottom Left Right
    Point aBegin( rOrg );
    Point aEnd( rOrg );

    long nL = nLeft;
    long nR = nRight;

    if ( eUsage == SVX_PAGE_MIRROR && !bSecond )
    {
        // f"ur gespiegelt drehen
        nL = nRight;
        nR = nLeft;
    }

    Rectangle aRect;

    aRect.Left()  = rOrg.X() + nL;
    aRect.Right() = rOrg.X() + aTempSize.Width() - nR;
    aRect.Top()   = rOrg.Y() + nTop;
    aRect.Bottom()= rOrg.Y() + aTempSize.Height() - nBottom;

    Rectangle aHdRect( aRect );
    Rectangle aFtRect( aRect );

    if ( bHeader )
    {
        // ggf. Header anzeigen
        aHdRect.Left() += nHdLeft;
        aHdRect.Right() -= nHdRight;
        aHdRect.Bottom() = aRect.Top() + nHdHeight;
        aRect.Top() += nHdHeight + nHdDist;
        SetFillColor( aHdColor );
        DrawRect( aHdRect );
    }

    if ( bFooter )
    {
        // ggf. Footer anzeigen
        aFtRect.Left() += nFtLeft;
        aFtRect.Right() -= nFtRight;
        aFtRect.Top() = aRect.Bottom() - nFtHeight;
        aRect.Bottom() -= nFtHeight + nFtDist;
        SetFillColor( aFtColor );
        DrawRect( aFtRect );
    }

    // Body malen
    SetFillColor( aColor );
    if ( pImpl->bBitmap )
    {
        DrawRect( aRect );
        Point aBmpPnt = aRect.TopLeft();
        Size aBmpSiz = aRect.GetSize();
        long nDeltaX = aBmpSiz.Width() / 15;
        long nDeltaY = aBmpSiz.Height() / 15;
        aBmpPnt.X() += nDeltaX;
        aBmpPnt.Y() += nDeltaY;
        aBmpSiz.Width() -= nDeltaX * 2;
        aBmpSiz.Height() -= nDeltaY * 2;
        DrawBitmap( aBmpPnt, aBmpSiz, pImpl->aBitmap );
    }
    else
        DrawRect( aRect );

    if(pImpl->bFrameDirection && !bTable)
    {
       //pImpl->nFrameDirection
        Point aPos;
        Font aFont(GetFont());
        const Size aSaveSize = aFont.GetSize();
        Size aDrawSize( 0, aRect.GetHeight() / 6);
        aFont.SetSize(aDrawSize);
        SetFont(aFont);
        String sText(String::CreateFromAscii("ABC"));
        Point aMove(1, GetTextHeight());
        sal_Unicode cArrow = 0x2193;
        long nAWidth = GetTextWidth(String(sText.GetChar(0)));
        switch(pImpl->nFrameDirection)
        {
            case FRMDIR_HORI_LEFT_TOP:
                aPos = aRect.TopLeft();
                aPos.X() += PixelToLogic(Point(1,1)).X();
                aMove.Y() = 0;
                cArrow = 0x2192;
            break;
            case FRMDIR_HORI_RIGHT_TOP:
                aPos = aRect.TopRight();
                aPos.X() -= nAWidth;
                aMove.Y() = 0;
                aMove.X() *= -1;
                cArrow = 0x2190;
            break;
            case FRMDIR_VERT_TOP_LEFT:
                aPos = aRect.TopLeft();
                aPos.X() += PixelToLogic(Point(1,1)).X();
                aMove.X() = 0;
            break;
            case FRMDIR_VERT_TOP_RIGHT:
                aPos = aRect.TopRight();
                aPos.X() -= nAWidth;
                aMove.X() = 0;
            break;
        }
        sText.Append(cArrow);
        for(USHORT i = 0; i < sText.Len(); i++)
        {
            String sDraw(sText.GetChar(i));
            long nHDiff = 0;
            long nCharWidth = GetTextWidth(sDraw);
            BOOL bHorizontal = 0 == aMove.Y();
            if(!bHorizontal)
            {
                nHDiff = (nAWidth - nCharWidth)/2;
                aPos.X() += nHDiff;
            }
            DrawText(aPos, sDraw);
            if(bHorizontal)
            {
                aPos.X() += aMove.X() < 0 ? - nCharWidth : nCharWidth;
            }
            else
            {
                aPos.X() -= nHDiff;
                aPos.Y() += aMove.Y();
            }
        }
        aFont.SetSize(aSaveSize);
        SetFont(aFont);

    }
    if ( bTable )
    {
        // Tabelle malen, ggf. zentrieren
        SetLineColor( Color(COL_LIGHTGRAY) );

        long nW = aRect.GetWidth(), nH = aRect.GetHeight();
        long nTW = CELL_WIDTH * 3, nTH = CELL_HEIGHT * 3;
        long _nLeft = bHorz ? aRect.Left() + ((nW - nTW) / 2) : aRect.Left();
        long _nTop = bVert ? aRect.Top() + ((nH - nTH) / 2) : aRect.Top();
        Rectangle aCellRect( Point( _nLeft, _nTop ), Size( CELL_WIDTH, CELL_HEIGHT ) );

        for ( USHORT i = 0; i < 3; ++i )
        {
            aCellRect.Left() = _nLeft;
            aCellRect.Right() = _nLeft + CELL_WIDTH;
            if ( i > 0 )
                aCellRect.Move( 0, CELL_HEIGHT );

            for ( USHORT j = 0; j < 3; ++j )
            {
                if ( j > 0 )
                    aCellRect.Move( CELL_WIDTH, 0 );
                DrawRect( aCellRect );
            }
        }
    }
}

// -----------------------------------------------------------------------

void SvxPageWindow::SetBorder( const SvxBoxItem& rNew )
{
    delete pImpl->pBorder;
    pImpl->pBorder = new SvxBoxItem( rNew );
}

// -----------------------------------------------------------------------

void SvxPageWindow::SetBitmap( Bitmap* pBmp )
{
    if ( pBmp )
    {
        pImpl->aBitmap = *pBmp;
        pImpl->bBitmap = TRUE;
    }
    else
        pImpl->bBitmap = FALSE;
}

// -----------------------------------------------------------------------

void SvxPageWindow::SetHdBorder( const SvxBoxItem& rNew )
{
    delete pHdBorder;
    pHdBorder = new SvxBoxItem( rNew );
}
// -----------------------------------------------------------------------

void SvxPageWindow::SetFtBorder( const SvxBoxItem& rNew )
{
    delete pFtBorder;
    pFtBorder = new SvxBoxItem( rNew );
}
/* -----------------------------13.06.2002 16:16------------------------------

 ---------------------------------------------------------------------------*/
void  SvxPageWindow::EnableFrameDirection(sal_Bool bEnable)
{
    pImpl->EnableFrameDirection(bEnable);
}
/* -----------------------------13.06.2002 16:16------------------------------

 ---------------------------------------------------------------------------*/
void  SvxPageWindow::SetFrameDirection(sal_Int32 nFrameDirection)
{
    pImpl->SetFrameDirection(nFrameDirection);
}

void SvxPageWindow::ResetBackground()
{
    pImpl->bResetBackground = sal_True;
}
<commit_msg>INTEGRATION: CWS pchfix04 (1.15.86); FILE MERGED 2007/02/05 12:13:55 os 1.15.86.1: #i73604# usage of ITEMID_* removed<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pagectrl.cxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: kz $ $Date: 2007-05-10 14:40:19 $
 *
 *  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_svx.hxx"

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

#ifndef _SV_BITMAP_HXX
#include <vcl/bitmap.hxx>
#endif
#ifndef _SVX_FRMDIRITEM_HXX
#include <frmdiritem.hxx>
#endif
#include "pageitem.hxx"
#include "pagectrl.hxx"
#include "boxitem.hxx"

#include <algorithm>

// struct PageWindow_Impl ------------------------------------------------

struct PageWindow_Impl
{
    SvxBoxItem*     pBorder;
    Bitmap          aBitmap;
    FASTBOOL        bBitmap;
    sal_Bool        bResetBackground;
    sal_Bool        bFrameDirection;
    sal_Int32       nFrameDirection;

    PageWindow_Impl() :
        pBorder(0),
        bBitmap(FALSE),
        bResetBackground(sal_False),
        bFrameDirection(sal_False),
        nFrameDirection(0) {}

    void        EnableFrameDirection(sal_Bool bEnable){bFrameDirection = bEnable;}
    void        SetFrameDirection(sal_Int32 nDirection){nFrameDirection = nDirection;}

};

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

#define CELL_WIDTH      1600L
#define CELL_HEIGHT      800L

// class SvxPageWindow ---------------------------------------------------

SvxPageWindow::SvxPageWindow( Window* pParent, const ResId& rId ) :

    Window( pParent, rId ),

    nTop        ( 0 ),
    nBottom     ( 0 ),
    nLeft       ( 0 ),
    nRight      ( 0 ),
    aColor      ( COL_TRANSPARENT ),
    nHdLeft     ( 0 ),
    nHdRight    ( 0 ),
    nHdDist     ( 0 ),
    nHdHeight   ( 0 ),
    aHdColor    ( COL_TRANSPARENT ),
    pHdBorder   ( 0 ),
    nFtLeft     ( 0 ),
    nFtRight    ( 0 ),
    nFtDist     ( 0 ),
    nFtHeight   ( 0 ),
    aFtColor    ( COL_TRANSPARENT ),
    pFtBorder   ( 0 ),
    bFooter     ( FALSE ),
    bHeader     ( FALSE ),
    bTable      ( FALSE ),
    bHorz       ( FALSE ),
    bVert       ( FALSE ),
    eUsage      ( SVX_PAGE_ALL )

{
    pImpl = new PageWindow_Impl;

    // defaultmaessing in Twips rechnen
    SetMapMode( MapMode( MAP_TWIP ) );
    aWinSize = GetOutputSizePixel();
    aWinSize.Height() -= 4;
    aWinSize.Width() -= 4;

    aWinSize = PixelToLogic( aWinSize );
    SetBackground();
}

// -----------------------------------------------------------------------

SvxPageWindow::~SvxPageWindow()
{
    delete pImpl;
    delete pHdBorder;
    delete pFtBorder;
}

// -----------------------------------------------------------------------

void __EXPORT SvxPageWindow::Paint( const Rectangle& )
{
    Fraction aXScale( aWinSize.Width(), std::max( (long) (aSize.Width() * 2 + aSize.Width() / 8), 1L ) );
    Fraction aYScale( aWinSize.Height(), std::max( aSize.Height(), 1L ) );
    MapMode aMapMode( GetMapMode() );

    if ( aYScale < aXScale )
    {
        aMapMode.SetScaleX( aYScale );
        aMapMode.SetScaleY( aYScale );
    }
    else
    {
        aMapMode.SetScaleX( aXScale );
        aMapMode.SetScaleY( aXScale );
    }
    SetMapMode( aMapMode );
    Size aSz( PixelToLogic( GetSizePixel() ) );
    long nYPos = ( aSz.Height() - aSize.Height() ) / 2;

    if ( eUsage == SVX_PAGE_ALL )
    {
        // alle Seiten gleich -> eine Seite malen
        if ( aSize.Width() > aSize.Height() )
        {
            // Querformat in gleicher Gr"osse zeichnen
            Fraction aX = aMapMode.GetScaleX();
            Fraction aY = aMapMode.GetScaleY();
            Fraction a2( 1.5 );
            aX *= a2;
            aY *= a2;
            aMapMode.SetScaleX( aX );
            aMapMode.SetScaleY( aY );
            SetMapMode( aMapMode );
            aSz = PixelToLogic( GetSizePixel() );
            nYPos = ( aSz.Height() - aSize.Height() ) / 2;
            long nXPos = ( aSz.Width() - aSize.Width() ) / 2;
            DrawPage( Point( nXPos, nYPos ), TRUE, TRUE );
        }
        else
            // Hochformat
            DrawPage( Point( ( aSz.Width() - aSize.Width() ) / 2, nYPos ), TRUE, TRUE );
    }
    else
    {
        // Linke und rechte Seite unterschiedlich -> ggf. zwei Seiten malen
        DrawPage( Point( 0, nYPos ), FALSE, (BOOL)( eUsage & SVX_PAGE_LEFT ) );
        DrawPage( Point( aSize.Width() + aSize.Width() / 8, nYPos ), TRUE,
                  (BOOL)( eUsage & SVX_PAGE_RIGHT ) );
    }
}

// -----------------------------------------------------------------------
void SvxPageWindow::DrawPage( const Point& rOrg, const BOOL bSecond, const BOOL bEnabled )
{
    const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
    const Color& rFieldColor = rStyleSettings.GetFieldColor();
    const Color& rFieldTextColor = rStyleSettings.GetFieldTextColor();
    const Color& rDisableColor = rStyleSettings.GetDisableColor();
    const Color& rDlgColor = rStyleSettings.GetDialogColor();

    // background
    if(!bSecond || pImpl->bResetBackground)
    {
        SetLineColor( Color(COL_TRANSPARENT) );
        SetFillColor( rDlgColor );
        Size winSize(GetOutputSize());
        DrawRect( Rectangle( Point(0,0), winSize ) );

        if ( pImpl->bResetBackground )
            pImpl->bResetBackground = sal_False;
    }
    SetLineColor( rFieldTextColor );
    // Schatten
    Size aTempSize = aSize;
    // Seite
    if ( !bEnabled )
    {
        SetFillColor( rDisableColor );
        DrawRect( Rectangle( rOrg, aTempSize ) );
        return;
    }
    SetFillColor( rFieldColor );
    DrawRect( Rectangle( rOrg, aTempSize ) );

    // Border Top Bottom Left Right
    Point aBegin( rOrg );
    Point aEnd( rOrg );

    long nL = nLeft;
    long nR = nRight;

    if ( eUsage == SVX_PAGE_MIRROR && !bSecond )
    {
        // f"ur gespiegelt drehen
        nL = nRight;
        nR = nLeft;
    }

    Rectangle aRect;

    aRect.Left()  = rOrg.X() + nL;
    aRect.Right() = rOrg.X() + aTempSize.Width() - nR;
    aRect.Top()   = rOrg.Y() + nTop;
    aRect.Bottom()= rOrg.Y() + aTempSize.Height() - nBottom;

    Rectangle aHdRect( aRect );
    Rectangle aFtRect( aRect );

    if ( bHeader )
    {
        // ggf. Header anzeigen
        aHdRect.Left() += nHdLeft;
        aHdRect.Right() -= nHdRight;
        aHdRect.Bottom() = aRect.Top() + nHdHeight;
        aRect.Top() += nHdHeight + nHdDist;
        SetFillColor( aHdColor );
        DrawRect( aHdRect );
    }

    if ( bFooter )
    {
        // ggf. Footer anzeigen
        aFtRect.Left() += nFtLeft;
        aFtRect.Right() -= nFtRight;
        aFtRect.Top() = aRect.Bottom() - nFtHeight;
        aRect.Bottom() -= nFtHeight + nFtDist;
        SetFillColor( aFtColor );
        DrawRect( aFtRect );
    }

    // Body malen
    SetFillColor( aColor );
    if ( pImpl->bBitmap )
    {
        DrawRect( aRect );
        Point aBmpPnt = aRect.TopLeft();
        Size aBmpSiz = aRect.GetSize();
        long nDeltaX = aBmpSiz.Width() / 15;
        long nDeltaY = aBmpSiz.Height() / 15;
        aBmpPnt.X() += nDeltaX;
        aBmpPnt.Y() += nDeltaY;
        aBmpSiz.Width() -= nDeltaX * 2;
        aBmpSiz.Height() -= nDeltaY * 2;
        DrawBitmap( aBmpPnt, aBmpSiz, pImpl->aBitmap );
    }
    else
        DrawRect( aRect );

    if(pImpl->bFrameDirection && !bTable)
    {
       //pImpl->nFrameDirection
        Point aPos;
        Font aFont(GetFont());
        const Size aSaveSize = aFont.GetSize();
        Size aDrawSize( 0, aRect.GetHeight() / 6);
        aFont.SetSize(aDrawSize);
        SetFont(aFont);
        String sText(String::CreateFromAscii("ABC"));
        Point aMove(1, GetTextHeight());
        sal_Unicode cArrow = 0x2193;
        long nAWidth = GetTextWidth(String(sText.GetChar(0)));
        switch(pImpl->nFrameDirection)
        {
            case FRMDIR_HORI_LEFT_TOP:
                aPos = aRect.TopLeft();
                aPos.X() += PixelToLogic(Point(1,1)).X();
                aMove.Y() = 0;
                cArrow = 0x2192;
            break;
            case FRMDIR_HORI_RIGHT_TOP:
                aPos = aRect.TopRight();
                aPos.X() -= nAWidth;
                aMove.Y() = 0;
                aMove.X() *= -1;
                cArrow = 0x2190;
            break;
            case FRMDIR_VERT_TOP_LEFT:
                aPos = aRect.TopLeft();
                aPos.X() += PixelToLogic(Point(1,1)).X();
                aMove.X() = 0;
            break;
            case FRMDIR_VERT_TOP_RIGHT:
                aPos = aRect.TopRight();
                aPos.X() -= nAWidth;
                aMove.X() = 0;
            break;
        }
        sText.Append(cArrow);
        for(USHORT i = 0; i < sText.Len(); i++)
        {
            String sDraw(sText.GetChar(i));
            long nHDiff = 0;
            long nCharWidth = GetTextWidth(sDraw);
            BOOL bHorizontal = 0 == aMove.Y();
            if(!bHorizontal)
            {
                nHDiff = (nAWidth - nCharWidth)/2;
                aPos.X() += nHDiff;
            }
            DrawText(aPos, sDraw);
            if(bHorizontal)
            {
                aPos.X() += aMove.X() < 0 ? - nCharWidth : nCharWidth;
            }
            else
            {
                aPos.X() -= nHDiff;
                aPos.Y() += aMove.Y();
            }
        }
        aFont.SetSize(aSaveSize);
        SetFont(aFont);

    }
    if ( bTable )
    {
        // Tabelle malen, ggf. zentrieren
        SetLineColor( Color(COL_LIGHTGRAY) );

        long nW = aRect.GetWidth(), nH = aRect.GetHeight();
        long nTW = CELL_WIDTH * 3, nTH = CELL_HEIGHT * 3;
        long _nLeft = bHorz ? aRect.Left() + ((nW - nTW) / 2) : aRect.Left();
        long _nTop = bVert ? aRect.Top() + ((nH - nTH) / 2) : aRect.Top();
        Rectangle aCellRect( Point( _nLeft, _nTop ), Size( CELL_WIDTH, CELL_HEIGHT ) );

        for ( USHORT i = 0; i < 3; ++i )
        {
            aCellRect.Left() = _nLeft;
            aCellRect.Right() = _nLeft + CELL_WIDTH;
            if ( i > 0 )
                aCellRect.Move( 0, CELL_HEIGHT );

            for ( USHORT j = 0; j < 3; ++j )
            {
                if ( j > 0 )
                    aCellRect.Move( CELL_WIDTH, 0 );
                DrawRect( aCellRect );
            }
        }
    }
}

// -----------------------------------------------------------------------

void SvxPageWindow::SetBorder( const SvxBoxItem& rNew )
{
    delete pImpl->pBorder;
    pImpl->pBorder = new SvxBoxItem( rNew );
}

// -----------------------------------------------------------------------

void SvxPageWindow::SetBitmap( Bitmap* pBmp )
{
    if ( pBmp )
    {
        pImpl->aBitmap = *pBmp;
        pImpl->bBitmap = TRUE;
    }
    else
        pImpl->bBitmap = FALSE;
}

// -----------------------------------------------------------------------

void SvxPageWindow::SetHdBorder( const SvxBoxItem& rNew )
{
    delete pHdBorder;
    pHdBorder = new SvxBoxItem( rNew );
}
// -----------------------------------------------------------------------

void SvxPageWindow::SetFtBorder( const SvxBoxItem& rNew )
{
    delete pFtBorder;
    pFtBorder = new SvxBoxItem( rNew );
}
/* -----------------------------13.06.2002 16:16------------------------------

 ---------------------------------------------------------------------------*/
void  SvxPageWindow::EnableFrameDirection(sal_Bool bEnable)
{
    pImpl->EnableFrameDirection(bEnable);
}
/* -----------------------------13.06.2002 16:16------------------------------

 ---------------------------------------------------------------------------*/
void  SvxPageWindow::SetFrameDirection(sal_Int32 nFrameDirection)
{
    pImpl->SetFrameDirection(nFrameDirection);
}

void SvxPageWindow::ResetBackground()
{
    pImpl->bResetBackground = sal_True;
}
<|endoftext|>


<commit_before>/*
	This file is part of the Rendering library.
	Copyright (C) 2007-2012 Benjamin Eikel <benjamin@eikel.org>
	Copyright (C) 2007-2012 Claudius Jähn <claudius@uni-paderborn.de>
	Copyright (C) 2007-2012 Ralf Petring <ralf@petring.net>

	This library is subject to the terms of the Mozilla Public License, v. 2.0.
	You should have received a copy of the MPL along with this library; see the
	file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "Helper.h"
#include "GLHeader.h"
#include <iostream>
#include <iomanip>
#if defined(ANDROID)
#include <android/log.h>
#endif /* defined(ANDROID) */

namespace Rendering {

static bool GLErrorChecking = false;

void enableGLErrorChecking() {
	GLErrorChecking = true;
}

void disableGLErrorChecking() {
	GLErrorChecking = false;
}

static const char * getGLErrorString(GLenum errorFlag) {
	switch (errorFlag) {
		case GL_NO_ERROR:
			return "GL_NO_ERROR";
		case GL_INVALID_ENUM:
			return "GL_INVALID_ENUM";
		case GL_INVALID_VALUE:
			return "GL_INVALID_VALUE";
		case GL_INVALID_OPERATION:
			return "GL_INVALID_OPERATION";
		case GL_OUT_OF_MEMORY:
			return "GL_OUT_OF_MEMORY";
#ifdef LIB_GL
		case GL_STACK_OVERFLOW:
			return "GL_STACK_OVERFLOW";
		case GL_STACK_UNDERFLOW:
			return "GL_STACK_UNDERFLOW";
		case GL_TABLE_TOO_LARGE:
			return "GL_TABLE_TOO_LARGE";
#endif /* LIB_GL */
#ifdef LIB_GLESv2
		case GL_INVALID_FRAMEBUFFER_OPERATION:
			return "GL_INVALID_FRAMEBUFFER_OPERATION";
#endif /* LIB_GLESv2 */
		default:
			return "Unknown error";
	}
}

void checkGLError(const char * file, int line) {
	if(!GLErrorChecking) {
		return;
	}
	// Call glGetError() in a loop, because there might be multiple recorded errors.
	GLenum errorFlag = glGetError();
	while (errorFlag != GL_NO_ERROR) {
#if defined(ANDROID)
		__android_log_print(ANDROID_LOG_WARN, "RenderingMobile", "GL ERROR (%i):%s at %s:%i", errorFlag, getGLErrorString(errorFlag), file, line);
#else
		std::cerr << "GL ERROR (0x" << std::hex << errorFlag << "):" << getGLErrorString(errorFlag) << " at " << file << ":" << std::dec << line << std::endl;
#endif
		errorFlag = glGetError();
	}
}

const char * getGLTypeString(uint32_t type) {
	switch (static_cast<GLenum>(type)) {
		case GL_BOOL:
			return "bool";
		case GL_UNSIGNED_BYTE:
			return "uchar";
		case GL_BYTE:
			return "char";
		case GL_UNSIGNED_SHORT:
			return "ushort";
		case GL_SHORT:
			return "short";
		case GL_UNSIGNED_INT:
			return "uint";
		case GL_INT:
			return "int";
		case GL_FLOAT:
			return "float";
#ifdef LIB_GL
		case GL_DOUBLE:
			return "double";
		case GL_UNSIGNED_INT_24_8_EXT:
			return "uint_24_8_EXT";
#endif
		default:
			return "";
	}
}

unsigned int getGLTypeSize(uint32_t type) {
	switch (static_cast<GLenum>(type)) {
		case GL_BOOL:
			return sizeof(GLboolean);
		case GL_UNSIGNED_BYTE:
			return sizeof(GLubyte);
		case GL_BYTE:
			return sizeof(GLbyte);
		case GL_UNSIGNED_SHORT:
			return sizeof(GLushort);
		case GL_SHORT:
			return sizeof(GLshort);
		case GL_UNSIGNED_INT:
			return sizeof(GLuint);
		case GL_INT:
			return sizeof(GLint);
		case GL_FLOAT:
			return sizeof(GLfloat);
	#ifdef LIB_GL
		case GL_DOUBLE:
			return sizeof(GLdouble);
		case GL_UNSIGNED_INT_24_8_EXT:
			return sizeof(GLuint);
	#endif /* LIB_GL */
		default:
			return 0;
	}
}

void outputGLInformation(std::ostream & output) {
	output << "OpenGL vendor: " << glGetString(GL_VENDOR) << '\n';
	output << "OpenGL renderer: " << glGetString(GL_RENDERER) << '\n';
	output << "OpenGL version: " << glGetString(GL_VERSION) << '\n';
	output << "OpenGL shading language version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << '\n';
}

const char * getGraphicsLanguageVersion() {
	return reinterpret_cast<const char *>(glGetString(GL_VERSION));
}

const char * getShadingLanguageVersion() {
	return reinterpret_cast<const char *>(glGetString(GL_SHADING_LANGUAGE_VERSION));
}

bool isExtensionSupported(const char * extension) {
#if defined(LIB_GLEW)
	return glewIsSupported(extension);
#else
	return false;
#endif
}

float readDepthValue(int32_t x, int32_t y) {
	GLfloat z;
	glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
	return z;
}

#if defined(LIB_GLEW) && defined(LIB_GL) && defined(GL_ARB_debug_output)

#if defined(_WIN32)
static void debugCallback(GLenum, GLenum, GLuint, GLenum, GLsizei , const char *, void * ) __attribute__((__stdcall__));
#endif

static void debugCallback(GLenum source,
						  GLenum type,
						  GLuint id,
						  GLenum severity,
						  GLsizei /*length*/,
						  const char * message,
						  void * /*userParam*/) {
	std::cerr << "GL DEBUG source=";
	switch(source) {
		case GL_DEBUG_SOURCE_API_ARB:
			std::cerr << "GL";
			break;
		case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
			std::cerr << "GLSL";
			break;
		case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
			std::cerr << "GLX/WGL";
			break;
		case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
			std::cerr << "ThirdParty";
			break;
		case GL_DEBUG_SOURCE_APPLICATION_ARB:
			std::cerr << "Application";
			break;
		case GL_DEBUG_SOURCE_OTHER_ARB:
		default:
			std::cerr << "Other";
			break;
	}
	std::cerr << " type=";
	switch(type) {
		case GL_DEBUG_TYPE_ERROR_ARB:
			std::cerr << "Error";
			break;
		case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
			std::cerr << "DeprecatedBehaviour";
			break;
		case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
			std::cerr << "UndefinedBehaviour";
			break;
		case GL_DEBUG_TYPE_PERFORMANCE_ARB:
			std::cerr << "Performance";
			break;
		case GL_DEBUG_TYPE_PORTABILITY_ARB:
			std::cerr << "Portability";
			break;
		case GL_DEBUG_TYPE_OTHER_ARB:
		default:
			std::cerr << "Other";
			break;
	}
	std::cerr << " id=" << id << " severity=";
	switch(severity) {
		case GL_DEBUG_SEVERITY_HIGH_ARB:
			std::cerr << "High";
			break;
		case GL_DEBUG_SEVERITY_MEDIUM_ARB:
			std::cerr << "Medium";
			break;
		case GL_DEBUG_SEVERITY_LOW_ARB:
		default:
			std::cerr << "Low";
			break;
	}
	std::cerr << " message=" << message << std::endl;
}
#endif

void enableDebugOutput() {
#if defined(LIB_GLEW) && defined(LIB_GL) && defined(GL_ARB_debug_output)
	if(!glewIsSupported("GL_ARB_debug_output")) {
		std::cerr << "GL_ARB_debug_output is not supported" << std::endl;
		return;
	}
	glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
	glDebugMessageCallbackARB(&debugCallback, nullptr);
	glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
	glDebugMessageInsertARB(GL_DEBUG_SOURCE_THIRD_PARTY_ARB, GL_DEBUG_TYPE_OTHER_ARB, 1, GL_DEBUG_SEVERITY_LOW_ARB, -1, "Rendering: Debugging enabled");
#else
	std::cerr << "GL_ARB_debug_output is not supported" << std::endl;
#endif
}

void disableDebugOutput() {
#if defined(LIB_GLEW) && defined(LIB_GL) && defined(GL_ARB_debug_output)
	if(!glewIsSupported("GL_ARB_debug_output")) {
		std::cerr << "GL_ARB_debug_output is not supported" << std::endl;
		return;
	}
	glDebugMessageInsertARB(GL_DEBUG_SOURCE_THIRD_PARTY_ARB, GL_DEBUG_TYPE_OTHER_ARB, 2, GL_DEBUG_SEVERITY_LOW_ARB, -1, "Rendering: Debugging disabled");
	glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE);
	glDebugMessageCallbackARB(nullptr, nullptr);
	glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
#else
	std::cerr << "GL_ARB_debug_output is not supported" << std::endl;
#endif
}

}
<commit_msg>Define userParam const void * instead of void *<commit_after>/*
	This file is part of the Rendering library.
	Copyright (C) 2007-2012 Benjamin Eikel <benjamin@eikel.org>
	Copyright (C) 2007-2012 Claudius Jähn <claudius@uni-paderborn.de>
	Copyright (C) 2007-2012 Ralf Petring <ralf@petring.net>

	This library is subject to the terms of the Mozilla Public License, v. 2.0.
	You should have received a copy of the MPL along with this library; see the
	file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "Helper.h"
#include "GLHeader.h"
#include <iostream>
#include <iomanip>
#if defined(ANDROID)
#include <android/log.h>
#endif /* defined(ANDROID) */

namespace Rendering {

static bool GLErrorChecking = false;

void enableGLErrorChecking() {
	GLErrorChecking = true;
}

void disableGLErrorChecking() {
	GLErrorChecking = false;
}

static const char * getGLErrorString(GLenum errorFlag) {
	switch (errorFlag) {
		case GL_NO_ERROR:
			return "GL_NO_ERROR";
		case GL_INVALID_ENUM:
			return "GL_INVALID_ENUM";
		case GL_INVALID_VALUE:
			return "GL_INVALID_VALUE";
		case GL_INVALID_OPERATION:
			return "GL_INVALID_OPERATION";
		case GL_OUT_OF_MEMORY:
			return "GL_OUT_OF_MEMORY";
#ifdef LIB_GL
		case GL_STACK_OVERFLOW:
			return "GL_STACK_OVERFLOW";
		case GL_STACK_UNDERFLOW:
			return "GL_STACK_UNDERFLOW";
		case GL_TABLE_TOO_LARGE:
			return "GL_TABLE_TOO_LARGE";
#endif /* LIB_GL */
#ifdef LIB_GLESv2
		case GL_INVALID_FRAMEBUFFER_OPERATION:
			return "GL_INVALID_FRAMEBUFFER_OPERATION";
#endif /* LIB_GLESv2 */
		default:
			return "Unknown error";
	}
}

void checkGLError(const char * file, int line) {
	if(!GLErrorChecking) {
		return;
	}
	// Call glGetError() in a loop, because there might be multiple recorded errors.
	GLenum errorFlag = glGetError();
	while (errorFlag != GL_NO_ERROR) {
#if defined(ANDROID)
		__android_log_print(ANDROID_LOG_WARN, "RenderingMobile", "GL ERROR (%i):%s at %s:%i", errorFlag, getGLErrorString(errorFlag), file, line);
#else
		std::cerr << "GL ERROR (0x" << std::hex << errorFlag << "):" << getGLErrorString(errorFlag) << " at " << file << ":" << std::dec << line << std::endl;
#endif
		errorFlag = glGetError();
	}
}

const char * getGLTypeString(uint32_t type) {
	switch (static_cast<GLenum>(type)) {
		case GL_BOOL:
			return "bool";
		case GL_UNSIGNED_BYTE:
			return "uchar";
		case GL_BYTE:
			return "char";
		case GL_UNSIGNED_SHORT:
			return "ushort";
		case GL_SHORT:
			return "short";
		case GL_UNSIGNED_INT:
			return "uint";
		case GL_INT:
			return "int";
		case GL_FLOAT:
			return "float";
#ifdef LIB_GL
		case GL_DOUBLE:
			return "double";
		case GL_UNSIGNED_INT_24_8_EXT:
			return "uint_24_8_EXT";
#endif
		default:
			return "";
	}
}

unsigned int getGLTypeSize(uint32_t type) {
	switch (static_cast<GLenum>(type)) {
		case GL_BOOL:
			return sizeof(GLboolean);
		case GL_UNSIGNED_BYTE:
			return sizeof(GLubyte);
		case GL_BYTE:
			return sizeof(GLbyte);
		case GL_UNSIGNED_SHORT:
			return sizeof(GLushort);
		case GL_SHORT:
			return sizeof(GLshort);
		case GL_UNSIGNED_INT:
			return sizeof(GLuint);
		case GL_INT:
			return sizeof(GLint);
		case GL_FLOAT:
			return sizeof(GLfloat);
	#ifdef LIB_GL
		case GL_DOUBLE:
			return sizeof(GLdouble);
		case GL_UNSIGNED_INT_24_8_EXT:
			return sizeof(GLuint);
	#endif /* LIB_GL */
		default:
			return 0;
	}
}

void outputGLInformation(std::ostream & output) {
	output << "OpenGL vendor: " << glGetString(GL_VENDOR) << '\n';
	output << "OpenGL renderer: " << glGetString(GL_RENDERER) << '\n';
	output << "OpenGL version: " << glGetString(GL_VERSION) << '\n';
	output << "OpenGL shading language version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << '\n';
}

const char * getGraphicsLanguageVersion() {
	return reinterpret_cast<const char *>(glGetString(GL_VERSION));
}

const char * getShadingLanguageVersion() {
	return reinterpret_cast<const char *>(glGetString(GL_SHADING_LANGUAGE_VERSION));
}

bool isExtensionSupported(const char * extension) {
#if defined(LIB_GLEW)
	return glewIsSupported(extension);
#else
	return false;
#endif
}

float readDepthValue(int32_t x, int32_t y) {
	GLfloat z;
	glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
	return z;
}

#if defined(LIB_GLEW) && defined(LIB_GL) && defined(GL_ARB_debug_output)

#if defined(_WIN32)
static void debugCallback(GLenum, GLenum, GLuint, GLenum, GLsizei , const char *, const void * ) __attribute__((__stdcall__));
#endif

static void debugCallback(GLenum source,
						  GLenum type,
						  GLuint id,
						  GLenum severity,
						  GLsizei /*length*/,
						  const char * message,
                          const void * /*userParam*/) {
	std::cerr << "GL DEBUG source=";
	switch(source) {
		case GL_DEBUG_SOURCE_API_ARB:
			std::cerr << "GL";
			break;
		case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
			std::cerr << "GLSL";
			break;
		case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
			std::cerr << "GLX/WGL";
			break;
		case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
			std::cerr << "ThirdParty";
			break;
		case GL_DEBUG_SOURCE_APPLICATION_ARB:
			std::cerr << "Application";
			break;
		case GL_DEBUG_SOURCE_OTHER_ARB:
		default:
			std::cerr << "Other";
			break;
	}
	std::cerr << " type=";
	switch(type) {
		case GL_DEBUG_TYPE_ERROR_ARB:
			std::cerr << "Error";
			break;
		case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
			std::cerr << "DeprecatedBehaviour";
			break;
		case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
			std::cerr << "UndefinedBehaviour";
			break;
		case GL_DEBUG_TYPE_PERFORMANCE_ARB:
			std::cerr << "Performance";
			break;
		case GL_DEBUG_TYPE_PORTABILITY_ARB:
			std::cerr << "Portability";
			break;
		case GL_DEBUG_TYPE_OTHER_ARB:
		default:
			std::cerr << "Other";
			break;
	}
	std::cerr << " id=" << id << " severity=";
	switch(severity) {
		case GL_DEBUG_SEVERITY_HIGH_ARB:
			std::cerr << "High";
			break;
		case GL_DEBUG_SEVERITY_MEDIUM_ARB:
			std::cerr << "Medium";
			break;
		case GL_DEBUG_SEVERITY_LOW_ARB:
		default:
			std::cerr << "Low";
			break;
	}
	std::cerr << " message=" << message << std::endl;
}
#endif

void enableDebugOutput() {
#if defined(LIB_GLEW) && defined(LIB_GL) && defined(GL_ARB_debug_output)
	if(!glewIsSupported("GL_ARB_debug_output")) {
		std::cerr << "GL_ARB_debug_output is not supported" << std::endl;
		return;
	}
	glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
	glDebugMessageCallbackARB(&debugCallback, nullptr);
	glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
	glDebugMessageInsertARB(GL_DEBUG_SOURCE_THIRD_PARTY_ARB, GL_DEBUG_TYPE_OTHER_ARB, 1, GL_DEBUG_SEVERITY_LOW_ARB, -1, "Rendering: Debugging enabled");
#else
	std::cerr << "GL_ARB_debug_output is not supported" << std::endl;
#endif
}

void disableDebugOutput() {
#if defined(LIB_GLEW) && defined(LIB_GL) && defined(GL_ARB_debug_output)
	if(!glewIsSupported("GL_ARB_debug_output")) {
		std::cerr << "GL_ARB_debug_output is not supported" << std::endl;
		return;
	}
	glDebugMessageInsertARB(GL_DEBUG_SOURCE_THIRD_PARTY_ARB, GL_DEBUG_TYPE_OTHER_ARB, 2, GL_DEBUG_SEVERITY_LOW_ARB, -1, "Rendering: Debugging disabled");
	glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE);
	glDebugMessageCallbackARB(nullptr, nullptr);
	glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
#else
	std::cerr << "GL_ARB_debug_output is not supported" << std::endl;
#endif
}

}
<|endoftext|>


<commit_before>/**
 * Copyright 2018 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <memory>

#include "nan.h"
#include "v8-profiler.h"

using namespace v8;

// Sampling Heap Profiler

Local<Value> TranslateAllocationProfile(AllocationProfile::Node* node) {
  Local<Object> js_node = Nan::New<Object>();

  Nan::Set(js_node, Nan::New<String>("name").ToLocalChecked(), node->name);
  Nan::Set(js_node, Nan::New<String>("scriptName").ToLocalChecked(),
           node->script_name);
  Nan::Set(js_node, Nan::New<String>("scriptId").ToLocalChecked(),
           Nan::New<Integer>(node->script_id));
  Nan::Set(js_node, Nan::New<String>("lineNumber").ToLocalChecked(),
           Nan::New<Integer>(node->line_number));
  Nan::Set(js_node, Nan::New<String>("columnNumber").ToLocalChecked(),
           Nan::New<Integer>(node->column_number));

  Local<Array> children = Nan::New<Array>(node->children.size());
  for (size_t i = 0; i < node->children.size(); i++) {
    Nan::Set(children, i, TranslateAllocationProfile(node->children[i]));
  }
  Nan::Set(js_node, Nan::New<String>("children").ToLocalChecked(), children);
  Local<Array> allocations = Nan::New<Array>(node->allocations.size());
  for (size_t i = 0; i < node->allocations.size(); i++) {
    AllocationProfile::Allocation alloc = node->allocations[i];
    Local<Object> js_alloc = Nan::New<Object>();
    Nan::Set(js_alloc, Nan::New<String>("sizeBytes").ToLocalChecked(),
             Nan::New<Number>(alloc.size));
    Nan::Set(js_alloc, Nan::New<String>("count").ToLocalChecked(),
             Nan::New<Number>(alloc.count));
    Nan::Set(allocations, i, js_alloc);
  }
  Nan::Set(js_node, Nan::New<String>("allocations").ToLocalChecked(),
           allocations);
  return js_node;
}

NAN_METHOD(StartSamplingHeapProfiler) {
  if (info.Length() == 2) {
    if (!info[0]->IsUint32()) {
      return Nan::ThrowTypeError("First argument type must be uint32.");
    }
    if (!info[1]->IsNumber()) {
      return Nan::ThrowTypeError("First argument type must be Integer.");
    }

#if NODE_MODULE_VERSION > NODE_8_0_MODULE_VERSION
    uint64_t sample_interval = info[0].As<Integer>()->Value();
    int stack_depth = info[1].As<Integer>()->Value();
#else
    uint64_t sample_interval = info[0].As<Integer>()->Uint32Value();
    int stack_depth = info[1].As<Integer>()->IntegerValue();
#endif

    info.GetIsolate()->GetHeapProfiler()->StartSamplingHeapProfiler(
        sample_interval, stack_depth);
  } else {
    info.GetIsolate()->GetHeapProfiler()->StartSamplingHeapProfiler();
  }
}

// Signature:
// stopSamplingHeapProfiler()
NAN_METHOD(StopSamplingHeapProfiler) {
  info.GetIsolate()->GetHeapProfiler()->StopSamplingHeapProfiler();
}

// Signature:
// getAllocationProfile(): AllocationProfileNode
NAN_METHOD(GetAllocationProfile) {
  std::unique_ptr<v8::AllocationProfile> profile(
      info.GetIsolate()->GetHeapProfiler()->GetAllocationProfile());
  AllocationProfile::Node* root = profile->GetRootNode();
  info.GetReturnValue().Set(TranslateAllocationProfile(root));
}

// Time profiler

#if NODE_MODULE_VERSION > NODE_8_0_MODULE_VERSION
// This profiler exists for the lifetime of the program. Not calling
// CpuProfiler::Dispose() is intentional.
CpuProfiler* cpuProfiler = CpuProfiler::New(v8::Isolate::GetCurrent());
#else
CpuProfiler* cpuProfiler = v8::Isolate::GetCurrent()->GetCpuProfiler();
#endif

Local<Object> CreateTimeNode(Local<String> name, Local<String> scriptName,
                             Local<Integer> scriptId, Local<Integer> lineNumber,
                             Local<Integer> columnNumber,
                             Local<Integer> hitCount, Local<Array> children) {
  Local<Object> js_node = Nan::New<Object>();
  Nan::Set(js_node, Nan::New<String>("name").ToLocalChecked(), name);
  Nan::Set(js_node, Nan::New<String>("scriptName").ToLocalChecked(),
           scriptName);
  Nan::Set(js_node, Nan::New<String>("scriptId").ToLocalChecked(), scriptId);
  Nan::Set(js_node, Nan::New<String>("lineNumber").ToLocalChecked(),
           lineNumber);
  Nan::Set(js_node, Nan::New<String>("columnNumber").ToLocalChecked(),
           columnNumber);
  Nan::Set(js_node, Nan::New<String>("hitCount").ToLocalChecked(), hitCount);
  Nan::Set(js_node, Nan::New<String>("children").ToLocalChecked(), children);

  return js_node;
}

#if NODE_MODULE_VERSION > NODE_11_0_MODULE_VERSION
Local<Object> TranslateLineNumbersTimeProfileNode(const CpuProfileNode* parent,
                                                  const CpuProfileNode* node);

Local<Array> GetLineNumberTimeProfileChildren(const CpuProfileNode* parent,
                                              const CpuProfileNode* node) {
  unsigned int index = 0;
  Local<Array> children;
  int32_t count = node->GetChildrenCount();

  unsigned int hitLineCount = node->GetHitLineCount();
  unsigned int hitCount = node->GetHitCount();
  if (hitLineCount > 0) {
    std::vector<CpuProfileNode::LineTick> entries(hitLineCount);
    node->GetLineTicks(&entries[0], hitLineCount);
    children = Nan::New<Array>(count + hitLineCount);
    for (const CpuProfileNode::LineTick entry : entries) {
      Nan::Set(children, index++,
               CreateTimeNode(
                   node->GetFunctionName(), node->GetScriptResourceName(),
                   Nan::New<Integer>(node->GetScriptId()),
                   Nan::New<Integer>(entry.line), Nan::New<Integer>(0),
                   Nan::New<Integer>(entry.hit_count), Nan::New<Array>(0)));
    }
  } else if (hitCount > 0) {
    // Handle nodes for pseudo-functions like "process" and "garbage collection"
    // which do not have hit line counts.
    children = Nan::New<Array>(count + 1);
    Nan::Set(
        children, index++,
        CreateTimeNode(node->GetFunctionName(), node->GetScriptResourceName(),
                       Nan::New<Integer>(node->GetScriptId()),
                       Nan::New<Integer>(node->GetLineNumber()),
                       Nan::New<Integer>(node->GetColumnNumber()),
                       Nan::New<Integer>(hitCount), Nan::New<Array>(0)));
  } else {
    children = Nan::New<Array>(count);
  }

  for (int32_t i = 0; i < count; i++) {
    Nan::Set(children, index++,
             TranslateLineNumbersTimeProfileNode(node, node->GetChild(i)));
  };

  return children;
}

Local<Object> TranslateLineNumbersTimeProfileNode(const CpuProfileNode* parent,
                                                  const CpuProfileNode* node) {
  return CreateTimeNode(
      parent->GetFunctionName(), parent->GetScriptResourceName(),
      Nan::New<Integer>(parent->GetScriptId()),
      Nan::New<Integer>(node->GetLineNumber()),
      Nan::New<Integer>(node->GetColumnNumber()), Nan::New<Integer>(0),
      GetLineNumberTimeProfileChildren(parent, node));
}

// In profiles with line level accurate line numbers, a node's line number
// and column number refer to the line/column from which the function was
// called.
Local<Value> TranslateLineNumbersTimeProfileRoot(const CpuProfileNode* node) {
  int32_t count = node->GetChildrenCount();
  std::vector<Local<Array>> childrenArrs(count);
  int32_t childCount = 0;
  for (int32_t i = 0; i < count; i++) {
    Local<Array> c = GetLineNumberTimeProfileChildren(node, node->GetChild(i));
    childCount = childCount + c->Length();
    childrenArrs[i] = c;
  }

  Local<Array> children = Nan::New<Array>(childCount);
  int32_t idx = 0;
  for (int32_t i = 0; i < count; i++) {
    Local<Array> arr = childrenArrs[i];
    for (uint32_t j = 0; j < arr->Length(); j++) {
      Nan::Set(children, idx, Nan::Get(arr, j).ToLocalChecked());
      idx++;
    }
  }

  return CreateTimeNode(node->GetFunctionName(), node->GetScriptResourceName(),
                        Nan::New<Integer>(node->GetScriptId()),
                        Nan::New<Integer>(node->GetLineNumber()),
                        Nan::New<Integer>(node->GetColumnNumber()),
                        Nan::New<Integer>(0), children);
}
#endif

Local<Value> TranslateTimeProfileNode(const CpuProfileNode* node) {
  int32_t count = node->GetChildrenCount();
  Local<Array> children = Nan::New<Array>(count);
  for (int32_t i = 0; i < count; i++) {
    Nan::Set(children, i, TranslateTimeProfileNode(node->GetChild(i)));
  }

  return CreateTimeNode(node->GetFunctionName(), node->GetScriptResourceName(),
                        Nan::New<Integer>(node->GetScriptId()),
                        Nan::New<Integer>(node->GetLineNumber()),
                        Nan::New<Integer>(node->GetColumnNumber()),
                        Nan::New<Integer>(node->GetHitCount()), children);
}

Local<Value> TranslateTimeProfile(const CpuProfile* profile,
                                  bool includeLineInfo) {
  Local<Object> js_profile = Nan::New<Object>();
  Nan::Set(js_profile, Nan::New<String>("title").ToLocalChecked(),
           profile->GetTitle());

#if NODE_MODULE_VERSION > NODE_11_0_MODULE_VERSION
  if (includeLineInfo) {
    Nan::Set(js_profile, Nan::New<String>("topDownRoot").ToLocalChecked(),
             TranslateLineNumbersTimeProfileRoot(profile->GetTopDownRoot()));
  } else {
    Nan::Set(js_profile, Nan::New<String>("topDownRoot").ToLocalChecked(),
             TranslateTimeProfileNode(profile->GetTopDownRoot()));
  }
#else
  Nan::Set(js_profile, Nan::New<String>("topDownRoot").ToLocalChecked(),
           TranslateTimeProfileNode(profile->GetTopDownRoot()));
#endif
  Nan::Set(js_profile, Nan::New<String>("startTime").ToLocalChecked(),
           Nan::New<Number>(profile->GetStartTime()));
  Nan::Set(js_profile, Nan::New<String>("endTime").ToLocalChecked(),
           Nan::New<Number>(profile->GetEndTime()));
  return js_profile;
}

// Signature:
// startProfiling(runName: string, includeLineInfo: boolean)
NAN_METHOD(StartProfiling) {
  if (info.Length() != 2) {
    return Nan::ThrowTypeError("StartProfiling must have two arguments.");
  }
  if (!info[0]->IsString()) {
    return Nan::ThrowTypeError("First argument must be a string.");
  }
  if (!info[1]->IsBoolean()) {
    return Nan::ThrowTypeError("Second argument must be a boolean.");
  }

  Local<String> name =
      Nan::MaybeLocal<String>(info[0].As<String>()).ToLocalChecked();

  // Sample counts and timestamps are not used, so we do not need to record
  // samples.
  const bool recordSamples = false;

// Line level accurate line information is not available in Node 11 or earlier.
#if NODE_MODULE_VERSION > NODE_11_0_MODULE_VERSION
  bool includeLineInfo =
      Nan::MaybeLocal<Boolean>(info[1].As<Boolean>()).ToLocalChecked()->Value();
  if (includeLineInfo) {
    cpuProfiler->StartProfiling(name, CpuProfilingMode::kCallerLineNumbers,
                                recordSamples);
  } else {
    cpuProfiler->StartProfiling(name, recordSamples);
  }
#else
  cpuProfiler->StartProfiling(name, recordSamples);
#endif
}

// Signature:
// stopProfiling(runName: string, includeLineInfo: boolean): TimeProfile
NAN_METHOD(StopProfiling) {
  if (info.Length() != 2) {
    return Nan::ThrowTypeError("StopProfling must have two arguments.");
  }
  if (!info[0]->IsString()) {
    return Nan::ThrowTypeError("First argument must be a string.");
  }
  if (!info[1]->IsBoolean()) {
    return Nan::ThrowTypeError("Second argument must be a boolean.");
  }
  Local<String> name =
      Nan::MaybeLocal<String>(info[0].As<String>()).ToLocalChecked();
  bool includeLineInfo =
      Nan::MaybeLocal<Boolean>(info[1].As<Boolean>()).ToLocalChecked()->Value();

  CpuProfile* profile = cpuProfiler->StopProfiling(name);
  Local<Value> translated_profile =
      TranslateTimeProfile(profile, includeLineInfo);
  profile->Delete();
  info.GetReturnValue().Set(translated_profile);
}

// Signature:
// setSamplingInterval(intervalMicros: number)
NAN_METHOD(SetSamplingInterval) {
#if NODE_MODULE_VERSION > NODE_8_0_MODULE_VERSION
  int us = info[0].As<Integer>()->Value();
#else
  int us = info[0].As<Integer>()->IntegerValue();
#endif
  cpuProfiler->SetSamplingInterval(us);
}

NAN_MODULE_INIT(InitAll) {
  Local<Object> timeProfiler = Nan::New<Object>();
  Nan::Set(timeProfiler, Nan::New("startProfiling").ToLocalChecked(),
           Nan::GetFunction(Nan::New<FunctionTemplate>(StartProfiling))
               .ToLocalChecked());
  Nan::Set(timeProfiler, Nan::New("stopProfiling").ToLocalChecked(),
           Nan::GetFunction(Nan::New<FunctionTemplate>(StopProfiling))
               .ToLocalChecked());
  Nan::Set(timeProfiler, Nan::New("setSamplingInterval").ToLocalChecked(),
           Nan::GetFunction(Nan::New<FunctionTemplate>(SetSamplingInterval))
               .ToLocalChecked());
  Nan::Set(target, Nan::New<String>("timeProfiler").ToLocalChecked(),
           timeProfiler);

  Local<Object> heapProfiler = Nan::New<Object>();
  Nan::Set(
      heapProfiler, Nan::New("startSamplingHeapProfiler").ToLocalChecked(),
      Nan::GetFunction(Nan::New<FunctionTemplate>(StartSamplingHeapProfiler))
          .ToLocalChecked());
  Nan::Set(
      heapProfiler, Nan::New("stopSamplingHeapProfiler").ToLocalChecked(),
      Nan::GetFunction(Nan::New<FunctionTemplate>(StopSamplingHeapProfiler))
          .ToLocalChecked());
  Nan::Set(heapProfiler, Nan::New("getAllocationProfile").ToLocalChecked(),
           Nan::GetFunction(Nan::New<FunctionTemplate>(GetAllocationProfile))
               .ToLocalChecked());
  Nan::Set(target, Nan::New<String>("heapProfiler").ToLocalChecked(),
           heapProfiler);
}

NODE_MODULE(google_cloud_profiler, InitAll);
<commit_msg>fix!: re-create CPU profiler each time a CPU profile is collected to work around V8 CPU profiler memory leak. (#142)<commit_after>/**
 * Copyright 2018 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <memory>

#include "nan.h"
#include "v8-profiler.h"

using namespace v8;

// Sampling Heap Profiler

Local<Value> TranslateAllocationProfile(AllocationProfile::Node* node) {
  Local<Object> js_node = Nan::New<Object>();

  Nan::Set(js_node, Nan::New<String>("name").ToLocalChecked(), node->name);
  Nan::Set(js_node, Nan::New<String>("scriptName").ToLocalChecked(),
           node->script_name);
  Nan::Set(js_node, Nan::New<String>("scriptId").ToLocalChecked(),
           Nan::New<Integer>(node->script_id));
  Nan::Set(js_node, Nan::New<String>("lineNumber").ToLocalChecked(),
           Nan::New<Integer>(node->line_number));
  Nan::Set(js_node, Nan::New<String>("columnNumber").ToLocalChecked(),
           Nan::New<Integer>(node->column_number));

  Local<Array> children = Nan::New<Array>(node->children.size());
  for (size_t i = 0; i < node->children.size(); i++) {
    Nan::Set(children, i, TranslateAllocationProfile(node->children[i]));
  }
  Nan::Set(js_node, Nan::New<String>("children").ToLocalChecked(), children);
  Local<Array> allocations = Nan::New<Array>(node->allocations.size());
  for (size_t i = 0; i < node->allocations.size(); i++) {
    AllocationProfile::Allocation alloc = node->allocations[i];
    Local<Object> js_alloc = Nan::New<Object>();
    Nan::Set(js_alloc, Nan::New<String>("sizeBytes").ToLocalChecked(),
             Nan::New<Number>(alloc.size));
    Nan::Set(js_alloc, Nan::New<String>("count").ToLocalChecked(),
             Nan::New<Number>(alloc.count));
    Nan::Set(allocations, i, js_alloc);
  }
  Nan::Set(js_node, Nan::New<String>("allocations").ToLocalChecked(),
           allocations);
  return js_node;
}

NAN_METHOD(StartSamplingHeapProfiler) {
  if (info.Length() == 2) {
    if (!info[0]->IsUint32()) {
      return Nan::ThrowTypeError("First argument type must be uint32.");
    }
    if (!info[1]->IsNumber()) {
      return Nan::ThrowTypeError("First argument type must be Integer.");
    }

#if NODE_MODULE_VERSION > NODE_8_0_MODULE_VERSION
    uint64_t sample_interval = info[0].As<Integer>()->Value();
    int stack_depth = info[1].As<Integer>()->Value();
#else
    uint64_t sample_interval = info[0].As<Integer>()->Uint32Value();
    int stack_depth = info[1].As<Integer>()->IntegerValue();
#endif

    info.GetIsolate()->GetHeapProfiler()->StartSamplingHeapProfiler(
        sample_interval, stack_depth);
  } else {
    info.GetIsolate()->GetHeapProfiler()->StartSamplingHeapProfiler();
  }
}

// Signature:
// stopSamplingHeapProfiler()
NAN_METHOD(StopSamplingHeapProfiler) {
  info.GetIsolate()->GetHeapProfiler()->StopSamplingHeapProfiler();
}

// Signature:
// getAllocationProfile(): AllocationProfileNode
NAN_METHOD(GetAllocationProfile) {
  std::unique_ptr<v8::AllocationProfile> profile(
      info.GetIsolate()->GetHeapProfiler()->GetAllocationProfile());
  AllocationProfile::Node* root = profile->GetRootNode();
  info.GetReturnValue().Set(TranslateAllocationProfile(root));
}

// Time profiler
#if NODE_MODULE_VERSION >= NODE_12_0_MODULE_VERSION
// For Node 12 and Node 14, a new CPU profiler object will be created each
// time profiling is started to work around
// https://bugs.chromium.org/p/v8/issues/detail?id=11051.
CpuProfiler* cpuProfiler;
// Default sampling interval is 1000us.
int samplingIntervalUS = 1000;
#elif NODE_MODULE_VERSION > NODE_8_0_MODULE_VERSION
// This profiler exists for the lifetime of the program. Not calling
// CpuProfiler::Dispose() is intentional.
CpuProfiler* cpuProfiler = CpuProfiler::New(v8::Isolate::GetCurrent());
#else
CpuProfiler* cpuProfiler = v8::Isolate::GetCurrent()->GetCpuProfiler();
#endif

Local<Object> CreateTimeNode(Local<String> name, Local<String> scriptName,
                             Local<Integer> scriptId, Local<Integer> lineNumber,
                             Local<Integer> columnNumber,
                             Local<Integer> hitCount, Local<Array> children) {
  Local<Object> js_node = Nan::New<Object>();
  Nan::Set(js_node, Nan::New<String>("name").ToLocalChecked(), name);
  Nan::Set(js_node, Nan::New<String>("scriptName").ToLocalChecked(),
           scriptName);
  Nan::Set(js_node, Nan::New<String>("scriptId").ToLocalChecked(), scriptId);
  Nan::Set(js_node, Nan::New<String>("lineNumber").ToLocalChecked(),
           lineNumber);
  Nan::Set(js_node, Nan::New<String>("columnNumber").ToLocalChecked(),
           columnNumber);
  Nan::Set(js_node, Nan::New<String>("hitCount").ToLocalChecked(), hitCount);
  Nan::Set(js_node, Nan::New<String>("children").ToLocalChecked(), children);

  return js_node;
}

#if NODE_MODULE_VERSION > NODE_11_0_MODULE_VERSION
Local<Object> TranslateLineNumbersTimeProfileNode(const CpuProfileNode* parent,
                                                  const CpuProfileNode* node);

Local<Array> GetLineNumberTimeProfileChildren(const CpuProfileNode* parent,
                                              const CpuProfileNode* node) {
  unsigned int index = 0;
  Local<Array> children;
  int32_t count = node->GetChildrenCount();

  unsigned int hitLineCount = node->GetHitLineCount();
  unsigned int hitCount = node->GetHitCount();
  if (hitLineCount > 0) {
    std::vector<CpuProfileNode::LineTick> entries(hitLineCount);
    node->GetLineTicks(&entries[0], hitLineCount);
    children = Nan::New<Array>(count + hitLineCount);
    for (const CpuProfileNode::LineTick entry : entries) {
      Nan::Set(children, index++,
               CreateTimeNode(
                   node->GetFunctionName(), node->GetScriptResourceName(),
                   Nan::New<Integer>(node->GetScriptId()),
                   Nan::New<Integer>(entry.line), Nan::New<Integer>(0),
                   Nan::New<Integer>(entry.hit_count), Nan::New<Array>(0)));
    }
  } else if (hitCount > 0) {
    // Handle nodes for pseudo-functions like "process" and "garbage collection"
    // which do not have hit line counts.
    children = Nan::New<Array>(count + 1);
    Nan::Set(
        children, index++,
        CreateTimeNode(node->GetFunctionName(), node->GetScriptResourceName(),
                       Nan::New<Integer>(node->GetScriptId()),
                       Nan::New<Integer>(node->GetLineNumber()),
                       Nan::New<Integer>(node->GetColumnNumber()),
                       Nan::New<Integer>(hitCount), Nan::New<Array>(0)));
  } else {
    children = Nan::New<Array>(count);
  }

  for (int32_t i = 0; i < count; i++) {
    Nan::Set(children, index++,
             TranslateLineNumbersTimeProfileNode(node, node->GetChild(i)));
  };

  return children;
}

Local<Object> TranslateLineNumbersTimeProfileNode(const CpuProfileNode* parent,
                                                  const CpuProfileNode* node) {
  return CreateTimeNode(
      parent->GetFunctionName(), parent->GetScriptResourceName(),
      Nan::New<Integer>(parent->GetScriptId()),
      Nan::New<Integer>(node->GetLineNumber()),
      Nan::New<Integer>(node->GetColumnNumber()), Nan::New<Integer>(0),
      GetLineNumberTimeProfileChildren(parent, node));
}

// In profiles with line level accurate line numbers, a node's line number
// and column number refer to the line/column from which the function was
// called.
Local<Value> TranslateLineNumbersTimeProfileRoot(const CpuProfileNode* node) {
  int32_t count = node->GetChildrenCount();
  std::vector<Local<Array>> childrenArrs(count);
  int32_t childCount = 0;
  for (int32_t i = 0; i < count; i++) {
    Local<Array> c = GetLineNumberTimeProfileChildren(node, node->GetChild(i));
    childCount = childCount + c->Length();
    childrenArrs[i] = c;
  }

  Local<Array> children = Nan::New<Array>(childCount);
  int32_t idx = 0;
  for (int32_t i = 0; i < count; i++) {
    Local<Array> arr = childrenArrs[i];
    for (uint32_t j = 0; j < arr->Length(); j++) {
      Nan::Set(children, idx, Nan::Get(arr, j).ToLocalChecked());
      idx++;
    }
  }

  return CreateTimeNode(node->GetFunctionName(), node->GetScriptResourceName(),
                        Nan::New<Integer>(node->GetScriptId()),
                        Nan::New<Integer>(node->GetLineNumber()),
                        Nan::New<Integer>(node->GetColumnNumber()),
                        Nan::New<Integer>(0), children);
}
#endif

Local<Value> TranslateTimeProfileNode(const CpuProfileNode* node) {
  int32_t count = node->GetChildrenCount();
  Local<Array> children = Nan::New<Array>(count);
  for (int32_t i = 0; i < count; i++) {
    Nan::Set(children, i, TranslateTimeProfileNode(node->GetChild(i)));
  }

  return CreateTimeNode(node->GetFunctionName(), node->GetScriptResourceName(),
                        Nan::New<Integer>(node->GetScriptId()),
                        Nan::New<Integer>(node->GetLineNumber()),
                        Nan::New<Integer>(node->GetColumnNumber()),
                        Nan::New<Integer>(node->GetHitCount()), children);
}

Local<Value> TranslateTimeProfile(const CpuProfile* profile,
                                  bool includeLineInfo) {
  Local<Object> js_profile = Nan::New<Object>();
  Nan::Set(js_profile, Nan::New<String>("title").ToLocalChecked(),
           profile->GetTitle());

#if NODE_MODULE_VERSION > NODE_11_0_MODULE_VERSION
  if (includeLineInfo) {
    Nan::Set(js_profile, Nan::New<String>("topDownRoot").ToLocalChecked(),
             TranslateLineNumbersTimeProfileRoot(profile->GetTopDownRoot()));
  } else {
    Nan::Set(js_profile, Nan::New<String>("topDownRoot").ToLocalChecked(),
             TranslateTimeProfileNode(profile->GetTopDownRoot()));
  }
#else
  Nan::Set(js_profile, Nan::New<String>("topDownRoot").ToLocalChecked(),
           TranslateTimeProfileNode(profile->GetTopDownRoot()));
#endif
  Nan::Set(js_profile, Nan::New<String>("startTime").ToLocalChecked(),
           Nan::New<Number>(profile->GetStartTime()));
  Nan::Set(js_profile, Nan::New<String>("endTime").ToLocalChecked(),
           Nan::New<Number>(profile->GetEndTime()));
  return js_profile;
}

// Signature:
// startProfiling(runName: string, includeLineInfo: boolean)
NAN_METHOD(StartProfiling) {
  if (info.Length() != 2) {
    return Nan::ThrowTypeError("StartProfiling must have two arguments.");
  }
  if (!info[0]->IsString()) {
    return Nan::ThrowTypeError("First argument must be a string.");
  }
  if (!info[1]->IsBoolean()) {
    return Nan::ThrowTypeError("Second argument must be a boolean.");
  }

#if NODE_MODULE_VERSION >= NODE_12_0_MODULE_VERSION
  // Since the CPU profiler is created and destroyed each time a CPU
  // profile is collected, there cannot be multiple CPU profiling requests
  // inflight in parallel.
  if (cpuProfiler) {
    return Nan::ThrowError("CPU profiler is already started.");
  }
  cpuProfiler = CpuProfiler::New(v8::Isolate::GetCurrent());
  cpuProfiler->SetSamplingInterval(samplingIntervalUS);
#endif

  Local<String> name =
      Nan::MaybeLocal<String>(info[0].As<String>()).ToLocalChecked();

  // Sample counts and timestamps are not used, so we do not need to record
  // samples.
  const bool recordSamples = false;

// Line level accurate line information is not available in Node 11 or earlier.
#if NODE_MODULE_VERSION > NODE_11_0_MODULE_VERSION
  bool includeLineInfo =
      Nan::MaybeLocal<Boolean>(info[1].As<Boolean>()).ToLocalChecked()->Value();
  if (includeLineInfo) {
    cpuProfiler->StartProfiling(name, CpuProfilingMode::kCallerLineNumbers,
                                recordSamples);
  } else {
    cpuProfiler->StartProfiling(name, recordSamples);
  }
#else
  cpuProfiler->StartProfiling(name, recordSamples);
#endif
}

// Signature:
// stopProfiling(runName: string, includeLineInfo: boolean): TimeProfile
NAN_METHOD(StopProfiling) {
#if NODE_MODULE_VERSION >= NODE_12_0_MODULE_VERSION
  if (!cpuProfiler) {
    return Nan::ThrowError("StopProfiling called without an active CPU profiler.");
  }
#endif
  if (info.Length() != 2) {
    return Nan::ThrowTypeError("StopProfling must have two arguments.");
  }
  if (!info[0]->IsString()) {
    return Nan::ThrowTypeError("First argument must be a string.");
  }
  if (!info[1]->IsBoolean()) {
    return Nan::ThrowTypeError("Second argument must be a boolean.");
  }
  Local<String> name =
      Nan::MaybeLocal<String>(info[0].As<String>()).ToLocalChecked();
  bool includeLineInfo =
      Nan::MaybeLocal<Boolean>(info[1].As<Boolean>()).ToLocalChecked()->Value();

  CpuProfile* profile = cpuProfiler->StopProfiling(name);
  Local<Value> translated_profile =
      TranslateTimeProfile(profile, includeLineInfo);
  profile->Delete();
#if NODE_MODULE_VERSION >= NODE_12_0_MODULE_VERSION
  // Dispose of CPU profiler to work around memory leak.
  cpuProfiler->Dispose();
  cpuProfiler = NULL;
#endif
  info.GetReturnValue().Set(translated_profile);
}

// Signature:
// setSamplingInterval(intervalMicros: number)
NAN_METHOD(SetSamplingInterval) {
#if NODE_MODULE_VERSION > NODE_8_0_MODULE_VERSION
  int us = info[0].As<Integer>()->Value();
#else
  int us = info[0].As<Integer>()->IntegerValue();
#endif
#if NODE_MODULE_VERSION >= NODE_12_0_MODULE_VERSION
  samplingIntervalUS = us;
#else
  cpuProfiler->SetSamplingInterval(us);
#endif
}

NAN_MODULE_INIT(InitAll) {
  Local<Object> timeProfiler = Nan::New<Object>();
  Nan::Set(timeProfiler, Nan::New("startProfiling").ToLocalChecked(),
           Nan::GetFunction(Nan::New<FunctionTemplate>(StartProfiling))
               .ToLocalChecked());
  Nan::Set(timeProfiler, Nan::New("stopProfiling").ToLocalChecked(),
           Nan::GetFunction(Nan::New<FunctionTemplate>(StopProfiling))
               .ToLocalChecked());
  Nan::Set(timeProfiler, Nan::New("setSamplingInterval").ToLocalChecked(),
           Nan::GetFunction(Nan::New<FunctionTemplate>(SetSamplingInterval))
               .ToLocalChecked());
  Nan::Set(target, Nan::New<String>("timeProfiler").ToLocalChecked(),
           timeProfiler);

  Local<Object> heapProfiler = Nan::New<Object>();
  Nan::Set(
      heapProfiler, Nan::New("startSamplingHeapProfiler").ToLocalChecked(),
      Nan::GetFunction(Nan::New<FunctionTemplate>(StartSamplingHeapProfiler))
          .ToLocalChecked());
  Nan::Set(
      heapProfiler, Nan::New("stopSamplingHeapProfiler").ToLocalChecked(),
      Nan::GetFunction(Nan::New<FunctionTemplate>(StopSamplingHeapProfiler))
          .ToLocalChecked());
  Nan::Set(heapProfiler, Nan::New("getAllocationProfile").ToLocalChecked(),
           Nan::GetFunction(Nan::New<FunctionTemplate>(GetAllocationProfile))
               .ToLocalChecked());
  Nan::Set(target, Nan::New<String>("heapProfiler").ToLocalChecked(),
           heapProfiler);
}

NODE_MODULE(google_cloud_profiler, InitAll);
<|endoftext|>


<commit_before>/*
	NOTE: you must: #include <SoftwareSerial.h>
	BEFORE including the class header file

	For Parallax LCD's (27976, 27977, 27979)
	For more information contact http://www.parallax.com

	Updated to Arduino 1.0 by Chad Johnston (cjohnston@megatome.com)
	July 11, 2012

	Original Work done by:
    Douglas Farrell
    cyberblob59@yahoo.com

    Used/Modified with permission from allen joslin
    --Based on SparkFunSerLCD.h from--
	allen joslin
	payson productions
	allen@joslin.net
*/
#include <Arduino.h>

#include <SoftwareSerial.h>
#include "ParallaxLCD.h"

#define PINOUT      0
#define POSBASE     1
#define BOUNCE      2
#define NUMROWS     3
#define NUMCOLS     4

ParallaxLCD::ParallaxLCD ( int pin, int numRows, int numCols, int posBase) : SoftwareSerial(pin,pin) {
	_bv[PINOUT]=pin;
	_bv[POSBASE]=posBase;
	_bv[BOUNCE]=10;
	_bv[NUMROWS]=numRows;
	_bv[NUMCOLS]=numCols;
	_ro[0]=0;
	_ro[1]=64;
	_ro[2]=numCols;
	_ro[3]=_ro[1]+numCols;
}

void ParallaxLCD::setup(boolean startEmpty ) {
	pinMode(_bv[PINOUT], OUTPUT);
	delay(_bv[BOUNCE]);
	begin(19200);
	delay(_bv[BOUNCE]);
	if (startEmpty) {
		empty();
	}
	cursorOff();
}

void ParallaxLCD::on () {
	write(24); delay(_bv[BOUNCE]);
}

void ParallaxLCD::off () {
	write(21); delay(_bv[BOUNCE]);
}

void ParallaxLCD::scrollLeft () {
	print(8); delay(_bv[BOUNCE]);
}

void ParallaxLCD::scrollRight () {
	write(9); delay(_bv[BOUNCE]);
}

void ParallaxLCD::empty () {
	write(12); delay(_bv[BOUNCE]*10);
}

void ParallaxLCD::cursorUnderline () {
	write(24); delay(_bv[BOUNCE]);
}

void ParallaxLCD::cursorBlock () {
	write(23); delay(_bv[BOUNCE]);
}

void ParallaxLCD::cursorOff () {
	write(22); delay(_bv[BOUNCE]);
}

void ParallaxLCD::cursorOnChrBlink () {
	write(25); delay(_bv[BOUNCE]);
}

void ParallaxLCD::cr () {
	write(13); delay(_bv[BOUNCE]);
}

void ParallaxLCD::lf () {
	write(10); delay(_bv[BOUNCE]);
}

void ParallaxLCD::backLightOn () {
	write(17); delay(_bv[BOUNCE]);
}

void ParallaxLCD::backLightOff () {
	write(18); delay(_bv[BOUNCE]);
}

void ParallaxLCD::pos ( int row, int col )
{
	if (row == 0)
		{
			write(128 + _ro[(row - _bv[POSBASE])] + (col - _bv[POSBASE])); delay(_bv[BOUNCE]);
		}
	else if (row == 1)
		{
			write(148 + _ro[(row - _bv[POSBASE])] + (col - _bv[POSBASE])); delay(_bv[BOUNCE]);
		}
	else if (row == 2)
		{
			write(168 + _ro[(row - _bv[POSBASE])] + (col - _bv[POSBASE])); delay(_bv[BOUNCE]);
		}
	else if (row == 3)
		{
			write(188 + _ro[(row - _bv[POSBASE])] + (col - _bv[POSBASE])); delay(_bv[BOUNCE]);
		}
}

// shortcuts

void ParallaxLCD::at ( int row, int col, char v )				{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, const char v[] )	{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, String v )             { pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, uint8_t v )			{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, int v )				{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, unsigned int v )	{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, long v )				{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, unsigned long v )	{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, long v, int t )		{ pos(row,col); print(v,t); }<commit_msg>Update ParallaxLCD.cpp<commit_after>/*
	NOTE: you must: #include <SoftwareSerial.h>
	BEFORE including the class header file

	For Parallax LCD's (27976, 27977, 27979)
	For more information contact http://www.parallax.com

	Updated to Arduino 1.0 by Chad Johnston (cjohnston@megatome.com)
	July 11, 2012

	Original Work done by:
    Douglas Farrell
    cyberblob59@yahoo.com

    Used/Modified with permission from allen joslin
    --Based on SparkFunSerLCD.h from--
	allen joslin
	payson productions
	allen@joslin.net

	Updated 8/1/2012 Martin C. Stoufer mcstoufer@speakeasy.net
        # Added interface functions to play music and define/print custom characters
*/
#include <Arduino.h>

#include <SoftwareSerial.h>
#include "ParallaxLCD.h"

#define PINOUT      0
#define POSBASE     1
#define BOUNCE      2
#define NUMROWS     3
#define NUMCOLS     4

ParallaxLCD::ParallaxLCD ( int pin, int numRows, int numCols, int posBase) : SoftwareSerial(pin,pin) {
	_bv[PINOUT]=pin;
	_bv[POSBASE]=posBase;
	_bv[BOUNCE]=10;
	_bv[NUMROWS]=numRows;
	_bv[NUMCOLS]=numCols;
	_ro[0]=0;
	_ro[1]=64;
	_ro[2]=numCols;
	_ro[3]=_ro[1]+numCols;
}

void ParallaxLCD::setup(boolean startEmpty ) {
	pinMode(_bv[PINOUT], OUTPUT);
	delay(_bv[BOUNCE]);
	begin(19200);
	delay(_bv[BOUNCE]);
	if (startEmpty) {
		empty();
	}
	cursorOff();
}

void ParallaxLCD::on () {
	write(24); delay(_bv[BOUNCE]);
}

void ParallaxLCD::off () {
	write(21); delay(_bv[BOUNCE]);
}

void ParallaxLCD::scrollLeft () {
	print(8); delay(_bv[BOUNCE]);
}

void ParallaxLCD::scrollRight () {
	write(9); delay(_bv[BOUNCE]);
}

void ParallaxLCD::empty () {
	write(12); delay(_bv[BOUNCE]*10);
}

void ParallaxLCD::cursorUnderline () {
	write(24); delay(_bv[BOUNCE]);
}

void ParallaxLCD::cursorBlock () {
	write(23); delay(_bv[BOUNCE]);
}

void ParallaxLCD::cursorOff () {
	write(22); delay(_bv[BOUNCE]);
}

void ParallaxLCD::cursorOnChrBlink () {
	write(25); delay(_bv[BOUNCE]);
}

void ParallaxLCD::cr () {
	write(13); delay(_bv[BOUNCE]);
}

void ParallaxLCD::lf () {
	write(10); delay(_bv[BOUNCE]);
}

void ParallaxLCD::backLightOn () {
	write(17); delay(_bv[BOUNCE]);
}

void ParallaxLCD::backLightOff () {
	write(18); delay(_bv[BOUNCE]);
}

/**
 * Duration: 208 - 214 (1/64th note - 1 whole note[2 secs])
 * Scale   : 215 - 219 (3rd - 7th scale)
 * Note    : 220 - 232 (A, A#, B, etc..., F#, F, G#)
 */
void ParallaxLCD::playTone(int duration, int scale, int note) {

	duration = constrain(duration, 208, 214);
	scale = constrain(scale, 215, 219);
	note = constrain(note, 220, 232);

    write(scale);
    write(note);
    write(duration);
    delay(_bv[BOUNCE]);
}

/**
 * Set a custom character at the 'charIndex' index (0-7) with an
 *  array of bytes. Nominally, this will contain 8 bytes in it.
 */
void ParallaxLCD::setCustomCharacter(int charIndex, byte bytes[]) {

   if(sizeof(bytes)/sizeof(bytes[0]) > 8) {
      return;
   }

   int index = constrain(charIndex, 0, 7);
   index = map(index, 0, 7, 248, 255);

   unsigned char *byte = bytes;

   write(index);
   for (int i=0; i < 8; i++) {
     write(byte[i]);
   }
   delay(_bv[BOUNCE]);
}

/**
 * Print whatever is stored in the custom character buffer.
 * If nothing is stored there, usually, nothing will print out.
 */
void ParallaxLCD::printCustomCharacter(int charIndex) {
   int index = constrain(charIndex, 0, 7);
   write(index);
   delay(_bv[BOUNCE]);
}

void ParallaxLCD::pos ( int row, int col )
{
	if (row == 0)
		{
			write(128 + _ro[(row - _bv[POSBASE])] + (col - _bv[POSBASE])); delay(_bv[BOUNCE]);
		}
	else if (row == 1)
		{
			write(148 + _ro[(row - _bv[POSBASE])] + (col - _bv[POSBASE])); delay(_bv[BOUNCE]);
		}
	else if (row == 2)
		{
			write(168 + _ro[(row - _bv[POSBASE])] + (col - _bv[POSBASE])); delay(_bv[BOUNCE]);
		}
	else if (row == 3)
		{
			write(188 + _ro[(row - _bv[POSBASE])] + (col - _bv[POSBASE])); delay(_bv[BOUNCE]);
		}
}

// shortcuts

void ParallaxLCD::at ( int row, int col, char v )				{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, const char v[] )	{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, String v )             { pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, uint8_t v )			{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, int v )				{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, unsigned int v )	{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, long v )				{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, unsigned long v )	{ pos(row,col); print(v); }
void ParallaxLCD::at ( int row, int col, long v, int t )		{ pos(row,col); print(v,t); }<|endoftext|>


<commit_before>/****************************************************************/
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*          All contents are licensed under LGPL V2.1           */
/*             See LICENSE for full restrictions                */
/****************************************************************/

#include "INSBase.h"
#include "Assembly.h"

template <>
InputParameters
validParams<INSBase>()
{
  InputParameters params = validParams<Kernel>();

  params.addClassDescription("This class computes various strong and weak components of the "
                             "incompressible navier stokes equations which can then be assembled "
                             "together in child classes.");
  // Coupled variables
  params.addRequiredCoupledVar("u", "x-velocity");
  params.addCoupledVar("v", 0, "y-velocity"); // only required in 2D and 3D
  params.addCoupledVar("w", 0, "z-velocity"); // only required in 3D
  params.addRequiredCoupledVar("p", "pressure");

  params.addParam<RealVectorValue>(
      "gravity", RealVectorValue(0, 0, 0), "Direction of the gravity vector");

  params.addParam<MaterialPropertyName>("mu_name", "mu", "The name of the dynamic viscosity");
  params.addParam<MaterialPropertyName>("rho_name", "rho", "The name of the density");

  params.addParam<bool>("stabilize", false, "Whether to use GLS (encompasses SUPG) stabilization.");
  params.addParam<Real>("alpha", 1., "Multiplicative factor on the stabilization parameter tau.");
  params.addParam<bool>(
      "laplace", true, "Whether the viscous term of the momentum equations is in laplace form.");
  params.addParam<bool>("convective_term", true, "Whether to include the convective term.");
  params.addParam<bool>("transient_term",
                        false,
                        "Whether there should be a transient term in the momentum residuals.");

  return params;
}

INSBase::INSBase(const InputParameters & parameters)
  : Kernel(parameters),
    _second_phi(_assembly.secondPhi()),

    // Coupled variables
    _u_vel(coupledValue("u")),
    _v_vel(coupledValue("v")),
    _w_vel(coupledValue("w")),
    _p(coupledValue("p")),

    // Gradients
    _grad_u_vel(coupledGradient("u")),
    _grad_v_vel(coupledGradient("v")),
    _grad_w_vel(coupledGradient("w")),
    _grad_p(coupledGradient("p")),

    // second derivative tensors
    _second_u_vel(coupledSecond("u")),
    _second_v_vel(coupledSecond("v")),
    _second_w_vel(coupledSecond("w")),

    // time derivatives
    _u_vel_dot(coupledDot("u")),
    _v_vel_dot(coupledDot("v")),
    _w_vel_dot(coupledDot("w")),

    // derivatives of time derivatives
    _d_u_vel_dot_du(coupledDotDu("u")),
    _d_v_vel_dot_dv(coupledDotDu("v")),
    _d_w_vel_dot_dw(coupledDotDu("w")),

    // Variable numberings
    _u_vel_var_number(coupled("u")),
    _v_vel_var_number(coupled("v")),
    _w_vel_var_number(coupled("w")),
    _p_var_number(coupled("p")),

    _gravity(getParam<RealVectorValue>("gravity")),

    // Material properties
    _mu(getMaterialProperty<Real>("mu_name")),
    _rho(getMaterialProperty<Real>("rho_name")),

    _stabilize(getParam<bool>("stabilize")),
    _alpha(getParam<Real>("alpha")),
    _laplace(getParam<bool>("laplace")),
    _convective_term(getParam<bool>("convective_term")),
    _transient_term(getParam<bool>("transient_term"))
{
}

RealVectorValue
INSBase::convectiveTerm()
{
  RealVectorValue convective_term(0, 0, 0);
  RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]);
  convective_term(0) = _rho[_qp] * U * _grad_u_vel[_qp];
  convective_term(1) = _rho[_qp] * U * _grad_v_vel[_qp];
  convective_term(2) = _rho[_qp] * U * _grad_w_vel[_qp];

  return convective_term;
}

RealVectorValue
INSBase::dConvecDUComp(unsigned comp)
{
  RealVectorValue convective_term(0, 0, 0);
  RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]);
  RealVectorValue d_U_d_comp(0, 0, 0);
  d_U_d_comp(comp) = _phi[_j][_qp];
  convective_term(0) = _rho[_qp] * d_U_d_comp * _grad_u_vel[_qp];
  convective_term(1) = _rho[_qp] * d_U_d_comp * _grad_v_vel[_qp];
  convective_term(2) = _rho[_qp] * d_U_d_comp * _grad_w_vel[_qp];

  convective_term(comp) += _rho[_qp] * U * _grad_phi[_j][_qp];

  return convective_term;
}

RealVectorValue
INSBase::strongViscousTermLaplace()
{
  RealVectorValue viscous_term(0, 0, 0);
  Real lap_u = _second_u_vel[_qp](0, 0) + _second_u_vel[_qp](1, 1) + _second_u_vel[_qp](2, 2);
  Real lap_v = _second_v_vel[_qp](0, 0) + _second_v_vel[_qp](1, 1) + _second_v_vel[_qp](2, 2);
  Real lap_w = _second_w_vel[_qp](0, 0) + _second_w_vel[_qp](1, 1) + _second_w_vel[_qp](2, 2);

  viscous_term(0) = -_mu[_qp] * lap_u;
  viscous_term(1) = -_mu[_qp] * lap_v;
  viscous_term(2) = -_mu[_qp] * lap_w;

  return viscous_term;
}

RealVectorValue
INSBase::strongViscousTermTraction()
{
  RealVectorValue viscous_term = strongViscousTermLaplace();

  viscous_term(0) +=
      -_mu[_qp] * (_second_u_vel[_qp](0, 0) + _second_v_vel[_qp](0, 1) + _second_w_vel[_qp](0, 2));
  viscous_term(1) +=
      -_mu[_qp] * (_second_u_vel[_qp](1, 0) + _second_v_vel[_qp](1, 1) + _second_w_vel[_qp](1, 2));
  viscous_term(2) +=
      -_mu[_qp] * (_second_u_vel[_qp](2, 0) + _second_v_vel[_qp](2, 1) + _second_w_vel[_qp](2, 2));

  return viscous_term;
}

RealVectorValue
INSBase::dStrongViscDUCompLaplace(unsigned comp)
{
  RealVectorValue viscous_term(0, 0, 0);
  viscous_term(comp) = -_mu[_qp] * (_second_phi[_j][_qp](0, 0) + _second_phi[_j][_qp](1, 1) +
                                    _second_phi[_j][_qp](2, 2));

  return viscous_term;
}

// Fix me
RealVectorValue
INSBase::dStrongViscDUCompTraction(unsigned comp)
{
  RealVectorValue viscous_term(0, 0, 0);
  viscous_term(comp) = -_mu[_qp] * (_second_phi[_j][_qp](0, 0) + _second_phi[_j][_qp](1, 1) +
                                    _second_phi[_j][_qp](2, 2));
  for (unsigned i = 0; i < 3; i++)
    viscous_term(i) += -_mu[_qp] * _second_phi[_j][_qp](i, comp);

  return viscous_term;
}

RealVectorValue
INSBase::weakViscousTermLaplace(unsigned comp)
{
  switch (comp)
  {
    case 0:
      return _mu[_qp] * _grad_u_vel[_qp];

    case 1:
      return _mu[_qp] * _grad_v_vel[_qp];

    case 2:
      return _mu[_qp] * _grad_w_vel[_qp];

    default:
      return _zero[_qp];
  }
}

RealVectorValue
INSBase::weakViscousTermTraction(unsigned comp)
{
  switch (comp)
  {
    case 0:
    {
      RealVectorValue transpose(_grad_u_vel[_qp](0), _grad_v_vel[_qp](0), _grad_w_vel[_qp](0));
      return _mu[_qp] * _grad_u_vel[_qp] + _mu[_qp] * transpose;
    }

    case 1:
    {
      RealVectorValue transpose(_grad_u_vel[_qp](1), _grad_v_vel[_qp](1), _grad_w_vel[_qp](1));
      return _mu[_qp] * _grad_v_vel[_qp] + _mu[_qp] * transpose;
    }

    case 2:
    {
      RealVectorValue transpose(_grad_u_vel[_qp](2), _grad_v_vel[_qp](2), _grad_w_vel[_qp](2));
      return _mu[_qp] * _grad_w_vel[_qp] + _mu[_qp] * transpose;
    }

    default:
      return _zero[_qp];
  }
}

RealVectorValue
INSBase::dWeakViscDUCompLaplace()
{
  return _mu[_qp] * _grad_phi[_j][_qp];
}

// Fix me
RealVectorValue
INSBase::dWeakViscDUCompTraction()
{
  return _mu[_qp] * _grad_phi[_j][_qp];
}

RealVectorValue
INSBase::strongPressureTerm()
{
  return _grad_p[_qp];
}

Real
INSBase::weakPressureTerm()
{
  return -_p[_qp];
}

RealVectorValue
INSBase::dStrongPressureDPressure()
{
  return _grad_phi[_j][_qp];
}

Real
INSBase::dWeakPressureDPressure()
{
  return -_phi[_j][_qp];
}

RealVectorValue
INSBase::bodyForcesTerm()
{
  return gravity();
}

RealVectorValue
INSBase::gravity()
{
  return -_rho[_qp] * _gravity;
}

RealVectorValue
INSBase::timeDerivativeTerm()
{
  RealVectorValue time_term(0, 0, 0);
  time_term(0) = _rho[_qp] * _u_vel_dot[_qp];
  time_term(1) = _rho[_qp] * _v_vel_dot[_qp];
  time_term(2) = _rho[_qp] * _w_vel_dot[_qp];

  return time_term;
}

RealVectorValue
INSBase::dTimeDerivativeDUComp(unsigned comp)
{
  Real base = _rho[_qp] * _phi[_j][_qp];
  switch (comp)
  {
    case 0:
      return RealVectorValue(base * _d_u_vel_dot_du[_qp], 0, 0);

    case 1:
      return RealVectorValue(0, base * _d_v_vel_dot_dv[_qp], 0);

    case 2:
      return RealVectorValue(0, 0, base * _d_w_vel_dot_dw[_qp]);

    default:
      mooseError("comp must be 0, 1, or 2");
  }
}

Real
INSBase::tau()
{
  Real nu = _mu[_qp] / _rho[_qp];
  RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]);
  Real h = _current_elem->hmax();
  return _alpha / std::sqrt((2. * U.norm() / h) * (2. * U.norm() / h) +
                            9. * (4. * nu / (h * h)) * (4. * nu / (h * h)));
}

Real
INSBase::dTauDUComp(unsigned comp)
{
  Real nu = _mu[_qp] / _rho[_qp];
  RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]);
  Real h = _current_elem->hmax();
  return -_alpha / 2. * std::pow((2. * U.norm() / h) * (2. * U.norm() / h) +
                                     9. * (4. * nu / (h * h)) * (4. * nu / (h * h)),
                                 -1.5) *
         2. * (2. * U.norm() / h) * 2. / h * U(comp) * _phi[_j][_qp] /
         (U.norm() + std::numeric_limits<double>::epsilon());
}
<commit_msg>Simplify functions in INSBase (#9687)<commit_after>/****************************************************************/
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*          All contents are licensed under LGPL V2.1           */
/*             See LICENSE for full restrictions                */
/****************************************************************/

#include "INSBase.h"
#include "Assembly.h"

template <>
InputParameters
validParams<INSBase>()
{
  InputParameters params = validParams<Kernel>();

  params.addClassDescription("This class computes various strong and weak components of the "
                             "incompressible navier stokes equations which can then be assembled "
                             "together in child classes.");
  // Coupled variables
  params.addRequiredCoupledVar("u", "x-velocity");
  params.addCoupledVar("v", 0, "y-velocity"); // only required in 2D and 3D
  params.addCoupledVar("w", 0, "z-velocity"); // only required in 3D
  params.addRequiredCoupledVar("p", "pressure");

  params.addParam<RealVectorValue>(
      "gravity", RealVectorValue(0, 0, 0), "Direction of the gravity vector");

  params.addParam<MaterialPropertyName>("mu_name", "mu", "The name of the dynamic viscosity");
  params.addParam<MaterialPropertyName>("rho_name", "rho", "The name of the density");

  params.addParam<bool>("stabilize", false, "Whether to use GLS (encompasses SUPG) stabilization.");
  params.addParam<Real>("alpha", 1., "Multiplicative factor on the stabilization parameter tau.");
  params.addParam<bool>(
      "laplace", true, "Whether the viscous term of the momentum equations is in laplace form.");
  params.addParam<bool>("convective_term", true, "Whether to include the convective term.");
  params.addParam<bool>("transient_term",
                        false,
                        "Whether there should be a transient term in the momentum residuals.");

  return params;
}

INSBase::INSBase(const InputParameters & parameters)
  : Kernel(parameters),
    _second_phi(_assembly.secondPhi()),

    // Coupled variables
    _u_vel(coupledValue("u")),
    _v_vel(coupledValue("v")),
    _w_vel(coupledValue("w")),
    _p(coupledValue("p")),

    // Gradients
    _grad_u_vel(coupledGradient("u")),
    _grad_v_vel(coupledGradient("v")),
    _grad_w_vel(coupledGradient("w")),
    _grad_p(coupledGradient("p")),

    // second derivative tensors
    _second_u_vel(coupledSecond("u")),
    _second_v_vel(coupledSecond("v")),
    _second_w_vel(coupledSecond("w")),

    // time derivatives
    _u_vel_dot(coupledDot("u")),
    _v_vel_dot(coupledDot("v")),
    _w_vel_dot(coupledDot("w")),

    // derivatives of time derivatives
    _d_u_vel_dot_du(coupledDotDu("u")),
    _d_v_vel_dot_dv(coupledDotDu("v")),
    _d_w_vel_dot_dw(coupledDotDu("w")),

    // Variable numberings
    _u_vel_var_number(coupled("u")),
    _v_vel_var_number(coupled("v")),
    _w_vel_var_number(coupled("w")),
    _p_var_number(coupled("p")),

    _gravity(getParam<RealVectorValue>("gravity")),

    // Material properties
    _mu(getMaterialProperty<Real>("mu_name")),
    _rho(getMaterialProperty<Real>("rho_name")),

    _stabilize(getParam<bool>("stabilize")),
    _alpha(getParam<Real>("alpha")),
    _laplace(getParam<bool>("laplace")),
    _convective_term(getParam<bool>("convective_term")),
    _transient_term(getParam<bool>("transient_term"))
{
}

RealVectorValue
INSBase::convectiveTerm()
{
  RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]);
  return _rho[_qp] *
         RealVectorValue(U * _grad_u_vel[_qp], U * _grad_v_vel[_qp], U * _grad_w_vel[_qp]);
}

RealVectorValue
INSBase::dConvecDUComp(unsigned comp)
{
  RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]);
  RealVectorValue d_U_d_comp(0, 0, 0);
  d_U_d_comp(comp) = _phi[_j][_qp];

  RealVectorValue convective_term = _rho[_qp] * RealVectorValue(d_U_d_comp * _grad_u_vel[_qp],
                                                                d_U_d_comp * _grad_v_vel[_qp],
                                                                d_U_d_comp * _grad_w_vel[_qp]);
  convective_term(comp) += _rho[_qp] * U * _grad_phi[_j][_qp];

  return convective_term;
}

RealVectorValue
INSBase::strongViscousTermLaplace()
{
  return -_mu[_qp] *
         RealVectorValue(_second_u_vel[_qp].tr(), _second_v_vel[_qp].tr(), _second_w_vel[_qp].tr());
}

RealVectorValue
INSBase::strongViscousTermTraction()
{
  return strongViscousTermLaplace() -
         _mu[_qp] *
             (_second_u_vel[_qp].row(0) + _second_v_vel[_qp].row(1) + _second_w_vel[_qp].row(2));
}

RealVectorValue
INSBase::dStrongViscDUCompLaplace(unsigned comp)
{
  RealVectorValue viscous_term(0, 0, 0);
  viscous_term(comp) = -_mu[_qp] * _second_phi[_j][_qp].tr();

  return viscous_term;
}

RealVectorValue
INSBase::dStrongViscDUCompTraction(unsigned comp)
{
  RealVectorValue viscous_term(0, 0, 0);
  viscous_term(comp) = -_mu[_qp] * (_second_phi[_j][_qp](0, 0) + _second_phi[_j][_qp](1, 1) +
                                    _second_phi[_j][_qp](2, 2));
  for (unsigned i = 0; i < 3; i++)
    viscous_term(i) += -_mu[_qp] * _second_phi[_j][_qp](i, comp);

  return viscous_term;
}

RealVectorValue
INSBase::weakViscousTermLaplace(unsigned comp)
{
  switch (comp)
  {
    case 0:
      return _mu[_qp] * _grad_u_vel[_qp];

    case 1:
      return _mu[_qp] * _grad_v_vel[_qp];

    case 2:
      return _mu[_qp] * _grad_w_vel[_qp];

    default:
      return _zero[_qp];
  }
}

RealVectorValue
INSBase::weakViscousTermTraction(unsigned comp)
{
  switch (comp)
  {
    case 0:
    {
      RealVectorValue transpose(_grad_u_vel[_qp](0), _grad_v_vel[_qp](0), _grad_w_vel[_qp](0));
      return _mu[_qp] * _grad_u_vel[_qp] + _mu[_qp] * transpose;
    }

    case 1:
    {
      RealVectorValue transpose(_grad_u_vel[_qp](1), _grad_v_vel[_qp](1), _grad_w_vel[_qp](1));
      return _mu[_qp] * _grad_v_vel[_qp] + _mu[_qp] * transpose;
    }

    case 2:
    {
      RealVectorValue transpose(_grad_u_vel[_qp](2), _grad_v_vel[_qp](2), _grad_w_vel[_qp](2));
      return _mu[_qp] * _grad_w_vel[_qp] + _mu[_qp] * transpose;
    }

    default:
      return _zero[_qp];
  }
}

RealVectorValue
INSBase::dWeakViscDUCompLaplace()
{
  return _mu[_qp] * _grad_phi[_j][_qp];
}

RealVectorValue
INSBase::dWeakViscDUCompTraction()
{
  return _mu[_qp] * _grad_phi[_j][_qp];
}

RealVectorValue
INSBase::strongPressureTerm()
{
  return _grad_p[_qp];
}

Real
INSBase::weakPressureTerm()
{
  return -_p[_qp];
}

RealVectorValue
INSBase::dStrongPressureDPressure()
{
  return _grad_phi[_j][_qp];
}

Real
INSBase::dWeakPressureDPressure()
{
  return -_phi[_j][_qp];
}

RealVectorValue
INSBase::bodyForcesTerm()
{
  return gravity();
}

RealVectorValue
INSBase::gravity()
{
  return -_rho[_qp] * _gravity;
}

RealVectorValue
INSBase::timeDerivativeTerm()
{
  return _rho[_qp] * RealVectorValue(_u_vel_dot[_qp], _v_vel_dot[_qp], _w_vel_dot[_qp]);
}

RealVectorValue
INSBase::dTimeDerivativeDUComp(unsigned comp)
{
  Real base = _rho[_qp] * _phi[_j][_qp];
  switch (comp)
  {
    case 0:
      return RealVectorValue(base * _d_u_vel_dot_du[_qp], 0, 0);

    case 1:
      return RealVectorValue(0, base * _d_v_vel_dot_dv[_qp], 0);

    case 2:
      return RealVectorValue(0, 0, base * _d_w_vel_dot_dw[_qp]);

    default:
      mooseError("comp must be 0, 1, or 2");
  }
}

Real
INSBase::tau()
{
  Real nu = _mu[_qp] / _rho[_qp];
  RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]);
  Real h = _current_elem->hmax();
  return _alpha / std::sqrt((2. * U.norm() / h) * (2. * U.norm() / h) +
                            9. * (4. * nu / (h * h)) * (4. * nu / (h * h)));
}

Real
INSBase::dTauDUComp(unsigned comp)
{
  Real nu = _mu[_qp] / _rho[_qp];
  RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]);
  Real h = _current_elem->hmax();
  return -_alpha / 2. * std::pow((2. * U.norm() / h) * (2. * U.norm() / h) +
                                     9. * (4. * nu / (h * h)) * (4. * nu / (h * h)),
                                 -1.5) *
         2. * (2. * U.norm() / h) * 2. / h * U(comp) * _phi[_j][_qp] /
         (U.norm() + std::numeric_limits<double>::epsilon());
}
<|endoftext|>