<commit_before>#include <string>
#include "dynamicsJRLJapan/Joint.h"
#include "dynamicsJRLJapan/HumanoidDynamicMultiBody.h"
#include "robotDynamics/jrlRobotDynamicsObjectConstructor.h"

using namespace std;
using namespace dynamicsJRLJapan;

void DisplayBody(CjrlBody *aBody)
{
  matrix3d InertiaMatrix = aBody->inertiaMatrix();

  cout << "Attached body:" << endl;
  cout << "Mass of the attached body: " << aBody->mass() << endl;
  cout << "Local center of mass: " << aBody->localCenterOfMass() << endl;
  cout << "Inertia matrix:" << endl;
  cout << InertiaMatrix << endl;

}
void DisplayJoint(Joint * aJoint)
{
  cout << "Joint : " << aJoint->getName() << endl;
  unsigned int NbCJ = aJoint->countChildJoints();
  if (aJoint->parentJoint()!=0)
    cout << "Father: " << ((Joint *)(aJoint->parentJoint()))->getName() << endl;
  cout << "Number of children : " << NbCJ << endl;
  for(unsigned int li=0;li<NbCJ;li++)
    cout << "Child("<<li<<")="
	 << ((Joint*)(aJoint->childJoint(li)))->getName() << endl;

  cout << "Current transformation " << aJoint->currentTransformation() << endl;

}

void RecursiveDisplayOfJoints(CjrlJoint *aJoint)
{
  if (aJoint==0)
    return;

  Joint *a2Joint=0;

  int NbChildren = aJoint->countChildJoints();

  a2Joint = dynamic_cast<Joint *>( aJoint);
  if (a2Joint==0)
    return;

  DisplayJoint(a2Joint);
  //DisplayBody(aJoint->linkedBody());
  for(int i=0;i<NbChildren;i++)
    {
      // Returns a const so we have to force the casting/
      RecursiveDisplayOfJoints((CjrlJoint *)a2Joint->childJoint(i));
    }
  //cout << " End for Joint: " << a2Joint->getName() << endl;
}

void recursiveMultibodyCopy(Joint *initJoint, Joint *newJoint)
{
  int lNbOfChildren= initJoint->countChildJoints();

  // stop test
  if (lNbOfChildren == 0) return ;

  for(int li=0;li<lNbOfChildren;li++)
    {

      Joint *Child = dynamic_cast<Joint *> (initJoint->childJoint(li)) ;

      if (Child != 0) {

	int type = Child->type();
	vector3d axe = Child->axe();
	float q = Child->quantity();
	matrix4d pose = Child->pose();
	string name = Child->getName() ;
	int IDinVRML = Child->getIDinVRML();

	Joint *a2newJoint = new Joint(type, axe, q, pose);
	a2newJoint->setName(name) ;
	a2newJoint->setIDinVRML(IDinVRML);

	newJoint->addChildJoint(*a2newJoint);
	a2newJoint->SetFatherJoint(newJoint);
	recursiveMultibodyCopy(Child, a2newJoint) ;
      }

    }
}

void PerformCopyFromJointsTree(HumanoidDynamicMultiBody *aHDR,
			       HumanoidDynamicMultiBody *a2HDR)
{
  Joint *InitJoint = dynamic_cast<Joint *>( aHDR->rootJoint()) ;

  int type =  InitJoint->type();
  vector3d axe = InitJoint->axe();
  float q = InitJoint->quantity();
  matrix4d pose = InitJoint->pose();
  string name = InitJoint->getName() ;

  Joint *newJoint = new Joint(type, axe, q, pose);
  newJoint->setName(name) ;

  a2HDR->rootJoint(*newJoint);

  recursiveMultibodyCopy(InitJoint, newJoint) ;

  cout << " ================== COPY BY CONSTRUCTOR  =================== " << endl ;
  RecursiveDisplayOfJoints(a2HDR->rootJoint());

  // Initialize the second humanoid from the joint tree.

  std::vector<NameAndRank_t> LinkJointNameAndRank;
  aHDR->getLinksBetweenJointNamesAndRank(LinkJointNameAndRank);
  a2HDR->setLinksBetweenJointNamesAndRank(LinkJointNameAndRank);

  a2HDR->InitializeFromJointsTree();

  // Copy the bodies.
  std::vector<CjrlJoint *> VecOfInitJoints = aHDR->jointVector();
  std::vector<CjrlJoint *> VecOfCopyJoints = a2HDR->jointVector();

  if (VecOfInitJoints.size()!=VecOfCopyJoints.size())
    {
      std::cout << "Problem while copying the joints. size : " <<VecOfInitJoints.size() << " size copy : " << VecOfCopyJoints.size()  <<endl;
      cout << endl << endl << "There is a probleme the new joints vector is not updated" << endl << endl ;
      exit(-1);
    }

  for(unsigned int i=0;i<VecOfInitJoints.size();i++)
    {
      if ((VecOfCopyJoints[i]!=0) &&
	  (VecOfInitJoints[i]!=0))
      *((DynamicBody *)VecOfCopyJoints[i]->linkedBody()) =
	*((DynamicBody *)VecOfInitJoints[i]->linkedBody());
    }

}

int main(int argc, char *argv[])
{
  int VerboseMode = 3;

  string aPath="/home/mpoirier/openrobots/OpenHRP/etc/HRP2JRL/";
  string aName="HRP2JRLmain.wrl";
  string JointToRank = "/home/mpoirier/openrobots/share/walkgenjrl/HRP2LinkJointRank.xml";
  string aSpecificitiesFileName =  "/home/mpoirier/openrobots/share/walkgenjrl/HRP2Specificities.xml";

  int argindex=1;
  if (argc>1)
    {
      aPath=argv[argindex++];
      argc--;
    }
  if (argc>1)
    {
      aName=argv[argindex++];
      argc--;
    }
  if (argc>1)
    {
      JointToRank=argv[argindex++];
      argc--;
    }
  if (argc>1)
    {
      aSpecificitiesFileName=argv[argindex++];
      argc--;
    }

  CjrlRobotDynamicsObjectConstructor <
  dynamicsJRLJapan::DynamicMultiBody,
    dynamicsJRLJapan::HumanoidDynamicMultiBody,
    dynamicsJRLJapan::JointFreeflyer,
    dynamicsJRLJapan::JointRotation,
    dynamicsJRLJapan::JointTranslation,
    dynamicsJRLJapan::Body >  aRobotDynamicsObjectConstructor;

  // Read the first humanoid.
  HumanoidDynamicMultiBody * aHDR =
    dynamic_cast<HumanoidDynamicMultiBody*>(aRobotDynamicsObjectConstructor.createhumanoidDynamicRobot());

  aHDR->parserVRML(aPath,
		   aName,
		   (char *)JointToRank.c_str());

  aHDR->SetHumanoidSpecificitiesFile(aSpecificitiesFileName);

  // Pretend to build the second humanoid.
  HumanoidDynamicMultiBody *a2HDR =
    dynamic_cast<HumanoidDynamicMultiBody*>(aRobotDynamicsObjectConstructor.createhumanoidDynamicRobot());

  PerformCopyFromJointsTree(aHDR, a2HDR);

  // Test the new humanoid structure.
  double dInitPos[40] = {
    0.0, 0.0, -26.0, 50.0, -24.0, 0.0, 0.0, 0.0, -26.0, 50.0, -24.0, 0.0,  // legs

    0.0, 0.0, 0.0, 0.0, // chest and head

    15.0, -10.0, 0.0, -30.0, 0.0, 0.0, 10.0, // right arm
    15.0,  10.0, 0.0, -30.0, 0.0, 0.0, 10.0, // left arm

    -20.0, 20.0, -20.0, 20.0, -20.0, // right hand
    -10.0, 10.0, -10.0, 10.0, -10.0  // left hand
  };

  // This is mandatory for this implementation of computeForwardKinematics
  // to compute the derivative of the momentum.
  aHDR->SetTimeStep(0.005);
  aHDR->setComputeAcceleration(false);
  aHDR->setComputeBackwardDynamics(false);
  aHDR->setComputeZMP(true);

  a2HDR->SetTimeStep(0.005);
  a2HDR->setComputeAcceleration(false);
  a2HDR->setComputeBackwardDynamics(false);
  a2HDR->setComputeZMP(true);

  int NbOfDofs = a2HDR->numberDof();
  if (VerboseMode>2)
    std::cout << "NbOfDofs :" << NbOfDofs << std::endl;

  MAL_VECTOR_DIM(aCurrentConf,double,NbOfDofs);
  int lindex=0;
  for(int i=0;i<6;i++)
    aCurrentConf[lindex++] = 0.0;

  for(int i=0;i<(NbOfDofs-6 < 40 ? NbOfDofs-6 : 40) ;i++)
    aCurrentConf[lindex++] = dInitPos[i]*M_PI/180.0;

  aHDR->currentConfiguration(aCurrentConf);
  a2HDR->currentConfiguration(aCurrentConf);

  MAL_VECTOR_DIM(aCurrentVel,double,NbOfDofs);
  lindex=0;
  for(int i=0;i<NbOfDofs;i++)
    aCurrentVel[lindex++] = 0.0;

  MAL_VECTOR_DIM(aCurrentAcc,double,NbOfDofs);
  MAL_VECTOR_FILL(aCurrentAcc,0.0);

  MAL_S3_VECTOR(ZMPval,double);

  for(int i=0;i<4;i++)
    {
      aHDR->currentVelocity(aCurrentVel);
      aHDR->currentAcceleration(aCurrentAcc);
      aHDR->computeForwardKinematics();
      ZMPval = aHDR->zeroMomentumPoint();
      if (VerboseMode>4)
	{
	  cout << i << "-th value of ZMP : " << ZMPval <<endl;
	  cout << "Should be equal to the CoM: " << aHDR->positionCenterOfMass() << endl;
	}

      a2HDR->currentVelocity(aCurrentVel);
      a2HDR->currentAcceleration(aCurrentAcc);
      a2HDR->computeForwardKinematics();
      ZMPval = a2HDR->zeroMomentumPoint();
      if(VerboseMode>4)
	{
	  cout << i << "-th value of ZMP : " << ZMPval <<endl;
	  cout << "Should be equal to the CoM: " << aHDR->positionCenterOfMass() << endl;
	}

    }

  if (VerboseMode>2)
    cout << " ================== AFTER PATGEN  =================== " << endl ;
     RecursiveDisplayOfJoints(a2HDR->rootJoint());
  delete aHDR;
  delete a2HDR;

}
<commit_msg>OS: Testing the defaut numbering for Mathieu's case.<commit_after>#include <string>
#include "dynamicsJRLJapan/Joint.h"
#include "dynamicsJRLJapan/HumanoidDynamicMultiBody.h"
#include "robotDynamics/jrlRobotDynamicsObjectConstructor.h"

using namespace std;
using namespace dynamicsJRLJapan;

void DisplayBody(CjrlBody *aBody)
{
  matrix3d InertiaMatrix = aBody->inertiaMatrix();

  cout << "Attached body:" << endl;
  cout << "Mass of the attached body: " << aBody->mass() << endl;
  cout << "Local center of mass: " << aBody->localCenterOfMass() << endl;
  cout << "Inertia matrix:" << endl;
  cout << InertiaMatrix << endl;

}
void DisplayJoint(Joint * aJoint)
{
  cout << "Joint : " << aJoint->getName() << endl;
  unsigned int NbCJ = aJoint->countChildJoints();
  if (aJoint->parentJoint()!=0)
    cout << "Father: " << ((Joint *)(aJoint->parentJoint()))->getName() << endl;
  cout << "Number of children : " << NbCJ << endl;
  for(unsigned int li=0;li<NbCJ;li++)
    cout << "Child("<<li<<")="
	 << ((Joint*)(aJoint->childJoint(li)))->getName() << endl;

  cout << "Current transformation " << aJoint->currentTransformation() << endl;

}

void RecursiveDisplayOfJoints(CjrlJoint *aJoint)
{
  if (aJoint==0)
    return;

  Joint *a2Joint=0;

  int NbChildren = aJoint->countChildJoints();

  a2Joint = dynamic_cast<Joint *>( aJoint);
  if (a2Joint==0)
    return;

  DisplayJoint(a2Joint);
  //DisplayBody(aJoint->linkedBody());
  for(int i=0;i<NbChildren;i++)
    {
      // Returns a const so we have to force the casting/
      RecursiveDisplayOfJoints((CjrlJoint *)a2Joint->childJoint(i));
    }
  //cout << " End for Joint: " << a2Joint->getName() << endl;
}

void recursiveMultibodyCopy(Joint *initJoint, Joint *newJoint)
{
  int lNbOfChildren= initJoint->countChildJoints();

  // stop test
  if (lNbOfChildren == 0) return ;

  for(int li=0;li<lNbOfChildren;li++)
    {

      Joint *Child = dynamic_cast<Joint *> (initJoint->childJoint(li)) ;

      if (Child != 0) {

	int type = Child->type();
	vector3d axe = Child->axe();
	float q = Child->quantity();
	matrix4d pose = Child->pose();
	string name = Child->getName() ;
	//	int IDinVRML = Child->getIDinVRML();

	Joint *a2newJoint = new Joint(type, axe, q, pose);
	a2newJoint->setName(name) ;
	//	a2newJoint->setIDinVRML(IDinVRML);

	newJoint->addChildJoint(*a2newJoint);
	a2newJoint->SetFatherJoint(newJoint);
	recursiveMultibodyCopy(Child, a2newJoint) ;
      }

    }
}

