<commit_before>/* RTcmix  - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <rtcmix_types.h>
#include <Option.h>
#include <PField.h>
#include <RTcmixMIDI.h>
#include <RTMidiPField.h>
#include <ugens.h>		// for warn, die

//FIXME: better to have a struct with one field a string, the other type?

#define NAME_VARIANTS	4
static char *_midi_type_name[][NAME_VARIANTS] = {
	// NB: Order of these must correspond to indices given by MIDIType enum!
	{ "cntl", "control", NULL, NULL },
	{ "noteonpitch", "onpitch", NULL, NULL },
	{ "noteonvel", "onvel", NULL, NULL },
	{ "noteoffpitch", "offpitch", NULL, NULL },
	{ "noteoffvel", "offvel", NULL, NULL },
	{ "bend", "pitchbend", NULL, NULL },
	{ "prog", "program", NULL, NULL },
	{ "chanpress", "monopress", "at", "aftertouch" },
	{ "polypress", "keypress", "polyat", "polyaftertouch" },
	{ NULL, NULL, NULL, NULL }
};

static char *_midi_controller_name[128] = {
				"", "mod", "breath", "", "foot",
				"port time", "data", "volume", "balance", "",
/* 10 */		"pan", "expression", "fxctl1", "fxctl2", "",
				"", "gp1", "gp2", "gp3", "gp4",
/* 20 */		"", "", "", "", "",
				"", "", "", "", "",
/* 30 */		"", "", "", "", "",
				"", "", "", "", "",
/* 40 */		"", "", "", "", "",
				"", "", "", "", "",
/* 50 */		"", "", "", "", "",
				"", "", "", "", "",
/* 60 */		"", "", "", "", "sustainsw",
				"portamentosw", "sostenutosw", "softpedsw", "legatosw", "hold2sw",
/* 70 */		"sc1", "sc2", "sc3", "sc4", "sc5",
				"sc6", "sc7", "sc8", "sc9", "sc10",
/* 80 */		"gp5", "gp6", "gp7", "gp8", "portamento",
				"", "", "", "", "",
/* 90 */		"", "fx1depth", "fx2depth", "fx3depth", "fx4depth",
				"fx5depth", "dataincr", "datadecr", "nrplsb", "nrpmsb",
/* 100 */	"rplsb", "rpmsb", "", "", "",
				"", "", "", "", "",
/* 110 */	"", "", "", "", "",
				"", "", "", "", "",
/* 120 */	"sound off", "reset cntl", "local cntl", "notes off", "omni off",
				"omni on", "mono on", "poly on"
};

// --------------------------------------------------------- midi_connection ---
//
//    midi = makeconnection("midi", min, max, default, lag, chan, type,
//                                                                [subtype])
//
//    <chan>      MIDI channel (1-16)
//
//    <type>      "noteonpitch", "noteonvel", "noteoffpitch", "noteoffpitch"
//                "cntl", "prog", "bend", "chanpress", "polypress"
//
//    <subtype>   depends on <type>:
//                   cntl       controller number or string symbol, such as
//                              "mod", "foot", "breath", "data", "volume", "pan"
//                   polypress  MIDI note number
//                   [no subtypes for the other types]
//

static RTNumberPField *
_midi_usage()
{
	die("makeconnection (midi)",
		"Usage: makeconnection(\"midi\", min, max, default, lag, "
		"chan, type[, subtype])");
	return NULL;
}

static MIDIType
_string_to_type(const char *type)
{
	for (int i = 0; _midi_type_name[i][0] != NULL; i++) {
		for (int j = 0; j < NAME_VARIANTS; j++) {
			const char *name = _midi_type_name[i][j];
			if (name == NULL)
				break;
			if (strcasecmp(type, name) == 0)
				return (MIDIType) i;
		}
	}
	return kMIDIInvalidType;
}

static MIDISubType
_string_to_subtype(const MIDIType type, const char *subtype)
{
	if (type == kMIDIControlType) {
		for (int i = 0; i < 128; i++) {
			const char *name = _midi_controller_name[i];
			if (strcmp(subtype, name) == 0)
				return (MIDISubType) i;
		}
	}
	return kMIDIInvalidSubType;
}

/* Parse MIDI control name string, a sequence of colon-separated strings,
   with line-splicing recognition and some white-space eating.  Reads this:

      midi_control_names = " \
         bank select: \
         modulation wheel: \
         : \
         foot: \
         ...
         last name"

   resulting in these names: "bank select", "modulation wheel", "", "foot",
   ... "last name".  All except the empty "" override the builtin names.
*/
static void
_read_config()
{
#ifdef NOTYET
	char *names = strdup(Option::midiCntlNames());
	char *p, buf[128];
	int i = 0;
	int j = 0;
	bool eatspace = true;
	for (i = 0, p = names; i < 128 && *p != 0; p++) {
		if (eatspace && isspace(*p))
			continue;
		if (*p == '\\')
			continue;
		if (*p == ':') {
			buf[j] = 0;
			if (buf[0])
				_midi_controller_name[i] = strdup(buf);
			i++;
			j = 0;
			eatspace = true;
		}
		else {
			buf[j++] = *p;
			if (j == 127) {
				warn("makeconnection (midi)",
						"Controller name in config file too long");
				break;
			}
			eatspace = false;
		}
	}
	free(names);
#endif
}

static RTNumberPField *
create_pfield(const Arg args[], const int nargs)
{
	static bool configRead = false;

	static RTcmixMIDI *midiport = NULL;
	if (midiport == NULL)				// first time, so init midi system
		midiport = createMIDIPort();
	if (midiport == NULL)
		return NULL;

	if (configRead == false) {
		_read_config();
		configRead = true;
	}

	double minval, maxval, defaultval, lag;
	int chan;
	MIDIType type = kMIDIInvalidType;
	MIDISubType subtype = kMIDIInvalidSubType;

	if (args[0].isType(DoubleType))
		minval = args[0];
	else
		return _midi_usage();

	if (args[1].isType(DoubleType))
		maxval = args[1];
	else
		return _midi_usage();

	if (args[2].isType(DoubleType))
		defaultval = args[2];
	else
		return _midi_usage();

	if (args[3].isType(DoubleType))
		lag = args[3];
	else
		return _midi_usage();
	if (lag < 0.0 || lag > 100.0) {
		die("makeconnection (midi)", "<lag> must be between 0 and 100");
		return NULL;
	}

	if (args[4].isType(DoubleType))
		chan = (int) args[4] - 1;		// convert to zero-based channel
	else
		return _midi_usage();
	if (chan < 0 || chan > 15) {
		die("makeconnection (midi)", "<chan> must be between 1 and 16");
		return NULL;
	}

	if (args[5].isType(StringType))
		type = _string_to_type(args[5]);
	else
		return _midi_usage();
	if (type == kMIDIInvalidType)
		return _midi_usage();

	if (nargs > 6) {
		if (args[6].isType(StringType))
			subtype = _string_to_subtype(type, args[6]);
		else if (args[6].isType(DoubleType))
			// NB: this can be a code or a literal int, e.g. note or controller num
			subtype = (MIDISubType) (int) args[6];
		else
			return _midi_usage();
		if (subtype == kMIDIInvalidSubType)
			return _midi_usage();
	}

	return new RTMidiPField(midiport, minval, maxval, defaultval, lag, chan,
																		type, subtype);
}

// The following functions are the publically-visible ones called by the
// system.

extern "C" {
	Handle create_handle(const Arg args[], const int nargs);
	int register_dso();
};

Handle
create_handle(const Arg args[], const int nargs)
{
	PField *pField = create_pfield(args, nargs);
	Handle handle = NULL;
	if (pField != NULL) {
		handle = new struct _handle;
		handle->type = PFieldType;
		handle->ptr = (void *) pField;
	}
	return handle;
}

int register_dso()
{
	 return 0;
}
<commit_msg>Convert lag to [0,1].<commit_after>/* RTcmix  - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <rtcmix_types.h>
#include <Option.h>
#include <PField.h>
#include <RTcmixMIDI.h>
#include <RTMidiPField.h>
#include <ugens.h>		// for warn, die

//FIXME: better to have a struct with one field a string, the other type?

#define NAME_VARIANTS	4
static char *_midi_type_name[][NAME_VARIANTS] = {
	// NB: Order of these must correspond to indices given by MIDIType enum!
	{ "cntl", "control", NULL, NULL },
	{ "noteonpitch", "onpitch", NULL, NULL },
	{ "noteonvel", "onvel", NULL, NULL },
	{ "noteoffpitch", "offpitch", NULL, NULL },
	{ "noteoffvel", "offvel", NULL, NULL },
	{ "bend", "pitchbend", NULL, NULL },
	{ "prog", "program", NULL, NULL },
	{ "chanpress", "monopress", "at", "aftertouch" },
	{ "polypress", "keypress", "polyat", "polyaftertouch" },
	{ NULL, NULL, NULL, NULL }
};

static char *_midi_controller_name[128] = {
				"", "mod", "breath", "", "foot",
				"port time", "data", "volume", "balance", "",
/* 10 */		"pan", "expression", "fxctl1", "fxctl2", "",
				"", "gp1", "gp2", "gp3", "gp4",
/* 20 */		"", "", "", "", "",
				"", "", "", "", "",
/* 30 */		"", "", "", "", "",
				"", "", "", "", "",
/* 40 */		"", "", "", "", "",
				"", "", "", "", "",
/* 50 */		"", "", "", "", "",
				"", "", "", "", "",
/* 60 */		"", "", "", "", "sustainsw",
				"portamentosw", "sostenutosw", "softpedsw", "legatosw", "hold2sw",
/* 70 */		"sc1", "sc2", "sc3", "sc4", "sc5",
				"sc6", "sc7", "sc8", "sc9", "sc10",
/* 80 */		"gp5", "gp6", "gp7", "gp8", "portamento",
				"", "", "", "", "",
/* 90 */		"", "fx1depth", "fx2depth", "fx3depth", "fx4depth",
				"fx5depth", "dataincr", "datadecr", "nrplsb", "nrpmsb",
/* 100 */	"rplsb", "rpmsb", "", "", "",
				"", "", "", "", "",
/* 110 */	"", "", "", "", "",
				"", "", "", "", "",
/* 120 */	"sound off", "reset cntl", "local cntl", "notes off", "omni off",
				"omni on", "mono on", "poly on"
};

// --------------------------------------------------------- midi_connection ---
//
//    midi = makeconnection("midi", min, max, default, lag, chan, type,
//                                                                [subtype])
//
//    <chan>      MIDI channel (1-16)
//
//    <type>      "noteonpitch", "noteonvel", "noteoffpitch", "noteoffpitch"
//                "cntl", "prog", "bend", "chanpress", "polypress"
//
//    <subtype>   depends on <type>:
//                   cntl       controller number or string symbol, such as
//                              "mod", "foot", "breath", "data", "volume", "pan"
//                   polypress  MIDI note number
//                   [no subtypes for the other types]
//

static RTNumberPField *
_midi_usage()
{
	die("makeconnection (midi)",
		"Usage: makeconnection(\"midi\", min, max, default, lag, "
		"chan, type[, subtype])");
	return NULL;
}

static MIDIType
_string_to_type(const char *type)
{
	for (int i = 0; _midi_type_name[i][0] != NULL; i++) {
		for (int j = 0; j < NAME_VARIANTS; j++) {
			const char *name = _midi_type_name[i][j];
			if (name == NULL)
				break;
			if (strcasecmp(type, name) == 0)
				return (MIDIType) i;
		}
	}
	return kMIDIInvalidType;
}

