<commit_before>// ConsoleApplication1.cpp : R\[ AvP[ṼGg |Cg`܂B
//

#include "stdafx.h"
#include <GL/glut.h>
#include <math.h>

#define CELLS_NO 51 //Z̑S̐
#define CELL_NEIGHBOR_NO 1 //Z̋ߖT
#define RULE_NO 30 //K
#define TIME_LIM 50 //
#define STATE_NO 2 //Ԑ
#define VIEW_SIZE 2.0 //ʂ̕

class Rule {
public:
	int ruleNo;
	int rulePatterns;
	Rule(int _ruleNo, int stateNo, int neighborNo) {
		ruleNo = _ruleNo;
		rulePatterns = (int)pow((double)STATE_NO, (double)2 * CELL_NEIGHBOR_NO + 1);
	}
	int getNextState(int decimalState) {
		int nextState = 0;
		int leftDecimal = ruleNo;
		for (int i = 0; i <= decimalState; i++)
		{
			nextState = leftDecimal % STATE_NO;
			leftDecimal /= STATE_NO;
		}
		return nextState;
	}
};

Rule thisRule = Rule(RULE_NO, STATE_NO, CELL_NEIGHBOR_NO);

//render square
void drawSquare(double x, double y, double width, double height)
{
	glBegin(GL_POLYGON);
	glVertex2d(x, y);
	glVertex2d(x + width, y);
	glVertex2d(x + width, y + height);
	glVertex2d(x, y + height);
	glEnd();
}
//render single cell
void drawCell(double x, double y, int state)
{
	double width = VIEW_SIZE / CELLS_NO;
	glColor3d((STATE_NO - 1 - state) / double(STATE_NO - 1), (STATE_NO - 1 - state) / double(STATE_NO - 1), (STATE_NO - 1 - state) / double(STATE_NO - 1));
	drawSquare(x, y, width, width);
}
//render cells row
void drawCellsRow(int cells[CELLS_NO], int time)
{
	double width = VIEW_SIZE / CELLS_NO;
	double x = -VIEW_SIZE / 2.0;
	double y = (TIME_LIM / 2.0 - time) * width;
	for (int i = 0; i < CELLS_NO; i++) {
		drawCell(x, y, cells[i]);
		x += width;
	}
}
//cell update by Rule
int updateCell(int neighborCells[CELL_NEIGHBOR_NO * 2 + 1])
{
	int decimalState = 0;
	int cellMaxNo = CELL_NEIGHBOR_NO * 2 + 1;
	for (int i = 0; i < cellMaxNo; i++)
	{
		decimalState += int(pow(double(STATE_NO), double(i))) * neighborCells[cellMaxNo - i - 1];
	}
	int n = thisRule.getNextState(decimalState);
	return n;
}

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	int cells[CELLS_NO] = { 0 }; //current cells state
	int tmpCells[CELLS_NO] = { 0 }; //temporary cells array
	cells[int(CELLS_NO / 2.0)] = 1;
	for (int i = 0; i < TIME_LIM; i++) {
		drawCellsRow(cells, i);
		for (int j = 0; j < CELLS_NO; j++)
		{
			int neighborCells[CELL_NEIGHBOR_NO * 2 + 1] = { 0 };
			for (int l = 0; l < CELL_NEIGHBOR_NO * 2 + 1; l++)
			{
				int n = (j + l - CELL_NEIGHBOR_NO) % CELLS_NO;
				if (n < 0)
				{
					n += CELLS_NO;
				}
				neighborCells[l] = cells[n];
			}
			tmpCells[j] = updateCell(neighborCells);
		}
		for (int k = 0; k < CELLS_NO; k++)
		{
			cells[k] = tmpCells[k];
		}
	}
	glFlush();
}

void init(void)
{
	glClearColor(0.0, 0.0, 1.0, 1.0);
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA);
	glutCreateWindow(argv[0]);
	glutDisplayFunc(display);
	init();
	glutMainLoop();
	return 0;
}<commit_msg>resharp2<commit_after>// ConsoleApplication1.cpp : R\[ AvP[ṼGg |Cg`܂B
//

#include "stdafx.h"
#include <GL/glut.h>
#include <math.h>

#define CELLS_NO 51 //Z̑S̐
#define CELL_NEIGHBOR_NO 1 //Z̋ߖT
#define RULE_NO 30 //K
#define TIME_LIM 50 //
#define STATE_NO 2 //Ԑ
#define VIEW_SIZE 2.0 //ʂ̕

class Rule {
public:
	int ruleNo;
	int rulePatterns;
	Rule(int _ruleNo, int stateNo, int neighborNo) {
		ruleNo = _ruleNo;
		rulePatterns = int(pow(double(STATE_NO), double(2) * CELL_NEIGHBOR_NO + 1));
	}
	int getNextState(int decimalState) {
		int nextState = 0;
		int leftDecimal = ruleNo;
		for (int i = 0; i <= decimalState; i++)
		{
			nextState = leftDecimal % STATE_NO;
			leftDecimal /= STATE_NO;
		}
		return nextState;
	}
};

Rule thisRule = Rule(RULE_NO, STATE_NO, CELL_NEIGHBOR_NO);

//render square
void drawSquare(double x, double y, double width, double height)
{
	glBegin(GL_POLYGON);
	glVertex2d(x, y);
	glVertex2d(x + width, y);
	glVertex2d(x + width, y + height);
	glVertex2d(x, y + height);
	glEnd();
}
//render single cell
void drawCell(double x, double y, int state)
{
	double width = VIEW_SIZE / CELLS_NO;
	glColor3d((STATE_NO - 1 - state) / double(STATE_NO - 1), (STATE_NO - 1 - state) / double(STATE_NO - 1), (STATE_NO - 1 - state) / double(STATE_NO - 1));
	drawSquare(x, y, width, width);
}
//render cells row
void drawCellsRow(int cells[CELLS_NO], int time)
{
	double width = VIEW_SIZE / CELLS_NO;
	double x = -VIEW_SIZE / 2.0;
	double y = (TIME_LIM / 2.0 - time) * width;
	for (int i = 0; i < CELLS_NO; i++) {
		drawCell(x, y, cells[i]);
		x += width;
	}
}
//cell update by Rule
int updateCell(int neighborCells[CELL_NEIGHBOR_NO * 2 + 1])
{
	int decimalState = 0;
	int cellMaxNo = CELL_NEIGHBOR_NO * 2 + 1;
	for (int i = 0; i < cellMaxNo; i++)
	{
		decimalState += int(pow(double(STATE_NO), double(i))) * neighborCells[cellMaxNo - i - 1];
	}
	int n = thisRule.getNextState(decimalState);
	return n;
}

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	int cells[CELLS_NO] = { 0 }; //current cells state
	int tmpCells[CELLS_NO] = { 0 }; //temporary cells array
	cells[int(CELLS_NO / 2.0)] = 1;
	for (int i = 0; i < TIME_LIM; i++) {
		drawCellsRow(cells, i);
		for (int j = 0; j < CELLS_NO; j++)
		{
			int neighborCells[CELL_NEIGHBOR_NO * 2 + 1] = { 0 };
			for (int l = 0; l < CELL_NEIGHBOR_NO * 2 + 1; l++)
			{
				int n = (j + l - CELL_NEIGHBOR_NO) % CELLS_NO;
				if (n < 0)
				{
					n += CELLS_NO;
				}
				neighborCells[l] = cells[n];
			}
			tmpCells[j] = updateCell(neighborCells);
		}
		for (int k = 0; k < CELLS_NO; k++)
		{
			cells[k] = tmpCells[k];
		}
	}
	glFlush();
}

void init(void)
{
	glClearColor(0.0, 0.0, 1.0, 1.0);
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA);
	glutCreateWindow(argv[0]);
	glutDisplayFunc(display);
	init();
	glutMainLoop();
	return 0;
}<|endoftext|>


<commit_before>#include "main.hpp"

#include "ReduceParticleCountEffect.hpp"

constexpr const char *ReduceParticleCountEffect::Name;

const char *ReduceParticleCountEffect::getName() const { return Name; }
const char *ReduceParticleCountEffect::getDescriptiveName() const {
  return "Reduce particle count";
}
const char *ReduceParticleCountEffect::getDescription() const {
  return "Reduces the amount of visible particles";
}

static auto EaseFunctionStrings = {
  "sine",
  "linear",
  "none",
};

void ReduceParticleCountEffect::loadConfig(const json &json) {
  amount = json.value("amount", 2u);
  easeInTime = json.value("easeInTime", 1000.f);
  easeOutTime = json.value("easeOutTime", 1000.f);
  easeFunc = jsonEnumValue(json, "easeFunc", EaseFunction::Sine, EaseFunctionStrings);
}
void ReduceParticleCountEffect::saveConfig(json &json) const {
  json.emplace("amount", amount);
  json.emplace("easeInTime", easeInTime);
  json.emplace("easeOutTime", easeOutTime);
  jsonEnumEmplace(json, "easeFunc", easeFunc, EaseFunctionStrings);
}

void ReduceParticleCountEffect::randomizeConfig(std::default_random_engine &random) {
}

void ReduceParticleCountEffect::registerEffect(EffectRegistrationData &data) const {
  data.vertexShader.appendMainBody(
      TEMPLATE(R"glsl(
  {
    float ease = 0.;
    switch(${easeFunc}) {
      case 0: // none
      ease = 1.f;
      break;
      case 1: // sine
      ease = (1. - cos(PI * min(${easeInProgress}, ${easeOutProgress}))) / 2.;
      break;
      case 2: // linear
      ease = min(${easeInProgress}, ${easeOutProgress});
      break;
    }

    if((gl_VertexID - pixelPosition.y * 8) % ${amount} != 0) {
      visibility *= 1. - ease;
    }
  }
  )glsl")
          .compile({
            UNIFORM(data.uniforms, "amount", GLSLType::Int,
                      [this](const RenderProps &props) {
                        return UniformValue(static_cast<int>(amount));
                      }),
            UNIFORM(data.uniforms, "easeInProgress", GLSLType::Float,
                      [this](const RenderProps &props) {
                        const auto time = glm::fract((props.state.clock.getTime() - timeBegin) / getPeriod());
                        const auto easeInTime = glm::min(this->easeInTime, getPeriod() / 2.f);
                        return UniformValue(glm::min(1.f, time / (easeInTime / getPeriod())));
                      }),
            UNIFORM(data.uniforms, "easeOutProgress", GLSLType::Float,
                      [this](const RenderProps &props) {
                        const auto time = glm::fract((props.state.clock.getTime() - timeBegin) / getPeriod());
                        const auto easeInTime = glm::min(this->easeInTime, getPeriod() / 2.f);
                        const auto easeOutTime = glm::min(this->easeOutTime, getPeriod() - easeInTime);
                        return UniformValue(glm::min(1.f, (1.f - time) / (easeOutTime / getPeriod())));
                      }),
            UNIFORM(data.uniforms, "easeFunc", GLSLType::Int,
                      [this](const RenderProps &props) {
                        return UniformValue(static_cast<int>(easeFunc));
                      }),
          })
          .c_str());
}

void ReduceParticleCountEffect::registerEffectSound(EffectSoundRegistrationData &data) const {
}
<commit_msg>Improve ReduceParticleCount transition<commit_after>#include "main.hpp"

#include "ReduceParticleCountEffect.hpp"

constexpr const char *ReduceParticleCountEffect::Name;

const char *ReduceParticleCountEffect::getName() const { return Name; }
const char *ReduceParticleCountEffect::getDescriptiveName() const {
  return "Reduce particle count";
}
const char *ReduceParticleCountEffect::getDescription() const {
  return "Reduces the amount of visible particles";
}

static auto EaseFunctionStrings = {
  "sine",
  "linear",
  "none",
};

void ReduceParticleCountEffect::loadConfig(const json &json) {
  amount = json.value("amount", 2u);
  easeInTime = json.value("easeInTime", 1000.f);
  easeOutTime = json.value("easeOutTime", 1000.f);
  easeFunc = jsonEnumValue(json, "easeFunc", EaseFunction::Sine, EaseFunctionStrings);
}
void ReduceParticleCountEffect::saveConfig(json &json) const {
  json.emplace("amount", amount);
  json.emplace("easeInTime", easeInTime);
  json.emplace("easeOutTime", easeOutTime);
  jsonEnumEmplace(json, "easeFunc", easeFunc, EaseFunctionStrings);
}

void ReduceParticleCountEffect::randomizeConfig(std::default_random_engine &random) {
}

