<commit_before>// Copyright (c) 2018 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "test/test_bitcoin.h"

#include "policy/policy.h"
#include "script/interpreter.h"

#include <boost/test/unit_test.hpp>

#include <array>

typedef std::vector<uint8_t> valtype;
typedef std::vector<valtype> stacktype;

BOOST_FIXTURE_TEST_SUITE(checkdatasig_tests, BasicTestingSetup)

std::array<uint32_t, 3> flagset{
    {0, STANDARD_SCRIPT_VERIFY_FLAGS, MANDATORY_SCRIPT_VERIFY_FLAGS}};

/**
 * General utility functions to check for script passing/failing.
 */
static void CheckTestResultForAllFlags(const stacktype &original_stack,
                                       const CScript &script,
                                       const stacktype &expected) {
    BaseSignatureChecker sigchecker;

    for (uint32_t flags : flagset) {
        // The opcode are not implemented yet, so we get a bad opcode error when
        // passing the activation flag.
        ScriptError err = SCRIPT_ERR_OK;
        stacktype stack{original_stack};
        bool r = EvalScript(stack, script, flags | SCRIPT_ENABLE_CHECKDATASIG,
                            sigchecker, &err);
        BOOST_CHECK(!r);
        BOOST_CHECK_EQUAL(err, SCRIPT_ERR_BAD_OPCODE);

        // Make sure that we get a bad opcode when the activation flag is not
        // passed.
        stack = original_stack;
        r = EvalScript(stack, script, flags, sigchecker, &err);
        BOOST_CHECK(!r);
        BOOST_CHECK_EQUAL(err, SCRIPT_ERR_BAD_OPCODE);
    }
}