static MIDISubType
_string_to_subtype(const MIDIType type, const char *subtype)
{
	if (type == kMIDIControlType) {
		for (int i = 0; i < 128; i++) {
			const char *name = _midi_controller_name[i];
			if (strcmp(subtype, name) == 0)
				return (MIDISubType) i;
		}
	}
	return kMIDIInvalidSubType;
}

/* Parse MIDI control name string, a sequence of colon-separated strings,
   with line-splicing recognition and some white-space eating.  Reads this:

      midi_control_names = " \
         bank select: \
         modulation wheel: \
         : \
         foot: \
         ...
         last name"

   resulting in these names: "bank select", "modulation wheel", "", "foot",
   ... "last name".  All except the empty "" override the builtin names.
*/
static void
_read_config()
{
#ifdef NOTYET
	char *names = strdup(Option::midiCntlNames());
	char *p, buf[128];
	int i = 0;
	int j = 0;
	bool eatspace = true;
	for (i = 0, p = names; i < 128 && *p != 0; p++) {
		if (eatspace && isspace(*p))
			continue;
		if (*p == '\\')
			continue;
		if (*p == ':') {
			buf[j] = 0;
			if (buf[0])
				_midi_controller_name[i] = strdup(buf);
			i++;
			j = 0;
			eatspace = true;
		}
		else {
			buf[j++] = *p;
			if (j == 127) {
				warn("makeconnection (midi)",
						"Controller name in config file too long");
				break;
			}
			eatspace = false;
		}
	}
	free(names);
#endif
}

static RTNumberPField *
create_pfield(const Arg args[], const int nargs)
{
	static bool configRead = false;

	static RTcmixMIDI *midiport = NULL;
	if (midiport == NULL)				// first time, so init midi system
		midiport = createMIDIPort();
	if (midiport == NULL)
		return NULL;

	if (configRead == false) {
		_read_config();
		configRead = true;
	}

	double minval, maxval, defaultval, lag;
	int chan;
	MIDIType type = kMIDIInvalidType;
	MIDISubType subtype = kMIDIInvalidSubType;

	if (args[0].isType(DoubleType))
		minval = args[0];
	else
		return _midi_usage();

	if (args[1].isType(DoubleType))
		maxval = args[1];
	else
		return _midi_usage();

	if (args[2].isType(DoubleType))
		defaultval = args[2];
	else
		return _midi_usage();

	if (args[3].isType(DoubleType))
		lag = args[3];
	else
		return _midi_usage();
	if (lag < 0.0 || lag > 100.0) {
		die("makeconnection (midi)", "<lag> must be between 0 and 100");
		return NULL;
	}
	lag *= 0.01;

	if (args[4].isType(DoubleType))
		chan = (int) args[4] - 1;		// convert to zero-based channel
	else
		return _midi_usage();
	if (chan < 0 || chan > 15) {
		die("makeconnection (midi)", "<chan> must be between 1 and 16");
		return NULL;
	}

	if (args[5].isType(StringType))
		type = _string_to_type(args[5]);
	else
		return _midi_usage();
	if (type == kMIDIInvalidType)
		return _midi_usage();

	if (nargs > 6) {
		if (args[6].isType(StringType))
			subtype = _string_to_subtype(type, args[6]);
		else if (args[6].isType(DoubleType))
			// NB: this can be a code or a literal int, e.g. note or controller num
			subtype = (MIDISubType) (int) args[6];
		else
			return _midi_usage();
		if (subtype == kMIDIInvalidSubType)
			return _midi_usage();
	}

	return new RTMidiPField(midiport, minval, maxval, defaultval, lag, chan,
																		type, subtype);
}

// The following functions are the publically-visible ones called by the
// system.

extern "C" {
	Handle create_handle(const Arg args[], const int nargs);
	int register_dso();
};

Handle
create_handle(const Arg args[], const int nargs)
{
	PField *pField = create_pfield(args, nargs);
	Handle handle = NULL;
	if (pField != NULL) {
		handle = new struct _handle;
		handle->type = PFieldType;
		handle->ptr = (void *) pField;
	}
	return handle;
}

