<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <osl/file.h>
#include <tools/vcompat.hxx>
#include <tools/debug.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/tempfile.hxx>
#include <ucbhelper/content.hxx>
#include <vcl/graph.hxx>
#include <vcl/gfxlink.hxx>
#include <vcl/cvtgrf.hxx>
#include <com/sun/star/ucb/CommandAbortedException.hpp>

GfxLink::GfxLink() :
    meType      ( GFX_LINK_TYPE_NONE ),
    mpBuf       ( NULL ),
    mpSwap      ( NULL ),
    mnBufSize   ( 0 ),
    mnUserId    ( 0UL ),
    mpImpData   ( new ImpGfxLink )
{
}

GfxLink::GfxLink( const GfxLink& rGfxLink ) :
    mpImpData( new ImpGfxLink )
{
    ImplCopy( rGfxLink );
}

GfxLink::GfxLink( sal_uInt8* pBuf, sal_uInt32 nSize, GfxLinkType nType, sal_Bool bOwns ) :
    mpImpData( new ImpGfxLink )
{
    DBG_ASSERT( (pBuf != NULL && nSize) || (!bOwns && nSize == 0),
                "GfxLink::GfxLink(): empty/NULL buffer given" );

    meType = nType;
    mnBufSize = nSize;
    mpSwap = NULL;
    mnUserId = 0UL;

    if( bOwns )
        mpBuf = new ImpBuffer( pBuf );
    else if( nSize )
    {
        mpBuf = new ImpBuffer( nSize );
        memcpy( mpBuf->mpBuffer, pBuf, nSize );
    }
    else
        mpBuf = NULL;
}

GfxLink::~GfxLink()
{
    if( mpBuf && !( --mpBuf->mnRefCount ) )
        delete mpBuf;

    if( mpSwap && !( --mpSwap->mnRefCount ) )
        delete mpSwap;

    delete mpImpData;
}

GfxLink& GfxLink::operator=( const GfxLink& rGfxLink )
{
    if( &rGfxLink != this )
    {
        if ( mpBuf && !( --mpBuf->mnRefCount ) )
            delete mpBuf;

        if( mpSwap && !( --mpSwap->mnRefCount ) )
            delete mpSwap;

        ImplCopy( rGfxLink );
    }

    return *this;
}

sal_Bool GfxLink::IsEqual( const GfxLink& rGfxLink ) const
{
    sal_Bool bIsEqual = sal_False;

    if ( ( mnBufSize == rGfxLink.mnBufSize ) && ( meType == rGfxLink.meType ) )
    {
        const sal_uInt8* pSource = GetData();
        const sal_uInt8* pDest = rGfxLink.GetData();
        sal_uInt32 nSourceSize = GetDataSize();
        sal_uInt32 nDestSize = rGfxLink.GetDataSize();
        if ( pSource && pDest && ( nSourceSize == nDestSize ) )
        {
            bIsEqual = memcmp( pSource, pDest, nSourceSize ) == 0;
        }
        else if ( ( pSource == 0 ) && ( pDest == 0 ) )
            bIsEqual = sal_True;
    }
    return bIsEqual;
}

void GfxLink::ImplCopy( const GfxLink& rGfxLink )
{
    mnBufSize = rGfxLink.mnBufSize;
    meType = rGfxLink.meType;
    mpBuf = rGfxLink.mpBuf;
    mpSwap = rGfxLink.mpSwap;
    mnUserId = rGfxLink.mnUserId;
    *mpImpData = *rGfxLink.mpImpData;

    if( mpBuf )
        mpBuf->mnRefCount++;

    if( mpSwap )
        mpSwap->mnRefCount++;
}

GfxLinkType GfxLink::GetType() const
{
    return meType;
}

sal_Bool GfxLink::IsNative() const
{
    return( meType >= GFX_LINK_FIRST_NATIVE_ID && meType <= GFX_LINK_LAST_NATIVE_ID );
}

sal_uInt32 GfxLink::GetDataSize() const
{
    return mnBufSize;
}

const sal_uInt8* GfxLink::GetData() const
{
    if( IsSwappedOut() )
        ( (GfxLink*) this )->SwapIn();

    return( mpBuf ? mpBuf->mpBuffer : NULL );
}

const Size& GfxLink::GetPrefSize() const
{
    return mpImpData->maPrefSize;
}

void GfxLink::SetPrefSize( const Size& rPrefSize )
{
    mpImpData->maPrefSize = rPrefSize;
    mpImpData->mbPrefSizeValid = true;
}

bool GfxLink::IsPrefSizeValid()
{
    return mpImpData->mbPrefSizeValid;
}

const MapMode& GfxLink::GetPrefMapMode() const
{
    return mpImpData->maPrefMapMode;
}

void GfxLink::SetPrefMapMode( const MapMode& rPrefMapMode )
{
    mpImpData->maPrefMapMode = rPrefMapMode;
    mpImpData->mbPrefMapModeValid = true;
}

bool GfxLink::IsPrefMapModeValid()
{
    return mpImpData->mbPrefMapModeValid;
}

sal_Bool GfxLink::LoadNative( Graphic& rGraphic )
{
    sal_Bool bRet = sal_False;

    if( IsNative() && mnBufSize )
    {
        const sal_uInt8* pData = GetData();

        if( pData )
        {
            SvMemoryStream  aMemStm;
            sal_uLong           nCvtType;

            aMemStm.SetBuffer( (char*) pData, mnBufSize, sal_False, mnBufSize );

            switch( meType )
            {
                case( GFX_LINK_TYPE_NATIVE_GIF ): nCvtType = CVT_GIF; break;
                case( GFX_LINK_TYPE_NATIVE_JPG ): nCvtType = CVT_JPG; break;
                case( GFX_LINK_TYPE_NATIVE_PNG ): nCvtType = CVT_PNG; break;
                case( GFX_LINK_TYPE_NATIVE_TIF ): nCvtType = CVT_TIF; break;
                case( GFX_LINK_TYPE_NATIVE_WMF ): nCvtType = CVT_WMF; break;
                case( GFX_LINK_TYPE_NATIVE_MET ): nCvtType = CVT_MET; break;
                case( GFX_LINK_TYPE_NATIVE_PCT ): nCvtType = CVT_PCT; break;
                case( GFX_LINK_TYPE_NATIVE_SVG ): nCvtType = CVT_SVG; break;

                default: nCvtType = CVT_UNKNOWN; break;
            }

            if( nCvtType && ( GraphicConverter::Import( aMemStm, rGraphic, nCvtType ) == ERRCODE_NONE ) )
                bRet = sal_True;
        }
    }

    return bRet;
}

void GfxLink::SwapOut()
{
    if( !IsSwappedOut() && mpBuf )
    {
        mpSwap = new ImpSwap( mpBuf->mpBuffer, mnBufSize );

        if( !mpSwap->IsSwapped() )
        {
            delete mpSwap;
            mpSwap = NULL;
        }
        else
        {
            if( !( --mpBuf->mnRefCount ) )
                delete mpBuf;

            mpBuf = NULL;
        }
    }
}

void GfxLink::SwapIn()
{
    if( IsSwappedOut() )
    {
        mpBuf = new ImpBuffer( mpSwap->GetData() );

        if( !( --mpSwap->mnRefCount ) )
            delete mpSwap;

        mpSwap = NULL;
    }
}

sal_Bool GfxLink::ExportNative( SvStream& rOStream ) const
{
    if( GetDataSize() )
    {
        if( IsSwappedOut() )
            mpSwap->WriteTo( rOStream );
        else if( GetData() )
            rOStream.Write( GetData(), GetDataSize() );
    }

    return ( rOStream.GetError() == ERRCODE_NONE );
}

SvStream& operator<<( SvStream& rOStream, const GfxLink& rGfxLink )
{
    VersionCompat* pCompat = new VersionCompat( rOStream, STREAM_WRITE, 2 );

    // Version 1
    rOStream << (sal_uInt16) rGfxLink.GetType() << rGfxLink.GetDataSize() << rGfxLink.GetUserId();

    // Version 2
    rOStream << rGfxLink.GetPrefSize() << rGfxLink.GetPrefMapMode();

    delete pCompat;

    if( rGfxLink.GetDataSize() )
    {
        if( rGfxLink.IsSwappedOut() )
            rGfxLink.mpSwap->WriteTo( rOStream );
        else if( rGfxLink.GetData() )
            rOStream.Write( rGfxLink.GetData(), rGfxLink.GetDataSize() );
    }

    return rOStream;
}

SvStream& operator>>( SvStream& rIStream, GfxLink& rGfxLink)
{
    Size            aSize;
    MapMode         aMapMode;
    sal_uInt32      nSize;
    sal_uInt32      nUserId;
    sal_uInt16          nType;
    sal_uInt8*          pBuf;
    bool            bMapAndSizeValid( false );
    VersionCompat*  pCompat = new VersionCompat( rIStream, STREAM_READ );

    // Version 1
    rIStream >> nType >> nSize >> nUserId;

    if( pCompat->GetVersion() >= 2 )
    {
        rIStream >> aSize >> aMapMode;
        bMapAndSizeValid = true;
    }

    delete pCompat;

    pBuf = new sal_uInt8[ nSize ];
    rIStream.Read( pBuf, nSize );

    rGfxLink = GfxLink( pBuf, nSize, (GfxLinkType) nType, sal_True );
    rGfxLink.SetUserId( nUserId );

    if( bMapAndSizeValid )
    {
        rGfxLink.SetPrefSize( aSize );
        rGfxLink.SetPrefMapMode( aMapMode );
    }

    return rIStream;
}

ImpSwap::ImpSwap( sal_uInt8* pData, sal_uLong nDataSize ) :
            mnDataSize( nDataSize ),
            mnRefCount( 1UL )
{
    if( pData && mnDataSize )
    {
        ::utl::TempFile aTempFile;

        maURL = aTempFile.GetURL();
        if( !maURL.isEmpty() )
        {
            SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
            if( pOStm )
            {
                pOStm->Write( pData, mnDataSize );
                sal_Bool bError = ( ERRCODE_NONE != pOStm->GetError() );
                delete pOStm;

                if( bError )
                {
                    osl_removeFile( maURL.pData );
                    maURL = String();
                }
            }
        }
    }
}

ImpSwap::~ImpSwap()
{
    if( IsSwapped() )
        osl_removeFile( maURL.pData );
}

