<commit_before>#include "background_subtractor.h"

// static VALUE BackgroundSubtractorClass;
static VALUE BackgroundSubtractorModule;
static VALUE BGSMOGClass;
static VALUE BGSMOG2Class;
static VALUE BGSGMGClass;
static VALUE BGSPratiMediodClass;

namespace Spyglass {
  namespace BackgroundSubtractor {
    void define_ruby_types() {
      // Module definition
      BackgroundSubtractorModule = rb_define_module_under(Spyglass::get_ruby_module(), "BackgroundSubtractor");

      // Class definition: MOG
      BGSMOGClass = rb_define_class_under(BackgroundSubtractorModule, "MOG", rb_cObject);
      rb_define_alloc_func(BGSMOGClass, rb_mog_alloc);
      rb_define_method(BGSMOGClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
      rb_define_method(BGSMOGClass, "subtract", RUBY_METHOD_FUNC(rb_subtract), -1);

      // Class definition: MOG2
      BGSMOG2Class = rb_define_class_under(BackgroundSubtractorModule, "MOG2", rb_cObject);
      rb_define_alloc_func(BGSMOG2Class, rb_mog2_alloc);
      rb_define_method(BGSMOG2Class, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
      rb_define_method(BGSMOG2Class, "subtract", RUBY_METHOD_FUNC(rb_subtract), -1);

      // Class definition: GMG
      BGSGMGClass = rb_define_class_under(BackgroundSubtractorModule, "GMG", rb_cObject);
      rb_define_alloc_func(BGSGMGClass, rb_gmg_alloc);
      rb_define_method(BGSGMGClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
      rb_define_method(BGSGMGClass, "subtract", RUBY_METHOD_FUNC(rb_subtract), -1);

      // Class definition: PratiMediod
      BGSPratiMediodClass = rb_define_class_under(BackgroundSubtractorModule, "PratiMediod", rb_cObject);
      rb_define_alloc_func(BGSPratiMediodClass, rb_prati_mediod_alloc);
      rb_define_method(BGSPratiMediodClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
      rb_define_method(BGSPratiMediodClass, "subtract", RUBY_METHOD_FUNC(rb_subtract), -1);
    }

    VALUE get_ruby_module() {
      return BackgroundSubtractorModule;
    }

    static VALUE rb_mog_alloc(VALUE self) {
      cv::BackgroundSubtractor *bg = new cv::BackgroundSubtractorMOG();
      return Data_Wrap_Struct(BGSMOGClass, NULL, rb_free, bg);
    }

    static VALUE rb_mog2_alloc(VALUE self) {
      cv::BackgroundSubtractor *bg = new cv::BackgroundSubtractorMOG2();
      return Data_Wrap_Struct(BGSMOG2Class, NULL, rb_free, bg);
    }

    static VALUE rb_gmg_alloc(VALUE self) {
      cv::BackgroundSubtractor *bg = new cv::BackgroundSubtractorGMG();
      return Data_Wrap_Struct(BGSGMGClass, NULL, rb_free, bg);
    }

    static VALUE rb_prati_mediod_alloc(VALUE self) {
      cv::BackgroundSubtractor *bg = new DPPratiMediodBGS();
      return Data_Wrap_Struct(BGSPratiMediodClass, NULL, rb_free, bg);
    }

    static void rb_free(cv::BackgroundSubtractor *bg) {
      delete bg;
    }

    static VALUE rb_initialize(int argc, VALUE *argv, VALUE self) {
      VALUE opts;
      rb_scan_args(argc, argv, "01", &opts);

      if(!RTEST(opts))
        return self;

      cv::BackgroundSubtractor *bg = SG_GET_BG_SUBTRACTOR(self);

      if(CLASS_OF(self) == BGSMOGClass) {
        SG_OPTION(opts, int,    history,          200,  NUM2INT);
        SG_OPTION(opts, int,    mixtures,         5,    NUM2INT);
        SG_OPTION(opts, double, background_ratio, 0.7,  NUM2DBL);

        bg->set("history", history);
        bg->set("nmixtures", mixtures);
        bg->set("backgroundRatio", background_ratio);
      } else if(CLASS_OF(self) == BGSMOG2Class) {
        SG_OPTION(opts, int,    history,          500,  NUM2INT);
        SG_OPTION(opts, double, threshold,        8.0,  NUM2DBL);
        SG_OPTION(opts, bool,   shadow_detection, true, RTEST);

        bg->set("history", history);
        bg->set("varThreshold", threshold);
        bg->set("detectShadows", shadow_detection);
      } else if(CLASS_OF(self) == BGSPratiMediodClass) {
        SG_OPTION(opts, int, history,       16, NUM2INT);
        SG_OPTION(opts, int, threshold,     30, NUM2INT);
        SG_OPTION(opts, int, sampling_rate, 5,  NUM2INT);

        bg->set("historySize", history);
        bg->set("threshold", threshold);
        bg->set("samplingRate", sampling_rate);
      }

      return self;
    }

    static VALUE rb_subtract(int argc, VALUE *argv, VALUE self) {
      VALUE image, learn_rate;
      double rate;

      rb_scan_args(argc, argv, "11", &image, &learn_rate);

      if(CLASS_OF(image) != Image::get_ruby_class()) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Image)",
            rb_obj_classname(image));
      }

      if(RTEST(learn_rate) && TYPE(learn_rate) != T_FLOAT && TYPE(learn_rate) != T_FIXNUM)
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Float or Fixnum)",
            rb_obj_classname(learn_rate));

      rate = RTEST(learn_rate) ? NUM2DBL(learn_rate) : -1.0;

      cv::BackgroundSubtractor *bg  = SG_GET_BG_SUBTRACTOR(self);
      cv::Mat *img                  = SG_GET_IMAGE(image);

      cv::Mat *delta = new cv::Mat();
      (*bg)(*img, *delta, rate);

      return Image::from_cvmat(delta);
    }
  }
}
<commit_msg>Remove old class def. variable.<commit_after>#include "background_subtractor.h"

static VALUE BackgroundSubtractorModule;
static VALUE BGSMOGClass;
static VALUE BGSMOG2Class;
static VALUE BGSGMGClass;
static VALUE BGSPratiMediodClass;

namespace Spyglass {
  namespace BackgroundSubtractor {
    void define_ruby_types() {
      // Module definition
      BackgroundSubtractorModule = rb_define_module_under(Spyglass::get_ruby_module(), "BackgroundSubtractor");

      // Class definition: MOG
      BGSMOGClass = rb_define_class_under(BackgroundSubtractorModule, "MOG", rb_cObject);
      rb_define_alloc_func(BGSMOGClass, rb_mog_alloc);
      rb_define_method(BGSMOGClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
      rb_define_method(BGSMOGClass, "subtract", RUBY_METHOD_FUNC(rb_subtract), -1);

      // Class definition: MOG2
      BGSMOG2Class = rb_define_class_under(BackgroundSubtractorModule, "MOG2", rb_cObject);
      rb_define_alloc_func(BGSMOG2Class, rb_mog2_alloc);
      rb_define_method(BGSMOG2Class, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
      rb_define_method(BGSMOG2Class, "subtract", RUBY_METHOD_FUNC(rb_subtract), -1);

      // Class definition: GMG
      BGSGMGClass = rb_define_class_under(BackgroundSubtractorModule, "GMG", rb_cObject);
      rb_define_alloc_func(BGSGMGClass, rb_gmg_alloc);
      rb_define_method(BGSGMGClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
      rb_define_method(BGSGMGClass, "subtract", RUBY_METHOD_FUNC(rb_subtract), -1);

      // Class definition: PratiMediod
      BGSPratiMediodClass = rb_define_class_under(BackgroundSubtractorModule, "PratiMediod", rb_cObject);
      rb_define_alloc_func(BGSPratiMediodClass, rb_prati_mediod_alloc);
      rb_define_method(BGSPratiMediodClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
      rb_define_method(BGSPratiMediodClass, "subtract", RUBY_METHOD_FUNC(rb_subtract), -1);
    }

    VALUE get_ruby_module() {
      return BackgroundSubtractorModule;
    }

    static VALUE rb_mog_alloc(VALUE self) {
      cv::BackgroundSubtractor *bg = new cv::BackgroundSubtractorMOG();
      return Data_Wrap_Struct(BGSMOGClass, NULL, rb_free, bg);
    }

    static VALUE rb_mog2_alloc(VALUE self) {
      cv::BackgroundSubtractor *bg = new cv::BackgroundSubtractorMOG2();
      return Data_Wrap_Struct(BGSMOG2Class, NULL, rb_free, bg);
    }

    static VALUE rb_gmg_alloc(VALUE self) {
      cv::BackgroundSubtractor *bg = new cv::BackgroundSubtractorGMG();
      return Data_Wrap_Struct(BGSGMGClass, NULL, rb_free, bg);
    }

    static VALUE rb_prati_mediod_alloc(VALUE self) {
      cv::BackgroundSubtractor *bg = new DPPratiMediodBGS();
      return Data_Wrap_Struct(BGSPratiMediodClass, NULL, rb_free, bg);
    }

    static void rb_free(cv::BackgroundSubtractor *bg) {
      delete bg;
    }

    static VALUE rb_initialize(int argc, VALUE *argv, VALUE self) {
      VALUE opts;
      rb_scan_args(argc, argv, "01", &opts);

      if(!RTEST(opts))
        return self;

      cv::BackgroundSubtractor *bg = SG_GET_BG_SUBTRACTOR(self);

      if(CLASS_OF(self) == BGSMOGClass) {
        SG_OPTION(opts, int,    history,          200,  NUM2INT);
        SG_OPTION(opts, int,    mixtures,         5,    NUM2INT);
        SG_OPTION(opts, double, background_ratio, 0.7,  NUM2DBL);

        bg->set("history", history);
        bg->set("nmixtures", mixtures);
        bg->set("backgroundRatio", background_ratio);
      } else if(CLASS_OF(self) == BGSMOG2Class) {
        SG_OPTION(opts, int,    history,          500,  NUM2INT);
        SG_OPTION(opts, double, threshold,        8.0,  NUM2DBL);
        SG_OPTION(opts, bool,   shadow_detection, true, RTEST);

        bg->set("history", history);
        bg->set("varThreshold", threshold);
        bg->set("detectShadows", shadow_detection);
      } else if(CLASS_OF(self) == BGSPratiMediodClass) {
        SG_OPTION(opts, int, history,       16, NUM2INT);
        SG_OPTION(opts, int, threshold,     30, NUM2INT);
        SG_OPTION(opts, int, sampling_rate, 5,  NUM2INT);

        bg->set("historySize", history);
        bg->set("threshold", threshold);
        bg->set("samplingRate", sampling_rate);
      }

      return self;
    }

    static VALUE rb_subtract(int argc, VALUE *argv, VALUE self) {
      VALUE image, learn_rate;
      double rate;

      rb_scan_args(argc, argv, "11", &image, &learn_rate);

      if(CLASS_OF(image) != Image::get_ruby_class()) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Image)",
            rb_obj_classname(image));
      }

      if(RTEST(learn_rate) && TYPE(learn_rate) != T_FLOAT && TYPE(learn_rate) != T_FIXNUM)
        rb_raise(rb_eTypeError, "wrong argument type %s (expected Float or Fixnum)",
            rb_obj_classname(learn_rate));

      rate = RTEST(learn_rate) ? NUM2DBL(learn_rate) : -1.0;

      cv::BackgroundSubtractor *bg  = SG_GET_BG_SUBTRACTOR(self);
      cv::Mat *img                  = SG_GET_IMAGE(image);

      cv::Mat *delta = new cv::Mat();
      (*bg)(*img, *delta, rate);

      return Image::from_cvmat(delta);
    }
  }
}
<|endoftext|>


<commit_before>//
// Realm C++ coding standard - by example
//

// Lines should never exceed 118 characters --------------------------------------------------------------------------

// Macro names use uppercase and have "REALM_" as prefix. Non-macro
// names never use all uppercase.

#define REALM_MY_MACRO 1

// A function name uses lowercase and its parts are separated by
// underscores.

my_type my_func()
{
    // Put the opening brace of a function body in the next line below
    // the function prototype. This also applies to class member
    // functions.

    // Put all other opening braces on the same line as the syntax
    // element to which the brace is subordinate.

    // Use 4 spaces per indentation level (no tabs please).

    if (...) {
        // ...
    }
    else {
        // ...
    }

    // Always put subordinate statements on a new line (to ease
    // debugging).

    if (...)
        return ...;

    // No space between type and '*' or '&'
    int* foo1 = ...;
    int& foo2 = ...;

    // 'const' goes before the type
    const int foo3 = ...;

    // ... but not when 'const' operates on a pointer type
    const int* foo3 = ...; // 'const' operates on 'int' not 'int*'
    int* const foo4 = ...; // 'const' operates on 'int*'
    int* const* const foo5 = ...;
}

void my_func_2()
{
    // This indentation and brace placement style agrees with K&R
    // style except for the 'extra' indentation of 'cases' in a switch
    // statement.

    switch (...) {
        case type_Foo: {
            // ...
            break;
        }
        case type_FooBar: {
            // ...
            break;
        }
    }

    try {
        // ...
    }
    catch (...) {
        // ...
    }
}

// A name space name uses lowercase and its parts are separated by
// underscores.

namespace my_namespace {

// No indentation inside name spaces.

// A Class name uses CamelCase with uppercase initial.

template<class T>
class MyClass: public Base {
public:
    MyClass(...):
        Base(...),
        m_bar(7),
        ...
    {
        // ...
    }

private:
    // Static member variables have prefix 's_'.
    static int s_foo;