int register_dso()
{
	 return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: iframe.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 22:28:34 $
 *
 *  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 "iframe.hxx"
#include "sfxdlg.hxx"
#include "sfxsids.hrc"

#ifndef _COM_SUN_STAR_FRAME_XDISPATCHPROVIDER_HPP_
#include <com/sun/star/frame/XDispatchProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XDISPATCH_HPP_
#include <com/sun/star/frame/XDispatch.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_
#include <com/sun/star/util/XURLTransformer.hpp>
#endif

#include <tools/urlobj.hxx>
#include <tools/debug.hxx>
#include <rtl/ustring.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <svtools/miscopt.hxx>
#include <vcl/window.hxx>

using namespace ::com::sun::star;

namespace sfx2
{

class IFrameWindow_Impl : public Window
{
    uno::Reference < frame::XFrame > mxFrame;
    sal_Bool                bActive;
    sal_Bool                bBorder;

public:
    IFrameWindow_Impl( Window *pParent,
                       sal_Bool bHasBorder,
                       WinBits nWinBits = 0 );

public:
    void            SetBorder( sal_Bool bNewBorder = sal_True );
    sal_Bool        HasBorder() const { return bBorder; }
};

IFrameWindow_Impl::IFrameWindow_Impl( Window *pParent, sal_Bool bHasBorder, WinBits nWinBits )
    : Window( pParent, nWinBits | WB_CLIPCHILDREN | WB_NODIALOGCONTROL | WB_DOCKBORDER )
    , bActive(sal_False)
    , bBorder(bHasBorder)
{
    if ( !bHasBorder )
        SetBorderStyle( WINDOW_BORDER_NOBORDER );
    else
        SetBorderStyle( WINDOW_BORDER_NORMAL );
    //SetActivateMode( ACTIVATE_MODE_GRABFOCUS );
}

void IFrameWindow_Impl::SetBorder( sal_Bool bNewBorder )
{
    if ( bBorder != bNewBorder )
    {
        Size aSize = GetSizePixel();
        bBorder = bNewBorder;
        if ( bBorder )
            SetBorderStyle( WINDOW_BORDER_NORMAL );
        else
            SetBorderStyle( WINDOW_BORDER_NOBORDER );
        if ( GetSizePixel() != aSize )
            SetSizePixel( aSize );
    }
}

#define PROPERTY_UNBOUND 0

SfxItemPropertyMap aIFramePropertyMap_Impl[] =
{
    { "FrameIsAutoBorder",    17, 1, &::getBooleanCppuType(), PROPERTY_UNBOUND, 0 },
    { "FrameIsAutoScroll",    17, 2, &::getBooleanCppuType(), PROPERTY_UNBOUND, 0 },
    { "FrameIsBorder",        13, 3, &::getBooleanCppuType(), PROPERTY_UNBOUND, 0 },
    { "FrameIsScrollingMode", 20, 4, &::getBooleanCppuType(), PROPERTY_UNBOUND, 0 },
    { "FrameMarginHeight",    17, 5, &::getCppuType( (sal_Int32*)0 ), PROPERTY_UNBOUND, 0 },
    { "FrameMarginWidth",     16, 6, &::getCppuType( (sal_Int32*)0 ), PROPERTY_UNBOUND, 0 },
    { "FrameName",             9, 7, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
    { "FrameURL",              8, 8, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
    {0,0,0,0,0,0}
};

SFX_IMPL_XSERVICEINFO( IFrameObject, "com.sun.star.embed.SpecialEmbeddedObject", "com.sun.star.comp.sfx2.IFrameObject" )
SFX_IMPL_SINGLEFACTORY( IFrameObject );

IFrameObject::IFrameObject( const uno::Reference < lang::XMultiServiceFactory >& rFact )
    : mxFact( rFact )
    , maPropSet( aIFramePropertyMap_Impl )
{
}

IFrameObject::~IFrameObject()
{
}

void SAL_CALL IFrameObject::initialize( const uno::Sequence< uno::Any >& aArguments ) throw ( uno::Exception, uno::RuntimeException )
{
    if ( aArguments.getLength() )
        aArguments[0] >>= mxObj;
}

sal_Bool SAL_CALL IFrameObject::load(
    const uno::Sequence < com::sun::star::beans::PropertyValue >& /*lDescriptor*/,
    const uno::Reference < frame::XFrame >& xFrame )
throw( uno::RuntimeException )
{
    if ( SvtMiscOptions().IsPluginsEnabled() )
    {
        DBG_ASSERT( !mxFrame.is(), "Frame already existing!" );
        Window* pParent = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
        IFrameWindow_Impl* pWin = new IFrameWindow_Impl( pParent, maFrmDescr.IsFrameBorderOn() );
        pWin->SetSizePixel( pParent->GetOutputSizePixel() );
        pWin->SetBackground();
        pWin->Show();

        uno::Reference < awt::XWindow > xWindow( pWin->GetComponentInterface(), uno::UNO_QUERY );
        xFrame->setComponent( xWindow, uno::Reference < frame::XController >() );

        // we must destroy the IFrame before the parent is destroyed
        xWindow->addEventListener( this );

        mxFrame = uno::Reference< frame::XFrame >( mxFact->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.frame.Frame" ) ),
                    uno::UNO_QUERY );
        uno::Reference < awt::XWindow > xWin( pWin->GetComponentInterface(), uno::UNO_QUERY );
        mxFrame->initialize( xWin );
        mxFrame->setName( maFrmDescr.GetName() );

        uno::Reference< frame::XDispatchProvider > xProv( mxFrame, uno::UNO_QUERY );

        util::URL aTargetURL;
        aTargetURL.Complete = ::rtl::OUString( maFrmDescr.GetURL().GetMainURL( INetURLObject::NO_DECODE ) );
        uno::Reference < util::XURLTransformer > xTrans( mxFact->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), uno::UNO_QUERY );
        xTrans->parseStrict( aTargetURL );

        uno::Sequence < beans::PropertyValue > aProps(2);
        aProps[0].Name = ::rtl::OUString::createFromAscii("PluginMode");
        aProps[0].Value <<= (sal_Int16) 2;
        aProps[1].Name = ::rtl::OUString::createFromAscii("ReadOnly");
        aProps[1].Value <<= (sal_Bool) sal_True;
        uno::Reference < frame::XDispatch > xDisp = xProv->queryDispatch( aTargetURL, ::rtl::OUString::createFromAscii("_self"), 0 );
        if ( xDisp.is() )
            xDisp->dispatch( aTargetURL, aProps );

        return TRUE;
    }

    return FALSE;
}

void SAL_CALL IFrameObject::cancel() throw( com::sun::star::uno::RuntimeException )
{
    try
    {
        uno::Reference < util::XCloseable > xClose( mxFrame, uno::UNO_QUERY );
        if ( xClose.is() )
            xClose->close( sal_True );
        mxFrame = 0;
    }
    catch ( uno::Exception& )
    {}
}

void SAL_CALL IFrameObject::close( sal_Bool /*bDeliverOwnership*/ ) throw( com::sun::star::util::CloseVetoException, com::sun::star::uno::RuntimeException )
{
}

void SAL_CALL IFrameObject::addCloseListener( const com::sun::star::uno::Reference < com::sun::star::util::XCloseListener >& ) throw( com::sun::star::uno::RuntimeException )
{
}

void SAL_CALL IFrameObject::removeCloseListener( const com::sun::star::uno::Reference < com::sun::star::util::XCloseListener >& ) throw( com::sun::star::uno::RuntimeException )
{
}

void SAL_CALL IFrameObject::disposing( const com::sun::star::lang::EventObject& ) throw (com::sun::star::uno::RuntimeException)
{
    cancel();
}

uno::Reference< beans::XPropertySetInfo > SAL_CALL IFrameObject::getPropertySetInfo() throw( ::com::sun::star::uno::RuntimeException )
{
    return maPropSet.getPropertySetInfo();
}

void SAL_CALL IFrameObject::setPropertyValue(const ::rtl::OUString& aPropertyName, const uno::Any& aAny)
    throw ( beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
{
    if ( aPropertyName.equalsAscii("FrameURL") )
    {
        ::rtl::OUString aURL;
        aAny >>= aURL;
        maFrmDescr.SetURL( String(aURL) );
    }
    else if ( aPropertyName.equalsAscii("FrameName") )
    {
        ::rtl::OUString aName;
        if ( aAny >>= aName )
            maFrmDescr.SetName( aName );
    }
    else if ( aPropertyName.equalsAscii("FrameIsAutoScroll") )
    {
        sal_Bool bIsAutoScroll;
        if ( (aAny >>= bIsAutoScroll) && bIsAutoScroll )
            maFrmDescr.SetScrollingMode( ScrollingAuto );
    }
    else if ( aPropertyName.equalsAscii("FrameIsScrollingMode") )
    {
        sal_Bool bIsScroll;
        if ( aAny >>= bIsScroll )
            maFrmDescr.SetScrollingMode( bIsScroll ? ScrollingYes : ScrollingNo );
    }
    else if ( aPropertyName.equalsAscii("FrameIsBorder") )
    {
        sal_Bool bIsBorder;
        if ( aAny >>= bIsBorder )
            maFrmDescr.SetFrameBorder( bIsBorder );
    }
    else if ( aPropertyName.equalsAscii("FrameIsAutoBorder") )
    {
        sal_Bool bIsAutoBorder;
        if ( (aAny >>= bIsAutoBorder) )
        {
            BOOL bBorder = maFrmDescr.IsFrameBorderOn();
            maFrmDescr.ResetBorder();
            if ( bIsAutoBorder )
                maFrmDescr.SetFrameBorder( bBorder );
        }
    }
    else if ( aPropertyName.equalsAscii("FrameMarginWidth") )
    {
        sal_Int32 nMargin;
        Size aSize = maFrmDescr.GetMargin();
        if ( aAny >>= nMargin )
        {
            aSize.Width() = nMargin;
            maFrmDescr.SetMargin( aSize );
        }
    }
    else if ( aPropertyName.equalsAscii("FrameMarginHeight") )
    {
        sal_Int32 nMargin;
        Size aSize = maFrmDescr.GetMargin();
        if ( aAny >>= nMargin )
        {
            aSize.Height() = nMargin;
            maFrmDescr.SetMargin( aSize );
        }
    }
    else
         throw beans::UnknownPropertyException();
}

uno::Any SAL_CALL IFrameObject::getPropertyValue(const ::rtl::OUString& aPropertyName)
        throw ( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
{
    uno::Any aAny;
    if ( aPropertyName.equalsAscii("FrameURL") )
    {
        aAny <<= ::rtl::OUString( maFrmDescr.GetURL().GetMainURL( INetURLObject::NO_DECODE ) );
    }
    else if ( aPropertyName.equalsAscii("FrameName") )
    {
        aAny <<= ::rtl::OUString( maFrmDescr.GetName() );
    }
    else if ( aPropertyName.equalsAscii("FrameIsAutoScroll") )
    {
        sal_Bool bIsAutoScroll = ( maFrmDescr.GetScrollingMode() == ScrollingAuto );
        aAny <<= bIsAutoScroll;
    }
    else if ( aPropertyName.equalsAscii("FrameIsScrollingMode") )
    {
        sal_Bool bIsScroll = ( maFrmDescr.GetScrollingMode() == ScrollingYes );
        aAny <<= bIsScroll;
    }
    else if ( aPropertyName.equalsAscii("FrameIsBorder") )
    {
        sal_Bool bIsBorder = maFrmDescr.IsFrameBorderOn();
        aAny <<= bIsBorder;
    }
    else if ( aPropertyName.equalsAscii("FrameIsAutoBorder") )
    {
        sal_Bool bIsAutoBorder = !maFrmDescr.IsFrameBorderSet();
        aAny <<= bIsAutoBorder;
    }
    else if ( aPropertyName.equalsAscii("FrameMarginWidth") )
    {
        aAny <<= (sal_Int32 ) maFrmDescr.GetMargin().Width();
    }
    else if ( aPropertyName.equalsAscii("FrameMarginHeight") )
    {
        aAny <<= (sal_Int32 ) maFrmDescr.GetMargin().Height();
    }
    else
         throw beans::UnknownPropertyException();
    return aAny;
}

void SAL_CALL IFrameObject::addPropertyChangeListener(const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener > & ) throw( ::com::sun::star::uno::RuntimeException )
{
}

void SAL_CALL IFrameObject::removePropertyChangeListener(const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener > & ) throw( ::com::sun::star::uno::RuntimeException )
{
}

void SAL_CALL IFrameObject::addVetoableChangeListener(const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener > & ) throw( ::com::sun::star::uno::RuntimeException )
{
}

void SAL_CALL IFrameObject::removeVetoableChangeListener(const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener > & ) throw( ::com::sun::star::uno::RuntimeException )
{
}

::sal_Int16 SAL_CALL IFrameObject::execute() throw (::com::sun::star::uno::RuntimeException)
{
    SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
    VclAbstractDialog* pDlg = pFact->CreateEditObjectDialog( NULL, SID_INSERT_FLOATINGFRAME, mxObj );
    if ( pDlg )
        pDlg->Execute();
    return 0;
}

void SAL_CALL IFrameObject::setTitle( const ::rtl::OUString& ) throw (::com::sun::star::uno::RuntimeException)
{
}

}
<commit_msg>INTEGRATION: CWS warningfixes03_SRC680 (1.6.86); FILE MERGED 2006/08/18 15:03:42 mhu 1.6.86.1: #i68745# Fixed GCC 4.0.x warning(s).<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: iframe.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: ihi $ $Date: 2006-08-29 11:16:29 $
 *
 *  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 "iframe.hxx"
#include "sfxdlg.hxx"
#include "sfxsids.hrc"

#ifndef _COM_SUN_STAR_FRAME_XDISPATCHPROVIDER_HPP_
#include <com/sun/star/frame/XDispatchProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XDISPATCH_HPP_
#include <com/sun/star/frame/XDispatch.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_
#include <com/sun/star/util/XURLTransformer.hpp>
#endif

#include <tools/urlobj.hxx>
#include <tools/debug.hxx>
#include <rtl/ustring.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <svtools/miscopt.hxx>
#include <vcl/window.hxx>

using namespace ::com::sun::star;

namespace sfx2
{

class IFrameWindow_Impl : public Window
{
    uno::Reference < frame::XFrame > mxFrame;
    sal_Bool                bActive;
    sal_Bool                bBorder;

public:
    IFrameWindow_Impl( Window *pParent,
                       sal_Bool bHasBorder,
                       WinBits nWinBits = 0 );

public:
    void            SetBorder( sal_Bool bNewBorder = sal_True );
    sal_Bool        HasBorder() const { return bBorder; }
};

IFrameWindow_Impl::IFrameWindow_Impl( Window *pParent, sal_Bool bHasBorder, WinBits nWinBits )
    : Window( pParent, nWinBits | WB_CLIPCHILDREN | WB_NODIALOGCONTROL | WB_DOCKBORDER )
    , bActive(sal_False)
    , bBorder(bHasBorder)
{
    if ( !bHasBorder )
        SetBorderStyle( WINDOW_BORDER_NOBORDER );
    else
        SetBorderStyle( WINDOW_BORDER_NORMAL );
    //SetActivateMode( ACTIVATE_MODE_GRABFOCUS );
}

void IFrameWindow_Impl::SetBorder( sal_Bool bNewBorder )
{
    if ( bBorder != bNewBorder )
    {
        Size aSize = GetSizePixel();
        bBorder = bNewBorder;
        if ( bBorder )
            SetBorderStyle( WINDOW_BORDER_NORMAL );
        else
            SetBorderStyle( WINDOW_BORDER_NOBORDER );
        if ( GetSizePixel() != aSize )
            SetSizePixel( aSize );
    }
}

#define PROPERTY_UNBOUND 0

SfxItemPropertyMap aIFramePropertyMap_Impl[] =
{
    { "FrameIsAutoBorder",    17, 1, &::getBooleanCppuType(), PROPERTY_UNBOUND, 0 },
    { "FrameIsAutoScroll",    17, 2, &::getBooleanCppuType(), PROPERTY_UNBOUND, 0 },
    { "FrameIsBorder",        13, 3, &::getBooleanCppuType(), PROPERTY_UNBOUND, 0 },
    { "FrameIsScrollingMode", 20, 4, &::getBooleanCppuType(), PROPERTY_UNBOUND, 0 },
    { "FrameMarginHeight",    17, 5, &::getCppuType( (sal_Int32*)0 ), PROPERTY_UNBOUND, 0 },
    { "FrameMarginWidth",     16, 6, &::getCppuType( (sal_Int32*)0 ), PROPERTY_UNBOUND, 0 },
    { "FrameName",             9, 7, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
    { "FrameURL",              8, 8, &::getCppuType((const ::rtl::OUString*)0), PROPERTY_UNBOUND, 0 },
    {0,0,0,0,0,0}
};

SFX_IMPL_XSERVICEINFO( IFrameObject, "com.sun.star.embed.SpecialEmbeddedObject", "com.sun.star.comp.sfx2.IFrameObject" )
SFX_IMPL_SINGLEFACTORY( IFrameObject );

IFrameObject::IFrameObject( const uno::Reference < lang::XMultiServiceFactory >& rFact )
    : mxFact( rFact )
    , maPropSet( aIFramePropertyMap_Impl )
{
}

IFrameObject::~IFrameObject()
{
}

void SAL_CALL IFrameObject::initialize( const uno::Sequence< uno::Any >& aArguments ) throw ( uno::Exception, uno::RuntimeException )
{
    if ( aArguments.getLength() )
        aArguments[0] >>= mxObj;
}

sal_Bool SAL_CALL IFrameObject::load(
    const uno::Sequence < com::sun::star::beans::PropertyValue >& /*lDescriptor*/,
    const uno::Reference < frame::XFrame >& xFrame )
throw( uno::RuntimeException )
{
    if ( SvtMiscOptions().IsPluginsEnabled() )
    {
        DBG_ASSERT( !mxFrame.is(), "Frame already existing!" );
        Window* pParent = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
        IFrameWindow_Impl* pWin = new IFrameWindow_Impl( pParent, maFrmDescr.IsFrameBorderOn() );
        pWin->SetSizePixel( pParent->GetOutputSizePixel() );
        pWin->SetBackground();
        pWin->Show();

        uno::Reference < awt::XWindow > xWindow( pWin->GetComponentInterface(), uno::UNO_QUERY );
        xFrame->setComponent( xWindow, uno::Reference < frame::XController >() );

        // we must destroy the IFrame before the parent is destroyed
        xWindow->addEventListener( this );

        mxFrame = uno::Reference< frame::XFrame >( mxFact->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.frame.Frame" ) ),
                    uno::UNO_QUERY );
        uno::Reference < awt::XWindow > xWin( pWin->GetComponentInterface(), uno::UNO_QUERY );
        mxFrame->initialize( xWin );
        mxFrame->setName( maFrmDescr.GetName() );

        uno::Reference< frame::XDispatchProvider > xProv( mxFrame, uno::UNO_QUERY );

        util::URL aTargetURL;
        aTargetURL.Complete = ::rtl::OUString( maFrmDescr.GetURL().GetMainURL( INetURLObject::NO_DECODE ) );
        uno::Reference < util::XURLTransformer > xTrans( mxFact->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), uno::UNO_QUERY );
        xTrans->parseStrict( aTargetURL );

        uno::Sequence < beans::PropertyValue > aProps(2);
        aProps[0].Name = ::rtl::OUString::createFromAscii("PluginMode");
        aProps[0].Value <<= (sal_Int16) 2;
        aProps[1].Name = ::rtl::OUString::createFromAscii("ReadOnly");
        aProps[1].Value <<= (sal_Bool) sal_True;
        uno::Reference < frame::XDispatch > xDisp = xProv->queryDispatch( aTargetURL, ::rtl::OUString::createFromAscii("_self"), 0 );
        if ( xDisp.is() )
            xDisp->dispatch( aTargetURL, aProps );

        return TRUE;
    }

    return FALSE;
}

void SAL_CALL IFrameObject::cancel() throw( com::sun::star::uno::RuntimeException )
{
    try
    {
        uno::Reference < util::XCloseable > xClose( mxFrame, uno::UNO_QUERY );
        if ( xClose.is() )
            xClose->close( sal_True );
        mxFrame = 0;
    }
    catch ( uno::Exception& )
    {}
}

void SAL_CALL IFrameObject::close( sal_Bool /*bDeliverOwnership*/ ) throw( com::sun::star::util::CloseVetoException, com::sun::star::uno::RuntimeException )
{
}

void SAL_CALL IFrameObject::addCloseListener( const com::sun::star::uno::Reference < com::sun::star::util::XCloseListener >& ) throw( com::sun::star::uno::RuntimeException )
{
}

void SAL_CALL IFrameObject::removeCloseListener( const com::sun::star::uno::Reference < com::sun::star::util::XCloseListener >& ) throw( com::sun::star::uno::RuntimeException )
{
}

void SAL_CALL IFrameObject::disposing( const com::sun::star::lang::EventObject& ) throw (com::sun::star::uno::RuntimeException)
{
    cancel();
}

uno::Reference< beans::XPropertySetInfo > SAL_CALL IFrameObject::getPropertySetInfo() throw( ::com::sun::star::uno::RuntimeException )
{
    return maPropSet.getPropertySetInfo();
}

void SAL_CALL IFrameObject::setPropertyValue(const ::rtl::OUString& aPropertyName, const uno::Any& aAny)
    throw ( beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
{
    if ( aPropertyName.equalsAscii("FrameURL") )
    {
        ::rtl::OUString aURL;
        aAny >>= aURL;
        maFrmDescr.SetURL( String(aURL) );
    }
    else if ( aPropertyName.equalsAscii("FrameName") )
    {
        ::rtl::OUString aName;
        if ( aAny >>= aName )
            maFrmDescr.SetName( aName );
    }
    else if ( aPropertyName.equalsAscii("FrameIsAutoScroll") )
    {
        sal_Bool bIsAutoScroll = sal_Bool();
        if ( (aAny >>= bIsAutoScroll) && bIsAutoScroll )
            maFrmDescr.SetScrollingMode( ScrollingAuto );
    }
    else if ( aPropertyName.equalsAscii("FrameIsScrollingMode") )
    {
        sal_Bool bIsScroll = sal_Bool();
        if ( aAny >>= bIsScroll )
            maFrmDescr.SetScrollingMode( bIsScroll ? ScrollingYes : ScrollingNo );
    }
    else if ( aPropertyName.equalsAscii("FrameIsBorder") )
    {
        sal_Bool bIsBorder = sal_Bool();
        if ( aAny >>= bIsBorder )
            maFrmDescr.SetFrameBorder( bIsBorder );
    }
    else if ( aPropertyName.equalsAscii("FrameIsAutoBorder") )
    {
        sal_Bool bIsAutoBorder = sal_Bool();
        if ( (aAny >>= bIsAutoBorder) )
        {
            BOOL bBorder = maFrmDescr.IsFrameBorderOn();
            maFrmDescr.ResetBorder();
            if ( bIsAutoBorder )
                maFrmDescr.SetFrameBorder( bBorder );
        }
    }
    else if ( aPropertyName.equalsAscii("FrameMarginWidth") )
    {
        sal_Int32 nMargin;
        Size aSize = maFrmDescr.GetMargin();
        if ( aAny >>= nMargin )
        {
            aSize.Width() = nMargin;
            maFrmDescr.SetMargin( aSize );
        }
    }
    else if ( aPropertyName.equalsAscii("FrameMarginHeight") )
    {
        sal_Int32 nMargin;
        Size aSize = maFrmDescr.GetMargin();
        if ( aAny >>= nMargin )
        {
            aSize.Height() = nMargin;
            maFrmDescr.SetMargin( aSize );
        }
    }
    else
         throw beans::UnknownPropertyException();
}

uno::Any SAL_CALL IFrameObject::getPropertyValue(const ::rtl::OUString& aPropertyName)
        throw ( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
{
    uno::Any aAny;
    if ( aPropertyName.equalsAscii("FrameURL") )
    {
        aAny <<= ::rtl::OUString( maFrmDescr.GetURL().GetMainURL( INetURLObject::NO_DECODE ) );
    }
    else if ( aPropertyName.equalsAscii("FrameName") )
    {
        aAny <<= ::rtl::OUString( maFrmDescr.GetName() );
    }
    else if ( aPropertyName.equalsAscii("FrameIsAutoScroll") )
    {
        sal_Bool bIsAutoScroll = ( maFrmDescr.GetScrollingMode() == ScrollingAuto );
        aAny <<= bIsAutoScroll;
    }
    else if ( aPropertyName.equalsAscii("FrameIsScrollingMode") )
    {
        sal_Bool bIsScroll = ( maFrmDescr.GetScrollingMode() == ScrollingYes );
        aAny <<= bIsScroll;
    }
    else if ( aPropertyName.equalsAscii("FrameIsBorder") )
    {
        sal_Bool bIsBorder = maFrmDescr.IsFrameBorderOn();
        aAny <<= bIsBorder;
    }
    else if ( aPropertyName.equalsAscii("FrameIsAutoBorder") )
    {
        sal_Bool bIsAutoBorder = !maFrmDescr.IsFrameBorderSet();
        aAny <<= bIsAutoBorder;
    }
    else if ( aPropertyName.equalsAscii("FrameMarginWidth") )
    {
        aAny <<= (sal_Int32 ) maFrmDescr.GetMargin().Width();
    }
    else if ( aPropertyName.equalsAscii("FrameMarginHeight") )
    {
        aAny <<= (sal_Int32 ) maFrmDescr.GetMargin().Height();
    }
    else
         throw beans::UnknownPropertyException();
    return aAny;
}

void SAL_CALL IFrameObject::addPropertyChangeListener(const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener > & ) throw( ::com::sun::star::uno::RuntimeException )
{
}

void SAL_CALL IFrameObject::removePropertyChangeListener(const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener > & ) throw( ::com::sun::star::uno::RuntimeException )
{
}

void SAL_CALL IFrameObject::addVetoableChangeListener(const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener > & ) throw( ::com::sun::star::uno::RuntimeException )
{
}

void SAL_CALL IFrameObject::removeVetoableChangeListener(const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener > & ) throw( ::com::sun::star::uno::RuntimeException )
{
}

::sal_Int16 SAL_CALL IFrameObject::execute() throw (::com::sun::star::uno::RuntimeException)
{
    SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
    VclAbstractDialog* pDlg = pFact->CreateEditObjectDialog( NULL, SID_INSERT_FLOATINGFRAME, mxObj );
    if ( pDlg )
        pDlg->Execute();
    return 0;
}

void SAL_CALL IFrameObject::setTitle( const ::rtl::OUString& ) throw (::com::sun::star::uno::RuntimeException)
{
}

}
<|endoftext|>


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

#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColorSpaceXform.h"
#include "SkColorSpaceXformPriv.h"
#include "SkConfig8888.h"
#include "SkColorPriv.h"
#include "SkDither.h"
#include "SkImageInfoPriv.h"
#include "SkMathPriv.h"
#include "SkOpts.h"
#include "SkPM4fPriv.h"
#include "SkRasterPipeline.h"
#include "SkUnPreMultiplyPriv.h"

// Fast Path 1: The memcpy() case.
static inline bool can_memcpy(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) {
    if (dstInfo.colorType() != srcInfo.colorType()) {
        return false;
    }

    if (dstInfo.alphaType() != srcInfo.alphaType() &&
        kOpaque_SkAlphaType != dstInfo.alphaType() &&
        kOpaque_SkAlphaType != srcInfo.alphaType())
    {
        // We need to premultiply or unpremultiply.
        return false;
    }

    return !dstInfo.colorSpace() ||
           SkColorSpace::Equals(dstInfo.colorSpace(), srcInfo.colorSpace());
}

enum AlphaVerb {
    kNothing_AlphaVerb,
    kPremul_AlphaVerb,
    kUnpremul_AlphaVerb,
};

template <bool kSwapRB>
static void wrap_unpremultiply(uint32_t* dst, const void* src, int count) {
    SkUnpremultiplyRow<kSwapRB>(dst, (const uint32_t*) src, count);
}

// Fast Path 2: Simple swizzles and premuls.
void swizzle_and_multiply(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
                          const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB) {
    void (*proc)(uint32_t* dst, const void* src, int count);
    const bool swapRB = dstInfo.colorType() != srcInfo.colorType();
    AlphaVerb alphaVerb = kNothing_AlphaVerb;
    if (kPremul_SkAlphaType == dstInfo.alphaType() &&
        kUnpremul_SkAlphaType == srcInfo.alphaType())
    {
        alphaVerb = kPremul_AlphaVerb;
    } else if (kUnpremul_SkAlphaType == dstInfo.alphaType() &&
               kPremul_SkAlphaType == srcInfo.alphaType()) {
        alphaVerb = kUnpremul_AlphaVerb;
    }

    switch (alphaVerb) {
        case kNothing_AlphaVerb:
            // If we do not need to swap or multiply, we should hit the memcpy case.
            SkASSERT(swapRB);
            proc = SkOpts::RGBA_to_BGRA;
            break;
        case kPremul_AlphaVerb:
            proc = swapRB ? SkOpts::RGBA_to_bgrA : SkOpts::RGBA_to_rgbA;
            break;
        case kUnpremul_AlphaVerb:
            proc = swapRB ? wrap_unpremultiply<true> : wrap_unpremultiply<false>;
            break;
    }

    for (int y = 0; y < dstInfo.height(); y++) {
        proc((uint32_t*) dstPixels, srcPixels, dstInfo.width());
        dstPixels = SkTAddOffset<void>(dstPixels, dstRB);
        srcPixels = SkTAddOffset<const void>(srcPixels, srcRB);
    }
}

// Default: Use the pipeline.
static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_t dstRB,
                                 const SkImageInfo& srcInfo, const void* srcRow, size_t srcRB,
                                 bool isColorAware) {
    SkRasterPipeline pipeline;
    switch (srcInfo.colorType()) {
        case kRGBA_8888_SkColorType:
            pipeline.append(SkRasterPipeline::load_8888, &srcRow);
            break;
        case kBGRA_8888_SkColorType:
            pipeline.append(SkRasterPipeline::load_8888, &srcRow);
            pipeline.append(SkRasterPipeline::swap_rb);
            break;
        case kRGB_565_SkColorType:
            pipeline.append(SkRasterPipeline::load_565, &srcRow);
            break;
        case kRGBA_F16_SkColorType:
            pipeline.append(SkRasterPipeline::load_f16, &srcRow);
            break;
        case kGray_8_SkColorType:
            pipeline.append(SkRasterPipeline::load_g8, &srcRow);
            break;
        default:
            return false;
    }

    if (isColorAware && srcInfo.gammaCloseToSRGB()) {
        pipeline.append_from_srgb(srcInfo.alphaType());
    }

    float matrix[12];
    if (isColorAware) {
        SkAssertResult(append_gamut_transform(&pipeline, matrix, srcInfo.colorSpace(),
                                              dstInfo.colorSpace()));
    }

    SkAlphaType sat = srcInfo.alphaType();
    SkAlphaType dat = dstInfo.alphaType();
    if (sat == kPremul_SkAlphaType && dat == kUnpremul_SkAlphaType) {
        pipeline.append(SkRasterPipeline::unpremul);
    } else if (sat == kUnpremul_SkAlphaType && dat == kPremul_SkAlphaType) {
        pipeline.append(SkRasterPipeline::premul);
    }

    if (isColorAware && dstInfo.gammaCloseToSRGB()) {
        pipeline.append(SkRasterPipeline::to_srgb);
    }

    switch (dstInfo.colorType()) {
        case kRGBA_8888_SkColorType:
            pipeline.append(SkRasterPipeline::store_8888, &dstRow);
            break;
        case kBGRA_8888_SkColorType:
            pipeline.append(SkRasterPipeline::swap_rb);
            pipeline.append(SkRasterPipeline::store_8888, &dstRow);
            break;
        case kRGB_565_SkColorType:
            pipeline.append(SkRasterPipeline::store_565, &dstRow);
            break;
        case kRGBA_F16_SkColorType:
            pipeline.append(SkRasterPipeline::store_f16, &dstRow);
            break;
        default:
            return false;
    }

    auto p = pipeline.compile();

    for (int y = 0; y < srcInfo.height(); ++y) {
        p(0,srcInfo.width());
        // The pipeline has pointers to srcRow and dstRow, so we just need to update them in the
        // loop to move between rows of src/dst.
        dstRow = SkTAddOffset<void>(dstRow, dstRB);
        srcRow = SkTAddOffset<const void>(srcRow, srcRB);
    }
    return true;
}

static bool extract_alpha(void* dst, size_t dstRB, const void* src, size_t srcRB,
                          const SkImageInfo& srcInfo, SkColorTable* ctable) {
    uint8_t* SK_RESTRICT dst8 = (uint8_t*)dst;

    const int w = srcInfo.width();
    const int h = srcInfo.height();
    if (srcInfo.isOpaque()) {
        // src is opaque, so just fill alpha with 0xFF
        for (int y = 0; y < h; ++y) {
           memset(dst8, 0xFF, w);
           dst8 += dstRB;
        }
        return true;
    }
    switch (srcInfo.colorType()) {
        case kN32_SkColorType: {
            const SkPMColor* SK_RESTRICT src32 = (const SkPMColor*)src;
            for (int y = 0; y < h; ++y) {
                for (int x = 0; x < w; ++x) {
                    dst8[x] = SkGetPackedA32(src32[x]);
                }
                dst8 += dstRB;
                src32 = (const SkPMColor*)((const char*)src32 + srcRB);
            }
            break;
        }
        case kARGB_4444_SkColorType: {
            const SkPMColor16* SK_RESTRICT src16 = (const SkPMColor16*)src;
            for (int y = 0; y < h; ++y) {
                for (int x = 0; x < w; ++x) {
                    dst8[x] = SkPacked4444ToA32(src16[x]);
                }
                dst8 += dstRB;
                src16 = (const SkPMColor16*)((const char*)src16 + srcRB);
            }
            break;
        }
        case kIndex_8_SkColorType: {
            if (nullptr == ctable) {
                return false;
            }
            const SkPMColor* SK_RESTRICT table = ctable->readColors();
            const uint8_t* SK_RESTRICT src8 = (const uint8_t*)src;
            for (int y = 0; y < h; ++y) {
                for (int x = 0; x < w; ++x) {
                    dst8[x] = SkGetPackedA32(table[src8[x]]);
                }
                dst8 += dstRB;
                src8 += srcRB;
            }
            break;
        }
        default:
            return false;
    }
    return true;
}

static inline bool optimized_color_xform(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) {
    if (kUnpremul_SkAlphaType == dstInfo.alphaType() && kPremul_SkAlphaType == srcInfo.alphaType())
    {
        return false;
    }

    switch (dstInfo.colorType()) {
        case kRGBA_8888_SkColorType:
        case kBGRA_8888_SkColorType:
        case kRGBA_F16_SkColorType:
            break;
        default:
            return false;
    }

    switch (srcInfo.colorType()) {
        case kRGBA_8888_SkColorType:
        case kBGRA_8888_SkColorType:
            break;
        default:
            return false;
    }

    return true;
}

static inline void apply_color_xform(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
                                     const SkImageInfo& srcInfo, const void* srcPixels,
                                     size_t srcRB) {
    SkColorSpaceXform::ColorFormat dstFormat = select_xform_format(dstInfo.colorType());
    SkColorSpaceXform::ColorFormat srcFormat = select_xform_format(srcInfo.colorType());
    SkAlphaType xformAlpha;
    switch (srcInfo.alphaType()) {
        case kOpaque_SkAlphaType:
            xformAlpha = kOpaque_SkAlphaType;
            break;
        case kPremul_SkAlphaType:
            SkASSERT(kPremul_SkAlphaType == dstInfo.alphaType());

            // This signal means: copy the src alpha to the dst, do not premultiply (in this
            // case because the pixels are already premultiplied).
            xformAlpha = kUnpremul_SkAlphaType;
            break;
        case kUnpremul_SkAlphaType:
            SkASSERT(kPremul_SkAlphaType == dstInfo.alphaType() ||
                     kUnpremul_SkAlphaType == dstInfo.alphaType());

            xformAlpha = dstInfo.alphaType();
            break;
        default:
            SkASSERT(false);
            xformAlpha = kUnpremul_SkAlphaType;
            break;
    }

    std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcInfo.colorSpace(),
                                                                      dstInfo.colorSpace());
    SkASSERT(xform);

    for (int y = 0; y < dstInfo.height(); y++) {
        SkAssertResult(xform->apply(dstFormat, dstPixels, srcFormat, srcPixels, dstInfo.width(),
                       xformAlpha));
        dstPixels = SkTAddOffset<void>(dstPixels, dstRB);
        srcPixels = SkTAddOffset<const void>(srcPixels, srcRB);
    }
}

bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
                             const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
                             SkColorTable* ctable) {
    SkASSERT(dstInfo.dimensions() == srcInfo.dimensions());
    SkASSERT(SkImageInfoValidConversion(dstInfo, srcInfo));

    const int width = srcInfo.width();
    const int height = srcInfo.height();

    // Fast Path 1: The memcpy() case.
    if (can_memcpy(dstInfo, srcInfo)) {
        SkRectMemcpy(dstPixels, dstRB, srcPixels, srcRB, dstInfo.minRowBytes(), dstInfo.height());
        return true;
    }

    const bool isColorAware = dstInfo.colorSpace();
    SkASSERT(srcInfo.colorSpace() || !isColorAware);

    // Fast Path 2: Simple swizzles and premuls.
    if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel() && !isColorAware) {
        swizzle_and_multiply(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB);
        return true;
    }

    if (isColorAware && optimized_color_xform(dstInfo, srcInfo)) {
        apply_color_xform(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB);
        return true;
    }

    /*
     *  Begin section where we try to change colorTypes along the way. Not all combinations
     *  are supported.
     */

    if (kAlpha_8_SkColorType == dstInfo.colorType() &&
        extract_alpha(dstPixels, dstRB, srcPixels, srcRB, srcInfo, ctable)) {
        return true;
    }

    //  Try the pipeline
    //
    if (copy_pipeline_pixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable)) {
        return true;
    }

    // Can no longer draw directly into 4444, but we can manually whack it for a few combinations
    if (kARGB_4444_SkColorType == dstInfo.colorType() &&
        (kN32_SkColorType == srcInfo.colorType() || kIndex_8_SkColorType == srcInfo.colorType())) {
        if (srcInfo.alphaType() == kUnpremul_SkAlphaType) {
            // Our method for converting to 4444 assumes premultiplied.
            return false;
        }

        const SkPMColor* table = nullptr;
        if (kIndex_8_SkColorType == srcInfo.colorType()) {
            SkASSERT(ctable);
            table = ctable->readColors();
        }

        for (int y = 0; y < height; ++y) {
            DITHER_4444_SCAN(y);
            SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*)dstPixels;
            if (table) {
                const uint8_t* SK_RESTRICT srcRow = (const uint8_t*)srcPixels;
                for (int x = 0; x < width; ++x) {
                    dstRow[x] = SkDitherARGB32To4444(table[srcRow[x]], DITHER_VALUE(x));
                }
            } else {
                const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)srcPixels;
                for (int x = 0; x < width; ++x) {
                    dstRow[x] = SkDitherARGB32To4444(srcRow[x], DITHER_VALUE(x));
                }
            }
            dstPixels = (char*)dstPixels + dstRB;
            srcPixels = (const char*)srcPixels + srcRB;
        }
        return true;
    }

    if (dstInfo.alphaType() == kUnpremul_SkAlphaType) {
        // We do not support drawing to unpremultiplied bitmaps.
        return false;
    }

    // Final fall-back, draw with a canvas
    //
    // Always clear the dest in case one of the blitters accesses it
    // TODO: switch the allocation of tmpDst to call sk_calloc_throw
    {
        SkBitmap bm;
        if (!bm.installPixels(srcInfo, const_cast<void*>(srcPixels), srcRB, ctable, nullptr, nullptr)) {
            return false;
        }
        std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(dstInfo, dstPixels, dstRB);
        if (!canvas) {
            return false;
        }

        SkPaint  paint;
        paint.setDither(true);

        canvas->clear(0);
        canvas->drawBitmap(bm, 0, 0, &paint);
        return true;
    }
}
<commit_msg>Fix CopyPixels() bug<commit_after>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColorSpaceXform.h"
#include "SkColorSpaceXformPriv.h"
#include "SkConfig8888.h"
#include "SkColorPriv.h"
#include "SkDither.h"
#include "SkImageInfoPriv.h"
#include "SkMathPriv.h"
#include "SkOpts.h"
#include "SkPM4fPriv.h"
#include "SkRasterPipeline.h"
#include "SkUnPreMultiplyPriv.h"

