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

#ifndef INCLUDED_SVTOOLS_PATHOPTIONS_HXX
#include <svtools/pathoptions.hxx>
#endif
#ifndef _SVTOOLS_LANGUAGEOPTIONS_HXX
#include <svtools/languageoptions.hxx>
#endif
#ifndef _UNOTOOLS_UCBSTREAMHELPER_HXX
#include <unotools/ucbstreamhelper.hxx>
#endif
#ifndef _URLOBJ_HXX
#include <tools/urlobj.hxx>
#endif
#ifndef _SV_VIRDEV_HXX
#include <vcl/virdev.hxx>
#endif
#ifndef _SFXAPP_HXX //autogen
#include <sfx2/app.hxx>
#endif
#ifndef _SV_STATUS_HXX //autogen
#include <vcl/status.hxx>
#endif
#ifndef _SFXINTITEM_HXX //autogen
#include <svtools/intitem.hxx>
#endif
#ifndef _SFXMSG_HXX //autogen
#include <sfx2/msg.hxx>
#endif
#ifndef _SFXOBJFACE_HXX //autogen
#include <sfx2/objface.hxx>
#endif
#ifndef _SFX_PRINTER_HXX
#include <sfx2/printer.hxx>
#endif
#ifndef _SVX_PSZCTRL_HXX //autogen
#include <svx/pszctrl.hxx>
#endif
#ifndef _SVX_ZOOMCTRL_HXX //autogen
#include <svx/zoomctrl.hxx>
#endif
#ifndef _SVX_MODCTRL_HXX //autogen
#include <svx/modctrl.hxx>
#endif
#ifndef _ZFORLIST_HXX
#include <svtools/zforlist.hxx>
#endif
#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif

#ifndef _EHDL_HXX
#include <svtools/ehdl.hxx>
#endif

#define ITEMID_SEARCH           SID_SEARCH_ITEM
#include <svx/svxids.hrc>
#include <offmgr/ofaids.hrc>
#include <svx/srchitem.hxx>

#pragma hdrstop

#define _SD_DLL                 // fuer SD_MOD()
#include "sderror.hxx"
#include "sdmod.hxx"
#include "sddll.hxx"
#include "sdresid.hxx"
#include "optsitem.hxx"
#include "docshell.hxx"
#include "drawdoc.hxx"
#include "app.hrc"
#include "glob.hrc"
#include "strings.hrc"
#include "res_bmp.hrc"
#include "cfgids.hxx"

TYPEINIT1( SdModule, SfxModule );

#define SdModule
#include "sdslots.hxx"

SFX_IMPL_INTERFACE(SdModule, SfxModule, SdResId(STR_APPLICATIONOBJECTBAR))
{
    SFX_STATUSBAR_REGISTRATION(RID_DRAW_STATUSBAR);
}

/*************************************************************************
|*
|* Ctor
|*
\************************************************************************/

SdModule::SdModule(SfxObjectFactory* pDrawObjFact, SfxObjectFactory* pGraphicObjFact)
:   SfxModule( SFX_APP()->CreateResManager("sd"), FALSE,
                  pDrawObjFact, pGraphicObjFact, NULL ),
    bWaterCan(FALSE),
    pTransferClip(NULL),
    pTransferDrag(NULL),
    pTransferSelection(NULL),
    pImpressOptions(NULL),
    pDrawOptions(NULL),
    pSearchItem(NULL),
    pNumberFormatter( NULL )
{
    SetName( UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "StarDraw" ) ) );  // Nicht uebersetzen!
    pSearchItem = new SvxSearchItem(ITEMID_SEARCH);
    pSearchItem->SetAppFlag(SVX_SEARCHAPP_DRAW);
    StartListening( *SFX_APP() );

    mpErrorHdl = new SfxErrorHandler( RID_SD_ERRHDL,
                                         ERRCODE_AREA_SD,
                                         ERRCODE_AREA_SD_END,
                                         GetResMgr() );

    // Create a new ref device and (by calling SetReferenceDevice())
    // set its resolution to 600 DPI.  This leads to a visually better
    // formatting of text in small sizes (6 point and below.)
    VirtualDevice* pDevice = new VirtualDevice;
    mpVirtualRefDevice = pDevice;
    pDevice->SetMapMode( MAP_100TH_MM );
    pDevice->SetReferenceDevice ( VirtualDevice::REFDEV_MODE06 );
}

/*************************************************************************
|*
|* Dtor
|*
\************************************************************************/

SdModule::~SdModule()
{
    delete pSearchItem;

    if( pNumberFormatter )
        delete pNumberFormatter;

    delete mpErrorHdl;
    delete static_cast< VirtualDevice* >( mpVirtualRefDevice );
}

/*************************************************************************
|*
|* Statusbar erzeugen
|*
\************************************************************************/

#define AUTOSIZE_WIDTH  180
#define TEXT_WIDTH(s)   rStatusBar.GetTextWidth((s))

void SdModule::FillStatusBar(StatusBar& rStatusBar)
{
    // Hinweis
    rStatusBar.InsertItem( SID_CONTEXT, TEXT_WIDTH( String().Fill( 30, 'x' ) ), // vorher 52
                            SIB_IN | SIB_LEFT | SIB_AUTOSIZE );

    // Groesse und Position
    rStatusBar.InsertItem( SID_ATTR_SIZE, SvxPosSizeStatusBarControl::GetDefItemWidth(rStatusBar), // vorher 42
                            SIB_IN | SIB_USERDRAW );
                            // SIB_AUTOSIZE | SIB_LEFT | SIB_OWNERDRAW );

    // Massstab
    rStatusBar.InsertItem( SID_ATTR_ZOOM, SvxZoomStatusBarControl::GetDefItemWidth(rStatusBar), SIB_IN | SIB_CENTER );
/*
    // Einfuege- / Uberschreibmodus
    rStatusBar.InsertItem( SID_ATTR_INSERT, TEXT_WIDTH( "EINFG" ),
                            SIB_IN | SIB_CENTER );

    // Selektionsmodus
    rStatusBar.InsertItem( SID_STATUS_SELMODE, TEXT_WIDTH( "ERG" ),
                            SIB_IN | SIB_CENTER );
*/
    // Dokument geaendert
    rStatusBar.InsertItem( SID_DOC_MODIFIED, SvxModifyControl::GetDefItemWidth(rStatusBar) );

    // Seite
    rStatusBar.InsertItem( SID_STATUS_PAGE, TEXT_WIDTH( String().Fill( 24, 'X' ) ),
                            SIB_IN | SIB_LEFT );

    // Praesentationslayout
    rStatusBar.InsertItem( SID_STATUS_LAYOUT, TEXT_WIDTH( String().Fill( 10, 'X' ) ),
                            SIB_IN | SIB_LEFT | SIB_AUTOSIZE );
}

/*************************************************************************
|*
|* get notifications
|*
\************************************************************************/

void SdModule::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
{
    if( rHint.ISA( SfxSimpleHint ) &&
        ( (SfxSimpleHint&) rHint ).GetId() == SFX_HINT_DEINITIALIZING )
    {
        delete pImpressOptions, pImpressOptions = NULL;
        delete pDrawOptions, pDrawOptions = NULL;
    }
}

/*************************************************************************
|*
|* Optionen zurueckgeben
|*
\************************************************************************/

SdOptions* SdModule::GetSdOptions(DocumentType eDocType)
{
    SdOptions* pOptions = NULL;

    if (eDocType == DOCUMENT_TYPE_DRAW)
    {
        if (!pDrawOptions)
            pDrawOptions = new SdOptions( SDCFG_DRAW );

        pOptions = pDrawOptions;
    }
    else if (eDocType == DOCUMENT_TYPE_IMPRESS)
    {
        if (!pImpressOptions)
            pImpressOptions = new SdOptions( SDCFG_IMPRESS );

        pOptions = pImpressOptions;
    }
    if( pOptions )
    {
        UINT16 nMetric = pOptions->GetMetric();

        SdDrawDocShell* pDocSh = PTR_CAST( SdDrawDocShell, SfxObjectShell::Current() );
        SdDrawDocument* pDoc = NULL;
        if (pDocSh)
            pDoc = pDocSh->GetDoc();

        if( nMetric != 0xffff && pDoc && eDocType == pDoc->GetDocumentType() )
            PutItem( SfxUInt16Item( SID_ATTR_METRIC, nMetric ) );
    }

    return(pOptions);
}

/*************************************************************************
|*
|* Optionen-Stream fuer interne Options oeffnen und zurueckgeben;
|* falls der Stream zum Lesen geoeffnet wird, aber noch nicht
|* angelegt wurde, wird ein 'leeres' RefObject zurueckgegeben
|*
\************************************************************************/

SvStorageStreamRef SdModule::GetOptionStream( const String& rOptionName,
                                              SdOptionStreamMode eMode )
{
    SdDrawDocShell*     pDocSh = PTR_CAST( SdDrawDocShell, SfxObjectShell::Current() );
    SvStorageStreamRef  xStm;

    if( pDocSh )
    {
        DocumentType    eType = pDocSh->GetDoc()->GetDocumentType();
        String          aStmName;

        if( !xOptionStorage.Is() )
        {
            INetURLObject aURL( SvtPathOptions().GetUserConfigPath() );

            aURL.Append( UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "drawing.cfg" ) ) );

            SvStream* pStm = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE );

            if( pStm )
                xOptionStorage = new SvStorage( pStm, TRUE );
        }

        if( DOCUMENT_TYPE_DRAW == eType )
            aStmName.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "Draw_" ) );
        else
            aStmName.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "Impress_" ) );

        aStmName += rOptionName;

        if( SD_OPTION_STORE == eMode || xOptionStorage->IsContained( aStmName ) )
            xStm = xOptionStorage->OpenStream( aStmName );
    }

    return xStm;
}

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

SvNumberFormatter* SdModule::GetNumberFormatter()
{
    if( !pNumberFormatter )
        pNumberFormatter = new SvNumberFormatter( ::comphelper::getProcessServiceFactory(), LANGUAGE_SYSTEM );

    return pNumberFormatter;
}

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

OutputDevice* SdModule::GetVirtualRefDevice (void)
{
    return mpVirtualRefDevice;
}

/** This method is deprecated and only an alias to
    <member>GetVirtualRefDevice()</member>.  The given argument is ignored.
*/
OutputDevice* SdModule::GetRefDevice (SdDrawDocShell& rDocShell)
{
    return GetVirtualRefDevice();
}

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

::com::sun::star::text::WritingMode SdModule::GetDefaultWritingMode() const
{
/*
    const SvtLanguageOptions aLanguageOptions;

    return( aLanguageOptions.IsCTLFontEnabled() ?
            ::com::sun::star::text::WritingMode_RL_TB :
            ::com::sun::star::text::WritingMode_LR_TB );
*/
    return ::com::sun::star::text::WritingMode_LR_TB;
}
<commit_msg>INTEGRATION: CWS impress1 (1.19.108); FILE MERGED 2003/10/28 09:46:04 af 1.19.108.2: RESYNC: (1.19-1.20); FILE MERGED 2003/09/17 09:27:44 af 1.19.108.1: #111996# Transition to stacked sub-shells. Introduction of namespace sd.<commit_after>/*************************************************************************
 *
 *  $RCSfile: sdmod.cxx,v $
 *
 *  $Revision: 1.23 $
 *
 *  last change: $Author: obo $ $Date: 2004-01-20 10:36:39 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef INCLUDED_SVTOOLS_PATHOPTIONS_HXX
#include <svtools/pathoptions.hxx>
#endif
#ifndef _SVTOOLS_LANGUAGEOPTIONS_HXX
#include <svtools/languageoptions.hxx>
#endif
#ifndef _UNOTOOLS_UCBSTREAMHELPER_HXX
#include <unotools/ucbstreamhelper.hxx>
#endif
#ifndef _URLOBJ_HXX
#include <tools/urlobj.hxx>
#endif
#ifndef _SV_VIRDEV_HXX
#include <vcl/virdev.hxx>
#endif
#ifndef _SFXAPP_HXX //autogen
#include <sfx2/app.hxx>
#endif
#ifndef _SV_STATUS_HXX //autogen
#include <vcl/status.hxx>
#endif
#ifndef _SFXINTITEM_HXX //autogen
#include <svtools/intitem.hxx>
#endif
#ifndef _SFXMSG_HXX //autogen
#include <sfx2/msg.hxx>
#endif
#ifndef _SFXOBJFACE_HXX //autogen
#include <sfx2/objface.hxx>
#endif
#ifndef _SFX_PRINTER_HXX
#include <sfx2/printer.hxx>
#endif
#ifndef _SVX_PSZCTRL_HXX //autogen
#include <svx/pszctrl.hxx>
#endif
#ifndef _SVX_ZOOMCTRL_HXX //autogen
#include <svx/zoomctrl.hxx>
#endif
#ifndef _SVX_MODCTRL_HXX //autogen
#include <svx/modctrl.hxx>
#endif
#ifndef _ZFORLIST_HXX
#include <svtools/zforlist.hxx>
#endif
#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif

#ifndef _EHDL_HXX
#include <svtools/ehdl.hxx>
#endif

#define ITEMID_SEARCH           SID_SEARCH_ITEM
#include <svx/svxids.hrc>
#include <offmgr/ofaids.hrc>
#include <svx/srchitem.hxx>

#pragma hdrstop

#define _SD_DLL                 // fuer SD_MOD()
#include "sderror.hxx"
#include "sdmod.hxx"
#include "sddll.hxx"
#include "sdresid.hxx"
#include "optsitem.hxx"
#ifndef SD_DRAW_DOC_SHELL_HXX
#include "DrawDocShell.hxx"
#endif
#include "drawdoc.hxx"
#include "app.hrc"
#include "glob.hrc"
#include "strings.hrc"
#include "res_bmp.hrc"
#include "cfgids.hxx"

TYPEINIT1( SdModule, SfxModule );

#define SdModule
#include "sdslots.hxx"

SFX_IMPL_INTERFACE(SdModule, SfxModule, SdResId(STR_APPLICATIONOBJECTBAR))
{
    SFX_STATUSBAR_REGISTRATION(RID_DRAW_STATUSBAR);
}

/*************************************************************************
|*
|* Ctor
|*
\************************************************************************/

SdModule::SdModule(SfxObjectFactory* pDrawObjFact, SfxObjectFactory* pGraphicObjFact)
:   SfxModule( SFX_APP()->CreateResManager("sd"), FALSE,
                  pDrawObjFact, pGraphicObjFact, NULL ),
    bWaterCan(FALSE),
    pTransferClip(NULL),
    pTransferDrag(NULL),
    pTransferSelection(NULL),
    pImpressOptions(NULL),
    pDrawOptions(NULL),
    pSearchItem(NULL),
    pNumberFormatter( NULL )
{
    SetName( UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "StarDraw" ) ) );  // Nicht uebersetzen!
    pSearchItem = new SvxSearchItem(ITEMID_SEARCH);
    pSearchItem->SetAppFlag(SVX_SEARCHAPP_DRAW);
    StartListening( *SFX_APP() );

    mpErrorHdl = new SfxErrorHandler( RID_SD_ERRHDL,
                                         ERRCODE_AREA_SD,
                                         ERRCODE_AREA_SD_END,
                                         GetResMgr() );

    // Create a new ref device and (by calling SetReferenceDevice())
    // set its resolution to 600 DPI.  This leads to a visually better
    // formatting of text in small sizes (6 point and below.)
    VirtualDevice* pDevice = new VirtualDevice;
    mpVirtualRefDevice = pDevice;
    pDevice->SetMapMode( MAP_100TH_MM );
    pDevice->SetReferenceDevice ( VirtualDevice::REFDEV_MODE06 );
}

/*************************************************************************
|*
|* Dtor
|*
\************************************************************************/

SdModule::~SdModule()
{
    delete pSearchItem;

    if( pNumberFormatter )
        delete pNumberFormatter;

    delete mpErrorHdl;
    delete static_cast< VirtualDevice* >( mpVirtualRefDevice );
}

/*************************************************************************
|*
|* Statusbar erzeugen
|*
\************************************************************************/

#define AUTOSIZE_WIDTH  180
#define TEXT_WIDTH(s)   rStatusBar.GetTextWidth((s))

void SdModule::FillStatusBar(StatusBar& rStatusBar)
{
    // Hinweis
    rStatusBar.InsertItem( SID_CONTEXT, TEXT_WIDTH( String().Fill( 30, 'x' ) ), // vorher 52
                            SIB_IN | SIB_LEFT | SIB_AUTOSIZE );

    // Groesse und Position
    rStatusBar.InsertItem( SID_ATTR_SIZE, SvxPosSizeStatusBarControl::GetDefItemWidth(rStatusBar), // vorher 42
                            SIB_IN | SIB_USERDRAW );
                            // SIB_AUTOSIZE | SIB_LEFT | SIB_OWNERDRAW );

    // Massstab
    rStatusBar.InsertItem( SID_ATTR_ZOOM, SvxZoomStatusBarControl::GetDefItemWidth(rStatusBar), SIB_IN | SIB_CENTER );
/*
    // Einfuege- / Uberschreibmodus
    rStatusBar.InsertItem( SID_ATTR_INSERT, TEXT_WIDTH( "EINFG" ),
                            SIB_IN | SIB_CENTER );

    // Selektionsmodus
    rStatusBar.InsertItem( SID_STATUS_SELMODE, TEXT_WIDTH( "ERG" ),
                            SIB_IN | SIB_CENTER );
*/
    // Dokument geaendert
    rStatusBar.InsertItem( SID_DOC_MODIFIED, SvxModifyControl::GetDefItemWidth(rStatusBar) );

    // Seite
    rStatusBar.InsertItem( SID_STATUS_PAGE, TEXT_WIDTH( String().Fill( 24, 'X' ) ),
                            SIB_IN | SIB_LEFT );

    // Praesentationslayout
    rStatusBar.InsertItem( SID_STATUS_LAYOUT, TEXT_WIDTH( String().Fill( 10, 'X' ) ),
                            SIB_IN | SIB_LEFT | SIB_AUTOSIZE );
}

/*************************************************************************
|*
|* get notifications
|*
\************************************************************************/

void SdModule::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
{
    if( rHint.ISA( SfxSimpleHint ) &&
        ( (SfxSimpleHint&) rHint ).GetId() == SFX_HINT_DEINITIALIZING )
    {
        delete pImpressOptions, pImpressOptions = NULL;
        delete pDrawOptions, pDrawOptions = NULL;
    }
}

/*************************************************************************
|*
|* Optionen zurueckgeben
|*
\************************************************************************/

SdOptions* SdModule::GetSdOptions(DocumentType eDocType)
{
    SdOptions* pOptions = NULL;

    if (eDocType == DOCUMENT_TYPE_DRAW)
    {
        if (!pDrawOptions)
            pDrawOptions = new SdOptions( SDCFG_DRAW );

        pOptions = pDrawOptions;
    }
    else if (eDocType == DOCUMENT_TYPE_IMPRESS)
    {
        if (!pImpressOptions)
            pImpressOptions = new SdOptions( SDCFG_IMPRESS );

        pOptions = pImpressOptions;
    }
    if( pOptions )
    {
        UINT16 nMetric = pOptions->GetMetric();

        ::sd::DrawDocShell* pDocSh = PTR_CAST(::sd::DrawDocShell, SfxObjectShell::Current() );
        SdDrawDocument* pDoc = NULL;
        if (pDocSh)
            pDoc = pDocSh->GetDoc();

        if( nMetric != 0xffff && pDoc && eDocType == pDoc->GetDocumentType() )
            PutItem( SfxUInt16Item( SID_ATTR_METRIC, nMetric ) );
    }

    return(pOptions);
}

/*************************************************************************
|*
|* Optionen-Stream fuer interne Options oeffnen und zurueckgeben;
|* falls der Stream zum Lesen geoeffnet wird, aber noch nicht
|* angelegt wurde, wird ein 'leeres' RefObject zurueckgegeben
|*
\************************************************************************/

SvStorageStreamRef SdModule::GetOptionStream( const String& rOptionName,
                                              SdOptionStreamMode eMode )
{
    ::sd::DrawDocShell*     pDocSh = PTR_CAST(::sd::DrawDocShell, SfxObjectShell::Current() );
    SvStorageStreamRef  xStm;

    if( pDocSh )
    {
        DocumentType    eType = pDocSh->GetDoc()->GetDocumentType();
        String          aStmName;

        if( !xOptionStorage.Is() )
        {
            INetURLObject aURL( SvtPathOptions().GetUserConfigPath() );

            aURL.Append( UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "drawing.cfg" ) ) );

            SvStream* pStm = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE );

            if( pStm )
                xOptionStorage = new SvStorage( pStm, TRUE );
        }

        if( DOCUMENT_TYPE_DRAW == eType )
            aStmName.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "Draw_" ) );
        else
            aStmName.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "Impress_" ) );

        aStmName += rOptionName;

        if( SD_OPTION_STORE == eMode || xOptionStorage->IsContained( aStmName ) )
            xStm = xOptionStorage->OpenStream( aStmName );
    }

    return xStm;
}

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

SvNumberFormatter* SdModule::GetNumberFormatter()
{
    if( !pNumberFormatter )
        pNumberFormatter = new SvNumberFormatter( ::comphelper::getProcessServiceFactory(), LANGUAGE_SYSTEM );

    return pNumberFormatter;
}

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

OutputDevice* SdModule::GetVirtualRefDevice (void)
{
    return mpVirtualRefDevice;
}

/** This method is deprecated and only an alias to
    <member>GetVirtualRefDevice()</member>.  The given argument is ignored.
*/
OutputDevice* SdModule::GetRefDevice (::sd::DrawDocShell& rDocShell)
{
    return GetVirtualRefDevice();
}

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

::com::sun::star::text::WritingMode SdModule::GetDefaultWritingMode() const
{
/*
    const SvtLanguageOptions aLanguageOptions;

    return( aLanguageOptions.IsCTLFontEnabled() ?
            ::com::sun::star::text::WritingMode_RL_TB :
            ::com::sun::star::text::WritingMode_LR_TB );
*/
    return ::com::sun::star::text::WritingMode_LR_TB;
}
<|endoftext|>


<commit_before>#include "ros/ros.h"
#include "geometry_msgs/Twist.h"
#include "sensor_msgs/LaserScan.h"
#include <nav_msgs/Odometry.h>
#include "std_msgs/String.h"

#include <cstdlib> // Needed for rand()
#include <ctime> // Needed to seed random number generator with a time value

float prevclosestRange = 0;
double linear_x;
double angular_z;

//pose of the robot
double px;
double py;
double theta;
double prevpx;
double prevpy;
bool isRotate;

int checkcount=0;

class RandomWalk {
		public:
		// Construst a new RandomWalk object and hook up this ROS node
		// to the simulated robot's velocity control and laser topics
		RandomWalk(ros::NodeHandle& nh) :
		fsm(FSM_MOVE_FORWARD),
		rotateStartTime(ros::Time::now()),
		rotateDuration(0.f) {
		// Initialize random time generator
		srand(time(NULL));
		// Advertise a new publisher for the simulated robot's velocity command topic
		// (the second argument indicates that if multiple command messages are in
		// the queue to be sent, only the last command will be sent)
		ros::NodeHandle n;
		commandPub = nh.advertise<geometry_msgs::Twist>("robot_2/cmd_vel",1000);
		truckPosPub = nh.advertise<std_msgs::String>("truck_position",1000);
		// Subscribe to the simulated robot's laser scan topic and tell ROS to call
		// this->commandCallback() whenever a new message is published on that topic
		laserSub = nh.subscribe<sensor_msgs::LaserScan>("robot_2/base_scan", 1000, &RandomWalk::commandCallback, this);
		StageOdo_sub = nh.subscribe<nav_msgs::Odometry>("robot_2/odom",1000, &RandomWalk::StageOdom_callback,this);
		//ros::Subscriber StageOdo_sub = n.subscribe<nav_msgs::Odometry>("robot_0/odom",1000, StageOdom_callback);

	};