void PerformCopyFromJointsTree(HumanoidDynamicMultiBody *aHDR,
			       HumanoidDynamicMultiBody *a2HDR)
{
  Joint *InitJoint = dynamic_cast<Joint *>( aHDR->rootJoint()) ;

  int type =  InitJoint->type();
  vector3d axe = InitJoint->axe();
  float q = InitJoint->quantity();
  matrix4d pose = InitJoint->pose();
  string name = InitJoint->getName() ;

  Joint *newJoint = new Joint(type, axe, q, pose);
  newJoint->setName(name) ;

  a2HDR->rootJoint(*newJoint);

  recursiveMultibodyCopy(InitJoint, newJoint) ;

  cout << " ================== COPY BY CONSTRUCTOR  =================== " << endl ;
  RecursiveDisplayOfJoints(a2HDR->rootJoint());

  // Initialize the second humanoid from the joint tree.

  std::vector<NameAndRank_t> LinkJointNameAndRank;
  aHDR->getLinksBetweenJointNamesAndRank(LinkJointNameAndRank);
  a2HDR->setLinksBetweenJointNamesAndRank(LinkJointNameAndRank);

  a2HDR->InitializeFromJointsTree();

  // Copy the bodies.
  std::vector<CjrlJoint *> VecOfInitJoints = aHDR->jointVector();
  std::vector<CjrlJoint *> VecOfCopyJoints = a2HDR->jointVector();

  if (VecOfInitJoints.size()!=VecOfCopyJoints.size())
    {
      std::cout << "Problem while copying the joints. size : " <<VecOfInitJoints.size() << " size copy : " << VecOfCopyJoints.size()  <<endl;
      cout << endl << endl << "There is a probleme the new joints vector is not updated" << endl << endl ;
      exit(-1);
    }

  for(unsigned int i=0;i<VecOfInitJoints.size();i++)
    {
      if ((VecOfCopyJoints[i]!=0) &&
	  (VecOfInitJoints[i]!=0))
      *((DynamicBody *)VecOfCopyJoints[i]->linkedBody()) =
	*((DynamicBody *)VecOfInitJoints[i]->linkedBody());
    }

}

int main(int argc, char *argv[])
{
  int VerboseMode = 3;
#if 0
  string aPath="/home/mpoirier/openrobots/OpenHRP/etc/HRP2JRL/";
  string aName="HRP2JRLmain.wrl";
  string JointToRank = "/home/mpoirier/openrobots/share/walkgenjrl/HRP2LinkJointRank.xml";
  string aSpecificitiesFileName =  "/home/mpoirier/openrobots/share/walkgenjrl/HRP2Specificities.xml";
#else
  string aPath="/home/stasse/src/OpenHRP/etc/HRP2JRL/";
  string aName="HRP2JRLmain.wrl";
  string JointToRank = "/home/stasse/src/OpenHRP/JRL/src/PatternGeneratorJRL/src/data/HRP2LinkJointRank.xml";
  string aSpecificitiesFileName =  "/home/stasse/src/OpenHRP/JRL/src/PatternGeneratorJRL/src/data/HRP2Specificities.xml";

#endif

  int argindex=1;
  if (argc>1)
    {
      aPath=argv[argindex++];
      argc--;
    }
  if (argc>1)
    {
      aName=argv[argindex++];
      argc--;
    }
  if (argc>1)
    {
      JointToRank=argv[argindex++];
      argc--;
    }
  if (argc>1)
    {
      aSpecificitiesFileName=argv[argindex++];
      argc--;
    }

  CjrlRobotDynamicsObjectConstructor <
  dynamicsJRLJapan::DynamicMultiBody,
    dynamicsJRLJapan::HumanoidDynamicMultiBody,
    dynamicsJRLJapan::JointFreeflyer,
    dynamicsJRLJapan::JointRotation,
    dynamicsJRLJapan::JointTranslation,
    dynamicsJRLJapan::Body >  aRobotDynamicsObjectConstructor;

  // Read the first humanoid.
  HumanoidDynamicMultiBody * aHDR =
    dynamic_cast<HumanoidDynamicMultiBody*>(aRobotDynamicsObjectConstructor.createhumanoidDynamicRobot());

  aHDR->parserVRML(aPath,
		   aName,
		   (char *)JointToRank.c_str());

  aHDR->SetHumanoidSpecificitiesFile(aSpecificitiesFileName);

  // Pretend to build the second humanoid.
  HumanoidDynamicMultiBody *a2HDR =
    dynamic_cast<HumanoidDynamicMultiBody*>(aRobotDynamicsObjectConstructor.createhumanoidDynamicRobot());

  PerformCopyFromJointsTree(aHDR, a2HDR);

  // Test the new humanoid structure.
  double dInitPos[40] = {
    0.0, 0.0, -26.0, 50.0, -24.0, 0.0, 0.0, 0.0, -26.0, 50.0, -24.0, 0.0,  // legs

    0.0, 0.0, 0.0, 0.0, // chest and head

    15.0, -10.0, 0.0, -30.0, 0.0, 0.0, 10.0, // right arm
    15.0,  10.0, 0.0, -30.0, 0.0, 0.0, 10.0, // left arm

    -20.0, 20.0, -20.0, 20.0, -20.0, // right hand
    -10.0, 10.0, -10.0, 10.0, -10.0  // left hand
  };

  // This is mandatory for this implementation of computeForwardKinematics
  // to compute the derivative of the momentum.
  aHDR->SetTimeStep(0.005);
  aHDR->setComputeAcceleration(false);
  aHDR->setComputeBackwardDynamics(false);
  aHDR->setComputeZMP(true);

  a2HDR->SetTimeStep(0.005);
  a2HDR->setComputeAcceleration(false);
  a2HDR->setComputeBackwardDynamics(false);
  a2HDR->setComputeZMP(true);

  int NbOfDofs = a2HDR->numberDof();
  if (VerboseMode>2)
    std::cout << "NbOfDofs :" << NbOfDofs << std::endl;

  MAL_VECTOR_DIM(aCurrentConf,double,NbOfDofs);
  int lindex=0;
  for(int i=0;i<6;i++)
    aCurrentConf[lindex++] = 0.0;

  for(int i=0;i<(NbOfDofs-6 < 40 ? NbOfDofs-6 : 40) ;i++)
    aCurrentConf[lindex++] = dInitPos[i]*M_PI/180.0;

  aHDR->currentConfiguration(aCurrentConf);
  a2HDR->currentConfiguration(aCurrentConf);

  MAL_VECTOR_DIM(aCurrentVel,double,NbOfDofs);
  lindex=0;
  for(int i=0;i<NbOfDofs;i++)
    aCurrentVel[lindex++] = 0.0;

  MAL_VECTOR_DIM(aCurrentAcc,double,NbOfDofs);
  MAL_VECTOR_FILL(aCurrentAcc,0.0);

  MAL_S3_VECTOR(ZMPval,double);

  for(int i=0;i<4;i++)
    {
      aHDR->currentVelocity(aCurrentVel);
      aHDR->currentAcceleration(aCurrentAcc);
      aHDR->computeForwardKinematics();
      ZMPval = aHDR->zeroMomentumPoint();
      if (VerboseMode>4)
	{
	  cout << i << "-th value of ZMP : " << ZMPval <<endl;
	  cout << "Should be equal to the CoM: " << aHDR->positionCenterOfMass() << endl;
	}

      a2HDR->currentVelocity(aCurrentVel);
      a2HDR->currentAcceleration(aCurrentAcc);
      a2HDR->computeForwardKinematics();
      ZMPval = a2HDR->zeroMomentumPoint();
      if(VerboseMode>4)
	{
	  cout << i << "-th value of ZMP : " << ZMPval <<endl;
	  cout << "Should be equal to the CoM: " << aHDR->positionCenterOfMass() << endl;
	}

    }

  if (VerboseMode>2)
    cout << " ================== AFTER PATGEN  =================== " << endl ;
     RecursiveDisplayOfJoints(a2HDR->rootJoint());
  delete aHDR;
  delete a2HDR;

}
<|endoftext|>


<commit_before>// fluxbox.hh for Fluxbox Window Manager
// Copyright (c) 2001 - 2002 Henrik Kinnunen (fluxgen@linuxmail.org)
//
// blackbox.hh for Blackbox - an X11 Window manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.	IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// $Id: fluxbox.hh,v 1.32 2002/10/23 17:32:30 fluxgen Exp $

#ifndef	 FLUXBOX_HH
#define	 FLUXBOX_HH

#include "Resource.hh"
#include "Keys.hh"
#include "BaseDisplay.hh"
#include "Image.hh"
#include "Timer.hh"
#include "Window.hh"
#include "Tab.hh"
#include "Toolbar.hh"
#include "Observer.hh"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H

#ifdef	SLIT
#include "Slit.hh"
#endif // SLIT

#include "SignalHandler.hh"
#include "FbAtoms.hh"

#include <X11/Xlib.h>
#include <X11/Xresource.h>

#include <cstdio>

#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else // !TIME_WITH_SYS_TIME
#ifdef	HAVE_SYS_TIME_H
#include <sys/time.h>
#else // !HAVE_SYS_TIME_H
#include <time.h>
#endif // HAVE_SYS_TIME_H
#endif // TIME_WITH_SYS_TIME

#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>

class AtomHandler;

