<commit_before>#include <cctype>
#include <iostream>
#include <list>
#include <sstream>

using namespace std;

inline void use_io_optimizations()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
}

constexpr int alphabet_size {26};

enum class NumerationSystem
{
    First, Second
};

NumerationSystem numeration_system(string& coordinates)
{
    if (isalpha(coordinates[1]) || coordinates.find('C', 1) == string::npos)
    {
        return NumerationSystem::First;
    }
    else
    {
        return NumerationSystem::Second;
    }
}

string first_to_second(string& coordinates)
{
    ostringstream to_second;

    string::size_type i {0};
    unsigned int column {0};

    for (; i < coordinates.size() && isalpha(coordinates[i]); ++i)
    {
        column = column * alphabet_size + coordinates[i] - 'A' + 1;
    }

    to_second << 'R' << coordinates.substr(i);
    to_second << 'C' << column;

    return to_second.str();
}

string second_to_first(string& coordinates)
{
    istringstream from_second {coordinates};
    ostringstream to_first;

    char delimiter;

    unsigned int row;
    unsigned int column;

    from_second >> delimiter >> row;
    from_second >> delimiter >> column;

    list<char> converted_column;

    while (column > 0)
    {
        --column;
        converted_column.push_front('A' + column % alphabet_size);
        column /= alphabet_size;
    }

    for (auto symbol : converted_column)
    {
        to_first << symbol;
    }

    to_first << row;

    return to_first.str();
}

int main()
{
    use_io_optimizations();

    unsigned int number_of_coordinates;
    cin >> number_of_coordinates;

    for (unsigned int i {0}; i < number_of_coordinates; ++i)
    {
        string cell_coordinates;
        cin >> cell_coordinates;

        switch (numeration_system(cell_coordinates))
        {
        case NumerationSystem::First:
            cout << first_to_second(cell_coordinates) << '\n';
            break;

        case NumerationSystem::Second:
            cout << second_to_first(cell_coordinates) << '\n';
            break;
        }
    }

    return 0;
}
<commit_msg>codeforces; pass by const reference in B. "Spreadsheet"<commit_after>#include <cctype>
#include <iostream>
#include <list>
#include <sstream>

using namespace std;

constexpr int alphabet_size {26};

enum class NumerationSystem
{
    First, Second
};

inline
void use_io_optimizations()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
}

NumerationSystem numeration_system(const string& coordinates)
{
    if (isalpha(coordinates[1]) || coordinates.find('C', 1) == string::npos)
    {
        return NumerationSystem::First;
    }
    else
    {
        return NumerationSystem::Second;
    }
}

string first_to_second(const string& coordinates)
{
    ostringstream to_second;

    string::size_type i {0};
    unsigned int column {0};

    for (; i < coordinates.size() && isalpha(coordinates[i]); ++i)
    {
        column = column * alphabet_size + coordinates[i] - 'A' + 1;
    }

    to_second << 'R' << coordinates.substr(i);
    to_second << 'C' << column;

    return to_second.str();
}

string second_to_first(const string& coordinates)
{
    istringstream from_second {coordinates};
    ostringstream to_first;

    char delimiter;

    unsigned int row;
    unsigned int column;

    from_second >> delimiter >> row;
    from_second >> delimiter >> column;

    list<char> converted_column;

    while (column > 0)
    {
        --column;
        converted_column.push_front('A' + column % alphabet_size);
        column /= alphabet_size;
    }

    for (auto symbol : converted_column)
    {
        to_first << symbol;
    }

    to_first << row;

    return to_first.str();
}