	void StageOdom_callback(nav_msgs::Odometry msg)
	{
		//This is the call back function to process odometry messages coming from Stage.

		px = -3 + msg.pose.pose.position.x;
		py = -3 + msg.pose.pose.position.y;
		//printf("%f",px);

		// If the current position is the same the previous position, then the robot is stuck and needs to move around
		if ((px == prevpx) && (py == prevpy)) {
			//msg.pose.pose.position.x = 5;
			//ROS_INFO("Prevpx: %f",prevpx);

			// Note the negative linear_x
			//linear_x=-0.2;
			//angular_z=1;

			//theta=10;
			//px = 5;
			//py= 5;
			//printf("Robot stuck");
			if (!isRotate) {
				ROS_INFO("Truck stuck");
				double r2 = (double)rand()/((double)RAND_MAX/(M_PI/2));
				double m2 = (double)rand()/((double)RAND_MAX/0.5);
				//ROS_INFO("r2" << r2);
				move(-m2, r2);

			}
		} else {
			// One the robot becomes unstuck, then it moves around again normally
			//linear_x = 0.2;
			//angular_z = 0.2;
			//ROS_INFO("Robot unstuck");
			//checkcount=0;
		}
		ROS_INFO("Truck -- Current x position is: %f", px);
		ROS_INFO("Truck -- Current y position is: %f", py);
		prevpx = px;
		prevpy = py;
	};

	// Send a velocity command
	void move(double linearVelMPS, double angularVelRadPS) {
		geometry_msgs::Twist msg; // The default constructor will set all commands to 0
		msg.linear.x = linearVelMPS;
		msg.angular.z = angularVelRadPS;
		commandPub.publish(msg);
	};

	// Process the incoming laser scan message
	void commandCallback(const sensor_msgs::LaserScan::ConstPtr& msg) {
		if (fsm == FSM_MOVE_FORWARD) {
			// Compute the average range value between MIN_SCAN_ANGLE and MAX_SCAN_ANGLE
			//
			// NOTE: ideally, the following loop should have additional checks to ensure
			// that indices are not out of bounds, by computing:
			//
			//- currAngle = msg->angle_min + msg->angle_increment*currIndex
			//
			// and then ensuring that currAngle <= msg->angle_max
			unsigned int minIndex = ceil((MIN_SCAN_ANGLE_RAD - msg->angle_min) / msg->angle_increment);
			unsigned int maxIndex = ceil((MAX_SCAN_ANGLE_RAD - msg->angle_min) / msg->angle_increment);
			float closestRange = msg->ranges[minIndex];

			for (unsigned int currIndex = minIndex + 1; currIndex < maxIndex; currIndex++) {
				if (msg->ranges[currIndex] < closestRange) {
					closestRange = msg->ranges[currIndex];
				}
			}
			//if (closestRange == prevclosestRange) {
			//	ROS_INFO_STREAM("STUCK");
			//	move(-FORWARD_SPEED_MPS, ROTATE_SPEED_RADPS);
			//	//move(0, ROTATE_SPEED_RADPS);
			//} else {

				//ROS_INFO_STREAM("Range: " << closestRange);
				prevclosestRange = closestRange;
				if (closestRange < PROXIMITY_RANGE_M) {
					fsm=FSM_ROTATE;
					rotateStartTime=ros::Time::now();
					float r2 = (float)rand()/((float)RAND_MAX/100);
					rotateDuration=ros::Duration(rand() % 2);
					//fsm= FSM_MOVE_FORWARD;
				}
			//}

		}
	};
	// Main FSM loop for ensuring that ROS messages are
	// processed in a timely manner, and also for sending
	// velocity controls to the simulated robot based on the FSM state
	void spin() {
		ros::Rate rate(10); // Specify the FSM loop rate in Hz
		while (ros::ok()) { // Keep spinning loop until user presses Ctrl+C
			std_msgs::String msg;
			std::stringstream ss;
			ss << "Truck -- px:" << px << " py:" << py << " theta:" << theta << " isRotate:" << isRotate;
    			msg.data = ss.str();

    			//ROS_INFO("%s", msg.data.c_str());

			if (fsm == FSM_MOVE_FORWARD) {
				//ROS_INFO_STREAM("Start forward");
				move(FORWARD_SPEED_MPS, 0);
				checkcount++;
				if (checkcount > 3) {
					isRotate=false;
				}
			}
			if (fsm == FSM_ROTATE) {
				//ROS_INFO_STREAM("Start rotate");
				move(0, ROTATE_SPEED_RADPS);
				rotateEndTime=ros::Time::now();
				isRotate=true;
				//ROS_INFO_STREAM("Time: " << rotateEndTime);

				if ((rotateEndTime - rotateStartTime) > rotateDuration) {
					fsm=FSM_MOVE_FORWARD;
					//ROS_INFO_STREAM("End rotate");
					checkcount=0;
				}
			}

		truckPosPub.publish(msg);

		ros::spinOnce(); // Need to call this function often to allow ROS to process incoming messages
		rate.sleep(); // Sleep for the rest of the cycle, to enforce the FSM loop rate
		}
	};
	enum FSM {FSM_MOVE_FORWARD, FSM_ROTATE};
	// Tunable parameters
	// TODO: tune parameters as you see fit
	const static double MIN_SCAN_ANGLE_RAD = -10.0/180*M_PI;
	const static double MAX_SCAN_ANGLE_RAD = +10.0/180*M_PI;
	const static float PROXIMITY_RANGE_M = 4; // Should be smaller than sensor_msgs::LaserScan::range_max
	const static double FORWARD_SPEED_MPS = 2;
	const static double ROTATE_SPEED_RADPS = M_PI/2;

	protected:
	ros::Publisher commandPub; // Publisher to the simulated robot's velocity command topic
	ros::Publisher truckPosPub;
	ros::Subscriber laserSub; // Subscriber to the simulated robot's laser scan topic
	enum FSM fsm; // Finite state machine for the random walk algorithm
	ros::Time rotateStartTime; // Start time of the rotation
	ros::Time rotateEndTime;
	ros::Duration rotateDuration; // Duration of the rotation
	ros::Subscriber StageOdo_sub;

};
int main(int argc, char **argv) {
	ros::init(argc, argv, "Trust"); // Initiate new ROS node named "Truck"
	ROS_INFO("This node is: Truck");
	ros::NodeHandle n;
	prevpx = 0;
	prevpx= 0;
	RandomWalk walker(n); // Create new random walk object
	walker.spin(); // Execute FSM loop
	return 0;
};

<commit_msg>Truck Rebase<commit_after>#include "ros/ros.h"
#include "geometry_msgs/Twist.h"
#include "sensor_msgs/LaserScan.h"
#include <nav_msgs/Odometry.h>
#include "std_msgs/String.h"

#include <cstdlib> // Needed for rand()
#include <ctime> // Needed to seed random number generator with a time value

float prevclosestRange = 0;
double linear_x;
double angular_z;

//pose of the robot
double px;
double py;
double theta;
double prevpx;
double prevpy;
bool isRotate;

int checkcount=0;

class RandomWalk {
		public:
		// Construst a new RandomWalk object and hook up this ROS node
		// to the simulated robot's velocity control and laser topics
		RandomWalk(ros::NodeHandle& nh) :
		fsm(FSM_MOVE_FORWARD),
		rotateStartTime(ros::Time::now()),
		rotateDuration(0.f) {
		// Initialize random time generator
		srand(time(NULL));
		// Advertise a new publisher for the simulated robot's velocity command topic
		// (the second argument indicates that if multiple command messages are in
		// the queue to be sent, only the last command will be sent)
		ros::NodeHandle n;
		commandPub = nh.advertise<geometry_msgs::Twist>("robot_2/cmd_vel",1000);
		truckPosPub = nh.advertise<std_msgs::String>("truck_position",1000);
		// Subscribe to the simulated robot's laser scan topic and tell ROS to call
		// this->commandCallback() whenever a new message is published on that topic
		laserSub = nh.subscribe<sensor_msgs::LaserScan>("robot_2/base_scan", 1000, &RandomWalk::commandCallback, this);
		StageOdo_sub = nh.subscribe<nav_msgs::Odometry>("robot_2/odom",1000, &RandomWalk::StageOdom_callback,this);
		//ros::Subscriber StageOdo_sub = n.subscribe<nav_msgs::Odometry>("robot_0/odom",1000, StageOdom_callback);

	};

	void StageOdom_callback(nav_msgs::Odometry msg)
	{
		//This is the call back function to process odometry messages coming from Stage.

		px = -3 + msg.pose.pose.position.x;
		py = -3 + msg.pose.pose.position.y;
		//printf("%f",px);

		// If the current position is the same the previous position, then the robot is stuck and needs to move around
		if ((px == prevpx) && (py == prevpy)) {
			//msg.pose.pose.position.x = 5;
			//ROS_INFO("Prevpx: %f",prevpx);

			// Note the negative linear_x
			//linear_x=-0.2;
			//angular_z=1;

			//theta=10;
			//px = 5;
			//py= 5;
			//printf("Robot stuck");
			if (!isRotate) {
				ROS_INFO("Truck stuck");
				double r2 = (double)rand()/((double)RAND_MAX/(M_PI/2));
				double m2 = (double)rand()/((double)RAND_MAX/0.5);
				//ROS_INFO("r2" << r2);
				move(-m2, r2);

			}
		} else {
			// One the robot becomes unstuck, then it moves around again normally
			//linear_x = 0.2;
			//angular_z = 0.2;
			//ROS_INFO("Robot unstuck");
			//checkcount=0;
		}
		ROS_INFO("Truck -- Current x position is: %f", px);
		ROS_INFO("Truck -- Current y position is: %f", py);
		prevpx = px;
		prevpy = py;
	};

	// Send a velocity command
	void move(double linearVelMPS, double angularVelRadPS) {
		geometry_msgs::Twist msg; // The default constructor will set all commands to 0
		msg.linear.x = linearVelMPS;
		msg.angular.z = angularVelRadPS;
		commandPub.publish(msg);
	};

	// Process the incoming laser scan message
	void commandCallback(const sensor_msgs::LaserScan::ConstPtr& msg) {
		if (fsm == FSM_MOVE_FORWARD) {
			// Compute the average range value between MIN_SCAN_ANGLE and MAX_SCAN_ANGLE
			//
			// NOTE: ideally, the following loop should have additional checks to ensure
			// that indices are not out of bounds, by computing:
			//
			//- currAngle = msg->angle_min + msg->angle_increment*currIndex
			//
			// and then ensuring that currAngle <= msg->angle_max
			unsigned int minIndex = ceil((MIN_SCAN_ANGLE_RAD - msg->angle_min) / msg->angle_increment);
			unsigned int maxIndex = ceil((MAX_SCAN_ANGLE_RAD - msg->angle_min) / msg->angle_increment);
			float closestRange = msg->ranges[minIndex];

			for (unsigned int currIndex = minIndex + 1; currIndex < maxIndex; currIndex++) {
				if (msg->ranges[currIndex] < closestRange) {
					closestRange = msg->ranges[currIndex];
				}
			}
			//if (closestRange == prevclosestRange) {
			//	ROS_INFO_STREAM("STUCK");
			//	move(-FORWARD_SPEED_MPS, ROTATE_SPEED_RADPS);
			//	//move(0, ROTATE_SPEED_RADPS);
			//} else {

				//ROS_INFO_STREAM("Range: " << closestRange);
				prevclosestRange = closestRange;
				if (closestRange < PROXIMITY_RANGE_M) {
					fsm=FSM_ROTATE;
					rotateStartTime=ros::Time::now();
					float r2 = (float)rand()/((float)RAND_MAX/100);
					rotateDuration=ros::Duration(rand() % 2);
					//fsm= FSM_MOVE_FORWARD;
				}
			//}

		}
	};
	// Main FSM loop for ensuring that ROS messages are
	// processed in a timely manner, and also for sending
	// velocity controls to the simulated robot based on the FSM state
	void spin() {
		ros::Rate rate(10); // Specify the FSM loop rate in Hz
		while (ros::ok()) { // Keep spinning loop until user presses Ctrl+C
			std_msgs::String msg;
			std::stringstream ss;
			ss << "Truck -- px:" << px << " py:" << py << " theta:" << theta << " isRotate:" << isRotate;
    			msg.data = ss.str();

    			//ROS_INFO("%s", msg.data.c_str());

			if (fsm == FSM_MOVE_FORWARD) {
				//ROS_INFO_STREAM("Start forward");
				move(FORWARD_SPEED_MPS, 0);
				checkcount++;
				if (checkcount > 3) {
					isRotate=false;
				}
			}
			if (fsm == FSM_ROTATE) {
				//ROS_INFO_STREAM("Start rotate");
				move(0, ROTATE_SPEED_RADPS);
				rotateEndTime=ros::Time::now();
				isRotate=true;
				//ROS_INFO_STREAM("Time: " << rotateEndTime);

				if ((rotateEndTime - rotateStartTime) > rotateDuration) {
					fsm=FSM_MOVE_FORWARD;
					//ROS_INFO_STREAM("End rotate");
					checkcount=0;
				}
			}

		truckPosPub.publish(msg);

		ros::spinOnce(); // Need to call this function often to allow ROS to process incoming messages
		rate.sleep(); // Sleep for the rest of the cycle, to enforce the FSM loop rate
		}
	};
	enum FSM {FSM_MOVE_FORWARD, FSM_ROTATE};
	// Tunable parameters
	// TODO: tune parameters as you see fit
	const static double MIN_SCAN_ANGLE_RAD = -10.0/180*M_PI;
	const static double MAX_SCAN_ANGLE_RAD = +10.0/180*M_PI;
	const static float PROXIMITY_RANGE_M = 4; // Should be smaller than sensor_msgs::LaserScan::range_max
	const static double FORWARD_SPEED_MPS = 2;
	const static double ROTATE_SPEED_RADPS = M_PI/2;