/**
	main class for the window manager.
	singleton type
*/
class Fluxbox : public BaseDisplay, public TimeoutHandler,
	public FbTk::EventHandler<FbTk::SignalEvent>,
	public FbAtoms,
	public FbTk::Observer {
public:
	Fluxbox(int argc, char **argv, const char * dpy_name= 0, const char *rc = 0);
	virtual ~Fluxbox();

	static Fluxbox *instance() { return singleton; }

	inline bool useTabs() { return *m_rc_tabs; }
	inline bool useIconBar() { return *m_rc_iconbar; }
	inline void saveTabs(bool value) { *m_rc_tabs = value; }
	inline void saveIconBar(bool value) { m_rc_iconbar = value; }
#ifdef HAVE_GETPID
	inline Atom getFluxboxPidAtom() const { return fluxbox_pid; }
	#ifdef KDE
	//For KDE dock applets
	inline Atom getKWM1DockwindowAtom() const { return kwm1_dockwindow; } //KDE v1.x
	inline Atom getKWM2DockwindowAtom() const { return kwm2_dockwindow; } //KDE v2.x
	#endif
#endif // HAVE_GETPID

	Basemenu *searchMenu(Window);

	FluxboxWindow *searchGroup(Window, FluxboxWindow *);
	FluxboxWindow *searchWindow(Window);
	inline FluxboxWindow *getFocusedWindow() { return focused_window; }

	BScreen *searchScreen(Window w);

	inline const Time &getDoubleClickInterval() const { return resource.double_click_interval; }
	inline const Time &getLastTime() const { return last_time; }

	Toolbar *searchToolbar(Window w);
	Tab *searchTab(Window);

	/// obsolete
	enum Titlebar{SHADE=0, MINIMIZE, MAXIMIZE, CLOSE, STICK, MENU, EMPTY};

	inline const std::vector<Fluxbox::Titlebar>& getTitlebarRight() { return *m_rc_titlebar_right; }
	inline const std::vector<Fluxbox::Titlebar>& getTitlebarLeft() { return *m_rc_titlebar_left; }
	inline const char *getStyleFilename() const { return m_rc_stylefile->c_str(); }

	inline const char *getMenuFilename() const { return m_rc_menufile->c_str(); }
	inline const std::string &getSlitlistFilename() const { return *m_rc_slitlistfile; }
	inline int colorsPerChannel() const { return *m_rc_colors_per_channel; }

	inline const timeval &getAutoRaiseDelay() const { return resource.auto_raise_delay; }

	inline unsigned int getCacheLife() const { return *m_rc_cache_life * 60000; }
	inline unsigned int getCacheMax() const { return *m_rc_cache_max; }

	inline void maskWindowEvents(Window w, FluxboxWindow *bw)
		{ masked = w; masked_window = bw; }
	inline void setNoFocus(Bool f) { no_focus = f; }

	void setFocusedWindow(FluxboxWindow *w);
	void shutdown();
	void load_rc(BScreen *);
	void loadRootCommand(BScreen *);
	void loadTitlebar();
	void saveStyleFilename(const char *val) { m_rc_stylefile = (val == 0 ? "" : val); }
	void saveMenuFilename(const char *);
	void saveTitlebarFilename(const char *);
	void saveSlitlistFilename(const char *val) { m_rc_slitlistfile = (val == 0 ? "" : val); }
	void saveMenuSearch(Window, Basemenu *);
	void saveWindowSearch(Window, FluxboxWindow *);
	void saveToolbarSearch(Window, Toolbar *);
	void saveTabSearch(Window, Tab *);
	void saveGroupSearch(Window, FluxboxWindow *);
	void save_rc();
	void removeMenuSearch(Window);
	void removeWindowSearch(Window);
	void removeToolbarSearch(Window);
	void removeTabSearch(Window);
	void removeGroupSearch(Window);
	void restart(const char * = 0);
	void reconfigure();
	void reconfigureTabs();
	void rereadMenu();
	void checkMenu();

	/// handle any system signal sent to the application
	void handleEvent(FbTk::SignalEvent * const signum);
	void update(FbTk::Subject *changed);

	void attachSignals(FluxboxWindow &win);

	virtual void timeout();

	inline const Cursor &getSessionCursor() const { return cursor.session; }
	inline const Cursor &getMoveCursor() const { return cursor.move; }
	inline const Cursor &getLowerLeftAngleCursor() const { return cursor.ll_angle; }
	inline const Cursor &getLowerRightAngleCursor() const { return cursor.lr_angle; }

#ifdef	SLIT
	Slit *searchSlit(Window);

	void saveSlitSearch(Window, Slit *);
	void removeSlitSearch(Window);
#endif // SLIT

#ifndef	 HAVE_STRFTIME

	enum { B_AMERICANDATE = 1, B_EUROPEANDATE };
#endif // HAVE_STRFTIME

	typedef std::vector<Fluxbox::Titlebar> TitlebarList;

private:
	struct cursor {
		Cursor session, move, ll_angle, lr_angle;
	} cursor;

	typedef struct MenuTimestamp {
		char *filename;
		time_t timestamp;
	} MenuTimestamp;

	struct resource {
		Time double_click_interval;
		timeval auto_raise_delay;
	} resource;

	std::string getRcFilename();
	void getDefaultDataFilename(char *, std::string &);
	void load_rc();

	void reload_rc();
	void real_rereadMenu();
	void real_reconfigure();

	void handleEvent(XEvent *xe);

	void setupConfigFiles();
	void handleButtonEvent(XButtonEvent &be);
	void handleUnmapNotify(XUnmapEvent &ue);
	void handleClientMessage(XClientMessageEvent &ce);
	void handleKeyEvent(XKeyEvent &ke);
	void doWindowAction(Keys::KeyAction action, const int param);

	ResourceManager m_resourcemanager, m_screen_rm;

	//--- Resources
	Resource<bool> m_rc_tabs, m_rc_iconbar;
	Resource<int> m_rc_colors_per_channel;
	Resource<std::string> m_rc_stylefile,
		m_rc_menufile, m_rc_keyfile, m_rc_slitlistfile,
		m_rc_groupfile;

	Resource<TitlebarList> m_rc_titlebar_left, m_rc_titlebar_right;
	Resource<unsigned int> m_rc_cache_life, m_rc_cache_max;

	void setTitlebar(std::vector<Fluxbox::Titlebar>& dir, const char *arg);

	std::map<Window, FluxboxWindow *> windowSearch;
	std::map<Window, FluxboxWindow *> groupSearch;
	std::map<Window, Basemenu *> menuSearch;
	std::map<Window, Toolbar *> toolbarSearch;
	typedef std::map<Window, Tab *> TabList;
	TabList tabSearch;

#ifdef SLIT
	std::map<Window, Slit *> slitSearch;
#ifdef KDE
	//For KDE dock applets
	Atom kwm1_dockwindow; //KDE v1.x
	Atom kwm2_dockwindow; //KDE v2.x
#endif//KDE
#endif // SLIT

	std::list<MenuTimestamp *> menuTimestamps;
	typedef std::list<BScreen *> ScreenList;
	ScreenList screenList;

	FluxboxWindow *focused_window, *masked_window;
	BTimer timer;

#ifdef		HAVE_GETPID
	Atom fluxbox_pid;
#endif // HAVE_GETPID

	bool no_focus, reconfigure_wait, reread_menu_wait;
	Time last_time;
	Window masked;
	std::string rc_file; ///< resource filename
	char **argv;
	int argc;
	std::auto_ptr<Keys> key;
	std::string slitlist_path;
	//default arguments for titlebar left and right
	static Fluxbox::Titlebar m_titlebar_left[], m_titlebar_right[];

	static Fluxbox *singleton;
	std::vector<AtomHandler *> m_atomhandler;
};

#endif // _FLUXBOX_HH_
<commit_msg>using new SignalEventHandler and EventHandler classes<commit_after>// fluxbox.hh for Fluxbox Window Manager
// Copyright (c) 2001 - 2002 Henrik Kinnunen (fluxgen@linuxmail.org)
//
// blackbox.hh for Blackbox - an X11 Window manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.	IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// $Id: fluxbox.hh,v 1.33 2002/11/27 21:59:25 fluxgen Exp $

#ifndef	 FLUXBOX_HH
#define	 FLUXBOX_HH

#include "Resource.hh"
#include "Keys.hh"
#include "BaseDisplay.hh"
#include "Image.hh"
#include "Timer.hh"
#include "Window.hh"
#include "Tab.hh"
#include "Toolbar.hh"
#include "Observer.hh"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H

#ifdef	SLIT
#include "Slit.hh"
#endif // SLIT

#include "SignalHandler.hh"
#include "FbAtoms.hh"

#include <X11/Xlib.h>
#include <X11/Xresource.h>

#include <cstdio>

#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else // !TIME_WITH_SYS_TIME
#ifdef	HAVE_SYS_TIME_H
#include <sys/time.h>
#else // !HAVE_SYS_TIME_H
#include <time.h>
#endif // HAVE_SYS_TIME_H
#endif // TIME_WITH_SYS_TIME

#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>

class AtomHandler;

/**
	main class for the window manager.
	singleton type
*/
class Fluxbox : public BaseDisplay, public TimeoutHandler,
	public FbTk::SignalEventHandler,
	public FbAtoms,
	public FbTk::Observer {
public:
	Fluxbox(int argc, char **argv, const char * dpy_name= 0, const char *rc = 0);
	virtual ~Fluxbox();

	static Fluxbox *instance() { return singleton; }

	inline bool useTabs() { return *m_rc_tabs; }
	inline bool useIconBar() { return *m_rc_iconbar; }
	inline void saveTabs(bool value) { *m_rc_tabs = value; }
	inline void saveIconBar(bool value) { m_rc_iconbar = value; }
#ifdef HAVE_GETPID
	inline Atom getFluxboxPidAtom() const { return fluxbox_pid; }
	#ifdef KDE
	//For KDE dock applets
	inline Atom getKWM1DockwindowAtom() const { return kwm1_dockwindow; } //KDE v1.x
	inline Atom getKWM2DockwindowAtom() const { return kwm2_dockwindow; } //KDE v2.x
	#endif
#endif // HAVE_GETPID

	Basemenu *searchMenu(Window);

	FluxboxWindow *searchGroup(Window, FluxboxWindow *);
	FluxboxWindow *searchWindow(Window);
	inline FluxboxWindow *getFocusedWindow() { return focused_window; }

	BScreen *searchScreen(Window w);

	inline const Time &getDoubleClickInterval() const { return resource.double_click_interval; }
	inline const Time &getLastTime() const { return last_time; }

	Toolbar *searchToolbar(Window w);
	Tab *searchTab(Window);

	/// obsolete
	enum Titlebar{SHADE=0, MINIMIZE, MAXIMIZE, CLOSE, STICK, MENU, EMPTY};

	inline const std::vector<Fluxbox::Titlebar>& getTitlebarRight() { return *m_rc_titlebar_right; }
	inline const std::vector<Fluxbox::Titlebar>& getTitlebarLeft() { return *m_rc_titlebar_left; }
	inline const char *getStyleFilename() const { return m_rc_stylefile->c_str(); }

	inline const char *getMenuFilename() const { return m_rc_menufile->c_str(); }
	inline const std::string &getSlitlistFilename() const { return *m_rc_slitlistfile; }
	inline int colorsPerChannel() const { return *m_rc_colors_per_channel; }

	inline const timeval &getAutoRaiseDelay() const { return resource.auto_raise_delay; }

	inline unsigned int getCacheLife() const { return *m_rc_cache_life * 60000; }
	inline unsigned int getCacheMax() const { return *m_rc_cache_max; }

	inline void maskWindowEvents(Window w, FluxboxWindow *bw)
		{ masked = w; masked_window = bw; }
	inline void setNoFocus(Bool f) { no_focus = f; }

	void setFocusedWindow(FluxboxWindow *w);
	void shutdown();
	void load_rc(BScreen *);
	void loadRootCommand(BScreen *);
	void loadTitlebar();
	void saveStyleFilename(const char *val) { m_rc_stylefile = (val == 0 ? "" : val); }
	void saveMenuFilename(const char *);
	void saveTitlebarFilename(const char *);
	void saveSlitlistFilename(const char *val) { m_rc_slitlistfile = (val == 0 ? "" : val); }
	void saveMenuSearch(Window, Basemenu *);
	void saveWindowSearch(Window, FluxboxWindow *);
	void saveToolbarSearch(Window, Toolbar *);
	void saveTabSearch(Window, Tab *);
	void saveGroupSearch(Window, FluxboxWindow *);
	void save_rc();
	void removeMenuSearch(Window);
	void removeWindowSearch(Window);
	void removeToolbarSearch(Window);
	void removeTabSearch(Window);
	void removeGroupSearch(Window);
	void restart(const char * = 0);
	void reconfigure();
	void reconfigureTabs();
	void rereadMenu();
	void checkMenu();

	/// handle any system signal sent to the application
	void handleSignal(int signum);
	void update(FbTk::Subject *changed);

	void attachSignals(FluxboxWindow &win);

	virtual void timeout();

	inline const Cursor &getSessionCursor() const { return cursor.session; }
	inline const Cursor &getMoveCursor() const { return cursor.move; }
	inline const Cursor &getLowerLeftAngleCursor() const { return cursor.ll_angle; }
	inline const Cursor &getLowerRightAngleCursor() const { return cursor.lr_angle; }

#ifdef	SLIT
	Slit *searchSlit(Window);

	void saveSlitSearch(Window, Slit *);
	void removeSlitSearch(Window);
#endif // SLIT

#ifndef	 HAVE_STRFTIME

	enum { B_AMERICANDATE = 1, B_EUROPEANDATE };
#endif // HAVE_STRFTIME

	typedef std::vector<Fluxbox::Titlebar> TitlebarList;

private:
	struct cursor {
		Cursor session, move, ll_angle, lr_angle;
	} cursor;

	typedef struct MenuTimestamp {
		char *filename;
		time_t timestamp;
	} MenuTimestamp;

	struct resource {
		Time double_click_interval;
		timeval auto_raise_delay;
	} resource;

	std::string getRcFilename();
	void getDefaultDataFilename(char *, std::string &);
	void load_rc();

	void reload_rc();
	void real_rereadMenu();
	void real_reconfigure();

	void handleEvent(XEvent *xe);

	void setupConfigFiles();
	void handleButtonEvent(XButtonEvent &be);
	void handleUnmapNotify(XUnmapEvent &ue);
	void handleClientMessage(XClientMessageEvent &ce);
	void handleKeyEvent(XKeyEvent &ke);
	void doWindowAction(Keys::KeyAction action, const int param);

	ResourceManager m_resourcemanager, m_screen_rm;

	//--- Resources
	Resource<bool> m_rc_tabs, m_rc_iconbar;
	Resource<int> m_rc_colors_per_channel;
	Resource<std::string> m_rc_stylefile,
		m_rc_menufile, m_rc_keyfile, m_rc_slitlistfile,
		m_rc_groupfile;

	Resource<TitlebarList> m_rc_titlebar_left, m_rc_titlebar_right;
	Resource<unsigned int> m_rc_cache_life, m_rc_cache_max;

	void setTitlebar(std::vector<Fluxbox::Titlebar>& dir, const char *arg);

	std::map<Window, FluxboxWindow *> windowSearch;
	std::map<Window, FluxboxWindow *> groupSearch;
	std::map<Window, Basemenu *> menuSearch;
	std::map<Window, Toolbar *> toolbarSearch;
	typedef std::map<Window, Tab *> TabList;
	TabList tabSearch;

#ifdef SLIT
	std::map<Window, Slit *> slitSearch;
#ifdef KDE
	//For KDE dock applets
	Atom kwm1_dockwindow; //KDE v1.x
	Atom kwm2_dockwindow; //KDE v2.x
#endif//KDE
#endif // SLIT

	std::list<MenuTimestamp *> menuTimestamps;
	typedef std::list<BScreen *> ScreenList;
	ScreenList screenList;

	FluxboxWindow *focused_window, *masked_window;
	BTimer timer;

#ifdef		HAVE_GETPID
	Atom fluxbox_pid;
#endif // HAVE_GETPID

	bool no_focus, reconfigure_wait, reread_menu_wait;
	Time last_time;
	Window masked;
	std::string rc_file; ///< resource filename
	char **argv;
	int argc;
	std::auto_ptr<Keys> key;
	std::string slitlist_path;
	//default arguments for titlebar left and right
	static Fluxbox::Titlebar m_titlebar_left[], m_titlebar_right[];

	static Fluxbox *singleton;
	std::vector<AtomHandler *> m_atomhandler;
};

#endif // _FLUXBOX_HH_
<|endoftext|>


<commit_before>#include "config.h"
#include "libs/mpq_libmpq04.h"
#include "libs/dbcfile.h"

