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

	File: Timer.cpp

	Description:

	Implementation of the Interpreter class' timer related methods

	Only one timer should every be active at any one time, so bear
	that in mind when examining the code herein.

******************************************************************************/
#include "Ist.h"

#pragma comment(lib, "winmm.lib")

#pragma code_seg(PRIM_SEG)

#include "ObjMem.h"
#include "Interprt.h"
#include "rc_vm.h"				// For error message ids
#include "InterprtPrim.inl"
#include "InterprtProc.inl"

// Smalltalk classes
#include "STExternal.h"

static UINT wTimerMax = 0xFFFF;

// Defines the maximum acceptable timer resolution, over which the VM refuses to run
static const UINT MAXTIMERRES = 60;

// Private timer function static. Modified by two threads.
static volatile UINT timerID;

uint64_t Interpreter::m_clockFrequency;

///////////////////////////////////////////////////////////////////////////////
// Smalltalk Alarm/Delay/Timers
//
// We use the Multimedia Timers because these do not fire via the message loop
// (i.e. they come back directly as under as separate thread of control in Win32),
// and are therefore much closer to the Smalltalk timer concept. These have a
// further advantage that they can operate at a much finer granularity
// (down to 1 millisecond).
//
// When we are unable to use an MM timer (e.g. because the period requested is
// too long) we can fall back on a normal Win32 timer, but these are less
// accurate, and require that the message loop is active (which SHOULD normally
// be the case, but somebody could have fiddled with the Smalltalk so there's no
// guarantee).
//

// Callback proc for MM timers
// N.B. This routine is called from a separate thread (in Win32), rather than in
// interrupt time, but careful coding is still important. The recommended
// list of routines is limited to:
//		EnterCriticalSection	ReleaseSemaphore
//		LeaveCriticalSection	SetEvent
//		timeGetSystemTime		timeGetTime
//		OutputDebugString		timeKillEvent
//		PostMessage				timeSetEvent
//
// "If a Win32 low-level audio callback [we are using mm timers here] shares data
// with other code, a Critical Section or similar mutual exclusion mechanism should
// be used to protect the integrity of the data".
// Access to the asynchronous semaphore array is protected by a critical section
// in the asynchronousSignal and CheckProcessSwitch routines. We don't really care
// that much about the timerID
void CALLBACK Interpreter::TimeProc(UINT uID, UINT /*uMsg*/, DWORD /*dwUser*/, DWORD /*dw1*/, DWORD /*dw2*/)
{
	// Avoid firing a timer which has been cancelled (or is about to be cancelled!)
	// We use an InterlockedExchange() to set the value to 0 so that the main thread
	// can recognise that the timer has fired without race conditions

	if (InterlockedExchange(LPLONG(&timerID), 0) != 0)
	{
		// If not previously killed (which is very unlikely except in certain exceptional
		// circumstances where the timer is killed at the exact moment it is about to fire)
		// then go ahead and signal the semaphore and the wakeup event

		// We mustn't access Pointers from an async thread when object memory is compacting
		// as the Pointer will be wrong
		GrabAsyncProtect();

		SemaphoreOTE* timerSemaphore = Pointers.TimingSemaphore;
		HARDASSERT(!ObjectMemoryIsIntegerObject(timerSemaphore));
		HARDASSERT(!timerSemaphore->isFree());
		HARDASSERT(timerSemaphore->m_oteClass == Pointers.ClassSemaphore);

		// Asynchronously signal the required semaphore asynchronously, which will be detected
		// in sync. with the dispatching of byte codes, and properly signalled
		asynchronousSignalNoProtect(timerSemaphore);
		// Signal the timing Event, in case the idle process has put the VM to sleep
		SetWakeupEvent();

		RelinquishAsyncProtect();
	}
	else
		// An old timer (which should have been cancelled) has fired
		trace("Old timer %d fired, current %d\n", uID, timerID);
}

///////////////////////////////////////////////////////////////////////////////
// Timer/Idling Primitives

// Signal a specified semaphore after the specified milliseconds duration (the argument).
// NOTE: NOT ABSOLUTE VALUE!
// If the specified time has already passed, then the TimingSemaphore is signalled immediately.
BOOL __fastcall Interpreter::primitiveSignalAtTick(CompiledMethod&, unsigned)
{
	Oop tickPointer = stackTop();
	SMALLINTEGER nDelay;

	if (ObjectMemoryIsIntegerObject(tickPointer))
		nDelay = ObjectMemoryIntegerValueOf(tickPointer);
	else
	{
		OTE* oteArg = reinterpret_cast<OTE*>(tickPointer);
		return primitiveFailureWith(PrimitiveFailureNonInteger, oteArg);	// ticks must be SmallInteger
	}

	// To avoid any race conditions against the global timerID value (it is quite
	// common for the timer to fire, for example, before the timeSetEvent() call
	// has actually returned in the duration is very short because the timer thread
	// is operating at a very high priority), we use an interlocked operation

	UINT outstandingID = InterlockedExchange(LPLONG(&timerID), 0);
	// If outstanding timer now fires, it will do nothing. We'll end up killing something which is already
	// dead of course, but that should be OK
	if (outstandingID)
	{
#ifdef OAD
		TRACESTREAM << "Killing existing timer with id " << outstandingID << endl;
#endif
		UINT kill = ::timeKillEvent(outstandingID);
		if (kill != TIMERR_NOERROR)
			trace("Failed to kill timer %u (%d,%d)!\n\r", outstandingID, kill, GetLastError());
	}

	if (nDelay > 0)
	{
		// Clamp the requested delay to the maximum if it is too large. This simplifies the Delay code in the image a little.
		if (nDelay > SMALLINTEGER(wTimerMax))
		{
			nDelay = wTimerMax;
		}

		// Set the timerID to a non-zero value just in case the timer fires before timeSetEvent() returns.
		// This allows the TimerProc to recognise the timer as valid (it doesn't really care about the
		// timerID anyway, just that we're interested in it).
		// N.B. We shouldn't need an interlocked operation here because, assuming no bugs in the Win32 MM
		// timers, we've killed any outstanding timer, and the timer thread should be dormant
		timerID = UINT(-1);		// -1 is not used as a timer ID.

		UINT newTimerID = ::timeSetEvent(nDelay, 0, TimeProc, 0, TIME_ONESHOT);
		if (newTimerID && newTimerID != UINT(-1))
		{
			// Unless timer has already fired, record the timer id so can cancel if necessary
			InterlockedCompareExchange(&timerID, newTimerID, -1);
			pop(2);		// No ref. counting required
		}
		else
		{
			// System refused to set timer for some reason
			DWORD error = GetLastError();
			trace("Oh no, failed to set a timer for %d mS (%d)!\n\r", nDelay, error);
			return primitiveFailureWithInt(PrimitiveFailureSystemError, error);
		}
	}
	else if (nDelay == 0)
	{
#ifdef _DEBUG
		TRACESTREAM << "Requested delay " << dec << nDelay << " passed, signalling immediately" << endl;
#endif
		// The request time has already passed, or does not fall within the
		// available timer resolution (i.e. it will happen too soon), so signal
		// it immediately
		// We must adjust stack before signalling, as may change Process (and therefore stack!)
		pop(2);

		// N.B. Signalling may detect a process switch, but does not actually perform it
		signalSemaphore(Pointers.TimingSemaphore);
	}
	// else requested delay was negative - we allow this to clear down the existing timer

#ifdef _DEBUG
	if (newProcessWaiting())
	{
		ASSERT(m_oteNewProcess->m_oteClass == Pointers.ClassProcess);
		ProcessOTE* activeProcess = scheduler()->m_activeProcess;

		TRACESTREAM << "signalAtTick: Caused process switch to " << m_oteNewProcess
			<< endl << "\t\tfrom " << activeProcess << endl
			<< "\tasync signals " << m_qAsyncSignals.isEmpty() << ')' << endl;
	}
#endif

	// Delay could already have fired
	CheckProcessSwitch();
	return primitiveSuccess();
}

BOOL __fastcall Interpreter::primitiveMillisecondClockValue()
{
	// QPC is declared as returning (via out param) a signed value, but this makes no sense because
	// the function boils down to a wrapper around the RDTSC instruction, which Intel's docs make
	// clear provides an unsigned 64-bit counter.
	// Treating the value as unsigned allows for more efficient division operations, and of course
	// we never want a negative value for this counter (even if we'd have turned to stone long before)

	uint64_t counter;
	// Don't bother checking return value as according to the MSDN docs this won't fail on XP and later
	::QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&counter));

	// Compiler can optimize this down to a single division operation that calculates both the quotient and remainder
	uint64_t seconds = counter / m_clockFrequency;
	uint64_t remainder = counter % m_clockFrequency;

	uint64_t millisecs = seconds * 1000 + (remainder * 1000 / m_clockFrequency);
	return replaceStackTopWithNew(Integer::NewUnsigned64(millisecs));
}

BOOL __fastcall Interpreter::primitiveMicrosecondClockValue()
{
	uint64_t counter;
	::QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&counter));

	uint64_t seconds = counter / m_clockFrequency;
	uint64_t remainder = counter % m_clockFrequency;
	uint64_t microsecs = seconds * 1000000 + (remainder * 1000000 / m_clockFrequency);
	return replaceStackTopWithNew(Integer::NewUnsigned64(microsecs));
}