	protected:
	ros::Publisher commandPub; // Publisher to the simulated robot's velocity command topic
	ros::Publisher truckPosPub;
	ros::Subscriber laserSub; // Subscriber to the simulated robot's laser scan topic
	enum FSM fsm; // Finite state machine for the random walk algorithm
	ros::Time rotateStartTime; // Start time of the rotation
	ros::Time rotateEndTime;
	ros::Duration rotateDuration; // Duration of the rotation
	ros::Subscriber StageOdo_sub;

};
int main(int argc, char **argv) {
	ros::init(argc, argv, "Trust"); // Initiate new ROS node named "Truck"
	ROS_INFO("This node is: Truck");
	ros::NodeHandle n;
	prevpx = 0;
	prevpx= 0;
	RandomWalk walker(n); // Create new random walk object
	walker.spin(); // Execute FSM loop
	return 0;
};

<|endoftext|>


<commit_before>
#include "window.h"
#include "painter.h"
#include <core/contract.h>
#include <stdexcept>
#include <xcb/xcb.h>

namespace xcb
{

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

window::window( xcb_connection_t *c, xcb_screen_t *screen )
	: _connection( c ), _screen( screen )
{
	precondition( _connection, "null connection" );
	precondition( _screen, "null screen" );
	_win = xcb_generate_id( _connection );

	uint32_t mask = XCB_CW_EVENT_MASK;
	const uint32_t cwvals[] = { XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY };

	xcb_create_window( _connection,    // Connection
		XCB_COPY_FROM_PARENT,          // depth (same as root)
		_win,                          // window Id
		_screen->root,                  // parent window
		0, 0,                          // x, y
		320, 240,                      // width, height
		10,                            // border_width
		XCB_WINDOW_CLASS_INPUT_OUTPUT, // class
		screen->root_visual,           // visual
		mask, cwvals );   // masks, not used yet

	const uint32_t values[] = { screen->black_pixel };
	xcb_change_window_attributes( _connection, _win, XCB_CW_BACK_PIXEL, values );
}

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

window::~window( void )
{
}

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

void window::raise( void )
{
	const static uint32_t values[] = { XCB_STACK_MODE_ABOVE };
	xcb_configure_window( _connection, _win, XCB_CONFIG_WINDOW_STACK_MODE, values);
}

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

/*
void window::lower( void )
{
	const static uint32_t values[] = { XCB_STACK_MODE_BELOW };
	xcb_configure_window( _connection, _win, XCB_CONFIG_WINDOW_STACK_MODE, values);
}
*/

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

void window::show( void )
{
	xcb_map_window( _connection, _win );
}

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

void window::hide( void )
{
	xcb_unmap_window( _connection, _win );
}

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

bool window::is_visible( void )
{
	// TODO fix this
	return true;
}

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

/*
rect window::geometry( void )
{
}
*/

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

void window::resize( double w, double h )
{
	const static uint32_t values[] = { uint32_t(w+0.5), uint32_t(h+0.5) };
	xcb_configure_window( _connection, _win, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values );
}

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

void window::set_minimum_size( double w, double h )
{
}

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

void window::set_title( const std::string &t )
{
}

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

std::shared_ptr<platform::painter> window::paint( void )
{
	return std::make_shared<painter>( _connection, _screen, _win );
}

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

xcb_window_t window::id( void ) const
{
	return _win;
}

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

}

<commit_msg>Implemented window set_title.<commit_after>
#include "window.h"
#include "painter.h"
#include <core/contract.h>
#include <stdexcept>
#include <xcb/xcb.h>

namespace xcb
{

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

window::window( xcb_connection_t *c, xcb_screen_t *screen )
	: _connection( c ), _screen( screen )
{
	precondition( _connection, "null connection" );
	precondition( _screen, "null screen" );
	_win = xcb_generate_id( _connection );

	uint32_t mask = XCB_CW_EVENT_MASK;
	const uint32_t cwvals[] = { XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY };

	xcb_create_window( _connection,    // Connection
		XCB_COPY_FROM_PARENT,          // depth (same as root)
		_win,                          // window Id
		_screen->root,                  // parent window
		0, 0,                          // x, y
		320, 240,                      // width, height
		10,                            // border_width
		XCB_WINDOW_CLASS_INPUT_OUTPUT, // class
		screen->root_visual,           // visual
		mask, cwvals );   // masks, not used yet

	const uint32_t values[] = { screen->black_pixel };
	xcb_change_window_attributes( _connection, _win, XCB_CW_BACK_PIXEL, values );
}

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

window::~window( void )
{
}

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

void window::raise( void )
{
	const static uint32_t values[] = { XCB_STACK_MODE_ABOVE };
	xcb_configure_window( _connection, _win, XCB_CONFIG_WINDOW_STACK_MODE, values);
}

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

/*
void window::lower( void )
{
	const static uint32_t values[] = { XCB_STACK_MODE_BELOW };
	xcb_configure_window( _connection, _win, XCB_CONFIG_WINDOW_STACK_MODE, values);
}
*/

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

void window::show( void )
{
	xcb_map_window( _connection, _win );
}

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

void window::hide( void )
{
	xcb_unmap_window( _connection, _win );
}

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

bool window::is_visible( void )
{
	// TODO fix this
	return true;
}

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

/*
rect window::geometry( void )
{
}
*/

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

void window::resize( double w, double h )
{
	const static uint32_t values[] = { uint32_t(w+0.5), uint32_t(h+0.5) };
	xcb_configure_window( _connection, _win, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values );
}

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

void window::set_minimum_size( double w, double h )
{
}

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

void window::set_title( const std::string &t )
{
	xcb_change_property( _connection, XCB_PROP_MODE_REPLACE, _win, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, t.size(), t.c_str() );
}

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

std::shared_ptr<platform::painter> window::paint( void )
{
	return std::make_shared<painter>( _connection, _screen, _win );
}

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

xcb_window_t window::id( void ) const
{
	return _win;
}

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

}

<|endoftext|>


<commit_before>/** probabilizer.cc
    Jeremy Barnes, 16 December 2014
    Copyright (c) 2014 Datacratic Inc.  All rights reserved.

    This file is part of MLDB. Copyright 2015 Datacratic. All rights reserved.

    Implementation of an algorithm to transform an arbitrary score into a
    calibrated probability.
*/

#include "probabilizer.h"
#include "mldb/ml/jml/probabilizer.h"
#include "mldb/server/mldb_server.h"
#include "mldb/core/dataset.h"
#include "mldb/sql/sql_expression.h"
#include "mldb/plugins/sql_config_validator.h"
#include "mldb/plugins/sql_expression_extractors.h"
#include "mldb/jml/stats/distribution.h"
#include "mldb/jml/utils/guard.h"
#include "mldb/jml/utils/worker_task.h"
#include "mldb/ml/jml/thread_context.h"
#include "mldb/arch/simd_vector.h"
#include "mldb/jml/utils/vector_utils.h"
#include "mldb/types/basic_value_descriptions.h"
#include "mldb/ml/value_descriptions.h"
#include "mldb/types/any_impl.h"
#include "mldb/types/distribution_description.h"
#include "mldb/http/http_exception.h"
#include "mldb/vfs/filter_streams.h"

#include "mldb/server/analytics.h"

using namespace std;
using namespace ML;

//#if (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ <= 6)
#define override
//#endif