// Fast Path 1: The memcpy() case.
static inline bool can_memcpy(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) {
    if (dstInfo.colorType() != srcInfo.colorType()) {
        return false;
    }

    if (dstInfo.alphaType() != srcInfo.alphaType() &&
        kOpaque_SkAlphaType != dstInfo.alphaType() &&
        kOpaque_SkAlphaType != srcInfo.alphaType())
    {
        // We need to premultiply or unpremultiply.
        return false;
    }

    return !dstInfo.colorSpace() ||
           SkColorSpace::Equals(dstInfo.colorSpace(), srcInfo.colorSpace());
}

enum AlphaVerb {
    kNothing_AlphaVerb,
    kPremul_AlphaVerb,
    kUnpremul_AlphaVerb,
};

template <bool kSwapRB>
static void wrap_unpremultiply(uint32_t* dst, const void* src, int count) {
    SkUnpremultiplyRow<kSwapRB>(dst, (const uint32_t*) src, count);
}

// Fast Path 2: Simple swizzles and premuls.
void swizzle_and_multiply(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
                          const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB) {
    void (*proc)(uint32_t* dst, const void* src, int count);
    const bool swapRB = dstInfo.colorType() != srcInfo.colorType();
    AlphaVerb alphaVerb = kNothing_AlphaVerb;
    if (kPremul_SkAlphaType == dstInfo.alphaType() &&
        kUnpremul_SkAlphaType == srcInfo.alphaType())
    {
        alphaVerb = kPremul_AlphaVerb;
    } else if (kUnpremul_SkAlphaType == dstInfo.alphaType() &&
               kPremul_SkAlphaType == srcInfo.alphaType()) {
        alphaVerb = kUnpremul_AlphaVerb;
    }

    switch (alphaVerb) {
        case kNothing_AlphaVerb:
            // If we do not need to swap or multiply, we should hit the memcpy case.
            SkASSERT(swapRB);
            proc = SkOpts::RGBA_to_BGRA;
            break;
        case kPremul_AlphaVerb:
            proc = swapRB ? SkOpts::RGBA_to_bgrA : SkOpts::RGBA_to_rgbA;
            break;
        case kUnpremul_AlphaVerb:
            proc = swapRB ? wrap_unpremultiply<true> : wrap_unpremultiply<false>;
            break;
    }

    for (int y = 0; y < dstInfo.height(); y++) {
        proc((uint32_t*) dstPixels, srcPixels, dstInfo.width());
        dstPixels = SkTAddOffset<void>(dstPixels, dstRB);
        srcPixels = SkTAddOffset<const void>(srcPixels, srcRB);
    }
}