void ReduceParticleCountEffect::registerEffect(EffectRegistrationData &data) const {
  data.vertexShader.appendMainBody(
      TEMPLATE(R"glsl(
  {
    float ease = 0.;
    switch(${easeFunc}) {
      case 0: // none
      ease = 1.f;
      break;
      case 1: // sine
      ease = (1. - cos(PI * min(${easeInProgress}, ${easeOutProgress}))) / 2.;
      break;
      case 2: // linear
      ease = min(${easeInProgress}, ${easeOutProgress});
      break;
    }

    if((gl_VertexID - pixelPosition.y * 8) % ${amount} != 0) {
      visibility *= 1. - ease;
      pointSize *= 1. - ease;
    }
  }
  )glsl")
          .compile({
            UNIFORM(data.uniforms, "amount", GLSLType::Int,
                      [this](const RenderProps &props) {
                        return UniformValue(static_cast<int>(amount));
                      }),
            UNIFORM(data.uniforms, "easeInProgress", GLSLType::Float,
                      [this](const RenderProps &props) {
                        const auto time = glm::fract((props.state.clock.getTime() - timeBegin) / getPeriod());
                        const auto easeInTime = glm::min(this->easeInTime, getPeriod() / 2.f);
                        return UniformValue(glm::min(1.f, time / (easeInTime / getPeriod())));
                      }),
            UNIFORM(data.uniforms, "easeOutProgress", GLSLType::Float,
                      [this](const RenderProps &props) {
                        const auto time = glm::fract((props.state.clock.getTime() - timeBegin) / getPeriod());
                        const auto easeInTime = glm::min(this->easeInTime, getPeriod() / 2.f);
                        const auto easeOutTime = glm::min(this->easeOutTime, getPeriod() - easeInTime);
                        return UniformValue(glm::min(1.f, (1.f - time) / (easeOutTime / getPeriod())));
                      }),
            UNIFORM(data.uniforms, "easeFunc", GLSLType::Int,
                      [this](const RenderProps &props) {
                        return UniformValue(static_cast<int>(easeFunc));
                      }),
          })
          .c_str());
}

void ReduceParticleCountEffect::registerEffectSound(EffectSoundRegistrationData &data) const {
}
<|endoftext|>


<commit_before>/* notepad-conduit.cc			KPilot
**
** Copyright (C) 2004 by Adriaan de Groot, Joern Ahrens
**
** The code for NotepadActionThread::unpackNotePad was taken from
** Angus Ainslies read-notepad.c, which is part of pilot-link.
** NotepadActionThread::saveImage is also based on read-notepad.c.
**
** This file is part of the Notepad conduit, a conduit for KPilot that
** stores the notepad drawings to files.
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
** MA 02111-1307, USA.
*/

/*
** Bug reports and questions can be sent to kde-pim@kde.org
*/

#ifdef DEBUG
#undef DEBUG
#define DEBUG (1)
#else
#define DEBUG (1)
#endif

#define DEBUG (1)

#include "options.h"
#include "pilotUser.h"
#include "pilotSerialDatabase.h"

#include "notepad-conduit.h"  // The Conduit action
#include "notepadconduit.h"   // The settings class

#include <pi-notepad.h>

#include <qthread.h>
#include <qapplication.h>
#include <qvaluelist.h>
#include <qimage.h>
#include <qdir.h>

extern "C"
{
long version_conduit_notepad = KPILOT_PLUGIN_API;
const char *id_conduit_notepad =
	"$Id$";
}

NotepadConduit::NotepadConduit(KPilotDeviceLink *d,	const char *n,
	const QStringList &args) :	ConduitAction(d, n, args)
{
	FUNCTIONSETUP;
#ifdef DEBUG
	DEBUGCONDUIT << id_conduit_notepad << endl;
#endif
	fConduitName=i18n("Notepad");
	thread = 0L;

	(void) id_conduit_notepad;
}

NotepadConduit::~NotepadConduit()
{
	FUNCTIONSETUP;
}

/* virtual */ bool NotepadConduit::exec()
{
	FUNCTIONSETUP;

#ifdef DEBUG
	DEBUGCONDUIT << fname << ": In exec() @" << (unsigned long) this << endl;
#endif

	QDir dir(NotepadConduitSettings::outputDirectory());
	if(!dir.exists() && !dir.mkdir(dir.path())) {
		emit logError(i18n("Unable to open %1").arg(dir.path()));
		delayDone();
		return false;
	}
	else {
		thread = new NotepadActionThread(this, pilotSocket());
		thread->start();
		// tickle is disabled due to crashs during sync
		// -> PADP TX "unexpected package"
//		startTickle();
	}

	return true;
}

bool NotepadConduit::event(QEvent *e)
{
	FUNCTIONSETUP;

	if(e->type() == QEvent::User) {
#ifdef DEBUG
		DEBUGCONDUIT << fname << ": Notepad thread done." << endl;
#endif
//		stopTickle();
		delayDone();
		if(thread->getFailed())
			logError(i18n("%1 notepads could not be saved").arg(thread->getFailed()));
		logMessage(i18n("%1 notepads saved").arg(thread->getSaved()));
		delete thread;
		return true;
	}
	else
		return ConduitAction::event(e);
}

//-----------------------------------------------------------------------------
// NotepadActionThread
//-----------------------------------------------------------------------------

NotepadActionThread::NotepadActionThread(QObject *parent, int pilotSocket) :
	fParent(parent), fPilotSocket(pilotSocket), notSaved(0), saved(0)
{
	FUNCTIONSETUP;
}

/*virtual*/ void NotepadActionThread::run()
{
	FUNCTIONSETUP;

	PilotSerialDatabase *db = new PilotSerialDatabase(fPilotSocket, "npadDB");

	int n = db->recordCount();
	QValueList<recordid_t> vl = db->idList();
	QValueList<recordid_t>::iterator it;
	struct NotePad a;
	for(it = vl.begin(); it != vl.end(); it++) {
		PilotRecord *pr = db->readRecordById(*it);
		if(pr) {
			unpack_NotePad(&a, (unsigned char*)pr->getData(), pr->getLen());
			saveImage(&a);
		}
	}
	QApplication::postEvent(fParent, new QEvent(QEvent::User));
}

int NotepadActionThread::unpackNotePad(struct NotePad *a, unsigned char *buffer, int len)
{
	FUNCTIONSETUP;

	unsigned char *start = buffer;

	a->createDate.sec = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->createDate.min = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->createDate.hour = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->createDate.day = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->createDate.month = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->createDate.year = (unsigned short int) get_short(buffer);
	buffer += 2;

	a->createDate.s = (unsigned short int) get_short(buffer);
	buffer += 2;

	a->changeDate.sec = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->changeDate.min = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->changeDate.hour = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->changeDate.day = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->changeDate.month = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->changeDate.year = (unsigned short int) get_short(buffer);
	buffer += 2;

	a->changeDate.s = (unsigned short int) get_short(buffer);
	buffer += 2;

	a->flags = (unsigned short int) get_short(buffer);
	buffer += 2;

	if( a->flags & NOTEPAD_FLAG_ALARM ) {
			a->alarmDate.sec = (unsigned short int) get_short(buffer);
			buffer += 2;
			a->alarmDate.min = (unsigned short int) get_short(buffer);
			buffer += 2;
			a->alarmDate.hour = (unsigned short int) get_short(buffer);
			buffer += 2;
			a->alarmDate.day = (unsigned short int) get_short(buffer);
			buffer += 2;
			a->alarmDate.month = (unsigned short int) get_short(buffer);
			buffer += 2;
			a->alarmDate.year = (unsigned short int) get_short(buffer);
			buffer += 2;

			a->alarmDate.s = (unsigned short int) get_short(buffer);
			buffer += 2;
		}

		if( a->flags & NOTEPAD_FLAG_NAME ) {
			a->name = strdup((char *) buffer);

			buffer += strlen( a->name ) + 1;

			if( (strlen( a->name ) + 1)%2 == 1)
				buffer++;

		}
		else {
			a->name = NULL;
		}

	if( a->flags & NOTEPAD_FLAG_BODY ) {
			a->body.bodyLen = get_long( buffer );
			buffer += 4;

			a->body.width = get_long( buffer );
			buffer += 4;

			a->body.height = get_long( buffer );
			buffer += 4;

			a->body.l1 = get_long( buffer );
			buffer += 4;

			a->body.dataType = get_long( buffer );
			buffer += 4;

			a->body.dataLen = get_long( buffer );
			buffer += 4;

			a->data = (dataRec_t*)malloc( a->body.dataLen );

			if( a->data == NULL )
				return( 0 );

			memcpy( a->data, buffer, a->body.dataLen );
		}

	return ( buffer - start );	/* FIXME: return real length */
}

void NotepadActionThread::saveImage(struct NotePad *n)
{
	FUNCTIONSETUP;

	int i,j,k,datapoints = 0;
	QImage image(n->body.width+8, n->body.height, 8, 2);

	image.setColor(0, qRgb(0xaa, 0xc1 ,0x91) );
	image.setColor(1, qRgb(0x30, 0x36, 0x29) );

	int x = 0;
	int y = 0;
	int pos = 0;
	for(i=0; i<n->body.dataLen/2; i++)
	{
		datapoints += n->data[i].repeat;
		for(j=0; j<n->data[i].repeat; j++)
		{
			for(k=0; k<8; k++)
			{
				y = pos / 160;
				x = pos % 160;

				if(n->data[i].data & 1<<(7-k))
					image.setPixel(x,y,1);
				else
		    		image.setPixel(x,y,0);
				pos++;
			}
		}
	}
	QString imgname = QString("%1/%2.png").arg(NotepadConduitSettings::outputDirectory()).arg(n->name);
	DEBUGCONDUIT << fname << ": Notepad " << imgname << endl;
	if(!image.save(imgname, "PNG", -1))
		notSaved++;
	else
		saved++;
}

<commit_msg><commit_after>/* notepad-conduit.cc			KPilot
**
** Copyright (C) 2004 by Adriaan de Groot, Joern Ahrens
**
** The code for NotepadActionThread::unpackNotePad was taken from
** Angus Ainslies read-notepad.c, which is part of pilot-link.
** NotepadActionThread::saveImage is also based on read-notepad.c.
**
** This file is part of the Notepad conduit, a conduit for KPilot that
** stores the notepad drawings to files.
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
** MA 02111-1307, USA.
*/

/*
** Bug reports and questions can be sent to kde-pim@kde.org
*/

#ifdef DEBUG
#undef DEBUG
#define DEBUG (1)
#else
#define DEBUG (1)
#endif

#define DEBUG (1)

#include "options.h"
#include "pilotUser.h"
#include "pilotSerialDatabase.h"

#include "notepad-conduit.h"  // The Conduit action
#include "notepadconduit.h"   // The settings class

#include <pi-notepad.h>

#include <qthread.h>
#include <qapplication.h>
#include <qvaluelist.h>
#include <qimage.h>
#include <qdir.h>

extern "C"
{
long version_conduit_notepad = KPILOT_PLUGIN_API;
const char *id_conduit_notepad =
	"$Id$";
}

NotepadConduit::NotepadConduit(KPilotDeviceLink *d,	const char *n,
	const QStringList &args) :	ConduitAction(d, n, args)
{
	FUNCTIONSETUP;
#ifdef DEBUG
	DEBUGCONDUIT << id_conduit_notepad << endl;
#endif
	fConduitName=i18n("Notepad");
	thread = 0L;

	(void) id_conduit_notepad;
}

NotepadConduit::~NotepadConduit()
{
	FUNCTIONSETUP;
}

/* virtual */ bool NotepadConduit::exec()
{
	FUNCTIONSETUP;

#ifdef DEBUG
	DEBUGCONDUIT << fname << ": In exec() @" << (unsigned long) this << endl;
#endif

	QDir dir(NotepadConduitSettings::outputDirectory());
	if(!dir.exists() && !dir.mkdir(dir.path())) {
		emit logError(i18n("Unable to open %1").arg(dir.path()));
		delayDone();
		return false;
	}
	else {
		thread = new NotepadActionThread(this, pilotSocket());
		thread->start();
		// tickle is disabled due to crashs during sync
		// -> PADP TX "unexpected package"
//		startTickle();
	}

	return true;
}

bool NotepadConduit::event(QEvent *e)
{
	FUNCTIONSETUP;

	if(e->type() == QEvent::User) {
#ifdef DEBUG
		DEBUGCONDUIT << fname << ": Notepad thread done." << endl;
#endif
//		stopTickle();
		delayDone();
		if(thread->getFailed())
			logError(i18n("1 notepad could not be saved", "%n notepads could not be saved", thread->getFailed()));
		logMessage(i18n("1 notepad saved", "%n notepads saved", thread->getSaved()));
		delete thread;
		return true;
	}
	else
		return ConduitAction::event(e);
}

//-----------------------------------------------------------------------------
// NotepadActionThread
//-----------------------------------------------------------------------------

NotepadActionThread::NotepadActionThread(QObject *parent, int pilotSocket) :
	fParent(parent), fPilotSocket(pilotSocket), notSaved(0), saved(0)
{
	FUNCTIONSETUP;
}