namespace Datacratic {
namespace MLDB {

DEFINE_STRUCTURE_DESCRIPTION(ProbabilizerConfig);

ProbabilizerConfigDescription::
ProbabilizerConfigDescription()
{
    addField("trainingData", &ProbabilizerConfig::trainingData,
             "Specification of the data for input to the probabilizer procedure. "
             "The expression is used to calculate the score for a given dataset row. "
             "Normally this will be the output of a classifier applied to that row. "
             "The select statement does not support groupby and having clauses. "
             "The expression to generate the weight.  A weight of 2.0 is "
             "equivalent "
             "to including the identical row twice in the training dataset.  "
             "This can be used to counteract the effect of sampling or weighting "
             "over the dataset that the probabilizer is trained on.  The "
             "default will weight each example the same.");
    addField("modelFileUrl", &ProbabilizerConfig::modelFileUrl,
             "URL where the model file (with extension '.prb') should be saved. "
             "This file can be loaded by a function of type 'probabilizer'.");
    addField("link", &ProbabilizerConfig::link,
             "Link function to use.  See documentation.  Generally the "
             "default, PROBIT, is a good place to start for binary "
             "classifification",
             ML::LOGIT);
    addField("functionName", &ProbabilizerConfig::functionName,
             "If specified, a probabilizer function of this name will be created using "
             "the trained probabilizer.");
    addParent<ProcedureConfig>();

    onPostValidate = validate<ProbabilizerConfig,
                              InputQuery,
                              NoGroupByHaving>(&ProbabilizerConfig::trainingData, "probabilizer");
}

struct ProbabilizerRepr {
    std::string style;
    ML::Link_Function link;
    ML::distribution<double> params;
};

DEFINE_STRUCTURE_DESCRIPTION(ProbabilizerRepr);

ProbabilizerReprDescription::
ProbabilizerReprDescription()
{
    addField("style", &ProbabilizerRepr::style,
             "Style of probabilizer to load");
    addField("link", &ProbabilizerRepr::link,
             "Link function for GLZ probabilizer");
    addField("params", &ProbabilizerRepr::params,
             "Parameterization of probabilizer");
}

/*****************************************************************************/
/* PROBABILIZER PROCEDURE                                                     */
/*****************************************************************************/

ProbabilizerProcedure::
ProbabilizerProcedure(MldbServer * owner,
            PolyConfig config,
            const std::function<bool (const Json::Value &)> & onProgress)
    : Procedure(owner)
{
    this->probabilizerConfig = config.params.convert<ProbabilizerConfig>();
}

Any
ProbabilizerProcedure::
getStatus() const
{
    return Any();
}

RunOutput
ProbabilizerProcedure::
run(const ProcedureRunConfig & run,
      const std::function<bool (const Json::Value &)> & onProgress) const
{
    // 1.  Construct an applyFunctionToProcedure object

    // 2.  Extend with our training function

    // 3.  Apply everything to construct the dataset

    // 4.  Apply the dataset

    auto runProcConf = applyRunConfOverProcConf(probabilizerConfig, run);

    auto onProgress2 = [&] (const Json::Value & progress)
        {
            Json::Value value;
            value["dataset"] = progress;
            return onProgress(value);
        };

    SqlExpressionMldbContext context(server);

    auto boundDataset = runProcConf.trainingData.stm->from->bind(context);
    auto score = extractNamedSubSelect("score", runProcConf.trainingData.stm->select);
    auto label = extractNamedSubSelect("label", runProcConf.trainingData.stm->select);
    auto weight = extractNamedSubSelect("weight", runProcConf.trainingData.stm->select);
    if (!weight)
        weight = SqlExpression::parse("1.0");

    // Here is what we need to calculate for each row in the dataset
    std::vector<std::shared_ptr<SqlExpression> > extra
        = { score, label, weight };

    // Build it

    // ...

    std::mutex fvsLock;
    std::vector<std::tuple<RowName, float, float, float> > fvs;

    std::atomic<int> numRows(0);

    auto aggregator = [&] (const MatrixNamedRow & row,
                           const std::vector<ExpressionValue> & extraVals)
        {
            float score = extraVals.at(0).toDouble();
            float label = extraVals.at(1).toDouble();
            float weight = extraVals.at(2).toDouble();
            ++numRows;

            std::unique_lock<std::mutex> guard(fvsLock);

            fvs.emplace_back(row.rowName, score, label, weight);
            return true;
        };

    iterateDataset(SelectExpression(), *boundDataset.dataset, boundDataset.asName,
                   runProcConf.trainingData.stm->when,
                   runProcConf.trainingData.stm->where,
                   extra, aggregator,
                   runProcConf.trainingData.stm->orderBy,
                   runProcConf.trainingData.stm->offset,
                   runProcConf.trainingData.stm->limit);

    int nx = numRows;

    /* Convert to the correct data structures. */

    boost::multi_array<double, 2> outputs(boost::extents[2][nx]);  // value, bias
    ML::distribution<double> correct(nx, 0.0);
    ML::distribution<double> weights(nx, 1.0);

    size_t numTrue = 0;

    for (unsigned x = 0;  x < nx;  ++x) {
        float score, label, weight;
        std::tie(std::ignore, score, label, weight) = fvs[x];

        //cerr << "x = " << x << " score = " << score << " label = " << label
        //     << " weight = " << weight << endl;

        outputs[0][x] = score;
        outputs[1][x] = 1.0;
        correct[x]    = label;
        weights[x]    = weight;
        numTrue      += label == 1;
    }

#if 0
    ML::filter_ostream out("prob-in.txt");

    for (unsigned i = 0;  i < nx;  ++i) {
        out << ML::format("%.15f %.16f %d\n",
                          outputs[0][i],
                          outputs[1][i],
                          correct[i]);

    }
#endif

    double trueOneRate = correct.dotprod(weights) / weights.total();
    double trueZeroRate = 1.0 - trueOneRate;

    double numExamples = nx;
    double sampleOneRate = numTrue / numExamples;
    double sampleZeroRate = 1.0 - sampleOneRate;

    cerr << "trueOneRate = " << trueOneRate
         << " trueZeroRate = " << trueZeroRate
         << " sampleOneRate = " << sampleOneRate
         << " sampleZeroRate = " << sampleZeroRate
         << endl;

    auto link = runProcConf.link;

    ML::Ridge_Regressor regressor;
    ML::distribution<double> probParams
        = ML::run_irls(correct, outputs, weights, link, regressor);

    cerr << "probParams = " << probParams << endl;

    // http://gking.harvard.edu/files/0s.pdf, section 4.2
    // Logistic Regression in Rare Events Data (Gary King and Langche Zeng)

    double correction = -log((1 - trueOneRate) / trueOneRate
                             * sampleOneRate / (1 - sampleOneRate));

    //cerr << "paramBefore = " << probParams[1] << endl;
    //cerr << "correction = " << correction
    //<< endl;

    probParams[1] += correction;

    cerr << "paramAfter = " << probParams[1] << endl;

    ProbabilizerRepr repr;
    repr.style = "glz";
    repr.link = link;
    repr.params = probParams;

    if (!runProcConf.modelFileUrl.toString().empty()) {
        ML::filter_ostream stream(runProcConf.modelFileUrl.toString());
        stream << jsonEncode(repr);
        stream.close();

        if(!runProcConf.functionName.empty()) {
            PolyConfig probaFuncPC;
            probaFuncPC.type = "probabilizer";
            probaFuncPC.id = runProcConf.functionName;
            probaFuncPC.params = ProbabilizeFunctionConfig(runProcConf.modelFileUrl);

            obtainFunction(server, probaFuncPC, onProgress2);
        }
    }

#if 0
    itl->probabilizer.link = link;
    itl->probabilizer.params.resize(1);
    itl->probabilizer.params[0] = probParams;
#endif

    return RunOutput(repr);
}

/*****************************************************************************/
/* PROBABILIZER FUNCTION COLUMN                                                 */
/*****************************************************************************/

DEFINE_STRUCTURE_DESCRIPTION(ProbabilizeFunctionConfig);

ProbabilizeFunctionConfigDescription::
ProbabilizeFunctionConfigDescription()
{
    addField("modelFileUrl", &ProbabilizeFunctionConfig::modelFileUrl,
             "URL of the model file (with extension '.prb') to load. "
             "This file is created by a procedure of type 'probabilizer.train'.");
}

struct ProbabilizeFunction::Itl {
    ML::GLZ_Probabilizer probabilizer;
};

ProbabilizeFunction::
ProbabilizeFunction(MldbServer * owner,
                 PolyConfig config,
                 const std::function<bool (const Json::Value &)> & onProgress)
    : Function(owner)
{
    functionConfig = config.params.convert<ProbabilizeFunctionConfig>();
    itl.reset(new Itl());
    ML::filter_istream stream(functionConfig.modelFileUrl.toString());
    auto repr = jsonDecodeStream<ProbabilizerRepr>(stream);
    itl->probabilizer.link = repr.link;
    itl->probabilizer.params.resize(1);
    itl->probabilizer.params[0] = repr.params;
}

ProbabilizeFunction::
ProbabilizeFunction(MldbServer * owner,
                 const ML::GLZ_Probabilizer & in)
    : Function(owner)
{
    itl.reset(new Itl());
    itl->probabilizer = in;
}

ProbabilizeFunction::
~ProbabilizeFunction()
{
}

Any
ProbabilizeFunction::
getStatus() const
{
    return Any();
}

FunctionOutput
ProbabilizeFunction::
apply(const FunctionApplier & applier,
      const FunctionContext & context) const
{
    ExpressionValue score = context.get<ExpressionValue>("score");
    float prob  = itl->probabilizer.apply(ML::Label_Dist(1, score.toDouble()))[0];
    FunctionOutput result;
    result.set("prob", ExpressionValue(prob, score.getEffectiveTimestamp()));
    return result;
}

FunctionInfo
ProbabilizeFunction::
getFunctionInfo() const
{
    FunctionInfo result;

    result.input.addNumericValue("score");
    result.output.addNumericValue("prob");

    return result;
}

namespace {

static RegisterProcedureType<ProbabilizerProcedure, ProbabilizerConfig>
regProbabilizer(builtinPackage(),
                "probabilizer.train",
                "Trains a model to calibrate a score into a probability",
                "procedures/Probabilizer.md.html");

static RegisterFunctionType<ProbabilizeFunction, ProbabilizeFunctionConfig>
regProbabilizeFunction(builtinPackage(),
                       "probabilizer",
                       "Apply a probability calibration model",
                       "functions/ApplyProbabilizer.md.html");

} // file scope

} // namespace MLDB
} // namespace Datacratic
<commit_msg>[MLDB-1104] fixed the documentation string<commit_after>/** probabilizer.cc
    Jeremy Barnes, 16 December 2014
    Copyright (c) 2014 Datacratic Inc.  All rights reserved.

    This file is part of MLDB. Copyright 2015 Datacratic. All rights reserved.

    Implementation of an algorithm to transform an arbitrary score into a
    calibrated probability.
*/

#include "probabilizer.h"
#include "mldb/ml/jml/probabilizer.h"
#include "mldb/server/mldb_server.h"
#include "mldb/core/dataset.h"
#include "mldb/sql/sql_expression.h"
#include "mldb/plugins/sql_config_validator.h"
#include "mldb/plugins/sql_expression_extractors.h"
#include "mldb/jml/stats/distribution.h"
#include "mldb/jml/utils/guard.h"
#include "mldb/jml/utils/worker_task.h"
#include "mldb/ml/jml/thread_context.h"
#include "mldb/arch/simd_vector.h"
#include "mldb/jml/utils/vector_utils.h"
#include "mldb/types/basic_value_descriptions.h"
#include "mldb/ml/value_descriptions.h"
#include "mldb/types/any_impl.h"
#include "mldb/types/distribution_description.h"
#include "mldb/http/http_exception.h"
#include "mldb/vfs/filter_streams.h"

#include "mldb/server/analytics.h"

using namespace std;
using namespace ML;

//#if (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ <= 6)
#define override
//#endif