BOOST_AUTO_TEST_CASE(checkdatasig_test) {
    CheckTestResultForAllFlags({}, CScript() << OP_CHECKDATASIG, {});
    CheckTestResultForAllFlags({}, CScript() << OP_CHECKDATASIGVERIFY, {});
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Check GetOpName(..) for completeness<commit_after>// Copyright (c) 2018 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "test/test_bitcoin.h"

#include "policy/policy.h"
#include "script/interpreter.h"

#include <boost/test/unit_test.hpp>

#include <array>

typedef std::vector<uint8_t> valtype;
typedef std::vector<valtype> stacktype;

BOOST_FIXTURE_TEST_SUITE(checkdatasig_tests, BasicTestingSetup)

std::array<uint32_t, 3> flagset{
    {0, STANDARD_SCRIPT_VERIFY_FLAGS, MANDATORY_SCRIPT_VERIFY_FLAGS}};

/**
 * General utility functions to check for script passing/failing.
 */
static void CheckTestResultForAllFlags(const stacktype &original_stack,
                                       const CScript &script,
                                       const stacktype &expected) {
    BaseSignatureChecker sigchecker;

    for (uint32_t flags : flagset) {
        // The opcode are not implemented yet, so we get a bad opcode error when
        // passing the activation flag.
        ScriptError err = SCRIPT_ERR_OK;
        stacktype stack{original_stack};
        bool r = EvalScript(stack, script, flags | SCRIPT_ENABLE_CHECKDATASIG,
                            sigchecker, &err);
        BOOST_CHECK(!r);
        BOOST_CHECK_EQUAL(err, SCRIPT_ERR_BAD_OPCODE);

        // Make sure that we get a bad opcode when the activation flag is not
        // passed.
        stack = original_stack;
        r = EvalScript(stack, script, flags, sigchecker, &err);
        BOOST_CHECK(!r);
        BOOST_CHECK_EQUAL(err, SCRIPT_ERR_BAD_OPCODE);
    }
}

BOOST_AUTO_TEST_CASE(checkdatasig_test) {
    CheckTestResultForAllFlags({}, CScript() << OP_CHECKDATASIG, {});
    CheckTestResultForAllFlags({}, CScript() << OP_CHECKDATASIGVERIFY, {});
}

BOOST_AUTO_TEST_CASE(checkdatasig_opcode_formatting) {
    BOOST_CHECK_EQUAL(GetOpName(OP_CHECKDATASIG), "OP_CHECKDATASIG");
    BOOST_CHECK_EQUAL(GetOpName(OP_CHECKDATASIGVERIFY), "OP_CHECKDATASIGVERIFY");
}
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*
 * This file contains sample wrappers showing Android Java Developers
 * who are not familiar with the NDK or JNI how to get data in and out of the
 * CPP and how to incorporate the sample code in
 * http://leveldb.googlecode.com/svn/trunk/doc/index.html into their JNI
 */
#include <string.h>
#include <jni.h>

#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>

#include "leveldb/db.h"

#define  LOG_TAG    "AndroidLevelDB"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

leveldb::DB* db;

extern "C" {
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_dbGet(JNIEnv * env, jobject thiz, jstring key1);
};

JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_dbGet(JNIEnv * env, jobject thiz, jstring key1)
{

	LOGI("In the get ");

	const char* key = env->GetStringUTFChars(key1,0);
	LOGI("Key");
	LOGI(key);

	std::string value;
	leveldb::Status status = db->Get(leveldb::ReadOptions(), key, &value);

	if (status.ok()) {
		const char* re =  value.c_str();
		return env->NewStringUTF(re);
	}else{
		const char* re =  status.ToString().c_str();
		return env->NewStringUTF(re);
	}

}

extern "C" {
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_dbPut(JNIEnv * env, jobject thiz, jstring key1, jstring value1);
};

JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_dbPut(JNIEnv * env, jobject thiz, jstring key1, jstring value1)
{
	LOGI("In the put ");

	const char* key = env->GetStringUTFChars(key1,0);
	const char* value = env->GetStringUTFChars(value1,0);
	LOGI("Key");
	LOGI(key);
	LOGI("Value");
	LOGI(value);

	leveldb::Status status = db->Put(leveldb::WriteOptions(), key, value);
	if (status.ok()) {
		const char* re =  status.ToString().c_str();
		return env->NewStringUTF(value);
	}else{
		const char* re =  status.ToString().c_str();
		return env->NewStringUTF(re);
	}

}
extern "C" {
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_dbOpen(JNIEnv* env, jobject thiz, jstring dbpath);

};

JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_dbOpen(JNIEnv* env, jobject thiz, jstring dbpath)
{
	const char* path = env->GetStringUTFChars(dbpath,0);
	LOGI("Opening database");
	LOGI(path);

	leveldb::Options options;
	options.create_if_missing = true;
	leveldb::Status status = leveldb::DB::Open(options, path, &db);
	const char* re =  status.ToString().c_str();
	return env->NewStringUTF(re);
}

extern "C" {
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_dbClose(JNIEnv* env, jobject thiz, jstring dbpath);

};

JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_dbClose(JNIEnv* env, jobject thiz, jstring dbpath)
{
	delete db;
	LOGI("Closed database");
	return env->NewStringUTF("Closed database");
}
extern "C" {
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_dbDelete(JNIEnv * env, jobject thiz, jstring key1);
};

JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_dbDelete(JNIEnv * env, jobject thiz, jstring key1)
{

	LOGI("In the delete ");

	const char* key = env->GetStringUTFChars(key1,0);
	LOGI("Key");
	LOGI(key);

	leveldb::Status status = db->Delete(leveldb::WriteOptions(), key);

	if (status.ok()) {
		const char* re =  status.ToString().c_str();
		return env->NewStringUTF(re);
	}else{
		const char* re =  status.ToString().c_str();
		return env->NewStringUTF(re);
	}

}
extern "C" {
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_GetProperty(JNIEnv * env, jobject thiz);
};

JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_GetProperty(JNIEnv * env, jobject thiz)
{
	return env->NewStringUTF("calling get property to find out db size etc");
}
<commit_msg>adding safetly checking and changing class names to the leveldb google code namespace<commit_after>/*
 * This file contains sample wrappers showing Android Java Developers
 * who are not familiar with the NDK or JNI how to get data in and out of the
 * CPP and how to incorporate the sample code in
 * http://leveldb.googlecode.com/svn/trunk/doc/index.html into their JNI
 */
#include <string.h>
#include <jni.h>

#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>

#include "leveldb/db.h"

#define  LOG_TAG    "AndroidLevelDB"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

leveldb::DB* db;
bool isDBopen;
char* databasePath;

extern "C" {
JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_dbGet(JNIEnv * env, jobject thiz, jstring key1);
};

JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_dbGet(JNIEnv * env, jobject thiz, jstring key1)
{
	//LOGI("In the get ");
	if(! isDBopen){
		LOGE("Trying to get when DB wasn't open");
//		LOGI("Opening database");

		leveldb::Options options;
		options.create_if_missing = true;
		leveldb::Status status = leveldb::DB::Open(options, databasePath, &db);
		if (status.ok()) {
			LOGI("Opened database");
			isDBopen = true;
		}else{
			LOGE("Failed to open database");
			isDBopen = false;
			databasePath = const_cast<char*>("");
			return env->NewStringUTF("NotFound");
		}
	}
	const char* key = env->GetStringUTFChars(key1,0);
	//LOGI("Key");
//	LOGI(key);

	std::string value;
	leveldb::Status status = db->Get(leveldb::ReadOptions(), key, &value);

	if (status.ok()) {
		const char* re =  value.c_str();
//		LOGI(re);
		return env->NewStringUTF(re);
	}else{
		const char* re =  status.ToString().c_str();
//		LOGI(re);
		return env->NewStringUTF("NotFound");
	}

}

extern "C" {
JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_dbPut(JNIEnv * env, jobject thiz, jstring key1, jstring value1);
};

JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_dbPut(JNIEnv * env, jobject thiz, jstring key1, jstring value1)
{
	if(! isDBopen){
		LOGE("Trying to put when DB wasn't open");
//		LOGI("Opening database");
		leveldb::Options options;
		options.create_if_missing = true;
		leveldb::Status status = leveldb::DB::Open(options, databasePath, &db);
		if (status.ok()) {
			LOGI("Opened database");
			isDBopen = true;
		}else{
			LOGE("Failed to open database");
			isDBopen = false;
			databasePath = const_cast<char*>("");
			return env->NewStringUTF("NotFound");
		}
	}
//	LOGI("In the put ");

	const char* key = env->GetStringUTFChars(key1,0);
	const char* value = env->GetStringUTFChars(value1,0);
	//LOGI("Key");
//	LOGI(key);
	//LOGI("Value");
//	LOGI(value);

	leveldb::Status status = db->Put(leveldb::WriteOptions(), key, value);
	if (status.ok()) {
		const char* re =  status.ToString().c_str();
//		LOGI(re);
		return env->NewStringUTF(value);
	}else{
		const char* re =  status.ToString().c_str();
		return env->NewStringUTF("NotFound");
	}

}
extern "C" {
JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_dbOpen(JNIEnv* env, jobject thiz, jstring dbpath);
};

JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_dbOpen(JNIEnv* env, jobject thiz, jstring dbpath)
{
	if(isDBopen){
		LOGI("DB was already open");
		return env->NewStringUTF("DB was already open");
	}
	const char* path = env->GetStringUTFChars(dbpath,0);
//	LOGI("Opening database");

	leveldb::Options options;
	options.create_if_missing = true;
	leveldb::Status status = leveldb::DB::Open(options, path, &db);
	if (status.ok()) {
		LOGI(path);
		LOGI("Opened database");
		isDBopen = true;
		databasePath = const_cast<char*>(path);
	}else{
		LOGE("Failed to open database");
		isDBopen = false;
		databasePath = const_cast<char*>("");
	}
	const char* re =  status.ToString().c_str();
	return env->NewStringUTF(re);
}

extern "C" {
JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_dbClose(JNIEnv* env, jobject thiz, jstring dbpath);

};

JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_dbClose(JNIEnv* env, jobject thiz, jstring dbpath)
{
	if(isDBopen){
		delete db;
		isDBopen = false;
		LOGI("Closed database");
	}else{
		LOGI("DB was already closed.");
	}
	return env->NewStringUTF("Closed database");
}
extern "C" {
JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_dbDestroy(JNIEnv* env, jobject thiz, jstring dbpath);

};

JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_dbDestroy(JNIEnv* env, jobject thiz, jstring dbpath)
{
	if(isDBopen){
		delete db;
	}
	const char* path = env->GetStringUTFChars(dbpath,0);
	leveldb::Options options;
	options.create_if_missing = true;
	leveldb::Status status = DestroyDB(path, options);
	LOGI("Destroyed (ie, cleared) database");

	/*re-open database */
	status = leveldb::DB::Open(options, path, &db);
	if (status.ok()) {
		LOGI(path);
		LOGI("Opened database");
		isDBopen = true;
		databasePath = const_cast<char*>(path);
	}else{
		LOGE("Failed to open database");
		isDBopen = false;
		databasePath = const_cast<char*>("");
	}
	return env->NewStringUTF("Destroyed (ie, cleared) database");
}
extern "C" {
JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_dbDelete(JNIEnv * env, jobject thiz, jstring key1);
};

JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_dbDelete(JNIEnv * env, jobject thiz, jstring key1)
{
	if(! isDBopen){
		LOGE("Trying to delete when DB wasn't open");
//		LOGI("Opening database");
		leveldb::Options options;
		options.create_if_missing = true;
		leveldb::Status status = leveldb::DB::Open(options, databasePath, &db);
		if (status.ok()) {
			LOGI("Opened database");
			isDBopen = true;
		}else{
			LOGE("Failed to open database");
			isDBopen = false;
			databasePath = const_cast<char*>("");
			return env->NewStringUTF("NotFound");
		}
	}
	LOGI("In the delete ");

	const char* key = env->GetStringUTFChars(key1,0);
	//LOGI("Key");
//	LOGI(key);

	leveldb::Status status = db->Delete(leveldb::WriteOptions(), key);
	if (status.ok()) {
		const char* re =  status.ToString().c_str();
		return env->NewStringUTF(re);
	}else{
		const char* re =  status.ToString().c_str();
		return env->NewStringUTF("NotFound");
	}

}
extern "C" {
JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_GetProperty(JNIEnv * env, jobject thiz);
};

JNIEXPORT jstring JNICALL Java_com_google_code_p_leveldb_LevelDB_GetProperty(JNIEnv * env, jobject thiz)
{
	return env->NewStringUTF("calling get property to find out db size etc");
}
<|endoftext|>


<commit_before><commit_msg>Criando estruturas de dados<commit_after>#include <iostream>
#include <string>

using namespace std;

typedef struct {
    String nome;
    String cpf;
    float saldo;
} Conta;

int main() {
    Conta conta;

    init_conta( conta );

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 Matt Hill
// Use of this source code is governed by The MIT License
// that can be found in the LICENSE file.

#include "DisplayUpdater.h"
#include "RgbMatrix.h"
#include "RgbMatrixContainer.h"
#include "Thread.h"

#include <cstdlib>
#include <stdio.h>
#include <unistd.h>

// Below are several classes that demo the capabilities of the RgbMatrix class.

// Demo of the capabilities of the RgbMatrix class
class RgbMatrixDrawShapes1 : public RgbMatrixContainer
{
public:
  RgbMatrixDrawShapes1(RgbMatrix *m) : RgbMatrixContainer(m) {}

  void run()
  {
    Color red;
    red.red = 135;

    Color green;
    green.green = 135;

    Color blue;
    blue.blue = 80;

    _matrix->setTextCursor(1, 19);
    _matrix->setFontSize(2);
    _matrix->setFontColor(green);
    _matrix->writeLetter('S');
    _matrix->writeLetter('i');
    _matrix->writeLetter('m');
    _matrix->writeLetter('p');
    _matrix->writeLetter('l');
    _matrix->writeLetter('e');

    _matrix->setTextCursor(1, 26);
    _matrix->setFontColor(blue);
    _matrix->writeLetter('S');
    _matrix->writeLetter('h');
    _matrix->writeLetter('a');
    _matrix->writeLetter('p');
    _matrix->writeLetter('e');
    _matrix->writeLetter('s');

    _matrix->drawRect(1, 1, 6, 6, blue);

    _matrix->drawCircle(10, 7, 3, red);

    _matrix->drawTriangle(25, 1, 31, 8, 20, 8, green);
  }

};

// Demo of the capabilities of the RgbMatrix class
class RgbMatrixDrawShapes2 : public RgbMatrixContainer
{
public:
  RgbMatrixDrawShapes2(RgbMatrix *m) : RgbMatrixContainer(m) {}

  void run()
  {
    Color b1;
    b1.blue = 155;

    Color b2;
    b2.green = 17;
    b2.blue = 205;

    Color b3;
    b3.green = 17;
    b3.blue = 224;

    Color b4;
    b4.green = 17;
    b4.blue = 234;

    Color b5;
    b5.blue = 255;

    _matrix->drawRect(0, 0, 1, 32, b1);
    _matrix->drawRect(9, 15, 1, 17, b2);
    _matrix->drawRect(10, 15, 1, 17, b3);
    _matrix->drawRect(11, 15, 1, 17, b4);
    _matrix->drawRect(12, 15, 1, 17, b5);
    _matrix->drawRect(13, 15, 1, 17, b1);
    _matrix->drawRect(14, 15, 1, 17, b2);
    _matrix->drawRect(15, 15, 1, 17, b3);
    _matrix->drawRect(16, 15, 1, 17, b4);
    _matrix->drawRect(17, 15, 1, 17, b5);
  }

};

// Cycle through colors, and pulse the entire matrix the same color.
class RgbMatrixPulsePixels : public RgbMatrixContainer
{
public:
  RgbMatrixPulsePixels(RgbMatrix *m) : RgbMatrixContainer(m) {}

  void run()
  {
    uint32_t count = 0;

    while (!isDone())
    {
      count++;

      int color = (count >> 9) % 7;
      int value = count & 0xFF;

      if (count & 0x100) value = 255 - value;

      int r, g, b;

      switch (color)
      {
        case 0: r = value; g = b = 0; break;
        case 1: g = value; r = b = 0; break;
        case 2: b = value; r = g = 0; break;
        case 3: r = g = value; b = 0; break;
        case 4: r = b = value; g = 0; break;
        case 5: g = b = value; r = 0; break;
        default: r = g = b = value; break;
      }

      Color pulse;
      pulse.red = r;
      pulse.green = g;
      pulse.blue = b;

      _matrix->fillScreen(pulse);

      usleep(5000);
    }
  }

};

// Demo of the capabilities of the RgbMatrix class
class RgbMatrixPulsePixelsGradient : public RgbMatrixContainer
{
public:
  RgbMatrixPulsePixelsGradient(RgbMatrix *m) : RgbMatrixContainer(m) {}

  void run()
  {
    uint32_t count = 0;

    Color fish;
    fish.red = 255;

    _matrix->drawPixel(0, 0, fish);

    while (!isDone())
    {
      count++;

      int color = (count >> 9) % 7; //512 steps for each color (256 up / 256 down)
      int value = count & 0xFF;

      if (count & 0x100) value = 255 - value; // pulse down

      int r, g, b;

      switch (color)
      {
        case 0: r = value; g = b = 0; break;
        case 1: g = value; r = b = 0; break;
        case 2: b = value; r = g = 0; break;
        case 3: r = g = value; b = 0; break;
        case 4: r = b = value; g = 0; break;
        case 5: g = b = value; r = 0; break;
        default: r = g = b = value; break;
      }

      for (int i=0; i < 32; i++)
      {
        Color iColor;
        iColor.red   = (((i+1) * 8) > r) ? r : 0;
        iColor.green = (((i+1) * 8) > g) ? g : 0;
        iColor.blue  = (((i+1) * 8) > b) ? b : 0;

        //int numero = rand() % 32;
        //_matrix->drawRect(i, numero, 1, 31 - numero, iColor);

        _matrix->drawRect(0, i, 32, 1, iColor);
      }

      usleep(2500);
    }
  }

};

// Draw a color wheel on the matrix.
class RgbMatrixColorWheel : public RgbMatrixContainer
{
public:
  RgbMatrixColorWheel(RgbMatrix *m) : RgbMatrixContainer(m) {}

  void run()
  {
    _matrix->drawColorWheel();
  }
};

//-----------------------------------------------------------------------------
// Display a menu and allow choosing different demos.

RgbMatrix *m = NULL;

RgbMatrixContainer *display = NULL;
RgbMatrixContainer *updater = NULL;

void displayMenu()
{
  std::system("clear");
  printf("      |------------------------------------------------|\n");
  printf("      |     Select an option from the menu below:      |\n");
  printf("      |------------------------------------------------|\n");
  printf("      |      (1) Pulse All Pixels                      |\n");
  printf("      |      (2) Pulse All Pixels with a Gradient      |\n");
  printf("      |      (3) Demo of Drawing Shapes                |\n");
  printf("      |      (4) Another Demo of Drawing Shapes        |\n");
  printf("      |      (5) Draw a Color Wheel                    |\n");
  printf("      |      (6) Quit                                  |\n");
  printf("      |------------------------------------------------|\n");
  printf("                   Your Choice: ");
}

void runDemo()
{
  updater->start(10);
  display->start();

  printf("Press <RETURN> when done viewing demo.\n");
  getchar();

  delete display;
  delete updater;

  display = NULL;
  updater = NULL;

  m->clearDisplay();
  m->updateDisplay();
}

int main(int argc, char *argv[])
{
  GpioProxy io;

 if (!io.initialize())
    return 1;

  m = new RgbMatrix(&io);

  char choice = '1';

  while (choice != '6' && choice != 'q' && choice != 'Q')
  {
    displayMenu();

    choice = getchar();
    getchar(); //consume the \n

    switch (choice)
    {
      case '1':
        display = new RgbMatrixPulsePixels(m);
        updater = new DisplayUpdater(m);
        printf("\n\nRunning Demo #1.\n\n");
        runDemo();
        break;

      case '2':
        display = new RgbMatrixPulsePixelsGradient(m);
        updater = new DisplayUpdater(m);
        printf("\n\nRunning Demo #2.\n\n");
        runDemo();
        break;

      case '3':
        display = new RgbMatrixDrawShapes1(m);
        updater = new DisplayUpdater(m);
        printf("\n\nRunning Demo #3.\n\n");
        runDemo();
        break;

      case '4':
        display = new RgbMatrixDrawShapes2(m);
        updater = new DisplayUpdater(m);
        printf("\n\nRunning Demo #4.\n\n");
        runDemo();
        break;

      case '5':
        display = new RgbMatrixColorWheel(m);
        updater = new DisplayUpdater(m);
        printf("\n\nRunning Demo #5.\n\n");
        runDemo();
        break;

      case '6':
        printf("\n\nHave a nice day!\n\n");
        break;

      default:
        break;
    }
  }

  // Stop threads and wait for them to join.
  if (display) delete display;
  if (updater) delete updater;

  // Clear and refresh the display.
  m->clearDisplay();
  m->updateDisplay();

  delete m;

  return 0;
}

<commit_msg>Add demo of drawing shapes.<commit_after>// Copyright (c) 2013 Matt Hill
// Use of this source code is governed by The MIT License
// that can be found in the LICENSE file.

#include "DisplayUpdater.h"
#include "RgbMatrix.h"
#include "RgbMatrixContainer.h"
#include "Thread.h"

#include <cstdlib>
#include <stdio.h>
#include <unistd.h>

// Below are several classes that demo the capabilities of the RgbMatrix class.

// Draw some shapes on the RGB Matrix.
class RgbMatrixDrawShapes1 : public RgbMatrixContainer
{
public:
  RgbMatrixDrawShapes1(RgbMatrix *m) : RgbMatrixContainer(m) {}

  void run()
  {
    Color red;
    red.red = 255;

    Color green;
    green.green = 255;

    Color blue;
    blue.blue = 255;

    Color purple;
    purple.red = 135;
    purple.blue = 255;

    Color yellow;
    yellow.red = 255;
    yellow.green = 255;

    Color turquoise;
    turquoise.green = 255;
    turquoise.blue = 255;

    // Draw some shapes
    _matrix->drawRect(1, 1, 8, 8, blue);

    _matrix->drawCircle(14, 5, 4, red);

    _matrix->drawTriangle(25, 1, 30, 8, 20, 8, green);

    _matrix->drawRect(1, 11, 9, 6, purple);

    _matrix->drawRoundRect(11, 11, 10, 6, 2, yellow);

    _matrix->drawWedge(30, 18, 8, 190, 270, turquoise);

    // Write some text
    _matrix->setTextCursor(1, 19);
    _matrix->setFontSize(2); // Medium (4x6) Font
    _matrix->setFontColor(green);
    _matrix->writeLetter('S');
    _matrix->writeLetter('i');
    _matrix->writeLetter('m');
    _matrix->writeLetter('p');
    _matrix->writeLetter('l');
    _matrix->writeLetter('e');

    _matrix->setTextCursor(1, 26);
    _matrix->setFontColor(blue);
    _matrix->writeLetter('S');
    _matrix->writeLetter('h');
    _matrix->writeLetter('a');
    _matrix->writeLetter('p');
    _matrix->writeLetter('e');
    _matrix->writeLetter('s');
 }

};

// Draw and fill some shapes on the RGB Matrix.
class RgbMatrixDrawShapes2 : public RgbMatrixContainer
{
public:
  RgbMatrixDrawShapes2(RgbMatrix *m) : RgbMatrixContainer(m) {}

  void run()
  {
    Color red;
    red.red = 255;

    Color green;
    green.green = 255;

    Color blue;
    blue.blue = 255;

    Color purple;
    purple.red = 135;
    purple.blue = 255;

    Color yellow;
    yellow.red = 255;
    yellow.green = 255;

    Color turquoise;
    turquoise.green = 255;
    turquoise.blue = 255;

    Color white;
    white.red = 255;
    white.green = 255;
    white.blue = 255;

    // Draw some shapes
    _matrix->drawRect(1, 1, 8, 8, blue);
    _matrix->fillRect(2, 2, 6, 6, red);

    _matrix->drawCircle(14, 5, 4, red);
    _matrix->fillCircle(14, 5, 3, blue);

    _matrix->drawTriangle(25, 1, 30, 8, 20, 8, green);
    _matrix->fillTriangle(25, 2, 29, 7, 21, 7, yellow);

    _matrix->fillRect(1, 11, 9, 6, purple);

    _matrix->drawRoundRect(11, 11, 10, 6, 2, yellow);
    _matrix->fillRoundRect(12, 12, 8, 4, 0, white);

    _matrix->fillCircleHalf(26, 14, 4, 1, 0, turquoise);
    _matrix->fillCircleHalf(26, 14, 4, 2, 0, purple);

    // Write some text
    _matrix->setTextCursor(1, 19);
    _matrix->setFontSize(2); // Medium (4x6) Font
    _matrix->setFontColor(green);
    _matrix->writeLetter('F');
    _matrix->writeLetter('i');
    _matrix->writeLetter('l');
    _matrix->writeLetter('l');
    _matrix->writeLetter('e');
    _matrix->writeLetter('d');

    _matrix->setTextCursor(1, 26);
    _matrix->setFontColor(blue);
    _matrix->writeLetter('S');
    _matrix->writeLetter('h');
    _matrix->writeLetter('a');
    _matrix->writeLetter('p');
    _matrix->writeLetter('e');
    _matrix->writeLetter('s');
  }

};

// Cycle through colors and pulse the entire matrix the same color.
class RgbMatrixPulsePixels : public RgbMatrixContainer
{
public:
  RgbMatrixPulsePixels(RgbMatrix *m) : RgbMatrixContainer(m) {}

  void run()
  {
    uint32_t count = 0;

    while (!isDone())
    {
      count++;

      int color = (count >> 9) % 7;
      int value = count & 0xFF;

      if (count & 0x100) value = 255 - value;

      int r, g, b;

      switch (color)
      {
        case 0: r = value; g = b = 0; break;
        case 1: g = value; r = b = 0; break;
        case 2: b = value; r = g = 0; break;
        case 3: r = g = value; b = 0; break;
        case 4: r = b = value; g = 0; break;
        case 5: g = b = value; r = 0; break;
        default: r = g = b = value; break;
      }

      Color pulse;
      pulse.red = r;
      pulse.green = g;
      pulse.blue = b;

      _matrix->fillScreen(pulse);

      usleep(5000);
    }
  }

};

// Cycle through colors and pulse the matrix in a gradient pattern.
class RgbMatrixPulsePixelsGradient : public RgbMatrixContainer
{
public:
  RgbMatrixPulsePixelsGradient(RgbMatrix *m) : RgbMatrixContainer(m) {}

  void run()
  {
    uint32_t count = 0;

    while (!isDone())
    {
      count++;

      int color = (count >> 9) % 7; //512 steps for each color (256 up / 256 down)
      int value = count & 0xFF;

      if (count & 0x100) value = 255 - value; // pulse down

      int r, g, b;

      switch (color)
      {
        case 0: r = value; g = b = 0; break;
        case 1: g = value; r = b = 0; break;
        case 2: b = value; r = g = 0; break;
        case 3: r = g = value; b = 0; break;
        case 4: r = b = value; g = 0; break;
        case 5: g = b = value; r = 0; break;
        default: r = g = b = value; break;
      }

      for (int i=0; i < 32; i++)
      {
        Color iColor;
        iColor.red   = (((i+1) * 8) > r) ? r : 0;
        iColor.green = (((i+1) * 8) > g) ? g : 0;
        iColor.blue  = (((i+1) * 8) > b) ? b : 0;

        _matrix->drawRect(0, i, 32, 1, iColor);
      }

      usleep(2500);
    }
  }

};

// Draw a color wheel on the matrix.
class RgbMatrixColorWheel : public RgbMatrixContainer
{
public:
  RgbMatrixColorWheel(RgbMatrix *m) : RgbMatrixContainer(m) {}

  void run()
  {
    _matrix->drawColorWheel();
  }
};

//-----------------------------------------------------------------------------
// Display a menu and allow choosing different demos.

RgbMatrix *m = NULL;

RgbMatrixContainer *display = NULL;
RgbMatrixContainer *updater = NULL;

void displayMenu()
{
  std::system("clear");
  printf("      |------------------------------------------------|\n");
  printf("      |     Select an option from the menu below:      |\n");
  printf("      |------------------------------------------------|\n");
  printf("      |      (1) Draw Simple Shapes                    |\n");
  printf("      |      (2) Draw and Fill Shapes                  |\n");
  printf("      |      (3) Pulse All Pixels                      |\n");
  printf("      |      (4) Pulse Pixels with a Gradient          |\n");
  printf("      |      (5) Draw a Color Wheel                    |\n");
  printf("      |      (6) Quit                                  |\n");
  printf("      |------------------------------------------------|\n");
  printf("                   Your Choice: ");
}

void runDemo()
{
  updater->start(10);
  display->start();

  printf("Press <RETURN> when done viewing demo.\n");
  getchar();

  delete display;
  delete updater;

  display = NULL;
  updater = NULL;

  m->clearDisplay();
  m->updateDisplay();
}

int main(int argc, char *argv[])
{
  GpioProxy io;

  if (!io.initialize())
    return 1;

  m = new RgbMatrix(&io);

  char choice = '1';

  while (choice != '6' && choice != 'q' && choice != 'Q')
  {
    displayMenu();

    choice = getchar();
    getchar(); //consume the \n

    switch (choice)
    {
      case '1':
        display = new RgbMatrixDrawShapes1(m);
        updater = new DisplayUpdater(m);
        printf("\n\nRunning Demo #1.\n\n");
        runDemo();
        break;

      case '2':
        display = new RgbMatrixDrawShapes2(m);
        updater = new DisplayUpdater(m);
        printf("\n\nRunning Demo #2.\n\n");
        runDemo();
        break;

      case '3':
        display = new RgbMatrixPulsePixels(m);
        updater = new DisplayUpdater(m);
        printf("\n\nRunning Demo #3.\n\n");
        runDemo();
        break;

      case '4':
        display = new RgbMatrixPulsePixelsGradient(m);
        updater = new DisplayUpdater(m);
        printf("\n\nRunning Demo #4.\n\n");
        runDemo();
        break;

      case '5':
        display = new RgbMatrixColorWheel(m);
        updater = new DisplayUpdater(m);
        printf("\n\nRunning Demo #5.\n\n");
        runDemo();
        break;

      case '6':
      case 'q':
      case 'Q':
        printf("\n\nHave a nice day!\n\n");
        break;

      default:
        break;
    }
  }

  // Stop threads and wait for them to join.
  if (display) delete display;
  if (updater) delete updater;

  // Clear and refresh the display.
  m->clearDisplay();
  m->updateDisplay();

  delete m;

  return 0;
}

<|endoftext|>


<commit_before>/*
 * appctorsdtors.cpp
 *
 *  Created on: 30 janv. 2013
 *      Author: fsulima
 */

#include <stdio.h>

class CtorDtorExample {
protected:
	int field1;
public:
	CtorDtorExample(int i) : field1(i) {
		printf("CtorDtorExample %p,%x constructor.\n", this, field1);
	}
	~CtorDtorExample() {
		printf("CtorDtorExample %p,%x destructor.\n", this, field1);
	}
};

static CtorDtorExample obj1(1);

int main (int argc, char **argv) {
	static CtorDtorExample obj2(2);
	printf("CtorDtorExample main\n");
}
<commit_msg>tests: cxx: Remove appctordtor example<commit_after><|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
//  tbMgr.cc
//-----------------------------------------------------------------------------
#include "Pre.h"
#include "tbMgr.h"
#include "Core/Core.h"
#include "Core/RunLoop.h"
#include "IO/Core/URLBuilder.h"
#include "Gfx/Gfx.h"
#include "Input/Input.h"
#include "animation/tb_widget_animation.h"
#include "tb_font_renderer.h"

void register_tbbf_font_renderer();

using namespace tb;

namespace Oryol {
namespace _priv {

//-----------------------------------------------------------------------------
tbMgr::~tbMgr() {
    o_assert(!this->IsValid());
}

//-----------------------------------------------------------------------------
void
tbMgr::Setup(const TBUISetup& setup) {
    o_assert_dbg(!this->IsValid());
    o_assert_dbg(setup.DefaultSkin.IsValid());
    o_assert_dbg(!setup.Fonts.Empty());
    o_assert_dbg(setup.DefaultFontName.IsValid());

    // initialize turbobadger
    this->renderer = Memory::New<tbOryolBatchRenderer>();
    this->renderer->Setup();
	tb_core_init(this->renderer, setup.Locale.AsCStr());

    // initialize turbobadger skin
    if (!g_tb_skin->Load(setup.DefaultSkin.AsCStr(), setup.OverrideSkin.AsCStr())) {
        o_error("tbMgr::Setup(): Failed to load skins!");
    }

    // use turbobadger's built-in font renderer
    register_tbbf_font_renderer();

    // setup fonts
    for (const auto& font : setup.Fonts) {
        g_font_manager->AddFontInfo(font.Location.AsCStr(), font.Name.AsCStr());
    }
    TBFontDescription fontDesc;
    fontDesc.SetID(TBIDC(setup.DefaultFontName.AsCStr()));
    fontDesc.SetSize(g_tb_skin->GetDimensionConverter()->DpToPx(setup.DefaultFontSize));
    g_font_manager->SetDefaultFontDescription(fontDesc);
    TBFontFace* font = g_font_manager->CreateFontFace(g_font_manager->GetDefaultFontDescription());
    if (font) {
        font->RenderGlyphs(setup.GlyphSet.AsCStr());
    }

    // input event handlers
    Input::SubscribeMouse([this](const Mouse::Event& e) {
        switch (e.Type) {
            case Mouse::Event::Move:
                this->onMouseMove((int)e.Position.x, (int)e.Position.y);
                break;
            case Mouse::Event::ButtonDown:
                this->onMouseButton(e.Button, true);
                break;
            case Mouse::Event::ButtonUp:
                this->onMouseButton(e.Button, false);
                break;
            case Mouse::Event::Scroll:
                this->onScroll((int)e.ScrollMovement.x, (int)e.ScrollMovement.y);
                break;
            default:
                break;
        }
    });
    Input::SubscribeKeyboard([this](const Keyboard::Event& e) {
        switch (e.Type) {
            case Keyboard::Event::KeyDown:
            case Keyboard::Event::KeyRepeat:
                this->onKey(e.KeyCode, true, false);
                break;
            case Keyboard::Event::KeyUp:
                this->onKey(e.KeyCode, false, true);
                break;
            case Keyboard::Event::WChar:
                this->onWChar(e.WCharCode);
                break;
            default:
                break;
        }
    });
    Input::SubscribeTouchpad([this](const Touchpad::Event& e) {
        switch (e.Type) {
            case Touchpad::Event::Tapped:
                this->onTapped(e.Position[0]);
                break;
            case Touchpad::Event::PanningStarted:
                this->onPanningStarted(e.StartPosition[0]);
                break;
            case Touchpad::Event::Panning:
                this->onPanning(e.Position[0]);
                break;
            case Touchpad::Event::PanningEnded:
                this->onPanningEnded(e.Position[0]);
                break;
            default:
                break;
        }
    });

    // add per-frame update method
    Core::PostRunLoop()->Add([this] {
        this->update();
    });

    TBWidgetsAnimationManager::Init();

    this->isValid = true;
}

//-----------------------------------------------------------------------------
void
tbMgr::Discard() {
    o_assert_dbg(this->IsValid());

    TBWidgetsAnimationManager::Shutdown();

    tb_core_shutdown();

    this->renderer->Discard();
    Memory::Delete(this->renderer);

    this->isValid = false;
}

//-----------------------------------------------------------------------------
bool
tbMgr::IsValid() const {
    return this->isValid;
}

//-----------------------------------------------------------------------------
void
tbMgr::update() {
    this->rootWidget.InvokeProcessStates();
    this->rootWidget.InvokeProcess();

    // send a release for each tap
    glm::vec2 pos;
    while (!this->touchTaps.Empty()) {
        this->touchTaps.Dequeue(pos);
        this->rootWidget.InvokePointerUp((int)pos.x, (int)pos.y, this->modifierKeys, true);
    }
}

//-----------------------------------------------------------------------------
void
tbMgr::Draw() {
    o_assert_dbg(this->IsValid());
    o_assert_dbg(this->renderer);

    const DisplayAttrs& disp = Gfx::RenderTargetAttrs();
    this->rootWidget.SetRect(TBRect(0, 0, disp.FramebufferWidth, disp.FramebufferHeight));

    TBAnimationManager::Update();

    this->renderer->BeginPaint(disp.FramebufferWidth, disp.FramebufferHeight);
    this->rootWidget.InvokePaint(TBWidget::PaintProps());
    this->renderer->EndPaint();

    // if animations are running, reinvalidate immediately
    if (TBAnimationManager::HasAnimationsRunning()) {
        this->rootWidget.Invalidate();
    }
}

//-----------------------------------------------------------------------------
tbOryolRootWidget*
tbMgr::GetRootWidget() {
    o_assert_dbg(this->IsValid());
    return &this->rootWidget;
}

//-----------------------------------------------------------------------------
void
tbMgr::onMouseMove(int posX, int posY) {
    this->mouseX = posX;
    this->mouseY = posY;
    this->rootWidget.InvokePointerMove(this->mouseX, this->mouseY, this->modifierKeys, false);
}

//-----------------------------------------------------------------------------
void
tbMgr::onMouseButton(Mouse::Button btn, bool down) {
    if (btn == Mouse::LMB) {
        if (down) {
            this->rootWidget.InvokePointerDown(this->mouseX, this->mouseY, 1, this->modifierKeys, false);
        }
        else {
            this->rootWidget.InvokePointerUp(this->mouseX, this->mouseY, this->modifierKeys, false);
        }
    }
    else if (btn == Mouse::RMB) {
        this->rootWidget.InvokePointerMove(this->mouseX, this->mouseY, this->modifierKeys, false);
        if (TBWidget::hovered_widget)
        {
            TBWidget::hovered_widget->ConvertFromRoot(this->mouseX, this->mouseY);
            TBWidgetEvent ev(EVENT_TYPE_CONTEXT_MENU, this->mouseX, this->mouseY, false, this->modifierKeys);
            TBWidget::hovered_widget->InvokeEvent(ev);
        }
    }
}

//-----------------------------------------------------------------------------
void
tbMgr::onTapped(const glm::vec2& pos) {
    this->touchTaps.Enqueue(pos);
    this->rootWidget.InvokePointerDown((int)pos.x, (int)pos.y, 1, this->modifierKeys, true);
}

//-----------------------------------------------------------------------------
void
tbMgr::onPanningStarted(const glm::vec2& pos) {
    this->rootWidget.InvokePointerDown((int)pos.x, (int)pos.y, 1, this->modifierKeys, true);
}

//-----------------------------------------------------------------------------
void
tbMgr::onPanningEnded(const glm::vec2& pos) {
    this->rootWidget.InvokePointerUp((int)pos.x, (int)pos.y, this->modifierKeys, true);
}

//-----------------------------------------------------------------------------
void
tbMgr::onPanning(const glm::vec2& pos) {
    this->rootWidget.InvokePointerMove((int)pos.x, (int)pos.y, this->modifierKeys, true);
}

//-----------------------------------------------------------------------------
void
tbMgr::onScroll(int wheelX, int wheelY) {
    this->rootWidget.InvokeWheel(this->mouseX, this->mouseY, wheelX, wheelY, this->modifierKeys);
}

//-----------------------------------------------------------------------------
static int
toupr_ascii(int ascii)
{
    if (ascii >= 'a' && ascii <= 'z') {
        return ascii + 'A' - 'a';
    }
    return ascii;
}

//-----------------------------------------------------------------------------
static bool
invokeShortcut(int key, SPECIAL_KEY specialKey, MODIFIER_KEYS modifierKeys, bool down) {

    #ifdef FIPS_OSX
    bool shortcut_key = (modifierKeys & TB_SUPER) ? true : false;
    #else
    bool shortcut_key = (modifierKeys & TB_CTRL) ? true : false;
    #endif
    if (!TBWidget::focused_widget || !down || !shortcut_key) {
        return false;
    }
    bool reverse_key = (modifierKeys & TB_SHIFT) ? true : false;
    int upper_key = toupr_ascii(key);
    TBID id;
    if (upper_key == 'X') {
        id = TBIDC("cut");
    }
    else if (upper_key == 'C' || specialKey == TB_KEY_INSERT) {
        id = TBIDC("copy");
    }
    else if (upper_key == 'V' || (specialKey == TB_KEY_INSERT && reverse_key)) {
        id = TBIDC("paste");
    }
    else if (upper_key == 'A') {
        id = TBIDC("selectall");
    }
    else if (upper_key == 'Z' || upper_key == 'Y') {
        bool undo = upper_key == 'Z';
        if (reverse_key) {
            undo = !undo;
        }
        id = undo ? TBIDC("undo") : TBIDC("redo");
    }
    else if (upper_key == 'N') {
        id = TBIDC("new");
    }
    else if (upper_key == 'O') {
        id = TBIDC("open");
    }
    else if (upper_key == 'S') {
        id = TBIDC("save");
    }
    else if (upper_key == 'W') {
        id = TBIDC("close");
    }
    else if (specialKey == TB_KEY_PAGE_UP) {
        id = TBIDC("prev_doc");
    }
    else if (specialKey == TB_KEY_PAGE_DOWN) {
        id = TBIDC("next_doc");
    }
    else {
        return false;
    }

    TBWidgetEvent ev(EVENT_TYPE_SHORTCUT);
    ev.modifierkeys = modifierKeys;
    ev.ref_id = id;
    return TBWidget::focused_widget->InvokeEvent(ev);
}

//-----------------------------------------------------------------------------
static bool
invokeKey(tbOryolRootWidget* rootWidget, unsigned int key, SPECIAL_KEY specialKey, MODIFIER_KEYS modifierKeys, bool down)
{
    if (invokeShortcut(key, specialKey, modifierKeys, down)) {
        return true;
    }
    rootWidget->InvokeKey(key, specialKey, modifierKeys, down);
    return true;
}

//-----------------------------------------------------------------------------
void
tbMgr::onWChar(wchar_t c) {
    if ((c >= 0xE000) && (c <= 0xF8FF)) {
        return;
    }
    invokeKey(&this->rootWidget, c, TB_KEY_UNDEFINED, this->modifierKeys, true);
    invokeKey(&this->rootWidget, c, TB_KEY_UNDEFINED, this->modifierKeys, false);
}

//-----------------------------------------------------------------------------
void
tbMgr::onKey(Key::Code key, bool down, bool up) {

    SPECIAL_KEY tbKey = TB_KEY_UNDEFINED;
    switch (key)
    {
        case Key::F1:       tbKey = TB_KEY_F1; break;
        case Key::F2:       tbKey = TB_KEY_F2; break;
        case Key::F3:       tbKey = TB_KEY_F3; break;
        case Key::F4:       tbKey = TB_KEY_F4; break;
        case Key::F5:       tbKey = TB_KEY_F5; break;
        case Key::F6:       tbKey = TB_KEY_F6; break;
        case Key::F7:       tbKey = TB_KEY_F7; break;
        case Key::F8:       tbKey = TB_KEY_F8; break;
        case Key::F9:       tbKey = TB_KEY_F9; break;
        case Key::F10:      tbKey = TB_KEY_F10; break;
        case Key::F11:      tbKey = TB_KEY_F11; break;
        case Key::F12:      tbKey = TB_KEY_F12; break;
        case Key::Left:     tbKey = TB_KEY_LEFT; break;
        case Key::Up:       tbKey = TB_KEY_UP; break;
        case Key::Right:    tbKey = TB_KEY_RIGHT; break;
        case Key::Down:     tbKey = TB_KEY_DOWN; break;
        case Key::PageUp:   tbKey = TB_KEY_PAGE_UP; break;
        case Key::PageDown: tbKey = TB_KEY_PAGE_DOWN; break;
        case Key::Home:     tbKey = TB_KEY_HOME; break;
        case Key::End:      tbKey = TB_KEY_END; break;
        case Key::Insert:   tbKey = TB_KEY_INSERT; break;
        case Key::Tab:      tbKey = TB_KEY_TAB; break;
        case Key::Delete:   tbKey = TB_KEY_DELETE; break;
        case Key::BackSpace:    tbKey = TB_KEY_BACKSPACE; break;
        case Key::Enter:
        case Key::NumEnter:
            tbKey = TB_KEY_ENTER; break;
        case Key::Escape:   tbKey = TB_KEY_ESC; break;
        case Key::Menu:
            if (TBWidget::focused_widget && !down) {
                TBWidgetEvent ev(EVENT_TYPE_CONTEXT_MENU);
                ev.modifierkeys = modifierKeys;
                TBWidget::focused_widget->InvokeEvent(ev);
            }
            break;
        case Key::LeftShift:
        case Key::RightShift:
            if (down) {
                this->modifierKeys |= TB_SHIFT;
            }
            else {
                this->modifierKeys &= ~TB_SHIFT;
            }
            break;
        case Key::LeftControl:
        case Key::RightControl:
            if (down) {
                this->modifierKeys |= TB_CTRL;
            }
            else {
                this->modifierKeys &= ~TB_CTRL;
            }
            break;
        case Key::LeftAlt:
        case Key::RightAlt:
            if (down) {
                this->modifierKeys |= TB_ALT;
            }
            else {
                this->modifierKeys &= ~TB_ALT;
            }
            break;
        case Key::LeftSuper:
        case Key::RightSuper:
            if (down) {
                this->modifierKeys |= TB_SUPER;
            }
            else {
                this->modifierKeys &= ~TB_SUPER;
            }
            break;
        default:
            break;
    }
    if (TB_KEY_UNDEFINED != tbKey) {
        invokeKey(&this->rootWidget, 0, tbKey, this->modifierKeys, down);
    }
}

} // namespace _priv
} // namespace Oryol

<commit_msg>Fix Turbobadger module to latest turbobadger API change.<commit_after>//-----------------------------------------------------------------------------
//  tbMgr.cc
//-----------------------------------------------------------------------------
#include "Pre.h"
#include "tbMgr.h"
#include "Core/Core.h"
#include "Core/RunLoop.h"
#include "IO/Core/URLBuilder.h"
#include "Gfx/Gfx.h"
#include "Input/Input.h"
#include "animation/tb_widget_animation.h"
#include "tb_font_renderer.h"
#include "tb_language.h"

void register_tbbf_font_renderer();

using namespace tb;

namespace Oryol {
namespace _priv {

//-----------------------------------------------------------------------------
tbMgr::~tbMgr() {
    o_assert(!this->IsValid());
}

//-----------------------------------------------------------------------------
void
tbMgr::Setup(const TBUISetup& setup) {
    o_assert_dbg(!this->IsValid());
    o_assert_dbg(setup.DefaultSkin.IsValid());
    o_assert_dbg(!setup.Fonts.Empty());
    o_assert_dbg(setup.DefaultFontName.IsValid());

    // initialize turbobadger
    this->renderer = Memory::New<tbOryolBatchRenderer>();
    this->renderer->Setup();
    tb_core_init(this->renderer);
    g_tb_lng->Load(setup.Locale.AsCStr());

    // initialize turbobadger skin
    if (!g_tb_skin->Load(setup.DefaultSkin.AsCStr(), setup.OverrideSkin.AsCStr())) {
        o_error("tbMgr::Setup(): Failed to load skins!");
    }

    // use turbobadger's built-in font renderer
    register_tbbf_font_renderer();

    // setup fonts
    for (const auto& font : setup.Fonts) {
        g_font_manager->AddFontInfo(font.Location.AsCStr(), font.Name.AsCStr());
    }
    TBFontDescription fontDesc;
    fontDesc.SetID(TBIDC(setup.DefaultFontName.AsCStr()));
    fontDesc.SetSize(g_tb_skin->GetDimensionConverter()->DpToPx(setup.DefaultFontSize));
    g_font_manager->SetDefaultFontDescription(fontDesc);
    TBFontFace* font = g_font_manager->CreateFontFace(g_font_manager->GetDefaultFontDescription());
    if (font) {
        font->RenderGlyphs(setup.GlyphSet.AsCStr());
    }

    // input event handlers
    Input::SubscribeMouse([this](const Mouse::Event& e) {
        switch (e.Type) {
            case Mouse::Event::Move:
                this->onMouseMove((int)e.Position.x, (int)e.Position.y);
                break;
            case Mouse::Event::ButtonDown:
                this->onMouseButton(e.Button, true);
                break;
            case Mouse::Event::ButtonUp:
                this->onMouseButton(e.Button, false);
                break;
            case Mouse::Event::Scroll:
                this->onScroll((int)e.ScrollMovement.x, (int)e.ScrollMovement.y);
                break;
            default:
                break;
        }
    });
    Input::SubscribeKeyboard([this](const Keyboard::Event& e) {
        switch (e.Type) {
            case Keyboard::Event::KeyDown:
            case Keyboard::Event::KeyRepeat:
                this->onKey(e.KeyCode, true, false);
                break;
            case Keyboard::Event::KeyUp:
                this->onKey(e.KeyCode, false, true);
                break;
            case Keyboard::Event::WChar:
                this->onWChar(e.WCharCode);
                break;
            default:
                break;
        }
    });
    Input::SubscribeTouchpad([this](const Touchpad::Event& e) {
        switch (e.Type) {
            case Touchpad::Event::Tapped:
                this->onTapped(e.Position[0]);
                break;
            case Touchpad::Event::PanningStarted:
                this->onPanningStarted(e.StartPosition[0]);
                break;
            case Touchpad::Event::Panning:
                this->onPanning(e.Position[0]);
                break;
            case Touchpad::Event::PanningEnded:
                this->onPanningEnded(e.Position[0]);
                break;
            default:
                break;
        }
    });

    // add per-frame update method
    Core::PostRunLoop()->Add([this] {
        this->update();
    });

    TBWidgetsAnimationManager::Init();

    this->isValid = true;
}

//-----------------------------------------------------------------------------
void
tbMgr::Discard() {
    o_assert_dbg(this->IsValid());

    TBWidgetsAnimationManager::Shutdown();

    tb_core_shutdown();

    this->renderer->Discard();
    Memory::Delete(this->renderer);

    this->isValid = false;
}

//-----------------------------------------------------------------------------
bool
tbMgr::IsValid() const {
    return this->isValid;
}

//-----------------------------------------------------------------------------
void
tbMgr::update() {
    this->rootWidget.InvokeProcessStates();
    this->rootWidget.InvokeProcess();

    // send a release for each tap
    glm::vec2 pos;
    while (!this->touchTaps.Empty()) {
        this->touchTaps.Dequeue(pos);
        this->rootWidget.InvokePointerUp((int)pos.x, (int)pos.y, this->modifierKeys, true);
    }
}

//-----------------------------------------------------------------------------
void
tbMgr::Draw() {
    o_assert_dbg(this->IsValid());
    o_assert_dbg(this->renderer);

    const DisplayAttrs& disp = Gfx::RenderTargetAttrs();
    this->rootWidget.SetRect(TBRect(0, 0, disp.FramebufferWidth, disp.FramebufferHeight));

    TBAnimationManager::Update();

    this->renderer->BeginPaint(disp.FramebufferWidth, disp.FramebufferHeight);
    this->rootWidget.InvokePaint(TBWidget::PaintProps());
    this->renderer->EndPaint();

    // if animations are running, reinvalidate immediately
    if (TBAnimationManager::HasAnimationsRunning()) {
        this->rootWidget.Invalidate();
    }
}

//-----------------------------------------------------------------------------
tbOryolRootWidget*
tbMgr::GetRootWidget() {
    o_assert_dbg(this->IsValid());
    return &this->rootWidget;
}

//-----------------------------------------------------------------------------
void
tbMgr::onMouseMove(int posX, int posY) {
    this->mouseX = posX;
    this->mouseY = posY;
    this->rootWidget.InvokePointerMove(this->mouseX, this->mouseY, this->modifierKeys, false);
}

//-----------------------------------------------------------------------------
void
tbMgr::onMouseButton(Mouse::Button btn, bool down) {
    if (btn == Mouse::LMB) {
        if (down) {
            this->rootWidget.InvokePointerDown(this->mouseX, this->mouseY, 1, this->modifierKeys, false);
        }
        else {
            this->rootWidget.InvokePointerUp(this->mouseX, this->mouseY, this->modifierKeys, false);
        }
    }
    else if (btn == Mouse::RMB) {
        this->rootWidget.InvokePointerMove(this->mouseX, this->mouseY, this->modifierKeys, false);
        if (TBWidget::hovered_widget)
        {
            TBWidget::hovered_widget->ConvertFromRoot(this->mouseX, this->mouseY);
            TBWidgetEvent ev(EVENT_TYPE_CONTEXT_MENU, this->mouseX, this->mouseY, false, this->modifierKeys);
            TBWidget::hovered_widget->InvokeEvent(ev);
        }
    }
}

//-----------------------------------------------------------------------------
void
tbMgr::onTapped(const glm::vec2& pos) {
    this->touchTaps.Enqueue(pos);
    this->rootWidget.InvokePointerDown((int)pos.x, (int)pos.y, 1, this->modifierKeys, true);
}

//-----------------------------------------------------------------------------
void
tbMgr::onPanningStarted(const glm::vec2& pos) {
    this->rootWidget.InvokePointerDown((int)pos.x, (int)pos.y, 1, this->modifierKeys, true);
}

//-----------------------------------------------------------------------------
void
tbMgr::onPanningEnded(const glm::vec2& pos) {
    this->rootWidget.InvokePointerUp((int)pos.x, (int)pos.y, this->modifierKeys, true);
}

//-----------------------------------------------------------------------------
void
tbMgr::onPanning(const glm::vec2& pos) {
    this->rootWidget.InvokePointerMove((int)pos.x, (int)pos.y, this->modifierKeys, true);
}

//-----------------------------------------------------------------------------
void
tbMgr::onScroll(int wheelX, int wheelY) {
    this->rootWidget.InvokeWheel(this->mouseX, this->mouseY, wheelX, wheelY, this->modifierKeys);
}

//-----------------------------------------------------------------------------
static int
toupr_ascii(int ascii)
{
    if (ascii >= 'a' && ascii <= 'z') {
        return ascii + 'A' - 'a';
    }
    return ascii;
}

//-----------------------------------------------------------------------------
static bool
invokeShortcut(int key, SPECIAL_KEY specialKey, MODIFIER_KEYS modifierKeys, bool down) {

    #ifdef FIPS_OSX
    bool shortcut_key = (modifierKeys & TB_SUPER) ? true : false;
    #else
    bool shortcut_key = (modifierKeys & TB_CTRL) ? true : false;
    #endif
    if (!TBWidget::focused_widget || !down || !shortcut_key) {
        return false;
    }
    bool reverse_key = (modifierKeys & TB_SHIFT) ? true : false;
    int upper_key = toupr_ascii(key);
    TBID id;
    if (upper_key == 'X') {
        id = TBIDC("cut");
    }
    else if (upper_key == 'C' || specialKey == TB_KEY_INSERT) {
        id = TBIDC("copy");
    }
    else if (upper_key == 'V' || (specialKey == TB_KEY_INSERT && reverse_key)) {
        id = TBIDC("paste");
    }
    else if (upper_key == 'A') {
        id = TBIDC("selectall");
    }
    else if (upper_key == 'Z' || upper_key == 'Y') {
        bool undo = upper_key == 'Z';
        if (reverse_key) {
            undo = !undo;
        }
        id = undo ? TBIDC("undo") : TBIDC("redo");
    }
    else if (upper_key == 'N') {
        id = TBIDC("new");
    }
    else if (upper_key == 'O') {
        id = TBIDC("open");
    }
    else if (upper_key == 'S') {
        id = TBIDC("save");
    }
    else if (upper_key == 'W') {
        id = TBIDC("close");
    }
    else if (specialKey == TB_KEY_PAGE_UP) {
        id = TBIDC("prev_doc");
    }
    else if (specialKey == TB_KEY_PAGE_DOWN) {
        id = TBIDC("next_doc");
    }
    else {
        return false;
    }

    TBWidgetEvent ev(EVENT_TYPE_SHORTCUT);
    ev.modifierkeys = modifierKeys;
    ev.ref_id = id;
    return TBWidget::focused_widget->InvokeEvent(ev);
}

//-----------------------------------------------------------------------------
static bool
invokeKey(tbOryolRootWidget* rootWidget, unsigned int key, SPECIAL_KEY specialKey, MODIFIER_KEYS modifierKeys, bool down)
{
    if (invokeShortcut(key, specialKey, modifierKeys, down)) {
        return true;
    }
    rootWidget->InvokeKey(key, specialKey, modifierKeys, down);
    return true;
}

//-----------------------------------------------------------------------------
void
tbMgr::onWChar(wchar_t c) {
    if ((c >= 0xE000) && (c <= 0xF8FF)) {
        return;
    }
    invokeKey(&this->rootWidget, c, TB_KEY_UNDEFINED, this->modifierKeys, true);
    invokeKey(&this->rootWidget, c, TB_KEY_UNDEFINED, this->modifierKeys, false);
}

//-----------------------------------------------------------------------------
void
tbMgr::onKey(Key::Code key, bool down, bool up) {

    SPECIAL_KEY tbKey = TB_KEY_UNDEFINED;
    switch (key)
    {
        case Key::F1:       tbKey = TB_KEY_F1; break;
        case Key::F2:       tbKey = TB_KEY_F2; break;
        case Key::F3:       tbKey = TB_KEY_F3; break;
        case Key::F4:       tbKey = TB_KEY_F4; break;
        case Key::F5:       tbKey = TB_KEY_F5; break;
        case Key::F6:       tbKey = TB_KEY_F6; break;
        case Key::F7:       tbKey = TB_KEY_F7; break;
        case Key::F8:       tbKey = TB_KEY_F8; break;
        case Key::F9:       tbKey = TB_KEY_F9; break;
        case Key::F10:      tbKey = TB_KEY_F10; break;
        case Key::F11:      tbKey = TB_KEY_F11; break;
        case Key::F12:      tbKey = TB_KEY_F12; break;
        case Key::Left:     tbKey = TB_KEY_LEFT; break;
        case Key::Up:       tbKey = TB_KEY_UP; break;
        case Key::Right:    tbKey = TB_KEY_RIGHT; break;
        case Key::Down:     tbKey = TB_KEY_DOWN; break;
        case Key::PageUp:   tbKey = TB_KEY_PAGE_UP; break;
        case Key::PageDown: tbKey = TB_KEY_PAGE_DOWN; break;
        case Key::Home:     tbKey = TB_KEY_HOME; break;
        case Key::End:      tbKey = TB_KEY_END; break;
        case Key::Insert:   tbKey = TB_KEY_INSERT; break;
        case Key::Tab:      tbKey = TB_KEY_TAB; break;
        case Key::Delete:   tbKey = TB_KEY_DELETE; break;
        case Key::BackSpace:    tbKey = TB_KEY_BACKSPACE; break;
        case Key::Enter:
        case Key::NumEnter:
            tbKey = TB_KEY_ENTER; break;
        case Key::Escape:   tbKey = TB_KEY_ESC; break;
        case Key::Menu:
            if (TBWidget::focused_widget && !down) {
                TBWidgetEvent ev(EVENT_TYPE_CONTEXT_MENU);
                ev.modifierkeys = modifierKeys;
                TBWidget::focused_widget->InvokeEvent(ev);
            }
            break;
        case Key::LeftShift:
        case Key::RightShift:
            if (down) {
                this->modifierKeys |= TB_SHIFT;
            }
            else {
                this->modifierKeys &= ~TB_SHIFT;
            }
            break;
        case Key::LeftControl:
        case Key::RightControl:
            if (down) {
                this->modifierKeys |= TB_CTRL;
            }
            else {
                this->modifierKeys &= ~TB_CTRL;
            }
            break;
        case Key::LeftAlt:
        case Key::RightAlt:
            if (down) {
                this->modifierKeys |= TB_ALT;
            }
            else {
                this->modifierKeys &= ~TB_ALT;
            }
            break;
        case Key::LeftSuper:
        case Key::RightSuper:
            if (down) {
                this->modifierKeys |= TB_SUPER;
            }
            else {
                this->modifierKeys &= ~TB_SUPER;
            }
            break;
        default:
            break;
    }
    if (TB_KEY_UNDEFINED != tbKey) {
        invokeKey(&this->rootWidget, 0, tbKey, this->modifierKeys, down);
    }
}

} // namespace _priv
} // namespace Oryol

<|endoftext|>


<commit_before>//
// Copyright(c) 2016-2017 benikabocha.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

#include <Saba/Base/UnicodeUtil.h>
#include <Saba/Base/Path.h>
#include <Saba/Model/MMD/MMDModel.h>
#include <Saba/Model/MMD/PMDModel.h>
#include <Saba/Model/MMD/PMXModel.h>
#include <Saba/Model/MMD/VMDFile.h>
#include <Saba/Model/MMD/VMDAnimation.h>

#include <iostream>
#include <vector>
#include <string>
#include <memory>

void Usage()
{
	std::cout << "mmd2obj <pmd/pmx file> [-vmd <vmd file>] [-t <animation time (sec)>]\n";
}

bool MMD2Obj(const std::vector<std::string>& args)
{
	if (args.size() <= 1)
	{
		Usage();
		return false;
	}

	// Analyze commad line.
	const std::string& modelPath = args[1];
	std::vector<std::string> vmdPaths;
	double	animTime = 0.0;

	for (size_t i = 2; i < args.size(); i++)
	{
		if (args[i] == "-vmd")
		{
			i++;
			if (i < args.size())
			{
				vmdPaths.push_back(args[i]);
			}
			else
			{
				Usage();
				return false;
			}
		}
		else if (args[i] == "-t")
		{
			i++;
			if (i < args.size())
			{
				animTime = std::stod(args[i]);
			}
			else
			{
				Usage();
				return false;
			}
		}
		else
		{
			Usage();
			return false;
		}
	}

	// Load model.
	std::shared_ptr<saba::MMDModel> mmdModel;
	std::string mmdDataPath = "";	// Set MMD data path(default toon texture path).
	std::string ext = saba::PathUtil::GetExt(modelPath);
	if (ext == "pmd")
	{
		auto pmdModel = std::make_unique<saba::PMDModel>();
		if (!pmdModel->Load(modelPath, mmdDataPath))
		{
			std::cout << "Load PMDModel Fail.\n";
			return false;
		}
		mmdModel = std::move(pmdModel);
	}
	else if (ext == "pmx")
	{
		auto pmxModel = std::make_unique<saba::PMXModel>();
		if (!pmxModel->Load(modelPath, mmdDataPath))
		{
			std::cout << "Load PMXModel Fail.\n";
			return false;
		}
		mmdModel = std::move(pmxModel);
	}
	else
	{
		std::cout << "Unsupported Model Ext : " << ext << "\n";
		return false;
	}

	// Load animation.
	auto vmdAnim = std::make_unique<saba::VMDAnimation>();
	if (!vmdAnim->Create(mmdModel))
	{
		std::cout << "Create VMDAnimation Fail.\n";
		return false;
	}
	for (const auto& vmdPath : vmdPaths)
	{
		saba::VMDFile vmdFile;
		if (!saba::ReadVMDFile(&vmdFile, vmdPath.c_str()))
		{
			std::cout << "Read VMD File Fail.\n";
			return false;
		}
		if (!vmdAnim->Add(vmdFile))
		{
			std::cout << "Add VMDAnimation Fail.\n";
			return false;
		}
	}

	// Initialize pose.
	{
		// Sync physics animation.
		mmdModel->InitializeAnimation();
		vmdAnim->SyncPhysics((float)animTime * 30.0f);
	}

	// Update animation(animation loop).
	{
		// Update bone animation.
		mmdModel->BeginAnimation();
		vmdAnim->Evaluate((float)animTime * 30.0f);
		mmdModel->UpdateAnimation();
		mmdModel->EndAnimation();

		// Update physics animation.
		mmdModel->UpdatePhysics(1.0f / 60.0f);

		// Update vertex.
		mmdModel->Update();
	}

	// Output OBJ file.
	std::ofstream objFile;
	objFile.open("output.obj");
	if (!objFile.is_open())
	{
		std::cout << "Open OBJ File Fail.\n";
		return false;
	}
	objFile << "# mmmd2obj\n";
	objFile << "mtllib output.mtl\n";

	// Write positions.
	size_t vtxCount = mmdModel->GetVertexCount();
	const glm::vec3* positions = mmdModel->GetUpdatePositions();
	for (size_t i = 0; i < vtxCount; i++)
	{
		objFile << "v " << positions[i].x << " " << positions[i].y << " " << positions[i].z << "\n";
	}
	const glm::vec3* normals = mmdModel->GetUpdateNormals();
	for (size_t i = 0; i < vtxCount; i++)
	{
		objFile << "vn " << normals[i].x << " " << normals[i].y << " " << normals[i].z << "\n";
	}
	const glm::vec2* uvs = mmdModel->GetUpdateUVs();
	for (size_t i = 0; i < vtxCount; i++)
	{
		objFile << "vt " << uvs[i].x << " " << uvs[i].y << "\n";
	}

	// Copy vertex indices.
	std::vector<size_t> indices(mmdModel->GetIndexCount());
	if (mmdModel->GetIndexElementSize() == 1)
	{
		uint8_t* mmdIndices = (uint8_t*)mmdModel->GetIndices();
		for (size_t i = 0; i < indices.size(); i++)
		{
			indices[i] = mmdIndices[i];
		}
	}
	else if (mmdModel->GetIndexElementSize() == 2)
	{
		uint16_t* mmdIndices = (uint16_t*)mmdModel->GetIndices();
		for (size_t i = 0; i < indices.size(); i++)
		{
			indices[i] = mmdIndices[i];
		}
	}
	else if (mmdModel->GetIndexElementSize() == 4)
	{
		uint32_t* mmdIndices = (uint32_t*)mmdModel->GetIndices();
		for (size_t i = 0; i < indices.size(); i++)
		{
			indices[i] = mmdIndices[i];
		}
	}
	else
	{
		return false;
	}

	// Write faces.
	size_t subMeshCount = mmdModel->GetSubMeshCount();
	const saba::MMDSubMesh* subMeshes = mmdModel->GetSubMeshes();
	for (size_t i = 0; i < subMeshCount; i++)
	{
		objFile << "\n";
		objFile << "usemtl " << subMeshes[i].m_materialID << "\n";

		for (size_t j = 0; j < subMeshes[i].m_vertexCount; j += 3)
		{
			auto vtxIdx = subMeshes[i].m_beginIndex + j;
			auto vi0 = indices[vtxIdx + 0] + 1;
			auto vi1 = indices[vtxIdx + 1] + 1;
			auto vi2 = indices[vtxIdx + 2] + 1;
			objFile << "f "
				<< vi0 << "/" << vi0 << "/" << vi0 << " "
				<< vi1 << "/" << vi1 << "/" << vi1 << " "
				<< vi2 << "/" << vi2 << "/" << vi2 << "\n";
		}
	}
	objFile.close();

	// Write materials.
	std::ofstream mtlFile;
	mtlFile.open("output.mtl");
	if (!mtlFile.is_open())
	{
		std::cout << "Open MTL File Fail.\n";
		return false;
	}

	objFile << "# mmmd2obj\n";
	size_t materialCount = mmdModel->GetMaterialCount();
	const saba::MMDMaterial* materials = mmdModel->GetMaterials();
	for (size_t i = 0; i < materialCount; i++)
	{
		const auto& m = materials[i];
		mtlFile << "newmtl " << i << "\n";

		mtlFile << "Ka " << m.m_ambient.r << " " << m.m_ambient.g << " " << m.m_ambient.b << "\n";
		mtlFile << "Kd " << m.m_diffuse.r << " " << m.m_diffuse.g << " " << m.m_diffuse.b << "\n";
		mtlFile << "Ks " << m.m_specular.r << " " << m.m_specular.g << " " << m.m_specular.b << "\n";
		mtlFile << "d " << m.m_alpha << "\n";
		mtlFile << "map_Kd " << m.m_texture << "\n";
		mtlFile << "\n";
	}
	mtlFile.close();

	return true;
}

#if _WIN32
int wmain(int argc, wchar_t** argv)
{
	std::vector<std::string> args(argc);
	for (int i = 0; i < argc; i++)
	{
		args[i] = saba::ToUtf8String(argv[i]);
	}

	if (!MMD2Obj(args))
	{
		std::cout << "Convert Fail.\n";
		return 1;
	}

	return 0;
}
#else // _WIN32
int main(int argc, char** argv)
{
	std::vector<std::string> args(argc);
	for (int i = 0; i < argc; i++)
	{
		args[i] = argv[i];
	}

	if (!MMD2Obj(args))
	{
		std::cout << "Convert Fail.\n";
		return 1;
	}

	return 0;
}
#endif // _WIN32<commit_msg>mmd2obj : add vpd support<commit_after>//
// Copyright(c) 2016-2017 benikabocha.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

#include <Saba/Base/UnicodeUtil.h>
#include <Saba/Base/Path.h>
#include <Saba/Model/MMD/MMDModel.h>
#include <Saba/Model/MMD/PMDModel.h>
#include <Saba/Model/MMD/PMXModel.h>
#include <Saba/Model/MMD/VMDFile.h>
#include <Saba/Model/MMD/VMDAnimation.h>
#include <Saba/Model/MMD/VPDFile.h>

#include <iostream>
#include <vector>
#include <string>
#include <memory>

void Usage()
{
	std::cout << "mmd2obj <pmd/pmx file> [-vmd <vmd file>] [-t <animation time (sec)>] [-vpd <vpd file>]\n";
}

bool MMD2Obj(const std::vector<std::string>& args)
{
	if (args.size() <= 1)
	{
		Usage();
		return false;
	}

	// Analyze commad line.
	const std::string& modelPath = args[1];
	std::vector<std::string> vmdPaths;
	std::string vpdPath;
	double	animTime = 0.0;

	for (size_t i = 2; i < args.size(); i++)
	{
		if (args[i] == "-vmd")
		{
			i++;
			if (i < args.size())
			{
				vmdPaths.push_back(args[i]);
			}
			else
			{
				Usage();
				return false;
			}
		}
		else if (args[i] == "-t")
		{
			i++;
			if (i < args.size())
			{
				animTime = std::stod(args[i]);
			}
			else
			{
				Usage();
				return false;
			}
		}
		else if (args[i] == "-vpd")
		{
			i++;
			if (i < args.size())
			{
				vpdPath = args[i];
			}
			else
			{
				Usage();
				return false;
			}
		}
		else
		{
			Usage();
			return false;
		}
	}

	// Load model.
	std::shared_ptr<saba::MMDModel> mmdModel;
	std::string mmdDataPath = "";	// Set MMD data path(default toon texture path).
	std::string ext = saba::PathUtil::GetExt(modelPath);
	if (ext == "pmd")
	{
		auto pmdModel = std::make_unique<saba::PMDModel>();
		if (!pmdModel->Load(modelPath, mmdDataPath))
		{
			std::cout << "Failed to load PMDModel.\n";
			return false;
		}
		mmdModel = std::move(pmdModel);
	}
	else if (ext == "pmx")
	{
		auto pmxModel = std::make_unique<saba::PMXModel>();
		if (!pmxModel->Load(modelPath, mmdDataPath))
		{
			std::cout << "Failed to load PMXModel.\n";
			return false;
		}
		mmdModel = std::move(pmxModel);
	}
	else
	{
		std::cout << "Unsupported Model Ext : " << ext << "\n";
		return false;
	}

	// Load animation.
	bool useVMDAnimation = !vmdPaths.empty();
	auto vmdAnim = std::make_unique<saba::VMDAnimation>();
	if (!vmdAnim->Create(mmdModel))
	{
		std::cout << "Failed to create VMDAnimation.\n";
		return false;
	}
	for (const auto& vmdPath : vmdPaths)
	{
		saba::VMDFile vmdFile;
		if (!saba::ReadVMDFile(&vmdFile, vmdPath.c_str()))
		{
			std::cout << "Failed to read VMD file.\n";
			return false;
		}
		if (!vmdAnim->Add(vmdFile))
		{
			std::cout << "Failed to add VMDAnimation.\n";
			return false;
		}
	}

	// Load pose.
	saba::VPDFile vpdFile;
	if (!vpdPath.empty())
	{
		if (!vmdPaths.empty())
		{
			std::cout << "Warning : Canceled to read VPD file.";
		}
		else
		{
			if (!saba::ReadVPDFile(&vpdFile, vpdPath.c_str()))
			{
				std::cout << "Failed to read VPD file.\n";
				return false;
			}

		}
	}

	// Initialize pose.
	{
		// Sync physics animation.
		mmdModel->InitializeAnimation();
		if (useVMDAnimation)
		{
			vmdAnim->SyncPhysics((float)animTime * 30.0f);
		}
		else
		{
			mmdModel->LoadPose(vpdFile);
		}
	}

	// Update animation(animation loop).
	{
		// Update bone animation.
		mmdModel->BeginAnimation();
		if (useVMDAnimation)
		{
			vmdAnim->Evaluate((float)animTime * 30.0f);
		}
		mmdModel->UpdateAnimation();
		mmdModel->EndAnimation();

		// Update physics animation.
		mmdModel->UpdatePhysics(1.0f / 60.0f);

		// Update vertex.
		mmdModel->Update();
	}

	// Output OBJ file.
	std::ofstream objFile;
	objFile.open("output.obj");
	if (!objFile.is_open())
	{
		std::cout << "Failed to open OBJ file.\n";
		return false;
	}
	objFile << "# mmmd2obj\n";
	objFile << "mtllib output.mtl\n";

	// Write positions.
	size_t vtxCount = mmdModel->GetVertexCount();
	const glm::vec3* positions = mmdModel->GetUpdatePositions();
	for (size_t i = 0; i < vtxCount; i++)
	{
		objFile << "v " << positions[i].x << " " << positions[i].y << " " << positions[i].z << "\n";
	}
	const glm::vec3* normals = mmdModel->GetUpdateNormals();
	for (size_t i = 0; i < vtxCount; i++)
	{
		objFile << "vn " << normals[i].x << " " << normals[i].y << " " << normals[i].z << "\n";
	}
	const glm::vec2* uvs = mmdModel->GetUpdateUVs();
	for (size_t i = 0; i < vtxCount; i++)
	{
		objFile << "vt " << uvs[i].x << " " << uvs[i].y << "\n";
	}

	// Copy vertex indices.
	std::vector<size_t> indices(mmdModel->GetIndexCount());
	if (mmdModel->GetIndexElementSize() == 1)
	{
		uint8_t* mmdIndices = (uint8_t*)mmdModel->GetIndices();
		for (size_t i = 0; i < indices.size(); i++)
		{
			indices[i] = mmdIndices[i];
		}
	}
	else if (mmdModel->GetIndexElementSize() == 2)
	{
		uint16_t* mmdIndices = (uint16_t*)mmdModel->GetIndices();
		for (size_t i = 0; i < indices.size(); i++)
		{
			indices[i] = mmdIndices[i];
		}
	}
	else if (mmdModel->GetIndexElementSize() == 4)
	{
		uint32_t* mmdIndices = (uint32_t*)mmdModel->GetIndices();
		for (size_t i = 0; i < indices.size(); i++)
		{
			indices[i] = mmdIndices[i];
		}
	}
	else
	{
		return false;
	}

	// Write faces.
	size_t subMeshCount = mmdModel->GetSubMeshCount();
	const saba::MMDSubMesh* subMeshes = mmdModel->GetSubMeshes();
	for (size_t i = 0; i < subMeshCount; i++)
	{
		objFile << "\n";
		objFile << "usemtl " << subMeshes[i].m_materialID << "\n";

		for (size_t j = 0; j < subMeshes[i].m_vertexCount; j += 3)
		{
			auto vtxIdx = subMeshes[i].m_beginIndex + j;
			auto vi0 = indices[vtxIdx + 0] + 1;
			auto vi1 = indices[vtxIdx + 1] + 1;
			auto vi2 = indices[vtxIdx + 2] + 1;
			objFile << "f "
				<< vi0 << "/" << vi0 << "/" << vi0 << " "
				<< vi1 << "/" << vi1 << "/" << vi1 << " "
				<< vi2 << "/" << vi2 << "/" << vi2 << "\n";
		}
	}
	objFile.close();

	// Write materials.
	std::ofstream mtlFile;
	mtlFile.open("output.mtl");
	if (!mtlFile.is_open())
	{
		std::cout << "Failed to open MTL file.\n";
		return false;
	}

	objFile << "# mmmd2obj\n";
	size_t materialCount = mmdModel->GetMaterialCount();
	const saba::MMDMaterial* materials = mmdModel->GetMaterials();
	for (size_t i = 0; i < materialCount; i++)
	{
		const auto& m = materials[i];
		mtlFile << "newmtl " << i << "\n";

		mtlFile << "Ka " << m.m_ambient.r << " " << m.m_ambient.g << " " << m.m_ambient.b << "\n";
		mtlFile << "Kd " << m.m_diffuse.r << " " << m.m_diffuse.g << " " << m.m_diffuse.b << "\n";
		mtlFile << "Ks " << m.m_specular.r << " " << m.m_specular.g << " " << m.m_specular.b << "\n";
		mtlFile << "d " << m.m_alpha << "\n";
		mtlFile << "map_Kd " << m.m_texture << "\n";
		mtlFile << "\n";
	}
	mtlFile.close();

	return true;
}

#if _WIN32
int wmain(int argc, wchar_t** argv)
{
	std::vector<std::string> args(argc);
	for (int i = 0; i < argc; i++)
	{
		args[i] = saba::ToUtf8String(argv[i]);
	}

	if (!MMD2Obj(args))
	{
		std::cout << "Failed to convert model data.\n";
		return 1;
	}

	return 0;
}
#else // _WIN32
int main(int argc, char** argv)
{
	std::vector<std::string> args(argc);
	for (int i = 0; i < argc; i++)
	{
		args[i] = argv[i];
	}

	if (!MMD2Obj(args))
	{
		std::cout << "Failed to convert model data.\n";
		return 1;
	}

	return 0;
}
#endif // _WIN32<|endoftext|>


<commit_before>/*

openfx-arena - https://github.com/olear/openfx-arena

Copyright (c) 2015, Ole-André Rodlie <olear@fxarena.net>
Copyright (c) 2015, FxArena DA <mail@fxarena.net>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Neither the name of FxArena DA nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "ReadPSD.h"
#include <iostream>
#include <string>
#include <Magick++.h>
#include "GenericReader.h"
#include "GenericOCIO.h"
#include "ofxsMacros.h"

#ifdef OFX_IO_USING_OCIO
#include <OpenColorIO/OpenColorIO.h>
#endif

#define kPluginName "ReadPSD"
#define kPluginGrouping "Image/Readers"
#define kPluginIdentifier "net.fxarena.openfx.ReadPSD"
#define kPluginVersionMajor 1
#define kPluginVersionMinor 6

#define kSupportsRGBA true
#define kSupportsRGB false
#define kSupportsAlpha false
#define kSupportsTiles false
#define kIsMultiPlanar true

class ReadPSDPlugin : public GenericReaderPlugin
{
public:
    ReadPSDPlugin(OfxImageEffectHandle handle);
    virtual ~ReadPSDPlugin();
private:
    virtual bool isVideoStream(const std::string& /*filename*/) OVERRIDE FINAL { return false; }
    virtual void decode(const std::string& filename, OfxTime time, const OfxRectI& renderWindow, float *pixelData, const OfxRectI& bounds,
                             OFX::PixelComponentEnum pixelComponents, int pixelComponentCount, int rowBytes) OVERRIDE FINAL
    {
        std::string rawComps;
        switch (pixelComponents) {
            case OFX::ePixelComponentAlpha:
                rawComps = kOfxImageComponentAlpha;
                break;
            case OFX::ePixelComponentRGB:
                rawComps = kOfxImageComponentRGB;
                break;
            case OFX::ePixelComponentRGBA:
                rawComps = kOfxImageComponentRGBA;
                break;
            default:
                OFX::throwSuiteStatusException(kOfxStatFailed);
                return;
        }
        decodePlane(filename, time, renderWindow, pixelData, bounds, pixelComponents, pixelComponentCount, rawComps, rowBytes);
    }
    virtual void getClipComponents(const OFX::ClipComponentsArguments& args, OFX::ClipComponentsSetter& clipComponents) OVERRIDE FINAL;
    virtual void decodePlane(const std::string& filename, OfxTime time, const OfxRectI& renderWindow, float *pixelData, const OfxRectI& bounds, OFX::PixelComponentEnum pixelComponents, int pixelComponentCount, const std::string& rawComponents, int rowBytes) OVERRIDE FINAL;
    virtual bool getFrameBounds(const std::string& filename, OfxTime time, OfxRectI *bounds, double *par, std::string *error) OVERRIDE FINAL;
    virtual void restoreState(const std::string& filename) OVERRIDE FINAL;
    virtual void onInputFileChanged(const std::string& newFile, OFX::PreMultiplicationEnum *premult, OFX::PixelComponentEnum *components, int *componentCount) OVERRIDE FINAL;
    std::string _filename;
    std::vector<Magick::Image> _psd;
};