// Establish the desired timer resolution and create the Win32 event used to terminate
// VM idling when a timer fires
#pragma code_seg(INIT_SEG)
HRESULT Interpreter::initializeTimer()
{
	if (::QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&m_clockFrequency)) == 0)
	{
		// MSDN says this shouldn't happen: "On systems that run WindowsXP or later, the function will always succeed and will thus never return zero."
		return ReportWin32Error(IDP_NOHIRESCLOCK, ::GetLastError());
	}

	timerID = 0;
	TIMECAPS tc;
	::timeGetDevCaps(&tc, sizeof(TIMECAPS));
	wTimerMax = tc.wPeriodMax;

	return S_OK;
}

#pragma code_seg(TERM_SEG)
void Interpreter::terminateTimer()
{
	static const char* szFmt = "Shutdown Error %u calling %s(%u)\n";
	MMRESULT err;
	if (timerID != 0)
	{
		err = ::timeKillEvent(timerID);
		if (err != TIMERR_NOERROR)
			trace(szFmt, err, "timeKillEvent", timerID);
	}
}

<commit_msg>Allow 1 or 2 args to timer primitive while switching to new form<commit_after>/******************************************************************************

	File: Timer.cpp

	Description:

	Implementation of the Interpreter class' timer related methods

	Only one timer should every be active at any one time, so bear
	that in mind when examining the code herein.

******************************************************************************/
#include "Ist.h"

#pragma comment(lib, "winmm.lib")

#pragma code_seg(PRIM_SEG)

#include "ObjMem.h"
#include "Interprt.h"
#include "rc_vm.h"				// For error message ids
#include "InterprtPrim.inl"
#include "InterprtProc.inl"

// Smalltalk classes
#include "STExternal.h"

static UINT wTimerMax = 0xFFFF;

// Defines the maximum acceptable timer resolution, over which the VM refuses to run
static const UINT MAXTIMERRES = 60;

// Private timer function static. Modified by two threads.
static volatile UINT timerID;

uint64_t Interpreter::m_clockFrequency;

///////////////////////////////////////////////////////////////////////////////
// Smalltalk Alarm/Delay/Timers
//
// We use the Multimedia Timers because these do not fire via the message loop
// (i.e. they come back directly as under as separate thread of control in Win32),
// and are therefore much closer to the Smalltalk timer concept. These have a
// further advantage that they can operate at a much finer granularity
// (down to 1 millisecond).
//
// When we are unable to use an MM timer (e.g. because the period requested is
// too long) we can fall back on a normal Win32 timer, but these are less
// accurate, and require that the message loop is active (which SHOULD normally
// be the case, but somebody could have fiddled with the Smalltalk so there's no
// guarantee).
//

// Callback proc for MM timers
// N.B. This routine is called from a separate thread (in Win32), rather than in
// interrupt time, but careful coding is still important. The recommended
// list of routines is limited to:
//		EnterCriticalSection	ReleaseSemaphore
//		LeaveCriticalSection	SetEvent
//		timeGetSystemTime		timeGetTime
//		OutputDebugString		timeKillEvent
//		PostMessage				timeSetEvent
//
// "If a Win32 low-level audio callback [we are using mm timers here] shares data
// with other code, a Critical Section or similar mutual exclusion mechanism should
// be used to protect the integrity of the data".
// Access to the asynchronous semaphore array is protected by a critical section
// in the asynchronousSignal and CheckProcessSwitch routines. We don't really care
// that much about the timerID
void CALLBACK Interpreter::TimeProc(UINT uID, UINT /*uMsg*/, DWORD /*dwUser*/, DWORD /*dw1*/, DWORD /*dw2*/)
{
	// Avoid firing a timer which has been cancelled (or is about to be cancelled!)
	// We use an InterlockedExchange() to set the value to 0 so that the main thread
	// can recognise that the timer has fired without race conditions

	if (InterlockedExchange(LPLONG(&timerID), 0) != 0)
	{
		// If not previously killed (which is very unlikely except in certain exceptional
		// circumstances where the timer is killed at the exact moment it is about to fire)
		// then go ahead and signal the semaphore and the wakeup event

		// We mustn't access Pointers from an async thread when object memory is compacting
		// as the Pointer will be wrong
		GrabAsyncProtect();

		SemaphoreOTE* timerSemaphore = Pointers.TimingSemaphore;
		HARDASSERT(!ObjectMemoryIsIntegerObject(timerSemaphore));
		HARDASSERT(!timerSemaphore->isFree());
		HARDASSERT(timerSemaphore->m_oteClass == Pointers.ClassSemaphore);

		// Asynchronously signal the required semaphore asynchronously, which will be detected
		// in sync. with the dispatching of byte codes, and properly signalled
		asynchronousSignalNoProtect(timerSemaphore);
		// Signal the timing Event, in case the idle process has put the VM to sleep
		SetWakeupEvent();

		RelinquishAsyncProtect();
	}
	else
		// An old timer (which should have been cancelled) has fired
		trace("Old timer %d fired, current %d\n", uID, timerID);
}

///////////////////////////////////////////////////////////////////////////////
// Timer/Idling Primitives

// Signal a specified semaphore after the specified milliseconds duration (the argument).
// NOTE: NOT ABSOLUTE VALUE!
// If the specified time has already passed, then the TimingSemaphore is signalled immediately.
BOOL __fastcall Interpreter::primitiveSignalAtTick(CompiledMethod&, unsigned argumentCount)
{
	Oop tickPointer = stackTop();
	SMALLINTEGER nDelay;

	if (ObjectMemoryIsIntegerObject(tickPointer))
		nDelay = ObjectMemoryIntegerValueOf(tickPointer);
	else
	{
		OTE* oteArg = reinterpret_cast<OTE*>(tickPointer);
		return primitiveFailureWith(PrimitiveFailureNonInteger, oteArg);	// ticks must be SmallInteger
	}

	// To avoid any race conditions against the global timerID value (it is quite
	// common for the timer to fire, for example, before the timeSetEvent() call
	// has actually returned in the duration is very short because the timer thread
	// is operating at a very high priority), we use an interlocked operation

	UINT outstandingID = InterlockedExchange(LPLONG(&timerID), 0);
	// If outstanding timer now fires, it will do nothing. We'll end up killing something which is already
	// dead of course, but that should be OK
	if (outstandingID)
	{
#ifdef OAD
		TRACESTREAM << "Killing existing timer with id " << outstandingID << endl;
#endif
		UINT kill = ::timeKillEvent(outstandingID);
		if (kill != TIMERR_NOERROR)
			trace("Failed to kill timer %u (%d,%d)!\n\r", outstandingID, kill, GetLastError());
	}

	if (nDelay > 0)
	{
		// Clamp the requested delay to the maximum if it is too large. This simplifies the Delay code in the image a little.
		if (nDelay > SMALLINTEGER(wTimerMax))
		{
			nDelay = wTimerMax;
		}

		// Set the timerID to a non-zero value just in case the timer fires before timeSetEvent() returns.
		// This allows the TimerProc to recognise the timer as valid (it doesn't really care about the
		// timerID anyway, just that we're interested in it).
		// N.B. We shouldn't need an interlocked operation here because, assuming no bugs in the Win32 MM
		// timers, we've killed any outstanding timer, and the timer thread should be dormant
		timerID = UINT(-1);		// -1 is not used as a timer ID.

		UINT newTimerID = ::timeSetEvent(nDelay, 0, TimeProc, 0, TIME_ONESHOT);
		if (newTimerID && newTimerID != UINT(-1))
		{
			// Unless timer has already fired, record the timer id so can cancel if necessary
			InterlockedCompareExchange(&timerID, newTimerID, -1);
			pop(argumentCount);		// No ref. counting required
		}
		else
		{
			// System refused to set timer for some reason
			DWORD error = GetLastError();
			trace("Oh no, failed to set a timer for %d mS (%d)!\n\r", nDelay, error);
			return primitiveFailureWithInt(PrimitiveFailureSystemError, error);
		}
	}
	else if (nDelay == 0)
	{
#ifdef _DEBUG
		TRACESTREAM << "Requested delay " << dec << nDelay << " passed, signalling immediately" << endl;
#endif
		// The request time has already passed, or does not fall within the
		// available timer resolution (i.e. it will happen too soon), so signal
		// it immediately
		// We must adjust stack before signalling, as may change Process (and therefore stack!)
		pop(argumentCount);

		// N.B. Signalling may detect a process switch, but does not actually perform it
		signalSemaphore(Pointers.TimingSemaphore);
	}
	// else requested delay was negative - we allow this to clear down the existing timer

#ifdef _DEBUG
	if (newProcessWaiting())
	{
		ASSERT(m_oteNewProcess->m_oteClass == Pointers.ClassProcess);
		ProcessOTE* activeProcess = scheduler()->m_activeProcess;

		TRACESTREAM << "signalAtTick: Caused process switch to " << m_oteNewProcess
			<< endl << "\t\tfrom " << activeProcess << endl
			<< "\tasync signals " << m_qAsyncSignals.isEmpty() << ')' << endl;
	}
#endif

	// Delay could already have fired
	CheckProcessSwitch();
	return primitiveSuccess();
}