// Default: Use the pipeline.
static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_t dstRB,
                                 const SkImageInfo& srcInfo, const void* srcRow, size_t srcRB,
                                 bool isColorAware) {
    SkRasterPipeline pipeline;
    switch (srcInfo.colorType()) {
        case kRGBA_8888_SkColorType:
            pipeline.append(SkRasterPipeline::load_8888, &srcRow);
            break;
        case kBGRA_8888_SkColorType:
            pipeline.append(SkRasterPipeline::load_8888, &srcRow);
            pipeline.append(SkRasterPipeline::swap_rb);
            break;
        case kRGB_565_SkColorType:
            pipeline.append(SkRasterPipeline::load_565, &srcRow);
            break;
        case kRGBA_F16_SkColorType:
            pipeline.append(SkRasterPipeline::load_f16, &srcRow);
            break;
        case kGray_8_SkColorType:
            pipeline.append(SkRasterPipeline::load_g8, &srcRow);
            break;
        default:
            return false;
    }

    if (isColorAware && srcInfo.gammaCloseToSRGB()) {
        pipeline.append_from_srgb(srcInfo.alphaType());
    }

    float matrix[12];
    if (isColorAware) {
        SkAssertResult(append_gamut_transform(&pipeline, matrix, srcInfo.colorSpace(),
                                              dstInfo.colorSpace()));
    }

    SkAlphaType sat = srcInfo.alphaType();
    SkAlphaType dat = dstInfo.alphaType();
    if (sat == kPremul_SkAlphaType && dat == kUnpremul_SkAlphaType) {
        pipeline.append(SkRasterPipeline::unpremul);
    } else if (sat == kUnpremul_SkAlphaType && dat == kPremul_SkAlphaType) {
        pipeline.append(SkRasterPipeline::premul);
    }

    if (isColorAware && dstInfo.gammaCloseToSRGB()) {
        pipeline.append(SkRasterPipeline::to_srgb);
    }

    switch (dstInfo.colorType()) {
        case kRGBA_8888_SkColorType:
            pipeline.append(SkRasterPipeline::store_8888, &dstRow);
            break;
        case kBGRA_8888_SkColorType:
            pipeline.append(SkRasterPipeline::swap_rb);
            pipeline.append(SkRasterPipeline::store_8888, &dstRow);
            break;
        case kRGB_565_SkColorType:
            pipeline.append(SkRasterPipeline::store_565, &dstRow);
            break;
        case kRGBA_F16_SkColorType:
            pipeline.append(SkRasterPipeline::store_f16, &dstRow);
            break;
        default:
            return false;
    }

    auto p = pipeline.compile();

    for (int y = 0; y < srcInfo.height(); ++y) {
        p(0,srcInfo.width());
        // The pipeline has pointers to srcRow and dstRow, so we just need to update them in the
        // loop to move between rows of src/dst.
        dstRow = SkTAddOffset<void>(dstRow, dstRB);
        srcRow = SkTAddOffset<const void>(srcRow, srcRB);
    }
    return true;
}