int main()
{
    use_io_optimizations();

    unsigned int number_of_coordinates;
    cin >> number_of_coordinates;

    for (unsigned int i {0}; i < number_of_coordinates; ++i)
    {
        string cell_coordinates;
        cin >> cell_coordinates;

        switch (numeration_system(cell_coordinates))
        {
        case NumerationSystem::First:
            cout << first_to_second(cell_coordinates) << '\n';
            break;

        case NumerationSystem::Second:
            cout << second_to_first(cell_coordinates) << '\n';
            break;
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Smoke tests to verify that clang sanitizers are actually working.

#include <pthread.h>
#include <stdint.h>

#include <memory>

#include "test/gtest_and_gmock.h"

namespace perfetto {
namespace {

#if defined(ADDRESS_SANITIZER)
TEST(SanitizerTests, ASAN_UserAfterFree) {
  EXPECT_DEATH(
      {
        void* alloc = malloc(16);
        volatile char* mem = reinterpret_cast<volatile char*>(alloc);
        mem[0] = 1;
        mem[15] = 1;
        free(alloc);
        mem[0] = 2;
        abort();
      },
      "AddressSanitizer:.*heap-use-after-free");
}
#endif  // ADDRESS_SANITIZER

#if defined(THREAD_SANITIZER)
TEST(SanitizerTests, TSAN_ThreadDataRace) {
  EXPECT_DEATH(
      {
        pthread_t thread;
        volatile int race_var = 0;
        auto thread_main = [](void* race_var_ptr) -> void* {
          (*reinterpret_cast<volatile int*>(race_var_ptr))++;
          return nullptr;
        };
        void* arg =
            const_cast<void*>(reinterpret_cast<volatile void*>(&race_var));
        ASSERT_EQ(0, pthread_create(&thread, nullptr, thread_main, arg));
        race_var--;
        ASSERT_EQ(0, pthread_join(thread, nullptr));
        abort();
      },
      "ThreadSanitizer:.*data race");
}
#endif  // THREAD_SANITIZER

#if defined(MEMORY_SANITIZER)
TEST(SanitizerTests, MSAN_UninitializedMemory) {
  EXPECT_DEATH(
      {
        std::unique_ptr<int> mem(new int[10]);
        volatile int* x = reinterpret_cast<volatile int*>(mem.get());
        if (x[rand() % 10] == 42)
          printf("\n");
        abort();
      },
      "MemorySanitizer:.*use-of-uninitialized-value");
}
#endif

// b/141460117: Leak sanitizer tests don't work in debug builds.
#if defined(LEAK_SANITIZER) && defined(NDEBUG)
TEST(SanitizerTests, LSAN_LeakMalloc) {
  EXPECT_DEATH(
      {
        void* alloc = malloc(16);
        reinterpret_cast<volatile char*>(alloc)[0] = 1;
        alloc = malloc(16);
        reinterpret_cast<volatile char*>(alloc)[0] = 2;
        free(alloc);
        exit(0);  // LSan runs on the atexit handler.
      },
      "LeakSanitizer:.*detected memory leaks");
}

TEST(SanitizerTests, LSAN_LeakCppNew) {
  EXPECT_DEATH(
      {
        std::unique_ptr<int> alloc(new int(1));
        *reinterpret_cast<volatile char*>(alloc.get()) = 1;
        alloc.release();
        alloc.reset(new int(2));
        *reinterpret_cast<volatile char*>(alloc.get()) = 2;
        exit(0);  // LSan runs on the atexit handler.
      },
      "LeakSanitizer:.*detected memory leaks");
}
#endif  // LEAK_SANITIZER && defined(NDEBUG)

#if defined(UNDEFINED_SANITIZER)
TEST(SanitizerTests, UBSAN_DivisionByZero) {
  EXPECT_DEATH(
      {
        volatile float div = 1;
        float res = 3 / (div - 1);
        ASSERT_GT(res, -1.0f);  // just use |res| to make the compiler happy.
        abort();
      },
      "error:.*division by zero");
}

TEST(SanitizerTests, UBSAN_ShiftExponent) {
  EXPECT_DEATH(
      {
        volatile uint32_t n = 32;
        volatile uint32_t shift = 31;
        uint64_t res = n << (shift + 3);
        ASSERT_NE(1u, res);  // just use |res| to make the compiler happy.
        abort();
      },
      "error:.*shift exponent");
}
#endif  // UNDEFINED_SANITIZER

#if !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && \
    !defined(MEMORY_SANITIZER) && !defined(LEAK_SANITIZER) &&    \
    !defined(UNDEFINED_SANITIZER)
TEST(SanitizerTests, NoSanitizersConfigured) {
  printf("No sanitizers configured!\n");
}
#endif

}  // namespace
}  // namespace perfetto
<commit_msg>Delete SanitizerTests.TSAN_ThreadDataRace<commit_after>/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Smoke tests to verify that clang sanitizers are actually working.

#include <pthread.h>
#include <stdint.h>

#include <memory>

#include "test/gtest_and_gmock.h"

namespace perfetto {
namespace {

#if defined(ADDRESS_SANITIZER)
TEST(SanitizerTests, ASAN_UserAfterFree) {
  EXPECT_DEATH(
      {
        void* alloc = malloc(16);
        volatile char* mem = reinterpret_cast<volatile char*>(alloc);
        mem[0] = 1;
        mem[15] = 1;
        free(alloc);
        mem[0] = 2;
        abort();
      },
      "AddressSanitizer:.*heap-use-after-free");
}
#endif  // ADDRESS_SANITIZER

#if defined(MEMORY_SANITIZER)
TEST(SanitizerTests, MSAN_UninitializedMemory) {
  EXPECT_DEATH(
      {
        std::unique_ptr<int> mem(new int[10]);
        volatile int* x = reinterpret_cast<volatile int*>(mem.get());
        if (x[rand() % 10] == 42)
          printf("\n");
        abort();
      },
      "MemorySanitizer:.*use-of-uninitialized-value");
}
#endif

// b/141460117: Leak sanitizer tests don't work in debug builds.
#if defined(LEAK_SANITIZER) && defined(NDEBUG)
TEST(SanitizerTests, LSAN_LeakMalloc) {
  EXPECT_DEATH(
      {
        void* alloc = malloc(16);
        reinterpret_cast<volatile char*>(alloc)[0] = 1;
        alloc = malloc(16);
        reinterpret_cast<volatile char*>(alloc)[0] = 2;
        free(alloc);
        exit(0);  // LSan runs on the atexit handler.
      },
      "LeakSanitizer:.*detected memory leaks");
}

TEST(SanitizerTests, LSAN_LeakCppNew) {
  EXPECT_DEATH(
      {
        std::unique_ptr<int> alloc(new int(1));
        *reinterpret_cast<volatile char*>(alloc.get()) = 1;
        alloc.release();
        alloc.reset(new int(2));
        *reinterpret_cast<volatile char*>(alloc.get()) = 2;
        exit(0);  // LSan runs on the atexit handler.
      },
      "LeakSanitizer:.*detected memory leaks");
}
#endif  // LEAK_SANITIZER && defined(NDEBUG)

#if defined(UNDEFINED_SANITIZER)
TEST(SanitizerTests, UBSAN_DivisionByZero) {
  EXPECT_DEATH(
      {
        volatile float div = 1;
        float res = 3 / (div - 1);
        ASSERT_GT(res, -1.0f);  // just use |res| to make the compiler happy.
        abort();
      },
      "error:.*division by zero");
}

TEST(SanitizerTests, UBSAN_ShiftExponent) {
  EXPECT_DEATH(
      {
        volatile uint32_t n = 32;
        volatile uint32_t shift = 31;
        uint64_t res = n << (shift + 3);
        ASSERT_NE(1u, res);  // just use |res| to make the compiler happy.
        abort();
      },
      "error:.*shift exponent");
}
#endif  // UNDEFINED_SANITIZER

#if !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && \
    !defined(MEMORY_SANITIZER) && !defined(LEAK_SANITIZER) &&    \
    !defined(UNDEFINED_SANITIZER)
TEST(SanitizerTests, NoSanitizersConfigured) {
  printf("No sanitizers configured!\n");
}
#endif

}  // namespace
}  // namespace perfetto
<|endoftext|>


<commit_before><commit_msg>OConnection: WaE unused variable<commit_after><|endoftext|>


<commit_before>#include "util.cpp"

/*
//util classes
struct Server {
	//input
	int capacity, size;
	//output
	int row = -1, slot = -1, pool = -1;
};

struct Input {
	int r, s, u, p, m;
	vector<vector<int>> blocked_slots;//first index: row, second index: slot
	vector<Server> servers;
};
*/

struct Row {
	int num, area, capacity;
};

bool sort_servers(const Server &a, const Server &b)	{
	if (a.capacity*b.size != b.capacity*a.size)
		return a.capacity*b.size > b.capacity*a.size;
	else
		return a.size < b.size;
}

bool sort_rows(const Row &a, const Row &b)	{
	if (a.capacity*b.area != b.capacity*a.area)
		return a.capacity*b.area > b.capacity*a.area;
	else
		return a.area < b.area;
}

void place_blocked_slots(vector<vector<int>>& field, Row &row, int row_index, vector<int>& slots)	{
	for (int i = 0; i < slots.size(); i++)
	{
		field[row_index][slots[i]] = 1;
		row.area--;
	}
}

bool assign_server_to_row(int s, vector<int>& field, Server &server)	{
	for (int i = 0; i < s-server.size; i++)
	{
	 	int cnt_occ = 0;
		for (int j = 0; j < server.size; j++)
			cnt_occ += field[i+j];
		if (cnt_occ == 0)
		{
			for (int j = 0; j < server.size; j++)
				field[i+j] = 1;
			server.slot = i;
			return true;
		}
	}
	return false;
}

void placeServers(Input &input) {
	// sort servers
	sort(input.servers.begin(),input.servers.end(),sort_servers);

	// create field and rows
	vector<vector<int>> field(input.r, vector<int>(input.s));
	vector<Row> rows(input.r);

	for (int i = 0; i < input.r; i++)
	{
		rows[i].num = i;
		rows[i].capacity = 0;
		rows[i].area = input.s;
		place_blocked_slots(field,rows[i],i,input.blocked_slots[i]);
	}

	// iterate through all servers
	for (int i = 0; i < input.m; i++)
	{
		sort(rows.begin(),rows.end(),sort_rows);

		// try to assign each server to worst possible row
		for (int j = 0; j < input.r; j++)
		{
			if (assign_server_to_row(input.s,field[j],input.servers[i]))
			{
				rows[j].area -= input.servers[i].size;
				rows[j].capacity += input.servers[i].capacity;
				input.servers[i].row = row[j].num;
			}
		}
	}
}
<commit_msg>fixed placeservers.cpp<commit_after>#include "util.cpp"

/*
//util classes
struct Server {
	//input
	int capacity, size;
	//output
	int row = -1, slot = -1, pool = -1;
};

struct Input {
	int r, s, u, p, m;
	vector<vector<int>> blocked_slots;//first index: row, second index: slot
	vector<Server> servers;
};
*/

struct Row {
	int num, area, capacity;
};

bool sort_servers(const Server &a, const Server &b)	{
	if (a.capacity*b.size != b.capacity*a.size)
		return a.capacity*b.size > b.capacity*a.size;
	else
		return a.size < b.size;
}

bool sort_rows(const Row &a, const Row &b)	{
	if (a.capacity*b.area != b.capacity*a.area)
		return a.capacity*b.area > b.capacity*a.area;
	else
		return a.area < b.area;
}

void place_blocked_slots(vector<vector<int>>& field, Row &row, int row_index, vector<int>& slots)	{
	for (int i = 0; i < slots.size(); i++)
	{
		field[row_index][slots[i]] = 1;
		row.area--;
	}
}

bool assign_server_to_row(int s, vector<int>& field, Server &server)	{
	for (int i = 0; i < s-server.size; i++)
	{
	 	int cnt_occ = 0;
		for (int j = 0; j < server.size; j++)
			cnt_occ += field[i+j];
		if (cnt_occ == 0)
		{
			for (int j = 0; j < server.size; j++)
				field[i+j] = 1;
			server.slot = i;
			return true;
		}
	}
	return false;
}

void placeServers(Input &input) {
	// sort servers
	sort(input.servers.begin(),input.servers.end(),sort_servers);

	// create field and rows
	vector<vector<int>> field(input.r, vector<int>(input.s));
	vector<Row> rows(input.r);

	for (int i = 0; i < input.r; i++)
	{
		rows[i].num = i;
		rows[i].capacity = 0;
		rows[i].area = input.s;
		place_blocked_slots(field,rows[i],i,input.blocked_slots[i]);
	}

	// iterate through all servers
	for (int i = 0; i < input.m; i++)
	{
		sort(rows.begin(),rows.end(),sort_rows);

		// try to assign each server to worst possible row
		for (int j = 0; j < input.r; j++)
		{
			if (assign_server_to_row(input.s,field[j],input.servers[i]))
			{
				rows[j].area -= input.servers[i].size;
				rows[j].capacity += input.servers[i].capacity;
				input.servers[i].row = rows[j].num;
			}
		}
	}
}
<|endoftext|>


<commit_before>/*
* this file is part of the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* based on the Null Theme Engine for Gtk+.
* Copyright (c) 2008 Robert Staudinger <robert.staudinger@gmail.com>
*
* This  library is free  software; you can  redistribute it and/or
* modify it  under  the terms  of the  GNU Lesser  General  Public
* License  as published  by the Free  Software  Foundation; either
* version 2 of the License, or( at your option ) any later version.
*
* This library is distributed  in the hope that it will be useful,
* but  WITHOUT ANY WARRANTY; without even  the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License  along  with  this library;  if not,  write to  the Free
* Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "oxygendemodialog.h"
#include "oxygeninputdemowidget.h"
#include "oxygenbuttondemowidget.h"

#include <iostream>

namespace Oxygen
{

    //_____________________________________________
    DemoDialog::DemoDialog( void )
    {

        // create main widget
        _mainWidget = gtk_window_new( GTK_WINDOW_TOPLEVEL );
        gtk_window_set_default_size( GTK_WINDOW( _mainWidget ), 630, 500 );
        gtk_window_set_title( GTK_WINDOW( _mainWidget ), "Oxygen-gtk Demo" );

        // vertical container
        GtkWidget* vbox( gtk_vbox_new( false, 5 ) );
        gtk_container_add( GTK_CONTAINER( _mainWidget ), vbox );
        gtk_widget_show( vbox );

        {
            // first horizontal container
            GtkWidget* hbox( gtk_hbox_new( false, 5 ) );
            gtk_box_pack_start( GTK_BOX( vbox ), hbox, true, true, 0 );
            gtk_widget_show( hbox );

            // iconview model
            _model = gtk_list_store_new( 2, GDK_TYPE_PIXBUF, G_TYPE_STRING );

            // inconview
            GtkWidget* scrolledWindow( gtk_scrolled_window_new( 0L, 0L ) );
            gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( scrolledWindow ), GTK_SHADOW_IN );
            gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scrolledWindow ), GTK_POLICY_NEVER, GTK_POLICY_NEVER );
            gtk_box_pack_start( GTK_BOX( hbox ), scrolledWindow, false, true, 0 );
            gtk_widget_show( scrolledWindow );

            GtkWidget* iconView( gtk_icon_view_new_with_model( GTK_TREE_MODEL( _model ) ) );
            gtk_icon_view_set_pixbuf_column( GTK_ICON_VIEW( iconView ), 0 );
            gtk_icon_view_set_text_column( GTK_ICON_VIEW( iconView ), 1 );
            gtk_icon_view_set_columns( GTK_ICON_VIEW( iconView ), 1 );

            gtk_icon_view_set_spacing( GTK_ICON_VIEW( iconView ), 0 );
            gtk_icon_view_set_margin( GTK_ICON_VIEW( iconView ), 0 );
            gtk_icon_view_set_column_spacing( GTK_ICON_VIEW( iconView ), 0 );
            gtk_icon_view_set_row_spacing( GTK_ICON_VIEW( iconView ), 0 );

            _selectionChangedId.connect( G_OBJECT(iconView), "selection-changed", G_CALLBACK( selectionChanged ), this );

            gtk_container_add( GTK_CONTAINER( scrolledWindow ), iconView );
            gtk_widget_show( iconView );

            // notebook
            _notebook = gtk_notebook_new();
            gtk_notebook_set_show_tabs( GTK_NOTEBOOK( _notebook ), false );
            gtk_box_pack_start( GTK_BOX( hbox ), _notebook, true, true, 0 );
            gtk_widget_show( _notebook );

        }

        {
            // statusbar
            GtkWidget* statusBar( gtk_hbox_new( false, 2 ) );
            gtk_box_pack_start( GTK_BOX( vbox ), statusBar, false, true, 0 );
            gtk_widget_show( statusBar );

            // enable checkbox
            _stateButton = gtk_check_button_new_with_label( "Enabled" );
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( _stateButton ), true );
            gtk_box_pack_start( GTK_BOX( statusBar ), _stateButton, false, false, 0 );
            gtk_widget_show( _stateButton );

            _toggleEnableStateId.connect( G_OBJECT(_stateButton), "toggled", G_CALLBACK( toggleEnableState ), this );

            // close button
            GtkWidget* button = gtk_button_new_from_stock( GTK_STOCK_OK );
            gtk_box_pack_end( GTK_BOX( statusBar ), button, false, true, 0 );
            gtk_widget_show( button );

        }

        addPage( new InputDemoWidget() );
        addPage( new ButtonDemoWidget() );

    }

    //_____________________________________________
    DemoDialog::~DemoDialog( void )
    {
        //_selectionChangedId.disconnect();
        //_toggleEnableStateId.disconnect();
    }

    //_____________________________________________
    void DemoDialog::addPage( DemoWidget* page )
    {
        // get icon
        GdkPixbuf* icon( 0L );
        if( !page->iconName().empty() )
        {
            GtkIconTheme* theme( gtk_icon_theme_get_default() );
            icon = gtk_icon_theme_load_icon( theme, page->iconName().c_str(), 22, (GtkIconLookupFlags) 0, 0L );
        }

        // insert in list
        GtkTreeIter iter;
        gtk_list_store_append( _model, &iter );
        gtk_list_store_set( _model, &iter, 0, icon, 1, page->name().c_str(), -1 );

        // add to notebook
        int index( gtk_notebook_append_page( GTK_NOTEBOOK( _notebook ), page->mainWidget(), 0L ) );
        gtk_widget_show( page->mainWidget() );

        _pages.insert( std::make_pair( index, page ) );
    }

    //_____________________________________________
    void DemoDialog::selectionChanged( GtkIconView* view, gpointer data )
    {
        // get pointer to dialog
        DemoDialog& dialog( *static_cast<DemoDialog*>( data ) );

        // get selection
        GList* selection = gtk_icon_view_get_selected_items( view );
        if( !selection ) return;

        // get first child
        GtkTreePath* path( static_cast<GtkTreePath*>( g_list_first( selection )->data ) );
        const int page( gtk_tree_path_get_indices( path )[0] );
        gtk_notebook_set_current_page( GTK_NOTEBOOK( dialog._notebook ), page );
        g_list_free( selection );

        // store enable state
        const bool enabled( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dialog._stateButton ) ) );

        // get matching page
        DemoWidget* widget( dialog._pages[page] );
        widget->setEnabled( enabled );

    }

    //_____________________________________________
    void DemoDialog::toggleEnableState( GtkToggleButton* button, gpointer data )
    {

        // get pointer to dialog
        DemoDialog& dialog( *static_cast<DemoDialog*>( data ) );

        // store enable state
        const bool enabled( gtk_toggle_button_get_active( button ) );

        // get current page
        const int page( gtk_notebook_get_current_page( GTK_NOTEBOOK( dialog._notebook ) ) );

        // get matching page
        DemoWidget* widget( dialog._pages[page] );
        widget->setEnabled( enabled );

    }
}
<commit_msg>put button in buttonBox, to get proper margin.<commit_after>/*
* this file is part of the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* based on the Null Theme Engine for Gtk+.
* Copyright (c) 2008 Robert Staudinger <robert.staudinger@gmail.com>
*
* This  library is free  software; you can  redistribute it and/or
* modify it  under  the terms  of the  GNU Lesser  General  Public
* License  as published  by the Free  Software  Foundation; either
* version 2 of the License, or( at your option ) any later version.
*
* This library is distributed  in the hope that it will be useful,
* but  WITHOUT ANY WARRANTY; without even  the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License  along  with  this library;  if not,  write to  the Free
* Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "oxygendemodialog.h"
#include "oxygeninputdemowidget.h"
#include "oxygenbuttondemowidget.h"

#include <iostream>

namespace Oxygen
{

    //_____________________________________________
    DemoDialog::DemoDialog( void )
    {

        // create main widget
        _mainWidget = gtk_window_new( GTK_WINDOW_TOPLEVEL );
        gtk_window_set_default_size( GTK_WINDOW( _mainWidget ), 630, 500 );
        gtk_window_set_title( GTK_WINDOW( _mainWidget ), "Oxygen-gtk Demo" );

        // vertical container
        GtkWidget* vbox( gtk_vbox_new( false, 5 ) );
        gtk_container_add( GTK_CONTAINER( _mainWidget ), vbox );
        gtk_widget_show( vbox );

        {
            // first horizontal container
            GtkWidget* hbox( gtk_hbox_new( false, 5 ) );
            gtk_box_pack_start( GTK_BOX( vbox ), hbox, true, true, 0 );
            gtk_widget_show( hbox );

            // iconview model
            _model = gtk_list_store_new( 2, GDK_TYPE_PIXBUF, G_TYPE_STRING );

            // inconview
            GtkWidget* scrolledWindow( gtk_scrolled_window_new( 0L, 0L ) );
            gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( scrolledWindow ), GTK_SHADOW_IN );
            gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scrolledWindow ), GTK_POLICY_NEVER, GTK_POLICY_NEVER );
            gtk_box_pack_start( GTK_BOX( hbox ), scrolledWindow, false, true, 0 );
            gtk_widget_show( scrolledWindow );

            GtkWidget* iconView( gtk_icon_view_new_with_model( GTK_TREE_MODEL( _model ) ) );
            gtk_icon_view_set_pixbuf_column( GTK_ICON_VIEW( iconView ), 0 );
            gtk_icon_view_set_text_column( GTK_ICON_VIEW( iconView ), 1 );
            gtk_icon_view_set_columns( GTK_ICON_VIEW( iconView ), 1 );

            gtk_icon_view_set_spacing( GTK_ICON_VIEW( iconView ), 0 );
            gtk_icon_view_set_margin( GTK_ICON_VIEW( iconView ), 0 );
            gtk_icon_view_set_column_spacing( GTK_ICON_VIEW( iconView ), 0 );
            gtk_icon_view_set_row_spacing( GTK_ICON_VIEW( iconView ), 0 );

            _selectionChangedId.connect( G_OBJECT(iconView), "selection-changed", G_CALLBACK( selectionChanged ), this );

            gtk_container_add( GTK_CONTAINER( scrolledWindow ), iconView );
            gtk_widget_show( iconView );

            // notebook
            _notebook = gtk_notebook_new();
            gtk_notebook_set_show_tabs( GTK_NOTEBOOK( _notebook ), false );
            gtk_box_pack_start( GTK_BOX( hbox ), _notebook, true, true, 0 );
            gtk_widget_show( _notebook );

        }

        {
            // statusbar
            GtkWidget* statusBar( gtk_hbox_new( false, 2 ) );
            gtk_box_pack_start( GTK_BOX( vbox ), statusBar, false, true, 0 );
            gtk_widget_show( statusBar );

            // enable checkbox
            _stateButton = gtk_check_button_new_with_label( "Enabled" );
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( _stateButton ), true );
            gtk_box_pack_start( GTK_BOX( statusBar ), _stateButton, false, false, 0 );
            gtk_widget_show( _stateButton );

            _toggleEnableStateId.connect( G_OBJECT(_stateButton), "toggled", G_CALLBACK( toggleEnableState ), this );

            // button box
            #if GTK_CHECK_VERSION( 3, 0, 0 )
            GtkWidget* buttonBox( gtk_button_box_new( GTK_ORIENTATION_HORIZONTAL) );
            #else
            GtkWidget* buttonBox( gtk_hbutton_box_new() );
            #endif

            gtk_button_box_set_layout( GTK_BUTTON_BOX( buttonBox ), GTK_BUTTONBOX_END );
            gtk_box_pack_end( GTK_BOX( statusBar ), buttonBox, true, true, 0 );
            gtk_widget_show( buttonBox );

            // close button
            GtkWidget* button = gtk_button_new_from_stock( GTK_STOCK_OK );
            gtk_box_pack_end( GTK_BOX( buttonBox ), button, false, true, 0 );
            gtk_widget_show( button );

        }

        addPage( new InputDemoWidget() );
        addPage( new ButtonDemoWidget() );

    }

    //_____________________________________________
    DemoDialog::~DemoDialog( void )
    {
        //_selectionChangedId.disconnect();
        //_toggleEnableStateId.disconnect();
    }

    //_____________________________________________
    void DemoDialog::addPage( DemoWidget* page )
    {
        // get icon
        GdkPixbuf* icon( 0L );
        if( !page->iconName().empty() )
        {
            GtkIconTheme* theme( gtk_icon_theme_get_default() );
            icon = gtk_icon_theme_load_icon( theme, page->iconName().c_str(), 22, (GtkIconLookupFlags) 0, 0L );
        }

        // insert in list
        GtkTreeIter iter;
        gtk_list_store_append( _model, &iter );
        gtk_list_store_set( _model, &iter, 0, icon, 1, page->name().c_str(), -1 );

        // add to notebook
        int index( gtk_notebook_append_page( GTK_NOTEBOOK( _notebook ), page->mainWidget(), 0L ) );
        gtk_widget_show( page->mainWidget() );

        _pages.insert( std::make_pair( index, page ) );
    }

    //_____________________________________________
    void DemoDialog::selectionChanged( GtkIconView* view, gpointer data )
    {
        // get pointer to dialog
        DemoDialog& dialog( *static_cast<DemoDialog*>( data ) );

        // get selection
        GList* selection = gtk_icon_view_get_selected_items( view );
        if( !selection ) return;

        // get first child
        GtkTreePath* path( static_cast<GtkTreePath*>( g_list_first( selection )->data ) );
        const int page( gtk_tree_path_get_indices( path )[0] );
        gtk_notebook_set_current_page( GTK_NOTEBOOK( dialog._notebook ), page );
        g_list_free( selection );

        // store enable state
        const bool enabled( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dialog._stateButton ) ) );

        // get matching page
        DemoWidget* widget( dialog._pages[page] );
        widget->setEnabled( enabled );

    }

    //_____________________________________________
    void DemoDialog::toggleEnableState( GtkToggleButton* button, gpointer data )
    {

        // get pointer to dialog
        DemoDialog& dialog( *static_cast<DemoDialog*>( data ) );

        // store enable state
        const bool enabled( gtk_toggle_button_get_active( button ) );

        // get current page
        const int page( gtk_notebook_get_current_page( GTK_NOTEBOOK( dialog._notebook ) ) );

        // get matching page
        DemoWidget* widget( dialog._pages[page] );
        widget->setEnabled( enabled );

    }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the demonstration applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "glshaders.h"

#define GLSHADERS_ASSERT_OPENGL(prefix, assertion, returnStatement)                         \
if (m_failed || !(assertion)) {                                                             \
    if (!m_failed) qCritical(prefix ": The necessary OpenGL functions are not available."); \
    m_failed = true;                                                                        \
    returnStatement;                                                                        \
}

GLShader::GLShader(const char *data, int size, GLenum shaderType)
: m_compileError(false), m_failed(false)
{
    GLSHADERS_ASSERT_OPENGL("GLShader::GLShader",
        glCreateShaderObjectARB && glShaderSourceARB && glCompileShaderARB && glGetObjectParameterivARB, return)

    m_shader = glCreateShaderObjectARB(shaderType);

    GLint glSize = size;
    glShaderSourceARB(m_shader, 1, &data, &glSize);
    glCompileShaderARB(m_shader);
    int status;
    glGetObjectParameterivARB(m_shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
    m_compileError = (status != 1);
}

GLShader::GLShader(const QString& fileName, GLenum shaderType)
    : m_compileError(false), m_failed(false)
{
    GLSHADERS_ASSERT_OPENGL("GLShader::GLShader",
        glCreateShaderObjectARB && glShaderSourceARB && glCompileShaderARB && glGetObjectParameterivARB, return)

    m_shader = glCreateShaderObjectARB(shaderType);

    QFile file(fileName);
    if (file.open(QIODevice::ReadOnly)) {
        QByteArray bytes = file.readAll();
        GLint size = file.size();
        const char *p = bytes.data();
        file.close();
        glShaderSourceARB(m_shader, 1, &p, &size);
        glCompileShaderARB(m_shader);
        int status;
        glGetObjectParameterivARB(m_shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
        m_compileError = (status != 1);
    } else {
        m_compileError = true;
    }
}

GLShader::~GLShader()
{
    GLSHADERS_ASSERT_OPENGL("GLShader::~GLShader", glDeleteObjectARB, return)

    glDeleteObjectARB(m_shader);
}

QString GLShader::log()
{
    GLSHADERS_ASSERT_OPENGL("GLShader::log", glGetObjectParameterivARB
        && glGetInfoLogARB, return QLatin1String("GLSL not supported."))

    int length;
    glGetObjectParameterivARB(m_shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
    char *log = new char[length + 1];
    GLsizei glLength = length;
    glGetInfoLogARB(m_shader, glLength, &glLength, log);
    log[glLength] = '\0';
    QString result(log);
    delete log;
    return result;
}

GLVertexShader::GLVertexShader(const char *data, int size) : GLShader(data, size, GL_VERTEX_SHADER_ARB)
{
}

GLVertexShader::GLVertexShader(const QString& fileName) : GLShader(fileName, GL_VERTEX_SHADER_ARB)
{
}

GLFragmentShader::GLFragmentShader(const char *data, int size) : GLShader(data, size, GL_FRAGMENT_SHADER_ARB)
{
}

GLFragmentShader::GLFragmentShader(const QString& fileName) : GLShader(fileName, GL_FRAGMENT_SHADER_ARB)
{
}

GLProgram::GLProgram() : m_linked(false), m_linkError(false), m_failed(false)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::GLProgram", glCreateProgramObjectARB, return)

    m_program = glCreateProgramObjectARB();
}

GLProgram::~GLProgram()
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::~GLProgram", glDeleteObjectARB, return)

    glDeleteObjectARB(m_program);
}

void GLProgram::attach(const GLShader &shader)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::attach", glAttachObjectARB, return)

    glAttachObjectARB(m_program, shader.m_shader);
    m_linked = m_linkError = false;
}

void GLProgram::detach(const GLShader &shader)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::detach", glDetachObjectARB, return)

    glDetachObjectARB(m_program, shader.m_shader);
    m_linked = m_linkError = false;
}

bool GLProgram::failed()
{
    if (m_failed || m_linkError)
        return true;

    if (m_linked)
        return false;

    GLSHADERS_ASSERT_OPENGL("GLProgram::failed", glLinkProgramARB && glGetObjectParameterivARB, return true)

    glLinkProgramARB(m_program);
    int status;
    glGetObjectParameterivARB(m_program, GL_OBJECT_LINK_STATUS_ARB, &status);
    m_linkError = !(m_linked = (status == 1));
    return m_linkError;
}

QString GLProgram::log()
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::log", glGetObjectParameterivARB && glGetInfoLogARB,
        return QLatin1String("Failed."))

    int length;
    glGetObjectParameterivARB(m_program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
    char *log = new char[length + 1];
    GLsizei glLength = length;
    glGetInfoLogARB(m_program, glLength, &glLength, log);
    log[glLength] = '\0';
    QString result(log);
    delete log;
    return result;
}

void GLProgram::bind()
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::bind", glUseProgramObjectARB, return)

    if (!failed())
        glUseProgramObjectARB(m_program);
}

void GLProgram::unbind()
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::bind", glUseProgramObjectARB, return)

    glUseProgramObjectARB(0);
}

bool GLProgram::hasParameter(const QString& name)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::hasParameter", glGetUniformLocationARB, return false)

    if (!failed()) {
        QByteArray asciiName = name.toAscii();
        return -1 != glGetUniformLocationARB(m_program, asciiName.data());
    }
    return false;
}

void GLProgram::setInt(const QString& name, int value)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::setInt", glGetUniformLocationARB && glUniform1iARB, return)

    if (!failed()) {
        QByteArray asciiName = name.toAscii();
        int loc = glGetUniformLocationARB(m_program, asciiName.data());
	    glUniform1iARB(loc, value);
    }
}

void GLProgram::setFloat(const QString& name, float value)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::setFloat", glGetUniformLocationARB && glUniform1fARB, return)

    if (!failed()) {
        QByteArray asciiName = name.toAscii();
        int loc = glGetUniformLocationARB(m_program, asciiName.data());
	    glUniform1fARB(loc, value);
    }
}

void GLProgram::setColor(const QString& name, QRgb value)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::setColor", glGetUniformLocationARB && glUniform4fARB, return)

    //qDebug() << "Setting color" << name;
    if (!failed()) {
        QByteArray asciiName = name.toAscii();
        int loc = glGetUniformLocationARB(m_program, asciiName.data());
        //qDebug() << "Location of" << name << "is" << loc;
        QColor color(value);
	    glUniform4fARB(loc, color.redF(), color.greenF(), color.blueF(), color.alphaF());
    }
}

void GLProgram::setMatrix(const QString& name, const gfx::Matrix4x4f &mat)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::setMatrix", glGetUniformLocationARB && glUniformMatrix4fvARB, return)

    if (!failed()) {
        QByteArray asciiName = name.toAscii();
        int loc = glGetUniformLocationARB(m_program, asciiName.data());
        //qDebug() << "Location of" << name << "is" << loc;
	    glUniformMatrix4fvARB(loc, 1, GL_FALSE, mat.bits());
    }
}<commit_msg>Fixed a compile issue on Solaris.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the demonstration applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "glshaders.h"

#define GLSHADERS_ASSERT_OPENGL(prefix, assertion, returnStatement)                         \
if (m_failed || !(assertion)) {                                                             \
    if (!m_failed) qCritical(prefix ": The necessary OpenGL functions are not available."); \
    m_failed = true;                                                                        \
    returnStatement;                                                                        \
}

GLShader::GLShader(const char *data, int size, GLenum shaderType)
: m_compileError(false), m_failed(false)
{
    GLSHADERS_ASSERT_OPENGL("GLShader::GLShader",
        glCreateShaderObjectARB && glShaderSourceARB && glCompileShaderARB && glGetObjectParameterivARB, return)

    m_shader = glCreateShaderObjectARB(shaderType);

    GLint glSize = size;
    glShaderSourceARB(m_shader, 1, static_cast<const GLcharARB**>(&data), &glSize);
    glCompileShaderARB(m_shader);
    int status;
    glGetObjectParameterivARB(m_shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
    m_compileError = (status != 1);
}

GLShader::GLShader(const QString& fileName, GLenum shaderType)
    : m_compileError(false), m_failed(false)
{
    GLSHADERS_ASSERT_OPENGL("GLShader::GLShader",
        glCreateShaderObjectARB && glShaderSourceARB && glCompileShaderARB && glGetObjectParameterivARB, return)

    m_shader = glCreateShaderObjectARB(shaderType);

    QFile file(fileName);
    if (file.open(QIODevice::ReadOnly)) {
        QByteArray bytes = file.readAll();
        GLint size = file.size();
        const char *p = bytes.data();
        file.close();
        glShaderSourceARB(m_shader, 1,  static_cast<const GLcharARB**>(&p), &size);
        glCompileShaderARB(m_shader);
        int status;
        glGetObjectParameterivARB(m_shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
        m_compileError = (status != 1);
    } else {
        m_compileError = true;
    }
}

GLShader::~GLShader()
{
    GLSHADERS_ASSERT_OPENGL("GLShader::~GLShader", glDeleteObjectARB, return)

    glDeleteObjectARB(m_shader);
}

QString GLShader::log()
{
    GLSHADERS_ASSERT_OPENGL("GLShader::log", glGetObjectParameterivARB
        && glGetInfoLogARB, return QLatin1String("GLSL not supported."))

    int length;
    glGetObjectParameterivARB(m_shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
    char *log = new char[length + 1];
    GLsizei glLength = length;
    glGetInfoLogARB(m_shader, glLength, &glLength,  static_cast<GLcharARB*>(log));
    log[glLength] = '\0';
    QString result(log);
    delete log;
    return result;
}

GLVertexShader::GLVertexShader(const char *data, int size) : GLShader(data, size, GL_VERTEX_SHADER_ARB)
{
}

GLVertexShader::GLVertexShader(const QString& fileName) : GLShader(fileName, GL_VERTEX_SHADER_ARB)
{
}

GLFragmentShader::GLFragmentShader(const char *data, int size) : GLShader(data, size, GL_FRAGMENT_SHADER_ARB)
{
}

GLFragmentShader::GLFragmentShader(const QString& fileName) : GLShader(fileName, GL_FRAGMENT_SHADER_ARB)
{
}

GLProgram::GLProgram() : m_linked(false), m_linkError(false), m_failed(false)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::GLProgram", glCreateProgramObjectARB, return)

    m_program = glCreateProgramObjectARB();
}

GLProgram::~GLProgram()
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::~GLProgram", glDeleteObjectARB, return)

    glDeleteObjectARB(m_program);
}

void GLProgram::attach(const GLShader &shader)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::attach", glAttachObjectARB, return)

    glAttachObjectARB(m_program, shader.m_shader);
    m_linked = m_linkError = false;
}

void GLProgram::detach(const GLShader &shader)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::detach", glDetachObjectARB, return)

    glDetachObjectARB(m_program, shader.m_shader);
    m_linked = m_linkError = false;
}

bool GLProgram::failed()
{
    if (m_failed || m_linkError)
        return true;

    if (m_linked)
        return false;

    GLSHADERS_ASSERT_OPENGL("GLProgram::failed", glLinkProgramARB && glGetObjectParameterivARB, return true)

    glLinkProgramARB(m_program);
    int status;
    glGetObjectParameterivARB(m_program, GL_OBJECT_LINK_STATUS_ARB, &status);
    m_linkError = !(m_linked = (status == 1));
    return m_linkError;
}

QString GLProgram::log()
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::log", glGetObjectParameterivARB && glGetInfoLogARB,
        return QLatin1String("Failed."))

    int length;
    glGetObjectParameterivARB(m_program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
    char *log = new char[length + 1];
    GLsizei glLength = length;
    glGetInfoLogARB(m_program, glLength, &glLength,  static_cast<GLcharARB*>(log));
    log[glLength] = '\0';
    QString result(log);
    delete log;
    return result;
}

void GLProgram::bind()
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::bind", glUseProgramObjectARB, return)

    if (!failed())
        glUseProgramObjectARB(m_program);
}

void GLProgram::unbind()
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::bind", glUseProgramObjectARB, return)

    glUseProgramObjectARB(0);
}

bool GLProgram::hasParameter(const QString& name)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::hasParameter", glGetUniformLocationARB, return false)

    if (!failed()) {
        QByteArray asciiName = name.toAscii();
        return -1 != glGetUniformLocationARB(m_program, static_cast<const GLcharARB*>(asciiName.data()));
    }
    return false;
}

void GLProgram::setInt(const QString& name, int value)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::setInt", glGetUniformLocationARB && glUniform1iARB, return)

    if (!failed()) {
        QByteArray asciiName = name.toAscii();
        int loc = glGetUniformLocationARB(m_program,  static_cast<const GLcharARB*>(asciiName.data()));
	    glUniform1iARB(loc, value);
    }
}

void GLProgram::setFloat(const QString& name, float value)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::setFloat", glGetUniformLocationARB && glUniform1fARB, return)

    if (!failed()) {
        QByteArray asciiName = name.toAscii();
        int loc = glGetUniformLocationARB(m_program, static_cast<const GLcharARB*>(asciiName.data()));
	    glUniform1fARB(loc, value);
    }
}

void GLProgram::setColor(const QString& name, QRgb value)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::setColor", glGetUniformLocationARB && glUniform4fARB, return)

    //qDebug() << "Setting color" << name;
    if (!failed()) {
        QByteArray asciiName = name.toAscii();
        int loc = glGetUniformLocationARB(m_program, static_cast<const GLcharARB*>(asciiName.data()));
        //qDebug() << "Location of" << name << "is" << loc;
        QColor color(value);
	    glUniform4fARB(loc, color.redF(), color.greenF(), color.blueF(), color.alphaF());
    }
}

void GLProgram::setMatrix(const QString& name, const gfx::Matrix4x4f &mat)
{
    GLSHADERS_ASSERT_OPENGL("GLProgram::setMatrix", glGetUniformLocationARB && glUniformMatrix4fvARB, return)

    if (!failed()) {
        QByteArray asciiName = name.toAscii();
        int loc = glGetUniformLocationARB(m_program,  static_cast<const GLcharARB*>(asciiName.data()));
        //qDebug() << "Location of" << name << "is" << loc;
	    glUniformMatrix4fvARB(loc, 1, GL_FALSE, mat.bits());
    }
}
<|endoftext|>


<commit_before>//
// PROJECT:         Aspia Remote Desktop
// FILE:            codec/cursor_encoder.cc
// LICENSE:         See top-level directory
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "codec/cursor_encoder.h"

#include "base/logging.h"

namespace aspia {

// Cache size can be in the range from 2 to 31.
static const uint8_t kCacheSize = 16;

// The compression ratio can be in the range of 1 to 9.
static const int32_t kCompressionRatio = 6;

CursorEncoder::CursorEncoder() :
    compressor_(kCompressionRatio),
    cache_(kCacheSize)
{
    static_assert(kCacheSize >= 2 && kCacheSize <= 31, "Invalid cache size");
    static_assert(kCompressionRatio >= 1 && kCompressionRatio <= 9, "Invalid compression ratio");
}

uint8_t* CursorEncoder::GetOutputBuffer(proto::CursorShape* cursor_shape, size_t size)
{
    cursor_shape->mutable_data()->resize(size);

    return const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(cursor_shape->mutable_data()->data()));
}

void CursorEncoder::CompressCursor(proto::CursorShape* cursor_shape, const MouseCursor* mouse_cursor)
{
    compressor_.Reset();

    int width = mouse_cursor->Size().Width();
    int height = mouse_cursor->Size().Height();

    const int row_size = width * sizeof(uint32_t);

    int packet_size = row_size * height;
    packet_size += packet_size / 100 + 16;

    uint8_t* compressed_pos = GetOutputBuffer(cursor_shape, packet_size);
    const uint8_t* source_pos = mouse_cursor->Data();

    int filled = 0;
    int row_pos = 0; // Position in the current row in bytes.
    int row_y = 0; // Current row.
    bool compress_again = true;

    while (compress_again)
    {
        Compressor::CompressorFlush flush = Compressor::CompressorNoFlush;

        // If we reached the last row in the rectangle.
        if (row_y == height - 1)
            flush = Compressor::CompressorFinish;

        int consumed = 0;
        int written = 0;

        compress_again = compressor_.Process(source_pos + row_pos, row_size - row_pos,
                                             compressed_pos + filled, packet_size - filled,
                                             flush, &consumed, &written);

        row_pos += consumed;
        filled += written;

        // If we have filled the message or we have reached the end of stream.
        if (filled == packet_size || !compress_again)
        {
            cursor_shape->mutable_data()->resize(filled);
            return;
        }

        // If we have reached the end of the current row in the rectangle and
        // this is not the last row.
        if (row_pos == row_size && row_y < height - 1)
        {
            row_pos = 0;
            source_pos += row_size;
            ++row_y;
        }
    }
}

std::unique_ptr<proto::CursorShape> CursorEncoder::Encode(std::unique_ptr<MouseCursor> mouse_cursor)
{
    if (!mouse_cursor)
        return nullptr;

    if (mouse_cursor->Size().Width() <= 0 ||
        mouse_cursor->Size().Width() > (std::numeric_limits<int16_t>::max() / 2) ||
        mouse_cursor->Size().Height() <= 0 ||
        mouse_cursor->Size().Height() > (std::numeric_limits<int16_t>::max() / 2))
    {
        DLOG(ERROR) << "Wrong size of cursor: "
                    << mouse_cursor->Size().Width()
                    << "x"
                    << mouse_cursor->Size().Height();
        return nullptr;
    }

    std::unique_ptr<proto::CursorShape> cursor_shape(new proto::CursorShape());

    size_t index = cache_.Find(mouse_cursor.get());

    // The cursor is not found in the cache.
    if (index == MouseCursorCache::kInvalidIndex)
    {
        cursor_shape->set_width(mouse_cursor->Size().Width());
        cursor_shape->set_height(mouse_cursor->Size().Height());
        cursor_shape->set_hotspot_x(mouse_cursor->Hotspot().x());
        cursor_shape->set_hotspot_y(mouse_cursor->Hotspot().y());

        CompressCursor(cursor_shape.get(), mouse_cursor.get());

        // If the cache is empty, then set the cache reset flag on the client
        // side and pass the maximum cache size.
        cursor_shape->set_flags(cache_.IsEmpty() ?
            (proto::CursorShape::RESET_CACHE | (kCacheSize & 0x1F)) : 0);

        // Add the cursor to the cache.
        cache_.Add(std::move(mouse_cursor));
    }
    else
    {
        cursor_shape->set_flags(proto::CursorShape::CACHE | (index & 0x1F));
    }

    return cursor_shape;
}

} // namespace aspia
<commit_msg>- Reducing the number of Size() calls<commit_after>//
// PROJECT:         Aspia Remote Desktop
// FILE:            codec/cursor_encoder.cc
// LICENSE:         See top-level directory
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "codec/cursor_encoder.h"

#include "base/logging.h"

namespace aspia {

// Cache size can be in the range from 2 to 31.
static const uint8_t kCacheSize = 16;

// The compression ratio can be in the range of 1 to 9.
static const int32_t kCompressionRatio = 6;

CursorEncoder::CursorEncoder() :
    compressor_(kCompressionRatio),
    cache_(kCacheSize)
{
    static_assert(kCacheSize >= 2 && kCacheSize <= 31, "Invalid cache size");
    static_assert(kCompressionRatio >= 1 && kCompressionRatio <= 9, "Invalid compression ratio");
}

uint8_t* CursorEncoder::GetOutputBuffer(proto::CursorShape* cursor_shape, size_t size)
{
    cursor_shape->mutable_data()->resize(size);

    return const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(cursor_shape->mutable_data()->data()));
}

void CursorEncoder::CompressCursor(proto::CursorShape* cursor_shape, const MouseCursor* mouse_cursor)
{
    compressor_.Reset();

    int width = mouse_cursor->Size().Width();
    int height = mouse_cursor->Size().Height();

    const int row_size = width * sizeof(uint32_t);

    int packet_size = row_size * height;
    packet_size += packet_size / 100 + 16;

    uint8_t* compressed_pos = GetOutputBuffer(cursor_shape, packet_size);
    const uint8_t* source_pos = mouse_cursor->Data();

    int filled = 0;
    int row_pos = 0; // Position in the current row in bytes.
    int row_y = 0; // Current row.
    bool compress_again = true;

    while (compress_again)
    {
        Compressor::CompressorFlush flush = Compressor::CompressorNoFlush;

        // If we reached the last row in the rectangle.
        if (row_y == height - 1)
            flush = Compressor::CompressorFinish;

        int consumed = 0;
        int written = 0;

        compress_again = compressor_.Process(source_pos + row_pos, row_size - row_pos,
                                             compressed_pos + filled, packet_size - filled,
                                             flush, &consumed, &written);

        row_pos += consumed;
        filled += written;

        // If we have filled the message or we have reached the end of stream.
        if (filled == packet_size || !compress_again)
        {
            cursor_shape->mutable_data()->resize(filled);
            return;
        }

        // If we have reached the end of the current row in the rectangle and
        // this is not the last row.
        if (row_pos == row_size && row_y < height - 1)
        {
            row_pos = 0;
            source_pos += row_size;
            ++row_y;
        }
    }
}

std::unique_ptr<proto::CursorShape> CursorEncoder::Encode(std::unique_ptr<MouseCursor> mouse_cursor)
{
    if (!mouse_cursor)
        return nullptr;

    const DesktopSize& size = mouse_cursor->Size();

    if (size.Width() <= 0 || size.Width() > (std::numeric_limits<int16_t>::max() / 2) ||
        size.Height() <= 0 || size.Height() > (std::numeric_limits<int16_t>::max() / 2))
    {
        DLOG(ERROR) << "Wrong size of cursor: " << size.Width() << "x" << size.Height();
        return nullptr;
    }

    std::unique_ptr<proto::CursorShape> cursor_shape(new proto::CursorShape());

    size_t index = cache_.Find(mouse_cursor.get());

    // The cursor is not found in the cache.
    if (index == MouseCursorCache::kInvalidIndex)
    {
        cursor_shape->set_width(size.Width());
        cursor_shape->set_height(size.Height());
        cursor_shape->set_hotspot_x(mouse_cursor->Hotspot().x());
        cursor_shape->set_hotspot_y(mouse_cursor->Hotspot().y());

        CompressCursor(cursor_shape.get(), mouse_cursor.get());

        // If the cache is empty, then set the cache reset flag on the client
        // side and pass the maximum cache size.
        cursor_shape->set_flags(cache_.IsEmpty() ?
            (proto::CursorShape::RESET_CACHE | (kCacheSize & 0x1F)) : 0);

        // Add the cursor to the cache.
        cache_.Add(std::move(mouse_cursor));
    }
    else
    {
        cursor_shape->set_flags(proto::CursorShape::CACHE | (index & 0x1F));
    }

    return cursor_shape;
}

} // namespace aspia
<|endoftext|>


<commit_before>#include "mocca/base/Thread.h"

using mocca::Thread;

std::mutex Thread::allThreadsMx_;
std::vector<Thread*> Thread::allThreads_;

Thread::Thread()
    : interrupted_(true)
    , thread_() {}

Thread::Thread(Thread&& other)
    : interrupted_(other.interrupted_.load())
    , thread_(std::move(other.thread_)) {
    other.interrupted_ = true;
    allThreads_.push_back(this);
}

Thread& Thread::operator=(Thread&& other) {
    if (thread_.joinable()) {
        thread_.join();
    }
    thread_ = std::move(other.thread_);
    return *this;
}

Thread::~Thread() {
    interrupted_ = true;
    if (thread_.joinable()) {
        thread_.join();
    }
    std::lock_guard<std::mutex> lock(allThreadsMx_);
    auto it = std::find(begin(allThreads_), end(allThreads_), this);
    if (it != end(allThreads_)) {
        allThreads_.erase(it);
    }
}

bool mocca::Thread::isInterrupted() const {
    return interrupted_;
}

void mocca::Thread::interrupt() {
    interrupted_ = true;
}

void mocca::Thread::interruptAll() {
    std::lock_guard<std::mutex> lock(allThreadsMx_);
    for (auto thread : allThreads_) {
        thread->interrupt();
    }
}<commit_msg>added missing include<commit_after>#include "mocca/base/Thread.h"

#include <algorithm>

using mocca::Thread;

std::mutex Thread::allThreadsMx_;
std::vector<Thread*> Thread::allThreads_;

Thread::Thread()
    : interrupted_(true)
    , thread_() {}

Thread::Thread(Thread&& other)
    : interrupted_(other.interrupted_.load())
    , thread_(std::move(other.thread_)) {
    other.interrupted_ = true;
    allThreads_.push_back(this);
}

Thread& Thread::operator=(Thread&& other) {
    if (thread_.joinable()) {
        thread_.join();
    }
    thread_ = std::move(other.thread_);
    return *this;
}

Thread::~Thread() {
    interrupted_ = true;
    if (thread_.joinable()) {
        thread_.join();
    }
    std::lock_guard<std::mutex> lock(allThreadsMx_);
    auto it = std::find(begin(allThreads_), end(allThreads_), this);
    if (it != end(allThreads_)) {
        allThreads_.erase(it);
    }
}

bool mocca::Thread::isInterrupted() const {
    return interrupted_;
}

void mocca::Thread::interrupt() {
    interrupted_ = true;
}

void mocca::Thread::interruptAll() {
    std::lock_guard<std::mutex> lock(allThreadsMx_);
    for (auto thread : allThreads_) {
        thread->interrupt();
    }
}<|endoftext|>


<commit_before>#include "VertexRenderer.hpp"
#include "FAST/SceneGraph.hpp"

namespace fast {

void VertexRenderer::draw(Matrix4f perspectiveMatrix, Matrix4f viewingMatrix, float zNear, float zFar, bool mode2D) {
    std::lock_guard<std::mutex> lock(mMutex);
    glEnable(GL_POINT_SPRITE); // Circles created in fragment shader will not work without this
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);

    activateShader();
    setShaderUniform("perspectiveTransform", perspectiveMatrix);
    setShaderUniform("viewTransform", viewingMatrix);

    for(auto it : mDataToRender) {
        // Delete old VAO
        if(mVAO.count(it.first) > 0)
            glDeleteVertexArrays(1, &mVAO[it.first]);
        // Create VAO
        uint VAO_ID;
        mVAO[it.first] = VAO_ID;
        glGenVertexArrays(1, &VAO_ID);
        glBindVertexArray(VAO_ID);

        Mesh::pointer points = std::static_pointer_cast<Mesh>(it.second);
        float pointSize = mDefaultPointSize;
        if(mInputSizes.count(it.first) > 0) {
            pointSize = mInputSizes[it.first];
        }
        bool useGlobalColor = false;
        Color color = Color::Green();
        if(mInputColors.count(it.first) > 0) {
            color = mInputColors[it.first];
            useGlobalColor = true;
        } else if(mDefaultColorSet) {
            color = mDefaultColor;
            useGlobalColor = true;
        }
        bool drawOnTop;
        if(mInputDrawOnTop.count(it.first) > 0) {
            drawOnTop = mInputDrawOnTop[it.first];
        } else {
            drawOnTop = mDefaultDrawOnTop;
        }
        if(drawOnTop)
            glDisable(GL_DEPTH_TEST);

        AffineTransformation::pointer transform = SceneGraph::getAffineTransformationFromData(points);
        setShaderUniform("transform", transform->getTransform());
        setShaderUniform("pointSize", pointSize);

        VertexBufferObjectAccess::pointer access = points->getVertexBufferObjectAccess(ACCESS_READ);
        GLuint* coordinateVBO = access->getCoordinateVBO();

        // Coordinates buffer
        glBindBuffer(GL_ARRAY_BUFFER, *coordinateVBO);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);

        // Color buffer
        if(access->hasColorVBO() && !useGlobalColor) {
            GLuint *colorVBO = access->getColorVBO();
            glBindBuffer(GL_ARRAY_BUFFER, *colorVBO);
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
            glEnableVertexAttribArray(1);
        } else {
            useGlobalColor = true;
        }
        setShaderUniform("useGlobalColor", useGlobalColor);
        setShaderUniform("globalColor", color.asVector());

        glDrawArrays(GL_POINTS, 0, points->getNrOfVertices());

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);

        if(drawOnTop)
            glEnable(GL_DEPTH_TEST);
    }

    deactivateShader();
}

void VertexRenderer::draw2D(
                cl::BufferGL PBO,
                uint width,
                uint height,
                Eigen::Transform<float, 3, Eigen::Affine> pixelToViewportTransform,
                float PBOspacing,
                Vector2f translation
        ) {
    std::lock_guard<std::mutex> lock(mMutex);

    OpenCLDevice::pointer device = std::dynamic_pointer_cast<OpenCLDevice>(getMainDevice());
    cl::CommandQueue queue = device->getCommandQueue();
    std::vector<cl::Memory> v;
    v.push_back(PBO);
    queue.enqueueAcquireGLObjects(&v);

    // Map would probably be better here, but doesn't work on NVIDIA, segfault surprise!
    //float* pixels = (float*)queue.enqueueMapBuffer(PBO, CL_TRUE, CL_MAP_WRITE, 0, width*height*sizeof(float)*4);
    std::unique_ptr<float[]> pixels(new float[width*height*sizeof(float)*4]);
    queue.enqueueReadBuffer(PBO, CL_TRUE, 0, width*height*4*sizeof(float), pixels.get());

    for(auto it : mDataToRender) {
    	Mesh::pointer points = std::static_pointer_cast<Mesh>(it.second);

		Color color = mDefaultColor;
        if(mInputColors.count(it.first) > 0) {
            color = mInputColors[it.first];
        }

    	MeshAccess::pointer access = points->getMeshAccess(ACCESS_READ);
        std::vector<MeshVertex> vertices = access->getVertices();

        // Draw each line
        int size = 3;
        for(int i = 0; i < vertices.size(); ++i) {
        	Vector2f position = vertices[i].getPosition().head(2); // In mm
        	Vector2i positinInPixles(
        			round(position.x() / PBOspacing),
        			round(position.y() / PBOspacing)
        	);

        	// Draw the line
        	for(int j = -size; j <= size; ++j) {
        	for(int k = -size; k <= size; ++k) {

        		int x = positinInPixles.x() + j;
        		int y = positinInPixles.y() + k;
        		y = height - 1 - y;
        		if(x < 0 || y < 0 || x >= width || y >= height)
        			continue;

        		pixels[4*(x + y*width)] = color.getRedValue();
        		pixels[4*(x + y*width) + 1] = color.getGreenValue();
        		pixels[4*(x + y*width) + 2] = color.getBlueValue();
        	}}
        }
    }

    //queue.enqueueUnmapMemObject(PBO, pixels);
    queue.enqueueWriteBuffer(PBO, CL_TRUE, 0, width*height*4*sizeof(float), pixels.get());
    queue.enqueueReleaseGLObjects(&v);
}

VertexRenderer::VertexRenderer() {
    mDefaultPointSize = 10;
    mDefaultColorSet = false;
    mDefaultDrawOnTop = false;
    createInputPort<Mesh>(0, false);

    createShaderProgram({
        Config::getKernelSourcePath() + "Visualization/VertexRenderer/VertexRenderer.vert",
        Config::getKernelSourcePath() + "Visualization/VertexRenderer/VertexRenderer.frag",
    });
}

uint VertexRenderer::addInputConnection(DataChannel::pointer port) {
    return Renderer::addInputConnection(port);
}

uint VertexRenderer::addInputConnection(DataChannel::pointer port, Color color,
        float size) {
    uint nr = addInputConnection(port);
    setColor(nr, color);
    setSize(nr, size);
    return nr;
}

uint VertexRenderer::addInputData(DataObject::pointer data) {
    return Renderer::addInputData(data);
}

uint VertexRenderer::addInputData(Mesh::pointer data, Color color, float size) {
    uint nr = addInputData(data);
    setColor(nr, color);
    setSize(nr, size);
	return nr;
}

void VertexRenderer::setDefaultColor(Color color) {
    mDefaultColor = color;
    mDefaultColorSet = true;
}

void VertexRenderer::setDefaultSize(float size) {
    mDefaultPointSize = size;
}

void VertexRenderer::setDefaultDrawOnTop(bool drawOnTop) {
    mDefaultDrawOnTop = drawOnTop;
}

void VertexRenderer::setDrawOnTop(uint inputNr, bool drawOnTop) {
    mInputDrawOnTop[inputNr] = drawOnTop;
}

void VertexRenderer::setColor(uint inputNr, Color color) {
    mInputColors[inputNr] = color;
}

void VertexRenderer::setSize(uint inputNr, float size) {
    mInputSizes[inputNr] = size;
}

} // end namespace fast
<commit_msg>fixed a OpenGL related memory leak in the VertexRenderer as reported by @androst<commit_after>#include "VertexRenderer.hpp"
#include "FAST/SceneGraph.hpp"

namespace fast {

void VertexRenderer::draw(Matrix4f perspectiveMatrix, Matrix4f viewingMatrix, float zNear, float zFar, bool mode2D) {
    std::lock_guard<std::mutex> lock(mMutex);
    glEnable(GL_POINT_SPRITE); // Circles created in fragment shader will not work without this
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);

    activateShader();
    setShaderUniform("perspectiveTransform", perspectiveMatrix);
    setShaderUniform("viewTransform", viewingMatrix);

    for(auto it : mDataToRender) {
        // Delete old VAO
        if(mVAO.count(it.first) > 0)
            glDeleteVertexArrays(1, &mVAO[it.first]);
        // Create VAO
        uint VAO_ID;
        glGenVertexArrays(1, &VAO_ID);
        mVAO[it.first] = VAO_ID;
        glBindVertexArray(VAO_ID);

        Mesh::pointer points = std::static_pointer_cast<Mesh>(it.second);
        float pointSize = mDefaultPointSize;
        if(mInputSizes.count(it.first) > 0) {
            pointSize = mInputSizes[it.first];
        }
        bool useGlobalColor = false;
        Color color = Color::Green();
        if(mInputColors.count(it.first) > 0) {
            color = mInputColors[it.first];
            useGlobalColor = true;
        } else if(mDefaultColorSet) {
            color = mDefaultColor;
            useGlobalColor = true;
        }
        bool drawOnTop;
        if(mInputDrawOnTop.count(it.first) > 0) {
            drawOnTop = mInputDrawOnTop[it.first];
        } else {
            drawOnTop = mDefaultDrawOnTop;
        }
        if(drawOnTop)
            glDisable(GL_DEPTH_TEST);

        auto transform = SceneGraph::getAffineTransformationFromData(points);
        setShaderUniform("transform", transform->getTransform());
        setShaderUniform("pointSize", pointSize);

        auto access = points->getVertexBufferObjectAccess(ACCESS_READ);
        GLuint* coordinateVBO = access->getCoordinateVBO();

        // Coordinates buffer
        glBindBuffer(GL_ARRAY_BUFFER, *coordinateVBO);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);

        // Color buffer
        if(access->hasColorVBO() && !useGlobalColor) {
            GLuint *colorVBO = access->getColorVBO();
            glBindBuffer(GL_ARRAY_BUFFER, *colorVBO);
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
            glEnableVertexAttribArray(1);
        } else {
            useGlobalColor = true;
        }
        setShaderUniform("useGlobalColor", useGlobalColor);
        setShaderUniform("globalColor", color.asVector());

        glDrawArrays(GL_POINTS, 0, points->getNrOfVertices());

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);

        if(drawOnTop)
            glEnable(GL_DEPTH_TEST);
    }

    deactivateShader();
}

void VertexRenderer::draw2D(
                cl::BufferGL PBO,
                uint width,
                uint height,
                Eigen::Transform<float, 3, Eigen::Affine> pixelToViewportTransform,
                float PBOspacing,
                Vector2f translation
        ) {
    std::lock_guard<std::mutex> lock(mMutex);

    OpenCLDevice::pointer device = std::dynamic_pointer_cast<OpenCLDevice>(getMainDevice());
    cl::CommandQueue queue = device->getCommandQueue();
    std::vector<cl::Memory> v;
    v.push_back(PBO);
    queue.enqueueAcquireGLObjects(&v);

    // Map would probably be better here, but doesn't work on NVIDIA, segfault surprise!
    //float* pixels = (float*)queue.enqueueMapBuffer(PBO, CL_TRUE, CL_MAP_WRITE, 0, width*height*sizeof(float)*4);
    std::unique_ptr<float[]> pixels(new float[width*height*sizeof(float)*4]);
    queue.enqueueReadBuffer(PBO, CL_TRUE, 0, width*height*4*sizeof(float), pixels.get());

    for(auto it : mDataToRender) {
    	Mesh::pointer points = std::static_pointer_cast<Mesh>(it.second);

		Color color = mDefaultColor;
        if(mInputColors.count(it.first) > 0) {
            color = mInputColors[it.first];
        }

    	MeshAccess::pointer access = points->getMeshAccess(ACCESS_READ);
        std::vector<MeshVertex> vertices = access->getVertices();

        // Draw each line
        int size = 3;
        for(int i = 0; i < vertices.size(); ++i) {
        	Vector2f position = vertices[i].getPosition().head(2); // In mm
        	Vector2i positinInPixles(
        			round(position.x() / PBOspacing),
        			round(position.y() / PBOspacing)
        	);

        	// Draw the line
        	for(int j = -size; j <= size; ++j) {
        	for(int k = -size; k <= size; ++k) {

        		int x = positinInPixles.x() + j;
        		int y = positinInPixles.y() + k;
        		y = height - 1 - y;
        		if(x < 0 || y < 0 || x >= width || y >= height)
        			continue;

        		pixels[4*(x + y*width)] = color.getRedValue();
        		pixels[4*(x + y*width) + 1] = color.getGreenValue();
        		pixels[4*(x + y*width) + 2] = color.getBlueValue();
        	}}
        }
    }

    //queue.enqueueUnmapMemObject(PBO, pixels);
    queue.enqueueWriteBuffer(PBO, CL_TRUE, 0, width*height*4*sizeof(float), pixels.get());
    queue.enqueueReleaseGLObjects(&v);
}

VertexRenderer::VertexRenderer() {
    mDefaultPointSize = 10;
    mDefaultColorSet = false;
    mDefaultDrawOnTop = false;
    createInputPort<Mesh>(0, false);

    createShaderProgram({
        Config::getKernelSourcePath() + "Visualization/VertexRenderer/VertexRenderer.vert",
        Config::getKernelSourcePath() + "Visualization/VertexRenderer/VertexRenderer.frag",
    });
}

uint VertexRenderer::addInputConnection(DataChannel::pointer port) {
    return Renderer::addInputConnection(port);
}

uint VertexRenderer::addInputConnection(DataChannel::pointer port, Color color,
        float size) {
    uint nr = addInputConnection(port);
    setColor(nr, color);
    setSize(nr, size);
    return nr;
}

uint VertexRenderer::addInputData(DataObject::pointer data) {
    return Renderer::addInputData(data);
}

uint VertexRenderer::addInputData(Mesh::pointer data, Color color, float size) {
    uint nr = addInputData(data);
    setColor(nr, color);
    setSize(nr, size);
	return nr;
}

void VertexRenderer::setDefaultColor(Color color) {
    mDefaultColor = color;
    mDefaultColorSet = true;
}

void VertexRenderer::setDefaultSize(float size) {
    mDefaultPointSize = size;
}

void VertexRenderer::setDefaultDrawOnTop(bool drawOnTop) {
    mDefaultDrawOnTop = drawOnTop;
}

void VertexRenderer::setDrawOnTop(uint inputNr, bool drawOnTop) {
    mInputDrawOnTop[inputNr] = drawOnTop;
}

void VertexRenderer::setColor(uint inputNr, Color color) {
    mInputColors[inputNr] = color;
}

void VertexRenderer::setSize(uint inputNr, float size) {
    mInputSizes[inputNr] = size;
}

} // end namespace fast
<|endoftext|>