    // Regular member variables have prefix 'm_'.
    int m_bar;
};

} // namespace my_namespace

// Names of values of an enumeration are composed of two parts
// separated by an underscore. The first part is a common lowercase
// prefix. The second part identifies the value and uses CamelCase
// with uppercase initial.

enum mode {
    mode_Foo,
    mode_FooBar
};

// Order of class members (roughly):

class MyClass2 {
public:
    // Types

    // Static variables
    // Regular variables

    // Static functions
    // Regular functions

protected:
    // Same as 'public'

private:
    // Same as 'public'

    // Friends
};

// About FIXMEs:
//
// A FIXME conveys information about a known issue or shortcoming. It
// may also include information on how to fix the problem, and on
// possible conflicts with anticipated future features.
//
// A FIXME is often added in the following situations:
//
// - While working on, or studying a particular part of the code you
//   uncover an issue or a shortcoming. Additionally, you may have
//   gained an understanding of how to fix it.
//
// - While implementing a new feature, you are forced to cut a corner,
//   but you have some good ideas about how to continue later, and/or
//   you may have knowledge about a certain planned feature that would
//   require a more complete solution.
//
// A FIXME is generally not about a bug or an error, and is should
// generally not be considered a task either. Is is simply a memo to
// oneself or to some other developer who is going to work on the code
// at some later point in time.
//
// A FIXME should never be deleted unless by somebody who understands
// the mening of it and knows that the problem is fixed, or has
// otherwise diappeard.
<commit_msg>Update coding_style_guide.cpp<commit_after>//
// Realm C++ coding standard - by example
//

// Lines should never exceed 118 characters --------------------------------------------------------------------------

// Macro names use uppercase and have "REALM_" as prefix. Non-macro
// names never use all uppercase.

#define REALM_MY_MACRO 1

// A function name uses lowercase and its parts are separated by
// underscores.

my_type my_func()
{
    // Put the opening brace of a function body in the next line below
    // the function prototype. This also applies to class member
    // functions.

    // Put all other opening braces on the same line as the syntax
    // element to which the brace is subordinate.

    // Use 4 spaces per indentation level (no tabs please).

    if (...) {
        // ...
    }
    else {
        // ...
    }

    // Always put subordinate statements on a new line (to ease
    // debugging).

    if (...)
        return ...;

    // No space between type and '*' or '&'
    int* foo1 = ...;
    int& foo2 = ...;

    // 'const' goes before the type
    const int foo3 = ...;

    // ... but not when 'const' operates on a pointer type
    const int* foo3 = ...; // 'const' operates on 'int' not 'int*'
    int* const foo4 = ...; // 'const' operates on 'int*'
    int* const* const foo5 = ...;
}

void my_func_2()
{
    // This indentation and brace placement style agrees with K&R
    // style except for the 'extra' indentation of 'cases' in a switch
    // statement.

    switch (...) {
        case type_Foo: {
            // ...
            break;
        }
        case type_FooBar: {
            // ...
            break;
        }
    }

    try {
        // ...
    }
    catch (...) {
        // ...
    }
}

// A name space name uses lowercase and its parts are separated by
// underscores.

namespace my_namespace {

// No indentation inside name spaces.

// A Class name uses CamelCase with uppercase initial.

template<class T>
class MyClass: public Base {
public:
    MyClass(...):
        Base(...),
        m_bar(7),
        ...
    {
        // ...
    }

private:
    // Static member variables have prefix 's_'.
    static int s_foo;

    // Regular member variables have prefix 'm_'.
    int m_bar;
};

} // namespace my_namespace

// Names of values of an enumeration are composed of two parts
// separated by an underscore. The first part is a common lowercase
// prefix. The second part identifies the value and uses CamelCase
// with uppercase initial.

enum mode {
    mode_Foo,
    mode_FooBar
};

// Order of class members (roughly):

class MyClass2 {
public:
    // Types

    // Static variables
    // Regular variables

    // Static functions
    // Regular functions

protected:
    // Same as 'public'

private:
    // Same as 'public'