ReadPSDPlugin::ReadPSDPlugin(OfxImageEffectHandle handle)
: GenericReaderPlugin(handle, kSupportsRGBA, kSupportsRGB, kSupportsAlpha, kSupportsTiles,
#ifdef OFX_EXTENSIONS_NUKE
(OFX::getImageEffectHostDescription() && OFX::getImageEffectHostDescription()->isMultiPlanar) ? kIsMultiPlanar : false
#else
false
#endif
)
{
    Magick::InitializeMagick(NULL);
    assert(_outputComponents);
}

ReadPSDPlugin::~ReadPSDPlugin()
{
}

void ReadPSDPlugin::getClipComponents(const OFX::ClipComponentsArguments& args, OFX::ClipComponentsSetter& clipComponents)
{
    #ifdef DEBUG
    std::cout << "getClipComponents ..." << std::endl;
    #endif
    assert(isMultiPlanar());
    clipComponents.addClipComponents(*_outputClip, getOutputComponents());
    clipComponents.setPassThroughClip(NULL, args.time, args.view);
    if (_psd.size()>0) {
        int startLayer = 0;
        if (_psd[0].format()=="Adobe Photoshop bitmap")
            startLayer++;
        for (int i = startLayer; i < (int)_psd.size(); i++) {
            std::ostringstream layerName;
            layerName << _psd[i].label();
            if (layerName.str().empty())
                layerName << "Image Layer #" << i; // add a label if empty
            std::string component(kNatronOfxImageComponentsPlane);
            component.append(layerName.str());
            component.append(kNatronOfxImageComponentsPlaneChannel);
            component.append("R");
            component.append(kNatronOfxImageComponentsPlaneChannel);
            component.append("G");
            component.append(kNatronOfxImageComponentsPlaneChannel);
            component.append("B");
            component.append(kNatronOfxImageComponentsPlaneChannel);
            component.append("A");
            clipComponents.addClipComponents(*_outputClip, component);
        }
    }
}