/*virtual*/ void NotepadActionThread::run()
{
	FUNCTIONSETUP;

	PilotSerialDatabase *db = new PilotSerialDatabase(fPilotSocket, "npadDB");

	int n = db->recordCount();
	QValueList<recordid_t> vl = db->idList();
	QValueList<recordid_t>::iterator it;
	struct NotePad a;
	for(it = vl.begin(); it != vl.end(); it++) {
		PilotRecord *pr = db->readRecordById(*it);
		if(pr) {
			unpack_NotePad(&a, (unsigned char*)pr->getData(), pr->getLen());
			saveImage(&a);
		}
	}
	QApplication::postEvent(fParent, new QEvent(QEvent::User));
}

int NotepadActionThread::unpackNotePad(struct NotePad *a, unsigned char *buffer, int len)
{
	FUNCTIONSETUP;

	unsigned char *start = buffer;

	a->createDate.sec = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->createDate.min = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->createDate.hour = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->createDate.day = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->createDate.month = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->createDate.year = (unsigned short int) get_short(buffer);
	buffer += 2;

	a->createDate.s = (unsigned short int) get_short(buffer);
	buffer += 2;

	a->changeDate.sec = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->changeDate.min = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->changeDate.hour = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->changeDate.day = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->changeDate.month = (unsigned short int) get_short(buffer);
	buffer += 2;
	a->changeDate.year = (unsigned short int) get_short(buffer);
	buffer += 2;

	a->changeDate.s = (unsigned short int) get_short(buffer);
	buffer += 2;

	a->flags = (unsigned short int) get_short(buffer);
	buffer += 2;

	if( a->flags & NOTEPAD_FLAG_ALARM ) {
			a->alarmDate.sec = (unsigned short int) get_short(buffer);
			buffer += 2;
			a->alarmDate.min = (unsigned short int) get_short(buffer);
			buffer += 2;
			a->alarmDate.hour = (unsigned short int) get_short(buffer);
			buffer += 2;
			a->alarmDate.day = (unsigned short int) get_short(buffer);
			buffer += 2;
			a->alarmDate.month = (unsigned short int) get_short(buffer);
			buffer += 2;
			a->alarmDate.year = (unsigned short int) get_short(buffer);
			buffer += 2;

			a->alarmDate.s = (unsigned short int) get_short(buffer);
			buffer += 2;
		}

		if( a->flags & NOTEPAD_FLAG_NAME ) {
			a->name = strdup((char *) buffer);

			buffer += strlen( a->name ) + 1;

			if( (strlen( a->name ) + 1)%2 == 1)
				buffer++;

		}
		else {
			a->name = NULL;
		}

	if( a->flags & NOTEPAD_FLAG_BODY ) {
			a->body.bodyLen = get_long( buffer );
			buffer += 4;

			a->body.width = get_long( buffer );
			buffer += 4;

			a->body.height = get_long( buffer );
			buffer += 4;

			a->body.l1 = get_long( buffer );
			buffer += 4;

			a->body.dataType = get_long( buffer );
			buffer += 4;

			a->body.dataLen = get_long( buffer );
			buffer += 4;

			a->data = (dataRec_t*)malloc( a->body.dataLen );

			if( a->data == NULL )
				return( 0 );

			memcpy( a->data, buffer, a->body.dataLen );
		}

	return ( buffer - start );	/* FIXME: return real length */
}

void NotepadActionThread::saveImage(struct NotePad *n)
{
	FUNCTIONSETUP;

	int i,j,k,datapoints = 0;
	QImage image(n->body.width+8, n->body.height, 8, 2);

	image.setColor(0, qRgb(0xaa, 0xc1 ,0x91) );
	image.setColor(1, qRgb(0x30, 0x36, 0x29) );

	int x = 0;
	int y = 0;
	int pos = 0;
	for(i=0; i<n->body.dataLen/2; i++)
	{
		datapoints += n->data[i].repeat;
		for(j=0; j<n->data[i].repeat; j++)
		{
			for(k=0; k<8; k++)
			{
				y = pos / 160;
				x = pos % 160;

				if(n->data[i].data & 1<<(7-k))
					image.setPixel(x,y,1);
				else
		    		image.setPixel(x,y,0);
				pos++;
			}
		}
	}
	QString imgname = QString("%1/%2.png").arg(NotepadConduitSettings::outputDirectory()).arg(n->name);
	DEBUGCONDUIT << fname << ": Notepad " << imgname << endl;
	if(!image.save(imgname, "PNG", -1))
		notSaved++;
	else
		saved++;
}

<|endoftext|>


<commit_before>/*
    This file is part of kdepim.

    Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
    Copyright (c) 2004 Till Adam <adam@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "groupwaredownloadjob.h"

#include "webdavhandler.h"
#include "folderlister.h"
#include "groupwaredataadaptor.h"

#include <kdebug.h>
#include <klocale.h>
#include <kurl.h>
#include <kio/job.h>
#include <kio/davjob.h>

#include <qapplication.h>
#include <qdatetime.h>
#include <qptrlist.h>
#include <qstringlist.h>
#include <qtimer.h>
#include <qdom.h>

using namespace KCal;
using namespace KPIM;

GroupwareDownloadJob::GroupwareDownloadJob( GroupwareDataAdaptor *adaptor )
  : GroupwareJob( adaptor )
{
}

void GroupwareDownloadJob::run()
{
  mFoldersForDownload = adaptor()->folderLister()->activeFolderIds();

  mItemsForDownload.clear();
  mCurrentlyOnServer.clear();

  mProgress = KPIM::ProgressManager::instance()->createProgressItem(
    KPIM::ProgressManager::getUniqueID(),
    adaptor()->downloadProgressMessage() );
  connect( mProgress,
           SIGNAL( progressItemCanceled( KPIM::ProgressItem * ) ),
           SLOT( cancelLoad() ) );

  listItems();
}

void GroupwareDownloadJob::listItems()
{
  if ( mFoldersForDownload.isEmpty() ) {
    if ( mProgress ) {
      mProgress->setTotalItems( mItemsForDownload.count() );
      mProgress->setCompletedItems( 1 );
      mProgress->updateProgress();
    }

    /* Delete incidences no longer present on the server */
    deleteIncidencesGoneFromServer();
    downloadItem();
  } else {
    QDomDocument props = WebdavHandler::createItemsAndVersionsPropsRequest();

    //kdDebug(7000) << "listItems: " << url.prettyURL() << endl;
    //kdDebug(7000) << "props: " << props.toString() << endl;

    KURL url = mFoldersForDownload.front();
    mFoldersForDownload.pop_front();

    adaptor()->setUserPassword( url );
    adaptor()->adaptDownloadUrl( url );

    kdDebug() << "OpenGroupware::listIncidences(): " << url << endl;

    mListEventsJob = KIO::davPropFind( url, props, "1", false );

    connect( mListEventsJob, SIGNAL( result( KIO::Job * ) ),
             SLOT( slotListJobResult( KIO::Job * ) ) );
  }
}

void GroupwareDownloadJob::slotListJobResult( KIO::Job *job )
{
  kdDebug() << "GroupwareDownloadJob::slotListJobResult(): " << endl;

  if ( job->error() ) {
    if ( mProgress ) {
      mProgress->setComplete();
      mProgress = 0;
    }
    error( job->errorString() );
  } else {
    QDomDocument doc = mListEventsJob->response();

    //kdDebug(7000) << " Doc: " << doc.toString() << endl;

    //kdDebug(7000) << idMapper().asString() << endl;
    QDomNodeList entries = doc.elementsByTagNameNS( "DAV:", "href" );
    QDomNodeList fingerprints = doc.elementsByTagNameNS( "DAV:", "getetag" );
    int c = entries.count();
    int i = 0;
    while ( i < c ) {
      QDomNode node = entries.item( i );
      QDomElement e = node.toElement();
      const QString &entry = e.text();
      node = fingerprints.item( i );
      e = node.toElement();
      i++;

      bool download = false;
      KURL url ( entry );
      const QString &location = url.path();
      const QString &newFingerprint = e.text();

      mCurrentlyOnServer << location;
      /* if not locally present, download */
      const QString &localId = adaptor()->idMapper()->localId( location );
      if ( !localId.isNull() && adaptor()->localItemExists( localId ) ) {
         //kdDebug(7000) << "Not locally present, download: " << location << endl;
        download = true;
      } else {
         //kdDebug(7000) << "Locally present " << endl;
        /* locally present, let's check if it's newer than what we have */
        const QString &oldFingerprint =
          adaptor()->idMapper()->fingerprint( localId );
        if ( oldFingerprint != newFingerprint ) {
          kdDebug(7000) << "Fingerprint changed old: " << oldFingerprint <<
            " new: " << newFingerprint << endl;
          // something changed on the server, let's see if we also changed it locally
          if ( adaptor()->localItemHasChanged( localId ) ) {
            // TODO conflict resolution
            kdDebug(7000) << "TODO conflict resolution" << endl;
            download = true;
          } else {
            download = true;
          }
        } else {
          //kdDebug(7000) << "Fingerprint did not change, don't download this one " << endl;
        }
      }
      if ( download ) {
        mItemsForDownload << entry;
      }
    }
  }

  mListEventsJob = 0;

  listItems();
}

void GroupwareDownloadJob::deleteIncidencesGoneFromServer()
{
  QMap<QString, QString> remoteIds( adaptor()->idMapper()->remoteIdMap() );
  QStringList::ConstIterator it = mCurrentlyOnServer.begin();
  while ( it != mCurrentlyOnServer.end() ) {
    remoteIds.remove( (*it) );
    ++it;
  }
  QMap<QString, QString>::ConstIterator it2;
  for (it2 = remoteIds.begin(); it2 != remoteIds.end(); ++it2) {
    adaptor()->deleteItem( remoteIds[ it2.key() ] );
  }
}

void GroupwareDownloadJob::downloadItem()
{
  kdDebug(7000) << " downloadItem " << endl;
  if ( !mItemsForDownload.isEmpty() ) {
    const QString entry = mItemsForDownload.front();
    mItemsForDownload.pop_front();

    KURL url( entry );
    url.setProtocol( "webdav" );
    mCurrentGetUrl = url.url(); // why can't I ask the job?
    adaptor()->setUserPassword( url );

    mJobData = QString::null;

    mDownloadJob = KIO::get( url, false, false );
    mDownloadJob->addMetaData( "accept", adaptor()->mimeType() );
    mDownloadJob->addMetaData( "PropagateHttpHeader", "true" );
    connect( mDownloadJob, SIGNAL( result( KIO::Job * ) ),
        SLOT( slotJobResult( KIO::Job * ) ) );
    connect( mDownloadJob, SIGNAL( data( KIO::Job *, const QByteArray & ) ),
        SLOT( slotJobData( KIO::Job *, const QByteArray & ) ) );
  } else {
    if ( mProgress ) mProgress->setComplete();
    mProgress = 0;
    success();
  }
}

void GroupwareDownloadJob::slotJobResult( KIO::Job *job )
{
  kdDebug() << "OpenGroupware::slotJobResult(): " << endl;

  if ( job->error() ) {
    error( job->errorString() );
  } else {
    const QString& headers = job->queryMetaData( "HTTP-Headers" );
    const QString& etag = WebdavHandler::getEtagFromHeaders( headers );

    const QString &remote = KURL( mCurrentGetUrl ).path();
    const QString &local = adaptor()->idMapper()->localId( remote );

    QString id = adaptor()->addItem( mJobData, local, remote );

    if ( id.isEmpty() ) {
      error( i18n("Error parsing calendar data.") );
    } else {
      if ( local.isEmpty() ) {
        adaptor()->idMapper()->setRemoteId( id, remote );
      }
      adaptor()->idMapper()->setFingerprint( id, etag );
    }
  }

  if ( mProgress ) {
    mProgress->incCompletedItems();
    mProgress->updateProgress();
  }
  mJobData = QString::null;
  mDownloadJob = 0;
  mCurrentGetUrl = QString::null;

  downloadItem();
}

void GroupwareDownloadJob::slotJobData( KIO::Job *, const QByteArray &data )
{
//  kdDebug() << "OpenGroupware::slotJobData()" << endl;

  mJobData.append( data.data() );
}

void GroupwareDownloadJob::kill()
{
  cancelLoad();
}

void GroupwareDownloadJob::cancelLoad()
{
  if ( mDownloadJob ) mDownloadJob->kill();
  mDownloadJob = 0;
  if ( mListEventsJob ) mListEventsJob->kill();
  mListEventsJob = 0;
  if ( mProgress ) mProgress->setComplete();
  mProgress = 0;
}