BOOL __fastcall Interpreter::primitiveMillisecondClockValue()
{
	// QPC is declared as returning (via out param) a signed value, but this makes no sense because
	// the function boils down to a wrapper around the RDTSC instruction, which Intel's docs make
	// clear provides an unsigned 64-bit counter.
	// Treating the value as unsigned allows for more efficient division operations, and of course
	// we never want a negative value for this counter (even if we'd have turned to stone long before)

	uint64_t counter;
	// Don't bother checking return value as according to the MSDN docs this won't fail on XP and later
	::QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&counter));

	// Compiler can optimize this down to a single division operation that calculates both the quotient and remainder
	uint64_t seconds = counter / m_clockFrequency;
	uint64_t remainder = counter % m_clockFrequency;

	uint64_t millisecs = seconds * 1000 + (remainder * 1000 / m_clockFrequency);
	return replaceStackTopWithNew(Integer::NewUnsigned64(millisecs));
}

BOOL __fastcall Interpreter::primitiveMicrosecondClockValue()
{
	uint64_t counter;
	::QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&counter));

	uint64_t seconds = counter / m_clockFrequency;
	uint64_t remainder = counter % m_clockFrequency;
	uint64_t microsecs = seconds * 1000000 + (remainder * 1000000 / m_clockFrequency);
	return replaceStackTopWithNew(Integer::NewUnsigned64(microsecs));
}

// Establish the desired timer resolution and create the Win32 event used to terminate
// VM idling when a timer fires
#pragma code_seg(INIT_SEG)
HRESULT Interpreter::initializeTimer()
{
	if (::QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&m_clockFrequency)) == 0)
	{
		// MSDN says this shouldn't happen: "On systems that run WindowsXP or later, the function will always succeed and will thus never return zero."
		return ReportWin32Error(IDP_NOHIRESCLOCK, ::GetLastError());
	}

	timerID = 0;
	TIMECAPS tc;
	::timeGetDevCaps(&tc, sizeof(TIMECAPS));
	wTimerMax = tc.wPeriodMax;

	return S_OK;
}