int main() {
	printf("Opening locale.mpq...\n");
	MPQArchive locale(WOW_INSTALL_DIR"Data/"WOW_LOCALE"/locale-"WOW_LOCALE".MPQ");

	printf("Opening WorldMapContinent.dbc...\n");
	DBCFile wmc("DBFilesClient\\WorldMapContinent.dbc");
	bool res = wmc.open();
	if(!res)
		return 1;
	printf("Extracting %i continents...\n", wmc.getRecordCount());
	for(DBCFile::Iterator itr = wmc.begin(); itr != wmc.end(); ++itr) {
		const DBCFile::Record& r(*itr);
		int cid = r.getInt(1);
		int mid = r.getInt(2);
		float x1 = r.getFloat(9);
		float y1 = r.getFloat(10);
		float x2 = r.getFloat(11);
		float y2 = r.getFloat(12);
		printf("%i, %i, %g, %g, %g, %g\n", cid, mid, x1, y1, x2, y2);
	}

	printf("Opening Map.dbc...\n");
	DBCFile map("DBFilesClient\\Map.dbc");

	return 0;
}
<commit_msg>WorldMapArea.dbc<commit_after>#include "config.h"
#include "libs/mpq_libmpq04.h"
#include "libs/dbcfile.h"

struct F2 {
	float x, y;
};

int main() {
	printf("Opening locale.mpq...\n");
	MPQArchive locale(WOW_INSTALL_DIR"Data/"WOW_LOCALE"/locale-"WOW_LOCALE".MPQ");

	printf("Opening WorldMapContinent.dbc...\n");
	DBCFile wmc("DBFilesClient\\WorldMapContinent.dbc");
	bool res = wmc.open();
	if(!res)
		return 1;
	printf("Extracting %i continents...\n", wmc.getRecordCount());
	for(DBCFile::Iterator itr = wmc.begin(); itr != wmc.end(); ++itr) {
		const DBCFile::Record& r(*itr);
		int cid = r.getInt(0);
		int mid = r.getInt(1);
		float x1 = r.getFloat(9);
		float y1 = r.getFloat(10);
		float x2 = r.getFloat(11);
		float y2 = r.getFloat(12);
		printf("%i, %i, %gx%g, %gx%g\n", cid, mid, x1, y1, x2, y2);
	}

	printf("Opening WorldMapArea.dbc...\n");
	DBCFile wma("DBFilesClient\\WorldMapArea.dbc");
	res = wma.open();
	if(!res)
		return 1;
	printf("Extracting %i map areas...\n", wma.getRecordCount());
	for(DBCFile::Iterator itr = wma.begin(); itr != wma.end(); ++itr) {
		const DBCFile::Record& r(*itr);
		int map = r.getInt(1);
		int at = r.getInt(2);
		const char* name = r.getString(3);
		F2 a = { r.getFloat(6), r.getFloat(4) };
		F2 b = { r.getFloat(7), r.getFloat(5) };
		int vmap = r.getInt(8);
		int dmap = r.getInt(9);
		printf("%i, %i, '%s', %gx%g, %gx%g, %i, %i\n",
			map, at, name, a.x, a.y, b.x, b.y, vmap, dmap);
	}

	// Records of WMA where 'at' == 0 are continents.
	// The world map images are found in interface/worldmap.
	// They are numbered 1 to 12 and ordered in a 4x3 grid,
	// left-to-right, top-to-bottom. Tiles are 256x256 pixels,
	// making the full image 1024x768 pixels.
	// I suspect the client would bilinear-scale these textures for higher resolutions.

	// Now: extract them!

	return 0;
}
<|endoftext|>


<commit_before>#include "xchainer/routines/indexing.h"

#include <algorithm>
#include <cstdint>
#include <iterator>
#include <string>
#include <vector>

#include "nonstd/optional.hpp"

#include "xchainer/array.h"
#include "xchainer/array_index.h"
#include "xchainer/dtype.h"
#include "xchainer/graph.h"
#include "xchainer/routines/creation.h"
#include "xchainer/routines/util.h"
#include "xchainer/shape.h"
#include "xchainer/slice.h"

namespace xchainer {
namespace internal {
namespace {

// Returns an array where elements at indices are added by the addends `b`.
//
// It is not-implace operation: the input arrays are not altered.
// It is differentiable with respect to `a` and `b`.
Array AddAt(const Array& a, const std::vector<ArrayIndex>& indices, const Array& b) {
    // TODO(sonots): dtype conversion
    CheckEqual(a.dtype(), b.dtype());

    Array out = a.AsConstant(CopyKind::kCopy);
    Array out_view = out.At(indices);

    // TODO(sonots): broadcasting
    CheckEqual(out_view.shape(), b.shape());

    a.device().Add(b, out_view, out_view);

    auto a_backward_function = [](const Array& gout, const std::vector<GraphId>&) { return gout; };
    auto b_backward_function = [indices](const Array& gout, const std::vector<GraphId>&) { return gout.At(indices); };
    xchainer::internal::SetUpOpNodes("add_at", {a, b}, out, {a_backward_function, b_backward_function});

    return out;
}

}  // namespace

Array At(const Array& a, const std::vector<ArrayIndex>& indices) {
    std::vector<int64_t> out_shape;
    std::vector<int64_t> out_strides;
    int64_t out_offset = a.offset();
    int64_t i_in = 0;
    for (const ArrayIndex& index : indices) {
        switch (index.tag()) {
            case ArrayIndexTag::kSingleElement: {
                int64_t dim = a.shape()[i_in];
                if (index.index() < -dim || dim <= index.index()) {
                    throw DimensionError(
                            "Index " + std::to_string(index.index()) + " is out of bounds for axis " + std::to_string(i_in) +
                            " with size " + std::to_string(dim));
                }
                out_offset += a.strides()[i_in] * ((index.index() + dim) % dim);
                ++i_in;
                break;
            }
            case ArrayIndexTag::kSlice: {
                const Slice& slice = index.slice();
                int64_t slice_length = slice.GetLength(a.shape()[i_in]);
                out_offset += a.strides()[i_in] * slice.GetStart(a.shape()[i_in]);
                out_shape.push_back(slice_length);
                out_strides.push_back(a.strides()[i_in] * slice.step());
                ++i_in;
                break;
            }
            case ArrayIndexTag::kNewAxis:
                out_shape.push_back(1);
                out_strides.push_back(0);
                break;
            default:
                assert(false);
        }
    }
    for (int64_t i = i_in; i < a.ndim(); ++i) {
        out_shape.push_back(a.shape()[i]);
        out_strides.push_back(a.strides()[i]);
    }

    Array out = xchainer::internal::MakeArray(
            {out_shape.begin(), out_shape.end()}, {out_strides.begin(), out_strides.end()}, a.dtype(), a.device(), a.data(), out_offset);

    auto backward_function = [ indices, other = a ](const Array& gout, const std::vector<GraphId>&) {
        Array gin = ZerosLike(other, other.device());
        return AddAt(gin, indices, gout);
    };
    xchainer::internal::SetUpOpNodes("get_item", {a}, out, {backward_function});

    return out;
}

}  // namespace internal

namespace {

// Adds elements of `b` indexed by `indices` into `a` and returns the result.
// Used in backward pass of Take()
//
// It is not-implace operation: the input arrays are not altered.
// It is differentiable with respect to `a` and `b`.
Array AddAt(const Array& a, const Array& indices, int8_t axis, const Array& b) {
    assert(0 <= axis && axis < a.ndim());
    assert(b.ndim() == indices.ndim() + a.ndim() - 1);
    CheckEqual(a.dtype(), b.dtype());

    Array out = EmptyLike(a, a.device());

    a.device().AddAt(a, indices, axis, b, out);

    auto a_backward_function = [](const Array& gout, const std::vector<GraphId>&) { return gout; };
    auto b_backward_function = [indices, axis](const Array& gout, const std::vector<GraphId>&) { return Take(gout, indices, axis); };
    xchainer::internal::SetUpOpNodes("add_at", {a, b}, out, {a_backward_function, b_backward_function});

    return out;
}

}  // namespace

Array Take(const Array& a, const Array& indices, int8_t axis) {
    // TODO(niboshi): Support other dtypes by casting
    if (indices.dtype() != Dtype::kInt64) {
        throw DtypeError(
                std::string{"Only "} + GetDtypeName(Dtype::kInt64) + " is supported as indices, but given " +
                GetDtypeName(indices.dtype()));
    }

    int8_t axis_norm = internal::NormalizeAxis(axis, a.ndim());

    std::vector<int64_t> out_shape_vec;
    out_shape_vec.reserve(a.ndim() + indices.ndim() - 1);
    std::copy(a.shape().begin(), a.shape().begin() + axis_norm, std::back_inserter(out_shape_vec));
    std::copy(indices.shape().begin(), indices.shape().end(), std::back_inserter(out_shape_vec));
    std::copy(a.shape().begin() + (axis_norm + 1), a.shape().end(), std::back_inserter(out_shape_vec));
    Array out = Empty({out_shape_vec.begin(), out_shape_vec.end()}, a.dtype(), a.device());

    a.device().Take(a, indices, axis_norm, out);

    auto backward_function = [ indices, axis_norm, a_shape = a.shape() ](const Array& gout, const std::vector<GraphId>&) {
        return AddAt(Zeros(a_shape, gout.dtype(), gout.device()), indices, axis_norm, gout);
    };
    xchainer::internal::SetUpOpNodes("take", {a}, out, {backward_function});

    return out;
}

}  // namespace xchainer
<commit_msg>Fix bad spelling in comments<commit_after>#include "xchainer/routines/indexing.h"

#include <algorithm>
#include <cstdint>
#include <iterator>
#include <string>
#include <vector>

#include "nonstd/optional.hpp"

#include "xchainer/array.h"
#include "xchainer/array_index.h"
#include "xchainer/dtype.h"
#include "xchainer/graph.h"
#include "xchainer/routines/creation.h"
#include "xchainer/routines/util.h"
#include "xchainer/shape.h"
#include "xchainer/slice.h"

namespace xchainer {
namespace internal {
namespace {

// Returns an array where elements at indices are added by the addends `b`.
//
// It is not in-place  operation: the input arrays are not altered.
// It is differentiable with respect to `a` and `b`.
Array AddAt(const Array& a, const std::vector<ArrayIndex>& indices, const Array& b) {
    // TODO(sonots): dtype conversion
    CheckEqual(a.dtype(), b.dtype());

    Array out = a.AsConstant(CopyKind::kCopy);
    Array out_view = out.At(indices);

    // TODO(sonots): broadcasting
    CheckEqual(out_view.shape(), b.shape());

    a.device().Add(b, out_view, out_view);

    auto a_backward_function = [](const Array& gout, const std::vector<GraphId>&) { return gout; };
    auto b_backward_function = [indices](const Array& gout, const std::vector<GraphId>&) { return gout.At(indices); };
    xchainer::internal::SetUpOpNodes("add_at", {a, b}, out, {a_backward_function, b_backward_function});

    return out;
}

}  // namespace

Array At(const Array& a, const std::vector<ArrayIndex>& indices) {
    std::vector<int64_t> out_shape;
    std::vector<int64_t> out_strides;
    int64_t out_offset = a.offset();
    int64_t i_in = 0;
    for (const ArrayIndex& index : indices) {
        switch (index.tag()) {
            case ArrayIndexTag::kSingleElement: {
                int64_t dim = a.shape()[i_in];
                if (index.index() < -dim || dim <= index.index()) {
                    throw DimensionError(
                            "Index " + std::to_string(index.index()) + " is out of bounds for axis " + std::to_string(i_in) +
                            " with size " + std::to_string(dim));
                }
                out_offset += a.strides()[i_in] * ((index.index() + dim) % dim);
                ++i_in;
                break;
            }
            case ArrayIndexTag::kSlice: {
                const Slice& slice = index.slice();
                int64_t slice_length = slice.GetLength(a.shape()[i_in]);
                out_offset += a.strides()[i_in] * slice.GetStart(a.shape()[i_in]);
                out_shape.push_back(slice_length);
                out_strides.push_back(a.strides()[i_in] * slice.step());
                ++i_in;
                break;
            }
            case ArrayIndexTag::kNewAxis:
                out_shape.push_back(1);
                out_strides.push_back(0);
                break;
            default:
                assert(false);
        }
    }
    for (int64_t i = i_in; i < a.ndim(); ++i) {
        out_shape.push_back(a.shape()[i]);
        out_strides.push_back(a.strides()[i]);
    }

    Array out = xchainer::internal::MakeArray(
            {out_shape.begin(), out_shape.end()}, {out_strides.begin(), out_strides.end()}, a.dtype(), a.device(), a.data(), out_offset);

    auto backward_function = [ indices, other = a ](const Array& gout, const std::vector<GraphId>&) {
        Array gin = ZerosLike(other, other.device());
        return AddAt(gin, indices, gout);
    };
    xchainer::internal::SetUpOpNodes("get_item", {a}, out, {backward_function});

    return out;
}

}  // namespace internal

namespace {

// Adds elements of `b` indexed by `indices` into `a` and returns the result.
// Used in backward pass of Take()
//
// It is not in-place operation: the input arrays are not altered.
// It is differentiable with respect to `a` and `b`.
Array AddAt(const Array& a, const Array& indices, int8_t axis, const Array& b) {
    assert(0 <= axis && axis < a.ndim());
    assert(b.ndim() == indices.ndim() + a.ndim() - 1);
    CheckEqual(a.dtype(), b.dtype());

    Array out = EmptyLike(a, a.device());

    a.device().AddAt(a, indices, axis, b, out);

    auto a_backward_function = [](const Array& gout, const std::vector<GraphId>&) { return gout; };
    auto b_backward_function = [indices, axis](const Array& gout, const std::vector<GraphId>&) { return Take(gout, indices, axis); };
    xchainer::internal::SetUpOpNodes("add_at", {a, b}, out, {a_backward_function, b_backward_function});

    return out;
}

}  // namespace

Array Take(const Array& a, const Array& indices, int8_t axis) {
    // TODO(niboshi): Support other dtypes by casting
    if (indices.dtype() != Dtype::kInt64) {
        throw DtypeError(
                std::string{"Only "} + GetDtypeName(Dtype::kInt64) + " is supported as indices, but given " +
                GetDtypeName(indices.dtype()));
    }

    int8_t axis_norm = internal::NormalizeAxis(axis, a.ndim());

    std::vector<int64_t> out_shape_vec;
    out_shape_vec.reserve(a.ndim() + indices.ndim() - 1);
    std::copy(a.shape().begin(), a.shape().begin() + axis_norm, std::back_inserter(out_shape_vec));
    std::copy(indices.shape().begin(), indices.shape().end(), std::back_inserter(out_shape_vec));
    std::copy(a.shape().begin() + (axis_norm + 1), a.shape().end(), std::back_inserter(out_shape_vec));
    Array out = Empty({out_shape_vec.begin(), out_shape_vec.end()}, a.dtype(), a.device());

    a.device().Take(a, indices, axis_norm, out);

    auto backward_function = [ indices, axis_norm, a_shape = a.shape() ](const Array& gout, const std::vector<GraphId>&) {
        return AddAt(Zeros(a_shape, gout.dtype(), gout.device()), indices, axis_norm, gout);
    };
    xchainer::internal::SetUpOpNodes("take", {a}, out, {backward_function});

    return out;
}

}  // namespace xchainer
<|endoftext|>