#include "groupwaredownloadjob.moc"
<commit_msg>Logic fix for local presence check. Delete local version before adding a downloaded update.<commit_after>/*
    This file is part of kdepim.

    Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
    Copyright (c) 2004 Till Adam <adam@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "groupwaredownloadjob.h"

#include "webdavhandler.h"
#include "folderlister.h"
#include "groupwaredataadaptor.h"

#include <kdebug.h>
#include <klocale.h>
#include <kurl.h>
#include <kio/job.h>
#include <kio/davjob.h>

#include <qapplication.h>
#include <qdatetime.h>
#include <qptrlist.h>
#include <qstringlist.h>
#include <qtimer.h>
#include <qdom.h>

using namespace KCal;
using namespace KPIM;

GroupwareDownloadJob::GroupwareDownloadJob( GroupwareDataAdaptor *adaptor )
  : GroupwareJob( adaptor )
{
}

void GroupwareDownloadJob::run()
{
  mFoldersForDownload = adaptor()->folderLister()->activeFolderIds();

  mItemsForDownload.clear();
  mCurrentlyOnServer.clear();

  mProgress = KPIM::ProgressManager::instance()->createProgressItem(
    KPIM::ProgressManager::getUniqueID(),
    adaptor()->downloadProgressMessage() );
  connect( mProgress,
           SIGNAL( progressItemCanceled( KPIM::ProgressItem * ) ),
           SLOT( cancelLoad() ) );

  listItems();
}

void GroupwareDownloadJob::listItems()
{
  if ( mFoldersForDownload.isEmpty() ) {
    if ( mProgress ) {
      mProgress->setTotalItems( mItemsForDownload.count() );
      mProgress->setCompletedItems( 1 );
      mProgress->updateProgress();
    }

    /* Delete incidences no longer present on the server */
    deleteIncidencesGoneFromServer();
    downloadItem();
  } else {
    QDomDocument props = WebdavHandler::createItemsAndVersionsPropsRequest();

    //kdDebug(7000) << "listItems: " << url.prettyURL() << endl;
    //kdDebug(7000) << "props: " << props.toString() << endl;

    KURL url = mFoldersForDownload.front();
    mFoldersForDownload.pop_front();

    adaptor()->setUserPassword( url );
    adaptor()->adaptDownloadUrl( url );

    kdDebug() << "OpenGroupware::listIncidences(): " << url << endl;

    mListEventsJob = KIO::davPropFind( url, props, "1", false );

    connect( mListEventsJob, SIGNAL( result( KIO::Job * ) ),
             SLOT( slotListJobResult( KIO::Job * ) ) );
  }
}

void GroupwareDownloadJob::slotListJobResult( KIO::Job *job )
{
  kdDebug() << "GroupwareDownloadJob::slotListJobResult(): " << endl;

  if ( job->error() ) {
    if ( mProgress ) {
      mProgress->setComplete();
      mProgress = 0;
    }
    error( job->errorString() );
  } else {
    QDomDocument doc = mListEventsJob->response();

    kdDebug(7000) << " Doc: " << doc.toString() << endl;
    kdDebug(7000) << " IdMapper: " << adaptor()->idMapper()->asString() << endl;

    QDomNodeList entries = doc.elementsByTagNameNS( "DAV:", "href" );
    QDomNodeList fingerprints = doc.elementsByTagNameNS( "DAV:", "getetag" );
    int c = entries.count();
    int i = 0;
    while ( i < c ) {
      QDomNode node = entries.item( i );
      QDomElement e = node.toElement();
      const QString &entry = e.text();
      node = fingerprints.item( i );
      e = node.toElement();
      i++;

      bool download = false;
      KURL url ( entry );
      const QString &location = url.path();
      const QString &newFingerprint = e.text();

      mCurrentlyOnServer << location;
      /* if not locally present, download */
      const QString &localId = adaptor()->idMapper()->localId( location );
      kdDebug(5006) << "Looking up remote: " << location << " found: " << localId << endl;
      if ( localId.isEmpty() || !adaptor()->localItemExists( localId ) ) {
         kdDebug(7000) << "Not locally present, download: " << location << endl;
        download = true;
      } else {
         kdDebug(7000) << "Locally present " << endl;
        /* locally present, let's check if it's newer than what we have */
        const QString &oldFingerprint =
          adaptor()->idMapper()->fingerprint( localId );
        if ( oldFingerprint != newFingerprint ) {
          kdDebug(7000) << "Fingerprint changed old: " << oldFingerprint <<
            " new: " << newFingerprint << endl;
          // something changed on the server, let's see if we also changed it locally
          if ( adaptor()->localItemHasChanged( localId ) ) {
            // TODO conflict resolution
            kdDebug(7000) << "TODO conflict resolution" << endl;
            download = true;
          } else {
            download = true;
          }
        } else {
          kdDebug(7000) << "Fingerprint did not change, don't download this one " << endl;
        }
      }
      if ( download ) {
        mItemsForDownload << entry;
      }
    }
  }

  mListEventsJob = 0;

  listItems();
}

void GroupwareDownloadJob::deleteIncidencesGoneFromServer()
{
  QMap<QString, QString> remoteIds( adaptor()->idMapper()->remoteIdMap() );
  QStringList::ConstIterator it = mCurrentlyOnServer.begin();
  while ( it != mCurrentlyOnServer.end() ) {
    remoteIds.remove( (*it) );
    ++it;
  }
  QMap<QString, QString>::ConstIterator it2;
  for (it2 = remoteIds.begin(); it2 != remoteIds.end(); ++it2) {
    adaptor()->deleteItem( remoteIds[ it2.key() ] );
  }
}

void GroupwareDownloadJob::downloadItem()
{
  kdDebug(7000) << " downloadItem " << endl;
  if ( !mItemsForDownload.isEmpty() ) {
    const QString entry = mItemsForDownload.front();
    mItemsForDownload.pop_front();

    KURL url( entry );
    url.setProtocol( "webdav" );
    mCurrentGetUrl = url.url(); // why can't I ask the job?
    adaptor()->setUserPassword( url );

    mJobData = QString::null;

    mDownloadJob = KIO::get( url, false, false );
    mDownloadJob->addMetaData( "accept", adaptor()->mimeType() );
    mDownloadJob->addMetaData( "PropagateHttpHeader", "true" );
    connect( mDownloadJob, SIGNAL( result( KIO::Job * ) ),
        SLOT( slotJobResult( KIO::Job * ) ) );
    connect( mDownloadJob, SIGNAL( data( KIO::Job *, const QByteArray & ) ),
        SLOT( slotJobData( KIO::Job *, const QByteArray & ) ) );
  } else {
    if ( mProgress ) mProgress->setComplete();
    mProgress = 0;
    success();
  }
}

void GroupwareDownloadJob::slotJobResult( KIO::Job *job )
{
  kdDebug() << "OpenGroupware::slotJobResult(): " << endl;

  if ( job->error() ) {
    error( job->errorString() );
  } else {
    const QString& headers = job->queryMetaData( "HTTP-Headers" );
    const QString& etag = WebdavHandler::getEtagFromHeaders( headers );

    const QString &remote = KURL( mCurrentGetUrl ).path();
    const QString &local = adaptor()->idMapper()->localId( remote );

    // remove old version, we would not have downnloaded
    // if it were still current
    adaptor()->deleteItem( local );
    QString id = adaptor()->addItem( mJobData, local, remote );

    if ( id.isEmpty() ) {
      error( i18n("Error parsing calendar data.") );
    } else {
      if ( local.isEmpty() ) {
        adaptor()->idMapper()->setRemoteId( id, remote );
      }
      adaptor()->idMapper()->setFingerprint( id, etag );
    }
  }

  if ( mProgress ) {
    mProgress->incCompletedItems();
    mProgress->updateProgress();
  }
  mJobData = QString::null;
  mDownloadJob = 0;
  mCurrentGetUrl = QString::null;

  downloadItem();
}

void GroupwareDownloadJob::slotJobData( KIO::Job *, const QByteArray &data )
{
//  kdDebug() << "OpenGroupware::slotJobData()" << endl;

  mJobData.append( data.data() );
}

void GroupwareDownloadJob::kill()
{
  cancelLoad();
}

void GroupwareDownloadJob::cancelLoad()
{
  if ( mDownloadJob ) mDownloadJob->kill();
  mDownloadJob = 0;
  if ( mListEventsJob ) mListEventsJob->kill();
  mListEventsJob = 0;
  if ( mProgress ) mProgress->setComplete();
  mProgress = 0;
}

#include "groupwaredownloadjob.moc"
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <sensor_msgs/Imu.h>
#include <nav_msgs/Odometry.h>
#include <geometry_msgs/PoseWithCovarianceStamped.h>
#include <tf/transform_broadcaster.h>
#include <tf/transform_listener.h>
#include <memory>
#include <iostream>

using namespace tf;
using namespace std;

ros::Publisher pose_pub;
std::unique_ptr<TransformBroadcaster> tf_broadcaster;
std::unique_ptr<TransformListener> tf_listener;

sensor_msgs::Imu imu;
nav_msgs::Odometry gps;

geometry_msgs::Point origin;
bool first = true;

bool imuIsValid()
{
    return imu.orientation.w != 0 ||
           imu.orientation.x != 0 ||
           imu.orientation.y != 0 ||
           imu.orientation.z != 0;
}

void publish_pose()
{
    if(!imuIsValid())
        return;
    geometry_msgs::PoseStamped pose;
    pose.header.frame_id = "/base_footprint";
    pose.pose.position.x = gps.pose.pose.position.x;
    pose.pose.position.y = gps.pose.pose.position.y;
    pose.pose.orientation = imu.orientation;
    pose_pub.publish(pose);

    Transform transform;
    transform.setOrigin(Vector3(pose.pose.position.x, pose.pose.position.y, 0.0));
    Quaternion q;
    quaternionMsgToTF(pose.pose.orientation, q);
    transform.setRotation(q);
    tf_broadcaster->sendTransform(StampedTransform(transform, ros::Time::now(), "map", "base_footprint"));

    ROS_INFO_STREAM("POSE " << pose.pose.position.x << " " << pose.pose.position.y);
}

void imu_callback(const sensor_msgs::ImuConstPtr& msg)
{
    imu = *msg;
    geometry_msgs::QuaternionStamped q;
    q.header.stamp = ros::Time(0);
    q.header.frame_id = imu.header.frame_id;
    q.quaternion = imu.orientation;
    tf_listener->waitForTransform("base_footprint", imu.header.frame_id, ros::Time(0), ros::Duration(10.0));
    geometry_msgs::QuaternionStamped transformed;
    tf_listener->transformQuaternion("base_footprint", q, transformed);
    imu.orientation = transformed.quaternion;

    publish_pose();
}

void gps_callback(const nav_msgs::OdometryConstPtr& msg)
{
    gps = *msg;
    if(first)
    {
        origin = gps.pose.pose.position;
        first = false;
    } else {
        gps.pose.pose.position.x -= origin.x;
        gps.pose.pose.position.y -= origin.y;
        gps.pose.pose.position.z -= origin.z;
    }
    publish_pose();
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "pose_tracker");

    tf_broadcaster = std::unique_ptr<TransformBroadcaster>(new TransformBroadcaster);

    tf_listener = std::unique_ptr<TransformListener>(new TransformListener);

    ros::NodeHandle nh;

    ros::Subscriber imu_sub = nh.subscribe("/imu", 1, imu_callback);

    ros::Subscriber gps_sub = nh.subscribe("/vo", 1, gps_callback);

    pose_pub = nh.advertise<geometry_msgs::PoseStamped>("/odom_combined", 1);

    ros::spin();

    return 0;
}
<commit_msg>Changes pose_tracker to store just orientation instead of whole IMU message.<commit_after>#include <ros/ros.h>
#include <sensor_msgs/Imu.h>
#include <nav_msgs/Odometry.h>
#include <geometry_msgs/PoseWithCovarianceStamped.h>
#include <tf/transform_broadcaster.h>
#include <tf/transform_listener.h>
#include <memory>
#include <iostream>

using namespace tf;
using namespace std;

ros::Publisher pose_pub;
std::unique_ptr<TransformBroadcaster> tf_broadcaster;
std::unique_ptr<TransformListener> tf_listener;

geometry_msgs::Quaternion orientation;
nav_msgs::Odometry gps;

geometry_msgs::Point origin;
bool first = true;

bool orientationIsValid()
{
    return orientation.w != 0 ||
           orientation.x != 0 ||
           orientation.y != 0 ||
           orientation.z != 0;
}

void publish_pose()
{
    if(!orientationIsValid())
        return;
    geometry_msgs::PoseStamped pose;
    pose.header.frame_id = "/base_footprint";
    pose.pose.position.x = gps.pose.pose.position.x;
    pose.pose.position.y = gps.pose.pose.position.y;
    pose.pose.orientation = orientation;
    pose_pub.publish(pose);

    Transform transform;
    transform.setOrigin(Vector3(pose.pose.position.x, pose.pose.position.y, 0.0));
    Quaternion q;
    quaternionMsgToTF(pose.pose.orientation, q);
    transform.setRotation(q);
    tf_broadcaster->sendTransform(StampedTransform(transform, ros::Time::now(), "map", "base_footprint"));

    ROS_INFO_STREAM("POSE " << pose.pose.position.x << " " << pose.pose.position.y);
}