#pragma code_seg(TERM_SEG)
void Interpreter::terminateTimer()
{
	static const char* szFmt = "Shutdown Error %u calling %s(%u)\n";
	MMRESULT err;
	if (timerID != 0)
	{
		err = ::timeKillEvent(timerID);
		if (err != TIMERR_NOERROR)
			trace(szFmt, err, "timeKillEvent", timerID);
	}
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: editutil.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2004-09-08 13:41:52 $
 *
 *  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 SC_EDITUTIL_HXX
#define SC_EDITUTIL_HXX

#ifndef INCLUDED_SCDLLAPI_H
#include "scdllapi.h"
#endif

#ifndef SC_ADDRESS_HXX
#include "address.hxx"
#endif

#ifndef _MyEDITENG_HXX //autogen
#include <svx/editeng.hxx>
#endif

#ifndef _SVX_PAGEITEM_HXX //autogen
#include <svx/pageitem.hxx>
#endif

#ifndef _DATE_HXX //autogen
#include <tools/date.hxx>
#endif

#ifndef _TIME_HXX //autogen
#include <tools/time.hxx>
#endif

#ifndef _GEN_HXX //autogen
#include <tools/gen.hxx>
#endif

#ifndef _FRACT_HXX //autogen
#include <tools/fract.hxx>
#endif

class OutputDevice;
class ScDocument;
class ScPatternAttr;

class ScEditUtil
{
    ScDocument*     pDoc;
    SCCOL           nCol;
    SCROW           nRow;
    SCTAB           nTab;
    Point           aScrPos;
    OutputDevice*   pDev;           // MapMode muss eingestellt sein
    double          nPPTX;
    double          nPPTY;
    Fraction        aZoomX;
    Fraction        aZoomY;

    static const char __FAR_DATA pCalcDelimiters[];

public:
    static String ModifyDelimiters( const String& rOld );
    static String GetSpaceDelimitedString( const EditEngine& rEngine );

public:
                ScEditUtil( ScDocument* pDocument, SCCOL nX, SCROW nY, SCTAB nZ,
                            const Point& rScrPosPixel,
                            OutputDevice* pDevice, double nScaleX, double nScaleY,
                            const Fraction& rX, const Fraction& rY ) :
                    pDoc(pDocument),nCol(nX),nRow(nY),nTab(nZ),
                    aScrPos(rScrPosPixel),pDev(pDevice),
                    nPPTX(nScaleX),nPPTY(nScaleY),aZoomX(rX),aZoomY(rY) {}

    Rectangle   GetEditArea( const ScPatternAttr* pPattern, BOOL bForceToTop );
};

class ScEditAttrTester
{
    EditEngine* pEngine;
    SfxItemSet* pEditAttrs;
    BOOL        bNeedsObject;
    BOOL        bNeedsCellAttr;

public:
                ScEditAttrTester( EditEngine* pEng );
                ~ScEditAttrTester();

    BOOL                NeedsObject() const     { return bNeedsObject; }
    BOOL                NeedsCellAttr() const   { return bNeedsCellAttr; }
    const SfxItemSet&   GetAttribs() const      { return *pEditAttrs; }
};

// construct pool before constructing EditEngine, destroy pool after EditEngine
class ScEnginePoolHelper
{
protected:
    SfxItemPool*    pEnginePool;
    SfxItemSet*     pDefaults;
    BOOL            bDeleteEnginePool;
    BOOL            bDeleteDefaults;

                    ScEnginePoolHelper( SfxItemPool* pEnginePool,
                        BOOL bDeleteEnginePool = FALSE );
                    ScEnginePoolHelper( const ScEnginePoolHelper& rOrg );
    virtual         ~ScEnginePoolHelper();
};

class SC_DLLPUBLIC ScEditEngineDefaulter : public ScEnginePoolHelper, public EditEngine
{
public:
                    /// bDeleteEnginePool: Engine becomes the owner of the pool
                    /// and deletes it on destruction
                    ScEditEngineDefaulter( SfxItemPool* pEnginePool,
                        BOOL bDeleteEnginePool = FALSE );
                    /// If rOrg.bDeleteEnginePool: pool gets cloned and will be
                    /// deleted on destruction. Defaults are not set.
                    ScEditEngineDefaulter( const ScEditEngineDefaulter& rOrg );
    virtual         ~ScEditEngineDefaulter();

                    /// Creates a copy of SfxItemSet if bRememberCopy set
    void            SetDefaults( const SfxItemSet& rDefaults, BOOL bRememberCopy = TRUE );

                    /// Becomes the owner of the SfxItemSet if bTakeOwnership set
    void            SetDefaults( SfxItemSet* pDefaults, BOOL bTakeOwnership = TRUE );

                    /// Set the item in the default ItemSet which is created
                    /// if it doesn't exist yet.
                    /// The default ItemSet is then applied to each paragraph.
    void            SetDefaultItem( const SfxPoolItem& rItem );

                    /// Overwritten method to be able to apply defaults already set
    void            SetText( const EditTextObject& rTextObject );
                    /// Current defaults are not applied, new defaults are applied
    void            SetTextNewDefaults( const EditTextObject& rTextObject,
                        const SfxItemSet& rDefaults, BOOL bRememberCopy = TRUE );
                    /// Current defaults are not applied, new defaults are applied
    void            SetTextNewDefaults( const EditTextObject& rTextObject,
                        SfxItemSet* pDefaults, BOOL bTakeOwnership = TRUE );

                    /// Overwritten method to be able to apply defaults already set
    void            SetText( const String& rText );
                    /// Current defaults are not applied, new defaults are applied
    void            SetTextNewDefaults( const String& rText,
                        const SfxItemSet& rDefaults, BOOL bRememberCopy = TRUE );
                    /// Current defaults are not applied, new defaults are applied
    void            SetTextNewDefaults( const String& rText,
                        SfxItemSet* pDefaults, BOOL bTakeOwnership = TRUE );

                    /// Paragraph attributes that are not defaults are copied to
                    /// character attributes and all paragraph attributes reset
    void            RemoveParaAttribs();

                    /// Re-apply existing defaults if set, same as in SetText,
                    /// but without EnableUndo/SetUpdateMode.
    void            RepeatDefaults();
};

// 1/100 mm
class ScTabEditEngine : public ScEditEngineDefaulter
{
private:
    void    Init(const ScPatternAttr& rPattern);
public:
    ScTabEditEngine( ScDocument* pDoc );            // Default
    // pEnginePool = ScDocument.GetEnginePool()
    // pTextObjectPool = ScDocument.GetEditPool()
    ScTabEditEngine( const ScPatternAttr& rPattern,
                    SfxItemPool* pEnginePool,
                    SfxItemPool* pTextObjectPool = NULL );
};

struct ScHeaderFieldData
{
    String      aTitle;             // Titel oder Dateiname wenn kein Titel
    String      aLongDocName;       // Pfad und Dateiname
    String      aShortDocName;      // nur Dateiname
    String      aTabName;
    Date        aDate;
    Time        aTime;
    long        nPageNo;
    long        nTotalPages;
    SvxNumType  eNumType;

    ScHeaderFieldData();
};

// fuer Feldbefehle in der Tabelle
class ScFieldEditEngine : public ScEditEngineDefaulter
{
private:
    BOOL    bExecuteURL;

public:
    // pEnginePool = ScDocument.GetEnginePool()
    // pTextObjectPool = ScDocument.GetEditPool()
    ScFieldEditEngine( SfxItemPool* pEnginePool,
                        SfxItemPool* pTextObjectPool = NULL,
                        BOOL bDeleteEnginePool = FALSE );

    void    SetExecuteURL(BOOL bSet)    { bExecuteURL = bSet; }

    virtual void    FieldClicked( const SvxFieldItem& rField, USHORT, USHORT );
    virtual String  CalcFieldValue( const SvxFieldItem& rField, USHORT nPara, USHORT nPos, Color*& rTxtColor, Color*& rFldColor );
};

// for headers/footers with fields
class ScHeaderEditEngine : public ScEditEngineDefaulter
{
private:
    ScHeaderFieldData   aData;

public:
    ScHeaderEditEngine( SfxItemPool* pEnginePool, BOOL bDeleteEnginePool = FALSE );
    virtual String CalcFieldValue( const SvxFieldItem& rField, USHORT nPara, USHORT nPos, Color*& rTxtColor, Color*& rFldColor );

    void SetTitle(const String& rNew)               { aData.aTitle = rNew; }
    void SetLongDocName(const String& rNew)         { aData.aLongDocName = rNew; }
    void SetShortDocName(const String& rNew)        { aData.aShortDocName = rNew; }
    void SetTabName(const String& rNew)             { aData.aTabName = rNew; }
    void SetDate(const Date& rNew)                  { aData.aDate = rNew; }
    void SetTime(const Time& rNew)                  { aData.aTime = rNew; }
    void SetPageNo(long nNew)                       { aData.nPageNo = nNew; }
    void SetTotalPages(long nNew)                   { aData.nTotalPages = nNew; }
    void SetNumType(SvxNumType eNew)                { aData.eNumType = eNew; }
    void SetData(const ScHeaderFieldData& rNew)     { aData = rNew; }
};

// for Note text objects.
class ScNoteEditEngine : public ScEditEngineDefaulter
{

public:
    // pEnginePool = ScDocument.GetEnginePool()
    // pTextObjectPool = ScDocument.GetEditPool()
    ScNoteEditEngine( SfxItemPool* pEnginePool,
                SfxItemPool* pTextObjectPool = NULL,
                BOOL bDeleteEnginePool = FALSE );

};

//  SvxFieldData-Ableitungen sind nach Svx verschoben

#endif

<commit_msg>INTEGRATION: CWS calc30 (1.8.186); FILE MERGED 2005/02/14 16:39:46 nn 1.8.186.1: #i42764# ScEditAttrTester: compare items to cell attributes, not pool defaults<commit_after>/*************************************************************************
 *
 *  $RCSfile: editutil.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-08 15:40:59 $
 *
 *  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 SC_EDITUTIL_HXX
#define SC_EDITUTIL_HXX

#ifndef INCLUDED_SCDLLAPI_H
#include "scdllapi.h"
#endif

#ifndef SC_ADDRESS_HXX
#include "address.hxx"
#endif

#ifndef _MyEDITENG_HXX //autogen
#include <svx/editeng.hxx>
#endif

#ifndef _SVX_PAGEITEM_HXX //autogen
#include <svx/pageitem.hxx>
#endif

#ifndef _DATE_HXX //autogen
#include <tools/date.hxx>
#endif

#ifndef _TIME_HXX //autogen
#include <tools/time.hxx>
#endif

#ifndef _GEN_HXX //autogen
#include <tools/gen.hxx>
#endif

#ifndef _FRACT_HXX //autogen
#include <tools/fract.hxx>
#endif

class OutputDevice;
class ScDocument;
class ScPatternAttr;
class ScEditEngineDefaulter;

class ScEditUtil
{
    ScDocument*     pDoc;
    SCCOL           nCol;
    SCROW           nRow;
    SCTAB           nTab;
    Point           aScrPos;
    OutputDevice*   pDev;           // MapMode muss eingestellt sein
    double          nPPTX;
    double          nPPTY;
    Fraction        aZoomX;
    Fraction        aZoomY;

    static const char __FAR_DATA pCalcDelimiters[];

public:
    static String ModifyDelimiters( const String& rOld );
    static String GetSpaceDelimitedString( const EditEngine& rEngine );

public:
                ScEditUtil( ScDocument* pDocument, SCCOL nX, SCROW nY, SCTAB nZ,
                            const Point& rScrPosPixel,
                            OutputDevice* pDevice, double nScaleX, double nScaleY,
                            const Fraction& rX, const Fraction& rY ) :
                    pDoc(pDocument),nCol(nX),nRow(nY),nTab(nZ),
                    aScrPos(rScrPosPixel),pDev(pDevice),
                    nPPTX(nScaleX),nPPTY(nScaleY),aZoomX(rX),aZoomY(rY) {}

    Rectangle   GetEditArea( const ScPatternAttr* pPattern, BOOL bForceToTop );
};

class ScEditAttrTester
{
    ScEditEngineDefaulter* pEngine;
    SfxItemSet* pEditAttrs;
    BOOL        bNeedsObject;
    BOOL        bNeedsCellAttr;

public:
                ScEditAttrTester( ScEditEngineDefaulter* pEng );
                ~ScEditAttrTester();

    BOOL                NeedsObject() const     { return bNeedsObject; }
    BOOL                NeedsCellAttr() const   { return bNeedsCellAttr; }
    const SfxItemSet&   GetAttribs() const      { return *pEditAttrs; }
};

// construct pool before constructing EditEngine, destroy pool after EditEngine
class ScEnginePoolHelper
{
protected:
    SfxItemPool*    pEnginePool;
    SfxItemSet*     pDefaults;
    BOOL            bDeleteEnginePool;
    BOOL            bDeleteDefaults;

                    ScEnginePoolHelper( SfxItemPool* pEnginePool,
                        BOOL bDeleteEnginePool = FALSE );
                    ScEnginePoolHelper( const ScEnginePoolHelper& rOrg );
    virtual         ~ScEnginePoolHelper();
};

class SC_DLLPUBLIC ScEditEngineDefaulter : public ScEnginePoolHelper, public EditEngine
{
public:
                    /// bDeleteEnginePool: Engine becomes the owner of the pool
                    /// and deletes it on destruction
                    ScEditEngineDefaulter( SfxItemPool* pEnginePool,
                        BOOL bDeleteEnginePool = FALSE );
                    /// If rOrg.bDeleteEnginePool: pool gets cloned and will be
                    /// deleted on destruction. Defaults are not set.
                    ScEditEngineDefaulter( const ScEditEngineDefaulter& rOrg );
    virtual         ~ScEditEngineDefaulter();

                    /// Creates a copy of SfxItemSet if bRememberCopy set
    void            SetDefaults( const SfxItemSet& rDefaults, BOOL bRememberCopy = TRUE );

                    /// Becomes the owner of the SfxItemSet if bTakeOwnership set
    void            SetDefaults( SfxItemSet* pDefaults, BOOL bTakeOwnership = TRUE );

                    /// Set the item in the default ItemSet which is created
                    /// if it doesn't exist yet.
                    /// The default ItemSet is then applied to each paragraph.
    void            SetDefaultItem( const SfxPoolItem& rItem );

                    /// Returns the stored defaults, used to find non-default character attributes
    const SfxItemSet& GetDefaults();

                    /// Overwritten method to be able to apply defaults already set
    void            SetText( const EditTextObject& rTextObject );
                    /// Current defaults are not applied, new defaults are applied
    void            SetTextNewDefaults( const EditTextObject& rTextObject,
                        const SfxItemSet& rDefaults, BOOL bRememberCopy = TRUE );
                    /// Current defaults are not applied, new defaults are applied
    void            SetTextNewDefaults( const EditTextObject& rTextObject,
                        SfxItemSet* pDefaults, BOOL bTakeOwnership = TRUE );

                    /// Overwritten method to be able to apply defaults already set
    void            SetText( const String& rText );
                    /// Current defaults are not applied, new defaults are applied
    void            SetTextNewDefaults( const String& rText,
                        const SfxItemSet& rDefaults, BOOL bRememberCopy = TRUE );
                    /// Current defaults are not applied, new defaults are applied
    void            SetTextNewDefaults( const String& rText,
                        SfxItemSet* pDefaults, BOOL bTakeOwnership = TRUE );

                    /// Paragraph attributes that are not defaults are copied to
                    /// character attributes and all paragraph attributes reset
    void            RemoveParaAttribs();

                    /// Re-apply existing defaults if set, same as in SetText,
                    /// but without EnableUndo/SetUpdateMode.
    void            RepeatDefaults();
};

// 1/100 mm
class ScTabEditEngine : public ScEditEngineDefaulter
{
private:
    void    Init(const ScPatternAttr& rPattern);
public:
    ScTabEditEngine( ScDocument* pDoc );            // Default
    // pEnginePool = ScDocument.GetEnginePool()
    // pTextObjectPool = ScDocument.GetEditPool()
    ScTabEditEngine( const ScPatternAttr& rPattern,
                    SfxItemPool* pEnginePool,
                    SfxItemPool* pTextObjectPool = NULL );
};

struct ScHeaderFieldData
{
    String      aTitle;             // Titel oder Dateiname wenn kein Titel
    String      aLongDocName;       // Pfad und Dateiname
    String      aShortDocName;      // nur Dateiname
    String      aTabName;
    Date        aDate;
    Time        aTime;
    long        nPageNo;
    long        nTotalPages;
    SvxNumType  eNumType;

    ScHeaderFieldData();
};

// fuer Feldbefehle in der Tabelle
class ScFieldEditEngine : public ScEditEngineDefaulter
{
private:
    BOOL    bExecuteURL;

public:
    // pEnginePool = ScDocument.GetEnginePool()
    // pTextObjectPool = ScDocument.GetEditPool()
    ScFieldEditEngine( SfxItemPool* pEnginePool,
                        SfxItemPool* pTextObjectPool = NULL,
                        BOOL bDeleteEnginePool = FALSE );

    void    SetExecuteURL(BOOL bSet)    { bExecuteURL = bSet; }

    virtual void    FieldClicked( const SvxFieldItem& rField, USHORT, USHORT );
    virtual String  CalcFieldValue( const SvxFieldItem& rField, USHORT nPara, USHORT nPos, Color*& rTxtColor, Color*& rFldColor );
};

// for headers/footers with fields
class ScHeaderEditEngine : public ScEditEngineDefaulter
{
private:
    ScHeaderFieldData   aData;

public:
    ScHeaderEditEngine( SfxItemPool* pEnginePool, BOOL bDeleteEnginePool = FALSE );
    virtual String CalcFieldValue( const SvxFieldItem& rField, USHORT nPara, USHORT nPos, Color*& rTxtColor, Color*& rFldColor );

    void SetTitle(const String& rNew)               { aData.aTitle = rNew; }
    void SetLongDocName(const String& rNew)         { aData.aLongDocName = rNew; }
    void SetShortDocName(const String& rNew)        { aData.aShortDocName = rNew; }
    void SetTabName(const String& rNew)             { aData.aTabName = rNew; }
    void SetDate(const Date& rNew)                  { aData.aDate = rNew; }
    void SetTime(const Time& rNew)                  { aData.aTime = rNew; }
    void SetPageNo(long nNew)                       { aData.nPageNo = nNew; }
    void SetTotalPages(long nNew)                   { aData.nTotalPages = nNew; }
    void SetNumType(SvxNumType eNew)                { aData.eNumType = eNew; }
    void SetData(const ScHeaderFieldData& rNew)     { aData = rNew; }
};

// for Note text objects.
class ScNoteEditEngine : public ScEditEngineDefaulter
{

public:
    // pEnginePool = ScDocument.GetEnginePool()
    // pTextObjectPool = ScDocument.GetEditPool()
    ScNoteEditEngine( SfxItemPool* pEnginePool,
                SfxItemPool* pTextObjectPool = NULL,
                BOOL bDeleteEnginePool = FALSE );

};

//  SvxFieldData-Ableitungen sind nach Svx verschoben

#endif

<|endoftext|>


<commit_before>#include "BinarySearchTree.h"
#include <cassert>
#include <cstddef>
#include <deque>
#include <iostream>
#include <utility>
#include <vector>

BsNode BSNIL = {-1, &BSNIL, &BSNIL};

#define is_nil(e) ((e) == &BSNIL)
#define not_nil(e) ((e) != &BSNIL)
#define set_nil(e) ((e) = &BSNIL)
#define is_leaf(e) (is_nil((e)->left) && is_nil((e)->right))

BsNode::BsNode() {
  value = -1;
  set_nil(left);
  set_nil(right);
}

BsNode::BsNode(int v, BsNode *l, BsNode *r) {
  value = v;
  left = l;
  right = r;
}

static void DumpNode(BsNode *e) {
  if (is_nil(e)) {
    return;
  }
  std::cout << "e/left/right:" << e->value << "," << e->left->value << ","
            << e->right->value << std::endl;
  DumpNode(e->left);
  DumpNode(e->right);
}

static void DumpTree(BinarySearchTree *t, int value) {
  std::cout << std::endl;
  std::cout << "value:" << value << std::endl;
  DumpNode(t->root);
}

static BsNode *Insert(BsNode *e, int value) {
  assert(e);
  if (is_nil(e)) {
    BsNode *p = new BsNode();
    set_nil(p->left);
    set_nil(p->right);
    p->value = value;
    return p;
  }
  //二分查找
  if (e->value > value) {
    e->left = Insert(e->left, value);
  } else if (e->value < value) {
    e->right = Insert(e->right, value);
  } else {
    assert(e->value != value);
  }
  return e;
}

static BsNode *Find(BsNode *e, int value) {
  if (is_nil(e)) {
    return &BSNIL;
  }
  //二分查找
  if (e->value == value) {
    return e;
  } else if (e->value > value) {
    return Find(e->left, value);
  } else {
    return Find(e->right, value);
  }
}

static void Free(BsNode *e) {
  if (is_nil(e)) {
    return;
  }
  Free(e->left);
  Free(e->right);
  delete e;
}

static void PreOrder(BsNode *e, std::vector<int> &result) {
  if (is_nil(e)) {
    return;
  }
  result.push_back(e->value);
  PreOrder(e->left, result);
  PreOrder(e->right, result);
}

static void PostOrder(BsNode *e, std::vector<int> &result) {
  if (is_nil(e)) {
    return;
  }
  PostOrder(e->left, result);
  PostOrder(e->right, result);
  result.push_back(e->value);
}

static void InOrder(BsNode *e, std::vector<int> &result) {
  if (is_nil(e)) {
    return;
  }
  InOrder(e->left, result);
  result.push_back(e->value);
  InOrder(e->right, result);
}

BinarySearchTree *BinarySearchTreeNew() {
  BinarySearchTree *t = new BinarySearchTree();
  set_nil(t->root);
  return t;
}

void BinarySearchTreeFree(BinarySearchTree *t) {
  assert(t);
  Free(t->root);
  delete t;
}

void BinarySearchTreeInsert(BinarySearchTree *t, int value) {
  assert(t);
  assert(value >= 0);
  t->root = Insert(t->root, value);
}

BsNode *BinarySearchTreeFind(BinarySearchTree *t, int value) {
  assert(t);
  assert(value >= 0);
  return Find(t->root, value);
}

static BsNode *Next(BsNode *e) {
  if (is_nil(e->right)) {
    return &BSNIL;
  }
  BsNode *next = e->right;
  while (not_nil(next->left)) {
    next = next->left;
  }
  return next;
}

static BsNode *Erase(BsNode *e, int value) {
  assert(value >= 0);
  assert(not_nil(e));

  if (e->value > value) {
    e->left = Erase(e->left, value);
  } else if (e->value < value) {
    e->right = Erase(e->right, value);
  } else {
    // e->value == value

    if (is_nil(e->left) || is_nil(e->right)) {
      BsNode *temp = not_nil(e->left) ? e->left : e->right;
      if (is_nil(temp)) {
        // 若e没有孩子节点则直接删除

        temp = e;
        set_nil(e);
        delete temp;
      } else {
        // 若e只有一个孩子节点则直接用该孩子节点替换e

        std::swap(e, temp);
        delete temp;
      }
    } else {
      // not_nil(e->left) && not_nil(e->right)

      BsNode *next = Next(e);
      e->value = next->value;
      e->right = Erase(e->right, next->value);
    }
  }

  return e;
}

void BinarySearchTreeErase(BinarySearchTree *t, int value) {
  assert(t);
  assert(not_nil(t->root));
  assert(value >= 0);
  // DumpTree(t, value);
  t->root = Erase(t->root, value);
}

std::vector<int> BinarySearchTreePreOrder(BinarySearchTree *t) {
  std::vector<int> result;
  PreOrder(t->root, result);
  return result;
}

std::vector<int> BinarySearchTreePostOrder(BinarySearchTree *t) {
  std::vector<int> result;
  PostOrder(t->root, result);
  return result;
}

std::vector<int> BinarySearchTreeInOrder(BinarySearchTree *t) {
  std::vector<int> result;
  InOrder(t->root, result);
  return result;
}

std::vector<int> BinarySearchTreeLevelOrder(BinarySearchTree *t) {
  std::vector<int> result;
  std::deque<BsNode *> q;
  q.push_back(t->root);

  while (!q.empty()) {
    BsNode *e = q.front();
    q.pop_front();
    if (is_nil(e)) {
      continue;
    }
    result.push_back(e->value);
    q.push_back(e->left);
    q.push_back(e->right);
  }
  return result;
}

<commit_msg>remove DumpNode DumpTree function<commit_after>#include "BinarySearchTree.h"
#include <cassert>
#include <cstddef>
#include <deque>
#include <iostream>
#include <utility>
#include <vector>

BsNode BSNIL = {-1, &BSNIL, &BSNIL};

#define is_nil(e) ((e) == &BSNIL)
#define not_nil(e) ((e) != &BSNIL)
#define set_nil(e) ((e) = &BSNIL)
#define is_leaf(e) (is_nil((e)->left) && is_nil((e)->right))

BsNode::BsNode() {
  value = -1;
  set_nil(left);
  set_nil(right);
}

BsNode::BsNode(int v, BsNode *l, BsNode *r) {
  value = v;
  left = l;
  right = r;
}

static BsNode *Insert(BsNode *e, int value) {
  assert(e);
  if (is_nil(e)) {
    BsNode *p = new BsNode();
    set_nil(p->left);
    set_nil(p->right);
    p->value = value;
    return p;
  }
  //二分查找
  if (e->value > value) {
    e->left = Insert(e->left, value);
  } else if (e->value < value) {
    e->right = Insert(e->right, value);
  } else {
    assert(e->value != value);
  }
  return e;
}

static BsNode *Find(BsNode *e, int value) {
  if (is_nil(e)) {
    return &BSNIL;
  }
  //二分查找
  if (e->value == value) {
    return e;
  } else if (e->value > value) {
    return Find(e->left, value);
  } else {
    return Find(e->right, value);
  }
}

static void Free(BsNode *e) {
  if (is_nil(e)) {
    return;
  }
  Free(e->left);
  Free(e->right);
  delete e;
}

static void PreOrder(BsNode *e, std::vector<int> &result) {
  if (is_nil(e)) {
    return;
  }
  result.push_back(e->value);
  PreOrder(e->left, result);
  PreOrder(e->right, result);
}

static void PostOrder(BsNode *e, std::vector<int> &result) {
  if (is_nil(e)) {
    return;
  }
  PostOrder(e->left, result);
  PostOrder(e->right, result);
  result.push_back(e->value);
}

static void InOrder(BsNode *e, std::vector<int> &result) {
  if (is_nil(e)) {
    return;
  }
  InOrder(e->left, result);
  result.push_back(e->value);
  InOrder(e->right, result);
}

BinarySearchTree *BinarySearchTreeNew() {
  BinarySearchTree *t = new BinarySearchTree();
  set_nil(t->root);
  return t;
}

void BinarySearchTreeFree(BinarySearchTree *t) {
  assert(t);
  Free(t->root);
  delete t;
}

void BinarySearchTreeInsert(BinarySearchTree *t, int value) {
  assert(t);
  assert(value >= 0);
  t->root = Insert(t->root, value);
}

BsNode *BinarySearchTreeFind(BinarySearchTree *t, int value) {
  assert(t);
  assert(value >= 0);
  return Find(t->root, value);
}

static BsNode *Next(BsNode *e) {
  if (is_nil(e->right)) {
    return &BSNIL;
  }
  BsNode *next = e->right;
  while (not_nil(next->left)) {
    next = next->left;
  }
  return next;
}

static BsNode *Erase(BsNode *e, int value) {
  assert(value >= 0);
  assert(not_nil(e));

  if (e->value > value) {
    e->left = Erase(e->left, value);
  } else if (e->value < value) {
    e->right = Erase(e->right, value);
  } else {
    // e->value == value

    if (is_nil(e->left) || is_nil(e->right)) {
      BsNode *temp = not_nil(e->left) ? e->left : e->right;
      if (is_nil(temp)) {
        // 若e没有孩子节点则直接删除

        temp = e;
        set_nil(e);
        delete temp;
      } else {
        // 若e只有一个孩子节点则直接用该孩子节点替换e

        std::swap(e, temp);
        delete temp;
      }
    } else {
      // not_nil(e->left) && not_nil(e->right)

      BsNode *next = Next(e);
      e->value = next->value;
      e->right = Erase(e->right, next->value);
    }
  }

  return e;
}

void BinarySearchTreeErase(BinarySearchTree *t, int value) {
  assert(t);
  assert(not_nil(t->root));
  assert(value >= 0);
  t->root = Erase(t->root, value);
}

std::vector<int> BinarySearchTreePreOrder(BinarySearchTree *t) {
  std::vector<int> result;
  PreOrder(t->root, result);
  return result;
}

std::vector<int> BinarySearchTreePostOrder(BinarySearchTree *t) {
  std::vector<int> result;
  PostOrder(t->root, result);
  return result;
}

std::vector<int> BinarySearchTreeInOrder(BinarySearchTree *t) {
  std::vector<int> result;
  InOrder(t->root, result);
  return result;
}

std::vector<int> BinarySearchTreeLevelOrder(BinarySearchTree *t) {
  std::vector<int> result;
  std::deque<BsNode *> q;
  q.push_back(t->root);

  while (!q.empty()) {
    BsNode *e = q.front();
    q.pop_front();
    if (is_nil(e)) {
      continue;
    }
    result.push_back(e->value);
    q.push_back(e->left);
    q.push_back(e->right);
  }
  return result;
}

<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

// Generates Objective C gRPC service interface out of Protobuf IDL.

#include <memory>

#include "src/compiler/config.h"
#include "src/compiler/objective_c_generator.h"
#include "src/compiler/objective_c_generator_helpers.h"

class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
 public:
  ObjectiveCGrpcGenerator() {}
  virtual ~ObjectiveCGrpcGenerator() {}

  virtual bool Generate(const grpc::protobuf::FileDescriptor *file,
                        const grpc::string &parameter,
                        grpc::protobuf::compiler::GeneratorContext *context,
                        grpc::string *error) const {

    if (file->service_count() == 0) {
      // No services.  Do nothing.
      return true;
    }

    grpc::string file_name = grpc_generator::FileNameInUpperCamel(file);
    grpc::string prefix = "RMT"; // TODO

    for (int i = 0; i < file->service_count(); i++) {
      const grpc::protobuf::ServiceDescriptor *service = file->service(i);

      // Generate .pb.h

      Insert(context, file_name + ".pbobjc.h", "imports",
          "#import <gRPC/ProtoService.h>\n");

      Insert(context, file_name + ".pbobjc.h", "global_scope",
          grpc_objective_c_generator::GetHeader(service, prefix));

      // Generate .pb.m

      Insert(context, file_name + ".pbobjc.m", "imports",
          "#import <gRPC/GRXWriteable.h>\n"
          "#import <gRPC/GRXWriter+Immediate.h>\n"
          "#import <gRPC/ProtoRPC.h>\n");

      Insert(context, file_name + ".pbobjc.m", "global_scope",
          grpc_objective_c_generator::GetSource(service, prefix));
    }

    return true;
  }

 private:
  // Insert the given code into the given file at the given insertion point.
  void Insert(grpc::protobuf::compiler::GeneratorContext *context,
              const grpc::string &filename, const grpc::string &insertion_point,
              const grpc::string &code) const {
    std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
        context->OpenForInsert(filename, insertion_point));
    grpc::protobuf::io::CodedOutputStream coded_out(output.get());
    coded_out.WriteRaw(code.data(), code.size());
  }
};