<commit_before>#include "vec.hpp"
#include "lib/catch.hpp"

TEST_CASE( "base vector accessors", "" ) {
    Vec<1> x = { 5 };
    REQUIRE( x[0] == 5 );
    x[0] = 9;
    REQUIRE( x[0] == 9 );

    Vec<2> xy = { 1, 2 };
    REQUIRE( xy[0] == 1 );
    REQUIRE( xy[1] == 2 );

    Vec<100> big;
    for ( int i = 0; i < 100; i++ ) big[i] = i;
    for ( int i = 0; i < 100; i++ ) REQUIRE( big[i] == i );
}

TEST_CASE( "structured vector accessors", "" ) {
    Vec2 xy = { 1, 2 };
    REQUIRE( xy.x == 1 );
    REQUIRE( xy.y == 2 );

    xy.x = 3;
    xy.y = 4;
    REQUIRE( xy.x == 3 );
    REQUIRE( xy.y == 4 );

    Vec3 xyz = { 5, 6, 7 };
    REQUIRE( xyz.x == 5 );
    REQUIRE( xyz.y == 6 );
    REQUIRE( xyz.z == 7 );
    REQUIRE( xyz.r == 5 );
    REQUIRE( xyz.g == 6 );
    REQUIRE( xyz.b == 7 );
    REQUIRE( xyz.xy.x == 5 );
    REQUIRE( xyz.xy.y == 6 );

    Vec4 xyzw = { 9, 10, 11, 12 };
    REQUIRE( xyzw.x == 9 );
    REQUIRE( xyzw.y == 10 );
    REQUIRE( xyzw.z == 11 );
    REQUIRE( xyzw.w == 12 );
    REQUIRE( xyzw.r == 9 );
    REQUIRE( xyzw.g == 10 );
    REQUIRE( xyzw.b == 11 );
    REQUIRE( xyzw.a == 12 );
    REQUIRE( xyzw.xy.x == 9 );
    REQUIRE( xyzw.xy.y == 10 );
    REQUIRE( xyzw.xyz.x == 9 );
    REQUIRE( xyzw.xyz.y == 10 );
    REQUIRE( xyzw.xyz.z == 11 );
}

TEST_CASE( "vector operations", "" ) {
    Vec2 a = { 1, 2 };
    Vec2 b = { 3, 4 };
    Vec2 c = a + b;

    REQUIRE( c.x == 4 );
    REQUIRE( c.y == 6 );

    Vec3 d = { 5, 6, 7 };
    Vec3 e = { 8, 9, 10 };
    Vec3 f = d * e;

    REQUIRE( f.x == 40 );
    REQUIRE( f.y == 54 );
    REQUIRE( f.z == 70 );

    Vec4 g = { 15, 16, 17, 18 };
    Vec4 h = { 11, 12, 13, 14 };
    Vec4 i = g - h;

    REQUIRE( i.x == 4 );
    REQUIRE( i.y == 4 );
    REQUIRE( i.z == 4 );
    REQUIRE( i.w == 4 );

    Vec<5> j = { 19 * 2, 20 * 2, 21 * 2, 22 * 2, 23 * 2 };
    Vec<5> k = { 19, 20, 21, 22, 23 };
    Vec<5> l = j / k;

    REQUIRE( l[0] == 2 );
    REQUIRE( l[1] == 2 );
    REQUIRE( l[2] == 2 );
    REQUIRE( l[3] == 2 );
    REQUIRE( l[4] == 2 );

    Vec<6> m = { 19 * 2, 20 * 2, 21 * 2, 22 * 2, 23 * 2, 24 * 2 };
    float n = 2;
    Vec<6> o = m / n;

    REQUIRE( o[0] == 19 );
    REQUIRE( o[1] == 20 );
    REQUIRE( o[2] == 21 );
    REQUIRE( o[3] == 22 );
    REQUIRE( o[4] == 23 );
    REQUIRE( o[5] == 24 );

    Vec<6> p = { 19, 20, 21, 22, 23, 24 };
    float q = 2;
    Vec<6> r = p * q;

    REQUIRE( r[0] == 38 );
    REQUIRE( r[1] == 40 );
    REQUIRE( r[2] == 42 );
    REQUIRE( r[3] == 44 );
    REQUIRE( r[4] == 46 );
    REQUIRE( r[5] == 48 );
}
<commit_msg>test free vector functions<commit_after>#include "vec.hpp"
#include "lib/catch.hpp"

TEST_CASE( "base vector accessors", "" ) {
    Vec<1> x = { 5 };
    REQUIRE( x[0] == 5 );
    x[0] = 9;
    REQUIRE( x[0] == 9 );

    Vec<2> xy = { 1, 2 };
    REQUIRE( xy[0] == 1 );
    REQUIRE( xy[1] == 2 );

    Vec<100> big;
    for ( int i = 0; i < 100; i++ ) big[i] = i;
    for ( int i = 0; i < 100; i++ ) REQUIRE( big[i] == i );
}

TEST_CASE( "structured vector accessors", "" ) {
    Vec2 xy = { 1, 2 };
    REQUIRE( xy.x == 1 );
    REQUIRE( xy.y == 2 );

    xy.x = 3;
    xy.y = 4;
    REQUIRE( xy.x == 3 );
    REQUIRE( xy.y == 4 );

    Vec3 xyz = { 5, 6, 7 };
    REQUIRE( xyz.x == 5 );
    REQUIRE( xyz.y == 6 );
    REQUIRE( xyz.z == 7 );
    REQUIRE( xyz.r == 5 );
    REQUIRE( xyz.g == 6 );
    REQUIRE( xyz.b == 7 );
    REQUIRE( xyz.xy.x == 5 );
    REQUIRE( xyz.xy.y == 6 );

    Vec4 xyzw = { 9, 10, 11, 12 };
    REQUIRE( xyzw.x == 9 );
    REQUIRE( xyzw.y == 10 );
    REQUIRE( xyzw.z == 11 );
    REQUIRE( xyzw.w == 12 );
    REQUIRE( xyzw.r == 9 );
    REQUIRE( xyzw.g == 10 );
    REQUIRE( xyzw.b == 11 );
    REQUIRE( xyzw.a == 12 );
    REQUIRE( xyzw.xy.x == 9 );
    REQUIRE( xyzw.xy.y == 10 );
    REQUIRE( xyzw.xyz.x == 9 );
    REQUIRE( xyzw.xyz.y == 10 );
    REQUIRE( xyzw.xyz.z == 11 );
}

TEST_CASE( "vector operations", "" ) {
    Vec2 a = { 1, 2 };
    Vec2 b = { 3, 4 };
    Vec2 c = a + b;

    REQUIRE( c.x == 4 );
    REQUIRE( c.y == 6 );

    Vec3 d = { 5, 6, 7 };
    Vec3 e = { 8, 9, 10 };
    Vec3 f = d * e;

    REQUIRE( f.x == 40 );
    REQUIRE( f.y == 54 );
    REQUIRE( f.z == 70 );

    Vec4 g = { 15, 16, 17, 18 };
    Vec4 h = { 11, 12, 13, 14 };
    Vec4 i = g - h;

    REQUIRE( i.x == 4 );
    REQUIRE( i.y == 4 );
    REQUIRE( i.z == 4 );
    REQUIRE( i.w == 4 );

    Vec<5> j = { 19 * 2, 20 * 2, 21 * 2, 22 * 2, 23 * 2 };
    Vec<5> k = { 19, 20, 21, 22, 23 };
    Vec<5> l = j / k;

    REQUIRE( l[0] == 2 );
    REQUIRE( l[1] == 2 );
    REQUIRE( l[2] == 2 );
    REQUIRE( l[3] == 2 );
    REQUIRE( l[4] == 2 );

    Vec<6> m = { 19 * 2, 20 * 2, 21 * 2, 22 * 2, 23 * 2, 24 * 2 };
    float n = 2;
    Vec<6> o = m / n;

    REQUIRE( o[0] == 19 );
    REQUIRE( o[1] == 20 );
    REQUIRE( o[2] == 21 );
    REQUIRE( o[3] == 22 );
    REQUIRE( o[4] == 23 );
    REQUIRE( o[5] == 24 );

    Vec<6> p = { 19, 20, 21, 22, 23, 24 };
    float q = 2;
    Vec<6> r = p * q;

    REQUIRE( r[0] == 38 );
    REQUIRE( r[1] == 40 );
    REQUIRE( r[2] == 42 );
    REQUIRE( r[3] == 44 );
    REQUIRE( r[4] == 46 );
    REQUIRE( r[5] == 48 );
}

TEST_CASE( "vector methods", "" ) {
    const float EPSILON = 1e-6;

    Vec2 a = { 2, 3 };

    REQUIRE( fabs( length( a ) - sqrt( 2*2 + 3*3 ) ) < EPSILON );
    REQUIRE( lengthsq( a ) == 2*2 + 3*3 );
    REQUIRE( length( normalize( a ) ) - 1 < EPSILON );

    Vec3 b = { 4, 5, 6 };

    REQUIRE( fabs( length( b ) - sqrt( 4*4 + 5*5 + 6*6 ) ) < EPSILON );
    REQUIRE( lengthsq( b ) == 4*4 + 5*5 + 6*6 );
    REQUIRE( length( normalize( b ) ) - 1 < EPSILON );

    Vec4 c = { 7, 8, 9, 10 };

    REQUIRE( fabs( length( c ) - sqrt( 7*7 + 8*8 + 9*9 + 10*10 ) ) < EPSILON );
    REQUIRE( lengthsq( c ) == 7*7 + 8*8 + 9*9 + 10*10 );
    REQUIRE( length( normalize( c ) ) - 1 < EPSILON );

    Vec2 a2 = { 4, 5 };
    REQUIRE( dot( a, a2 ) == 2*4 + 3*5 );

    Vec3 b2 = { 7, 8, 9 };
    REQUIRE( dot( b, b2 ) == 4*7 + 5*8 + 6*9 );

    Vec4 c2 = { 11, 12, 13, 14 };
    REQUIRE( dot( c, c2 ) == 7*11 + 8*12 + 9*13 + 10*14 );

    REQUIRE( dot( cross( b, b2 ), b ) == 0 );
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Endless Mobile
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * Written by:
 *     Jasper St. Pierre <jstpierre@mecheye.net>
 */

#include "gobject.h"
#include "function.h"
#include "value.h"

using namespace v8;

namespace GNodeJS {

static bool InitGParameterFromProperty(GParameter    *parameter,
                                       void          *klass,
                                       Handle<String> name,
                                       Handle<Value>  value)
{
    String::Utf8Value name_str (name);
    GParamSpec *pspec = g_object_class_find_property (G_OBJECT_CLASS (klass), *name_str);
    if (pspec == NULL)
        return false;

    parameter->name = pspec->name;
    g_value_init (&parameter->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
    V8ToGValue (&parameter->value, value);
    return true;
}

static bool InitGParametersFromProperty(GParameter    **parameters_p,
                                        int            *n_parameters_p,
                                        void           *klass,
                                        Handle<Object>  property_hash)
{
    Local<Array> properties = property_hash->GetOwnPropertyNames ();
    int n_parameters = properties->Length();
    GParameter *parameters = g_new0 (GParameter, n_parameters);

    for (int i = 0; i < n_parameters; i++) {
        Local<Value> name = properties->Get (i);
        Local<Value> value = property_hash->Get (name);

        if (!InitGParameterFromProperty (&parameters[i], klass, name->ToString (), value))
            return false;
    }

    *parameters_p = parameters;
    *n_parameters_p = n_parameters;
    return true;
}

static void ToggleNotify(gpointer user_data, GObject *gobject, gboolean toggle_down);

G_DEFINE_QUARK(gnode_js_object, gnode_js_object);

static void AssociateGObject(Handle<Object> object, GObject *gobject) {
    object->SetPointerInInternalField (0, gobject);

    g_object_ref_sink (gobject);
    g_object_add_toggle_ref (gobject, ToggleNotify, NULL);

    Object *object_p = *object;
    g_object_set_qdata (gobject, gnode_js_object_quark (), object_p);
}

static Handle<Value> GObjectConstructor(const Arguments &args) {
    HandleScope scope;

    /* The flow of this function is a bit twisty.

     * There's two cases for when this code is called:
     * user code doing `new Gtk.Widget({ ... })`, and
     * internal code as part of WrapperFromGObject, where
     * the constructor is called with one external. */

    if (!args.IsConstructCall ()) {
        ThrowException (Exception::TypeError (String::New ("Not a construct call.")));
        return scope.Close (Undefined ());
    }

    Handle<Object> self = args.This ();

    if (args[0]->IsExternal ()) {
        /* The External case. This is how WrapperFromGObject is called. */

        void *data = External::Unwrap (args[0]);
        GObject *gobject = G_OBJECT (data);

        AssociateGObject (self, gobject);
    } else {
        /* User code calling `new Gtk.Widget({ ... })` */

        GObject *gobject;
        GIBaseInfo *info = (GIBaseInfo *) External::Unwrap(args.Data ());
        GType gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *) info);
        void *klass = g_type_class_ref (gtype);

        GParameter *parameters = NULL;
        int n_parameters = 0;

        if (args[0]->IsObject ()) {
            Local<Object> property_hash = args[0]->ToObject ();

            if (!InitGParametersFromProperty (&parameters, &n_parameters, klass, property_hash)) {
                ThrowException (Exception::TypeError (String::New ("Unable to make GParameters.")));
                goto out;
            }
        }

        gobject = (GObject *) g_object_newv (gtype, n_parameters, parameters);
        AssociateGObject (self, gobject);

    out:
        g_free (parameters);
        g_type_class_unref (klass);
    }

    return self;
}

G_DEFINE_QUARK(gnode_js_template, gnode_js_template);

static void ClassDestroyed(Persistent<Value> object, void *data) {
    GIBaseInfo *info = (GIBaseInfo *) data;
    GType gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *) info);
    g_type_set_qdata (gtype, gnode_js_template_quark (), NULL);
    g_base_info_unref (info);
}