namespace Datacratic {
namespace MLDB {

DEFINE_STRUCTURE_DESCRIPTION(ProbabilizerConfig);

ProbabilizerConfigDescription::
ProbabilizerConfigDescription()
{
    addField("trainingData", &ProbabilizerConfig::trainingData,
             "Specification of the data for input to the probabilizer procedure. "
             "The select expression is used to calculate the score for a given dataset row. "
             "Normally this will be the output of a classifier function applied to that row. "
             "The select expression is also used to generate the label.  The label is used to "
             "know the correctness of the probabilizer. "
             "The select expression can also contain an optional weight sub-expression. "
             "A weight of 2.0 is equivalent "
             "to including the identical row twice in the training dataset.  "
             "This can be used to counteract the effect of sampling or weighting "
             "over the dataset that the probabilizer is trained on.  The "
             "default will weight each example the same."
             "The select statement does not support groupby and having clauses. ");
    addField("modelFileUrl", &ProbabilizerConfig::modelFileUrl,
             "URL where the model file (with extension '.prb') should be saved. "
             "This file can be loaded by a function of type 'probabilizer'.");
    addField("link", &ProbabilizerConfig::link,
             "Link function to use.  See documentation.  Generally the "
             "default, PROBIT, is a good place to start for binary "
             "classifification",
             ML::LOGIT);
    addField("functionName", &ProbabilizerConfig::functionName,
             "If specified, a probabilizer function of this name will be created using "
             "the trained probabilizer.");
    addParent<ProcedureConfig>();

    onPostValidate = validate<ProbabilizerConfig,
                              InputQuery,
                              NoGroupByHaving>(&ProbabilizerConfig::trainingData, "probabilizer");
}

struct ProbabilizerRepr {
    std::string style;
    ML::Link_Function link;
    ML::distribution<double> params;
};

DEFINE_STRUCTURE_DESCRIPTION(ProbabilizerRepr);

ProbabilizerReprDescription::
ProbabilizerReprDescription()
{
    addField("style", &ProbabilizerRepr::style,
             "Style of probabilizer to load");
    addField("link", &ProbabilizerRepr::link,
             "Link function for GLZ probabilizer");
    addField("params", &ProbabilizerRepr::params,
             "Parameterization of probabilizer");
}

/*****************************************************************************/
/* PROBABILIZER PROCEDURE                                                     */
/*****************************************************************************/

ProbabilizerProcedure::
ProbabilizerProcedure(MldbServer * owner,
            PolyConfig config,
            const std::function<bool (const Json::Value &)> & onProgress)
    : Procedure(owner)
{
    this->probabilizerConfig = config.params.convert<ProbabilizerConfig>();
}

Any
ProbabilizerProcedure::
getStatus() const
{
    return Any();
}

RunOutput
ProbabilizerProcedure::
run(const ProcedureRunConfig & run,
      const std::function<bool (const Json::Value &)> & onProgress) const
{
    // 1.  Construct an applyFunctionToProcedure object

    // 2.  Extend with our training function

    // 3.  Apply everything to construct the dataset

    // 4.  Apply the dataset

    auto runProcConf = applyRunConfOverProcConf(probabilizerConfig, run);

    auto onProgress2 = [&] (const Json::Value & progress)
        {
            Json::Value value;
            value["dataset"] = progress;
            return onProgress(value);
        };

    SqlExpressionMldbContext context(server);

    auto boundDataset = runProcConf.trainingData.stm->from->bind(context);
    auto score = extractNamedSubSelect("score", runProcConf.trainingData.stm->select);
    auto label = extractNamedSubSelect("label", runProcConf.trainingData.stm->select);
    auto weight = extractNamedSubSelect("weight", runProcConf.trainingData.stm->select);
    if (!weight)
        weight = SqlExpression::parse("1.0");

    // Here is what we need to calculate for each row in the dataset
    std::vector<std::shared_ptr<SqlExpression> > extra
        = { score, label, weight };

    // Build it

    // ...

    std::mutex fvsLock;
    std::vector<std::tuple<RowName, float, float, float> > fvs;

    std::atomic<int> numRows(0);

    auto aggregator = [&] (const MatrixNamedRow & row,
                           const std::vector<ExpressionValue> & extraVals)
        {
            float score = extraVals.at(0).toDouble();
            float label = extraVals.at(1).toDouble();
            float weight = extraVals.at(2).toDouble();
            ++numRows;

            std::unique_lock<std::mutex> guard(fvsLock);

            fvs.emplace_back(row.rowName, score, label, weight);
            return true;
        };

    iterateDataset(SelectExpression(), *boundDataset.dataset, boundDataset.asName,
                   runProcConf.trainingData.stm->when,
                   runProcConf.trainingData.stm->where,
                   extra, aggregator,
                   runProcConf.trainingData.stm->orderBy,
                   runProcConf.trainingData.stm->offset,
                   runProcConf.trainingData.stm->limit);

    int nx = numRows;

    /* Convert to the correct data structures. */

    boost::multi_array<double, 2> outputs(boost::extents[2][nx]);  // value, bias
    ML::distribution<double> correct(nx, 0.0);
    ML::distribution<double> weights(nx, 1.0);

    size_t numTrue = 0;

    for (unsigned x = 0;  x < nx;  ++x) {
        float score, label, weight;
        std::tie(std::ignore, score, label, weight) = fvs[x];

        //cerr << "x = " << x << " score = " << score << " label = " << label
        //     << " weight = " << weight << endl;

        outputs[0][x] = score;
        outputs[1][x] = 1.0;
        correct[x]    = label;
        weights[x]    = weight;
        numTrue      += label == 1;
    }

#if 0
    ML::filter_ostream out("prob-in.txt");

    for (unsigned i = 0;  i < nx;  ++i) {
        out << ML::format("%.15f %.16f %d\n",
                          outputs[0][i],
                          outputs[1][i],
                          correct[i]);

    }
#endif

    double trueOneRate = correct.dotprod(weights) / weights.total();
    double trueZeroRate = 1.0 - trueOneRate;

    double numExamples = nx;
    double sampleOneRate = numTrue / numExamples;
    double sampleZeroRate = 1.0 - sampleOneRate;

    cerr << "trueOneRate = " << trueOneRate
         << " trueZeroRate = " << trueZeroRate
         << " sampleOneRate = " << sampleOneRate
         << " sampleZeroRate = " << sampleZeroRate
         << endl;

    auto link = runProcConf.link;

    ML::Ridge_Regressor regressor;
    ML::distribution<double> probParams
        = ML::run_irls(correct, outputs, weights, link, regressor);

    cerr << "probParams = " << probParams << endl;

    // http://gking.harvard.edu/files/0s.pdf, section 4.2
    // Logistic Regression in Rare Events Data (Gary King and Langche Zeng)

    double correction = -log((1 - trueOneRate) / trueOneRate
                             * sampleOneRate / (1 - sampleOneRate));

    //cerr << "paramBefore = " << probParams[1] << endl;
    //cerr << "correction = " << correction
    //<< endl;

    probParams[1] += correction;

    cerr << "paramAfter = " << probParams[1] << endl;

    ProbabilizerRepr repr;
    repr.style = "glz";
    repr.link = link;
    repr.params = probParams;

    if (!runProcConf.modelFileUrl.toString().empty()) {
        ML::filter_ostream stream(runProcConf.modelFileUrl.toString());
        stream << jsonEncode(repr);
        stream.close();

        if(!runProcConf.functionName.empty()) {
            PolyConfig probaFuncPC;
            probaFuncPC.type = "probabilizer";
            probaFuncPC.id = runProcConf.functionName;
            probaFuncPC.params = ProbabilizeFunctionConfig(runProcConf.modelFileUrl);

            obtainFunction(server, probaFuncPC, onProgress2);
        }
    }

#if 0
    itl->probabilizer.link = link;
    itl->probabilizer.params.resize(1);
    itl->probabilizer.params[0] = probParams;
#endif

    return RunOutput(repr);
}

/*****************************************************************************/
/* PROBABILIZER FUNCTION COLUMN                                                 */
/*****************************************************************************/

DEFINE_STRUCTURE_DESCRIPTION(ProbabilizeFunctionConfig);

ProbabilizeFunctionConfigDescription::
ProbabilizeFunctionConfigDescription()
{
    addField("modelFileUrl", &ProbabilizeFunctionConfig::modelFileUrl,
             "URL of the model file (with extension '.prb') to load. "
             "This file is created by a procedure of type 'probabilizer.train'.");
}

struct ProbabilizeFunction::Itl {
    ML::GLZ_Probabilizer probabilizer;
};

ProbabilizeFunction::
ProbabilizeFunction(MldbServer * owner,
                 PolyConfig config,
                 const std::function<bool (const Json::Value &)> & onProgress)
    : Function(owner)
{
    functionConfig = config.params.convert<ProbabilizeFunctionConfig>();
    itl.reset(new Itl());
    ML::filter_istream stream(functionConfig.modelFileUrl.toString());
    auto repr = jsonDecodeStream<ProbabilizerRepr>(stream);
    itl->probabilizer.link = repr.link;
    itl->probabilizer.params.resize(1);
    itl->probabilizer.params[0] = repr.params;
}

ProbabilizeFunction::
ProbabilizeFunction(MldbServer * owner,
                 const ML::GLZ_Probabilizer & in)
    : Function(owner)
{
    itl.reset(new Itl());
    itl->probabilizer = in;
}

ProbabilizeFunction::
~ProbabilizeFunction()
{
}

Any
ProbabilizeFunction::
getStatus() const
{
    return Any();
}

FunctionOutput
ProbabilizeFunction::
apply(const FunctionApplier & applier,
      const FunctionContext & context) const
{
    ExpressionValue score = context.get<ExpressionValue>("score");
    float prob  = itl->probabilizer.apply(ML::Label_Dist(1, score.toDouble()))[0];
    FunctionOutput result;
    result.set("prob", ExpressionValue(prob, score.getEffectiveTimestamp()));
    return result;
}

FunctionInfo
ProbabilizeFunction::
getFunctionInfo() const
{
    FunctionInfo result;

    result.input.addNumericValue("score");
    result.output.addNumericValue("prob");

    return result;
}

namespace {

static RegisterProcedureType<ProbabilizerProcedure, ProbabilizerConfig>
regProbabilizer(builtinPackage(),
                "probabilizer.train",
                "Trains a model to calibrate a score into a probability",
                "procedures/Probabilizer.md.html");

static RegisterFunctionType<ProbabilizeFunction, ProbabilizeFunctionConfig>
regProbabilizeFunction(builtinPackage(),
                       "probabilizer",
                       "Apply a probability calibration model",
                       "functions/ApplyProbabilizer.md.html");

} // file scope

} // namespace MLDB
} // namespace Datacratic
<|endoftext|>


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

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  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 "RecentFilesMenu.h"

#include "ActiveObjects.h"
#include "DataSource.h"
#include "LoadDataReaction.h"
#include "SaveLoadStateReaction.h"
#include "Utilities.h"

#include <pqSettings.h>

#include <QDebug>
#include <QMenu>
#include <QMessageBox>

#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

#include <string>

namespace tomviz {

namespace{
void get_settings(pugi::xml_document& doc)
{
  QSettings* settings = pqApplicationCore::instance()->settings();
  QString recent = settings->value("recentFiles").toString();
  if (recent.isEmpty() || !doc.load(recent.toUtf8().data()) ||
      !doc.child("tomvizRecentFilesMenu")) {
    doc.append_child("tomvizRecentFilesMenu");
  }
}

QJsonObject loadSettings()
{
  // Load the recent files from our saved state.
  auto settings = pqApplicationCore::instance()->settings();
  auto recent = settings->value("recentFiles").toByteArray();
  auto doc = QJsonDocument::fromJson(recent);
  if (!doc.isNull() && doc.isObject()) {
    return doc.object();
  } else {
    QJsonObject json;
    json["readers"] = QJsonArray();
    return QJsonObject();
  }
}

void saveSettings(QJsonObject json)
{
  // Save recent file list to our saved state, prune lists to be <= 10 entries.
  QJsonArray readers;
  if (json.contains("readers") && json["readers"].isArray()) {
    readers = json["readers"].toArray();
  }
  QJsonArray states;
  if (json.contains("states") && json["states"].isArray()) {
    states = json["states"].toArray();
  }
  if (readers.size() > 10) {
    // We need to prune the list to 10.
    while (readers.size() > 10) {
      readers.removeLast();
    }
  }
  if (states.size() > 10) {
    // We need to prune the list to 10.
    while (states.size() > 10) {
      states.removeLast();
    }
  }
  QJsonDocument doc(json);

  auto settings = pqApplicationCore::instance()->settings();
  settings->setValue("recentFiles", doc.toJson(QJsonDocument::Compact));
}

void save_settings(pugi::xml_document& doc)
{
  Q_UNUSED(doc)
/*
  // trim the list.
  pugi::xml_node root = doc.root();
  std::vector<pugi::xml_node> to_remove;
  int counter = 0;
  for (pugi::xml_node node = root.child("DataReader"); node;
       node = node.next_sibling("DataReader"), counter++) {
    if (counter >= MAX_ITEMS) {
      to_remove.push_back(node);
    }
  }
  counter = 0;
  for (pugi::xml_node node = root.child("State"); node;
       node = node.next_sibling("State"), counter++) {
    if (counter >= MAX_ITEMS) {
      to_remove.push_back(node);
    }
  }
  for (size_t cc = 0; cc < to_remove.size(); cc++) {
    root.remove_child(to_remove[cc]);
  }

  std::ostringstream stream;
  doc.save(stream);
  QSettings* settings = pqApplicationCore::instance()->settings();
  settings->setValue("recentFiles", stream.str().c_str());
*/
}

}

RecentFilesMenu::RecentFilesMenu(QMenu& menu, QObject* p)
  : QObject(p)
{
  connect(&menu, SIGNAL(aboutToShow()), SLOT(aboutToShowMenu()));
}

RecentFilesMenu::~RecentFilesMenu() = default;

void RecentFilesMenu::pushDataReader(DataSource* dataSource)
{
  // Add non-proxy based readers separately.
  auto settings = loadSettings();
  auto readerList = settings["readers"].toArray();
  QJsonObject readerJson;
  readerJson["fileName"] = dataSource->fileName();
  readerJson["stack"] = dataSource->isImageStack();
  if (!dataSource->pvReaderXml().isEmpty()) {
    readerJson["pvXml"] = dataSource->pvReaderXml();
  }
  readerList.push_front(readerJson);
  settings["readers"] = readerList;
  saveSettings(settings);
}

void RecentFilesMenu::pushStateFile(const QString& filename)
{
  pugi::xml_document settings;
  get_settings(settings);

  pugi::xml_node root = settings.root();
  for (pugi::xml_node node = root.child("State"); node;
       node = node.next_sibling("State")) {
    if (filename == node.attribute("filename").as_string("")) {
      root.remove_child(node);
      break;
    }
  }

  pugi::xml_node node = root.prepend_child("State");
  node.append_attribute("filename").set_value(filename.toLatin1().data());
  save_settings(settings);
}

void RecentFilesMenu::aboutToShowMenu()
{
  auto menu = qobject_cast<QMenu*>(sender());
  Q_ASSERT(menu);
  menu->clear();

  auto json = loadSettings();

  // There are no entries, make it clear in the recent files menu.
  if (!json.contains("readers") && !json.contains("states")) {
    auto actn = menu->addAction("Empty");
    actn->setEnabled(false);
    return;
  }

  // We have something, let's populate the recent files and/or state files.
  bool headerAdded = false;
  int index = 0;
  foreach(QJsonValue file, json["readers"].toArray()) {
    if (file.isObject()) {
      auto object = file.toObject();
      if (headerAdded == false) {
        auto actn = menu->addAction("Data files");
        actn->setEnabled(false);
        headerAdded = true;
      }
      bool stack = object["stack"].toBool(false);
      auto actn =
        menu->addAction(QIcon(":/pqWidgets/Icons/pqInspect22.png"),
                        object["fileName"].toString("<bug>"));
      actn->setData(index);
      connect(actn, &QAction::triggered, [this, actn, stack]() {
        dataSourceTriggered(actn, stack);
      });
      ++index;
    }
  }

  headerAdded = false;
  foreach(QJsonValue file, json["states"].toArray()) {
    qDebug() << "File:" << file;
    if (file.isObject()) {
      auto object = file.toObject();
      if (headerAdded == false) {
        auto actn = menu->addAction("State files");
        actn->setEnabled(false);
        headerAdded = true;
      }
      auto actn =
        menu->addAction(QIcon(":/icons/tomviz.png"),
                        object["fileName"].toString("<bug>"));
      actn->setData(object["fileName"].toString("<bug>"));
      connect(actn, SIGNAL(triggered()), SLOT(stateTriggered()));
    }
  }
}

void RecentFilesMenu::dataSourceTriggered(QAction* actn, bool stack)
{
  int index = actn->data().toInt();
  auto json = loadSettings();
  QJsonArray readers;
  if (json["readers"].isArray()) {
    readers = json["readers"].toArray();
  } else {
    return;
  }

  QJsonObject file;
  if (index < readers.size() && readers.at(index).isObject()) {
    file = readers.at(index).toObject();
    // Check the file actually exists, remove it if not.
    if (!QFileInfo::exists(file["fileName"].toString()) && !stack) {
      QMessageBox::warning(
        tomviz::mainWidget(), "Error",
        QString("The file '%1' does not exist").arg(actn->iconText()));
      readers.removeAt(index);
      json["readers"] = readers;
      saveSettings(json);
      return;
    }
    // Otherwise attempt to load the file, and bump it to the top of the list
    // if it is loaded successfully.
    auto ds = LoadDataReaction::loadData(file["fileName"].toString(), true,
                                         false, false);
    readers.removeAt(index);
    if (ds) {
      readers.prepend(file);
    }
    json["readers"] = readers;
    saveSettings(json);
  }
}

void RecentFilesMenu::stateTriggered()
{
  auto actn = qobject_cast<QAction*>(sender());
  Q_ASSERT(actn);

  QString filename = actn->data().toString();

  if (QFileInfo::exists(actn->iconText())) {
    if (SaveLoadStateReaction::loadState(filename)) {
      // the above call will ensure that the file name moves to top of the list
      // since it calls pushStateFile() on success.
      return;
    }
  } else {
    // // If the user tried to open a recent file that no longer exists, remove
    // it from the recent files
    QMessageBox::warning(
      tomviz::mainWidget(), "Error",
      QString("The file '%1' does not exist").arg(actn->iconText()));
  }

  // remove the item from the recent state files list.
  pugi::xml_document settings;
  get_settings(settings);
  pugi::xml_node root = settings.root();
  for (pugi::xml_node node = root.child("State"); node;
       node = node.next_sibling("State")) {
    if (filename == node.attribute("filename").as_string()) {
      root.remove_child(node);
      save_settings(settings);
      break;
    }
  }
}
}
<commit_msg>Filter duplicates and limit max number of recent files entries<commit_after>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  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 "RecentFilesMenu.h"