static bool extract_alpha(void* dst, size_t dstRB, const void* src, size_t srcRB,
                          const SkImageInfo& srcInfo, SkColorTable* ctable) {
    uint8_t* SK_RESTRICT dst8 = (uint8_t*)dst;

    const int w = srcInfo.width();
    const int h = srcInfo.height();
    if (srcInfo.isOpaque()) {
        // src is opaque, so just fill alpha with 0xFF
        for (int y = 0; y < h; ++y) {
           memset(dst8, 0xFF, w);
           dst8 += dstRB;
        }
        return true;
    }
    switch (srcInfo.colorType()) {
        case kN32_SkColorType: {
            const SkPMColor* SK_RESTRICT src32 = (const SkPMColor*)src;
            for (int y = 0; y < h; ++y) {
                for (int x = 0; x < w; ++x) {
                    dst8[x] = SkGetPackedA32(src32[x]);
                }
                dst8 += dstRB;
                src32 = (const SkPMColor*)((const char*)src32 + srcRB);
            }
            break;
        }
        case kARGB_4444_SkColorType: {
            const SkPMColor16* SK_RESTRICT src16 = (const SkPMColor16*)src;
            for (int y = 0; y < h; ++y) {
                for (int x = 0; x < w; ++x) {
                    dst8[x] = SkPacked4444ToA32(src16[x]);
                }
                dst8 += dstRB;
                src16 = (const SkPMColor16*)((const char*)src16 + srcRB);
            }
            break;
        }
        case kIndex_8_SkColorType: {
            if (nullptr == ctable) {
                return false;
            }
            const SkPMColor* SK_RESTRICT table = ctable->readColors();
            const uint8_t* SK_RESTRICT src8 = (const uint8_t*)src;
            for (int y = 0; y < h; ++y) {
                for (int x = 0; x < w; ++x) {
                    dst8[x] = SkGetPackedA32(table[src8[x]]);
                }
                dst8 += dstRB;
                src8 += srcRB;
            }
            break;
        }
        default:
            return false;
    }
    return true;
}

static inline bool optimized_color_xform(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) {
    if (kUnpremul_SkAlphaType == dstInfo.alphaType() && kPremul_SkAlphaType == srcInfo.alphaType())
    {
        return false;
    }

    switch (dstInfo.colorType()) {
        case kRGBA_8888_SkColorType:
        case kBGRA_8888_SkColorType:
        case kRGBA_F16_SkColorType:
            break;
        default:
            return false;
    }

    switch (srcInfo.colorType()) {
        case kRGBA_8888_SkColorType:
        case kBGRA_8888_SkColorType:
            break;
        default:
            return false;
    }

    return true;
}

static inline void apply_color_xform(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
                                     const SkImageInfo& srcInfo, const void* srcPixels,
                                     size_t srcRB) {
    SkColorSpaceXform::ColorFormat dstFormat = select_xform_format(dstInfo.colorType());
    SkColorSpaceXform::ColorFormat srcFormat = select_xform_format(srcInfo.colorType());
    SkAlphaType xformAlpha;
    switch (srcInfo.alphaType()) {
        case kOpaque_SkAlphaType:
            xformAlpha = kOpaque_SkAlphaType;
            break;
        case kPremul_SkAlphaType:
            SkASSERT(kPremul_SkAlphaType == dstInfo.alphaType());

            // This signal means: copy the src alpha to the dst, do not premultiply (in this
            // case because the pixels are already premultiplied).
            xformAlpha = kUnpremul_SkAlphaType;
            break;
        case kUnpremul_SkAlphaType:
            SkASSERT(kPremul_SkAlphaType == dstInfo.alphaType() ||
                     kUnpremul_SkAlphaType == dstInfo.alphaType());

            xformAlpha = dstInfo.alphaType();
            break;
        default:
            SkASSERT(false);
            xformAlpha = kUnpremul_SkAlphaType;
            break;
    }

    std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcInfo.colorSpace(),
                                                                      dstInfo.colorSpace());
    SkASSERT(xform);

    for (int y = 0; y < dstInfo.height(); y++) {
        SkAssertResult(xform->apply(dstFormat, dstPixels, srcFormat, srcPixels, dstInfo.width(),
                       xformAlpha));
        dstPixels = SkTAddOffset<void>(dstPixels, dstRB);
        srcPixels = SkTAddOffset<const void>(srcPixels, srcRB);
    }
}

bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
                             const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
                             SkColorTable* ctable) {
    SkASSERT(dstInfo.dimensions() == srcInfo.dimensions());
    SkASSERT(SkImageInfoValidConversion(dstInfo, srcInfo));

    const int width = srcInfo.width();
    const int height = srcInfo.height();

    // Fast Path 1: The memcpy() case.
    if (can_memcpy(dstInfo, srcInfo)) {
        SkRectMemcpy(dstPixels, dstRB, srcPixels, srcRB, dstInfo.minRowBytes(), dstInfo.height());
        return true;
    }

    const bool isColorAware = dstInfo.colorSpace();
    SkASSERT(srcInfo.colorSpace() || !isColorAware);

    // Fast Path 2: Simple swizzles and premuls.
    if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel() && !isColorAware) {
        swizzle_and_multiply(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB);
        return true;
    }

    if (isColorAware && optimized_color_xform(dstInfo, srcInfo)) {
        apply_color_xform(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB);
        return true;
    }

    /*
     *  Begin section where we try to change colorTypes along the way. Not all combinations
     *  are supported.
     */

    if (kAlpha_8_SkColorType == dstInfo.colorType() &&
        extract_alpha(dstPixels, dstRB, srcPixels, srcRB, srcInfo, ctable)) {
        return true;
    }

    //  Try the pipeline
    //
    if (copy_pipeline_pixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, isColorAware)) {
        return true;
    }

    // Can no longer draw directly into 4444, but we can manually whack it for a few combinations
    if (kARGB_4444_SkColorType == dstInfo.colorType() &&
        (kN32_SkColorType == srcInfo.colorType() || kIndex_8_SkColorType == srcInfo.colorType())) {
        if (srcInfo.alphaType() == kUnpremul_SkAlphaType) {
            // Our method for converting to 4444 assumes premultiplied.
            return false;
        }

        const SkPMColor* table = nullptr;
        if (kIndex_8_SkColorType == srcInfo.colorType()) {
            SkASSERT(ctable);
            table = ctable->readColors();
        }

        for (int y = 0; y < height; ++y) {
            DITHER_4444_SCAN(y);
            SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*)dstPixels;
            if (table) {
                const uint8_t* SK_RESTRICT srcRow = (const uint8_t*)srcPixels;
                for (int x = 0; x < width; ++x) {
                    dstRow[x] = SkDitherARGB32To4444(table[srcRow[x]], DITHER_VALUE(x));
                }
            } else {
                const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)srcPixels;
                for (int x = 0; x < width; ++x) {
                    dstRow[x] = SkDitherARGB32To4444(srcRow[x], DITHER_VALUE(x));
                }
            }
            dstPixels = (char*)dstPixels + dstRB;
            srcPixels = (const char*)srcPixels + srcRB;
        }
        return true;
    }

    if (dstInfo.alphaType() == kUnpremul_SkAlphaType) {
        // We do not support drawing to unpremultiplied bitmaps.
        return false;
    }

    // Final fall-back, draw with a canvas
    //
    // Always clear the dest in case one of the blitters accesses it
    // TODO: switch the allocation of tmpDst to call sk_calloc_throw
    {
        SkBitmap bm;
        if (!bm.installPixels(srcInfo, const_cast<void*>(srcPixels), srcRB, ctable, nullptr, nullptr)) {
            return false;
        }
        std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(dstInfo, dstPixels, dstRB);
        if (!canvas) {
            return false;
        }

        SkPaint  paint;
        paint.setDither(true);

        canvas->clear(0);
        canvas->drawBitmap(bm, 0, 0, &paint);
        return true;
    }
}
<|endoftext|>


<commit_before>/*
 * File:   TrisDb.cpp
 * Author: tiepologian <tiepolo.gian@gmail.com>
 *
 * Created on 18 maggio 2014, 14.50
 */

#include "TrisDb.h"
#include "LogManager.h"

volatile sig_atomic_t TrisDb::_terminateLoop = 0;

TrisDb::TrisDb(Config* config) {
    signal(SIGTERM, stop);
    this->_parser = new QueryParser();
    this->_planner = new QueryPlanner(this);
    this->_config = config;
    if (this->_config->getSetting("port") != "0") {
        // listen on TCP socket
        GenericServer* tcp = new TcpServer(this, std::atoi(_config->getSetting("port").c_str()));
        this->addServer(tcp);
    }
    if (this->_config->getSetting("unixsocket") != "no") {
        // listen on Unix socket
        GenericServer* uds = new UnixSocketServer(this, this->_config->getSetting("unixsocket"));
        this->addServer(uds);
    }
}

TrisDb::~TrisDb() {
    for (auto &i : this->_servers) {
        delete i;
    }
}

void TrisDb::addServer(GenericServer* g) {
    this->_servers.push_back(g);
}

void TrisDb::create(std::string a, std::string b, std::string c) {
    boost::lock_guard<boost::shared_mutex> lock(_mutex);
    dbData.add(a, b, c);
}

bool TrisDb::remove(std::string a, std::string b, std::string c) {
    boost::lock_guard<boost::shared_mutex> lock(_mutex);
    return dbData.remove(a, b, c);
}

Utils::ResultVector TrisDb::getFromA(std::string a) {
    boost::shared_lock<boost::shared_mutex> lock(_mutex);
    return dbData.getA(a);
}

Utils::ResultVector TrisDb::getFromB(std::string b) {
    boost::shared_lock<boost::shared_mutex> lock(_mutex);
    return dbData.getB(b);
}

Utils::ResultVector TrisDb::getFromC(std::string c) {
    boost::shared_lock<boost::shared_mutex> lock(_mutex);
    return dbData.getC(c);
}

Utils::ResultVector TrisDb::get(int index, std::string c) {
    switch (index) {
        case 0:
            return getFromA(c);
        case 1:
            return getFromB(c);
        case 2:
            return getFromC(c);
    }
}

Utils::ResultVector TrisDb::getAll() {
    boost::shared_lock<boost::shared_mutex> lock(_mutex);
    return dbData.getAll();
}

Utils::ResultVector TrisDb::count() {
    boost::shared_lock<boost::shared_mutex> lock(_mutex);
    return dbData.getCount();
}

Utils::ResultVector TrisDb::status() {
    boost::shared_lock<boost::shared_mutex> lock(_mutex);
    Utils::ResultVector result;
    auto tmp = dbData.getCount();
    result.push_back(tmp.at(0));
    double vm, rss;
    Utils::process_mem_usage(vm, rss);
    rss /= 1024.0;
    result.push_back(std::make_tuple("memory", "value", std::to_string(rss) + " MB"));
    int connections = 0;
    for (auto &i : this->_servers) {
        connections += i->getOpenConnections();
    }
    result.push_back(std::make_tuple("connections", "value", std::to_string(connections)));
    return result;
}

void TrisDb::clearAll() {
    boost::lock_guard<boost::shared_mutex> lock(_mutex);
    dbData.clearAll();
}

void TrisDb::benchmark() {
    LogManager::getSingleton()->log(LogManager::LINFO, "Starting benchmark");
    double now_1 = TimeUtils::getCurrentTimestamp();
    for (int i = 0; i < 1000000; i++) {
        create("Key" + std::to_string(i), "Value" + std::to_string(i), Utils::toString(i));
        if (i % 100000 == 0) {
            std::cout << std::to_string(i) << std::endl;
        }
    }
    double now_2 = TimeUtils::getCurrentTimestamp();
    double tempo = now_2 - now_1;
    double speed = 1000000.0 / (tempo / 1000.0);
    LogManager::getSingleton()->log(LogManager::LINFO, "Writing 1,000,000 triples took " + std::to_string(tempo) + "ms");
    LogManager::getSingleton()->log(LogManager::LINFO, "Write Speed: " + std::to_string(speed) + "/s");

    double now_3 = TimeUtils::getCurrentTimestamp();
    for (int i = 0; i < 1000000; i++) {
        Utils::ResultVector res = getFromA("Key" + std::to_string(i));
        if (i % 100000 == 0) {
            std::cout << std::to_string(i) << std::endl;
        }
    }
    double now_4 = TimeUtils::getCurrentTimestamp();
    double tempo_2 = now_4 - now_3;
    double speed_2 = 1000000.0 / (tempo_2 / 1000.0);
    LogManager::getSingleton()->log(LogManager::LINFO, "Reading 1,000,000 triples took " + std::to_string(tempo_2) + "ms");
    LogManager::getSingleton()->log(LogManager::LINFO, "Read Speed: " + std::to_string(speed_2) + "/s");
}

QueryParser* TrisDb::getParser() {
    return _parser;
}

QueryPlanner* TrisDb::getPlanner() {
    return _planner;
}

void TrisDb::run() {
    // Check manifest file to see if db exists
    if (StorageEngine::getSingleton()->checkManifest(this->_config->getSetting("dbfolder"))) {
        // load database
        StorageEngine::getSingleton()->syncLoad(&this->dbData, this->_config->getSetting("dbfolder"));
    }
    // main thread calls run to start server
    // every run method creates a new thread, then main thread loops
    for (auto &i : this->_servers) {
        LogManager::getSingleton()->log(LogManager::LINFO, "Starting " + i->getServerName());
        i->run();
    }
    // sleep
    LogManager::getSingleton()->log(LogManager::LINFO, "Database ready");
    while (!TrisDb::_terminateLoop) {
        std::chrono::milliseconds dura(2000);
        std::this_thread::sleep_for(dura);
    }
    // SIGTERM received, stop servers
    for (auto &i : this->_servers) {
        i->stop();
    }
    // give the other threads time to terminate
    // TODO:    this isn't very secure because if there are queries going on it
    //          could take longer to close TCP or Unix Socket connections.
    //          We should wait for a message/signal from the threads
    sleep(2);
    StorageEngine::getSingleton()->syncSave(&this->dbData, this->_config->getSetting("dbfolder"));
}

void TrisDb::stop(int param) {
    LogManager::getSingleton()->log(LogManager::LINFO, "Received signal SIGTERM");
    TrisDb::_terminateLoop = 1;
}<commit_msg>Fixed #4<commit_after>/*
 * File:   TrisDb.cpp
 * Author: tiepologian <tiepolo.gian@gmail.com>
 *
 * Created on 18 maggio 2014, 14.50
 */

#include "TrisDb.h"
#include "LogManager.h"

volatile sig_atomic_t TrisDb::_terminateLoop = 0;

TrisDb::TrisDb(Config* config) {
    signal(SIGTERM, stop);
    this->_parser = new QueryParser();
    this->_planner = new QueryPlanner(this);
    this->_config = config;
    if (this->_config->getSetting("port") != "0") {
        // listen on TCP socket
        GenericServer* tcp = new TcpServer(this, std::atoi(_config->getSetting("port").c_str()));
        this->addServer(tcp);
    }
    if (this->_config->getSetting("unixsocket") != "no") {
        // listen on Unix socket
        GenericServer* uds = new UnixSocketServer(this, this->_config->getSetting("unixsocket"));
        this->addServer(uds);
    }
}

TrisDb::~TrisDb() {
    for (auto &i : this->_servers) {
        delete i;
    }
}

void TrisDb::addServer(GenericServer* g) {
    this->_servers.push_back(g);
}

void TrisDb::create(std::string a, std::string b, std::string c) {
    boost::lock_guard<boost::shared_mutex> lock(_mutex);
    dbData.add(a, b, c);
}

bool TrisDb::remove(std::string a, std::string b, std::string c) {
    boost::lock_guard<boost::shared_mutex> lock(_mutex);
    return dbData.remove(a, b, c);
}

Utils::ResultVector TrisDb::getFromA(std::string a) {
    boost::shared_lock<boost::shared_mutex> lock(_mutex);
    return dbData.getA(a);
}

Utils::ResultVector TrisDb::getFromB(std::string b) {
    boost::shared_lock<boost::shared_mutex> lock(_mutex);
    return dbData.getB(b);
}

Utils::ResultVector TrisDb::getFromC(std::string c) {
    boost::shared_lock<boost::shared_mutex> lock(_mutex);
    return dbData.getC(c);
}

Utils::ResultVector TrisDb::get(int index, std::string c) {
    switch (index) {
        case 0:
            return getFromA(c);
        case 1:
            return getFromB(c);
        case 2:
            return getFromC(c);
    }
}

Utils::ResultVector TrisDb::getAll() {
    boost::shared_lock<boost::shared_mutex> lock(_mutex);
    return dbData.getAll();
}

Utils::ResultVector TrisDb::count() {
    boost::shared_lock<boost::shared_mutex> lock(_mutex);
    return dbData.getCount();
}

Utils::ResultVector TrisDb::status() {
    boost::shared_lock<boost::shared_mutex> lock(_mutex);
    Utils::ResultVector result;
    auto tmp = dbData.getCount();
    result.push_back(tmp.at(0));
    double vm, rss;
    Utils::process_mem_usage(vm, rss);
    rss /= 1024.0;
    result.push_back(std::make_tuple("memory", "value", std::to_string(rss) + " MB"));
    int connections = 0;
    for (auto &i : this->_servers) {
        connections += i->getOpenConnections();
    }
    result.push_back(std::make_tuple("connections", "value", std::to_string(connections)));
    return result;
}