static void DefineConstructorMethods(Handle<FunctionTemplate> constructor, GIBaseInfo *info) {
    int n_methods = g_object_info_get_n_methods (info);
    for (int i = 0; i < n_methods; i++) {
        GIFunctionInfo *meth_info = g_object_info_get_method (info, i);
        GIFunctionInfoFlags flags = g_function_info_get_flags (meth_info);

        if (!(flags & GI_FUNCTION_IS_METHOD)) {
            const char *function_name = g_base_info_get_name ((GIBaseInfo *) meth_info);
            Handle<Function> fn = MakeFunction (meth_info);
            constructor->Set (String::NewSymbol (function_name), fn);
        }

        g_base_info_unref ((GIBaseInfo *) meth_info);
    }
}

static void DefinePrototypeMethods(Handle<ObjectTemplate> prototype, GIBaseInfo *info) {
    int n_methods = g_object_info_get_n_methods (info);
    for (int i = 0; i < n_methods; i++) {
        GIFunctionInfo *meth_info = g_object_info_get_method (info, i);
        GIFunctionInfoFlags flags = g_function_info_get_flags (meth_info);

        if (flags & GI_FUNCTION_IS_METHOD) {
            const char *function_name = g_base_info_get_name ((GIBaseInfo *) meth_info);
            Handle<Function> fn = MakeFunction (meth_info);
            prototype->Set (String::NewSymbol (function_name), fn);
        }

        g_base_info_unref ((GIBaseInfo *) meth_info);
    }
}

static Handle<FunctionTemplate> GetClassTemplateFromGI(GIBaseInfo *info);

static Handle<FunctionTemplate> GetClassTemplate(GIBaseInfo *info, GType gtype) {
    void *data = g_type_get_qdata (gtype, gnode_js_template_quark ());
    if (data) {
        FunctionTemplate *tpl_p = (FunctionTemplate *) data;
        Persistent<FunctionTemplate> tpl(tpl_p);
        return tpl;
    } else {
        Persistent<FunctionTemplate> tpl = Persistent<FunctionTemplate>::New (FunctionTemplate::New (GObjectConstructor, External::Wrap (info)));
        tpl.MakeWeak (g_base_info_ref (info), ClassDestroyed);

        const char *class_name = g_base_info_get_name (info);
        tpl->SetClassName (String::NewSymbol (class_name));

        FunctionTemplate *tpl_p = *tpl;
        g_type_set_qdata (gtype, gnode_js_template_quark (), tpl_p);

        GIObjectInfo *parent_info = g_object_info_get_parent (info);
        if (parent_info) {
            Handle<FunctionTemplate> parent_tpl = GetClassTemplateFromGI ((GIBaseInfo *) parent_info);
            tpl->Inherit (parent_tpl);
        }

        DefineConstructorMethods (tpl, info);
        DefinePrototypeMethods (tpl->PrototypeTemplate (), info);

        tpl->InstanceTemplate ()->SetInternalFieldCount (1);

        return tpl;
    }
}

static Handle<FunctionTemplate> GetClassTemplateFromGI(GIBaseInfo *info) {
    GType gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *) info);
    return GetClassTemplate (info, gtype);
}

static Handle<FunctionTemplate> GetClassTemplateFromGType(GType gtype) {
    GIRepository *repo = g_irepository_get_default ();
    GIBaseInfo *info = g_irepository_find_by_gtype (repo, gtype);
    return GetClassTemplate (info, gtype);
}

Handle<Function> MakeClass(GIBaseInfo *info) {
    Handle<FunctionTemplate> tpl = GetClassTemplateFromGI (info);
    return tpl->GetFunction ();
}

static void ObjectDestroyed(Persistent<Value> object, void *data) {
    GObject *gobject = G_OBJECT (data);

    /* We're destroying the wrapper object, so make sure to clear out
     * the qdata that points back to us. */
    g_object_set_qdata (gobject, gnode_js_object_quark (), NULL);

    g_object_unref (gobject);
}

static void ToggleNotify(gpointer user_data, GObject *gobject, gboolean toggle_down) {
    void *data = g_object_get_qdata (gobject, gnode_js_object_quark ());
    assert (data != NULL);
    Object *obj_p = (Object *) data;
    Persistent<Object> obj(obj_p);

    if (toggle_down) {
        /* We're dropping from 2 refs to 1 ref. We are the last holder. Make
         * sure that that our weak ref is installed. */
        obj.MakeWeak (gobject, ObjectDestroyed);
    } else {
        /* We're going from 1 ref to 2 refs. We can't let our wrapper be
         * collected, so make sure that our reference is persistent */
        obj.ClearWeak ();
    }
}

Handle<Value> WrapperFromGObject(GObject *gobject) {
    void *data = g_object_get_qdata (gobject, gnode_js_object_quark ());

    /* Easy case: we already have a wrapper. */
    if (data) {
        Object *obj_p = (Object *) data;
        Persistent<Object> obj(obj_p);
        return obj;
    } else {
        GType gtype = G_OBJECT_TYPE (gobject);

        Handle<FunctionTemplate> tpl = GetClassTemplateFromGType (gtype);
        Handle<Function> constructor = tpl->GetFunction ();

        Handle<Value> gobject_external = External::New (gobject);
        Handle<Value> args[] = { gobject_external };
        Local<Object> obj_local = constructor->NewInstance (1, args);
        Persistent<Object> obj = Persistent<Object>::New (obj_local);
        return obj;
    }
}

GObject * GObjectFromWrapper(Handle<Value> value) {
    Handle<Object> object = value->ToObject ();
    void *data = object->GetPointerFromInternalField (0);
    GObject *gobject = G_OBJECT (data);
    return gobject;
}

};
<commit_msg>gobject: Add a base class template<commit_after>/*
 * Copyright (C) 2014 Endless Mobile
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * Written by:
 *     Jasper St. Pierre <jstpierre@mecheye.net>
 */

#include "gobject.h"
#include "function.h"
#include "value.h"

using namespace v8;

namespace GNodeJS {

static bool InitGParameterFromProperty(GParameter    *parameter,
                                       void          *klass,
                                       Handle<String> name,
                                       Handle<Value>  value)
{
    String::Utf8Value name_str (name);
    GParamSpec *pspec = g_object_class_find_property (G_OBJECT_CLASS (klass), *name_str);
    if (pspec == NULL)
        return false;

    parameter->name = pspec->name;
    g_value_init (&parameter->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
    V8ToGValue (&parameter->value, value);
    return true;
}

static bool InitGParametersFromProperty(GParameter    **parameters_p,
                                        int            *n_parameters_p,
                                        void           *klass,
                                        Handle<Object>  property_hash)
{
    Local<Array> properties = property_hash->GetOwnPropertyNames ();
    int n_parameters = properties->Length();
    GParameter *parameters = g_new0 (GParameter, n_parameters);

    for (int i = 0; i < n_parameters; i++) {
        Local<Value> name = properties->Get (i);
        Local<Value> value = property_hash->Get (name);

        if (!InitGParameterFromProperty (&parameters[i], klass, name->ToString (), value))
            return false;
    }

    *parameters_p = parameters;
    *n_parameters_p = n_parameters;
    return true;
}

static void ToggleNotify(gpointer user_data, GObject *gobject, gboolean toggle_down);

G_DEFINE_QUARK(gnode_js_object, gnode_js_object);

static void AssociateGObject(Handle<Object> object, GObject *gobject) {
    object->SetPointerInInternalField (0, gobject);

    g_object_ref_sink (gobject);
    g_object_add_toggle_ref (gobject, ToggleNotify, NULL);

    Object *object_p = *object;
    g_object_set_qdata (gobject, gnode_js_object_quark (), object_p);
}

static Handle<Value> GObjectConstructor(const Arguments &args) {
    HandleScope scope;

    /* The flow of this function is a bit twisty.

     * There's two cases for when this code is called:
     * user code doing `new Gtk.Widget({ ... })`, and
     * internal code as part of WrapperFromGObject, where
     * the constructor is called with one external. */

    if (!args.IsConstructCall ()) {
        ThrowException (Exception::TypeError (String::New ("Not a construct call.")));
        return scope.Close (Undefined ());
    }

    Handle<Object> self = args.This ();

    if (args[0]->IsExternal ()) {
        /* The External case. This is how WrapperFromGObject is called. */

        void *data = External::Unwrap (args[0]);
        GObject *gobject = G_OBJECT (data);

        AssociateGObject (self, gobject);
    } else {
        /* User code calling `new Gtk.Widget({ ... })` */

        GObject *gobject;
        GIBaseInfo *info = (GIBaseInfo *) External::Unwrap(args.Data ());
        GType gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *) info);
        void *klass = g_type_class_ref (gtype);

        GParameter *parameters = NULL;
        int n_parameters = 0;

        if (args[0]->IsObject ()) {
            Local<Object> property_hash = args[0]->ToObject ();

            if (!InitGParametersFromProperty (&parameters, &n_parameters, klass, property_hash)) {
                ThrowException (Exception::TypeError (String::New ("Unable to make GParameters.")));
                goto out;
            }
        }

        gobject = (GObject *) g_object_newv (gtype, n_parameters, parameters);
        AssociateGObject (self, gobject);

    out:
        g_free (parameters);
        g_type_class_unref (klass);
    }

    return self;
}

G_DEFINE_QUARK(gnode_js_template, gnode_js_template);

static void ClassDestroyed(Persistent<Value> object, void *data) {
    GIBaseInfo *info = (GIBaseInfo *) data;
    GType gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *) info);
    g_type_set_qdata (gtype, gnode_js_template_quark (), NULL);
    g_base_info_unref (info);
}

static void DefineConstructorMethods(Handle<FunctionTemplate> constructor, GIBaseInfo *info) {
    int n_methods = g_object_info_get_n_methods (info);
    for (int i = 0; i < n_methods; i++) {
        GIFunctionInfo *meth_info = g_object_info_get_method (info, i);
        GIFunctionInfoFlags flags = g_function_info_get_flags (meth_info);

        if (!(flags & GI_FUNCTION_IS_METHOD)) {
            const char *function_name = g_base_info_get_name ((GIBaseInfo *) meth_info);
            Handle<Function> fn = MakeFunction (meth_info);
            constructor->Set (String::NewSymbol (function_name), fn);
        }

        g_base_info_unref ((GIBaseInfo *) meth_info);
    }
}