void ReadPSDPlugin::decodePlane(const std::string& /*filename*/, OfxTime /*time*/, const OfxRectI& /*renderWindow*/, float *pixelData, const OfxRectI& bounds,
                                 OFX::PixelComponentEnum /*pixelComponents*/, int /*pixelComponentCount*/, const std::string& rawComponents, int /*rowBytes*/)
{
    #ifdef DEBUG
    std::cout << "decodePlane ..." << std::endl;
    #endif
    int offsetX = 0;
    int offsetY = 0;
    int layer = 0;
    int width = bounds.x2;
    int height = bounds.y2;
    std::string layerName;
    std::vector<std::string> layerChannels = OFX::mapPixelComponentCustomToLayerChannels(rawComponents);
    int numChannels = layerChannels.size();
    if (numChannels==5) // layer+R+G+B+A
        layerName=layerChannels[0];
    if (!layerName.empty()) {
        for (size_t i = 0; i < _psd.size(); i++) {
            bool foundLayer = false;
            std::ostringstream psdLayer;
            psdLayer << "Image Layer #" << i;
            if (_psd[i].label()==layerName)
                foundLayer = true;
            if (psdLayer.str()==layerName && !foundLayer)
                foundLayer = true;
            if (foundLayer) {
                if ((int)_psd[i].columns()!=bounds.x2)
                    offsetX = _psd[i].page().xOff();
                if ((int)_psd[i].rows()!=bounds.y2)
                    offsetY = _psd[i].page().yOff();
                layer = i;
                break;
            }
        }
    }
    Magick::Image container(Magick::Geometry(width,height),Magick::Color("rgba(0,0,0,0)"));
    container.composite(_psd[layer],offsetX,offsetY,Magick::OverCompositeOp);
    container.flip();
    container.write(0,0,width,height,"RGBA",Magick::FloatPixel,pixelData);
}