void TrisDb::clearAll() {
    boost::lock_guard<boost::shared_mutex> lock(_mutex);
    dbData.clearAll();
}

void TrisDb::benchmark() {
    LogManager::getSingleton()->log(LogManager::LINFO, "Starting benchmark");
    double now_1 = TimeUtils::getCurrentTimestamp();
    for (int i = 0; i < 1000000; i++) {
        create("Key" + std::to_string(i), "Value" + std::to_string(i), Utils::toString(i));
        if (i % 100000 == 0) {
            std::cout << std::to_string(i) << std::endl;
        }
    }
    double now_2 = TimeUtils::getCurrentTimestamp();
    double tempo = now_2 - now_1;
    double speed = 1000000.0 / (tempo / 1000.0);
    LogManager::getSingleton()->log(LogManager::LINFO, "Writing 1,000,000 triples took " + std::to_string(tempo) + "ms");
    LogManager::getSingleton()->log(LogManager::LINFO, "Write Speed: " + std::to_string(speed) + "/s");

    double now_3 = TimeUtils::getCurrentTimestamp();
    for (int i = 0; i < 1000000; i++) {
        Utils::ResultVector res = getFromA("Key" + std::to_string(i));
        if (i % 100000 == 0) {
            std::cout << std::to_string(i) << std::endl;
        }
    }
    double now_4 = TimeUtils::getCurrentTimestamp();
    double tempo_2 = now_4 - now_3;
    double speed_2 = 1000000.0 / (tempo_2 / 1000.0);
    LogManager::getSingleton()->log(LogManager::LINFO, "Reading 1,000,000 triples took " + std::to_string(tempo_2) + "ms");
    LogManager::getSingleton()->log(LogManager::LINFO, "Read Speed: " + std::to_string(speed_2) + "/s");
}

QueryParser* TrisDb::getParser() {
    return _parser;
}

QueryPlanner* TrisDb::getPlanner() {
    return _planner;
}

void TrisDb::run() {
    // Check manifest file to see if db exists
    if (StorageEngine::getSingleton()->checkManifest(this->_config->getSetting("dbfolder"))) {
        // load database
        StorageEngine::getSingleton()->syncLoad(&this->dbData, this->_config->getSetting("dbfolder"));
    }
    // main thread calls run to start server
    // every run method creates a new thread, then main thread loops
    for (auto &i : this->_servers) {
        LogManager::getSingleton()->log(LogManager::LINFO, "Starting " + i->getServerName());
        i->run();
    }
    // sleep
    LogManager::getSingleton()->log(LogManager::LINFO, "Database ready");
    while (!TrisDb::_terminateLoop) {
        std::chrono::milliseconds dura(1000);
        std::this_thread::sleep_for(dura);
    }
    // SIGTERM received, stop servers
    for (auto &i : this->_servers) {
        i->stop();
    }
    // give the IO threads time to terminate
    sleep(1);
    StorageEngine::getSingleton()->syncSave(&this->dbData, this->_config->getSetting("dbfolder"));
}

void TrisDb::stop(int param) {
    LogManager::getSingleton()->log(LogManager::LINFO, "Received signal SIGTERM");
    TrisDb::_terminateLoop = 1;
}
<|endoftext|>


<commit_before>#include <raytracer.h>

#include <cassert>
#include <cmath>

using namespace raytracer;

static const double PI  = 4.0 * atan(1.0);
static const double TAU = 2.0 * PI;

Vector::Vector() {
	x = 0.0; y = 1.0; z = 0.0;
}

Vector::Vector(double x, double y, double z) {
	this->x = x; this->y = y; this->z = z;
}

Vector::Vector(const Vector & v) {
	x = v.x; y = v.y; z = v.z;
}

void Vector::seed() {
	std::srand(std::time(NULL));
}

Vector Vector::random(double r) {

	r *= std::rand();

	double t = TAU * std::rand(),
		   p = PI * std::rand(),
		   rcosp = r * std::sin(p);

	return Vector(
			rcosp * std::cos(t),
			rcosp * std::sin(t),
			r * std::sin(p)
		);
}

double Vector::dot(const Vector & v, const Vector & w) {
	return v.x * w.x + v.y * w.y + v.z * w.z;
}

double Vector::dot() const {
	return x * x + y * y + z * z;
}

double Vector::dot(const Vector & v) const {
	return x * v.x + y * v.y + z * v.z;
}

Vector Vector::cross(const Vector & v, const Vector & w) {
	return Vector(
			v.y * w.z - v.z * w.y,
			v.z * w.x - v.x * w.z,
			v.x * w.y - v.y * w.x
		);
}

Vector Vector::cross(const Vector & v) const {
	return Vector(
			y * v.z - z * v.y,
			z * v.x - x * v.z,
			x * v.y - y * v.x
		);
}

void Vector::copy(const Vector & v) {
	x = v.x; y = v.y; z = v.z;
}

void Vector::copy(double x, double y, double z) {
	this->x = x; this->y = y; this->z = z;
}

void Vector::power(double p) {
	x = std::pow(x,p);
	y = std::pow(y,p);
	z = std::pow(z,p);
}

void Vector::normalize() {
	double l = std::sqrt(x * x + y * y + z * z);

	assert(l >= DIV_LIMIT);

	// don't divide by what is essentially zero
	if (l < DIV_LIMIT) {
		x = 0.0;
		y = 1.0;
		z = 0.0;
	}

	else {
		x /= l;
		y /= l;
		z /= l;
	}
}

void Vector::scale(double s) {
	x *= s; y *= s; z *= s;
}

void Vector::scale(const Vector & v) {
	x *= v.x;
	y *= v.y;
	z *= v.z;
}

void Vector::add(const Vector & v) {
	x += v.x; y += v.y; z += v.z;
}

void Vector::add(double x, double y, double z) {
	this->x += x; this->y += y; this->z += z;
}

void Vector::subtract(const Vector & v) {
	x -= v.x; y -= v.y; z -= v.z;
}

void Vector::subtract(double x, double y, double z) {
	this->x -= x; this->y -= y; this->z -= z;
}

void Vector::translate(const Vector & v, double s) {
	x += s * v.x; y += s * v.y; z += s * v.z;
}

void Vector::reflect(const Vector & normal) {

	assert(std::abs(dot() - 1.0) < DIV_LIMIT); // should be a direction vector

	translate(normal, -2.0 * dot(normal));
}

//note: ratio is the ratio of the indexes of refraction across the surface
//interface for a vector traveling in the direction of the normal.
//Specifically, it is the incident index divided by the resultant index.
void Vector::refract(const Vector & normal, double index_ratio) {

	assert(std::abs(dot() - 1.0) < DIV_LIMIT); // should be a direction vector

	double s = dot(normal);
	double sign = 1.0;

	if (s < 0) {
		index_ratio = 1.0 / index_ratio;
		sign = -1.0;
	}

	translate(normal, -1.0 * s);
	scale(index_ratio);

	s = sign * std::sqrt(1.0 - dot());
	translate(normal, s);
}

void Vector::project(const Vector & v) {
	double l = dot(v);
	copy(v); scale(l);
}

void Vector::unproject(const Vector & v) {
	Vector p = v;
	p.scale(dot(v));
	subtract(p);
}

<commit_msg>moved over to the proper rng from doing it all wrong before<commit_after>#include <raytracer.h>

#include <cassert>
#include <cmath>

using namespace raytracer;

static const double PI  = 4.0 * atan(1.0);
static const double TAU = 2.0 * PI;

Vector::Vector() {
	x = 0.0; y = 1.0; z = 0.0;
}

Vector::Vector(double x, double y, double z) {
	this->x = x; this->y = y; this->z = z;
}

Vector::Vector(const Vector & v) {
	x = v.x; y = v.y; z = v.z;
}

Vector Vector::random(double r) {

	RNG *rng = RNG::get();
	r *= rng->next();

	double t = TAU * rng->next(),
		   p = PI * rng->next(),
		   rcosp = r * std::sin(p);

	return Vector(
			rcosp * std::cos(t),
			rcosp * std::sin(t),
			r * std::sin(p)
		);
}

double Vector::dot(const Vector & v, const Vector & w) {
	return v.x * w.x + v.y * w.y + v.z * w.z;
}

double Vector::dot() const {
	return x * x + y * y + z * z;
}

double Vector::dot(const Vector & v) const {
	return x * v.x + y * v.y + z * v.z;
}

Vector Vector::cross(const Vector & v, const Vector & w) {
	return Vector(
			v.y * w.z - v.z * w.y,
			v.z * w.x - v.x * w.z,
			v.x * w.y - v.y * w.x
		);
}

Vector Vector::cross(const Vector & v) const {
	return Vector(
			y * v.z - z * v.y,
			z * v.x - x * v.z,
			x * v.y - y * v.x
		);
}

void Vector::copy(const Vector & v) {
	x = v.x; y = v.y; z = v.z;
}

void Vector::copy(double x, double y, double z) {
	this->x = x; this->y = y; this->z = z;
}

void Vector::power(double p) {
	x = std::pow(x,p);
	y = std::pow(y,p);
	z = std::pow(z,p);
}

void Vector::normalize() {
	double l = std::sqrt(x * x + y * y + z * z);

	assert(l >= DIV_LIMIT);

	// don't divide by what is essentially zero
	if (l < DIV_LIMIT) {
		x = 0.0;
		y = 1.0;
		z = 0.0;
	}

	else {
		x /= l;
		y /= l;
		z /= l;
	}
}

void Vector::scale(double s) {
	x *= s; y *= s; z *= s;
}

void Vector::scale(const Vector & v) {
	x *= v.x;
	y *= v.y;
	z *= v.z;
}

void Vector::add(const Vector & v) {
	x += v.x; y += v.y; z += v.z;
}

void Vector::add(double x, double y, double z) {
	this->x += x; this->y += y; this->z += z;
}

void Vector::subtract(const Vector & v) {
	x -= v.x; y -= v.y; z -= v.z;
}

void Vector::subtract(double x, double y, double z) {
	this->x -= x; this->y -= y; this->z -= z;
}

void Vector::translate(const Vector & v, double s) {
	x += s * v.x; y += s * v.y; z += s * v.z;
}

void Vector::reflect(const Vector & normal) {

	assert(std::abs(dot() - 1.0) < DIV_LIMIT); // should be a direction vector

	translate(normal, -2.0 * dot(normal));
}

//note: ratio is the ratio of the indexes of refraction across the surface
//interface for a vector traveling in the direction of the normal.
//Specifically, it is the incident index divided by the resultant index.
void Vector::refract(const Vector & normal, double index_ratio) {

	assert(std::abs(dot() - 1.0) < DIV_LIMIT); // should be a direction vector

	double s = dot(normal);
	double sign = 1.0;

	if (s < 0) {
		index_ratio = 1.0 / index_ratio;
		sign = -1.0;
	}

	translate(normal, -1.0 * s);
	scale(index_ratio);

	s = sign * std::sqrt(1.0 - dot());
	translate(normal, s);
}

void Vector::project(const Vector & v) {
	double l = dot(v);
	copy(v); scale(l);
}

void Vector::unproject(const Vector & v) {
	Vector p = v;
	p.scale(dot(v));
	subtract(p);
}

<|endoftext|>