sal_uInt8* ImpSwap::GetData() const
{
    sal_uInt8* pData;

    if( IsSwapped() )
    {
        SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE );
        if( pIStm )
        {
            pData = new sal_uInt8[ mnDataSize ];
            pIStm->Read( pData, mnDataSize );
            sal_Bool bError = ( ERRCODE_NONE != pIStm->GetError() );
            delete pIStm;

            if( bError )
                delete[] pData, pData = NULL;
        }
        else
            pData = NULL;
    }
    else
        pData = NULL;

    return pData;
}

void ImpSwap::WriteTo( SvStream& rOStm ) const
{
    sal_uInt8* pData = GetData();

    if( pData )
    {
        rOStm.Write( pData, mnDataSize );
        delete[] pData;
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Resolves: #i119965# Fixed saving slides where temporary files...<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <osl/file.h>
#include <tools/vcompat.hxx>
#include <tools/debug.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/tempfile.hxx>
#include <ucbhelper/content.hxx>
#include <vcl/graph.hxx>
#include <vcl/gfxlink.hxx>
#include <vcl/cvtgrf.hxx>
#include <com/sun/star/ucb/CommandAbortedException.hpp>

GfxLink::GfxLink() :
    meType      ( GFX_LINK_TYPE_NONE ),
    mpBuf       ( NULL ),
    mpSwap      ( NULL ),
    mnBufSize   ( 0 ),
    mnUserId    ( 0UL ),
    mpImpData   ( new ImpGfxLink )
{
}

GfxLink::GfxLink( const GfxLink& rGfxLink ) :
    mpImpData( new ImpGfxLink )
{
    ImplCopy( rGfxLink );
}

GfxLink::GfxLink( sal_uInt8* pBuf, sal_uInt32 nSize, GfxLinkType nType, sal_Bool bOwns ) :
    mpImpData( new ImpGfxLink )
{
    DBG_ASSERT( (pBuf != NULL && nSize) || (!bOwns && nSize == 0),
                "GfxLink::GfxLink(): empty/NULL buffer given" );

    meType = nType;
    mnBufSize = nSize;
    mpSwap = NULL;
    mnUserId = 0UL;

    if( bOwns )
        mpBuf = new ImpBuffer( pBuf );
    else if( nSize )
    {
        mpBuf = new ImpBuffer( nSize );
        memcpy( mpBuf->mpBuffer, pBuf, nSize );
    }
    else
        mpBuf = NULL;
}

GfxLink::~GfxLink()
{
    if( mpBuf && !( --mpBuf->mnRefCount ) )
        delete mpBuf;

    if( mpSwap && !( --mpSwap->mnRefCount ) )
        delete mpSwap;

    delete mpImpData;
}

GfxLink& GfxLink::operator=( const GfxLink& rGfxLink )
{
    if( &rGfxLink != this )
    {
        if ( mpBuf && !( --mpBuf->mnRefCount ) )
            delete mpBuf;

        if( mpSwap && !( --mpSwap->mnRefCount ) )
            delete mpSwap;

        ImplCopy( rGfxLink );
    }

    return *this;
}

sal_Bool GfxLink::IsEqual( const GfxLink& rGfxLink ) const
{
    sal_Bool bIsEqual = sal_False;

    if ( ( mnBufSize == rGfxLink.mnBufSize ) && ( meType == rGfxLink.meType ) )
    {
        const sal_uInt8* pSource = GetData();
        const sal_uInt8* pDest = rGfxLink.GetData();
        sal_uInt32 nSourceSize = GetDataSize();
        sal_uInt32 nDestSize = rGfxLink.GetDataSize();
        if ( pSource && pDest && ( nSourceSize == nDestSize ) )
        {
            bIsEqual = memcmp( pSource, pDest, nSourceSize ) == 0;
        }
        else if ( ( pSource == 0 ) && ( pDest == 0 ) )
            bIsEqual = sal_True;
    }
    return bIsEqual;
}

void GfxLink::ImplCopy( const GfxLink& rGfxLink )
{
    mnBufSize = rGfxLink.mnBufSize;
    meType = rGfxLink.meType;
    mpBuf = rGfxLink.mpBuf;
    mpSwap = rGfxLink.mpSwap;
    mnUserId = rGfxLink.mnUserId;
    *mpImpData = *rGfxLink.mpImpData;

    if( mpBuf )
        mpBuf->mnRefCount++;

    if( mpSwap )
        mpSwap->mnRefCount++;
}

GfxLinkType GfxLink::GetType() const
{
    return meType;
}

sal_Bool GfxLink::IsNative() const
{
    return( meType >= GFX_LINK_FIRST_NATIVE_ID && meType <= GFX_LINK_LAST_NATIVE_ID );
}

sal_uInt32 GfxLink::GetDataSize() const
{
    return mnBufSize;
}

const sal_uInt8* GfxLink::GetData() const
{
    if( IsSwappedOut() )
        ( (GfxLink*) this )->SwapIn();

    return( mpBuf ? mpBuf->mpBuffer : NULL );
}

const Size& GfxLink::GetPrefSize() const
{
    return mpImpData->maPrefSize;
}

void GfxLink::SetPrefSize( const Size& rPrefSize )
{
    mpImpData->maPrefSize = rPrefSize;
    mpImpData->mbPrefSizeValid = true;
}

bool GfxLink::IsPrefSizeValid()
{
    return mpImpData->mbPrefSizeValid;
}

const MapMode& GfxLink::GetPrefMapMode() const
{
    return mpImpData->maPrefMapMode;
}

void GfxLink::SetPrefMapMode( const MapMode& rPrefMapMode )
{
    mpImpData->maPrefMapMode = rPrefMapMode;
    mpImpData->mbPrefMapModeValid = true;
}

bool GfxLink::IsPrefMapModeValid()
{
    return mpImpData->mbPrefMapModeValid;
}

sal_Bool GfxLink::LoadNative( Graphic& rGraphic )
{
    sal_Bool bRet = sal_False;

    if( IsNative() && mnBufSize )
    {
        const sal_uInt8* pData = GetData();

        if( pData )
        {
            SvMemoryStream  aMemStm;
            sal_uLong           nCvtType;

            aMemStm.SetBuffer( (char*) pData, mnBufSize, sal_False, mnBufSize );

            switch( meType )
            {
                case( GFX_LINK_TYPE_NATIVE_GIF ): nCvtType = CVT_GIF; break;
                case( GFX_LINK_TYPE_NATIVE_JPG ): nCvtType = CVT_JPG; break;
                case( GFX_LINK_TYPE_NATIVE_PNG ): nCvtType = CVT_PNG; break;
                case( GFX_LINK_TYPE_NATIVE_TIF ): nCvtType = CVT_TIF; break;
                case( GFX_LINK_TYPE_NATIVE_WMF ): nCvtType = CVT_WMF; break;
                case( GFX_LINK_TYPE_NATIVE_MET ): nCvtType = CVT_MET; break;
                case( GFX_LINK_TYPE_NATIVE_PCT ): nCvtType = CVT_PCT; break;
                case( GFX_LINK_TYPE_NATIVE_SVG ): nCvtType = CVT_SVG; break;

                default: nCvtType = CVT_UNKNOWN; break;
            }

            if( nCvtType && ( GraphicConverter::Import( aMemStm, rGraphic, nCvtType ) == ERRCODE_NONE ) )
                bRet = sal_True;
        }
    }

    return bRet;
}

void GfxLink::SwapOut()
{
    if( !IsSwappedOut() && mpBuf )
    {
        mpSwap = new ImpSwap( mpBuf->mpBuffer, mnBufSize );

        if( !mpSwap->IsSwapped() )
        {
            delete mpSwap;
            mpSwap = NULL;
        }
        else
        {
            if( !( --mpBuf->mnRefCount ) )
                delete mpBuf;

            mpBuf = NULL;
        }
    }
}

void GfxLink::SwapIn()
{
    if( IsSwappedOut() )
    {
        mpBuf = new ImpBuffer( mpSwap->GetData() );

        if( !( --mpSwap->mnRefCount ) )
            delete mpSwap;

        mpSwap = NULL;
    }
}

sal_Bool GfxLink::ExportNative( SvStream& rOStream ) const
{
    if( GetDataSize() )
    {
        if( IsSwappedOut() )
            mpSwap->WriteTo( rOStream );
        else if( GetData() )
            rOStream.Write( GetData(), GetDataSize() );
    }

    return ( rOStream.GetError() == ERRCODE_NONE );
}

SvStream& operator<<( SvStream& rOStream, const GfxLink& rGfxLink )
{
    VersionCompat* pCompat = new VersionCompat( rOStream, STREAM_WRITE, 2 );

    // Version 1
    rOStream << (sal_uInt16) rGfxLink.GetType() << rGfxLink.GetDataSize() << rGfxLink.GetUserId();

    // Version 2
    rOStream << rGfxLink.GetPrefSize() << rGfxLink.GetPrefMapMode();

    delete pCompat;

    if( rGfxLink.GetDataSize() )
    {
        if( rGfxLink.IsSwappedOut() )
            rGfxLink.mpSwap->WriteTo( rOStream );
        else if( rGfxLink.GetData() )
            rOStream.Write( rGfxLink.GetData(), rGfxLink.GetDataSize() );
    }

    return rOStream;
}

SvStream& operator>>( SvStream& rIStream, GfxLink& rGfxLink)
{
    Size            aSize;
    MapMode         aMapMode;
    sal_uInt32      nSize;
    sal_uInt32      nUserId;
    sal_uInt16          nType;
    sal_uInt8*          pBuf;
    bool            bMapAndSizeValid( false );
    VersionCompat*  pCompat = new VersionCompat( rIStream, STREAM_READ );

    // Version 1
    rIStream >> nType >> nSize >> nUserId;

    if( pCompat->GetVersion() >= 2 )
    {
        rIStream >> aSize >> aMapMode;
        bMapAndSizeValid = true;
    }

    delete pCompat;

    pBuf = new sal_uInt8[ nSize ];
    rIStream.Read( pBuf, nSize );

    rGfxLink = GfxLink( pBuf, nSize, (GfxLinkType) nType, sal_True );
    rGfxLink.SetUserId( nUserId );

    if( bMapAndSizeValid )
    {
        rGfxLink.SetPrefSize( aSize );
        rGfxLink.SetPrefMapMode( aMapMode );
    }

    return rIStream;
}

ImpSwap::ImpSwap( sal_uInt8* pData, sal_uLong nDataSize ) :
            mnDataSize( nDataSize ),
            mnRefCount( 1UL )
{
    if( pData && mnDataSize )
    {
        ::utl::TempFile aTempFile;

        maURL = aTempFile.GetURL();
        if( !maURL.isEmpty() )
        {
            SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
            if( pOStm )
            {
                pOStm->Write( pData, mnDataSize );
                sal_Bool bError = ( ERRCODE_NONE != pOStm->GetError() );
                delete pOStm;

                if( bError )
                {
                    osl_removeFile( maURL.pData );
                    maURL = String();
                }
            }
        }
    }
}

ImpSwap::~ImpSwap()
{
    if( IsSwapped() )
        osl_removeFile( maURL.pData );
}

sal_uInt8* ImpSwap::GetData() const
{
    sal_uInt8* pData;

    if( IsSwapped() )
    {
        SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( maURL, STREAM_READWRITE );
        if( pIStm )
        {
            pData = new sal_uInt8[ mnDataSize ];
            pIStm->Read( pData, mnDataSize );
            sal_Bool bError = ( ERRCODE_NONE != pIStm->GetError() );
            sal_Size nActReadSize = pIStm->Tell();
            if (nActReadSize != mnDataSize)
            {
                bError = sal_True;
            }
            delete pIStm;

            if( bError )
                delete[] pData, pData = NULL;
        }
        else
            pData = NULL;
    }
    else
        pData = NULL;

    return pData;
}

void ImpSwap::WriteTo( SvStream& rOStm ) const
{
    sal_uInt8* pData = GetData();

    if( pData )
    {
        rOStm.Write( pData, mnDataSize );
        delete[] pData;
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>// The following two definitions are required by llvm/Support/DataTypes.h
#define __STDC_LIMIT_MACROS 1
#define __STDC_CONSTANT_MACROS 1

#include "llvm/Support/CommandLine.h"
#include "ofpx.h"
#include "ofp/yaml/decoder.h"
#include "ofp/yaml/encoder.h"
#include <iostream>
#include <fstream>

//-------------------------------------//
// d e c o d e _ o n e _ m e s s a g e //
//-------------------------------------//

static int decode_one_message(const ofp::Message *message) {
  ofp::yaml::Decoder decoder{message};

  if (!decoder.error().empty()) {
    std::cerr << "Error: Decode failed: " << decoder.error() << '\n';
    return 128;
  }

  std::cout << decoder.result();

  // Now double-check the result by re-encoding the message. We should obtain
  // the original message contents.

  ofp::yaml::Encoder encoder{decoder.result()};

  if (!encoder.error().empty()) {
    std::cerr << "Error: Decode succeeded but encode failed: " << encoder.error() << '\n';
    return 129;
  }

  if (encoder.size() != message->size()) {
    std::cerr << "Error: Encode yielded different size data: " << encoder.size() << " vs. " << message->size() << '\n' << ofp::RawDataToHex(encoder.data(), encoder.size()) << '\n';
    return 130;
  }

  if (std::memcmp(message->data(), encoder.data(), encoder.size()) != 0) {
    std::cerr << "Error: Encode yielded different data:\n" << ofp::RawDataToHex(encoder.data(), encoder.size()) << '\n' << ofp::RawDataToHex(message->data(), message->size()) << '\n';
    //return 131;
  }

  return 0;
}

//-------------------------------//
// d e c o d e _ m e s s a g e s //
//-------------------------------//

static int decode_messages(std::ifstream &input) {
  ofp::Message message{nullptr};

  while (input) {
    char *msg = (char *)message.mutableData(sizeof(ofp::Header));

    input.read(msg, sizeof(ofp::Header));
    if (input) {
      // Read the rest of the message.

      size_t msgLen = message.header()->length();
      if (msgLen < sizeof(ofp::Header)) {
        std::cerr << "Error: Message length " << msgLen
                  << " bytes is too short." << '\n';
        return 2;
      }

      msg = (char *)message.mutableData(msgLen);
      input.read(msg + sizeof(ofp::Header),
                 ofp::Signed_cast(msgLen - sizeof(ofp::Header)));

      if (input) {
        message.transmogrify();

        int result = decode_one_message(&message);
        if (result) {
          return result;
        }

      } else if (!input.eof()) {
        // There was an error reading the message body.
        std::cerr << "Error: Only " << input.gcount() << " bytes read of body."
                  << '\n' << input.rdstate();
        return 1;
      }

    } else if (!input.eof()) {
      // There was an error reading the message header.
      std::cerr << "Error: Only " << input.gcount() << " bytes read of header."
                << '\n' << input.rdstate();
      return 1;
    }
  }

  return 0;
}

//-----------------------//
// d e c o d e _ f i l e //
//-----------------------//

static int decode_file(const std::string &filename) {
  std::ifstream input{filename, std::ifstream::binary};
  int result = -1;

  if (input) {
    result = decode_messages(input);
    input.close();
  } else {
    std::cerr << "Error: opening file " << filename << '\n';
  }

  return result;
}

//-------------------------//
// d e c o d e _ f i l e s //
//-------------------------//

static int decode_files(const std::vector<std::string> &files) {
  for (const std::string &filename : files) {
    int result = decode_file(filename);
    if (result) {
      return result;
    }
  }

  return 0;
}

//-------------------//
// o f p x _ p i n g //
//-------------------//

int ofpx_decode(int argc, char **argv) {
  using namespace llvm;

  cl::list<std::string> inputFiles(cl::Positional, cl::desc("<Input files>"),
                                   cl::OneOrMore);

  cl::ParseCommandLineOptions(argc, argv);

  return decode_files(inputFiles);
}
<commit_msg>Changes to error reporting in ofpx_decode.<commit_after>// The following two definitions are required by llvm/Support/DataTypes.h
#define __STDC_LIMIT_MACROS 1
#define __STDC_CONSTANT_MACROS 1

#include "llvm/Support/CommandLine.h"
#include "ofpx.h"
#include "ofp/yaml/decoder.h"
#include "ofp/yaml/encoder.h"
#include <iostream>
#include <fstream>

//-------------------------------------//
// d e c o d e _ o n e _ m e s s a g e //
//-------------------------------------//

static int decode_one_message(const ofp::Message *message) {
  ofp::yaml::Decoder decoder{message};

  if (!decoder.error().empty()) {
    std::cerr << "Error: Decode failed: " << decoder.error() << '\n';
    return 128;
  }

  std::cout << decoder.result();

  // Now double-check the result by re-encoding the message. We should obtain
  // the original message contents.

  ofp::yaml::Encoder encoder{decoder.result()};

  if (!encoder.error().empty()) {
    std::cerr << "Error: Decode succeeded but encode failed: " << encoder.error() << '\n';
    //return 129;
  }

  if (encoder.size() != message->size()) {
    std::cerr << "Error: Encode yielded different size data: " << encoder.size() << " vs. " << message->size() << '\n' << ofp::RawDataToHex(encoder.data(), encoder.size()) << '\n' << ofp::RawDataToHex(message->data(), message->size()) << '\n';
    //return 130;
  } else if (std::memcmp(message->data(), encoder.data(), encoder.size()) != 0) {
    std::cerr << "Error: Encode yielded different data:\n" << ofp::RawDataToHex(encoder.data(), encoder.size()) << '\n' << ofp::RawDataToHex(message->data(), message->size()) << '\n';
    //return 131;
  }

  return 0;
}

//-------------------------------//
// d e c o d e _ m e s s a g e s //
//-------------------------------//

static int decode_messages(std::ifstream &input) {
  ofp::Message message{nullptr};

  while (input) {
    char *msg = (char *)message.mutableData(sizeof(ofp::Header));

    input.read(msg, sizeof(ofp::Header));
    if (input) {
      // Read the rest of the message.

      size_t msgLen = message.header()->length();
      if (msgLen < sizeof(ofp::Header)) {
        std::cerr << "Error: Message length " << msgLen
                  << " bytes is too short." << '\n';
        return 2;
      }

      msg = (char *)message.mutableData(msgLen);
      input.read(msg + sizeof(ofp::Header),
                 ofp::Signed_cast(msgLen - sizeof(ofp::Header)));

      if (input) {
        message.transmogrify();

        int result = decode_one_message(&message);
        if (result) {
          return result;
        }

      } else if (!input.eof()) {
        // There was an error reading the message body.
        std::cerr << "Error: Only " << input.gcount() << " bytes read of body."
                  << '\n' << input.rdstate();
        return 1;
      }

    } else if (!input.eof()) {
      // There was an error reading the message header.
      std::cerr << "Error: Only " << input.gcount() << " bytes read of header."
                << '\n' << input.rdstate();
      return 1;
    }
  }

  return 0;
}

//-----------------------//
// d e c o d e _ f i l e //
//-----------------------//

static int decode_file(const std::string &filename) {
  std::ifstream input{filename, std::ifstream::binary};
  int result = -1;

  if (input) {
    result = decode_messages(input);
    input.close();
  } else {
    std::cerr << "Error: opening file " << filename << '\n';
  }

  return result;
}

//-------------------------//
// d e c o d e _ f i l e s //
//-------------------------//

static int decode_files(const std::vector<std::string> &files) {
  for (const std::string &filename : files) {
    int result = decode_file(filename);
    if (result) {
      return result;
    }
  }

  return 0;
}

//-------------------//
// o f p x _ p i n g //
//-------------------//

int ofpx_decode(int argc, char **argv) {
  using namespace llvm;

  cl::list<std::string> inputFiles(cl::Positional, cl::desc("<Input files>"),
                                   cl::OneOrMore);

  cl::ParseCommandLineOptions(argc, argv);

  return decode_files(inputFiles);
}
<|endoftext|>


<commit_before>/*
 * katch/examples/run_tch_ea_query.cpp
 *
 *
 * This file is part of
 *
 * KaTCH -- Karlsruhe Time-Dependent Contraction Hierarchies
 *
 * Copyright (C) 2015
 *
 * Institut fuer Theroretische Informatik,
 * Karlsruher Institut fuer Technology (KIT),
 * 76131 Karlsruhe, Germany
 *
 * Author: Gernot Veit Batz
 *
 *
 *
 * KaTCH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * KaTCH 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 Affero General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with Contraction Hierarchies; see the file COPYING;
 * if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <iostream>
#include <stdlib.h>
#include <string>

#include "util/misc.h"
#include "io/btch_format.h"
#include "io/demands_format.h"
#include "io/edge_info.h"
#include "io/tch_format.h"
#include "query/tch_ea_query.h"

int main(int argc, char** argv)
{
    using Graph = katch::TchEaQuery::Graph;
    using EdgeInfo = katch::EdgeInfo<Graph::TTF>;

    const char* binary_name = argv[0];

    if ( argc != 3 )
    {
        std::cerr
            << std::endl
            << "USAGE: " << binary_name
            << " <.btch input file> <.demands input file>" << std::endl
            << std::endl;

        return EXIT_FAILURE;
    }

    const std::string btch_input_file_name(argv[1]);
    const std::string demands_input_file_name(argv[2]);

    std::vector<EdgeInfo> edge_list = katch::btch_format::read_edges<EdgeInfo>(btch_input_file_name);

    Graph graph(std::move(edge_list));
    KATCH_STATUS("Graph has " << graph.get_n_nodes() << " nodes, " << graph.get_n_edges() << " edges.\n");

    std::vector<katch::demands_format::Demand> demands = katch::demands_format::read(demands_input_file_name);
    katch::TchEaQuery query(std::move(graph));

    KATCH_STATUS("Running " << demands.size() << " queries...");

    double max_abs_error = 0.0;
    double max_rel_error = 0.0;
    double total_abs_error = 0.0;
    double total_rel_error = 0.0;

    double max_abs_error_expand = 0.0;
    double max_rel_error_expand = 0.0;
    double total_abs_error_expand = 0.0;
    double total_rel_error_expand = 0.0;

    double total_route_extraction_and_expansion_time = 0.0;

    auto t1 = katch::util::time_stamp();

    for ( const auto& demand : demands )
    {
        // obtain travel time from start to destination
        const double t_arr = query.one_to_one(demand._start, demand._destination, demand._t_dep);

        // compute absolute and relative errors of obtained travel time
        const double abs_error = fabs(t_arr - demand._t_arr);
        max_abs_error = std::max(max_abs_error, abs_error);
        total_abs_error += abs_error;

        const double rel_error = abs_error / demand._t_arr;
        max_rel_error = std::max(max_rel_error, rel_error);
        total_rel_error += rel_error;

        auto t_expand_begin = katch::util::time_stamp();

        // obtain up-down-path from start to destination (requires katch::TchEaQuery::one_to_one called first)
        const katch::TchEaQuery::Path up_down_path = query.get_up_down_path(demand._destination);

        // expand up-down-path to obtain path in the original road network
        const katch::TchEaQuery::Path original_path = query.expand_path(up_down_path);

        auto t_expand_end = katch::util::time_stamp();
        total_route_extraction_and_expansion_time += katch::util::get_duration_in_seconds(t_expand_begin, t_expand_end);

        // compute absolute and relative errors of the travel time of the expanded path
        const double t_arr_expand = original_path.get_t_arr(original_path.get_n_edges());

        const double abs_error_expand = fabs(t_arr_expand - demand._t_arr);
        max_abs_error_expand = std::max(max_abs_error_expand, abs_error_expand);
        total_abs_error_expand += abs_error_expand;

        const double rel_error_expand = abs_error_expand / demand._t_arr;
        max_rel_error_expand = std::max(max_rel_error_expand, rel_error_expand);
        total_rel_error_expand += rel_error_expand;
    }

    auto t2 = katch::util::time_stamp();

    KATCH_CONTINUE_STATUS(" OK\n");

    KATCH_STATUS("avg. running time (including route extraction) = " << ((katch::util::get_duration_in_seconds(t1, t2) / double(demands.size())) *1000.0) << " msec\n");
    KATCH_STATUS("avg. running time (without route extraction)   = " << (((katch::util::get_duration_in_seconds(t1, t2) - total_route_extraction_and_expansion_time) / double(demands.size())) *1000.0) << " msec\n");
    KATCH_STATUS("\n");
    KATCH_STATUS("Error of computed arrival time\n");
    KATCH_STATUS("------------------------------\n");
    KATCH_STATUS("max. rel. error = " << (max_rel_error * 100.0) << " %\n");
    KATCH_STATUS("avg. rel. error = " << ((total_rel_error / double(demands.size())) * 100.0) << " %\n");

    KATCH_STATUS("\n");
    KATCH_STATUS("Error of arrival time of expanded route\n");
    KATCH_STATUS("---------------------------------------\n");
    KATCH_STATUS("max. rel. error = " << (max_rel_error_expand  * 100.0) << " %\n");
    KATCH_STATUS("avg. rel. error = " << ((total_rel_error_expand / double(demands.size())) * 100.0) << " %\n");
//    KATCH_STATUS("avg. running time = " << ((katch::util::get_duration_in_seconds(t1, t2)  / double(demands.size())) *1000.0) << " msec\n");

    return EXIT_SUCCESS;
}
<commit_msg>removed blind include<commit_after>/*
 * katch/examples/run_tch_ea_query.cpp
 *
 *
 * This file is part of
 *
 * KaTCH -- Karlsruhe Time-Dependent Contraction Hierarchies
 *
 * Copyright (C) 2015
 *
 * Institut fuer Theroretische Informatik,
 * Karlsruher Institut fuer Technology (KIT),
 * 76131 Karlsruhe, Germany
 *
 * Author: Gernot Veit Batz
 *
 *
 *
 * KaTCH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * KaTCH 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 Affero General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with Contraction Hierarchies; see the file COPYING;
 * if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <iostream>
#include <stdlib.h>
#include <string>

#include "util/misc.h"
#include "io/btch_format.h"
#include "io/demands_format.h"
#include "io/edge_info.h"
#include "query/tch_ea_query.h"

int main(int argc, char** argv)
{
    using Graph = katch::TchEaQuery::Graph;
    using EdgeInfo = katch::EdgeInfo<Graph::TTF>;

    const char* binary_name = argv[0];

    if ( argc != 3 )
    {
        std::cerr
            << std::endl
            << "USAGE: " << binary_name
            << " <.btch input file> <.demands input file>" << std::endl
            << std::endl;

        return EXIT_FAILURE;
    }

    const std::string btch_input_file_name(argv[1]);
    const std::string demands_input_file_name(argv[2]);

    std::vector<EdgeInfo> edge_list = katch::btch_format::read_edges<EdgeInfo>(btch_input_file_name);

    Graph graph(std::move(edge_list));
    KATCH_STATUS("Graph has " << graph.get_n_nodes() << " nodes, " << graph.get_n_edges() << " edges.\n");

    std::vector<katch::demands_format::Demand> demands = katch::demands_format::read(demands_input_file_name);
    katch::TchEaQuery query(std::move(graph));

    KATCH_STATUS("Running " << demands.size() << " queries...");

    double max_abs_error = 0.0;
    double max_rel_error = 0.0;
    double total_abs_error = 0.0;
    double total_rel_error = 0.0;

    double max_abs_error_expand = 0.0;
    double max_rel_error_expand = 0.0;
    double total_abs_error_expand = 0.0;
    double total_rel_error_expand = 0.0;

    double total_route_extraction_and_expansion_time = 0.0;

    auto t1 = katch::util::time_stamp();

    for ( const auto& demand : demands )
    {
        // obtain travel time from start to destination
        const double t_arr = query.one_to_one(demand._start, demand._destination, demand._t_dep);

        // compute absolute and relative errors of obtained travel time
        const double abs_error = fabs(t_arr - demand._t_arr);
        max_abs_error = std::max(max_abs_error, abs_error);
        total_abs_error += abs_error;

        const double rel_error = abs_error / demand._t_arr;
        max_rel_error = std::max(max_rel_error, rel_error);
        total_rel_error += rel_error;

        auto t_expand_begin = katch::util::time_stamp();

        // obtain up-down-path from start to destination (requires katch::TchEaQuery::one_to_one called first)
        const katch::TchEaQuery::Path up_down_path = query.get_up_down_path(demand._destination);

        // expand up-down-path to obtain path in the original road network
        const katch::TchEaQuery::Path original_path = query.expand_path(up_down_path);

        auto t_expand_end = katch::util::time_stamp();
        total_route_extraction_and_expansion_time += katch::util::get_duration_in_seconds(t_expand_begin, t_expand_end);

        // compute absolute and relative errors of the travel time of the expanded path
        const double t_arr_expand = original_path.get_t_arr(original_path.get_n_edges());

        const double abs_error_expand = fabs(t_arr_expand - demand._t_arr);
        max_abs_error_expand = std::max(max_abs_error_expand, abs_error_expand);
        total_abs_error_expand += abs_error_expand;

        const double rel_error_expand = abs_error_expand / demand._t_arr;
        max_rel_error_expand = std::max(max_rel_error_expand, rel_error_expand);
        total_rel_error_expand += rel_error_expand;
    }

    auto t2 = katch::util::time_stamp();

    KATCH_CONTINUE_STATUS(" OK\n");

    KATCH_STATUS("avg. running time (including route extraction) = " << ((katch::util::get_duration_in_seconds(t1, t2) / double(demands.size())) *1000.0) << " msec\n");
    KATCH_STATUS("avg. running time (without route extraction)   = " << (((katch::util::get_duration_in_seconds(t1, t2) - total_route_extraction_and_expansion_time) / double(demands.size())) *1000.0) << " msec\n");
    KATCH_STATUS("\n");
    KATCH_STATUS("Error of computed arrival time\n");
    KATCH_STATUS("------------------------------\n");
    KATCH_STATUS("max. rel. error = " << (max_rel_error * 100.0) << " %\n");
    KATCH_STATUS("avg. rel. error = " << ((total_rel_error / double(demands.size())) * 100.0) << " %\n");

    KATCH_STATUS("\n");
    KATCH_STATUS("Error of arrival time of expanded route\n");
    KATCH_STATUS("---------------------------------------\n");
    KATCH_STATUS("max. rel. error = " << (max_rel_error_expand  * 100.0) << " %\n");
    KATCH_STATUS("avg. rel. error = " << ((total_rel_error_expand / double(demands.size())) * 100.0) << " %\n");
//    KATCH_STATUS("avg. running time = " << ((katch::util::get_duration_in_seconds(t1, t2)  / double(demands.size())) *1000.0) << " msec\n");

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <set>
#include <list>
#include <iterator>

#include "otc/otcli.h"
#include "otc/tree_operations.h"
#include "otc/tree_iter.h"
using namespace otc;
using std::vector;
using std::unique_ptr;
using std::set;
using std::list;
using std::map;
using std::string;
using namespace otc;

typedef TreeMappedWithSplits Tree_t;

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::set<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::list<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

struct RSplit
{
  set<long> in;
  set<long> out;
  set<long> all;
  RSplit() = default;
  RSplit(const set<long>& i, const set<long>& a)
    :in(i),all(a)
  {
    out = set_difference_as_set(all,in);
    assert(in.size() + out.size() == all.size());
  }
};

std::ostream& operator<<(std::ostream& o, const RSplit& s)
{
  o<<s.in<<" | "<<s.out;
  return o;
}

/// Merge components c1 and c2 and return the component name that survived
long merge_components(long c1, long c2, map<long,long>& component, map<long,list<long>>& elements)
{
  if (elements[c2].size() > elements[c1].size())
    std::swap(c1,c2);

  for(long i:elements[c2])
    component[i] = c1;

  elements[c1].splice(elements[c1].begin(), elements[c2]);

  return c1;
}

bool empty_intersection(const set<long>& x, const set<long>& y)
{
  std::set<long>::const_iterator i = x.begin();
  std::set<long>::const_iterator j = y.begin();
  while (i != x.end() && j != y.end())
  {
    if (*i == *j)
      return false;
    else if (*i < *j)
      ++i;
    else
      ++j;
  }
  return true;
}

/// Construct a tree with all the splits mentioned, and return a null pointer if this is not possible
unique_ptr<Tree_t> BUILD(const std::set<long>& tips, const vector<RSplit>& splits)
{
  std::unique_ptr<Tree_t> tree(new Tree_t());
  tree->createRoot();

  // 1. First handle trees of size 1 and 2
  if (tips.size() == 1)
  {
    tree->getRoot()->setOttId(*tips.begin());
    return tree;
  }
  else if (tips.size() == 2)
  {
    auto Node1a = tree->createChild(tree->getRoot());
    auto Node1b = tree->createChild(tree->getRoot());
    auto it = tips.begin();
    Node1a->setOttId(*it++);
    Node1b->setOttId(*it++);
    return tree;
  }

  // 2. Initialize the mapping from elements to components
  map<long,long> component;      // element   -> component
  map<long,list<long>> elements; // component -> elements
  for(long i: tips)
  {
    component[i] = i;
    elements[i].push_back(i);
  }

  // 3. For each split, all the leaves in the include group must be in the same component
  for(const auto& split: splits)
  {
    long c1 = -1;
    for(long i: split.in)
    {
      long c2 = component[i];
      if (c1 != -1 and c1 != c2)
	merge_components(c1,c2,component,elements);
      c1 = component[i];
    }
  }

  // 4. If we can't subdivide the leaves in any way, then the splits are not consistent, so return failure
  long first = *tips.begin();
  if (elements[component[first]].size() == tips.size())
    return {};

  // 5. Create the set of tips in each connected component
  map<long,set<long>> subtips;
  for(long c: tips)
  {
    if (c != component[c]) continue;

    set<long>& s = subtips[c];
    for(long l: elements[c])
      s.insert(l);
  }

  // 6. Determine the splits that are not satisfied yet and go into each component
  map<long,vector<RSplit>> subsplits;
  for(const auto& split: splits)
  {
    long first = *split.in.begin();
    long c = component[first];

    // if none of the exclude group are in the component, then the split is satisfied by the top-level partition.
    if (empty_intersection(split.out, subtips[c])) continue;

    subsplits[c].push_back(split);
  }

  // 7. Recursively solve the sub-problems of the partition components
  for(const auto& x: subtips)
  {
    auto subtree = BUILD(x.second, subsplits[x.first]);
    if (not subtree) return {};

    tree->addSubtree(tree->getRoot(), *subtree);
  }

  return tree;
}

/// Run the BUILD algorithm on the first n splits
unique_ptr<Tree_t> BUILD(const std::set<long>& tips, const vector<RSplit>& splits, int n)
{
  vector<RSplit> splits2;
  for(int i=0;i<n;i++)
    splits2.push_back(splits[i]);
  return BUILD(tips,splits2);
}

/// Copy node names from taxonomy to tree based on ott ids, and copy the root name also
void add_names(unique_ptr<Tree_t>& tree, const unique_ptr<Tree_t>& taxonomy)
{
  clearAndfillDesIdSets(*tree);

  for(auto n1: iter_post(*tree))
    for(auto n2: iter_post(*taxonomy))
      if (n1->getData().desIds == n2->getData().desIds)
	n1->setName( n2->getName());
}

/// Get the list of splits, and add them one at a time if they are consistent with previous splits
unique_ptr<Tree_t> combine(const vector<unique_ptr<Tree_t>>& trees)
{
  // Standardize names to 0..n-1 for this subproblem
  const auto& taxonomy = trees.back();
  auto all_leaves = taxonomy->getRoot()->getData().desIds;

  // 1. Find splits in order of input trees
  vector<RSplit> splits;
  for(const auto& tree: trees)
  {
    auto root = tree->getRoot();
    const auto leafTaxa = root->getData().desIds;

    for(const auto& leaf: set_difference_as_set(leafTaxa, all_leaves))
      throw OTCError()<<"OTT Id "<<leaf<<" not in taxonomy!";

    for(auto nd: iter_post_const(*tree))
    {
      const auto& descendants = nd->getData().desIds;
      RSplit split{descendants, leafTaxa};
      if (split.in.size()>1 and split.out.size())
      	splits.push_back(split);
    }
  }

  // 2. Add splits sequentially if they are consistent with previous splits.
  vector<RSplit> consistent;
  for(const auto& split: splits)
  {
    consistent.push_back(split);
    auto result = BUILD(all_leaves, consistent);
    if (not result)
    {
      consistent.pop_back();
      LOG(DEBUG)<<"Reject: "<<split<<"\n";
    }
    else
      LOG(DEBUG)<<"Keep:   "<<split<<"\n";
  }

  // 3. Construct final tree and add names
  auto tree = BUILD(all_leaves, consistent);
  add_names(tree, taxonomy);
  return tree;
}

bool handleRequireOttIds(OTCLI & otCLI, const std::string & arg)
{
  if (arg == "true" or arg == "yes" or arg == "True" or arg == "Yes")
    otCLI.getParsingRules().requireOttIds = true;
  else if (arg == "false" or arg == "no" or arg == "False" or arg == "no")
    otCLI.getParsingRules().requireOttIds = false;
  else
    return false;

  return true;
}

bool handlePruneUnrecognizedTips(OTCLI & otCLI, const std::string & arg)
{
  if (arg == "true" or arg == "yes" or arg == "True" or arg == "Yes")
    otCLI.getParsingRules().pruneUnrecognizedInputTips = true;
  else if (arg == "false" or arg == "no" or arg == "False" or arg == "no")
    otCLI.getParsingRules().pruneUnrecognizedInputTips = false;
  else
    return false;

  return true;
}

bool synthesize_taxonomy = false;

bool handleSynthesizeTaxonomy(OTCLI &, const std::string & arg)
{
  if (arg == "true" or "yes" or "True" or "Yes")
    synthesize_taxonomy = true;
  else if (arg == "false" or "no" or "False" or "no")
    synthesize_taxonomy = false;
  else
    return false;

  return true;
}

unique_ptr<Tree_t> make_unresolved_tree(const vector<unique_ptr<Tree_t>>& trees, bool use_ids)
{
  std::unique_ptr<Tree_t> tree(new Tree_t());
  tree->createRoot();

  if (use_ids)
  {
    map<long,string> names;
    for(const auto& tree: trees)
      for(auto nd: iter_pre_const(*tree))
	if (nd->isTip())
	{
	  long id = nd->getOttId();
	  auto it = names.find(id);
	  if (it == names.end())
	    names[id] = nd->getName();
	}

    for(const auto& n: names)
    {
      auto node = tree->createChild(tree->getRoot());
      node->setOttId(n.first);
      node->setName(n.second);
    }
    clearAndfillDesIdSets(*tree);
  }
  else
  {
    set<string> names;
    for(const auto& tree: trees)
      for(auto nd: iter_pre_const(*tree))
	if (nd->isTip())
	  names.insert(nd->getName());

    for(const auto& n: names)
    {
      auto node = tree->createChild(tree->getRoot());
      node->setName(n);
    }
  }

  return tree;
}

string newick(const Tree_t &t)
{
  std::ostringstream s;
  writeTreeAsNewick(s, t);
  return s.str();
}

int main(int argc, char *argv[]) {
    OTCLI otCLI("otc-solve-subproblem",
                "takes at series of tree files. Each is treated as a subproblem.\n",
		"subproblem.tre");

    otCLI.addFlag('o',
		  "Require OTT ids.  Defaults to true",
		  handleRequireOttIds,
		  true);
    otCLI.addFlag('p',
		  "Prune unrecognized tips.  Defaults to false",
		  handlePruneUnrecognizedTips,
		  true);
    otCLI.addFlag('T',
		  "Synthesize unresolved taxonomy from all mentioned taxa.  Defaults to false",
		  handleSynthesizeTaxonomy,
		  false);

    vector<unique_ptr<Tree_t>> trees;
    auto get = [&trees](OTCLI &, unique_ptr<Tree_t> nt) {trees.push_back(std::move(nt)); return true;};

    if (argc < 2)
	throw OTCError("No subproblem provided!");

    // I think multiple subproblem files are essentially concatenated.
    // Is it possible to read a single subproblem from cin?
    if (treeProcessingMain<Tree_t>(otCLI, argc, argv, get, nullptr, 1))
      std::exit(1);

    bool requireOttIds = otCLI.getParsingRules().requireOttIds;
    if (synthesize_taxonomy)
    {
      trees.push_back(make_unresolved_tree(trees,requireOttIds));
      LOG(DEBUG)<<"taxonomy = "<<newick(*trees.back())<<"\n";
    }

    // Add fake Ott Ids to tips and compute desIds
    if (not requireOttIds)
    {
      auto& taxonomy = trees.back();

      // 1. Compute mapping from name -> id
      long id = 1;
      map<string,long> name_to_id;
      for(auto nd: iter_pre(*taxonomy))
	if (nd->isTip())
	{
	  string name = nd->getName();
	  if (not name.size())
	    throw OTCError()<<"Taxonomy tip has no label or OTT id!";
	  auto it = name_to_id.find(name);
	  if (it != name_to_id.end())
	    throw OTCError()<<"Tip label '"<<name<<"' occurs twice in taxonomy!";
	  name_to_id[name] = id++;
	}

      // 2. Set ids
      for(auto& tree: trees)
	for(auto nd: iter_post(*tree))
	  if (nd->isTip())
	  {
	    string name = nd->getName();
	    if (not name.size())
	      throw OTCError()<<"Tip has no label or OTT id!";
	    auto it = name_to_id.find(name);
	    if (it == name_to_id.end())
	      throw OTCError()<<"Can't find label '"<<name<<"' in taxonomy!";
	    auto id = it->second;
	    nd->setOttId(id);
	  }

      // 3. Compute DesIds.
      for(auto& tree: trees)
	clearAndfillDesIdSets(*tree);
    }

    auto tree = combine(trees);

    writeTreeAsNewick(std::cout, *tree);
    std::cout<<"\n";
}
<commit_msg>Remove dead code.<commit_after>#include <algorithm>
#include <set>
#include <list>
#include <iterator>

#include "otc/otcli.h"
#include "otc/tree_operations.h"
#include "otc/tree_iter.h"
using namespace otc;
using std::vector;
using std::unique_ptr;
using std::set;
using std::list;
using std::map;
using std::string;
using namespace otc;

typedef TreeMappedWithSplits Tree_t;

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::set<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::list<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

struct RSplit
{
  set<long> in;
  set<long> out;
  set<long> all;
  RSplit() = default;
  RSplit(const set<long>& i, const set<long>& a)
    :in(i),all(a)
  {
    out = set_difference_as_set(all,in);
    assert(in.size() + out.size() == all.size());
  }
};

std::ostream& operator<<(std::ostream& o, const RSplit& s)
{
  o<<s.in<<" | "<<s.out;
  return o;
}

/// Merge components c1 and c2 and return the component name that survived
long merge_components(long c1, long c2, map<long,long>& component, map<long,list<long>>& elements)
{
  if (elements[c2].size() > elements[c1].size())
    std::swap(c1,c2);

  for(long i:elements[c2])
    component[i] = c1;

  elements[c1].splice(elements[c1].begin(), elements[c2]);

  return c1;
}

bool empty_intersection(const set<long>& x, const set<long>& y)
{
  std::set<long>::const_iterator i = x.begin();
  std::set<long>::const_iterator j = y.begin();
  while (i != x.end() && j != y.end())
  {
    if (*i == *j)
      return false;
    else if (*i < *j)
      ++i;
    else
      ++j;
  }
  return true;
}

/// Construct a tree with all the splits mentioned, and return a null pointer if this is not possible
unique_ptr<Tree_t> BUILD(const std::set<long>& tips, const vector<RSplit>& splits)
{
  std::unique_ptr<Tree_t> tree(new Tree_t());
  tree->createRoot();

  // 1. First handle trees of size 1 and 2
  if (tips.size() == 1)
  {
    tree->getRoot()->setOttId(*tips.begin());
    return tree;
  }
  else if (tips.size() == 2)
  {
    auto Node1a = tree->createChild(tree->getRoot());
    auto Node1b = tree->createChild(tree->getRoot());
    auto it = tips.begin();
    Node1a->setOttId(*it++);
    Node1b->setOttId(*it++);
    return tree;
  }

  // 2. Initialize the mapping from elements to components
  map<long,long> component;      // element   -> component
  map<long,list<long>> elements; // component -> elements
  for(long i: tips)
  {
    component[i] = i;
    elements[i].push_back(i);
  }

  // 3. For each split, all the leaves in the include group must be in the same component
  for(const auto& split: splits)
  {
    long c1 = -1;
    for(long i: split.in)
    {
      long c2 = component[i];
      if (c1 != -1 and c1 != c2)
	merge_components(c1,c2,component,elements);
      c1 = component[i];
    }
  }

  // 4. If we can't subdivide the leaves in any way, then the splits are not consistent, so return failure
  long first = *tips.begin();
  if (elements[component[first]].size() == tips.size())
    return {};

  // 5. Create the set of tips in each connected component
  map<long,set<long>> subtips;
  for(long c: tips)
  {
    if (c != component[c]) continue;

    set<long>& s = subtips[c];
    for(long l: elements[c])
      s.insert(l);
  }

  // 6. Determine the splits that are not satisfied yet and go into each component
  map<long,vector<RSplit>> subsplits;
  for(const auto& split: splits)
  {
    long first = *split.in.begin();
    long c = component[first];

    // if none of the exclude group are in the component, then the split is satisfied by the top-level partition.
    if (empty_intersection(split.out, subtips[c])) continue;

    subsplits[c].push_back(split);
  }

  // 7. Recursively solve the sub-problems of the partition components
  for(const auto& x: subtips)
  {
    auto subtree = BUILD(x.second, subsplits[x.first]);
    if (not subtree) return {};

    tree->addSubtree(tree->getRoot(), *subtree);
  }

  return tree;
}

/// Copy node names from taxonomy to tree based on ott ids, and copy the root name also
void add_names(unique_ptr<Tree_t>& tree, const unique_ptr<Tree_t>& taxonomy)
{
  clearAndfillDesIdSets(*tree);

  for(auto n1: iter_post(*tree))
    for(auto n2: iter_post(*taxonomy))
      if (n1->getData().desIds == n2->getData().desIds)
	n1->setName( n2->getName());
}

/// Get the list of splits, and add them one at a time if they are consistent with previous splits
unique_ptr<Tree_t> combine(const vector<unique_ptr<Tree_t>>& trees)
{
  // Standardize names to 0..n-1 for this subproblem
  const auto& taxonomy = trees.back();
  auto all_leaves = taxonomy->getRoot()->getData().desIds;

  // 1. Find splits in order of input trees
  vector<RSplit> splits;
  for(const auto& tree: trees)
  {
    auto root = tree->getRoot();
    const auto leafTaxa = root->getData().desIds;

    for(const auto& leaf: set_difference_as_set(leafTaxa, all_leaves))
      throw OTCError()<<"OTT Id "<<leaf<<" not in taxonomy!";

    for(auto nd: iter_post_const(*tree))
    {
      const auto& descendants = nd->getData().desIds;
      RSplit split{descendants, leafTaxa};
      if (split.in.size()>1 and split.out.size())
      	splits.push_back(split);
    }
  }

  // 2. Add splits sequentially if they are consistent with previous splits.
  vector<RSplit> consistent;
  for(const auto& split: splits)
  {
    consistent.push_back(split);
    auto result = BUILD(all_leaves, consistent);
    if (not result)
    {
      consistent.pop_back();
      LOG(DEBUG)<<"Reject: "<<split<<"\n";
    }
    else
      LOG(DEBUG)<<"Keep:   "<<split<<"\n";
  }

  // 3. Construct final tree and add names
  auto tree = BUILD(all_leaves, consistent);
  add_names(tree, taxonomy);
  return tree;
}

bool handleRequireOttIds(OTCLI & otCLI, const std::string & arg)
{
  if (arg == "true" or arg == "yes" or arg == "True" or arg == "Yes")
    otCLI.getParsingRules().requireOttIds = true;
  else if (arg == "false" or arg == "no" or arg == "False" or arg == "no")
    otCLI.getParsingRules().requireOttIds = false;
  else
    return false;

  return true;
}

bool handlePruneUnrecognizedTips(OTCLI & otCLI, const std::string & arg)
{
  if (arg == "true" or arg == "yes" or arg == "True" or arg == "Yes")
    otCLI.getParsingRules().pruneUnrecognizedInputTips = true;
  else if (arg == "false" or arg == "no" or arg == "False" or arg == "no")
    otCLI.getParsingRules().pruneUnrecognizedInputTips = false;
  else
    return false;

  return true;
}

bool synthesize_taxonomy = false;

bool handleSynthesizeTaxonomy(OTCLI &, const std::string & arg)
{
  if (arg == "true" or "yes" or "True" or "Yes")
    synthesize_taxonomy = true;
  else if (arg == "false" or "no" or "False" or "no")
    synthesize_taxonomy = false;
  else
    return false;

  return true;
}

unique_ptr<Tree_t> make_unresolved_tree(const vector<unique_ptr<Tree_t>>& trees, bool use_ids)
{
  std::unique_ptr<Tree_t> tree(new Tree_t());
  tree->createRoot();

  if (use_ids)
  {
    map<long,string> names;
    for(const auto& tree: trees)
      for(auto nd: iter_pre_const(*tree))
	if (nd->isTip())
	{
	  long id = nd->getOttId();
	  auto it = names.find(id);
	  if (it == names.end())
	    names[id] = nd->getName();
	}

    for(const auto& n: names)
    {
      auto node = tree->createChild(tree->getRoot());
      node->setOttId(n.first);
      node->setName(n.second);
    }
    clearAndfillDesIdSets(*tree);
  }
  else
  {
    set<string> names;
    for(const auto& tree: trees)
      for(auto nd: iter_pre_const(*tree))
	if (nd->isTip())
	  names.insert(nd->getName());

    for(const auto& n: names)
    {
      auto node = tree->createChild(tree->getRoot());
      node->setName(n);
    }
  }

  return tree;
}

string newick(const Tree_t &t)
{
  std::ostringstream s;
  writeTreeAsNewick(s, t);
  return s.str();
}

int main(int argc, char *argv[]) {
    OTCLI otCLI("otc-solve-subproblem",
                "takes at series of tree files. Each is treated as a subproblem.\n",
		"subproblem.tre");

    otCLI.addFlag('o',
		  "Require OTT ids.  Defaults to true",
		  handleRequireOttIds,
		  true);
    otCLI.addFlag('p',
		  "Prune unrecognized tips.  Defaults to false",
		  handlePruneUnrecognizedTips,
		  true);
    otCLI.addFlag('T',
		  "Synthesize unresolved taxonomy from all mentioned taxa.  Defaults to false",
		  handleSynthesizeTaxonomy,
		  false);

    vector<unique_ptr<Tree_t>> trees;
    auto get = [&trees](OTCLI &, unique_ptr<Tree_t> nt) {trees.push_back(std::move(nt)); return true;};

    if (argc < 2)
	throw OTCError("No subproblem provided!");

    // I think multiple subproblem files are essentially concatenated.
    // Is it possible to read a single subproblem from cin?
    if (treeProcessingMain<Tree_t>(otCLI, argc, argv, get, nullptr, 1))
      std::exit(1);

    bool requireOttIds = otCLI.getParsingRules().requireOttIds;
    if (synthesize_taxonomy)
    {
      trees.push_back(make_unresolved_tree(trees,requireOttIds));
      LOG(DEBUG)<<"taxonomy = "<<newick(*trees.back())<<"\n";
    }

    // Add fake Ott Ids to tips and compute desIds
    if (not requireOttIds)
    {
      auto& taxonomy = trees.back();

      // 1. Compute mapping from name -> id
      long id = 1;
      map<string,long> name_to_id;
      for(auto nd: iter_pre(*taxonomy))
	if (nd->isTip())
	{
	  string name = nd->getName();
	  if (not name.size())
	    throw OTCError()<<"Taxonomy tip has no label or OTT id!";
	  auto it = name_to_id.find(name);
	  if (it != name_to_id.end())
	    throw OTCError()<<"Tip label '"<<name<<"' occurs twice in taxonomy!";
	  name_to_id[name] = id++;
	}

      // 2. Set ids
      for(auto& tree: trees)
	for(auto nd: iter_post(*tree))
	  if (nd->isTip())
	  {
	    string name = nd->getName();
	    if (not name.size())
	      throw OTCError()<<"Tip has no label or OTT id!";
	    auto it = name_to_id.find(name);
	    if (it == name_to_id.end())
	      throw OTCError()<<"Can't find label '"<<name<<"' in taxonomy!";
	    auto id = it->second;
	    nd->setOttId(id);
	  }

      // 3. Compute DesIds.
      for(auto& tree: trees)
	clearAndfillDesIdSets(*tree);
    }

    auto tree = combine(trees);

    writeTreeAsNewick(std::cout, *tree);
    std::cout<<"\n";
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com>
** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSerialPort module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "console.h"

#include <QScrollBar>

#include <QtCore/QDebug>

Console::Console(QWidget *parent)
    : QPlainTextEdit(parent)
    , localEchoEnabled(false)
{
    document()->setMaximumBlockCount(100);
    QPalette p = palette();
    p.setColor(QPalette::Base, Qt::black);
    p.setColor(QPalette::Text, Qt::green);
    setPalette(p);

}

void Console::putData(const QByteArray &data)
{
    insertPlainText(QString(data));

    QScrollBar *bar = verticalScrollBar();
    bar->setValue(bar->maximum());
}

void Console::setLocalEchoEnabled(bool set)
{
    localEchoEnabled = set;
}

void Console::keyPressEvent(QKeyEvent *e)
{
    switch (e->key()) {
    case Qt::Key_Backspace:
    case Qt::Key_Left:
    case Qt::Key_Right:
    case Qt::Key_Up:
    case Qt::Key_Down:
        // skip processing
        break;
    default:
        if (localEchoEnabled)
            QPlainTextEdit::keyPressEvent(e);
        emit getData(e->text().toLocal8Bit());
    }
}

void Console::mousePressEvent(QMouseEvent *e)
{
    Q_UNUSED(e)
    setFocus();
}

void Console::mouseDoubleClickEvent(QMouseEvent *e)
{
    Q_UNUSED(e)
}

void Console::contextMenuEvent(QContextMenuEvent *e)
{
    Q_UNUSED(e)
}
<commit_msg>force terminal font to be fixed<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com>
** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSerialPort module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "console.h"

#include <QScrollBar>

#include <QtCore/QDebug>

Console::Console(QWidget *parent)
    : QPlainTextEdit(parent)
    , localEchoEnabled(false)
{
    document()->setMaximumBlockCount(100);
    QPalette p = palette();
    p.setColor(QPalette::Base, Qt::black);
    p.setColor(QPalette::Text, Qt::green);
    setPalette(p);

    setFont(QFont("Courier", 15));

}

void Console::putData(const QByteArray &data)
{
    insertPlainText(QString(data));

    QScrollBar *bar = verticalScrollBar();
    bar->setValue(bar->maximum());
}

void Console::setLocalEchoEnabled(bool set)
{
    localEchoEnabled = set;
}

void Console::keyPressEvent(QKeyEvent *e)
{
    switch (e->key()) {
    case Qt::Key_Backspace:
    case Qt::Key_Left:
    case Qt::Key_Right:
    case Qt::Key_Up:
    case Qt::Key_Down:
        // skip processing
        break;
    default:
        if (localEchoEnabled)
            QPlainTextEdit::keyPressEvent(e);
        emit getData(e->text().toLocal8Bit());
    }
}

void Console::mousePressEvent(QMouseEvent *e)
{
    Q_UNUSED(e)
    setFocus();
}

void Console::mouseDoubleClickEvent(QMouseEvent *e)
{
    Q_UNUSED(e)
}

void Console::contextMenuEvent(QContextMenuEvent *e)
{
    Q_UNUSED(e)
}
<|endoftext|>


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

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

#include <tools/ref.hxx>
#ifndef _SV_SVSYS_HXX
#include <svsys.h>
#endif

#ifndef _SV_SALGDI_HXX
#include <salgdi.hxx>
#endif

#ifndef _DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _SV_SVDATA_HXX
#include <svdata.hxx>
#endif
#ifndef _TL_POLY_HXX
#include <tools/poly.hxx>
#endif
#ifndef _SV_METAACT_HXX
#include <metaact.hxx>
#endif
#ifndef _SV_GDIMTF_HXX
#include <gdimtf.hxx>
#endif
#ifndef _SV_OUTDATA_HXX
#include <outdata.hxx>
#endif
#ifndef _SV_OUTDEV_H
#include <outdev.h>
#endif
#ifndef _SV_OUTDEV_HXX
#include <outdev.hxx>
#endif
#ifndef _SV_VIRDEV_HXX
#include <virdev.hxx>
#endif

// =======================================================================

DBG_NAMEEX( OutputDevice )

// =======================================================================

void OutputDevice::DrawRect( const Rectangle& rRect,
                             ULONG nHorzRound, ULONG nVertRound )
{
    DBG_TRACE( "OutputDevice::DrawRoundRect()" );
    DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );

    if ( mpMetaFile )
        mpMetaFile->AddAction( new MetaRoundRectAction( rRect, nHorzRound, nVertRound ) );

    if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() )
        return;

    const Rectangle aRect( ImplLogicToDevicePixel( rRect ) );

    if ( aRect.IsEmpty() )
        return;

    nHorzRound = ImplLogicWidthToDevicePixel( nHorzRound );
    nVertRound = ImplLogicHeightToDevicePixel( nVertRound );

    // we need a graphics
    if ( !mpGraphics )
    {
        if ( !ImplGetGraphics() )
            return;
    }

    if ( mbInitClipRegion )
        ImplInitClipRegion();
    if ( mbOutputClipped )
        return;

    if ( mbInitLineColor )
        ImplInitLineColor();
    if ( mbInitFillColor )
        ImplInitFillColor();

    if ( !nHorzRound && !nVertRound )
        mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), this );
    else
    {
        const Polygon aRoundRectPoly( aRect, nHorzRound, nVertRound );

        if ( aRoundRectPoly.GetSize() >= 2 )
        {
            const SalPoint* pPtAry = (const SalPoint*) aRoundRectPoly.GetConstPointAry();

            if ( !mbFillColor )
                mpGraphics->DrawPolyLine( aRoundRectPoly.GetSize(), pPtAry, this );
            else
                mpGraphics->DrawPolygon( aRoundRectPoly.GetSize(), pPtAry, this );
        }
    }

    if( mpAlphaVDev )
        mpAlphaVDev->DrawRect( rRect, nHorzRound, nVertRound );
}

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

void OutputDevice::DrawEllipse( const Rectangle& rRect )
{
    DBG_TRACE( "OutputDevice::DrawEllipse()" );
    DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );

    if ( mpMetaFile )
        mpMetaFile->AddAction( new MetaEllipseAction( rRect ) );

    if  ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() )
        return;

    Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
    if ( aRect.IsEmpty() )
        return;

    // we need a graphics
    if ( !mpGraphics )
    {
        if ( !ImplGetGraphics() )
            return;
    }

    if ( mbInitClipRegion )
        ImplInitClipRegion();
    if ( mbOutputClipped )
        return;

    if ( mbInitLineColor )
        ImplInitLineColor();

    Polygon aRectPoly( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
    if ( aRectPoly.GetSize() >= 2 )
    {
        const SalPoint* pPtAry = (const SalPoint*)aRectPoly.GetConstPointAry();
        if ( !mbFillColor )
            mpGraphics->DrawPolyLine( aRectPoly.GetSize(), pPtAry, this );
        else
        {
            if ( mbInitFillColor )
                ImplInitFillColor();
            mpGraphics->DrawPolygon( aRectPoly.GetSize(), pPtAry, this );
        }
    }

    if( mpAlphaVDev )
        mpAlphaVDev->DrawEllipse( rRect );
}

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

void OutputDevice::DrawArc( const Rectangle& rRect,
                            const Point& rStartPt, const Point& rEndPt )
{
    DBG_TRACE( "OutputDevice::DrawArc()" );
    DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );

    if ( mpMetaFile )
        mpMetaFile->AddAction( new MetaArcAction( rRect, rStartPt, rEndPt ) );

    if ( !IsDeviceOutputNecessary() || !mbLineColor || ImplIsRecordLayout() )
        return;

    Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
    if ( aRect.IsEmpty() )
        return;

    // we need a graphics
    if ( !mpGraphics )
    {
        if ( !ImplGetGraphics() )
            return;
    }

    if ( mbInitClipRegion )
        ImplInitClipRegion();
    if ( mbOutputClipped )
        return;

    if ( mbInitLineColor )
        ImplInitLineColor();

    const Point     aStart( ImplLogicToDevicePixel( rStartPt ) );
    const Point     aEnd( ImplLogicToDevicePixel( rEndPt ) );
    Polygon         aArcPoly( aRect, aStart, aEnd, POLY_ARC );

    if ( aArcPoly.GetSize() >= 2 )
    {
        const SalPoint* pPtAry = (const SalPoint*)aArcPoly.GetConstPointAry();
        mpGraphics->DrawPolyLine( aArcPoly.GetSize(), pPtAry, this );
    }

    if( mpAlphaVDev )
        mpAlphaVDev->DrawArc( rRect, rStartPt, rEndPt );
}

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

void OutputDevice::DrawPie( const Rectangle& rRect,
                            const Point& rStartPt, const Point& rEndPt )
{
    DBG_TRACE( "OutputDevice::DrawPie()" );
    DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );

    if ( mpMetaFile )
        mpMetaFile->AddAction( new MetaPieAction( rRect, rStartPt, rEndPt ) );

    if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() )
        return;

    Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
    if ( aRect.IsEmpty() )
        return;

    // we need a graphics
    if ( !mpGraphics )
    {
        if ( !ImplGetGraphics() )
            return;
    }

    if ( mbInitClipRegion )
        ImplInitClipRegion();
    if ( mbOutputClipped )
        return;

    if ( mbInitLineColor )
        ImplInitLineColor();

    const Point     aStart( ImplLogicToDevicePixel( rStartPt ) );
    const Point     aEnd( ImplLogicToDevicePixel( rEndPt ) );
    Polygon         aPiePoly( aRect, aStart, aEnd, POLY_PIE );

    if ( aPiePoly.GetSize() >= 2 )
    {
        const SalPoint* pPtAry = (const SalPoint*)aPiePoly.GetConstPointAry();
        if ( !mbFillColor )
            mpGraphics->DrawPolyLine( aPiePoly.GetSize(), pPtAry, this );
        else
        {
            if ( mbInitFillColor )
                ImplInitFillColor();
            mpGraphics->DrawPolygon( aPiePoly.GetSize(), pPtAry, this );
        }
    }

    if( mpAlphaVDev )
        mpAlphaVDev->DrawPie( rRect, rStartPt, rEndPt );
}

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

void OutputDevice::DrawChord( const Rectangle& rRect,
                              const Point& rStartPt, const Point& rEndPt )
{
    DBG_TRACE( "OutputDevice::DrawChord()" );
    DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );

    if ( mpMetaFile )
        mpMetaFile->AddAction( new MetaChordAction( rRect, rStartPt, rEndPt ) );

    if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() )
        return;

    Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
    if ( aRect.IsEmpty() )
        return;

    // we need a graphics
    if ( !mpGraphics )
    {
        if ( !ImplGetGraphics() )
            return;
    }

    if ( mbInitClipRegion )
        ImplInitClipRegion();
    if ( mbOutputClipped )
        return;

    if ( mbInitLineColor )
        ImplInitLineColor();

    const Point     aStart( ImplLogicToDevicePixel( rStartPt ) );
    const Point     aEnd( ImplLogicToDevicePixel( rEndPt ) );
    Polygon         aChordPoly( aRect, aStart, aEnd, POLY_CHORD );

    if ( aChordPoly.GetSize() >= 2 )
    {
        const SalPoint* pPtAry = (const SalPoint*)aChordPoly.GetConstPointAry();
        if ( !mbFillColor )
            mpGraphics->DrawPolyLine( aChordPoly.GetSize(), pPtAry, this );
        else
        {
            if ( mbInitFillColor )
                ImplInitFillColor();
            mpGraphics->DrawPolygon( aChordPoly.GetSize(), pPtAry, this );
        }
    }

    if( mpAlphaVDev )
        mpAlphaVDev->DrawChord( rRect, rStartPt, rEndPt );
}
<commit_msg>INTEGRATION: CWS vgbugs07 (1.9.240); FILE MERGED 2007/06/04 13:29:37 vg 1.9.240.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: outdev5.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 20:19:52 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#include <tools/ref.hxx>
#ifndef _SV_SVSYS_HXX
#include <svsys.h>
#endif

#ifndef _SV_SALGDI_HXX
#include <vcl/salgdi.hxx>
#endif

#ifndef _DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _SV_SVDATA_HXX
#include <vcl/svdata.hxx>
#endif
#ifndef _TL_POLY_HXX
#include <tools/poly.hxx>
#endif
#ifndef _SV_METAACT_HXX
#include <vcl/metaact.hxx>
#endif
#ifndef _SV_GDIMTF_HXX
#include <vcl/gdimtf.hxx>
#endif
#ifndef _SV_OUTDATA_HXX
#include <outdata.hxx>
#endif
#ifndef _SV_OUTDEV_H
#include <outdev.h>
#endif
#ifndef _SV_OUTDEV_HXX
#include <vcl/outdev.hxx>
#endif
#ifndef _SV_VIRDEV_HXX
#include <vcl/virdev.hxx>
#endif

// =======================================================================

DBG_NAMEEX( OutputDevice )

// =======================================================================

void OutputDevice::DrawRect( const Rectangle& rRect,
                             ULONG nHorzRound, ULONG nVertRound )
{
    DBG_TRACE( "OutputDevice::DrawRoundRect()" );
    DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );

    if ( mpMetaFile )
        mpMetaFile->AddAction( new MetaRoundRectAction( rRect, nHorzRound, nVertRound ) );

    if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() )
        return;

    const Rectangle aRect( ImplLogicToDevicePixel( rRect ) );

    if ( aRect.IsEmpty() )
        return;

    nHorzRound = ImplLogicWidthToDevicePixel( nHorzRound );
    nVertRound = ImplLogicHeightToDevicePixel( nVertRound );

    // we need a graphics
    if ( !mpGraphics )
    {
        if ( !ImplGetGraphics() )
            return;
    }

    if ( mbInitClipRegion )
        ImplInitClipRegion();
    if ( mbOutputClipped )
        return;

    if ( mbInitLineColor )
        ImplInitLineColor();
    if ( mbInitFillColor )
        ImplInitFillColor();

    if ( !nHorzRound && !nVertRound )
        mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), this );
    else
    {
        const Polygon aRoundRectPoly( aRect, nHorzRound, nVertRound );

        if ( aRoundRectPoly.GetSize() >= 2 )
        {
            const SalPoint* pPtAry = (const SalPoint*) aRoundRectPoly.GetConstPointAry();

            if ( !mbFillColor )
                mpGraphics->DrawPolyLine( aRoundRectPoly.GetSize(), pPtAry, this );
            else
                mpGraphics->DrawPolygon( aRoundRectPoly.GetSize(), pPtAry, this );
        }
    }

    if( mpAlphaVDev )
        mpAlphaVDev->DrawRect( rRect, nHorzRound, nVertRound );
}

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

void OutputDevice::DrawEllipse( const Rectangle& rRect )
{
    DBG_TRACE( "OutputDevice::DrawEllipse()" );
    DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );

    if ( mpMetaFile )
        mpMetaFile->AddAction( new MetaEllipseAction( rRect ) );

    if  ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() )
        return;

    Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
    if ( aRect.IsEmpty() )
        return;

    // we need a graphics
    if ( !mpGraphics )
    {
        if ( !ImplGetGraphics() )
            return;
    }

    if ( mbInitClipRegion )
        ImplInitClipRegion();
    if ( mbOutputClipped )
        return;

    if ( mbInitLineColor )
        ImplInitLineColor();

    Polygon aRectPoly( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
    if ( aRectPoly.GetSize() >= 2 )
    {
        const SalPoint* pPtAry = (const SalPoint*)aRectPoly.GetConstPointAry();
        if ( !mbFillColor )
            mpGraphics->DrawPolyLine( aRectPoly.GetSize(), pPtAry, this );
        else
        {
            if ( mbInitFillColor )
                ImplInitFillColor();
            mpGraphics->DrawPolygon( aRectPoly.GetSize(), pPtAry, this );
        }
    }

    if( mpAlphaVDev )
        mpAlphaVDev->DrawEllipse( rRect );
}

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

void OutputDevice::DrawArc( const Rectangle& rRect,
                            const Point& rStartPt, const Point& rEndPt )
{
    DBG_TRACE( "OutputDevice::DrawArc()" );
    DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );

    if ( mpMetaFile )
        mpMetaFile->AddAction( new MetaArcAction( rRect, rStartPt, rEndPt ) );

    if ( !IsDeviceOutputNecessary() || !mbLineColor || ImplIsRecordLayout() )
        return;

    Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
    if ( aRect.IsEmpty() )
        return;

    // we need a graphics
    if ( !mpGraphics )
    {
        if ( !ImplGetGraphics() )
            return;
    }

    if ( mbInitClipRegion )
        ImplInitClipRegion();
    if ( mbOutputClipped )
        return;

    if ( mbInitLineColor )
        ImplInitLineColor();

    const Point     aStart( ImplLogicToDevicePixel( rStartPt ) );
    const Point     aEnd( ImplLogicToDevicePixel( rEndPt ) );
    Polygon         aArcPoly( aRect, aStart, aEnd, POLY_ARC );

    if ( aArcPoly.GetSize() >= 2 )
    {
        const SalPoint* pPtAry = (const SalPoint*)aArcPoly.GetConstPointAry();
        mpGraphics->DrawPolyLine( aArcPoly.GetSize(), pPtAry, this );
    }

    if( mpAlphaVDev )
        mpAlphaVDev->DrawArc( rRect, rStartPt, rEndPt );
}

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

void OutputDevice::DrawPie( const Rectangle& rRect,
                            const Point& rStartPt, const Point& rEndPt )
{
    DBG_TRACE( "OutputDevice::DrawPie()" );
    DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );

    if ( mpMetaFile )
        mpMetaFile->AddAction( new MetaPieAction( rRect, rStartPt, rEndPt ) );

    if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() )
        return;

    Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
    if ( aRect.IsEmpty() )
        return;

    // we need a graphics
    if ( !mpGraphics )
    {
        if ( !ImplGetGraphics() )
            return;
    }

    if ( mbInitClipRegion )
        ImplInitClipRegion();
    if ( mbOutputClipped )
        return;

    if ( mbInitLineColor )
        ImplInitLineColor();

    const Point     aStart( ImplLogicToDevicePixel( rStartPt ) );
    const Point     aEnd( ImplLogicToDevicePixel( rEndPt ) );
    Polygon         aPiePoly( aRect, aStart, aEnd, POLY_PIE );

    if ( aPiePoly.GetSize() >= 2 )
    {
        const SalPoint* pPtAry = (const SalPoint*)aPiePoly.GetConstPointAry();
        if ( !mbFillColor )
            mpGraphics->DrawPolyLine( aPiePoly.GetSize(), pPtAry, this );
        else
        {
            if ( mbInitFillColor )
                ImplInitFillColor();
            mpGraphics->DrawPolygon( aPiePoly.GetSize(), pPtAry, this );
        }
    }

    if( mpAlphaVDev )
        mpAlphaVDev->DrawPie( rRect, rStartPt, rEndPt );
}

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

void OutputDevice::DrawChord( const Rectangle& rRect,
                              const Point& rStartPt, const Point& rEndPt )
{
    DBG_TRACE( "OutputDevice::DrawChord()" );
    DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );

    if ( mpMetaFile )
        mpMetaFile->AddAction( new MetaChordAction( rRect, rStartPt, rEndPt ) );

    if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() )
        return;

    Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
    if ( aRect.IsEmpty() )
        return;

    // we need a graphics
    if ( !mpGraphics )
    {
        if ( !ImplGetGraphics() )
            return;
    }

    if ( mbInitClipRegion )
        ImplInitClipRegion();
    if ( mbOutputClipped )
        return;

    if ( mbInitLineColor )
        ImplInitLineColor();

    const Point     aStart( ImplLogicToDevicePixel( rStartPt ) );
    const Point     aEnd( ImplLogicToDevicePixel( rEndPt ) );
    Polygon         aChordPoly( aRect, aStart, aEnd, POLY_CHORD );

    if ( aChordPoly.GetSize() >= 2 )
    {
        const SalPoint* pPtAry = (const SalPoint*)aChordPoly.GetConstPointAry();
        if ( !mbFillColor )
            mpGraphics->DrawPolyLine( aChordPoly.GetSize(), pPtAry, this );
        else
        {
            if ( mbInitFillColor )
                ImplInitFillColor();
            mpGraphics->DrawPolygon( aChordPoly.GetSize(), pPtAry, this );
        }
    }

    if( mpAlphaVDev )
        mpAlphaVDev->DrawChord( rRect, rStartPt, rEndPt );
}
<|endoftext|>