void imu_callback(const sensor_msgs::ImuConstPtr& msg)
{
    geometry_msgs::QuaternionStamped q;
    q.header.stamp = ros::Time(0);
    q.header.frame_id = msg->header.frame_id;
    q.quaternion = msg->orientation;
    tf_listener->waitForTransform("base_footprint", msg->header.frame_id, ros::Time(0), ros::Duration(10.0));
    geometry_msgs::QuaternionStamped transformed;
    tf_listener->transformQuaternion("base_footprint", q, transformed);
    orientation = transformed.quaternion;

    publish_pose();
}

void gps_callback(const nav_msgs::OdometryConstPtr& msg)
{
    gps = *msg;
    if(first)
    {
        origin = gps.pose.pose.position;
        first = false;
    } else {
        gps.pose.pose.position.x -= origin.x;
        gps.pose.pose.position.y -= origin.y;
        gps.pose.pose.position.z -= origin.z;
    }
    publish_pose();
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "pose_tracker");

    tf_broadcaster = std::unique_ptr<TransformBroadcaster>(new TransformBroadcaster);

    tf_listener = std::unique_ptr<TransformListener>(new TransformListener);

    ros::NodeHandle nh;

    ros::Subscriber imu_sub = nh.subscribe("/imu", 1, imu_callback);

    ros::Subscriber gps_sub = nh.subscribe("/vo", 1, gps_callback);

    pose_pub = nh.advertise<geometry_msgs::PoseStamped>("/odom_combined", 1);

    ros::spin();

    return 0;
}
<|endoftext|>


<commit_before>#include <vector>
#include <string>
#include <sstream>
#include <pcl/io/pcd_io.h>
#include <pcl/common/time.h>
#include <pcl/console/parse.h>
#include <pcl/search/kdtree.h>
#include <pcl/search/brute_force.h>

using namespace std;

int
main (int argc, char ** argv)
{
  if (argc < 2)
  {
    pcl::console::print_info ("Syntax is: %s -pcd <pcd-file> (-radius <radius> | -knn <k> )\n", argv[0]);
    return (1);
  }

  string pcd_path;
  bool use_pcd_file = pcl::console::find_switch (argc, argv, "-pcd");
  if (use_pcd_file)
    pcl::console::parse (argc, argv, "-pcd", pcd_path);

  float radius = -1;
  if (pcl::console::find_switch (argc, argv, "-radius"))
    pcl::console::parse (argc, argv, "-radius", radius);

  int k = -1;
  if (pcl::console::find_switch (argc, argv, "-knn"))
    pcl::console::parse (argc, argv, "-knn", k);

  if ((radius * k) > 0)
  {
    cout << "please specify only one of the options -radius and -knn" << endl;
    return (1);
  }

  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB>);

  if (use_pcd_file)
    pcl::io::loadPCDFile (pcd_path, *cloud);
  else
  {
    cloud->resize (1000000);
    for (unsigned idx = 0; idx < cloud->size (); ++idx)
    {
      (*cloud)[idx].x = (double)rand () / (double)RAND_MAX;
      (*cloud)[idx].y = (double)rand () / (double)RAND_MAX;
      (*cloud)[idx].z = (double)rand () / (double)RAND_MAX;
    }
  }

  pcl::search::KdTree<pcl::PointXYZRGB> tree;
  pcl::PointXYZRGB query;
  query.x = 0.5;
  query.y = 0.5;
  query.z = 0.5;

  vector<int> kd_indices;
  vector<float> kd_distances;

  double start, stop;
  double kd_setup;
  double kd_search;
  double bf_setup;
  double bf_search;

  start = pcl::getTime ();
  tree.setInputCloud (cloud);
  stop = pcl::getTime ();
  cout << "setting up kd tree: " << (kd_setup = stop - start) << endl;
  start = pcl::getTime ();
  tree.nearestKSearchT (query, k, kd_indices, kd_distances);
  stop = pcl::getTime ();
  cout << "single search with kd tree; " << (kd_search = stop - start) << " :: " << kd_indices[0] << " , " << kd_distances [0] << endl;

  vector<int> bf_indices;
  vector<float> bf_distances;
  pcl::search::BruteForce<pcl::PointXYZRGB> brute_force;
  start = pcl::getTime ();
  brute_force.setInputCloud (cloud);
  stop = pcl::getTime ();
  cout << "setting up brute force search: " << (bf_setup = stop - start) << endl;

  start = pcl::getTime ();
  brute_force.nearestKSearchT (query, k, bf_indices, bf_distances);
  stop = pcl::getTime ();
  cout << "single search with brute force; " << (bf_search = stop - start) << " :: " << bf_indices[0] << " , " << bf_distances [0] << endl;
  cout << "amortization after searches: " << (kd_setup - bf_setup) / (bf_search - kd_search) << endl;

  if (kd_indices.size () != bf_indices.size ())
  {
    cerr << "number does not match" << endl;
  }
  else
  {
    for (unsigned idx = 0; idx < kd_indices.size (); ++idx)
    {
      if (kd_indices[idx] != bf_indices[idx] && kd_distances[idx] != bf_distances[idx])
      {
        cerr << "results do not match: " << idx << " nearest neighbor: "
                << kd_indices[idx] << " with distance: " << kd_distances[idx] << " vs. "
                << bf_indices[idx] << " with distance: " << bf_distances[idx] << endl;
      }
    }
  }
  return (0);
}
<commit_msg>added radius search to test<commit_after>#include <vector>
#include <string>
#include <sstream>
#include <pcl/io/pcd_io.h>
#include <pcl/common/time.h>
#include <pcl/console/parse.h>
#include <pcl/search/kdtree.h>
#include <pcl/search/brute_force.h>

using namespace std;

int
main (int argc, char ** argv)
{
  if (argc < 2)
  {
    pcl::console::print_info ("Syntax is: %s [-pcd <pcd-file>] (-radius <radius> [-knn <k>] | -knn <k> )\n", argv[0]);
    return (1);
  }

  string pcd_path;
  bool use_pcd_file = pcl::console::find_switch (argc, argv, "-pcd");
  if (use_pcd_file)
    pcl::console::parse (argc, argv, "-pcd", pcd_path);

  float radius = -1;
  if (pcl::console::find_switch (argc, argv, "-radius"))
    pcl::console::parse (argc, argv, "-radius", radius);

  int k = -1;
  if (pcl::console::find_switch (argc, argv, "-knn"))
    pcl::console::parse (argc, argv, "-knn", k);

  if (radius < 0 && k < 0)
  {
    cout << "please specify at least one of the options -radius and -knn" << endl;
    return (1);
  }

  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB>);

  if (use_pcd_file)
    pcl::io::loadPCDFile (pcd_path, *cloud);
  else
  {
    cloud->resize (1000000);
    for (unsigned idx = 0; idx < cloud->size (); ++idx)
    {
      (*cloud)[idx].x = (double)rand () / (double)RAND_MAX;
      (*cloud)[idx].y = (double)rand () / (double)RAND_MAX;
      (*cloud)[idx].z = (double)rand () / (double)RAND_MAX;
    }
  }

  pcl::search::KdTree<pcl::PointXYZRGB> tree;
  pcl::PointXYZRGB query;
  query.x = 0.5;
  query.y = 0.5;
  query.z = 0.5;

  vector<int> kd_indices;
  vector<float> kd_distances;
  vector<int> bf_indices;
  vector<float> bf_distances;

  double start, stop;
  double kd_setup;
  double kd_search;
  double bf_setup;
  double bf_search;

  if (k > 0)
  {
    start = pcl::getTime ();
    tree.setInputCloud (cloud);
    stop = pcl::getTime ();
    cout << "setting up kd tree: " << (kd_setup = stop - start) << endl;

    start = pcl::getTime ();
    tree.nearestKSearchT (query, k, kd_indices, kd_distances);
    stop = pcl::getTime ();
    cout << "single search with kd tree; " << (kd_search = stop - start) << " :: " << kd_indices[0] << " , " << kd_distances [0] << endl;

    pcl::search::BruteForce<pcl::PointXYZRGB> brute_force;
    start = pcl::getTime ();
    brute_force.setInputCloud (cloud);
    stop = pcl::getTime ();
    cout << "setting up brute force search: " << (bf_setup = stop - start) << endl;

    start = pcl::getTime ();
    brute_force.nearestKSearchT (query, k, bf_indices, bf_distances);
    stop = pcl::getTime ();
    cout << "single search with brute force; " << (bf_search = stop - start) << " :: " << bf_indices[0] << " , " << bf_distances [0] << endl;
    cout << "amortization after searches: " << (kd_setup - bf_setup) / (bf_search - kd_search) << endl;
  }
  else
  {
    start = pcl::getTime ();
    tree.setInputCloud (cloud);
    stop = pcl::getTime ();
    cout << "setting up kd tree: " << (kd_setup = stop - start) << endl;

    start = pcl::getTime ();
    tree.radiusSearch (query, radius, kd_indices, kd_distances, k);
    stop = pcl::getTime ();
    cout << "single search with kd tree; " << (kd_search = stop - start) << " :: " << kd_indices[0] << " , " << kd_distances [0] << endl;

    pcl::search::BruteForce<pcl::PointXYZRGB> brute_force;
    start = pcl::getTime ();
    brute_force.setInputCloud (cloud);
    stop = pcl::getTime ();
    cout << "setting up brute force search: " << (bf_setup = stop - start) << endl;

    start = pcl::getTime ();
    brute_force.radiusSearch (query, radius, bf_indices, bf_distances, k);
    stop = pcl::getTime ();
    cout << "single search with brute force; " << (bf_search = stop - start) << " :: " << bf_indices[0] << " , " << bf_distances [0] << endl;
    cout << "amortization after searches: " << (kd_setup - bf_setup) / (bf_search - kd_search) << endl;
  }

  if (kd_indices.size () != bf_indices.size ())
  {
    cerr << "size of results do not match " <<kd_indices.size () << " vs. " << bf_indices.size () << endl;
  }
  else
  {
    cerr << "size of result: " <<kd_indices.size () << endl;
    for (unsigned idx = 0; idx < kd_indices.size (); ++idx)
    {
      if (kd_indices[idx] != bf_indices[idx] && kd_distances[idx] != bf_distances[idx])
      {
        cerr << "results do not match: " << idx << " nearest neighbor: "
                << kd_indices[idx] << " with distance: " << kd_distances[idx] << " vs. "
                << bf_indices[idx] << " with distance: " << bf_distances[idx] << endl;
      }
    }
  }
  return (0);
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
// Please see LICENSE.md in repository root for license information
// https://github.com/AtomicGameEngine/AtomicGameEngine

#include "Precompiled.h"
#include "../Core/Context.h"
#include "../Graphics/Graphics.h"
#include "../Graphics/GraphicsEvents.h"
#include "../Graphics/View.h"
#include "../Scene/Scene.h"
#include "../Graphics/Camera.h"
#include "../Scene/SceneEvents.h"
#include "../Graphics/Light.h"
#include "../Resource/ResourceCache.h"
#include "../Graphics/Technique.h"
#include "../Environment/ProcSky.h"
#include "../Graphics/Renderer.h"

#if defined(_MSC_VER)
#include "stdint.h"
#endif

#if defined(EMSCRIPTEN)
#include <stdint.h>
#endif