bool ReadPSDPlugin::getFrameBounds(const std::string& /*filename*/,
                              OfxTime /*time*/,
                              OfxRectI *bounds,
                              double *par,
                              std::string */*error*/)
{
    #ifdef DEBUG
    std::cout << "getFrameBounds ..." << std::endl;
    #endif
    if (_psd[0].columns()>0 && _psd[0].rows()>0) {
        bounds->x1 = 0;
        bounds->x2 = _psd[0].columns();
        bounds->y1 = 0;
        bounds->y2 = _psd[0].rows();
        *par = 1.0;
    }
    #ifdef DEBUG
    std::cout << "bounds " << bounds->x2 << "x" << bounds->y2 << std::endl;
    #endif
    return true;
}

void ReadPSDPlugin::restoreState(const std::string& filename)
{
    #ifdef DEBUG
    std::cout << "restoreState ..." << std::endl;
    #endif
    _psd.clear();
    try {
        Magick::readImages(&_psd, filename);
    }
    catch(Magick::Exception) {
        setPersistentMessage(OFX::Message::eMessageError, "", "Unable to read image");
        OFX::throwSuiteStatusException(kOfxStatErrFormat);
    }
    if (_psd[0].columns()>0 && _psd[0].rows()>0)
        _filename = filename;
    else {
        _psd.clear();
        setPersistentMessage(OFX::Message::eMessageError, "", "Unable to read image");
        OFX::throwSuiteStatusException(kOfxStatErrFormat);
    }
}