static void DefinePrototypeMethods(Handle<ObjectTemplate> prototype, GIBaseInfo *info) {
    int n_methods = g_object_info_get_n_methods (info);
    for (int i = 0; i < n_methods; i++) {
        GIFunctionInfo *meth_info = g_object_info_get_method (info, i);
        GIFunctionInfoFlags flags = g_function_info_get_flags (meth_info);

        if (flags & GI_FUNCTION_IS_METHOD) {
            const char *function_name = g_base_info_get_name ((GIBaseInfo *) meth_info);
            Handle<Function> fn = MakeFunction (meth_info);
            prototype->Set (String::NewSymbol (function_name), fn);
        }

        g_base_info_unref ((GIBaseInfo *) meth_info);
    }
}

static Handle<FunctionTemplate> GetBaseClassTemplate() {
    Local<FunctionTemplate> tpl = FunctionTemplate::New ();
    tpl->InstanceTemplate ()->SetInternalFieldCount (1);
    return tpl;
}

static Handle<FunctionTemplate> GetClassTemplateFromGI(GIBaseInfo *info);

static Handle<FunctionTemplate> GetClassTemplate(GIBaseInfo *info, GType gtype) {
    void *data = g_type_get_qdata (gtype, gnode_js_template_quark ());
    if (data) {
        FunctionTemplate *tpl_p = (FunctionTemplate *) data;
        Persistent<FunctionTemplate> tpl(tpl_p);
        return tpl;
    } else {
        Persistent<FunctionTemplate> tpl = Persistent<FunctionTemplate>::New (FunctionTemplate::New (GObjectConstructor, External::Wrap (info)));
        tpl.MakeWeak (g_base_info_ref (info), ClassDestroyed);

        const char *class_name = g_base_info_get_name (info);
        tpl->SetClassName (String::NewSymbol (class_name));

        FunctionTemplate *tpl_p = *tpl;
        g_type_set_qdata (gtype, gnode_js_template_quark (), tpl_p);

        GIObjectInfo *parent_info = g_object_info_get_parent (info);
        if (parent_info) {
            Handle<FunctionTemplate> parent_tpl = GetClassTemplateFromGI ((GIBaseInfo *) parent_info);
            tpl->Inherit (parent_tpl);
        } else {
            tpl->Inherit (GetBaseClassTemplate ());
        }

        DefineConstructorMethods (tpl, info);
        DefinePrototypeMethods (tpl->PrototypeTemplate (), info);

        return tpl;
    }
}

static Handle<FunctionTemplate> GetClassTemplateFromGI(GIBaseInfo *info) {
    GType gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *) info);
    return GetClassTemplate (info, gtype);
}

static Handle<FunctionTemplate> GetClassTemplateFromGType(GType gtype) {
    GIRepository *repo = g_irepository_get_default ();
    GIBaseInfo *info = g_irepository_find_by_gtype (repo, gtype);
    return GetClassTemplate (info, gtype);
}

Handle<Function> MakeClass(GIBaseInfo *info) {
    Handle<FunctionTemplate> tpl = GetClassTemplateFromGI (info);
    return tpl->GetFunction ();
}

static void ObjectDestroyed(Persistent<Value> object, void *data) {
    GObject *gobject = G_OBJECT (data);

    /* We're destroying the wrapper object, so make sure to clear out
     * the qdata that points back to us. */
    g_object_set_qdata (gobject, gnode_js_object_quark (), NULL);

    g_object_unref (gobject);
}

static void ToggleNotify(gpointer user_data, GObject *gobject, gboolean toggle_down) {
    void *data = g_object_get_qdata (gobject, gnode_js_object_quark ());
    assert (data != NULL);
    Object *obj_p = (Object *) data;
    Persistent<Object> obj(obj_p);

    if (toggle_down) {
        /* We're dropping from 2 refs to 1 ref. We are the last holder. Make
         * sure that that our weak ref is installed. */
        obj.MakeWeak (gobject, ObjectDestroyed);
    } else {
        /* We're going from 1 ref to 2 refs. We can't let our wrapper be
         * collected, so make sure that our reference is persistent */
        obj.ClearWeak ();
    }
}

Handle<Value> WrapperFromGObject(GObject *gobject) {
    void *data = g_object_get_qdata (gobject, gnode_js_object_quark ());

    /* Easy case: we already have a wrapper. */
    if (data) {
        Object *obj_p = (Object *) data;
        Persistent<Object> obj(obj_p);
        return obj;
    } else {
        GType gtype = G_OBJECT_TYPE (gobject);

        Handle<FunctionTemplate> tpl = GetClassTemplateFromGType (gtype);
        Handle<Function> constructor = tpl->GetFunction ();

        Handle<Value> gobject_external = External::New (gobject);
        Handle<Value> args[] = { gobject_external };
        Local<Object> obj_local = constructor->NewInstance (1, args);
        Persistent<Object> obj = Persistent<Object>::New (obj_local);
        return obj;
    }
}

GObject * GObjectFromWrapper(Handle<Value> value) {
    Handle<Object> object = value->ToObject ();
    void *data = object->GetPointerFromInternalField (0);
    GObject *gobject = G_OBJECT (data);
    return gobject;
}

};
<|endoftext|>


<commit_before>
fun F : (y1 : integer, y2 : integer, z : [integer], x2 : [integer]) -> ()
  let x : [integer] = []
  let x' : [integer] = [] typed [integer]
  x = y1 :: y2 :: z
  x @ x2 = y2 :: z
  [ ] typed list boolean
  [] typed list list list string
  [1, 2,4, 1+4]

  <>