namespace Atomic
{

extern const char* GEOMETRY_CATEGORY;

float ProcSky::timeOfDay_ = 0.0f;

ProcSky::ProcSky(Context* context) :
    Drawable(context, DRAWABLE_GEOMETRY),
    geometry_(new Geometry(context)),
    vertexBuffer_(new VertexBuffer(context_)),
    indexBuffer_(new IndexBuffer(context_)),
    autoUpdate_(false),
    dayTime_(0.0f),
    lastDayTimeUpdate_(-1.0f),
    shadowFade_(1.0f),
    customWorldTransform_(Matrix3x4::IDENTITY),
    initialized_(false),
    flipped_(false)
{

}

ProcSky::~ProcSky()
{

}

void ProcSky::RegisterObject(Context* context)
{
    context->RegisterFactory<ProcSky>(GEOMETRY_CATEGORY);

    COPY_BASE_ATTRIBUTES(Drawable);
}

void ProcSky::UpdateBatches(const FrameInfo& frame)
{
    if (!initialized_)
        Initialize();

    distance_ = 0.0f;

    // Follow only the camera rotation, not position
    Matrix3x4 customView(Vector3::ZERO, frame.camera_->GetNode()->GetWorldRotation().Inverse(), Vector3::ONE);
    customWorldTransform_ = customView * node_->GetWorldTransform();

    for (unsigned i = 0; i < batches_.Size(); ++i)
    {
        batches_[i].worldTransform_ = &customWorldTransform_;
        batches_[i].numWorldTransforms_ = 1;
        batches_[i].distance_ = 0.0f;
    }

}

void ProcSky::UpdateGeometry(const FrameInfo& frame)
{
    if (!initialized_)
        Initialize();

    if ( indexBuffer_->IsDataLost())
        UpdateIndexBuffer();

    UpdateVertexBuffer(frame);

}

UpdateGeometryType ProcSky::GetUpdateGeometryType()
{
    // updates vertex buffer per frame
    return UPDATE_MAIN_THREAD;
}

void ProcSky::OnWorldBoundingBoxUpdate()
{
    // The skybox is supposed to be visible everywhere, so set a humongous bounding box
    worldBoundingBox_.Define(-M_LARGE_VALUE, M_LARGE_VALUE);
}

void ProcSky::OnNodeSet(Node* node)
{
    Drawable::OnNodeSet(node);

    if (node && node->GetScene())
    {
        SubscribeToEvent(node->GetScene(), E_SCENEUPDATE, HANDLER(ProcSky, HandleSceneUpdate));
        SubscribeToEvent(E_BEGINVIEWUPDATE, HANDLER(ProcSky, HandleBeginViewUpdate));
    }

}

void ProcSky::HandleBeginViewUpdate(StringHash eventType, VariantMap& eventData)
{
#ifdef ATOMIC_OPENGL
    flipped_ = false;
    View* view = static_cast<View*>(eventData[BeginViewUpdate::P_VIEW].GetPtr());
    if (view && view->GetRenderTarget())
        flipped_ = true;

#endif

}

void ProcSky::HandleSceneUpdate(StringHash eventType, VariantMap& eventData)
{

    using namespace SceneUpdate;

    if (!initialized_)
        Initialize();

    float timeStep = eventData[P_TIMESTEP].GetFloat();

    if (autoUpdate_)
    {
        dayTime_ += timeStep * .1f;
        SetDayTime(dayTime_);
    }

}

float ProcSky::SetDayTime(float time)
{
    if (!initialized_)
        Initialize();

    sunAngle_ = (time+0.5f) * M_PI;

    int degrees = int(sunAngle_ * M_RADTODEG);

    degrees %= 360;

    timeOfDay_ = ((degrees + 90) % 360) / 15.0f;

    if (degrees >= 150 || degrees <= 15)
    {
        // fade out
        if (shadowFade_ < 0.0f || shadowFade_ != 1.0f)
        {
            shadowFade_ += .05f;

            if (shadowFade_ > 1.0f)
                shadowFade_ = 1.0f;

            sunlight_->SetShadowIntensity(shadowFade_);

        }
        else
        {

        }

    }
    else
    {
        // fade in
        if (shadowFade_ < 0.0f || shadowFade_ != 0.0f)
        {
            shadowFade_ -= .05f;

            if (shadowFade_ < 0.0f)
                shadowFade_ = 0.0f;

            sunlight_->SetShadowIntensity(shadowFade_);
        }
        else
        {
        }
    }

    Quaternion rot(degrees, Vector3::RIGHT);

    node_->SetRotation(rot);

    float daylight = cosf( time * M_PI ) * 0.8f + 0.4f;

    if( daylight > 1.0f )
        daylight = 1.0f;

    if( daylight < 0.0f )
        daylight = 0.0f;

    daylight = sqrtf( daylight );

    float dawnGlow = sinf( time * M_PI * 1.0f );
    int glowX = dawnGlow > 0.0f ? 0 : 7;
    dawnGlow = Atomic::Max( 0.0f, fabs( dawnGlow * dawnGlow * dawnGlow ) * 1.1f - 0.1f );

    Color top = Color(0,0,0,1).Lerp(topColor_, daylight);
    Color horiz = Color(.1,.1,.1,1).Lerp(horizColor_, daylight);

    uint8_t skytex[32 * 8 * 4 ];
    uint8_t* p;

    // bottom row is black
    p = &skytex[31*8*4];

    for( uint32_t x = 0; x < 8; x++ )
    {
        *p++ = 0;
        *p++ = 0;
        *p++ = 0;
        *p++ = 255;
    }

    p = skytex;
    for( uint32_t z = 0; z < 31; z++ )
    {
        for( uint32_t x = 0; x < 8; x++ )
        {
            float xGlow = Atomic::Max( 0, -abs((int)x-glowX) + 5 ) / 5.0f;
            float hGlow = z/31.0f;
            float glow = (dawnGlow * hGlow * hGlow * sqrtf( xGlow ));

            Color baseColor = top.Lerp(horiz, Atomic::Min( 1.0f, float (z*11) / 255.0f));
            baseColor = baseColor.Lerp(lerpColor_, glow );

            // pic a color from the mid - horizon (this is cheesy!)
            if (z == 28 && x == 4)
            {
                fogColor_ = baseColor;
                zone_->SetFogColor(fogColor_);
                Color sunColor (.3f, .2f, .1f);
                sunColor += fogColor_;

                sunlight_->SetColor(sunColor);

                Color ambient = sunColor * .75f;

                if (ambient.r_ < .25f)
                    ambient.r_ = .25f;
                if (ambient.g_ < .25f)
                    ambient.g_ = .25f;
                if (ambient.b_ < .25f)
                    ambient.b_ = .25f;

                zone_->SetAmbientColor(ambient);

            }

            unsigned r = Clamp(((int)(baseColor.r_ * 255.0f)), 0, 255);
            unsigned g = Clamp(((int)(baseColor.g_ * 255.0f)), 0, 255);
            unsigned b = Clamp(((int)(baseColor.b_ * 255.0f)), 0, 255);

            *p++ = (uint8_t) r;
            *p++ = (uint8_t) g;
            *p++ = (uint8_t) b;
            *p++ = 255;
        }
    }

    //if (fabs(lastDayTimeUpdate_ - dayTime_) > .005f)
    {
        skyTexture_->SetData(0,0,0,8,32,skytex);
        lastDayTimeUpdate_ = dayTime_;
    }

    return Atomic::Max( 4.0f/15.0f, daylight );
}

void ProcSky::UpdateIndexBuffer()
{
    unsigned short* dest = (unsigned short*)indexBuffer_->Lock(0, 6, true);
    *dest++ = 2; *dest++ = 1; *dest++ = 0;
    *dest++ = 0; *dest++ = 3; *dest++ = 2;

    indexBuffer_->Unlock();
    indexBuffer_->ClearDataLost();
}

void ProcSky::UpdateVertexBuffer(const FrameInfo &frame)
{

    float* vdest = (float*)vertexBuffer_->Lock(0, 4, true);

    const Frustum& frustum = frame.camera_->GetFrustum();

    // Upper left corner
    Vector3 n;

    Vector3 planes[4];
    planes[0] = frustum.planes_[PLANE_LEFT].normal_;
    planes[1] = frustum.planes_[PLANE_RIGHT].normal_;
    planes[2] = frustum.planes_[PLANE_UP].normal_;
    planes[3] = frustum.planes_[PLANE_DOWN].normal_;

    float top = 1.0f;
    float bottom = -1.0f;

#ifdef ATOMIC_OPENGL
    top = -1.0f;
    bottom = 1.0f;
#endif

    // 0 2
    n = planes[0].CrossProduct(planes[2]);
    *vdest++ = -1.0f;
    *vdest++ =  top;
    *vdest++ =  0.5f;

    *vdest++ = n.x_;
    *vdest++ = -n.y_;
    *vdest++ = n.z_ ;

    // Lower left corner
    // 3 0
    n = planes[3].CrossProduct(planes[0]);
    *vdest++ = -1.0f;
    *vdest++ = bottom;
    *vdest++ =  0.5f;

    *vdest++ = n.x_;
    *vdest++ = -n.y_;
    *vdest++ = n.z_;

    // Lower right corner
    // 1 3
    n = planes[1].CrossProduct(planes[3]);
    *vdest++ = 1.0f;
    *vdest++ = bottom;
    *vdest++ =  0.5f;

    *vdest++ = n.x_;
    *vdest++ = -n.y_;
    *vdest++ = n.z_;

    // Upper right corner

    // 2 1
    n = planes[2].CrossProduct(planes[1]);
    *vdest++ = 1.0f;
    *vdest++ = top;
    *vdest++ =  0.5f;

    *vdest++ = n.x_;
    *vdest++ = -n.y_;
    *vdest++ = n.z_;

    vertexBuffer_->Unlock();
    vertexBuffer_->ClearDataLost();
}

void ProcSky::Initialize()
{
    initialized_ = true;

    topColor_.b_ = float(0x76) / 255.0f;
    topColor_.g_ = float(0x4a) / 255.0f;
    topColor_.r_ = float(0x1f) / 255.0f;
    topColor_.a_ = 1.0f;

    horizColor_.b_ = float(0xca) / 255.0f;
    horizColor_.g_ = float(0x9b) / 255.0f;
    horizColor_.r_ = float(0x65) / 255.0f;
    horizColor_.a_ = 1.0f;

    lerpColor_.b_ = float(0x16) / 255.0f;
    lerpColor_.g_ = float(0x40) / 255.0f;
    lerpColor_.r_ = float(0x9b) / 255.0f;
    lerpColor_.a_ = 1.0f;

    sunlight_ = node_->CreateComponent<Light>();
    sunlight_->SetLightType(LIGHT_DIRECTIONAL);
    sunlight_->SetCastShadows(true);

    sunlight_->SetShadowBias(BiasParameters(0.0001f, 0.5f));
    // Set cascade splits at 10, 50 and 200 world units, fade shadows out at 80% of maximum shadow distance
#if ANDROID
    sunlight_->SetShadowCascade(CascadeParameters(50.0f, 0.0f, 0.0f, 0.0f, 0.8f));
#else
    sunlight_->SetShadowCascade(CascadeParameters(10.0f, 50.0f, 200.0f, 0.0f, 0.8f));
#endif

    ResourceCache* cache = GetSubsystem<ResourceCache>();

    skyMaterial_ = cache->GetResource<Material>("Materials/ProcSky.xml");

    geometry_->SetVertexBuffer(0, vertexBuffer_, MASK_POSITION | MASK_NORMAL );
    geometry_->SetIndexBuffer(indexBuffer_);

    indexBuffer_->SetSize( 6, false);
    UpdateIndexBuffer();

    // updated per frame
    vertexBuffer_->SetSize(4, MASK_POSITION | MASK_NORMAL , true);

    batches_.Resize(1);
    batches_[0].geometry_ = geometry_;
    batches_[0].geometryType_ = GEOM_STATIC_NOINSTANCING;
    batches_[0].worldTransform_ = &customWorldTransform_;
    batches_[0].material_ = skyMaterial_;
    batches_[0].geometry_->SetDrawRange(TRIANGLE_LIST, 0, 6, false);

    skyTexture_ = new Texture2D(context_);

    skyMaterial_->SetTexture(TU_DIFFUSE , skyTexture_);

    skyTexture_->SetMipsToSkip(QUALITY_LOW, 0); // No quality reduction
    skyTexture_->SetNumLevels(1); // No mipmaps
    skyTexture_->SetAddressMode(COORD_U, ADDRESS_CLAMP);
    skyTexture_->SetAddressMode(COORD_V, ADDRESS_CLAMP);

    int width = 8;
    int height = 32;

    skyTexture_->SetSize(width, height, Graphics::GetRGBAFormat(), TEXTURE_DYNAMIC);
    SharedArrayPtr<unsigned char> emptyBitmap(new unsigned char[width * height * 4]);
    memset(emptyBitmap.Get(), 0, width * height * 4);
    skyTexture_->SetData(0, 0, 0, width, height, emptyBitmap.Get());

    PODVector<Component*> components;
    node_->GetScene()->GetComponents(components, Zone::GetTypeStatic(), true);
    zone_ = (Zone*)components[0];

}

void ProcSky::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results)
{
    // Do not record a raycast result for a skybox, as it would block all other results
}

}
<commit_msg>Fix for GL proc sky<commit_after>// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
// Please see LICENSE.md in repository root for license information
// https://github.com/AtomicGameEngine/AtomicGameEngine

#include "Precompiled.h"
#include "../Core/Context.h"
#include "../Graphics/Graphics.h"
#include "../Graphics/GraphicsEvents.h"
#include "../Graphics/View.h"
#include "../Scene/Scene.h"
#include "../Graphics/Camera.h"
#include "../Scene/SceneEvents.h"
#include "../Graphics/Light.h"
#include "../Resource/ResourceCache.h"
#include "../Graphics/Technique.h"
#include "../Environment/ProcSky.h"
#include "../Graphics/Renderer.h"

#if defined(_MSC_VER)
#include "stdint.h"
#endif

#if defined(EMSCRIPTEN)
#include <stdint.h>
#endif