#include "ActiveObjects.h"
#include "DataSource.h"
#include "LoadDataReaction.h"
#include "SaveLoadStateReaction.h"
#include "Utilities.h"

#include <pqSettings.h>

#include <QDebug>
#include <QMenu>
#include <QMessageBox>

#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

#include <string>

namespace tomviz {

namespace{
void get_settings(pugi::xml_document& doc)
{
  QSettings* settings = pqApplicationCore::instance()->settings();
  QString recent = settings->value("recentFiles").toString();
  if (recent.isEmpty() || !doc.load(recent.toUtf8().data()) ||
      !doc.child("tomvizRecentFilesMenu")) {
    doc.append_child("tomvizRecentFilesMenu");
  }
}

QJsonObject loadSettings()
{
  // Load the recent files from our saved state.
  auto settings = pqApplicationCore::instance()->settings();
  auto recent = settings->value("recentFiles").toByteArray();
  auto doc = QJsonDocument::fromJson(recent);
  if (!doc.isNull() && doc.isObject()) {
    return doc.object();
  } else {
    QJsonObject json;
    json["readers"] = QJsonArray();
    return QJsonObject();
  }
}

void saveSettings(QJsonObject json)
{
  // Save recent file list to our saved state, prune lists to be <= 10 entries.
  QJsonArray readers;
  if (json.contains("readers") && json["readers"].isArray()) {
    readers = json["readers"].toArray();
  }
  QJsonArray states;
  if (json.contains("states") && json["states"].isArray()) {
    states = json["states"].toArray();
  }
  if (readers.size() > 10) {
    // We need to prune the list to 10.
    while (readers.size() > 10) {
      readers.removeLast();
    }
  }
  if (states.size() > 10) {
    // We need to prune the list to 10.
    while (states.size() > 10) {
      states.removeLast();
    }
  }
  json["readers"] = readers;
  json["states"] = states;
  QJsonDocument doc(json);

  auto settings = pqApplicationCore::instance()->settings();
  settings->setValue("recentFiles", doc.toJson(QJsonDocument::Compact));
}

void save_settings(pugi::xml_document& doc)
{
  Q_UNUSED(doc)
/*
  // trim the list.
  pugi::xml_node root = doc.root();
  std::vector<pugi::xml_node> to_remove;
  int counter = 0;
  for (pugi::xml_node node = root.child("DataReader"); node;
       node = node.next_sibling("DataReader"), counter++) {
    if (counter >= MAX_ITEMS) {
      to_remove.push_back(node);
    }
  }
  counter = 0;
  for (pugi::xml_node node = root.child("State"); node;
       node = node.next_sibling("State"), counter++) {
    if (counter >= MAX_ITEMS) {
      to_remove.push_back(node);
    }
  }
  for (size_t cc = 0; cc < to_remove.size(); cc++) {
    root.remove_child(to_remove[cc]);
  }

  std::ostringstream stream;
  doc.save(stream);
  QSettings* settings = pqApplicationCore::instance()->settings();
  settings->setValue("recentFiles", stream.str().c_str());
*/
}

}

RecentFilesMenu::RecentFilesMenu(QMenu& menu, QObject* p)
  : QObject(p)
{
  connect(&menu, SIGNAL(aboutToShow()), SLOT(aboutToShowMenu()));
}

RecentFilesMenu::~RecentFilesMenu() = default;

void RecentFilesMenu::pushDataReader(DataSource* dataSource)
{
  // Add non-proxy based readers separately.
  auto settings = loadSettings();
  auto readerList = settings["readers"].toArray();
  QJsonObject readerJson;
  readerJson["fileName"] = dataSource->fileName();
  readerJson["stack"] = dataSource->isImageStack();
  if (!dataSource->pvReaderXml().isEmpty()) {
    readerJson["pvXml"] = dataSource->pvReaderXml();
  }
  // remove the file if it is already in the list
  for (int i = readerList.size() - 1; i >= 0; --i) {
    if (readerList[i].toObject()["fileName"] == readerJson["fileName"]) {
      readerList.removeAt(i);
    }
  }
  readerList.push_front(readerJson);
  settings["readers"] = readerList;
  saveSettings(settings);
}

void RecentFilesMenu::pushStateFile(const QString& filename)
{
  pugi::xml_document settings;
  get_settings(settings);

  pugi::xml_node root = settings.root();
  for (pugi::xml_node node = root.child("State"); node;
       node = node.next_sibling("State")) {
    if (filename == node.attribute("filename").as_string("")) {
      root.remove_child(node);
      break;
    }
  }

  pugi::xml_node node = root.prepend_child("State");
  node.append_attribute("filename").set_value(filename.toLatin1().data());
  save_settings(settings);
}

void RecentFilesMenu::aboutToShowMenu()
{
  auto menu = qobject_cast<QMenu*>(sender());
  Q_ASSERT(menu);
  menu->clear();

  auto json = loadSettings();

  // There are no entries, make it clear in the recent files menu.
  if (!json.contains("readers") && !json.contains("states")) {
    auto actn = menu->addAction("Empty");
    actn->setEnabled(false);
    return;
  }

  // We have something, let's populate the recent files and/or state files.
  bool headerAdded = false;
  int index = 0;
  foreach(QJsonValue file, json["readers"].toArray()) {
    if (file.isObject()) {
      auto object = file.toObject();
      if (headerAdded == false) {
        auto actn = menu->addAction("Data files");
        actn->setEnabled(false);
        headerAdded = true;
      }
      bool stack = object["stack"].toBool(false);
      auto actn =
        menu->addAction(QIcon(":/pqWidgets/Icons/pqInspect22.png"),
                        object["fileName"].toString("<bug>"));
      actn->setData(index);
      connect(actn, &QAction::triggered, [this, actn, stack]() {
        dataSourceTriggered(actn, stack);
      });
      ++index;
    }
  }

  headerAdded = false;
  foreach(QJsonValue file, json["states"].toArray()) {
    qDebug() << "File:" << file;
    if (file.isObject()) {
      auto object = file.toObject();
      if (headerAdded == false) {
        auto actn = menu->addAction("State files");
        actn->setEnabled(false);
        headerAdded = true;
      }
      auto actn =
        menu->addAction(QIcon(":/icons/tomviz.png"),
                        object["fileName"].toString("<bug>"));
      actn->setData(object["fileName"].toString("<bug>"));
      connect(actn, SIGNAL(triggered()), SLOT(stateTriggered()));
    }
  }
}

void RecentFilesMenu::dataSourceTriggered(QAction* actn, bool stack)
{
  int index = actn->data().toInt();
  auto json = loadSettings();
  QJsonArray readers;
  if (json["readers"].isArray()) {
    readers = json["readers"].toArray();
  } else {
    return;
  }

  QJsonObject file;
  if (index < readers.size() && readers.at(index).isObject()) {
    file = readers.at(index).toObject();
    // Check the file actually exists, remove it if not.
    if (!QFileInfo::exists(file["fileName"].toString()) && !stack) {
      QMessageBox::warning(
        tomviz::mainWidget(), "Error",
        QString("The file '%1' does not exist").arg(actn->iconText()));
      readers.removeAt(index);
      json["readers"] = readers;
      saveSettings(json);
      return;
    }
    // Otherwise attempt to load the file, and bump it to the top of the list
    // if it is loaded successfully.
    auto ds = LoadDataReaction::loadData(file["fileName"].toString(), true,
                                         false, false);
    readers.removeAt(index);
    if (ds) {
      readers.prepend(file);
    }
    json["readers"] = readers;
    saveSettings(json);
  }
}

void RecentFilesMenu::stateTriggered()
{
  auto actn = qobject_cast<QAction*>(sender());
  Q_ASSERT(actn);

  QString filename = actn->data().toString();

  if (QFileInfo::exists(actn->iconText())) {
    if (SaveLoadStateReaction::loadState(filename)) {
      // the above call will ensure that the file name moves to top of the list
      // since it calls pushStateFile() on success.
      return;
    }
  } else {
    // // If the user tried to open a recent file that no longer exists, remove
    // it from the recent files
    QMessageBox::warning(
      tomviz::mainWidget(), "Error",
      QString("The file '%1' does not exist").arg(actn->iconText()));
  }

  // remove the item from the recent state files list.
  pugi::xml_document settings;
  get_settings(settings);
  pugi::xml_node root = settings.root();
  for (pugi::xml_node node = root.child("State"); node;
       node = node.next_sibling("State")) {
    if (filename == node.attribute("filename").as_string()) {
      root.remove_child(node);
      save_settings(settings);
      break;
    }
  }
}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkTypes.h"
#include "BenchTimer.h"
#include "PictureBenchmark.h"
#include "SkCanvas.h"
#include "SkPicture.h"
#include "SkString.h"
#include "picture_utils.h"

namespace sk_tools {

BenchTimer* PictureBenchmark::setupTimer() {
#if SK_SUPPORT_GPU
    PictureRenderer* renderer = getRenderer();

    if (renderer != NULL && renderer->isUsingGpuDevice()) {
        return SkNEW_ARGS(BenchTimer, (renderer->getGLContext()));
    } else {
        return SkNEW_ARGS(BenchTimer, (NULL));
    }
#else
    return SkNEW_ARGS(BenchTimer, (NULL));
#endif
}

void PipePictureBenchmark::run(SkPicture* pict) {
    SkASSERT(pict);
    if (NULL == pict) {
        return;
    }

    fRenderer.init(pict);

    // We throw this away to remove first time effects (such as paging in this
    // program)
    fRenderer.render();
    fRenderer.resetState();

    BenchTimer* timer = this->setupTimer();
    double wall_time = 0, truncated_wall_time = 0;
#if SK_SUPPORT_GPU
    double gpu_time = 0;
#endif

    for (int i = 0; i < fRepeats; ++i) {
        timer->start();
        fRenderer.render();
        timer->end();
        fRenderer.resetState();

        wall_time += timer->fWall;
        truncated_wall_time += timer->fTruncatedWall;
#if SK_SUPPORT_GPU
        if (fRenderer.isUsingGpuDevice()) {
            gpu_time += timer->fGpu;
        }
#endif
    }

    SkString result;
    result.printf("pipe: msecs = %6.2f", wall_time / fRepeats);
#if SK_SUPPORT_GPU
    if (fRenderer.isUsingGpuDevice()) {
        result.appendf(" gmsecs = %6.2f", gpu_time / fRepeats);
    }
#endif
    result.appendf("\n");
    sk_tools::print_msg(result.c_str());

    fRenderer.end();
    SkDELETE(timer);
}

void RecordPictureBenchmark::run(SkPicture* pict) {
    SkASSERT(pict);
    if (NULL == pict) {
        return;
    }

    BenchTimer* timer = setupTimer();
    double wall_time = 0, truncated_wall_time = 0;

    for (int i = 0; i < fRepeats + 1; ++i) {
        SkPicture replayer;
        SkCanvas* recorder = replayer.beginRecording(pict->width(), pict->height());

        timer->start();
        recorder->drawPicture(*pict);
        timer->end();

        // We want to ignore first time effects
        if (i > 0) {
            wall_time += timer->fWall;
            truncated_wall_time += timer->fTruncatedWall;
        }
    }

    SkString result;
    result.printf("record: msecs = %6.5f\n", wall_time / fRepeats);
    sk_tools::print_msg(result.c_str());

    SkDELETE(timer);
}

void SimplePictureBenchmark::run(SkPicture* pict) {
    SkASSERT(pict);
    if (NULL == pict) {
        return;
    }

    fRenderer.init(pict);

    // We throw this away to remove first time effects (such as paging in this
    // program)
    fRenderer.render();
    fRenderer.resetState();

    BenchTimer* timer = this->setupTimer();
    double wall_time = 0, truncated_wall_time = 0;
#if SK_SUPPORT_GPU
    double gpu_time = 0;
#endif

    for (int i = 0; i < fRepeats; ++i) {
        timer->start();
        fRenderer.render();
        timer->end();
        fRenderer.resetState();

        wall_time += timer->fWall;
        truncated_wall_time += timer->fTruncatedWall;
#if SK_SUPPORT_GPU
        if (fRenderer.isUsingGpuDevice()) {
            gpu_time += timer->fGpu;
        }
#endif
    }

    SkString result;
    result.printf("simple: msecs = %6.2f", wall_time / fRepeats);
#if SK_SUPPORT_GPU
    if (fRenderer.isUsingGpuDevice()) {
        result.appendf(" gmsecs = %6.2f", gpu_time / fRepeats);
    }
#endif
    result.appendf("\n");
    sk_tools::print_msg(result.c_str());

    fRenderer.end();
    SkDELETE(timer);
}

void TiledPictureBenchmark::run(SkPicture* pict) {
    SkASSERT(pict);
    if (NULL == pict) {
        return;
    }

    fRenderer.init(pict);

    // We throw this away to remove first time effects (such as paging in this
    // program)
    fRenderer.drawTiles();
    fRenderer.resetState();

    BenchTimer* timer = setupTimer();
    double wall_time = 0, truncated_wall_time = 0;
#if SK_SUPPORT_GPU
    double gpu_time = 0;
#endif

    for (int i = 0; i < fRepeats; ++i) {
        timer->start();
        fRenderer.drawTiles();
        timer->end();
        fRenderer.resetState();

        wall_time += timer->fWall;
        truncated_wall_time += timer->fTruncatedWall;
#if SK_SUPPORT_GPU
        if (fRenderer.isUsingGpuDevice()) {
            gpu_time += timer->fGpu;
        }
#endif
    }

    SkString result;
    if (fRenderer.getTileMinPowerOf2Width() > 0) {
        result.printf("%i_pow2tiles_%iminx%i: msecs = %6.2f", fRenderer.numTiles(),
                      fRenderer.getTileMinPowerOf2Width(), fRenderer.getTileHeight(),
                      wall_time / fRepeats);
    } else {
        result.printf("%i_tiles_%ix%i: msecs = %6.2f", fRenderer.numTiles(),
                      fRenderer.getTileWidth(), fRenderer.getTileHeight(), wall_time / fRepeats);
    }
#if SK_SUPPORT_GPU
    if (fRenderer.isUsingGpuDevice()) {
        result.appendf(" gmsecs = %6.2f", gpu_time / fRepeats);
    }
#endif
    result.appendf("\n");
    sk_tools::print_msg(result.c_str());

    fRenderer.end();
    SkDELETE(timer);
}

void UnflattenPictureBenchmark::run(SkPicture* pict) {
    SkASSERT(pict);
    if (NULL == pict) {
        return;
    }

    BenchTimer* timer = setupTimer();
    double wall_time = 0, truncated_wall_time = 0;

    for (int i = 0; i < fRepeats + 1; ++i) {
        SkPicture replayer;
        SkCanvas* recorder = replayer.beginRecording(pict->width(), pict->height());

        recorder->drawPicture(*pict);

        timer->start();
        replayer.endRecording();
        timer->end();

        // We want to ignore first time effects
        if (i > 0) {
            wall_time += timer->fWall;
            truncated_wall_time += timer->fTruncatedWall;
        }
    }

    SkString result;
    result.printf("unflatten: msecs = %6.4f\n", wall_time / fRepeats);
    sk_tools::print_msg(result.c_str());

    SkDELETE(timer);
}

}
<commit_msg>Change picture record benchmark to include begin/end record in timings and make the source picture draw itself into record canvas, so it records the draws instead of directly copying the picture. Review URL: https://codereview.appspot.com/6501045<commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkTypes.h"
#include "BenchTimer.h"
#include "PictureBenchmark.h"
#include "SkCanvas.h"
#include "SkPicture.h"
#include "SkString.h"
#include "picture_utils.h"

namespace sk_tools {

BenchTimer* PictureBenchmark::setupTimer() {
#if SK_SUPPORT_GPU
    PictureRenderer* renderer = getRenderer();

    if (renderer != NULL && renderer->isUsingGpuDevice()) {
        return SkNEW_ARGS(BenchTimer, (renderer->getGLContext()));
    } else {
        return SkNEW_ARGS(BenchTimer, (NULL));
    }
#else
    return SkNEW_ARGS(BenchTimer, (NULL));
#endif
}

void PipePictureBenchmark::run(SkPicture* pict) {
    SkASSERT(pict);
    if (NULL == pict) {
        return;
    }

    fRenderer.init(pict);

    // We throw this away to remove first time effects (such as paging in this
    // program)
    fRenderer.render();
    fRenderer.resetState();

    BenchTimer* timer = this->setupTimer();
    double wall_time = 0, truncated_wall_time = 0;
#if SK_SUPPORT_GPU
    double gpu_time = 0;
#endif

    for (int i = 0; i < fRepeats; ++i) {
        timer->start();
        fRenderer.render();
        timer->end();
        fRenderer.resetState();

        wall_time += timer->fWall;
        truncated_wall_time += timer->fTruncatedWall;
#if SK_SUPPORT_GPU
        if (fRenderer.isUsingGpuDevice()) {
            gpu_time += timer->fGpu;
        }
#endif
    }

    SkString result;
    result.printf("pipe: msecs = %6.2f", wall_time / fRepeats);
#if SK_SUPPORT_GPU
    if (fRenderer.isUsingGpuDevice()) {
        result.appendf(" gmsecs = %6.2f", gpu_time / fRepeats);
    }
#endif
    result.appendf("\n");
    sk_tools::print_msg(result.c_str());

    fRenderer.end();
    SkDELETE(timer);
}

void RecordPictureBenchmark::run(SkPicture* pict) {
    SkASSERT(pict);
    if (NULL == pict) {
        return;
    }

    BenchTimer* timer = setupTimer();
    double wall_time = 0, truncated_wall_time = 0;

    for (int i = 0; i < fRepeats + 1; ++i) {
        SkPicture replayer;

        timer->start();
        SkCanvas* recorder = replayer.beginRecording(pict->width(), pict->height());
        pict->draw(recorder);
        replayer.endRecording();
        timer->end();

        // We want to ignore first time effects
        if (i > 0) {
            wall_time += timer->fWall;
            truncated_wall_time += timer->fTruncatedWall;
        }
    }

    SkString result;
    result.printf("record: msecs = %6.5f\n", wall_time / fRepeats);
    sk_tools::print_msg(result.c_str());

    SkDELETE(timer);
}

void SimplePictureBenchmark::run(SkPicture* pict) {
    SkASSERT(pict);
    if (NULL == pict) {
        return;
    }

    fRenderer.init(pict);

    // We throw this away to remove first time effects (such as paging in this
    // program)
    fRenderer.render();
    fRenderer.resetState();

    BenchTimer* timer = this->setupTimer();
    double wall_time = 0, truncated_wall_time = 0;
#if SK_SUPPORT_GPU
    double gpu_time = 0;
#endif

    for (int i = 0; i < fRepeats; ++i) {
        timer->start();
        fRenderer.render();
        timer->end();
        fRenderer.resetState();

        wall_time += timer->fWall;
        truncated_wall_time += timer->fTruncatedWall;
#if SK_SUPPORT_GPU
        if (fRenderer.isUsingGpuDevice()) {
            gpu_time += timer->fGpu;
        }
#endif
    }

    SkString result;
    result.printf("simple: msecs = %6.2f", wall_time / fRepeats);
#if SK_SUPPORT_GPU
    if (fRenderer.isUsingGpuDevice()) {
        result.appendf(" gmsecs = %6.2f", gpu_time / fRepeats);
    }
#endif
    result.appendf("\n");
    sk_tools::print_msg(result.c_str());

    fRenderer.end();
    SkDELETE(timer);
}

void TiledPictureBenchmark::run(SkPicture* pict) {
    SkASSERT(pict);
    if (NULL == pict) {
        return;
    }

    fRenderer.init(pict);

    // We throw this away to remove first time effects (such as paging in this
    // program)
    fRenderer.drawTiles();
    fRenderer.resetState();

    BenchTimer* timer = setupTimer();
    double wall_time = 0, truncated_wall_time = 0;
#if SK_SUPPORT_GPU
    double gpu_time = 0;
#endif

    for (int i = 0; i < fRepeats; ++i) {
        timer->start();
        fRenderer.drawTiles();
        timer->end();
        fRenderer.resetState();

        wall_time += timer->fWall;
        truncated_wall_time += timer->fTruncatedWall;
#if SK_SUPPORT_GPU
        if (fRenderer.isUsingGpuDevice()) {
            gpu_time += timer->fGpu;
        }
#endif
    }

    SkString result;
    if (fRenderer.getTileMinPowerOf2Width() > 0) {
        result.printf("%i_pow2tiles_%iminx%i: msecs = %6.2f", fRenderer.numTiles(),
                      fRenderer.getTileMinPowerOf2Width(), fRenderer.getTileHeight(),
                      wall_time / fRepeats);
    } else {
        result.printf("%i_tiles_%ix%i: msecs = %6.2f", fRenderer.numTiles(),
                      fRenderer.getTileWidth(), fRenderer.getTileHeight(), wall_time / fRepeats);
    }
#if SK_SUPPORT_GPU
    if (fRenderer.isUsingGpuDevice()) {
        result.appendf(" gmsecs = %6.2f", gpu_time / fRepeats);
    }
#endif
    result.appendf("\n");
    sk_tools::print_msg(result.c_str());

    fRenderer.end();
    SkDELETE(timer);
}

void UnflattenPictureBenchmark::run(SkPicture* pict) {
    SkASSERT(pict);
    if (NULL == pict) {
        return;
    }

    BenchTimer* timer = setupTimer();
    double wall_time = 0, truncated_wall_time = 0;

    for (int i = 0; i < fRepeats + 1; ++i) {
        SkPicture replayer;
        SkCanvas* recorder = replayer.beginRecording(pict->width(), pict->height());

        recorder->drawPicture(*pict);

        timer->start();
        replayer.endRecording();
        timer->end();

        // We want to ignore first time effects
        if (i > 0) {
            wall_time += timer->fWall;
            truncated_wall_time += timer->fTruncatedWall;
        }
    }

    SkString result;
    result.printf("unflatten: msecs = %6.4f\n", wall_time / fRepeats);
    sk_tools::print_msg(result.c_str());

    SkDELETE(timer);
}

}
<|endoftext|>