void ReadPSDPlugin::onInputFileChanged(const std::string& newFile,
                                  OFX::PreMultiplicationEnum *premult,
                                  OFX::PixelComponentEnum *components,int */*componentCount*/)
{
    #ifdef DEBUG
    std::cout << "onInputFileChanged ..." << std::endl;
    #endif
    assert(premult && components);
    if (newFile!=_filename)
        restoreState(newFile);
    # ifdef OFX_IO_USING_OCIO
    switch(_psd[0].colorSpace()) {
    case Magick::RGBColorspace:
        _ocio->setInputColorspace("sRGB");
        break;
    case Magick::sRGBColorspace:
        _ocio->setInputColorspace("sRGB");
        break;
    case Magick::scRGBColorspace:
        _ocio->setInputColorspace("sRGB");
        break;
    case Magick::Rec709LumaColorspace:
        _ocio->setInputColorspace("Rec709");
        break;
    case Magick::Rec709YCbCrColorspace:
        _ocio->setInputColorspace("Rec709");
        break;
    default:
        _ocio->setInputColorspace("Linear");
        break;
    }
    # endif // OFX_IO_USING_OCIO
    *components = OFX::ePixelComponentRGBA;
    *premult = OFX::eImageOpaque;
}

using namespace OFX;

mDeclareReaderPluginFactory(ReadPSDPluginFactory, {}, {}, false);