namespace Atomic
{

extern const char* GEOMETRY_CATEGORY;

float ProcSky::timeOfDay_ = 0.0f;

ProcSky::ProcSky(Context* context) :
    Drawable(context, DRAWABLE_GEOMETRY),
    geometry_(new Geometry(context)),
    vertexBuffer_(new VertexBuffer(context_)),
    indexBuffer_(new IndexBuffer(context_)),
    autoUpdate_(false),
    dayTime_(0.0f),
    lastDayTimeUpdate_(-1.0f),
    shadowFade_(1.0f),
    customWorldTransform_(Matrix3x4::IDENTITY),
    initialized_(false),
    flipped_(false)
{

}

ProcSky::~ProcSky()
{

}

void ProcSky::RegisterObject(Context* context)
{
    context->RegisterFactory<ProcSky>(GEOMETRY_CATEGORY);

    COPY_BASE_ATTRIBUTES(Drawable);
}

void ProcSky::UpdateBatches(const FrameInfo& frame)
{
    if (!initialized_)
        Initialize();

    distance_ = 0.0f;

    // Follow only the camera rotation, not position
    Matrix3x4 customView(Vector3::ZERO, frame.camera_->GetNode()->GetWorldRotation().Inverse(), Vector3::ONE);
    customWorldTransform_ = customView * node_->GetWorldTransform();

    for (unsigned i = 0; i < batches_.Size(); ++i)
    {
        batches_[i].worldTransform_ = &customWorldTransform_;
        batches_[i].numWorldTransforms_ = 1;
        batches_[i].distance_ = 0.0f;
    }

}

void ProcSky::UpdateGeometry(const FrameInfo& frame)
{
    if (!initialized_)
        Initialize();

    if ( indexBuffer_->IsDataLost())
        UpdateIndexBuffer();

    UpdateVertexBuffer(frame);

}

UpdateGeometryType ProcSky::GetUpdateGeometryType()
{
    // updates vertex buffer per frame
    return UPDATE_MAIN_THREAD;
}

void ProcSky::OnWorldBoundingBoxUpdate()
{
    // The skybox is supposed to be visible everywhere, so set a humongous bounding box
    worldBoundingBox_.Define(-M_LARGE_VALUE, M_LARGE_VALUE);
}

void ProcSky::OnNodeSet(Node* node)
{
    Drawable::OnNodeSet(node);

    if (node && node->GetScene())
    {
        SubscribeToEvent(node->GetScene(), E_SCENEUPDATE, HANDLER(ProcSky, HandleSceneUpdate));
        SubscribeToEvent(E_BEGINVIEWUPDATE, HANDLER(ProcSky, HandleBeginViewUpdate));
    }

}

void ProcSky::HandleBeginViewUpdate(StringHash eventType, VariantMap& eventData)
{
#ifdef ATOMIC_OPENGL
    flipped_ = false;
    View* view = static_cast<View*>(eventData[BeginViewUpdate::P_VIEW].GetPtr());
    if (view && view->GetRenderTarget())
        flipped_ = true;

#endif

}

void ProcSky::HandleSceneUpdate(StringHash eventType, VariantMap& eventData)
{

    using namespace SceneUpdate;

    if (!initialized_)
        Initialize();

    float timeStep = eventData[P_TIMESTEP].GetFloat();

    if (autoUpdate_)
    {
        dayTime_ += timeStep * .1f;
        SetDayTime(dayTime_);
    }

}

float ProcSky::SetDayTime(float time)
{
    if (!initialized_)
        Initialize();

    sunAngle_ = (time+0.5f) * M_PI;

    int degrees = int(sunAngle_ * M_RADTODEG);

    degrees %= 360;

    timeOfDay_ = ((degrees + 90) % 360) / 15.0f;

    if (degrees >= 150 || degrees <= 15)
    {
        // fade out
        if (shadowFade_ < 0.0f || shadowFade_ != 1.0f)
        {
            shadowFade_ += .05f;

            if (shadowFade_ > 1.0f)
                shadowFade_ = 1.0f;

            sunlight_->SetShadowIntensity(shadowFade_);

            if (!sunlight_->GetCastShadows())
                sunlight_->SetCastShadows(true);

        }
        else
        {
            if (sunlight_->GetCastShadows())
                sunlight_->SetCastShadows(false);
        }

    }
    else
    {
        // fade in
        if (shadowFade_ < 0.0f || shadowFade_ != 0.0f)
        {
            shadowFade_ -= .05f;

            if (shadowFade_ < 0.0f)
                shadowFade_ = 0.0f;

            sunlight_->SetShadowIntensity(shadowFade_);

            if (!sunlight_->GetCastShadows())
                sunlight_->SetCastShadows(true);

        }
        else
        {
            if (!sunlight_->GetCastShadows())
                sunlight_->SetCastShadows(true);
        }
    }

    Quaternion rot(degrees, Vector3::RIGHT);

    node_->SetRotation(rot);

    float daylight = cosf( time * M_PI ) * 0.8f + 0.4f;

    if( daylight > 1.0f )
        daylight = 1.0f;

    if( daylight < 0.0f )
        daylight = 0.0f;

    daylight = sqrtf( daylight );

    float dawnGlow = sinf( time * M_PI * 1.0f );
    int glowX = dawnGlow > 0.0f ? 0 : 7;
    dawnGlow = Atomic::Max( 0.0f, fabs( dawnGlow * dawnGlow * dawnGlow ) * 1.1f - 0.1f );

    Color top = Color(0,0,0,1).Lerp(topColor_, daylight);
    Color horiz = Color(.1,.1,.1,1).Lerp(horizColor_, daylight);

    uint8_t skytex[32 * 8 * 4 ];
    uint8_t* p;

    // bottom row is black
    p = &skytex[31*8*4];

    for( uint32_t x = 0; x < 8; x++ )
    {
        *p++ = 0;
        *p++ = 0;
        *p++ = 0;
        *p++ = 255;
    }

    p = skytex;
    for( uint32_t z = 0; z < 31; z++ )
    {
        for( uint32_t x = 0; x < 8; x++ )
        {
            float xGlow = Atomic::Max( 0, -abs((int)x-glowX) + 5 ) / 5.0f;
            float hGlow = z/31.0f;
            float glow = (dawnGlow * hGlow * hGlow * sqrtf( xGlow ));

            Color baseColor = top.Lerp(horiz, Atomic::Min( 1.0f, float (z*11) / 255.0f));
            baseColor = baseColor.Lerp(lerpColor_, glow );

            // pic a color from the mid - horizon (this is cheesy!)
            if (z == 28 && x == 4)
            {
                fogColor_ = baseColor;
                zone_->SetFogColor(fogColor_);
                Color sunColor (.3f, .2f, .1f);
                sunColor += fogColor_;

                sunlight_->SetColor(sunColor);

                Color ambient = sunColor * .75f;

                if (ambient.r_ < .25f)
                    ambient.r_ = .25f;
                if (ambient.g_ < .25f)
                    ambient.g_ = .25f;
                if (ambient.b_ < .25f)
                    ambient.b_ = .25f;

                zone_->SetAmbientColor(ambient);

            }

            unsigned r = Clamp(((int)(baseColor.r_ * 255.0f)), 0, 255);
            unsigned g = Clamp(((int)(baseColor.g_ * 255.0f)), 0, 255);
            unsigned b = Clamp(((int)(baseColor.b_ * 255.0f)), 0, 255);

            *p++ = (uint8_t) r;
            *p++ = (uint8_t) g;
            *p++ = (uint8_t) b;
            *p++ = 255;
        }
    }

    //if (fabs(lastDayTimeUpdate_ - dayTime_) > .005f)
    {
        skyTexture_->SetData(0,0,0,8,32,skytex);
        lastDayTimeUpdate_ = dayTime_;
    }

    return Atomic::Max( 4.0f/15.0f, daylight );
}

void ProcSky::UpdateIndexBuffer()
{
    unsigned short* dest = (unsigned short*)indexBuffer_->Lock(0, 6, true);
    *dest++ = 2; *dest++ = 1; *dest++ = 0;
    *dest++ = 0; *dest++ = 3; *dest++ = 2;

    indexBuffer_->Unlock();
    indexBuffer_->ClearDataLost();
}

void ProcSky::UpdateVertexBuffer(const FrameInfo &frame)
{

    float* vdest = (float*)vertexBuffer_->Lock(0, 4, true);

    const Frustum& frustum = frame.camera_->GetFrustum();

    // Upper left corner
    Vector3 n;

    Vector3 planes[4];
    planes[0] = frustum.planes_[PLANE_LEFT].normal_;
    planes[1] = frustum.planes_[PLANE_RIGHT].normal_;
    planes[2] = frustum.planes_[PLANE_UP].normal_;
    planes[3] = frustum.planes_[PLANE_DOWN].normal_;

    float top = 1.0f;
    float bottom = -1.0f;

#ifdef ATOMIC_OPENGL
if (flipped_)
{
    top = -1.0f;
    bottom = 1.0f;
}
#endif

    // 0 2
    n = planes[0].CrossProduct(planes[2]);
    *vdest++ = -1.0f;
    *vdest++ =  top;
    *vdest++ =  0.5f;

    *vdest++ = n.x_;
    *vdest++ = -n.y_;
    *vdest++ = n.z_ ;

    // Lower left corner
    // 3 0
    n = planes[3].CrossProduct(planes[0]);
    *vdest++ = -1.0f;
    *vdest++ = bottom;
    *vdest++ =  0.5f;

    *vdest++ = n.x_;
    *vdest++ = -n.y_;
    *vdest++ = n.z_;

    // Lower right corner
    // 1 3
    n = planes[1].CrossProduct(planes[3]);
    *vdest++ = 1.0f;
    *vdest++ = bottom;
    *vdest++ =  0.5f;

    *vdest++ = n.x_;
    *vdest++ = -n.y_;
    *vdest++ = n.z_;

    // Upper right corner

    // 2 1
    n = planes[2].CrossProduct(planes[1]);
    *vdest++ = 1.0f;
    *vdest++ = top;
    *vdest++ =  0.5f;

    *vdest++ = n.x_;
    *vdest++ = -n.y_;
    *vdest++ = n.z_;

    vertexBuffer_->Unlock();
    vertexBuffer_->ClearDataLost();
}

void ProcSky::Initialize()
{
    initialized_ = true;

    topColor_.b_ = float(0x76) / 255.0f;
    topColor_.g_ = float(0x4a) / 255.0f;
    topColor_.r_ = float(0x1f) / 255.0f;
    topColor_.a_ = 1.0f;

    horizColor_.b_ = float(0xca) / 255.0f;
    horizColor_.g_ = float(0x9b) / 255.0f;
    horizColor_.r_ = float(0x65) / 255.0f;
    horizColor_.a_ = 1.0f;

    lerpColor_.b_ = float(0x16) / 255.0f;
    lerpColor_.g_ = float(0x40) / 255.0f;
    lerpColor_.r_ = float(0x9b) / 255.0f;
    lerpColor_.a_ = 1.0f;

    sunlight_ = node_->CreateComponent<Light>();
    sunlight_->SetLightType(LIGHT_DIRECTIONAL);
    sunlight_->SetCastShadows(true);

    sunlight_->SetShadowBias(BiasParameters(0.0001f, 0.5f));
    // Set cascade splits at 10, 50 and 200 world units, fade shadows out at 80% of maximum shadow distance
#if ANDROID
    sunlight_->SetShadowCascade(CascadeParameters(50.0f, 0.0f, 0.0f, 0.0f, 0.8f));
#else
    sunlight_->SetShadowCascade(CascadeParameters(10.0f, 50.0f, 200.0f, 0.0f, 0.8f));
#endif

    ResourceCache* cache = GetSubsystem<ResourceCache>();

    skyMaterial_ = cache->GetResource<Material>("Materials/ProcSky.xml");

    geometry_->SetVertexBuffer(0, vertexBuffer_, MASK_POSITION | MASK_NORMAL );
    geometry_->SetIndexBuffer(indexBuffer_);

    indexBuffer_->SetSize( 6, false);
    UpdateIndexBuffer();

    // updated per frame
    vertexBuffer_->SetSize(4, MASK_POSITION | MASK_NORMAL , true);

    batches_.Resize(1);
    batches_[0].geometry_ = geometry_;
    batches_[0].geometryType_ = GEOM_STATIC_NOINSTANCING;
    batches_[0].worldTransform_ = &customWorldTransform_;
    batches_[0].material_ = skyMaterial_;
    batches_[0].geometry_->SetDrawRange(TRIANGLE_LIST, 0, 6, false);

    skyTexture_ = new Texture2D(context_);

    skyMaterial_->SetTexture(TU_DIFFUSE , skyTexture_);

    skyTexture_->SetMipsToSkip(QUALITY_LOW, 0); // No quality reduction
    skyTexture_->SetNumLevels(1); // No mipmaps
    skyTexture_->SetAddressMode(COORD_U, ADDRESS_CLAMP);
    skyTexture_->SetAddressMode(COORD_V, ADDRESS_CLAMP);

    int width = 8;
    int height = 32;

    skyTexture_->SetSize(width, height, Graphics::GetRGBAFormat(), TEXTURE_DYNAMIC);
    SharedArrayPtr<unsigned char> emptyBitmap(new unsigned char[width * height * 4]);
    memset(emptyBitmap.Get(), 0, width * height * 4);
    skyTexture_->SetData(0, 0, 0, width, height, emptyBitmap.Get());

    PODVector<Component*> components;
    node_->GetScene()->GetComponents(components, Zone::GetTypeStatic(), true);
    zone_ = (Zone*)components[0];

}

void ProcSky::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results)
{
    // Do not record a raycast result for a skybox, as it would block all other results
}

}
<|endoftext|>