int main(int argc, char *argv[]) {
  ObjectiveCGrpcGenerator generator;
  return grpc::protobuf::compiler::PluginMain(argc, argv, &generator);
}
<commit_msg>Generate separate files until either of GeneratorContext::OpenForAppend/Insert work.<commit_after>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

// Generates Objective C gRPC service interface out of Protobuf IDL.

#include <memory>

#include "src/compiler/config.h"
#include "src/compiler/objective_c_generator.h"
#include "src/compiler/objective_c_generator_helpers.h"

using ::grpc::string;

class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
 public:
  ObjectiveCGrpcGenerator() {}
  virtual ~ObjectiveCGrpcGenerator() {}

  virtual bool Generate(const grpc::protobuf::FileDescriptor *file,
                        const string &parameter,
                        grpc::protobuf::compiler::GeneratorContext *context,
                        string *error) const {

    if (file->service_count() == 0) {
      // No services.  Do nothing.
      return true;
    }

    string file_name = grpc_generator::FileNameInUpperCamel(file);
    string prefix = "RMT"; // TODO

    for (int i = 0; i < file->service_count(); i++) {
      const grpc::protobuf::ServiceDescriptor *service = file->service(i);

      {
        // Generate .pbrpc.h

        string imports = string("#import \"") + file_name + ".pbobjc.h\"\n"
          "#import <gRPC/ProtoService.h>\n";
        //Append(context, file_name + ".pbobjc.h",/* "imports",*/ imports);

        string declarations =
            grpc_objective_c_generator::GetHeader(service, prefix);
        //Append(context, file_name + ".pbobjc.h",/* "global_scope",*/
        //    declarations);

        Write(context, file_name + ".pbrpc.h", imports + declarations);
      }

      {
        // Generate .pbrpc.m

        string imports = string("#import \"") + file_name + ".pbrpc.h\"\n"
          "#import <gRPC/GRXWriteable.h>\n"
          "#import <gRPC/GRXWriter+Immediate.h>\n"
          "#import <gRPC/ProtoRPC.h>\n";
        //Append(context, file_name + ".pbobjc.m",/* "imports",*/ imports);

        string definitions =
            grpc_objective_c_generator::GetSource(service, prefix);
        //Append(context, file_name + ".pbobjc.m",/* "global_scope",*/
        //    definitions);
        Write(context, file_name + ".pbrpc.m", imports + definitions);
      }
    }

    return true;
  }

 private:
  // Insert the given code into the given file at the given insertion point.
  void Insert(grpc::protobuf::compiler::GeneratorContext *context,
              const string &filename, const string &insertion_point,
              const string &code) const {
    std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
        context->OpenForInsert(filename, insertion_point));
    grpc::protobuf::io::CodedOutputStream coded_out(output.get());
    coded_out.WriteRaw(code.data(), code.size());
  }

  // Append the given code into the given file.
  void Append(grpc::protobuf::compiler::GeneratorContext *context,
              const string &filename, const string &code) const {
    std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
        context->OpenForAppend(filename));
    grpc::protobuf::io::CodedOutputStream coded_out(output.get());
    coded_out.WriteRaw(code.data(), code.size());
  }

  // Write the given code into the given file.
  void Write(grpc::protobuf::compiler::GeneratorContext *context,
              const string &filename, const string &code) const {
    std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
        context->Open(filename));
    grpc::protobuf::io::CodedOutputStream coded_out(output.get());
    coded_out.WriteRaw(code.data(), code.size());
  }
};