/** @brief The basic describe function, passed a plugin descriptor */
void ReadPSDPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
    GenericReaderDescribe(desc, kSupportsTiles, kIsMultiPlanar);
    desc.setLabel(kPluginName);

    #ifdef OFX_EXTENSIONS_TUTTLE
    const char* extensions[] = {"psd", "xcf", NULL};
    desc.addSupportedExtensions(extensions);
    desc.setPluginEvaluation(92);
    #endif

    std::string magickV = MagickCore::GetMagickVersion(NULL);
    desc.setPluginDescription("Read Photoshop/GIMP/Cinepaint image formats.\n\nWritten by Ole-André Rodlie <olear@fxarena.net>\n\nPowered by "+magickV);
}

/** @brief The describe in context function, passed a plugin descriptor and a context */
void ReadPSDPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, ContextEnum context)
{
    PageParamDescriptor *page = GenericReaderDescribeInContextBegin(desc, context, isVideoStreamPlugin(), kSupportsRGBA, kSupportsRGB, kSupportsAlpha, kSupportsTiles);
    GenericReaderDescribeInContextEnd(desc, context, page, "reference", "reference");
}

/** @brief The create instance function, the plugin must return an object derived from the \ref OFX::ImageEffect class */
ImageEffect* ReadPSDPluginFactory::createInstance(OfxImageEffectHandle handle,
                                     ContextEnum /*context*/)
{
    ReadPSDPlugin* ret =  new ReadPSDPlugin(handle);
    ret->restoreStateFromParameters();
    return ret;
}