<commit_before>//===-- HexagonTargetTransformInfo.cpp - Hexagon specific TTI pass --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
/// \file
/// This file implements a TargetTransformInfo analysis pass specific to the
/// Hexagon target machine. It uses the target's detailed information to provide
/// more precise answers to certain TTI queries, while letting the target
/// independent and default TTI implementations handle the rest.
///
//===----------------------------------------------------------------------===//

#include "HexagonTargetTransformInfo.h"
#include "llvm/Support/Debug.h"

using namespace llvm;

#define DEBUG_TYPE "hexagontti"

TargetTransformInfo::PopcntSupportKind
HexagonTTIImpl::getPopcntSupport(unsigned IntTyWidthInBit) const {
  // Return Fast Hardware support as every input  < 64 bits will be promoted
  // to 64 bits.
  return TargetTransformInfo::PSK_FastHardware;
}

// The Hexagon target can unroll loops with run-time trip counts.
void HexagonTTIImpl::getUnrollingPreferences(Loop *L,
                                             TTI::UnrollingPreferences &UP) {
  UP.Runtime = UP.Partial = true;
}

unsigned HexagonTTIImpl::getNumberOfRegisters(bool vector) const {
  if (vector) {
    // While its true that v60 has vector registers,
    // we do not want to advertise it through this API
    // as it enables LOOP and SLP vectorization.
    return 0;
  }
  return 32;
}
<commit_msg>[Hexagon] Edit a comment. NFC<commit_after>//===-- HexagonTargetTransformInfo.cpp - Hexagon specific TTI pass --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
/// \file
/// This file implements a TargetTransformInfo analysis pass specific to the
/// Hexagon target machine. It uses the target's detailed information to provide
/// more precise answers to certain TTI queries, while letting the target
/// independent and default TTI implementations handle the rest.
///
//===----------------------------------------------------------------------===//

#include "HexagonTargetTransformInfo.h"
#include "llvm/Support/Debug.h"

using namespace llvm;

#define DEBUG_TYPE "hexagontti"

TargetTransformInfo::PopcntSupportKind
HexagonTTIImpl::getPopcntSupport(unsigned IntTyWidthInBit) const {
  // Return Fast Hardware support as every input  < 64 bits will be promoted
  // to 64 bits.
  return TargetTransformInfo::PSK_FastHardware;
}

// The Hexagon target can unroll loops with run-time trip counts.
void HexagonTTIImpl::getUnrollingPreferences(Loop *L,
                                             TTI::UnrollingPreferences &UP) {
  UP.Runtime = UP.Partial = true;
}

unsigned HexagonTTIImpl::getNumberOfRegisters(bool vector) const {
  return vector ? 0 : 32;
}
<|endoftext|>


<commit_before>//===- ProfilingUtils.cpp - Helper functions shared by profilers ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a few helper functions which are used by profile
// instrumentation code to instrument the code.  This allows the profiler pass
// to worry about *what* to insert, and these functions take care of *how* to do
// it.
//
//===----------------------------------------------------------------------===//

#include "ProfilingUtils.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"

void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName,
                                   GlobalValue *Array) {
  LLVMContext &Context = MainFn->getContext();
  const Type *ArgVTy =
    PointerType::getUnqual(Type::getInt8PtrTy(Context));
  const PointerType *UIntPtr =
        Type::getInt32PtrTy(Context);
  Module &M = *MainFn->getParent();
  Constant *InitFn = M.getOrInsertFunction(FnName, Type::getInt32Ty(Context),
                                           Type::getInt32Ty(Context),
                                           ArgVTy, UIntPtr,
                                           Type::getInt32Ty(Context),
                                           (Type *)0);

  // This could force argc and argv into programs that wouldn't otherwise have
  // them, but instead we just pass null values in.
  std::vector<Value*> Args(4);
  Args[0] = Constant::getNullValue(Type::getInt32Ty(Context));
  Args[1] = Constant::getNullValue(ArgVTy);

  // Skip over any allocas in the entry block.
  BasicBlock *Entry = MainFn->begin();
  BasicBlock::iterator InsertPos = Entry->begin();
  while (isa<AllocaInst>(InsertPos)) ++InsertPos;

  std::vector<Constant*> GEPIndices(2,
                             Constant::getNullValue(Type::getInt32Ty(Context)));
  unsigned NumElements = 0;
  if (Array) {
    Args[2] = ConstantExpr::getGetElementPtr(Array, &GEPIndices[0],
                                             GEPIndices.size());
    NumElements =
      cast<ArrayType>(Array->getType()->getElementType())->getNumElements();
  } else {
    // If this profiling instrumentation doesn't have a constant array, just
    // pass null.
    Args[2] = ConstantPointerNull::get(UIntPtr);
  }
  Args[3] = ConstantInt::get(Type::getInt32Ty(Context), NumElements);

  Instruction *InitCall = CallInst::Create(InitFn, Args.begin(), Args.end(),
                                           "newargc", InsertPos);

  // If argc or argv are not available in main, just pass null values in.
  Function::arg_iterator AI;
  switch (MainFn->arg_size()) {
  default:
  case 2:
    AI = MainFn->arg_begin(); ++AI;
    if (AI->getType() != ArgVTy) {
      Instruction::CastOps opcode = CastInst::getCastOpcode(AI, false, ArgVTy,
                                                            false);
      InitCall->setOperand(2,
          CastInst::Create(opcode, AI, ArgVTy, "argv.cast", InitCall));
    } else {
      InitCall->setOperand(2, AI);
    }
    /* FALL THROUGH */

  case 1:
    AI = MainFn->arg_begin();
    // If the program looked at argc, have it look at the return value of the
    // init call instead.
    if (!AI->getType()->isIntegerTy(32)) {
      Instruction::CastOps opcode;
      if (!AI->use_empty()) {
        opcode = CastInst::getCastOpcode(InitCall, true, AI->getType(), true);
        AI->replaceAllUsesWith(
          CastInst::Create(opcode, InitCall, AI->getType(), "", InsertPos));
      }
      opcode = CastInst::getCastOpcode(AI, true,
                                       Type::getInt32Ty(Context), true);
      InitCall->setOperand(1,
          CastInst::Create(opcode, AI, Type::getInt32Ty(Context),
                           "argc.cast", InitCall));
    } else {
      AI->replaceAllUsesWith(InitCall);
      InitCall->setOperand(1, AI);
    }

  case 0: break;
  }
}

void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum,
                                   GlobalValue *CounterArray) {
  // Insert the increment after any alloca or PHI instructions...
  BasicBlock::iterator InsertPos = BB->getFirstNonPHI();
  while (isa<AllocaInst>(InsertPos))
    ++InsertPos;

  LLVMContext &Context = BB->getContext();

  // Create the getelementptr constant expression
  std::vector<Constant*> Indices(2);
  Indices[0] = Constant::getNullValue(Type::getInt32Ty(Context));
  Indices[1] = ConstantInt::get(Type::getInt32Ty(Context), CounterNum);
  Constant *ElementPtr =
    ConstantExpr::getGetElementPtr(CounterArray, &Indices[0],
                                          Indices.size());

  // Load, increment and store the value back.
  Value *OldVal = new LoadInst(ElementPtr, "OldFuncCounter", InsertPos);
  Value *NewVal = BinaryOperator::Create(Instruction::Add, OldVal,
                                 ConstantInt::get(Type::getInt32Ty(Context), 1),
                                         "NewFuncCounter", InsertPos);
  new StoreInst(NewVal, ElementPtr, InsertPos);
}
<commit_msg>use setArgOperand<commit_after>//===- ProfilingUtils.cpp - Helper functions shared by profilers ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a few helper functions which are used by profile
// instrumentation code to instrument the code.  This allows the profiler pass
// to worry about *what* to insert, and these functions take care of *how* to do
// it.
//
//===----------------------------------------------------------------------===//

#include "ProfilingUtils.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"

void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName,
                                   GlobalValue *Array) {
  LLVMContext &Context = MainFn->getContext();
  const Type *ArgVTy =
    PointerType::getUnqual(Type::getInt8PtrTy(Context));
  const PointerType *UIntPtr =
        Type::getInt32PtrTy(Context);
  Module &M = *MainFn->getParent();
  Constant *InitFn = M.getOrInsertFunction(FnName, Type::getInt32Ty(Context),
                                           Type::getInt32Ty(Context),
                                           ArgVTy, UIntPtr,
                                           Type::getInt32Ty(Context),
                                           (Type *)0);

  // This could force argc and argv into programs that wouldn't otherwise have
  // them, but instead we just pass null values in.
  std::vector<Value*> Args(4);
  Args[0] = Constant::getNullValue(Type::getInt32Ty(Context));
  Args[1] = Constant::getNullValue(ArgVTy);

  // Skip over any allocas in the entry block.
  BasicBlock *Entry = MainFn->begin();
  BasicBlock::iterator InsertPos = Entry->begin();
  while (isa<AllocaInst>(InsertPos)) ++InsertPos;

  std::vector<Constant*> GEPIndices(2,
                             Constant::getNullValue(Type::getInt32Ty(Context)));
  unsigned NumElements = 0;
  if (Array) {
    Args[2] = ConstantExpr::getGetElementPtr(Array, &GEPIndices[0],
                                             GEPIndices.size());
    NumElements =
      cast<ArrayType>(Array->getType()->getElementType())->getNumElements();
  } else {
    // If this profiling instrumentation doesn't have a constant array, just
    // pass null.
    Args[2] = ConstantPointerNull::get(UIntPtr);
  }
  Args[3] = ConstantInt::get(Type::getInt32Ty(Context), NumElements);

  CallInst *InitCall = CallInst::Create(InitFn, Args.begin(), Args.end(),
                                        "newargc", InsertPos);

  // If argc or argv are not available in main, just pass null values in.
  Function::arg_iterator AI;
  switch (MainFn->arg_size()) {
  default:
  case 2:
    AI = MainFn->arg_begin(); ++AI;
    if (AI->getType() != ArgVTy) {
      Instruction::CastOps opcode = CastInst::getCastOpcode(AI, false, ArgVTy,
                                                            false);
      InitCall->setArgOperand(1,
          CastInst::Create(opcode, AI, ArgVTy, "argv.cast", InitCall));
    } else {
      InitCall->setArgOperand(1, AI);
    }
    /* FALL THROUGH */

  case 1:
    AI = MainFn->arg_begin();
    // If the program looked at argc, have it look at the return value of the
    // init call instead.
    if (!AI->getType()->isIntegerTy(32)) {
      Instruction::CastOps opcode;
      if (!AI->use_empty()) {
        opcode = CastInst::getCastOpcode(InitCall, true, AI->getType(), true);
        AI->replaceAllUsesWith(
          CastInst::Create(opcode, InitCall, AI->getType(), "", InsertPos));
      }
      opcode = CastInst::getCastOpcode(AI, true,
                                       Type::getInt32Ty(Context), true);
      InitCall->setArgOperand(0,
          CastInst::Create(opcode, AI, Type::getInt32Ty(Context),
                           "argc.cast", InitCall));
    } else {
      AI->replaceAllUsesWith(InitCall);
      InitCall->setArgOperand(0, AI);
    }

  case 0: break;
  }
}

void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum,
                                   GlobalValue *CounterArray) {
  // Insert the increment after any alloca or PHI instructions...
  BasicBlock::iterator InsertPos = BB->getFirstNonPHI();
  while (isa<AllocaInst>(InsertPos))
    ++InsertPos;

  LLVMContext &Context = BB->getContext();

  // Create the getelementptr constant expression
  std::vector<Constant*> Indices(2);
  Indices[0] = Constant::getNullValue(Type::getInt32Ty(Context));
  Indices[1] = ConstantInt::get(Type::getInt32Ty(Context), CounterNum);
  Constant *ElementPtr =
    ConstantExpr::getGetElementPtr(CounterArray, &Indices[0],
                                          Indices.size());

  // Load, increment and store the value back.
  Value *OldVal = new LoadInst(ElementPtr, "OldFuncCounter", InsertPos);
  Value *NewVal = BinaryOperator::Create(Instruction::Add, OldVal,
                                 ConstantInt::get(Type::getInt32Ty(Context), 1),
                                         "NewFuncCounter", InsertPos);
  new StoreInst(NewVal, ElementPtr, InsertPos);
}
<|endoftext|>