<commit_msg>added more test cases, and an example of how bracketing of local definitions is a bad idea;<commit_after>
fun F : (y1 : integer, y2 : integer, z : [integer], x2 : [integer]) -> ()
  let x : [integer] = []
  let x_annotated_too : [integer] = [] typed [integer]
  let x_annotated_too' : [integer] = ([] typed [integer])

  # NOTE none of these make it into the symbol table, since they are bracketed
  #      out of the containing function's scope! They are type checked, then discarded.
  (let x' : [integer] = ([] typed [integer])) typed [integer]
  (let x'' : [integer] = []) typed [integer]
  (let x''' = ([] typed [integer])) typed [integer]
  (let x'''' = []) typed [integer]

  x = y1 :: y2 :: z
  x @ x2 = y2 :: z
  [ ] typed list boolean
  [] typed list list list string
  [1, 2,4, 1+4]

  @: print (symbol_table) :@ typed <>

  <>
<|endoftext|>


<commit_before>/*
 * Copyright 2015-2017 Two Pore Guys, Inc.
 * All rights reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted providing that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 *
 */

#include "catch.hpp"

#include <rpc/object.h>
#include "../src/internal.h"

SCENARIO("RPC_OBJECT_CREATE", "Create RPC object and check its internal value") {
        GIVEN("Integer initialized RPC object") {
                rpc_object_t object;
                int value = 10;

                object = rpc_int64_create(value);
                REQUIRE(rpc_get_type(object) == RPC_TYPE_UINT64);
                REQUIRE(rpc_int64_get_value(object) == value);
                REQUIRE(object->ro_refcnt == 1);
                REQUIRE(object->ro_value.rv_i == value);

                WHEN("reference count is incremented") {
                        rpc_retain(object);

                        THEN("reference count equals 2"){
                                REQUIRE(object->ro_refcnt == 2);
                        }

                        AND_WHEN("reference count is decremented") {
                                rpc_release(object);

                                AND_THEN("reference count equals 1") {
                                        REQUIRE(object->ro_refcnt == 1);
                                }
                        }
                }
        }
}
<commit_msg>FIXED: typo in test<commit_after>/*
 * Copyright 2015-2017 Two Pore Guys, Inc.
 * All rights reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted providing that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 *
 */

#include "catch.hpp"

#include <rpc/object.h>
#include "../src/internal.h"

SCENARIO("RPC_OBJECT_CREATE", "Create RPC object and check its internal value") {
        GIVEN("Integer initialized RPC object") {
                rpc_object_t object;
                int value = 10;

                object = rpc_int64_create(value);
                REQUIRE(rpc_get_type(object) == RPC_TYPE_INT64);
                REQUIRE(rpc_int64_get_value(object) == value);
                REQUIRE(object->ro_refcnt == 1);
                REQUIRE(object->ro_value.rv_i == value);

                WHEN("reference count is incremented") {
                        rpc_retain(object);

                        THEN("reference count equals 2"){
                                REQUIRE(object->ro_refcnt == 2);
                        }

                        AND_WHEN("reference count is decremented") {
                                rpc_release(object);

                                AND_THEN("reference count equals 1") {
                                        REQUIRE(object->ro_refcnt == 1);
                                }
                        }
                }
        }
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/tools/test_shell/webwidget_host.h"

#include <cairo/cairo.h>
#include <gtk/gtk.h>

#include "base/logging.h"
#include "base/gfx/platform_canvas_linux.h"
#include "base/gfx/platform_device_linux.h"
#include "base/gfx/bitmap_platform_device_linux.h"
#include "webkit/glue/webinputevent.h"
#include "webkit/glue/webwidget.h"

namespace {

// -----------------------------------------------------------------------------
// Callback functions to proxy to host...

gboolean ConfigureEvent(GtkWidget* widget, GdkEventConfigure* config,
                        WebWidgetHost* host) {
  DLOG(INFO) << "  -- Resize " << config->width << " " << config->height;
  host->Resize(gfx::Size(config->width, config->height));
  return FALSE;
}

gboolean ExposeEvent(GtkWidget* widget, GdkEventExpose* expose,
                     WebWidgetHost* host) {
  gfx::Rect rect(expose->area);
  host->UpdatePaintRect(rect);
  host->Paint();
  return FALSE;
}

gboolean DestroyEvent(GtkWidget* widget, GdkEvent* event,
                      WebWidgetHost* host) {
  host->WindowDestroyed();
  return FALSE;
}

gboolean KeyPressReleaseEvent(GtkWidget* widget, GdkEventKey* event,
                              WebWidgetHost* host) {
  WebKeyboardEvent wke(event);
  host->webwidget()->HandleInputEvent(&wke);

  // The WebKeyboardEvent model, when holding down a key, is:
  //   KEY_DOWN, CHAR, (repeated CHAR as key repeats,) KEY_UP
  // The GDK model for the same sequence is just:
  //   KEY_PRESS, (repeated KEY_PRESS as key repeats,) KEY_RELEASE
  // So we must simulate a CHAR event for every key press.
  if (event->type == GDK_KEY_PRESS) {
    wke.type = WebKeyboardEvent::CHAR;
    host->webwidget()->HandleInputEvent(&wke);
  }

  return FALSE;
}

gboolean FocusIn(GtkWidget* widget, GdkEventFocus* focus,
                 WebWidgetHost* host) {
  host->webwidget()->SetFocus(true);
  return FALSE;
}

gboolean FocusOut(GtkWidget* widget, GdkEventFocus* focus,
                  WebWidgetHost* host) {
  host->webwidget()->SetFocus(false);
  return FALSE;
}

gboolean ButtonPressReleaseEvent(GtkWidget* widget, GdkEventButton* event,
                                 WebWidgetHost* host) {
  WebMouseEvent wme(event);
  host->webwidget()->HandleInputEvent(&wme);
  return FALSE;
}

gboolean MouseMoveEvent(GtkWidget* widget, GdkEventMotion* event,
                        WebWidgetHost* host) {
  WebMouseEvent wme(event);
  host->webwidget()->HandleInputEvent(&wme);
  return FALSE;
}

gboolean MouseScrollEvent(GtkWidget* widget, GdkEventScroll* event,
                          WebWidgetHost* host) {
  WebMouseWheelEvent wmwe(event);
  host->webwidget()->HandleInputEvent(&wmwe);
  return FALSE;
}

}  // anonymous namespace

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

gfx::WindowHandle WebWidgetHost::CreateWindow(gfx::WindowHandle box,
                                              void* host) {
  GtkWidget* widget = gtk_drawing_area_new();
  gtk_box_pack_start(GTK_BOX(box), widget, TRUE, TRUE, 0);

  gtk_widget_add_events(widget, GDK_EXPOSURE_MASK |
                                GDK_POINTER_MOTION_MASK |
                                GDK_BUTTON_PRESS_MASK |
                                GDK_BUTTON_RELEASE_MASK |
                                GDK_KEY_PRESS_MASK |
                                GDK_KEY_RELEASE_MASK);
  GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
  g_signal_connect(widget, "configure-event", G_CALLBACK(ConfigureEvent), host);
  g_signal_connect(widget, "expose-event", G_CALLBACK(ExposeEvent), host);
  g_signal_connect(widget, "destroy-event", G_CALLBACK(DestroyEvent), host);
  g_signal_connect(widget, "key-press-event", G_CALLBACK(KeyPressReleaseEvent),
                   host);
  g_signal_connect(widget, "key-release-event",
                   G_CALLBACK(KeyPressReleaseEvent), host);
  g_signal_connect(widget, "focus-in-event", G_CALLBACK(FocusIn), host);
  g_signal_connect(widget, "focus-out-event", G_CALLBACK(FocusOut), host);
  g_signal_connect(widget, "button-press-event",
                   G_CALLBACK(ButtonPressReleaseEvent), host);
  g_signal_connect(widget, "button-release-event",
                   G_CALLBACK(ButtonPressReleaseEvent), host);
  g_signal_connect(widget, "motion-notify-event", G_CALLBACK(MouseMoveEvent),
                   host);
  g_signal_connect(widget, "scroll-event", G_CALLBACK(MouseScrollEvent),
                   host);

  return widget;
}

WebWidgetHost* WebWidgetHost::Create(gfx::WindowHandle box,
                                     WebWidgetDelegate* delegate) {
  WebWidgetHost* host = new WebWidgetHost();
  host->view_ = CreateWindow(box, host);
  host->webwidget_ = WebWidget::Create(delegate);

  return host;
}

void WebWidgetHost::UpdatePaintRect(const gfx::Rect& rect) {
  paint_rect_ = paint_rect_.Union(rect);
}

void WebWidgetHost::DidInvalidateRect(const gfx::Rect& damaged_rect) {
  DLOG_IF(WARNING, painting_) << "unexpected invalidation while painting";

  UpdatePaintRect(damaged_rect);

  gtk_widget_queue_draw_area(GTK_WIDGET(view_), damaged_rect.x(),
      damaged_rect.y(), damaged_rect.width(), damaged_rect.height());
}

void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
  // This is used for optimizing painting when the renderer is scrolled. We're
  // currently not doing any optimizations so just invalidate the region.
  DidInvalidateRect(clip_rect);
}

WebWidgetHost* FromWindow(gfx::WindowHandle view) {
  const gpointer p = g_object_get_data(G_OBJECT(view), "webwidgethost");
  return (WebWidgetHost* ) p;
}

WebWidgetHost::WebWidgetHost()
    : view_(NULL),
      webwidget_(NULL),
      scroll_dx_(0),
      scroll_dy_(0),
      track_mouse_leave_(false) {
  set_painting(false);
}

WebWidgetHost::~WebWidgetHost() {
  webwidget_->Close();
  webwidget_->Release();
}

void WebWidgetHost::Resize(const gfx::Size &newsize) {
  // The pixel buffer backing us is now the wrong size
  canvas_.reset();

  gtk_widget_set_size_request(GTK_WIDGET(view_), newsize.width(), newsize.height());
  webwidget_->Resize(gfx::Size(newsize.width(), newsize.height()));
}

void WebWidgetHost::Paint() {
  gint width, height;
  gtk_widget_get_size_request(GTK_WIDGET(view_), &width, &height);
  gfx::Rect client_rect(width, height);

  // Allocate a canvas if necessary
  if (!canvas_.get()) {
    ResetScrollRect();
    paint_rect_ = client_rect;
    canvas_.reset(new gfx::PlatformCanvas(width, height, true));
    if (!canvas_.get()) {
      // memory allocation failed, we can't paint.
      LOG(ERROR) << "Failed to allocate memory for " << width << "x" << height;
      return;
    }
  }

  // This may result in more invalidation
  webwidget_->Layout();

  // Paint the canvas if necessary.  Allow painting to generate extra rects the
  // first time we call it.  This is necessary because some WebCore rendering
  // objects update their layout only when painted.
  for (int i = 0; i < 2; ++i) {
    paint_rect_ = client_rect.Intersect(paint_rect_);
    if (!paint_rect_.IsEmpty()) {
      gfx::Rect rect(paint_rect_);
      paint_rect_ = gfx::Rect();

      DLOG_IF(WARNING, i == 1) << "painting caused additional invalidations";
      PaintRect(rect);
    }
  }
  DCHECK(paint_rect_.IsEmpty());

  // BitBlit to the X server
  gfx::PlatformDeviceLinux &platdev = canvas_->getTopPlatformDevice();
  gfx::BitmapPlatformDeviceLinux* const bitdev =
    static_cast<gfx::BitmapPlatformDeviceLinux* >(&platdev);

  cairo_t* cairo_drawable = gdk_cairo_create(view_->window);
  cairo_set_source_surface(cairo_drawable, bitdev->surface(), 0, 0);
  cairo_paint(cairo_drawable);
  cairo_destroy(cairo_drawable);
}

void WebWidgetHost::ResetScrollRect() {
  // This method is only needed for optimized scroll painting, which we don't
  // care about in the test shell, yet.
}

void WebWidgetHost::PaintRect(const gfx::Rect& rect) {
  set_painting(true);
  webwidget_->Paint(canvas_.get(), rect);
  set_painting(false);
}

// -----------------------------------------------------------------------------
// This is called when the GTK window is destroyed. In the Windows code this
// deletes this object. Since it's only test_shell it probably doesn't matter
// that much.
// -----------------------------------------------------------------------------
void WebWidgetHost::WindowDestroyed() {
  delete this;
}
<commit_msg>Fix test_shell resizing.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/tools/test_shell/webwidget_host.h"

#include <cairo/cairo.h>
#include <gtk/gtk.h>

#include "base/logging.h"
#include "base/gfx/platform_canvas_linux.h"
#include "base/gfx/platform_device_linux.h"
#include "base/gfx/bitmap_platform_device_linux.h"
#include "webkit/glue/webinputevent.h"
#include "webkit/glue/webwidget.h"

namespace {

// -----------------------------------------------------------------------------
// Callback functions to proxy to host...

gboolean ConfigureEvent(GtkWidget* widget, GdkEventConfigure* config,
                        WebWidgetHost* host) {
  host->Resize(gfx::Size(config->width, config->height));
  return FALSE;
}

gboolean ExposeEvent(GtkWidget* widget, GdkEventExpose* expose,
                     WebWidgetHost* host) {
  gfx::Rect rect(expose->area);
  host->UpdatePaintRect(rect);
  host->Paint();
  return FALSE;
}

gboolean DestroyEvent(GtkWidget* widget, GdkEvent* event,
                      WebWidgetHost* host) {
  host->WindowDestroyed();
  return FALSE;
}

gboolean KeyPressReleaseEvent(GtkWidget* widget, GdkEventKey* event,
                              WebWidgetHost* host) {
  WebKeyboardEvent wke(event);
  host->webwidget()->HandleInputEvent(&wke);

  // The WebKeyboardEvent model, when holding down a key, is:
  //   KEY_DOWN, CHAR, (repeated CHAR as key repeats,) KEY_UP
  // The GDK model for the same sequence is just:
  //   KEY_PRESS, (repeated KEY_PRESS as key repeats,) KEY_RELEASE
  // So we must simulate a CHAR event for every key press.
  if (event->type == GDK_KEY_PRESS) {
    wke.type = WebKeyboardEvent::CHAR;
    host->webwidget()->HandleInputEvent(&wke);
  }

  return FALSE;
}

gboolean FocusIn(GtkWidget* widget, GdkEventFocus* focus,
                 WebWidgetHost* host) {
  host->webwidget()->SetFocus(true);
  return FALSE;
}

gboolean FocusOut(GtkWidget* widget, GdkEventFocus* focus,
                  WebWidgetHost* host) {
  host->webwidget()->SetFocus(false);
  return FALSE;
}

gboolean ButtonPressReleaseEvent(GtkWidget* widget, GdkEventButton* event,
                                 WebWidgetHost* host) {
  WebMouseEvent wme(event);
  host->webwidget()->HandleInputEvent(&wme);
  return FALSE;
}

gboolean MouseMoveEvent(GtkWidget* widget, GdkEventMotion* event,
                        WebWidgetHost* host) {
  WebMouseEvent wme(event);
  host->webwidget()->HandleInputEvent(&wme);
  return FALSE;
}

gboolean MouseScrollEvent(GtkWidget* widget, GdkEventScroll* event,
                          WebWidgetHost* host) {
  WebMouseWheelEvent wmwe(event);
  host->webwidget()->HandleInputEvent(&wmwe);
  return FALSE;
}

}  // anonymous namespace

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

gfx::WindowHandle WebWidgetHost::CreateWindow(gfx::WindowHandle box,
                                              void* host) {
  GtkWidget* widget = gtk_drawing_area_new();
  gtk_box_pack_start(GTK_BOX(box), widget, TRUE, TRUE, 0);

  gtk_widget_add_events(widget, GDK_EXPOSURE_MASK |
                                GDK_POINTER_MOTION_MASK |
                                GDK_BUTTON_PRESS_MASK |
                                GDK_BUTTON_RELEASE_MASK |
                                GDK_KEY_PRESS_MASK |
                                GDK_KEY_RELEASE_MASK);
  GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
  g_signal_connect(widget, "configure-event", G_CALLBACK(ConfigureEvent), host);
  g_signal_connect(widget, "expose-event", G_CALLBACK(ExposeEvent), host);
  g_signal_connect(widget, "destroy-event", G_CALLBACK(DestroyEvent), host);
  g_signal_connect(widget, "key-press-event", G_CALLBACK(KeyPressReleaseEvent),
                   host);
  g_signal_connect(widget, "key-release-event",
                   G_CALLBACK(KeyPressReleaseEvent), host);
  g_signal_connect(widget, "focus-in-event", G_CALLBACK(FocusIn), host);
  g_signal_connect(widget, "focus-out-event", G_CALLBACK(FocusOut), host);
  g_signal_connect(widget, "button-press-event",
                   G_CALLBACK(ButtonPressReleaseEvent), host);
  g_signal_connect(widget, "button-release-event",
                   G_CALLBACK(ButtonPressReleaseEvent), host);
  g_signal_connect(widget, "motion-notify-event", G_CALLBACK(MouseMoveEvent),
                   host);
  g_signal_connect(widget, "scroll-event", G_CALLBACK(MouseScrollEvent),
                   host);

  return widget;
}

WebWidgetHost* WebWidgetHost::Create(gfx::WindowHandle box,
                                     WebWidgetDelegate* delegate) {
  WebWidgetHost* host = new WebWidgetHost();
  host->view_ = CreateWindow(box, host);
  host->webwidget_ = WebWidget::Create(delegate);

  return host;
}

void WebWidgetHost::UpdatePaintRect(const gfx::Rect& rect) {
  paint_rect_ = paint_rect_.Union(rect);
}

void WebWidgetHost::DidInvalidateRect(const gfx::Rect& damaged_rect) {
  DLOG_IF(WARNING, painting_) << "unexpected invalidation while painting";

  UpdatePaintRect(damaged_rect);

  gtk_widget_queue_draw_area(GTK_WIDGET(view_), damaged_rect.x(),
      damaged_rect.y(), damaged_rect.width(), damaged_rect.height());
}

void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
  // This is used for optimizing painting when the renderer is scrolled. We're
  // currently not doing any optimizations so just invalidate the region.
  DidInvalidateRect(clip_rect);
}

WebWidgetHost* FromWindow(gfx::WindowHandle view) {
  const gpointer p = g_object_get_data(G_OBJECT(view), "webwidgethost");
  return (WebWidgetHost* ) p;
}

WebWidgetHost::WebWidgetHost()
    : view_(NULL),
      webwidget_(NULL),
      scroll_dx_(0),
      scroll_dy_(0),
      track_mouse_leave_(false) {
  set_painting(false);
}

WebWidgetHost::~WebWidgetHost() {
  webwidget_->Close();
  webwidget_->Release();
}

void WebWidgetHost::Resize(const gfx::Size &newsize) {
  // The pixel buffer backing us is now the wrong size
  canvas_.reset();

  webwidget_->Resize(gfx::Size(newsize.width(), newsize.height()));
}

void WebWidgetHost::Paint() {
  int width = view_->allocation.width;
  int height = view_->allocation.height;
  gfx::Rect client_rect(width, height);

  // Allocate a canvas if necessary
  if (!canvas_.get()) {
    ResetScrollRect();
    paint_rect_ = client_rect;
    canvas_.reset(new gfx::PlatformCanvas(width, height, true));
    if (!canvas_.get()) {
      // memory allocation failed, we can't paint.
      LOG(ERROR) << "Failed to allocate memory for " << width << "x" << height;
      return;
    }
  }

  // This may result in more invalidation
  webwidget_->Layout();

  // Paint the canvas if necessary.  Allow painting to generate extra rects the
  // first time we call it.  This is necessary because some WebCore rendering
  // objects update their layout only when painted.
  for (int i = 0; i < 2; ++i) {
    paint_rect_ = client_rect.Intersect(paint_rect_);
    if (!paint_rect_.IsEmpty()) {
      gfx::Rect rect(paint_rect_);
      paint_rect_ = gfx::Rect();

      DLOG_IF(WARNING, i == 1) << "painting caused additional invalidations";
      PaintRect(rect);
    }
  }
  DCHECK(paint_rect_.IsEmpty());

  // BitBlit to the X server
  gfx::PlatformDeviceLinux &platdev = canvas_->getTopPlatformDevice();
  gfx::BitmapPlatformDeviceLinux* const bitdev =
    static_cast<gfx::BitmapPlatformDeviceLinux* >(&platdev);

  cairo_t* cairo_drawable = gdk_cairo_create(view_->window);
  cairo_set_source_surface(cairo_drawable, bitdev->surface(), 0, 0);
  cairo_paint(cairo_drawable);
  cairo_destroy(cairo_drawable);
}

void WebWidgetHost::ResetScrollRect() {
  // This method is only needed for optimized scroll painting, which we don't
  // care about in the test shell, yet.
}

void WebWidgetHost::PaintRect(const gfx::Rect& rect) {
  set_painting(true);
  webwidget_->Paint(canvas_.get(), rect);
  set_painting(false);
}

// -----------------------------------------------------------------------------
// This is called when the GTK window is destroyed. In the Windows code this
// deletes this object. Since it's only test_shell it probably doesn't matter
// that much.
// -----------------------------------------------------------------------------
void WebWidgetHost::WindowDestroyed() {
  delete this;
}
<|endoftext|>