void getReadPSDPluginID(OFX::PluginFactoryArray &ids)
{
    static ReadPSDPluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
    ids.push_back(&p);
}
<commit_msg>ReadPSD: get icc profiles and add to choice param<commit_after>/*

openfx-arena - https://github.com/olear/openfx-arena

Copyright (c) 2015, Ole-André Rodlie <olear@fxarena.net>
Copyright (c) 2015, FxArena DA <mail@fxarena.net>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Neither the name of FxArena DA nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "ReadPSD.h"
#include <iostream>
#include <string>
#include <Magick++.h>
#include "GenericReader.h"
#include "GenericOCIO.h"
#include "ofxsMacros.h"
#include <lcms2.h>
#include <dirent.h>

#ifdef OFX_IO_USING_OCIO
#include <OpenColorIO/OpenColorIO.h>
#endif

#define kPluginName "ReadPSD"
#define kPluginGrouping "Image/Readers"
#define kPluginIdentifier "net.fxarena.openfx.ReadPSD"
#define kPluginVersionMajor 1
#define kPluginVersionMinor 7

#define kSupportsRGBA true
#define kSupportsRGB false
#define kSupportsAlpha false
#define kSupportsTiles false
#define kIsMultiPlanar true

#define kParamICC "icc"
#define kParamICCLabel "ICC profile"
#define kParamICCHint "Convert to the selected ICC profile"

void _getProFiles(std::vector<std::string> &files, bool desc) {
    std::vector<std::string> paths;
    paths.push_back("/usr/share/color/icc/");
    paths.push_back("\\Windows\\system32\\spool\\drivers\\color\\");
    paths.push_back("/Library/ColorSync/Profiles/");
    for (unsigned int i = 0; i < paths.size(); i++) {
        DIR *dp;
        struct dirent *dirp;
        if((dp=opendir(paths[i].c_str())) != NULL) {
            while ((dirp=readdir(dp)) != NULL) {
                std::string proFile = dirp->d_name;
                std::ostringstream profileDesc;
                    cmsHPROFILE lcmsProfile;
                    char buffer[500];
                    std::ostringstream path;
                    bool rgb = false;
                    path << paths[i] << proFile;
                    lcmsProfile = cmsOpenProfileFromFile(path.str().c_str(), "r");
                    if (lcmsProfile) {
                        cmsGetProfileInfoASCII(lcmsProfile, cmsInfoDescription, "en", "US", buffer, 500);
                        profileDesc << buffer;
                        if(cmsGetColorSpace(lcmsProfile) == cmsSigRgbData)
                            rgb = true;
                    }
                    cmsCloseProfile(lcmsProfile);
                    if (!profileDesc.str().empty() && rgb) {
                        if (desc)
                            files.push_back(profileDesc.str());
                        else
                            files.push_back(std::string(dirp->d_name));
                    }
            }
        }
        closedir(dp);
    }
}

class ReadPSDPlugin : public GenericReaderPlugin
{
public:
    ReadPSDPlugin(OfxImageEffectHandle handle);
    virtual ~ReadPSDPlugin();
private:
    virtual bool isVideoStream(const std::string& /*filename*/) OVERRIDE FINAL { return false; }
    virtual void decode(const std::string& filename, OfxTime time, const OfxRectI& renderWindow, float *pixelData, const OfxRectI& bounds,
                             OFX::PixelComponentEnum pixelComponents, int pixelComponentCount, int rowBytes) OVERRIDE FINAL
    {
        std::string rawComps;
        switch (pixelComponents) {
            case OFX::ePixelComponentAlpha:
                rawComps = kOfxImageComponentAlpha;
                break;
            case OFX::ePixelComponentRGB:
                rawComps = kOfxImageComponentRGB;
                break;
            case OFX::ePixelComponentRGBA:
                rawComps = kOfxImageComponentRGBA;
                break;
            default:
                OFX::throwSuiteStatusException(kOfxStatFailed);
                return;
        }
        decodePlane(filename, time, renderWindow, pixelData, bounds, pixelComponents, pixelComponentCount, rawComps, rowBytes);
    }
    virtual void getClipComponents(const OFX::ClipComponentsArguments& args, OFX::ClipComponentsSetter& clipComponents) OVERRIDE FINAL;
    virtual void decodePlane(const std::string& filename, OfxTime time, const OfxRectI& renderWindow, float *pixelData, const OfxRectI& bounds, OFX::PixelComponentEnum pixelComponents, int pixelComponentCount, const std::string& rawComponents, int rowBytes) OVERRIDE FINAL;
    virtual bool getFrameBounds(const std::string& filename, OfxTime time, OfxRectI *bounds, double *par, std::string *error) OVERRIDE FINAL;
    virtual void restoreState(const std::string& filename) OVERRIDE FINAL;
    virtual void onInputFileChanged(const std::string& newFile, OFX::PreMultiplicationEnum *premult, OFX::PixelComponentEnum *components, int *componentCount) OVERRIDE FINAL;
    std::string _filename;
    std::vector<Magick::Image> _psd;
    OFX::ChoiceParam *_icc;
};

ReadPSDPlugin::ReadPSDPlugin(OfxImageEffectHandle handle)
: GenericReaderPlugin(handle, kSupportsRGBA, kSupportsRGB, kSupportsAlpha, kSupportsTiles,
#ifdef OFX_EXTENSIONS_NUKE
(OFX::getImageEffectHostDescription() && OFX::getImageEffectHostDescription()->isMultiPlanar) ? kIsMultiPlanar : false
#else
false
#endif
)
{
    Magick::InitializeMagick(NULL);

    _icc = fetchChoiceParam(kParamICC);
    assert(_outputComponents && _icc);
}

ReadPSDPlugin::~ReadPSDPlugin()
{
}

void ReadPSDPlugin::getClipComponents(const OFX::ClipComponentsArguments& args, OFX::ClipComponentsSetter& clipComponents)
{
    #ifdef DEBUG
    std::cout << "getClipComponents ..." << std::endl;
    #endif
    assert(isMultiPlanar());
    clipComponents.addClipComponents(*_outputClip, getOutputComponents());
    clipComponents.setPassThroughClip(NULL, args.time, args.view);
    if (_psd.size()>0) {
        int startLayer = 0;
        if (_psd[0].format()=="Adobe Photoshop bitmap")
            startLayer++;
        for (int i = startLayer; i < (int)_psd.size(); i++) {
            std::ostringstream layerName;
            layerName << _psd[i].label();
            if (layerName.str().empty())
                layerName << "Image Layer #" << i; // add a label if empty
            std::string component(kNatronOfxImageComponentsPlane);
            component.append(layerName.str());
            component.append(kNatronOfxImageComponentsPlaneChannel);
            component.append("R");
            component.append(kNatronOfxImageComponentsPlaneChannel);
            component.append("G");
            component.append(kNatronOfxImageComponentsPlaneChannel);
            component.append("B");
            component.append(kNatronOfxImageComponentsPlaneChannel);
            component.append("A");
            clipComponents.addClipComponents(*_outputClip, component);
        }
    }
}

void ReadPSDPlugin::decodePlane(const std::string& /*filename*/, OfxTime time, const OfxRectI& /*renderWindow*/, float *pixelData, const OfxRectI& bounds,
                                 OFX::PixelComponentEnum /*pixelComponents*/, int /*pixelComponentCount*/, const std::string& rawComponents, int /*rowBytes*/)
{
    #ifdef DEBUG
    std::cout << "decodePlane ..." << std::endl;
    #endif
    int offsetX = 0;
    int offsetY = 0;
    int layer = 0;
    int width = bounds.x2;
    int height = bounds.y2;
    std::string layerName;
    int iccProfileID = 0;
    std::vector<std::string> layerChannels = OFX::mapPixelComponentCustomToLayerChannels(rawComponents);
    int numChannels = layerChannels.size();
    _icc->getValueAtTime(time, iccProfileID);
    if (numChannels==5) // layer+R+G+B+A
        layerName=layerChannels[0];
    if (!layerName.empty()) {
        for (size_t i = 0; i < _psd.size(); i++) {
            bool foundLayer = false;
            std::ostringstream psdLayer;
            psdLayer << "Image Layer #" << i;
            if (_psd[i].label()==layerName)
                foundLayer = true;
            if (psdLayer.str()==layerName && !foundLayer)
                foundLayer = true;
            if (foundLayer) {
                if ((int)_psd[i].columns()!=bounds.x2)
                    offsetX = _psd[i].page().xOff();
                if ((int)_psd[i].rows()!=bounds.y2)
                    offsetY = _psd[i].page().yOff();
                layer = i;
                break;
            }
        }
    }
    Magick::Image container(Magick::Geometry(width,height),Magick::Color("rgba(0,0,0,0)"));
    container.composite(_psd[layer],offsetX,offsetY,Magick::OverCompositeOp);
    container.flip();
    container.write(0,0,width,height,"RGBA",Magick::FloatPixel,pixelData);
}

bool ReadPSDPlugin::getFrameBounds(const std::string& /*filename*/,
                              OfxTime /*time*/,
                              OfxRectI *bounds,
                              double *par,
                              std::string */*error*/)
{
    #ifdef DEBUG
    std::cout << "getFrameBounds ..." << std::endl;
    #endif
    if (_psd[0].columns()>0 && _psd[0].rows()>0) {
        bounds->x1 = 0;
        bounds->x2 = _psd[0].columns();
        bounds->y1 = 0;
        bounds->y2 = _psd[0].rows();
        *par = 1.0;
    }
    #ifdef DEBUG
    std::cout << "bounds " << bounds->x2 << "x" << bounds->y2 << std::endl;
    #endif
    return true;
}

void ReadPSDPlugin::restoreState(const std::string& filename)
{
    #ifdef DEBUG
    std::cout << "restoreState ..." << std::endl;
    #endif
    _psd.clear();
    try {
        Magick::readImages(&_psd, filename);
    }
    catch(Magick::Exception) {
        setPersistentMessage(OFX::Message::eMessageError, "", "Unable to read image");
        OFX::throwSuiteStatusException(kOfxStatErrFormat);
    }
    if (_psd[0].columns()>0 && _psd[0].rows()>0) {
        _filename = filename;
        if (_psd[0].iccColorProfile().length()>0) { // image has an icc profile
        }
    }
    else {
        _psd.clear();
        setPersistentMessage(OFX::Message::eMessageError, "", "Unable to read image");
        OFX::throwSuiteStatusException(kOfxStatErrFormat);
    }
}

void ReadPSDPlugin::onInputFileChanged(const std::string& newFile,
                                  OFX::PreMultiplicationEnum *premult,
                                  OFX::PixelComponentEnum *components,int */*componentCount*/)
{
    #ifdef DEBUG
    std::cout << "onInputFileChanged ..." << std::endl;
    #endif
    assert(premult && components);
    if (newFile!=_filename)
        restoreState(newFile);
    # ifdef OFX_IO_USING_OCIO
    switch(_psd[0].colorSpace()) {
    case Magick::RGBColorspace:
        _ocio->setInputColorspace("sRGB");
        break;
    case Magick::sRGBColorspace:
        _ocio->setInputColorspace("sRGB");
        break;
    case Magick::scRGBColorspace:
        _ocio->setInputColorspace("sRGB");
        break;
    case Magick::Rec709LumaColorspace:
        _ocio->setInputColorspace("Rec709");
        break;
    case Magick::Rec709YCbCrColorspace:
        _ocio->setInputColorspace("Rec709");
        break;
    default:
        _ocio->setInputColorspace("Linear");
        break;
    }
    # endif // OFX_IO_USING_OCIO
    *components = OFX::ePixelComponentRGBA;
    *premult = OFX::eImageOpaque;
}

using namespace OFX;

mDeclareReaderPluginFactory(ReadPSDPluginFactory, {}, {}, false);

/** @brief The basic describe function, passed a plugin descriptor */
void ReadPSDPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
    GenericReaderDescribe(desc, kSupportsTiles, kIsMultiPlanar);
    desc.setLabel(kPluginName);

    #ifdef OFX_EXTENSIONS_TUTTLE
    const char* extensions[] = {"psd", "xcf", NULL};
    desc.addSupportedExtensions(extensions);
    desc.setPluginEvaluation(92);
    #endif

    std::string magickV = MagickCore::GetMagickVersion(NULL);
    desc.setPluginDescription("Read Photoshop/GIMP/Cinepaint image formats.\n\nWritten by Ole-André Rodlie <olear@fxarena.net>\n\nPowered by "+magickV);
}

/** @brief The describe in context function, passed a plugin descriptor and a context */
void ReadPSDPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, ContextEnum context)
{
    PageParamDescriptor *page = GenericReaderDescribeInContextBegin(desc, context, isVideoStreamPlugin(), kSupportsRGBA, kSupportsRGB, kSupportsAlpha, kSupportsTiles);
    {
        ChoiceParamDescriptor* param = desc.defineChoiceParam(kParamICC);
        param->setLabel(kParamICCLabel);
        param->setHint(kParamICCHint);
        param->appendOption("Undefined");
        std::vector<std::string> profiles;
        _getProFiles(profiles, true);
        for (unsigned int i = 0;i < profiles.size();i++)
            param->appendOption(profiles[i]);
        page->addChild(*param);
    }
    GenericReaderDescribeInContextEnd(desc, context, page, "reference", "reference");
}

/** @brief The create instance function, the plugin must return an object derived from the \ref OFX::ImageEffect class */
ImageEffect* ReadPSDPluginFactory::createInstance(OfxImageEffectHandle handle,
                                     ContextEnum /*context*/)
{
    ReadPSDPlugin* ret =  new ReadPSDPlugin(handle);
    ret->restoreStateFromParameters();
    return ret;
}

void getReadPSDPluginID(OFX::PluginFactoryArray &ids)
{
    static ReadPSDPluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
    ids.push_back(&p);
}
<|endoftext|>