    // Friends
};

// Use of 'auto' keyword:
//
// 'auto' should *not* be used for trivial cases where the type declaration
// is short, non-templated, and non-derived (type_t, int64_t, std::string,
// etc.

// About FIXMEs:
//
// A FIXME conveys information about a known issue or shortcoming. It
// may also include information on how to fix the problem, and on
// possible conflicts with anticipated future features.
//
// A FIXME is often added in the following situations:
//
// - While working on, or studying a particular part of the code you
//   uncover an issue or a shortcoming. Additionally, you may have
//   gained an understanding of how to fix it.
//
// - While implementing a new feature, you are forced to cut a corner,
//   but you have some good ideas about how to continue later, and/or
//   you may have knowledge about a certain planned feature that would
//   require a more complete solution.
//
// A FIXME is generally not about a bug or an error, and is should
// generally not be considered a task either. Is is simply a memo to
// oneself or to some other developer who is going to work on the code
// at some later point in time.
//
// A FIXME should never be deleted unless by somebody who understands
// the mening of it and knows that the problem is fixed, or has
// otherwise diappeard.
<|endoftext|>


<commit_before>/*
 Copyright (c) 2015, The Cinder Project, All rights reserved.

 This code is intended for use with the Cinder C++ library: http://libcinder.org

 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.
 * 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 "cinder/gl/ShaderPreprocessor.h"
#include "cinder/gl/gl.h"
#include "cinder/app/Platform.h"
#include "cinder/Utilities.h"
#include "cinder/Log.h"

#include <regex>

using namespace std;

namespace cinder { namespace gl {

namespace {
	const regex sIncludeRegex = regex( "^[ \t]*#[ ]*include[ ]+[\"<](.*)[\">].*" );
} // anonymous namespace

ShaderPreprocessor::ShaderPreprocessor()
{
	mSearchDirectories.push_back( app::Platform::get()->getAssetPath( "" ) );

	// set the default version
#if defined( CINDER_GL_ES_3 )
	mVersion = 300;
#elif defined( CINDER_GL_ES_2 )
	mVersion = 110;
#else // desktop
	mVersion = 150;
#endif
}

string ShaderPreprocessor::parse( const fs::path &sourcePath )
{
	set<fs::path> includeTree;

	return parseDirectives( parseRecursive( sourcePath, fs::path(), includeTree ) );
}

string ShaderPreprocessor::parse( const std::string &source, const fs::path &sourcePath )
{
	CI_ASSERT( ! fs::is_directory( sourcePath ) );

	return parseDirectives( parseTopLevel( source, sourcePath.parent_path() ) );
}

std::string ShaderPreprocessor::parseDirectives( const std::string &source )
{
	stringstream output;
	istringstream input( source );

	string version;

	// go through each line and find the #version directive
	string line;
	while( getline( input, line ) ) {
		if( line.find( "#version" ) != string::npos ) {
			version = line;
		}
		else
			output << line;
		output << endl;
	}

	// if we don't have a version yet, add the default one
	if( version.empty() ) {
#if defined( CINDER_GL_ES )
		version = "#version " + to_string( mVersion ) + "es\n";
#else
		version = "#version " + to_string( mVersion ) + "\n";
#endif
	}
	else
		version += "\n";

	// copy the preprocessor directives to a string starting with the version
	std::string directivesString = version;
	for( auto define : mDefineDirectives ) {
		directivesString += "#define " + define + "\n";
	}

	return directivesString + output.str();
}

string ShaderPreprocessor::parseTopLevel( const string &source, const fs::path &currentDirectory )
{
	set<fs::path> includeTree;

	stringstream output;
	istringstream input( source );

	// go through each line and process includes
	string line;
	smatch matches;

	size_t lineNumber = 1;

	while( getline( input, line ) ) {
		if( regex_search( line, matches, sIncludeRegex ) ) {
			output << parseRecursive( matches[1].str(), currentDirectory, includeTree );
			output << "#line " << lineNumber << endl;
		}
		else
			output << line;

		output << endl;
		lineNumber++;
	}

	return output.str();
}

string ShaderPreprocessor::parseRecursive( const fs::path &path, const fs::path &currentDirectory, set<fs::path> &includeTree )
{
	const fs::path fullPath = findFullPath( path, currentDirectory );

	if( includeTree.count( fullPath ) )
		throw ShaderPreprocessorExc( "circular include found, path: " + fullPath.string() );

	includeTree.insert( fullPath );

	stringstream output;
	ifstream input( fullPath.c_str() );
	if( ! input.is_open() )
		throw ShaderPreprocessorExc( "Failed to open file at path: " + fullPath.string() );

	// go through each line and process includes
	string line;
	smatch matches;

	size_t lineNumber = 1;

	while( getline( input, line ) ) {
		if( regex_search( line, matches, sIncludeRegex ) ) {
			output << parseRecursive( matches[1].str(), fullPath.parent_path(), includeTree );
			output << "#line " << lineNumber << endl;
		}
		else
			output << line;

		output << endl;
		lineNumber++;
	}

	input.close();
	return output.str();
}

void ShaderPreprocessor::addSearchDirectory( const fs::path &directory )
{
	if( ! fs::is_directory( directory ) ) {
		CI_LOG_E( "Not a directory: " << directory );
		return;
	}

	fs::path dirCanonical = fs::canonical( directory );
	auto it = find( mSearchDirectories.begin(), mSearchDirectories.end(), dirCanonical );
	if( it == mSearchDirectories.end() )
		mSearchDirectories.push_back( dirCanonical );
}

void ShaderPreprocessor::removeSearchDirectory( const fs::path &directory )
{
	fs::path dirCanonical = fs::canonical( directory );
	mSearchDirectories.erase( remove( mSearchDirectories.begin(), mSearchDirectories.end(), dirCanonical ), mSearchDirectories.end() );
}

void ShaderPreprocessor::addDefine( const std::string &define )
{
	mDefineDirectives.push_back( define );
}

void ShaderPreprocessor::addDefine( const std::string &define, const std::string &value )
{
	mDefineDirectives.push_back( define + " " + value );
}
void ShaderPreprocessor::setDefineDirectives( const std::vector<std::string> &defines )
{
	mDefineDirectives = defines;
}

fs::path ShaderPreprocessor::findFullPath( const fs::path &includePath, const fs::path &currentDirectory )
{
	auto fullPath = currentDirectory / includePath;
	if( fs::exists( fullPath ) )
		return fs::canonical( fullPath );

	for( auto dirIt = mSearchDirectories.rbegin(); dirIt != mSearchDirectories.rend(); ++dirIt ) {
		fullPath = *dirIt / includePath;
		if( fs::exists( fullPath ) )
			return fs::canonical( fullPath );
	}

	throw ShaderPreprocessorExc( "could not find shader with include path: " + includePath.string() );
}

} } // namespace cinder::gl
<commit_msg>fix winrt build error due to it being stuck on boost::filesystem V2, still have to deal with lack of fs::canonical() there..<commit_after>/*
 Copyright (c) 2015, The Cinder Project, All rights reserved.

 This code is intended for use with the Cinder C++ library: http://libcinder.org

 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.
 * 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 "cinder/gl/ShaderPreprocessor.h"
#include "cinder/gl/gl.h"
#include "cinder/app/Platform.h"
#include "cinder/Utilities.h"
#include "cinder/Log.h"

#include <regex>

using namespace std;

namespace cinder { namespace gl {

namespace {
	const regex sIncludeRegex = regex( "^[ \t]*#[ ]*include[ ]+[\"<](.*)[\">].*" );
} // anonymous namespace

ShaderPreprocessor::ShaderPreprocessor()
{
	mSearchDirectories.push_back( app::Platform::get()->getAssetPath( "" ) );

	// set the default version
#if defined( CINDER_GL_ES_3 )
	mVersion = 300;
#elif defined( CINDER_GL_ES_2 )
	mVersion = 110;
#else // desktop
	mVersion = 150;
#endif
}

string ShaderPreprocessor::parse( const fs::path &sourcePath )
{
	set<fs::path> includeTree;

	return parseDirectives( parseRecursive( sourcePath, fs::path(), includeTree ) );
}

string ShaderPreprocessor::parse( const std::string &source, const fs::path &sourcePath )
{
	CI_ASSERT( ! fs::is_directory( sourcePath ) );

	return parseDirectives( parseTopLevel( source, sourcePath.parent_path() ) );
}

std::string ShaderPreprocessor::parseDirectives( const std::string &source )
{
	stringstream output;
	istringstream input( source );

	string version;

	// go through each line and find the #version directive
	string line;
	while( getline( input, line ) ) {
		if( line.find( "#version" ) != string::npos ) {
			version = line;
		}
		else
			output << line;
		output << endl;
	}

	// if we don't have a version yet, add the default one
	if( version.empty() ) {
#if defined( CINDER_GL_ES )
		version = "#version " + to_string( mVersion ) + "es\n";
#else
		version = "#version " + to_string( mVersion ) + "\n";
#endif
	}
	else
		version += "\n";

	// copy the preprocessor directives to a string starting with the version
	std::string directivesString = version;
	for( auto define : mDefineDirectives ) {
		directivesString += "#define " + define + "\n";
	}

	return directivesString + output.str();
}

string ShaderPreprocessor::parseTopLevel( const string &source, const fs::path &currentDirectory )
{
	set<fs::path> includeTree;

	stringstream output;
	istringstream input( source );

	// go through each line and process includes
	string line;
	smatch matches;

	size_t lineNumber = 1;

	while( getline( input, line ) ) {
		if( regex_search( line, matches, sIncludeRegex ) ) {
			output << parseRecursive( matches[1].str(), currentDirectory, includeTree );
			output << "#line " << lineNumber << endl;
		}
		else
			output << line;

		output << endl;
		lineNumber++;
	}

	return output.str();
}

string ShaderPreprocessor::parseRecursive( const fs::path &path, const fs::path &currentDirectory, set<fs::path> &includeTree )
{
	const fs::path fullPath = findFullPath( path, currentDirectory );

	if( includeTree.count( fullPath ) )
		throw ShaderPreprocessorExc( "circular include found, path: " + fullPath.string() );

	includeTree.insert( fullPath );

	stringstream output;
	ifstream input( fullPath.string().c_str() );
	if( ! input.is_open() )
		throw ShaderPreprocessorExc( "Failed to open file at path: " + fullPath.string() );

	// go through each line and process includes
	string line;
	smatch matches;

	size_t lineNumber = 1;

	while( getline( input, line ) ) {
		if( regex_search( line, matches, sIncludeRegex ) ) {
			output << parseRecursive( matches[1].str(), fullPath.parent_path(), includeTree );
			output << "#line " << lineNumber << endl;
		}
		else
			output << line;

		output << endl;
		lineNumber++;
	}

	input.close();
	return output.str();
}

void ShaderPreprocessor::addSearchDirectory( const fs::path &directory )
{
	if( ! fs::is_directory( directory ) ) {
		CI_LOG_E( "Not a directory: " << directory );
		return;
	}

	fs::path dirCanonical = fs::canonical( directory );
	auto it = find( mSearchDirectories.begin(), mSearchDirectories.end(), dirCanonical );
	if( it == mSearchDirectories.end() )
		mSearchDirectories.push_back( dirCanonical );
}

void ShaderPreprocessor::removeSearchDirectory( const fs::path &directory )
{
	fs::path dirCanonical = fs::canonical( directory );
	mSearchDirectories.erase( remove( mSearchDirectories.begin(), mSearchDirectories.end(), dirCanonical ), mSearchDirectories.end() );
}

void ShaderPreprocessor::addDefine( const std::string &define )
{
	mDefineDirectives.push_back( define );
}

void ShaderPreprocessor::addDefine( const std::string &define, const std::string &value )
{
	mDefineDirectives.push_back( define + " " + value );
}
void ShaderPreprocessor::setDefineDirectives( const std::vector<std::string> &defines )
{
	mDefineDirectives = defines;
}

fs::path ShaderPreprocessor::findFullPath( const fs::path &includePath, const fs::path &currentDirectory )
{
	auto fullPath = currentDirectory / includePath;
	if( fs::exists( fullPath ) )
		return fs::canonical( fullPath );

	for( auto dirIt = mSearchDirectories.rbegin(); dirIt != mSearchDirectories.rend(); ++dirIt ) {
		fullPath = *dirIt / includePath;
		if( fs::exists( fullPath ) )
			return fs::canonical( fullPath );
	}

	throw ShaderPreprocessorExc( "could not find shader with include path: " + includePath.string() );
}

} } // namespace cinder::gl
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: vclevent.cxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#include <vcl/vclevent.hxx>

TYPEINIT0(VclSimpleEvent);
TYPEINIT1(VclWindowEvent, VclSimpleEvent);
TYPEINIT1(VclMenuEvent, VclSimpleEvent);

void VclEventListeners::Call( VclSimpleEvent* pEvent ) const
{
    // Copy the list, because this can be destroyed when calling a Link...
    std::list<Link> aCopy( *this );
    std::list<Link>::iterator aIter( aCopy.begin() );
    while ( aIter != aCopy.end() )
    {
        (*aIter).Call( pEvent );
        aIter++;
    }
}

BOOL VclEventListeners::Process( VclSimpleEvent* pEvent ) const
{
    BOOL bProcessed = FALSE;
    // Copy the list, because this can be destroyed when calling a Link...
    std::list<Link> aCopy( *this );
    std::list<Link>::iterator aIter( aCopy.begin() );
    while ( aIter != aCopy.end() )
    {
        if( (*aIter).Call( pEvent ) != 0 )
        {
            bProcessed = TRUE;
            break;
        }
        aIter++;
    }
    return bProcessed;
}
<commit_msg>INTEGRATION: CWS aquavcl07 (1.6.4); FILE MERGED 2008/05/14 20:21:13 pl 1.6.4.1: #i78832# protect window event handlers against handler destroying the window<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: vclevent.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#include "vcl/vclevent.hxx"
#include "vcl/svdata.hxx"

TYPEINIT0(VclSimpleEvent);
TYPEINIT1(VclWindowEvent, VclSimpleEvent);
TYPEINIT1(VclMenuEvent, VclSimpleEvent);

void VclEventListeners::Call( VclSimpleEvent* pEvent ) const
{
    // Copy the list, because this can be destroyed when calling a Link...
    std::list<Link> aCopy( *this );
    std::list<Link>::iterator aIter( aCopy.begin() );
    if( pEvent->IsA( VclWindowEvent::StaticType() ) )
    {
        VclWindowEvent* pWinEvent = static_cast<VclWindowEvent*>(pEvent);
        ImplDelData aDel( pWinEvent->GetWindow() );
        while ( aIter != aCopy.end() && ! aDel.IsDead() )
        {
            (*aIter).Call( pEvent );
            aIter++;
        }
    }
    else
    {
        while ( aIter != aCopy.end() )
        {
            (*aIter).Call( pEvent );
            aIter++;
        }
    }
}

BOOL VclEventListeners::Process( VclSimpleEvent* pEvent ) const
{
    BOOL bProcessed = FALSE;
    // Copy the list, because this can be destroyed when calling a Link...
    std::list<Link> aCopy( *this );
    std::list<Link>::iterator aIter( aCopy.begin() );
    while ( aIter != aCopy.end() )
    {
        if( (*aIter).Call( pEvent ) != 0 )
        {
            bProcessed = TRUE;
            break;
        }
        aIter++;
    }
    return bProcessed;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ctrl.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: pl $ $Date: 2002-05-16 11:52:50 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#define _SV_CTRL_CXX

#ifndef _SV_RC_H
#include <rc.h>
#endif
#ifndef _SV_SVDATA_HXX
#include <svdata.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <svapp.hxx>
#endif
#ifndef _SV_EVENT_HXX
#include <event.hxx>
#endif
#ifndef _SV_CTRL_HXX
#include <ctrl.hxx>
#endif
#ifndef _VCL_CONTROLLAYOUT_HXX
#include <controllayout.hxx>
#endif

#pragma hdrstop

using namespace vcl;

// =======================================================================

void Control::ImplInitData()
{
    mbHasFocus      = FALSE;
    mpLayoutData    = NULL;
}

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

Control::Control( WindowType nType ) :
    Window( nType )
{
    ImplInitData();
}

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

Control::Control( Window* pParent, WinBits nStyle ) :
    Window( WINDOW_CONTROL )
{
    ImplInitData();
    Window::ImplInit( pParent, nStyle, NULL );
}

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

Control::Control( Window* pParent, const ResId& rResId ) :
    Window( WINDOW_CONTROL )
{
    ImplInitData();
    rResId.SetRT( RSC_CONTROL );
    WinBits nStyle = ImplInitRes( rResId );
    ImplInit( pParent, nStyle, NULL );
    ImplLoadRes( rResId );

    if ( !(nStyle & WB_HIDE) )
        Show();
}

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

Control::~Control()
{
    delete mpLayoutData, mpLayoutData = NULL;
}

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

void Control::GetFocus()
{
    Window::GetFocus();
}

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

void Control::LoseFocus()
{
    Window::LoseFocus();
}

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

void Control::Resize()
{
    delete mpLayoutData, mpLayoutData = NULL;
    Window::Resize();
}

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

void Control::FillLayoutData() const
{
}

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

void Control::SetText( const String& rStr )
{
    delete mpLayoutData;
    mpLayoutData = NULL;
    Window::SetText( rStr );
}

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

Rectangle ControlLayoutData::GetCharacterBounds( long nIndex ) const
{
    return (nIndex >= 0 && nIndex < m_aUnicodeBoundRects.size()) ? m_aUnicodeBoundRects[ nIndex ] : Rectangle();
}

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

Rectangle Control::GetCharacterBounds( long nIndex ) const
{
    if( ! mpLayoutData )
        FillLayoutData();
    return mpLayoutData ? mpLayoutData->GetCharacterBounds( nIndex ) : Rectangle();
}

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

long ControlLayoutData::GetIndexForPoint( const Point& rPoint ) const
{
    long nIndex = -1;
    for( long i = m_aUnicodeBoundRects.size()-1; i >= 0; i-- )
    {
        if( m_aUnicodeBoundRects[ i ].IsInside( rPoint ) )
        {
            nIndex = i;
            break;
        }
    }
    return nIndex;
}

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

long Control::GetIndexForPoint( const Point& rPoint ) const
{
    long nIndex = -1;
    if( ! mpLayoutData )
        FillLayoutData();
    return mpLayoutData ? mpLayoutData->GetIndexForPoint( rPoint ) : -1;
}

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

long ControlLayoutData::GetLineCount() const
{
    long nLines = m_aLineIndices.size();
    if( nLines == 0 && m_aDisplayText.Len() )
        nLines = 1;
    return nLines;
}

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

long Control::GetLineCount() const
{
    if( ! mpLayoutData )
        FillLayoutData();
    return mpLayoutData ? mpLayoutData->GetLineCount() : 0;
}

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

Pair ControlLayoutData::GetLineStartEnd( long nLine ) const
{
    Pair aPair( -1, -1 );

    int nDisplayLines = m_aLineIndices.size();
    if( nLine >= 0 && nLine < nDisplayLines )
    {
        aPair.A() = m_aLineIndices[nLine];
        if( nLine+1 < m_aLineIndices.size() )
            aPair.B() = m_aLineIndices[nLine+1]-1;
        else
            aPair.B() = m_aDisplayText.Len()-1;
    }
    else if( nLine == 0 && nDisplayLines == 0 && m_aDisplayText.Len() )
    {
        // special case for single line controls so the implementations
        // in that case do not have to fill in the line indices
        aPair.A() = 0;
        aPair.B() = m_aDisplayText.Len()-1;
    }
    return aPair;
}

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

Pair Control::GetLineStartEnd( long nLine ) const
{
    if( ! mpLayoutData )
        FillLayoutData();
    return mpLayoutData ? mpLayoutData->GetLineStartEnd( nLine ) : Pair( -1, -1 );
}

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

String Control::GetDisplayText() const
{
    if( ! mpLayoutData )
        FillLayoutData();
    return mpLayoutData ? mpLayoutData->m_aDisplayText : GetText();
}

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

long Control::Notify( NotifyEvent& rNEvt )
{
    if ( rNEvt.GetType() == EVENT_GETFOCUS )
    {
        if ( !mbHasFocus )
        {
            mbHasFocus = TRUE;
            ImplDelData aDelData;
            ImplAddDel( &aDelData );
            ImplCallEventListeners( VCLEVENT_CONTROL_GETFOCUS );
            if ( aDelData.IsDelete() )
                return TRUE;
            maGetFocusHdl.Call( this );
            if ( aDelData.IsDelete() )
                return TRUE;
            ImplRemoveDel( &aDelData );
        }
    }
    else
    {
        if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
        {
            Window* pFocusWin = Application::GetFocusWindow();
            if ( !pFocusWin || !ImplIsWindowOrChild( pFocusWin ) )
            {
                mbHasFocus = FALSE;
                ImplDelData aDelData;
                ImplAddDel( &aDelData );
                ImplCallEventListeners( VCLEVENT_CONTROL_LOSEFOCUS );
                if ( aDelData.IsDelete() )
                    return TRUE;
                maLoseFocusHdl.Call( this );
                if ( aDelData.IsDelete() )
                    return TRUE;
                ImplRemoveDel( &aDelData );
            }
        }
    }

    return Window::Notify( rNEvt );
}

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

void Control::StateChanged( StateChangedType nStateChange )
{
    if( nStateChange == STATE_CHANGE_INITSHOW   ||
        nStateChange == STATE_CHANGE_VISIBLE    ||
        nStateChange == STATE_CHANGE_FORMAT     ||
        nStateChange == STATE_CHANGE_ZOOM       ||
        nStateChange == STATE_CHANGE_BORDER     ||
        nStateChange == STATE_CHANGE_CONTROLFONT
        )
    {
        delete mpLayoutData;
        mpLayoutData = NULL;
    }
    Window::StateChanged( nStateChange );
}

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

void Control::AppendLayoutData( const Control& rSubControl ) const
{
    if( ! rSubControl.mpLayoutData )
        rSubControl.FillLayoutData();
    if( ! rSubControl.mpLayoutData || ! rSubControl.mpLayoutData->m_aDisplayText.Len() )
        return;

    long nCurrentIndex = mpLayoutData->m_aDisplayText.Len();
    mpLayoutData->m_aDisplayText.Append( rSubControl.mpLayoutData->m_aDisplayText );
    int nLines = rSubControl.mpLayoutData->m_aLineIndices.size();
    int n;
    mpLayoutData->m_aLineIndices.push_back( nCurrentIndex );
    for( n = 1; n < nLines; n++ )
        mpLayoutData->m_aLineIndices.push_back( rSubControl.mpLayoutData->m_aLineIndices[n] + nCurrentIndex );
    int nRectangles = rSubControl.mpLayoutData->m_aUnicodeBoundRects.size();
    for( n = 0; n < nRectangles; n++ )
    {
        Rectangle aRect = rSubControl.LogicToPixel( rSubControl.mpLayoutData->m_aUnicodeBoundRects[n] );
        Point aTL = aRect.TopLeft();
        aTL = rSubControl.OutputToAbsoluteScreenPixel( aTL );
        aTL = AbsoluteScreenToOutputPixel( aTL );
        aRect.SetPos( aTL );
        aRect = PixelToLogic( aRect );
        mpLayoutData->m_aUnicodeBoundRects.push_back( aRect );
    }
}

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

void Control::SetLayoutDataParent( const Control* pParent ) const
{
    if( mpLayoutData )
        mpLayoutData->m_pParent = pParent;
}

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

void Control::ImplSubControlLayoutChanged() const
{
    delete mpLayoutData, mpLayoutData = NULL;
}

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

ControlLayoutData::~ControlLayoutData()
{
    if( m_pParent )
        m_pParent->ImplSubControlLayoutChanged();
}
<commit_msg>INTEGRATION: CWS uaa01 (1.8.134); FILE MERGED 2003/04/03 14:22:31 thb 1.8.134.1: #108199# Fix from PL<commit_after>/*************************************************************************
 *
 *  $RCSfile: ctrl.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2003-04-04 16:53:26 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#define _SV_CTRL_CXX

#ifndef _SV_RC_H
#include <rc.h>
#endif
#ifndef _SV_SVDATA_HXX
#include <svdata.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <svapp.hxx>
#endif
#ifndef _SV_EVENT_HXX
#include <event.hxx>
#endif
#ifndef _SV_CTRL_HXX
#include <ctrl.hxx>
#endif
#ifndef _VCL_CONTROLLAYOUT_HXX
#include <controllayout.hxx>
#endif

#pragma hdrstop

using namespace vcl;

// =======================================================================

void Control::ImplInitData()
{
    mbHasFocus      = FALSE;
    mpLayoutData    = NULL;
}

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

Control::Control( WindowType nType ) :
    Window( nType )
{
    ImplInitData();
}

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

Control::Control( Window* pParent, WinBits nStyle ) :
    Window( WINDOW_CONTROL )
{
    ImplInitData();
    Window::ImplInit( pParent, nStyle, NULL );
}

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

Control::Control( Window* pParent, const ResId& rResId ) :
    Window( WINDOW_CONTROL )
{
    ImplInitData();
    rResId.SetRT( RSC_CONTROL );
    WinBits nStyle = ImplInitRes( rResId );
    ImplInit( pParent, nStyle, NULL );
    ImplLoadRes( rResId );

    if ( !(nStyle & WB_HIDE) )
        Show();
}

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

Control::~Control()
{
    delete mpLayoutData, mpLayoutData = NULL;
}

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

void Control::GetFocus()
{
    Window::GetFocus();
}

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

void Control::LoseFocus()
{
    Window::LoseFocus();
}

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

void Control::Resize()
{
    delete mpLayoutData, mpLayoutData = NULL;
    Window::Resize();
}

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

void Control::FillLayoutData() const
{
}

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

void Control::SetText( const String& rStr )
{
    delete mpLayoutData;
    mpLayoutData = NULL;
    Window::SetText( rStr );
}

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

Rectangle ControlLayoutData::GetCharacterBounds( long nIndex ) const
{
    return (nIndex >= 0 && nIndex < m_aUnicodeBoundRects.size()) ? m_aUnicodeBoundRects[ nIndex ] : Rectangle();
}

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

Rectangle Control::GetCharacterBounds( long nIndex ) const
{
    if( ! mpLayoutData )
        FillLayoutData();
    return mpLayoutData ? mpLayoutData->GetCharacterBounds( nIndex ) : Rectangle();
}

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

long ControlLayoutData::GetIndexForPoint( const Point& rPoint ) const
{
    long nIndex = -1;
    for( long i = m_aUnicodeBoundRects.size()-1; i >= 0; i-- )
    {
        if( m_aUnicodeBoundRects[ i ].IsInside( rPoint ) )
        {
            nIndex = i;
            break;
        }
    }
    return nIndex;
}

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

long Control::GetIndexForPoint( const Point& rPoint ) const
{
    long nIndex = -1;
    if( ! mpLayoutData )
        FillLayoutData();
    return mpLayoutData ? mpLayoutData->GetIndexForPoint( rPoint ) : -1;
}

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

long ControlLayoutData::GetLineCount() const
{
    long nLines = m_aLineIndices.size();
    if( nLines == 0 && m_aDisplayText.Len() )
        nLines = 1;
    return nLines;
}

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

long Control::GetLineCount() const
{
    if( ! mpLayoutData )
        FillLayoutData();
    return mpLayoutData ? mpLayoutData->GetLineCount() : 0;
}

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

Pair ControlLayoutData::GetLineStartEnd( long nLine ) const
{
    Pair aPair( -1, -1 );

    int nDisplayLines = m_aLineIndices.size();
    if( nLine >= 0 && nLine < nDisplayLines )
    {
        aPair.A() = m_aLineIndices[nLine];
        if( nLine+1 < m_aLineIndices.size() )
            aPair.B() = m_aLineIndices[nLine+1]-1;
        else
            aPair.B() = m_aDisplayText.Len()-1;
    }
    else if( nLine == 0 && nDisplayLines == 0 && m_aDisplayText.Len() )
    {
        // special case for single line controls so the implementations
        // in that case do not have to fill in the line indices
        aPair.A() = 0;
        aPair.B() = m_aDisplayText.Len()-1;
    }
    return aPair;
}

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

Pair Control::GetLineStartEnd( long nLine ) const
{
    if( ! mpLayoutData )
        FillLayoutData();
    return mpLayoutData ? mpLayoutData->GetLineStartEnd( nLine ) : Pair( -1, -1 );
}

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

String Control::GetDisplayText() const
{
    if( ! mpLayoutData )
        FillLayoutData();
    return mpLayoutData ? mpLayoutData->m_aDisplayText : GetText();
}

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

long Control::Notify( NotifyEvent& rNEvt )
{
    if ( rNEvt.GetType() == EVENT_GETFOCUS )
    {
        if ( !mbHasFocus )
        {
            mbHasFocus = TRUE;
            ImplDelData aDelData;
            ImplAddDel( &aDelData );
            ImplCallEventListeners( VCLEVENT_CONTROL_GETFOCUS );
            if ( aDelData.IsDelete() )
                return TRUE;
            maGetFocusHdl.Call( this );
            if ( aDelData.IsDelete() )
                return TRUE;
            ImplRemoveDel( &aDelData );
        }
    }
    else
    {
        if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
        {
            Window* pFocusWin = Application::GetFocusWindow();
            if ( !pFocusWin || !ImplIsWindowOrChild( pFocusWin ) )
            {
                mbHasFocus = FALSE;
                ImplDelData aDelData;
                ImplAddDel( &aDelData );
                ImplCallEventListeners( VCLEVENT_CONTROL_LOSEFOCUS );
                if ( aDelData.IsDelete() )
                    return TRUE;
                maLoseFocusHdl.Call( this );
                if ( aDelData.IsDelete() )
                    return TRUE;
                ImplRemoveDel( &aDelData );
            }
        }
    }

    return Window::Notify( rNEvt );
}

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

void Control::StateChanged( StateChangedType nStateChange )
{
    if( nStateChange == STATE_CHANGE_INITSHOW   ||
        nStateChange == STATE_CHANGE_VISIBLE    ||
        nStateChange == STATE_CHANGE_FORMAT     ||
        nStateChange == STATE_CHANGE_ZOOM       ||
        nStateChange == STATE_CHANGE_BORDER     ||
        nStateChange == STATE_CHANGE_CONTROLFONT
        )
    {
        delete mpLayoutData;
        mpLayoutData = NULL;
    }
    Window::StateChanged( nStateChange );
}

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

void Control::AppendLayoutData( const Control& rSubControl ) const
{
    if( ! rSubControl.mpLayoutData )
        rSubControl.FillLayoutData();
    if( ! rSubControl.mpLayoutData || ! rSubControl.mpLayoutData->m_aDisplayText.Len() )
        return;

    long nCurrentIndex = mpLayoutData->m_aDisplayText.Len();
    mpLayoutData->m_aDisplayText.Append( rSubControl.mpLayoutData->m_aDisplayText );
    int nLines = rSubControl.mpLayoutData->m_aLineIndices.size();
    int n;
    mpLayoutData->m_aLineIndices.push_back( nCurrentIndex );
    for( n = 1; n < nLines; n++ )
        mpLayoutData->m_aLineIndices.push_back( rSubControl.mpLayoutData->m_aLineIndices[n] + nCurrentIndex );
    int nRectangles = rSubControl.mpLayoutData->m_aUnicodeBoundRects.size();
        Rectangle aRel = const_cast<Control&>(rSubControl).GetWindowExtentsRelative( const_cast<Control*>(this) );
    for( n = 0; n < nRectangles; n++ )
    {
        Rectangle aRect = rSubControl.mpLayoutData->m_aUnicodeBoundRects[n];
        aRect.Move( aRel.Left(), aRel.Top() );
        mpLayoutData->m_aUnicodeBoundRects.push_back( aRect );
    }
}

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

void Control::SetLayoutDataParent( const Control* pParent ) const
{
    if( mpLayoutData )
        mpLayoutData->m_pParent = pParent;
}

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

void Control::ImplSubControlLayoutChanged() const
{
    delete mpLayoutData, mpLayoutData = NULL;
}

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

ControlLayoutData::~ControlLayoutData()
{
    if( m_pParent )
        m_pParent->ImplSubControlLayoutChanged();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: polyscan.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 12:09:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <string.h>
#include <tools/new.hxx>
#include "salbtype.hxx"
#include "polyscan.hxx"

#ifndef _TL_POLY_HXX
#include <tools/poly.hxx>
#endif

// ----------------
// - PolyScanline -
// ----------------

PolyScanline::PolyScanline() :
        mpFirst ( NULL ),
        mpLast  ( NULL ),
        mpAct   ( NULL ),
        mnLeft  ( 0L ),
        mnRight ( 0L )
{
}

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

PolyScanline::~PolyScanline()
{
    ImplDelete();
}

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

void PolyScanline::ImplDelete()
{
    ScanlinePoint* pAct = mpFirst;

    while( pAct )
    {
        ScanlinePoint* pNext = pAct->mpNext;
        delete pAct;
        pAct = pNext;
    }

    mnLeft = mnRight = 0L;
    mpFirst = mpAct = mpLast = NULL;
}

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

void PolyScanline::Insert( long nX )
{
    // first point to insert?
    if( !mpFirst )
        mpLast = mpFirst = new ScanlinePoint( mnLeft = mnRight = nX, NULL );
    else
    {
        // insert at the beginning of the scanline
        if( nX <= mpFirst->mnX )
            mpFirst = new ScanlinePoint( mnLeft = nX, mpFirst );
        else if( nX >= mnRight )
            mpLast = mpLast->mpNext = new ScanlinePoint( mnRight = nX, NULL );
        else
        {
            ScanlinePoint* pLast = mpFirst;
            ScanlinePoint* pAct = mpFirst->mpNext;

            while( pAct )
            {
                // insert in the midlle of the scanline?
                if( nX <= pAct->mnX )
                {
                    pLast->mpNext = new ScanlinePoint( nX, pAct );
                    break;
                }

                pLast = pAct;
                pAct = pAct->mpNext;
            }
        }
    }
}

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

void PolyScanline::Set( long nStart, long nEnd )
{
    if( mpFirst )
        ImplDelete();

    if( nStart <= nEnd )
        mpFirst = new ScanlinePoint( mnLeft = nStart, mpLast = new ScanlinePoint( mnRight = nEnd, NULL ) );
    else
        mpFirst = new ScanlinePoint( mnLeft = nEnd, mpLast = new ScanlinePoint( mnRight = nStart, NULL ) );
}

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

BOOL PolyScanline::GetFirstSegment( PolyScanSegment& rSegment )
{
    BOOL bRet = GetFirstX( rSegment.mnStart );

    if( bRet && !GetNextX( rSegment.mnEnd ) )
        rSegment.mnEnd = rSegment.mnStart;

    return bRet;
}

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

BOOL PolyScanline::GetNextSegment( PolyScanSegment& rSegment )
{
    BOOL bRet = GetNextX( rSegment.mnStart );

    if( bRet && !GetNextX( rSegment.mnEnd ) )
        rSegment.mnEnd = rSegment.mnStart;

    return bRet;
}

// ---------------
// - PolyScanner -
// ---------------

PolyScanner::PolyScanner( const Rectangle& rRect )
{
    if( !rRect.IsEmpty() )
    {
        Rectangle   aRect( rRect );
        ULONG       nHeight;

        aRect.Justify();
        mnLeft = aRect.Left();
        mnTop = aRect.Top();
        mnRight = aRect.Right();
        mnBottom = aRect.Bottom();
        mpArray = new PolyScanline[ nHeight = Height() ];

        for( ULONG i = 0UL; i < nHeight; i++ )
            mpArray[ i ].Set( mnLeft, mnRight );
    }
    else
    {
        mnLeft = mnTop = mnRight = mnBottom = 0L;
        mpArray = NULL;
    }
}

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

PolyScanner::PolyScanner( const Polygon& rPoly )
{
    const long nCount = rPoly.GetSize();

    if( nCount )
    {
        long    nLast = nCount - 1;
        Point   aFirst( rPoly[ 0 ] );
        Point   aLast( rPoly[ (USHORT) nLast ] );

        while( nLast && ( aLast == aFirst ) )
            aLast = rPoly[ (USHORT) --nLast ];

        if( !nLast )
        {
            aLast = rPoly[ 0 ];
            mnLeft = mnRight = aLast.X();
            mnTop = mnBottom = aLast.Y();
            mpArray = new PolyScanline[ 1UL ];
            mpArray[ 0 ].Set( mnLeft, mnRight );
        }
        else
        {
            const Rectangle aRect( rPoly.GetBoundRect() );
            ULONG           nHeight;

            mnLeft = aRect.Left();
            mnTop = aRect.Top();
            mnRight = aRect.Right();
            mnBottom = aRect.Bottom();
            aLast = aFirst;
            mpArray = new PolyScanline[ nHeight = Height() ];

            for( long i = 1L; i <= nLast; i++ )
            {
                const Point& rPt = rPoly[ (USHORT) i ];

                if( rPt != aLast )
                {
                    InsertLine( aLast, rPt );
                    aLast = rPt;
                }
            }

            InsertLine( aLast, aFirst );
        }
    }
    else
        mpArray = NULL;
}

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

PolyScanner::PolyScanner( const PolyPolygon& rPolyPoly )
{
    mpArray = NULL;
}

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

PolyScanner::~PolyScanner()
{
    delete[] mpArray;
}

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

PolyScanline* PolyScanner::operator[]( ULONG nPos ) const
{
    DBG_ASSERT( nPos < Count(), "nPos out of range!" );
    return( mpArray ? ( mpArray + nPos ) : NULL );
}

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

void PolyScanner::InsertLine( const Point& rStart, const Point& rEnd )
{
    long nX, nY;

    if( rStart.Y() == rEnd.Y() )
        mpArray[ rStart.Y() - mnTop ].Insert( rStart.X() );
    else if( rStart.X() == rEnd.X() )
    {
        // vertical line
        const long nEndY = rEnd.Y();

        nX = rStart.X();
        nY = rStart.Y();

        if( nEndY > nY )
            while( nY < nEndY )
                mpArray[ nY++ - mnTop ].Insert( nX );
        else
            while( nY > nEndY )
                mpArray[ nY-- - mnTop ].Insert( nX );
    }
    else
    {
        const long  nDX = labs( rEnd.X() - rStart.X() );
        const long  nDY = labs( rEnd.Y() - rStart.Y() );
        const long  nStartX = rStart.X();
        const long  nStartY = rStart.Y();
        const long  nEndX = rEnd.X();
        const long  nEndY = rEnd.Y();
        const long  nXInc = ( nStartX < nEndX ) ? 1L : -1L;
        const long  nYInc = ( nStartY < nEndY ) ? 1L : -1L;
        long        nLastX = nStartX;
        long        nLastY = nStartY;
        BOOL        bLast = FALSE;

        mpArray[ nStartY - mnTop ].Insert( nStartX );

        if( nDX >= nDY )
        {
            const long  nDYX = ( nDY - nDX ) << 1;
            const long  nDY2 = nDY << 1;
            long        nD = nDY2 - nDX;

            for( nX = nStartX, nY = nLastY = nStartY; nX != nEndX; )
            {
                if( nY != nLastY )
                {
                    if( bLast )
                        mpArray[ nLastY - mnTop ].Insert( nLastX );

                    mpArray[ nY - mnTop ].Insert( nX );
                    bLast = FALSE;
                }
                else
                    bLast = TRUE;

                nLastX = nX;
                nLastY = nY;

                if( nD < 0L )
                    nD += nDY2;
                else
                {
                    nD += nDYX;
                    nY += nYInc;
                }

                nX += nXInc;
            }
        }
        else
        {
            const long  nDYX = ( nDX - nDY ) << 1;
            const long  nDY2 = nDX << 1;
            long        nD = nDY2 - nDY;

            for( nX = nStartX, nY = nStartY; nY != nEndY; )
            {
                if( nY != nLastY )
                {
                    if( bLast )
                        mpArray[ nLastY - mnTop ].Insert( nLastX );

                    mpArray[ nY - mnTop ].Insert( nX );
                    bLast = FALSE;
                }
                else
                    bLast = TRUE;

                nLastX = nX;
                nLastY = nY;

                if( nD < 0L )
                    nD += nDY2;
                else
                {
                    nD += nDYX;
                    nX += nXInc;
                }

                nY += nYInc;
            }
        }

        if( bLast )
            mpArray[ nLastY - mnTop ].Insert( nLastX );
    }
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.3.376); FILE MERGED 2006/09/01 17:57:47 kaib 1.3.376.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: polyscan.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 12:09:22 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#include <string.h>
#include <tools/new.hxx>
#include "salbtype.hxx"
#include "polyscan.hxx"

#ifndef _TL_POLY_HXX
#include <tools/poly.hxx>
#endif

// ----------------
// - PolyScanline -
// ----------------

PolyScanline::PolyScanline() :
        mpFirst ( NULL ),
        mpLast  ( NULL ),
        mpAct   ( NULL ),
        mnLeft  ( 0L ),
        mnRight ( 0L )
{
}

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

PolyScanline::~PolyScanline()
{
    ImplDelete();
}

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

void PolyScanline::ImplDelete()
{
    ScanlinePoint* pAct = mpFirst;

    while( pAct )
    {
        ScanlinePoint* pNext = pAct->mpNext;
        delete pAct;
        pAct = pNext;
    }

    mnLeft = mnRight = 0L;
    mpFirst = mpAct = mpLast = NULL;
}

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

void PolyScanline::Insert( long nX )
{
    // first point to insert?
    if( !mpFirst )
        mpLast = mpFirst = new ScanlinePoint( mnLeft = mnRight = nX, NULL );
    else
    {
        // insert at the beginning of the scanline
        if( nX <= mpFirst->mnX )
            mpFirst = new ScanlinePoint( mnLeft = nX, mpFirst );
        else if( nX >= mnRight )
            mpLast = mpLast->mpNext = new ScanlinePoint( mnRight = nX, NULL );
        else
        {
            ScanlinePoint* pLast = mpFirst;
            ScanlinePoint* pAct = mpFirst->mpNext;

            while( pAct )
            {
                // insert in the midlle of the scanline?
                if( nX <= pAct->mnX )
                {
                    pLast->mpNext = new ScanlinePoint( nX, pAct );
                    break;
                }

                pLast = pAct;
                pAct = pAct->mpNext;
            }
        }
    }
}

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

void PolyScanline::Set( long nStart, long nEnd )
{
    if( mpFirst )
        ImplDelete();

    if( nStart <= nEnd )
        mpFirst = new ScanlinePoint( mnLeft = nStart, mpLast = new ScanlinePoint( mnRight = nEnd, NULL ) );
    else
        mpFirst = new ScanlinePoint( mnLeft = nEnd, mpLast = new ScanlinePoint( mnRight = nStart, NULL ) );
}

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

BOOL PolyScanline::GetFirstSegment( PolyScanSegment& rSegment )
{
    BOOL bRet = GetFirstX( rSegment.mnStart );

    if( bRet && !GetNextX( rSegment.mnEnd ) )
        rSegment.mnEnd = rSegment.mnStart;

    return bRet;
}

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

BOOL PolyScanline::GetNextSegment( PolyScanSegment& rSegment )
{
    BOOL bRet = GetNextX( rSegment.mnStart );

    if( bRet && !GetNextX( rSegment.mnEnd ) )
        rSegment.mnEnd = rSegment.mnStart;

    return bRet;
}

// ---------------
// - PolyScanner -
// ---------------

PolyScanner::PolyScanner( const Rectangle& rRect )
{
    if( !rRect.IsEmpty() )
    {
        Rectangle   aRect( rRect );
        ULONG       nHeight;

        aRect.Justify();
        mnLeft = aRect.Left();
        mnTop = aRect.Top();
        mnRight = aRect.Right();
        mnBottom = aRect.Bottom();
        mpArray = new PolyScanline[ nHeight = Height() ];

        for( ULONG i = 0UL; i < nHeight; i++ )
            mpArray[ i ].Set( mnLeft, mnRight );
    }
    else
    {
        mnLeft = mnTop = mnRight = mnBottom = 0L;
        mpArray = NULL;
    }
}

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

PolyScanner::PolyScanner( const Polygon& rPoly )
{
    const long nCount = rPoly.GetSize();

    if( nCount )
    {
        long    nLast = nCount - 1;
        Point   aFirst( rPoly[ 0 ] );
        Point   aLast( rPoly[ (USHORT) nLast ] );

        while( nLast && ( aLast == aFirst ) )
            aLast = rPoly[ (USHORT) --nLast ];

        if( !nLast )
        {
            aLast = rPoly[ 0 ];
            mnLeft = mnRight = aLast.X();
            mnTop = mnBottom = aLast.Y();
            mpArray = new PolyScanline[ 1UL ];
            mpArray[ 0 ].Set( mnLeft, mnRight );
        }
        else
        {
            const Rectangle aRect( rPoly.GetBoundRect() );
            ULONG           nHeight;

            mnLeft = aRect.Left();
            mnTop = aRect.Top();
            mnRight = aRect.Right();
            mnBottom = aRect.Bottom();
            aLast = aFirst;
            mpArray = new PolyScanline[ nHeight = Height() ];

            for( long i = 1L; i <= nLast; i++ )
            {
                const Point& rPt = rPoly[ (USHORT) i ];

                if( rPt != aLast )
                {
                    InsertLine( aLast, rPt );
                    aLast = rPt;
                }
            }

            InsertLine( aLast, aFirst );
        }
    }
    else
        mpArray = NULL;
}

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

PolyScanner::PolyScanner( const PolyPolygon& rPolyPoly )
{
    mpArray = NULL;
}

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

PolyScanner::~PolyScanner()
{
    delete[] mpArray;
}

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

PolyScanline* PolyScanner::operator[]( ULONG nPos ) const
{
    DBG_ASSERT( nPos < Count(), "nPos out of range!" );
    return( mpArray ? ( mpArray + nPos ) : NULL );
}

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

void PolyScanner::InsertLine( const Point& rStart, const Point& rEnd )
{
    long nX, nY;

    if( rStart.Y() == rEnd.Y() )
        mpArray[ rStart.Y() - mnTop ].Insert( rStart.X() );
    else if( rStart.X() == rEnd.X() )
    {
        // vertical line
        const long nEndY = rEnd.Y();

        nX = rStart.X();
        nY = rStart.Y();

        if( nEndY > nY )
            while( nY < nEndY )
                mpArray[ nY++ - mnTop ].Insert( nX );
        else
            while( nY > nEndY )
                mpArray[ nY-- - mnTop ].Insert( nX );
    }
    else
    {
        const long  nDX = labs( rEnd.X() - rStart.X() );
        const long  nDY = labs( rEnd.Y() - rStart.Y() );
        const long  nStartX = rStart.X();
        const long  nStartY = rStart.Y();
        const long  nEndX = rEnd.X();
        const long  nEndY = rEnd.Y();
        const long  nXInc = ( nStartX < nEndX ) ? 1L : -1L;
        const long  nYInc = ( nStartY < nEndY ) ? 1L : -1L;
        long        nLastX = nStartX;
        long        nLastY = nStartY;
        BOOL        bLast = FALSE;

        mpArray[ nStartY - mnTop ].Insert( nStartX );

        if( nDX >= nDY )
        {
            const long  nDYX = ( nDY - nDX ) << 1;
            const long  nDY2 = nDY << 1;
            long        nD = nDY2 - nDX;

            for( nX = nStartX, nY = nLastY = nStartY; nX != nEndX; )
            {
                if( nY != nLastY )
                {
                    if( bLast )
                        mpArray[ nLastY - mnTop ].Insert( nLastX );

                    mpArray[ nY - mnTop ].Insert( nX );
                    bLast = FALSE;
                }
                else
                    bLast = TRUE;

                nLastX = nX;
                nLastY = nY;

                if( nD < 0L )
                    nD += nDY2;
                else
                {
                    nD += nDYX;
                    nY += nYInc;
                }

                nX += nXInc;
            }
        }
        else
        {
            const long  nDYX = ( nDX - nDY ) << 1;
            const long  nDY2 = nDX << 1;
            long        nD = nDY2 - nDY;

            for( nX = nStartX, nY = nStartY; nY != nEndY; )
            {
                if( nY != nLastY )
                {
                    if( bLast )
                        mpArray[ nLastY - mnTop ].Insert( nLastX );

                    mpArray[ nY - mnTop ].Insert( nX );
                    bLast = FALSE;
                }
                else
                    bLast = TRUE;

                nLastX = nX;
                nLastY = nY;

                if( nD < 0L )
                    nD += nDY2;
                else
                {
                    nD += nDYX;
                    nX += nXInc;
                }

                nY += nYInc;
            }
        }

        if( bLast )
            mpArray[ nLastY - mnTop ].Insert( nLastX );
    }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QString>
#include <QtTest/QtTest>
#include <QtCore/QCoreApplication>

#include <qllcpsocket.h>
#include <qnearfieldmanager.h>
#include <qnearfieldtarget.h>
#include "qnfctestcommon.h"
#include "qnfctestutil.h"

QTM_USE_NAMESPACE

Q_DECLARE_METATYPE(QNearFieldTarget*)
Q_DECLARE_METATYPE(QLlcpSocket::Error);

class tst_qllcpsocketremote : public QObject
{
    Q_OBJECT

public:
    tst_qllcpsocketremote();

private Q_SLOTS:

    // ALERT Handshake required, do NOTchange the sequence of handshaking testcases.
    void testCase0();  // Intial handshake - work with  tst_qllcpsocketlocal testCase0
    void testCase1();   // handshake 1,2  - work with  tst_qllcpsocketlocal testCase1
    void testCase2();   // handshake 3   - work with  tst_qllcpsocketlocal testCase2

    void cleanupTest();

private:
     QNearFieldManager *m_nfcManager;
     QNearFieldTarget *m_target;
     QLlcpSocket *m_socket;
     quint8 m_port;
};

tst_qllcpsocketremote::tst_qllcpsocketremote()
{
    qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget*");
    qRegisterMetaType<QNearFieldTarget *>("QLlcpSocket::Error");
}

/*!
 Description: Init test case for NFC LLCP connection-less mode socket - local peer

 TestScenario:
     Touch a NFC device with LLCP connection-less service actived

 TestExpectedResults:
     Signal of target detected has been found.
*/
void tst_qllcpsocketremote::testCase0()
{
    m_nfcManager = new QNearFieldManager;
    QSignalSpy targetDetectedSpy(m_nfcManager, SIGNAL(targetDetected(QNearFieldTarget*)));
    m_nfcManager->startTargetDetection(QNearFieldTarget::AnyTarget);

    QString message("Remote wait touch");
    QNfcTestUtil::ShowMessage(message);
    QTRY_VERIFY(!targetDetectedSpy.isEmpty());

    m_target = targetDetectedSpy.at(targetDetectedSpy.count() - 1).at(0).value<QNearFieldTarget *>();
    QVERIFY(m_target!=NULL);
    QVERIFY(m_target->accessMethods() & QNearFieldTarget::LlcpAccess);

    m_port = 35;
    m_socket = new QLlcpSocket;
}

/*!
 Description:  Description: Receive the message and send the acknowledged identical message

 TestScenario: 1. Remote peer binds to local port
               2. Remote peer receives the message sending from the local peer
               3. Remote peer sends the echoed message to the local peer

 TestExpectedResults:
               1. Remote peer binds to local port successfully.
               2. The message has been received from remote peer.
               3. The message has be sent to local peer.
*/
void tst_qllcpsocketremote::testCase1()
{
    // STEP 1:  bind the local port for current socket
    QSignalSpy readyReadSpy(m_socket, SIGNAL(readyRead()));
    bool ret = m_socket->bind(m_port);

    QString message("handshake 1");
    QNfcTestUtil::ShowMessage(message);

    QTRY_VERIFY(readyReadSpy.count() == 1);
    QVERIFY(ret);

    // STEP 2: Receive data from the peer which send messages to
    QByteArray datagram;
    if (m_socket->hasPendingDatagrams())
    {
       datagram.resize(m_socket->pendingDatagramSize());
       qint64 readSize = m_socket->readDatagram(datagram.data(), datagram.size());
       QVERIFY(readSize != -1);
    }

    // STEP 3: Send the received message back to the intiated device.
    QSignalSpy errorSpy(m_socket, SIGNAL(error(QLlcpSocket::Error)));
    QSignalSpy bytesWrittenSpy(m_socket, SIGNAL(bytesWritten(qint64)));

    qint64 val = m_socket->writeDatagram(datagram,m_target, m_port);
    QVERIFY(val != -1);

    QTRY_VERIFY(bytesWrittenSpy.count() == 1);
    QList<QVariant> arguments = bytesWrittenSpy.takeFirst(); // take the first signal
    qint64 writtenSize  = arguments.at(0).value<qint64>();
    QVERIFY(writtenSize > 0);

    QString message2("handshake 2");
    QNfcTestUtil::ShowMessage(message2);

    // make sure the no error signal emitted
    QCOMPARE(errorSpy.count(), 0);
}

/*!
 Description: Unit test for NFC LLCP connection-less mode socket - remote peer (passive)

 TestScenario: 1. Remote peer binds to local port ( already done in testCase1)
               2. Remote peer  receive datagram twice
               3. Remote peer waitForReadyRead

 TestExpectedResults:
               1. Remote peer binds to local port successfully.
               2. Remote peer  receive datagram twice successfully
               3. waitForReadyRead return true as long as readyReadSpy not empty
*/
void tst_qllcpsocketremote::testCase2()
{
    // STEP 1:  bind the local port for current socket
    QSignalSpy readyReadSpy(m_socket, SIGNAL(readyRead()));
    QString expectedMessage1("testcase2 string str1");
    QString expectedMessage2("testcase2 string str2");

    QString boxMessage("handshake 3");
    QNfcTestUtil::ShowMessage(boxMessage);

    QTRY_VERIFY(readyReadSpy.count() == 1);

    QByteArray datagram;
    if (m_socket->hasPendingDatagrams())
    {
       datagram.resize(m_socket->pendingDatagramSize());
       qint64 readSize = m_socket->readDatagram(datagram.data(), datagram.size());
       QVERIFY(readSize != -1);
    }

    QString receivedMessage1 = datagram.data();
    qDebug() << "receivedMessage1: " << receivedMessage1;
    //QVERIFY(expectedMessage1 == receivedMessage1);
    QVERIFY(expectedMessage1.size() > 0);

    QTRY_VERIFY(readyReadSpy.count() == 2);

     QByteArray datagram2;
    if (m_socket->hasPendingDatagrams())
    {
       datagram2.resize(m_socket->pendingDatagramSize());
       qint64 readSize = m_socket->readDatagram(datagram2.data(), datagram2.size());
       QVERIFY(readSize != -1);
    }
    QString receivedMessage2 = datagram2.data();
    qDebug() << "receivedMessage2: " << receivedMessage2;
    //QVERIFY(expectedMessage2 == receivedMessage2);
    QVERIFY(expectedMessage2.size() > 0);

    const int Timeout = 10 * 1000;
    bool ret = m_socket->waitForReadyRead(Timeout);

    QVERIFY(ret);
 }

void tst_qllcpsocketremote::cleanupTest()
{
   delete m_nfcManager;
   delete m_socket;
}

QTEST_MAIN(tst_qllcpsocketremote);

#include "tst_qllcpsocketremote.moc"
<commit_msg>llcp testcase2 fixes<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QString>
#include <QtTest/QtTest>
#include <QtCore/QCoreApplication>

#include <qllcpsocket.h>
#include <qnearfieldmanager.h>
#include <qnearfieldtarget.h>
#include "qnfctestcommon.h"
#include "qnfctestutil.h"

QTM_USE_NAMESPACE

Q_DECLARE_METATYPE(QNearFieldTarget*)
Q_DECLARE_METATYPE(QLlcpSocket::Error);

class tst_qllcpsocketremote : public QObject
{
    Q_OBJECT

public:
    tst_qllcpsocketremote();

private Q_SLOTS:

    // ALERT Handshake required, do NOTchange the sequence of handshaking testcases.
    void testCase0();  // Intial handshake - work with  tst_qllcpsocketlocal testCase0
    void testCase1();   // handshake 1,2  - work with  tst_qllcpsocketlocal testCase1
    void testCase2();   // handshake 3   - work with  tst_qllcpsocketlocal testCase2

    void cleanupTest();

private:
     QNearFieldManager *m_nfcManager;
     QNearFieldTarget *m_target;
     QLlcpSocket *m_socket;
     quint8 m_port;
};

tst_qllcpsocketremote::tst_qllcpsocketremote()
{
    qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget*");
    qRegisterMetaType<QNearFieldTarget *>("QLlcpSocket::Error");
}

/*!
 Description: Init test case for NFC LLCP connection-less mode socket - local peer

 TestScenario:
     Touch a NFC device with LLCP connection-less service actived

 TestExpectedResults:
     Signal of target detected has been found.
*/
void tst_qllcpsocketremote::testCase0()
{
    m_nfcManager = new QNearFieldManager;
    QSignalSpy targetDetectedSpy(m_nfcManager, SIGNAL(targetDetected(QNearFieldTarget*)));
    m_nfcManager->startTargetDetection(QNearFieldTarget::AnyTarget);

    QString message("Remote wait touch");
    QNfcTestUtil::ShowMessage(message);
    QTRY_VERIFY(!targetDetectedSpy.isEmpty());

    m_target = targetDetectedSpy.at(targetDetectedSpy.count() - 1).at(0).value<QNearFieldTarget *>();
    QVERIFY(m_target!=NULL);
    QVERIFY(m_target->accessMethods() & QNearFieldTarget::LlcpAccess);

    m_port = 35;
    m_socket = new QLlcpSocket;
}

/*!
 Description:  Description: Receive the message and send the acknowledged identical message

 TestScenario: 1. Remote peer binds to local port
               2. Remote peer receives the message sending from the local peer
               3. Remote peer sends the echoed message to the local peer

 TestExpectedResults:
               1. Remote peer binds to local port successfully.
               2. The message has been received from remote peer.
               3. The message has be sent to local peer.
*/
void tst_qllcpsocketremote::testCase1()
{

    // STEP 1:  bind the local port for current socket
    QSignalSpy readyReadSpy(m_socket, SIGNAL(readyRead()));
    bool ret = m_socket->bind(m_port);
    QVERIFY(ret);

    QString message("handshake 1");
    QNfcTestUtil::ShowMessage(message);

    QTRY_VERIFY(readyReadSpy.count() == 1);
    QVERIFY(ret);

    // STEP 2: Receive data from the peer which send messages to
    QByteArray datagram;
    if (m_socket->hasPendingDatagrams())
    {
       datagram.resize(m_socket->pendingDatagramSize());
       qint64 readSize = m_socket->readDatagram(datagram.data(), datagram.size());
       QVERIFY(readSize != -1);
    }

    // STEP 3: Send the received message back to the intiated device.
    QSignalSpy errorSpy(m_socket, SIGNAL(error(QLlcpSocket::Error)));
    QSignalSpy bytesWrittenSpy(m_socket, SIGNAL(bytesWritten(qint64)));

    qint64 val = m_socket->writeDatagram(datagram,m_target, m_port);
    QVERIFY(val != -1);

    QTRY_VERIFY(bytesWrittenSpy.count() == 1);
    QList<QVariant> arguments = bytesWrittenSpy.takeFirst(); // take the first signal
    qint64 writtenSize  = arguments.at(0).value<qint64>();
    QVERIFY(writtenSize > 0);

    QString message2("handshake 2");
    QNfcTestUtil::ShowMessage(message2);

    // make sure the no error signal emitted
    QCOMPARE(errorSpy.count(), 0);
}

/*!
 Description: Unit test for NFC LLCP connection-less mode socket - remote peer (passive)

 TestScenario: 1. Remote peer binds to local port ( already done in testCase1)
               2. Remote peer  receive datagram twice
               3. Remote peer waitForReadyRead

 TestExpectedResults:
               1. Remote peer binds to local port successfully.
               2. Remote peer  receive datagram twice successfully
               3. waitForReadyRead return true as long as readyReadSpy not empty
*/
void tst_qllcpsocketremote::testCase2()
{
    QLlcpSocket localSocket;
    bool ret = localSocket.bind(m_port);
    QVERIFY(ret);

    // STEP 1:  bind the local port for current socket
    QSignalSpy readyReadSpy(&localSocket, SIGNAL(readyRead()));
    QString expectedMessage1("testcase2 string str1");
    QString expectedMessage2("testcase2 string str2");

    QString boxMessage("handshake 3");
    QNfcTestUtil::ShowMessage(boxMessage);

    QTRY_VERIFY(readyReadSpy.count() == 1);

    QByteArray datagram;
    if (localSocket.hasPendingDatagrams())
    {
       datagram.resize(localSocket.pendingDatagramSize());
       qint64 readSize = localSocket.readDatagram(datagram.data(), datagram.size());
       QVERIFY(readSize != -1);
    }

    QString receivedMessage1 = datagram.data();
    qDebug() << "receivedMessage1: " << receivedMessage1;
    QVERIFY(expectedMessage1 == receivedMessage1);

    QTRY_VERIFY(readyReadSpy.count() == 2);

     QByteArray datagram2;
    if (localSocket.hasPendingDatagrams())
    {
       datagram2.resize(localSocket.pendingDatagramSize());
       qint64 readSize = localSocket.readDatagram(datagram2.data(), datagram2.size());
       QVERIFY(readSize != -1);
    }
    QString receivedMessage2 = datagram2.data();
    qDebug() << "receivedMessage2: " << receivedMessage2;
    QVERIFY(expectedMessage2 == receivedMessage2);

    const int Timeout = 10 * 1000;
    ret = localSocket.waitForReadyRead(Timeout);

    QVERIFY(ret);
 }

void tst_qllcpsocketremote::cleanupTest()
{
   delete m_nfcManager;
   delete m_socket;
}

QTEST_MAIN(tst_qllcpsocketremote);

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