int main(int argc, char *argv[]) {
  ObjectiveCGrpcGenerator generator;
  return grpc::protobuf::compiler::PluginMain(argc, argv, &generator);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2010, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// Implementations of the abstract Texture2D.
// Texture Class for handling Cairo Rendering Mode.

#include "core/cross/cairo/texture_cairo.h"
#include "core/cross/cairo/renderer_cairo.h"

namespace o3d {

namespace {

Texture::RGBASwizzleIndices g_gl_abgr32f_swizzle_indices = {0, 1, 2, 3};

}  // anonymous namespace.

namespace o2d {

static int CairoFormatFromO3DFormat(
    Texture::Format format) {
  switch (format) {
    case Texture::ARGB8:
      return CAIRO_FORMAT_ARGB32;
    case Texture::XRGB8:
      return CAIRO_FORMAT_RGB24;
    default:
      return -1;
  }
  // Cairo also supports two other pure-alpha formats, but we don't expose those
  // capabilities.
}

TextureCairo::TextureCairo(ServiceLocator* service_locator,
                           cairo_surface_t* image_surface,
                           cairo_t* image_surface_context,
                           Texture::Format format,
                           int levels,
                           int width,
                           int height,
                           bool enable_render_surfaces)
    : Texture2D(service_locator,
                width,
                height,
                format,
                levels,
                enable_render_surfaces),
      renderer_(static_cast<RendererCairo*>(
          service_locator->GetService<Renderer>())),
      image_surface_(image_surface),
      image_surface_context_(image_surface_context) {
  DLOG(INFO) << "Texture2D Construct";
  DCHECK_NE(format, Texture::UNKNOWN_FORMAT);
}

// Creates a new texture object from scratch.
TextureCairo* TextureCairo::Create(ServiceLocator* service_locator,
                                   Texture::Format format,
                                   int levels,
                                   int width,
                                   int height,
                                   bool enable_render_surfaces) {
  int cairo_format = CairoFormatFromO3DFormat(format);
  cairo_surface_t* image_surface;
  cairo_t* image_surface_context;
  cairo_status_t status;
  if (-1 == cairo_format) {
    DLOG(ERROR) << "Texture format " << format << " not supported by Cairo";
    goto fail0;
  }
  image_surface = cairo_image_surface_create(
      static_cast<cairo_format_t>(cairo_format),
      width,
      height);
  status = cairo_surface_status(image_surface);
  if (CAIRO_STATUS_SUCCESS != status) {
    DLOG(ERROR) << "Error creating Cairo image surface: " << status;
    goto fail1;
  }
  image_surface_context = cairo_create(image_surface);
  status = cairo_status(image_surface_context);
  if (CAIRO_STATUS_SUCCESS != status) {
    DLOG(ERROR) << "Error creating Cairo image surface draw context: "
                << status;
    goto fail2;
  }

  return new TextureCairo(service_locator,
                          image_surface,
                          image_surface_context,
                          format,
                          levels,
                          width,
                          height,
                          enable_render_surfaces);

 fail2:
  cairo_destroy(image_surface_context);
 fail1:
  cairo_surface_destroy(image_surface);
 fail0:
  return NULL;
}

// In 2D: is not really used
const Texture::RGBASwizzleIndices& TextureCairo::GetABGR32FSwizzleIndices() {
  NOTIMPLEMENTED();
  return g_gl_abgr32f_swizzle_indices;
}

TextureCairo::~TextureCairo() {
  cairo_destroy(image_surface_context_);
  cairo_surface_destroy(image_surface_);
  renderer_ = NULL;
  DLOG(INFO) << "Texture2DCairo Destruct";
}

// Set the image data to the renderer
void TextureCairo::SetRect(int level,
                           unsigned dst_left,
                           unsigned dst_top,
                           unsigned src_width,
                           unsigned src_height,
                           const void* src_data,
                           int src_pitch) {
  DLOG(INFO) << "Texture2DCairo SetRect";

  // Create image surface to represent the source.
  cairo_surface_t* source_image_surface = cairo_image_surface_create_for_data(
      const_cast<unsigned char*>(
          static_cast<const unsigned char*>(src_data)),
      cairo_image_surface_get_format(image_surface_),
      src_width,
      src_height,
      src_pitch);

  // Set that surface as the source for paint operations to our texture.
  cairo_set_source_surface(image_surface_context_,
                           source_image_surface,
                           dst_left,
                           dst_top);

  // Paint to the texture. This copies the data.
  cairo_paint(image_surface_context_);

  // Discard our reference to the source surface.
  cairo_surface_destroy(source_image_surface);

  if (level == 0) {
    TextureUpdated();
  }
}

// Locks the given mipmap level of this texture for loading from main memory,
// and returns a pointer to the buffer.
bool TextureCairo::PlatformSpecificLock(
    int level, void** data, int* pitch, Texture::AccessMode mode) {
  NOTIMPLEMENTED();
  return true;
}

// In Open GL: Unlocks the given mipmap level of this texture, uploading
// the main memory data buffer to GL.
//
// In 2D: is not really used
bool TextureCairo::PlatformSpecificUnlock(int level) {
  NOTIMPLEMENTED();
  return true;
}

// In 2D: is not really used
RenderSurface::Ref TextureCairo::PlatformSpecificGetRenderSurface(
    int mip_level) {
  DCHECK_LT(mip_level, levels());
  NOTIMPLEMENTED();
  return RenderSurface::Ref(NULL);
}

// Returns the implementation-specific texture handle for this texture.
void* TextureCairo::GetTextureHandle() const {
  NOTIMPLEMENTED();
  return reinterpret_cast<void*>(NULL);
}

}  // namespace o2d

}  // namespace o3d
<commit_msg>O2D: - Fix graphical artifacting for images downloaded from the Internet caused by overwriting them with their own mip-maps. This resulted in each image being rendered with copies of itself of decreasing size in one of the corners. Cairo does not support/need mip-maps, so we now just ignore the calls to set the mip-maps. - Do not alpha-blend new texture content with the old texture content, which is wrong and would have been wasting a bit of CPU too.<commit_after>/*
 * Copyright 2010, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// Implementations of the abstract Texture2D.
// Texture Class for handling Cairo Rendering Mode.

#include "core/cross/cairo/texture_cairo.h"
#include "core/cross/cairo/renderer_cairo.h"

namespace o3d {

namespace {

Texture::RGBASwizzleIndices g_gl_abgr32f_swizzle_indices = {0, 1, 2, 3};

}  // anonymous namespace.

namespace o2d {

static int CairoFormatFromO3DFormat(
    Texture::Format format) {
  switch (format) {
    case Texture::ARGB8:
      return CAIRO_FORMAT_ARGB32;
    case Texture::XRGB8:
      return CAIRO_FORMAT_RGB24;
    default:
      return -1;
  }
  // Cairo also supports two other pure-alpha formats, but we don't expose those
  // capabilities.
}

TextureCairo::TextureCairo(ServiceLocator* service_locator,
                           cairo_surface_t* image_surface,
                           cairo_t* image_surface_context,
                           Texture::Format format,
                           int levels,
                           int width,
                           int height,
                           bool enable_render_surfaces)
    : Texture2D(service_locator,
                width,
                height,
                format,
                levels,
                enable_render_surfaces),
      renderer_(static_cast<RendererCairo*>(
          service_locator->GetService<Renderer>())),
      image_surface_(image_surface),
      image_surface_context_(image_surface_context) {
  DLOG(INFO) << "Texture2D Construct";
  DCHECK_NE(format, Texture::UNKNOWN_FORMAT);
}

// Creates a new texture object from scratch.
TextureCairo* TextureCairo::Create(ServiceLocator* service_locator,
                                   Texture::Format format,
                                   int levels,
                                   int width,
                                   int height,
                                   bool enable_render_surfaces) {
  int cairo_format = CairoFormatFromO3DFormat(format);
  cairo_surface_t* image_surface;
  cairo_t* image_surface_context;
  cairo_status_t status;
  if (-1 == cairo_format) {
    DLOG(ERROR) << "Texture format " << format << " not supported by Cairo";
    goto fail0;
  }
  image_surface = cairo_image_surface_create(
      static_cast<cairo_format_t>(cairo_format),
      width,
      height);
  status = cairo_surface_status(image_surface);
  if (CAIRO_STATUS_SUCCESS != status) {
    DLOG(ERROR) << "Error creating Cairo image surface: " << status;
    goto fail1;
  }
  image_surface_context = cairo_create(image_surface);
  status = cairo_status(image_surface_context);
  if (CAIRO_STATUS_SUCCESS != status) {
    DLOG(ERROR) << "Error creating Cairo image surface draw context: "
                << status;
    goto fail2;
  }

  cairo_set_operator(image_surface_context, CAIRO_OPERATOR_SOURCE);

  return new TextureCairo(service_locator,
                          image_surface,
                          image_surface_context,
                          format,
                          levels,
                          width,
                          height,
                          enable_render_surfaces);

 fail2:
  cairo_destroy(image_surface_context);
 fail1:
  cairo_surface_destroy(image_surface);
 fail0:
  return NULL;
}

// In 2D: is not really used
const Texture::RGBASwizzleIndices& TextureCairo::GetABGR32FSwizzleIndices() {
  NOTIMPLEMENTED();
  return g_gl_abgr32f_swizzle_indices;
}

TextureCairo::~TextureCairo() {
  cairo_destroy(image_surface_context_);
  cairo_surface_destroy(image_surface_);
  renderer_ = NULL;
  DLOG(INFO) << "Texture2DCairo Destruct";
}

// Set the image data to the renderer
void TextureCairo::SetRect(int level,
                           unsigned dst_left,
                           unsigned dst_top,
                           unsigned src_width,
                           unsigned src_height,
                           const void* src_data,
                           int src_pitch) {
  DLOG(INFO) << "Texture2DCairo SetRect";

  if (0 != level) {
    // Cairo does not support/need mip-maps.
    return;
  }

  // Create image surface to represent the source.
  cairo_surface_t* source_image_surface = cairo_image_surface_create_for_data(
      const_cast<unsigned char*>(
          static_cast<const unsigned char*>(src_data)),
      cairo_image_surface_get_format(image_surface_),
      src_width,
      src_height,
      src_pitch);

  // Set that surface as the source for paint operations to our texture.
  cairo_set_source_surface(image_surface_context_,
                           source_image_surface,
                           dst_left,
                           dst_top);

  // Paint to the texture. This copies the data.
  cairo_paint(image_surface_context_);

  // Discard our reference to the source surface.
  cairo_surface_destroy(source_image_surface);

  TextureUpdated();
}

// Locks the given mipmap level of this texture for loading from main memory,
// and returns a pointer to the buffer.
bool TextureCairo::PlatformSpecificLock(
    int level, void** data, int* pitch, Texture::AccessMode mode) {
  NOTIMPLEMENTED();
  return true;
}

// In Open GL: Unlocks the given mipmap level of this texture, uploading
// the main memory data buffer to GL.
//
// In 2D: is not really used
bool TextureCairo::PlatformSpecificUnlock(int level) {
  NOTIMPLEMENTED();
  return true;
}

// In 2D: is not really used
RenderSurface::Ref TextureCairo::PlatformSpecificGetRenderSurface(
    int mip_level) {
  DCHECK_LT(mip_level, levels());
  NOTIMPLEMENTED();
  return RenderSurface::Ref(NULL);
}

// Returns the implementation-specific texture handle for this texture.
void* TextureCairo::GetTextureHandle() const {
  NOTIMPLEMENTED();
  return reinterpret_cast<void*>(NULL);
}

}  // namespace o2d

}  // namespace o3d
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: fltlst.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2005-07-20 12:25:01 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#include "fltlst.hxx"

//*****************************************************************************************************************
//  includes
//*****************************************************************************************************************
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif

#include "sfxuno.hxx"
#include "docfac.hxx"

#include <vcl/svapp.hxx>
#include <vos/mutex.hxx>

//*****************************************************************************************************************
//  namespaces
//*****************************************************************************************************************
using namespace ::com::sun::star;

//*****************************************************************************************************************
//  definitions
//*****************************************************************************************************************

/*-************************************************************************************************************//**
    @short          ctor
    @descr          These initialize an instance of a SfxFilterListener class. Created object listen automaticly
                    on right FilterFactory-Service for all changes and synchronize right SfxFilterContainer with
                    corresponding framework-cache.
                    We use given "sFactory" value to decide which query must be used to fill "pContainer" with new values.
                    Given "pContainer" hold us alive as uno reference and we use it to syschronize it with framework caches.
                    We will die, if he die! see dtor for further informations.

    @seealso        dtor
    @seealso        class framework::FilterCache
    @seealso        service ::document::FilterFactory

    @param          "sFactory"  , short name of module which contains filter container
    @param          "pContainer", pointer to filter container which will be informed
    @return         -

    @onerror        We show some assertions in non product version.
                    Otherwise we do nothing!
    @threadsafe     yes

    @last_change    17.10.2001 10:27
*//*-*************************************************************************************************************/
SfxFilterListener::SfxFilterListener()
{
    uno::Reference< lang::XMultiServiceFactory > xSmgr = ::comphelper::getProcessServiceFactory();
    if( xSmgr.is() == sal_True )
    {
        uno::Reference< util::XRefreshable > xNotifier( xSmgr->createInstance( DEFINE_CONST_OUSTRING("com.sun.star.document.FilterConfigRefresh") ), uno::UNO_QUERY );
        if( xNotifier.is() == sal_True )
        {
            m_xFilterCache = xNotifier;
            m_xFilterCache->addRefreshListener( this );
        }
    }
}

SfxFilterListener::~SfxFilterListener()
{
}

void SAL_CALL SfxFilterListener::refreshed( const lang::EventObject& aSource ) throw( uno::RuntimeException )
{
    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    uno::Reference< util::XRefreshable > xContainer( aSource.Source, uno::UNO_QUERY );
    if(
        (xContainer.is()           ) &&
        (xContainer==m_xFilterCache)
      )
    {
        SfxFilterContainer::ReadFilters_Impl( TRUE );
    }
}

void SAL_CALL SfxFilterListener::disposing( const lang::EventObject& aSource ) throw( uno::RuntimeException )
{
    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    uno::Reference< util::XRefreshable > xNotifier( aSource.Source, uno::UNO_QUERY );
    if (!xNotifier.is())
        return;

    if (xNotifier == m_xFilterCache)
        m_xFilterCache.clear();
}
<commit_msg>INTEGRATION: CWS ooo19126 (1.6.40); FILE MERGED 2005/09/05 15:22:21 rt 1.6.40.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fltlst.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 17:53:37 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "fltlst.hxx"

//*****************************************************************************************************************
//  includes
//*****************************************************************************************************************
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif

#include "sfxuno.hxx"
#include "docfac.hxx"

#include <vcl/svapp.hxx>
#include <vos/mutex.hxx>

//*****************************************************************************************************************
//  namespaces
//*****************************************************************************************************************
using namespace ::com::sun::star;

//*****************************************************************************************************************
//  definitions
//*****************************************************************************************************************

/*-************************************************************************************************************//**
    @short          ctor
    @descr          These initialize an instance of a SfxFilterListener class. Created object listen automaticly
                    on right FilterFactory-Service for all changes and synchronize right SfxFilterContainer with
                    corresponding framework-cache.
                    We use given "sFactory" value to decide which query must be used to fill "pContainer" with new values.
                    Given "pContainer" hold us alive as uno reference and we use it to syschronize it with framework caches.
                    We will die, if he die! see dtor for further informations.

    @seealso        dtor
    @seealso        class framework::FilterCache
    @seealso        service ::document::FilterFactory

    @param          "sFactory"  , short name of module which contains filter container
    @param          "pContainer", pointer to filter container which will be informed
    @return         -

    @onerror        We show some assertions in non product version.
                    Otherwise we do nothing!
    @threadsafe     yes

    @last_change    17.10.2001 10:27
*//*-*************************************************************************************************************/
SfxFilterListener::SfxFilterListener()
{
    uno::Reference< lang::XMultiServiceFactory > xSmgr = ::comphelper::getProcessServiceFactory();
    if( xSmgr.is() == sal_True )
    {
        uno::Reference< util::XRefreshable > xNotifier( xSmgr->createInstance( DEFINE_CONST_OUSTRING("com.sun.star.document.FilterConfigRefresh") ), uno::UNO_QUERY );
        if( xNotifier.is() == sal_True )
        {
            m_xFilterCache = xNotifier;
            m_xFilterCache->addRefreshListener( this );
        }
    }
}

SfxFilterListener::~SfxFilterListener()
{
}

void SAL_CALL SfxFilterListener::refreshed( const lang::EventObject& aSource ) throw( uno::RuntimeException )
{
    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    uno::Reference< util::XRefreshable > xContainer( aSource.Source, uno::UNO_QUERY );
    if(
        (xContainer.is()           ) &&
        (xContainer==m_xFilterCache)
      )
    {
        SfxFilterContainer::ReadFilters_Impl( TRUE );
    }
}

void SAL_CALL SfxFilterListener::disposing( const lang::EventObject& aSource ) throw( uno::RuntimeException )
{
    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    uno::Reference< util::XRefreshable > xNotifier( aSource.Source, uno::UNO_QUERY );
    if (!xNotifier.is())
        return;

    if (xNotifier == m_xFilterCache)
        m_xFilterCache.clear();
}
<|endoftext|>