<commit_before>#include <silicium/alignment_of.hpp>
#include <silicium/arithmetic/add.hpp>
#include <silicium/arithmetic/overflow_or.hpp>
#include <silicium/array_view.hpp>
#include <silicium/asio/accepting_source.hpp>
#include <silicium/asio/async.hpp>
#include <silicium/asio/async_source.hpp>
#include <silicium/asio/connecting_observable.hpp>
#include <silicium/asio/connecting_source.hpp>
#include <silicium/asio/post_forwarder.hpp>
#include <silicium/asio/posting_observable.hpp>
#include <silicium/asio/process_output.hpp>
#include <silicium/asio/reading_observable.hpp>
#include <silicium/asio/socket_sink.hpp>
#include <silicium/asio/socket_source.hpp>
#include <silicium/asio/tcp_acceptor.hpp>
#include <silicium/asio/timer.hpp>
#include <silicium/asio/use_observable.hpp>
#include <silicium/asio/writing_observable.hpp>
#include <silicium/block_thread.hpp>
#include <silicium/boost_threading.hpp>
#include <silicium/bounded_int.hpp>
#include <silicium/buffer.hpp>
#include <silicium/byte.hpp>
#include <silicium/byte_order_intrinsics.hpp>
#include <silicium/c_string.hpp>
#include <silicium/config.hpp>
#include <silicium/detail/argument_of.hpp>
#include <silicium/detail/basic_dynamic_library.hpp>
#include <silicium/detail/element_from_optional_like.hpp>
#include <silicium/detail/integer_sequence.hpp>
#include <silicium/detail/line_source.hpp>
#include <silicium/detail/proper_value_function.hpp>
#include <silicium/dynamic_library.hpp>
#include <silicium/environment_variables.hpp>
#include <silicium/error_code.hpp>
#include <silicium/error_handler.hpp>
#include <silicium/error_or.hpp>
#include <silicium/exchange.hpp>
#include <silicium/expected.hpp>
#include <silicium/explicit_operator_bool.hpp>
#include <silicium/file_handle.hpp>
#include <silicium/function.hpp>
#include <silicium/future.hpp>
#include <silicium/get_last_error.hpp>
#include <silicium/html/generator.hpp>
#include <silicium/html/tree.hpp>
#include <silicium/http/generate_header.hpp>
#include <silicium/http/generate_request.hpp>
#include <silicium/http/generate_response.hpp>
#include <silicium/http/http.hpp>
#include <silicium/http/parse_request.hpp>
#include <silicium/http/parse_response.hpp>
#include <silicium/http/receive_request.hpp>
#include <silicium/http/request_parser_sink.hpp>
#include <silicium/http/uri.hpp>
#include <silicium/identity.hpp>
#include <silicium/initialize_array.hpp>
#include <silicium/is_handle.hpp>
#include <silicium/iterator_range.hpp>
#include <silicium/make_array.hpp>
#include <silicium/make_destructor.hpp>
#include <silicium/memory_range.hpp>
#include <silicium/move.hpp>
#include <silicium/move_if_noexcept.hpp>
#include <silicium/native_file_descriptor.hpp>
#include <silicium/noexcept_string.hpp>
#include <silicium/null_mutex.hpp>
#include <silicium/observable/bridge.hpp>
#include <silicium/observable/cache.hpp>
#include <silicium/observable/constant.hpp>
#include <silicium/observable/consume.hpp>
#include <silicium/observable/coroutine.hpp>
#include <silicium/observable/coroutine_generator.hpp>
#include <silicium/observable/deref_optional.hpp>
#include <silicium/observable/empty.hpp>
#include <silicium/observable/end.hpp>
#include <silicium/observable/enumerate.hpp>
#include <silicium/observable/erase_shared.hpp>
#include <silicium/observable/erase_unique.hpp>
#include <silicium/observable/erased_observer.hpp>
#include <silicium/observable/error_or_enumerate.hpp>
#include <silicium/observable/extensible_observer.hpp>
#include <silicium/observable/filter.hpp>
#include <silicium/observable/finite_state_machine.hpp>
#include <silicium/observable/flatten.hpp>
#include <silicium/observable/for_each.hpp>
#include <silicium/observable/function.hpp>
#include <silicium/observable/function_observer.hpp>
#include <silicium/observable/generator.hpp>
#include <silicium/observable/limited.hpp>
#include <silicium/observable/observable.hpp>
#include <silicium/observable/observer.hpp>
#include <silicium/observable/on_first.hpp>
#include <silicium/observable/ptr.hpp>
#include <silicium/observable/ready_future.hpp>
#include <silicium/observable/ref.hpp>
#include <silicium/observable/source.hpp>
#include <silicium/observable/spawn_coroutine.hpp>
#include <silicium/observable/spawn_observable.hpp>
#include <silicium/observable/take.hpp>
#include <silicium/observable/thread.hpp>
#include <silicium/observable/thread_generator.hpp>
#include <silicium/observable/total_consumer.hpp>
#include <silicium/observable/transform.hpp>
#include <silicium/observable/transform_if_initialized.hpp>
#include <silicium/observable/tuple.hpp>
#include <silicium/observable/variant.hpp>
#include <silicium/observable/virtualized.hpp>
#include <silicium/observable/while.hpp>
#include <silicium/observable/yield_context.hpp>
#include <silicium/observable2.hpp>
#include <silicium/optional.hpp>
#include <silicium/os_string.hpp>
#include <silicium/pipe.hpp>
#include <silicium/process_handle.hpp>
#include <silicium/program_options.hpp>
#include <silicium/ptr_adaptor.hpp>
#include <silicium/range_value.hpp>
#include <silicium/read_file.hpp>
#include <silicium/serialization.hpp>
#include <silicium/sink/append.hpp>
#include <silicium/sink/buffer.hpp>
#include <silicium/sink/buffering_sink.hpp>
#include <silicium/sink/container_buffer.hpp>
#include <silicium/sink/copy.hpp>
#include <silicium/sink/function_sink.hpp>
#include <silicium/sink/iterator_sink.hpp>
#include <silicium/sink/multi_sink.hpp>
#include <silicium/sink/ostream_sink.hpp>
#include <silicium/sink/ptr_sink.hpp>
#include <silicium/sink/sink.hpp>
#include <silicium/sink/throwing_sink.hpp>
#include <silicium/sink/virtualized_sink.hpp>
#include <silicium/source/buffering_source.hpp>
#include <silicium/source/empty.hpp>
#include <silicium/source/enumerating_source.hpp>
#include <silicium/source/error_extracting_source.hpp>
#include <silicium/source/filter_source.hpp>
#include <silicium/source/generator_source.hpp>
#include <silicium/source/memory_source.hpp>
#include <silicium/source/observable_source.hpp>
#include <silicium/source/ptr_source.hpp>
#include <silicium/source/range_source.hpp>
#include <silicium/source/received_from_socket_source.hpp>
#include <silicium/source/single_source.hpp>
#include <silicium/source/source.hpp>
#include <silicium/source/throwing_source.hpp>
#include <silicium/source/transforming_source.hpp>
#include <silicium/source/virtualized_source.hpp>
#include <silicium/sqlite3.hpp>
#include <silicium/std_threading.hpp>
#include <silicium/steady_clock.hpp>
#include <silicium/success.hpp>
#include <silicium/terminate_on_exception.hpp>
#include <silicium/then.hpp>
#include <silicium/throw_last_error.hpp>
#include <silicium/to_shared.hpp>
#include <silicium/to_unique.hpp>
#include <silicium/trait.hpp>
#include <silicium/type_traits.hpp>
#include <silicium/utility.hpp>
#include <silicium/variant.hpp>
#include <silicium/vector.hpp>
#include <silicium/version.hpp>
#include <silicium/win32/dynamic_library_impl.hpp>
#include <silicium/win32/process_handle.hpp>
#include <silicium/win32/win32.hpp>
#include <silicium/write.hpp>
#include <silicium/zlib/deflating_sink.hpp>
#include <silicium/zlib/inflating_sink.hpp>
#include <silicium/zlib/zlib.hpp>
<commit_msg>update Win32 #include test<commit_after>#include <silicium/alignment_of.hpp>
#include <silicium/arithmetic/add.hpp>
#include <silicium/arithmetic/overflow_or.hpp>
#include <silicium/array_view.hpp>
#include <silicium/asio/accepting_source.hpp>
#include <silicium/asio/async.hpp>
#include <silicium/asio/async_source.hpp>
#include <silicium/asio/connecting_observable.hpp>
#include <silicium/asio/connecting_source.hpp>
#include <silicium/asio/post_forwarder.hpp>
#include <silicium/asio/posting_observable.hpp>
#include <silicium/asio/process_output.hpp>
#include <silicium/asio/reading_observable.hpp>
#include <silicium/asio/socket_sink.hpp>
#include <silicium/asio/socket_source.hpp>
#include <silicium/asio/tcp_acceptor.hpp>
#include <silicium/asio/timer.hpp>
#include <silicium/asio/use_observable.hpp>
#include <silicium/asio/writing_observable.hpp>
#include <silicium/block_thread.hpp>
#include <silicium/boost_threading.hpp>
#include <silicium/bounded_int.hpp>
#include <silicium/buffer.hpp>
#include <silicium/byte.hpp>
#include <silicium/byte_order_intrinsics.hpp>
#include <silicium/c_string.hpp>
#include <silicium/config.hpp>
#include <silicium/detail/argument_of.hpp>
#include <silicium/detail/basic_dynamic_library.hpp>
#include <silicium/detail/element_from_optional_like.hpp>
#include <silicium/detail/integer_sequence.hpp>
#include <silicium/detail/line_source.hpp>
#include <silicium/detail/proper_value_function.hpp>
#include <silicium/dynamic_library.hpp>
#include <silicium/environment_variables.hpp>
#include <silicium/error_code.hpp>
#include <silicium/error_handler.hpp>
#include <silicium/error_or.hpp>
#include <silicium/exchange.hpp>
#include <silicium/expected.hpp>
#include <silicium/explicit_operator_bool.hpp>
#include <silicium/file_handle.hpp>
#include <silicium/function.hpp>
#include <silicium/future.hpp>
#include <silicium/get_last_error.hpp>
#include <silicium/html/generator.hpp>
#include <silicium/html/tree.hpp>
#include <silicium/http/generate_header.hpp>
#include <silicium/http/generate_request.hpp>
#include <silicium/http/generate_response.hpp>
#include <silicium/http/http.hpp>
#include <silicium/http/parse_request.hpp>
#include <silicium/http/parse_response.hpp>
#include <silicium/http/receive_request.hpp>
#include <silicium/http/request_parser_sink.hpp>
#include <silicium/http/uri.hpp>
#include <silicium/identity.hpp>
#include <silicium/initialize_array.hpp>
#include <silicium/is_handle.hpp>
#include <silicium/iterator_range.hpp>
#include <silicium/make_array.hpp>
#include <silicium/make_destructor.hpp>
#include <silicium/memory_range.hpp>
#include <silicium/move.hpp>
#include <silicium/move_if_noexcept.hpp>
#include <silicium/native_file_descriptor.hpp>
#include <silicium/noexcept_string.hpp>
#include <silicium/null_mutex.hpp>
#include <silicium/observable/bridge.hpp>
#include <silicium/observable/cache.hpp>
#include <silicium/observable/constant.hpp>
#include <silicium/observable/consume.hpp>
#include <silicium/observable/coroutine.hpp>
#include <silicium/observable/coroutine_generator.hpp>
#include <silicium/observable/deref_optional.hpp>
#include <silicium/observable/empty.hpp>
#include <silicium/observable/end.hpp>
#include <silicium/observable/enumerate.hpp>
#include <silicium/observable/erase_shared.hpp>
#include <silicium/observable/erase_unique.hpp>
#include <silicium/observable/erased_observer.hpp>
#include <silicium/observable/error_or_enumerate.hpp>
#include <silicium/observable/extensible_observer.hpp>
#include <silicium/observable/filter.hpp>
#include <silicium/observable/finite_state_machine.hpp>
#include <silicium/observable/flatten.hpp>
#include <silicium/observable/for_each.hpp>
#include <silicium/observable/function.hpp>
#include <silicium/observable/function_observer.hpp>
#include <silicium/observable/generator.hpp>
#include <silicium/observable/limited.hpp>
#include <silicium/observable/observable.hpp>
#include <silicium/observable/observer.hpp>
#include <silicium/observable/on_first.hpp>
#include <silicium/observable/ptr.hpp>
#include <silicium/observable/ready_future.hpp>
#include <silicium/observable/ref.hpp>
#include <silicium/observable/source.hpp>
#include <silicium/observable/spawn_coroutine.hpp>
#include <silicium/observable/spawn_observable.hpp>
#include <silicium/observable/take.hpp>
#include <silicium/observable/thread.hpp>
#include <silicium/observable/thread_generator.hpp>
#include <silicium/observable/total_consumer.hpp>
#include <silicium/observable/transform.hpp>
#include <silicium/observable/transform_if_initialized.hpp>
#include <silicium/observable/tuple.hpp>
#include <silicium/observable/variant.hpp>
#include <silicium/observable/virtualized.hpp>
#include <silicium/observable/while.hpp>
#include <silicium/observable/yield_context.hpp>
#include <silicium/observable2.hpp>
#include <silicium/optional.hpp>
#include <silicium/os_string.hpp>
#include <silicium/pipe.hpp>
#include <silicium/process_handle.hpp>
#include <silicium/program_options.hpp>
#include <silicium/ptr_adaptor.hpp>
#include <silicium/range_value.hpp>
#include <silicium/read_file.hpp>
#include <silicium/serialization.hpp>
#include <silicium/sink/append.hpp>
#include <silicium/sink/buffer.hpp>
#include <silicium/sink/buffering_sink.hpp>
#include <silicium/sink/container_buffer.hpp>
#include <silicium/sink/copy.hpp>
#include <silicium/sink/function_sink.hpp>
#include <silicium/sink/iterator_sink.hpp>
#include <silicium/sink/multi_sink.hpp>
#include <silicium/sink/ostream_sink.hpp>
#include <silicium/sink/ptr_sink.hpp>
#include <silicium/sink/sink.hpp>
#include <silicium/sink/throwing_sink.hpp>
#include <silicium/sink/virtualized_sink.hpp>
#include <silicium/source/buffering_source.hpp>
#include <silicium/source/empty.hpp>
#include <silicium/source/enumerating_source.hpp>
#include <silicium/source/error_extracting_source.hpp>
#include <silicium/source/filter_source.hpp>
#include <silicium/source/generator_source.hpp>
#include <silicium/source/memory_source.hpp>
#include <silicium/source/observable_source.hpp>
#include <silicium/source/ptr_source.hpp>
#include <silicium/source/range_source.hpp>
#include <silicium/source/received_from_socket_source.hpp>
#include <silicium/source/single_source.hpp>
#include <silicium/source/source.hpp>
#include <silicium/source/throwing_source.hpp>
#include <silicium/source/transforming_source.hpp>
#include <silicium/source/virtualized_source.hpp>
#include <silicium/std_threading.hpp>
#include <silicium/steady_clock.hpp>
#include <silicium/success.hpp>
#include <silicium/terminate_on_exception.hpp>
#include <silicium/then.hpp>
#include <silicium/throw_last_error.hpp>
#include <silicium/to_shared.hpp>
#include <silicium/to_unique.hpp>
#include <silicium/trait.hpp>
#include <silicium/type_traits.hpp>
#include <silicium/utility.hpp>
#include <silicium/variant.hpp>
#include <silicium/vector.hpp>
#include <silicium/version.hpp>
#include <silicium/win32/dynamic_library_impl.hpp>
#include <silicium/win32/process_handle.hpp>
#include <silicium/win32/win32.hpp>
#include <silicium/write.hpp>
#include <silicium/zlib/deflating_sink.hpp>
#include <silicium/zlib/inflating_sink.hpp>
#include <silicium/zlib/zlib.hpp>
<|endoftext|>


<commit_before>// Copyright (c) 2007, 2008 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include <cmath>

#include "libmv/image/image.h"
#include "libmv/image/convolve.h"

namespace libmv {

// Zero mean Gaussian.
double Gaussian(double x, double sigma) {
  return 1/sqrt(2*M_PI*sigma*sigma) * exp(-(x*x/2/sigma/sigma));
}
double GaussianDerivative(double x, double sigma) {
  return -x / sigma / sigma * Gaussian(x, sigma);
}
// Solve the inverse of the Gaussian for positive x.
double GaussianInversePositive(double y, double sigma) {
  return sqrt(-2 * sigma * sigma * log(y * sigma * sqrt(2*M_PI)));
}

// Compute a Gaussian kernel and derivative, such that you can take the
// derivitave of an image by convolving with the kernel horizontally then the
// derivative vertically to get (eg) the y derivative.
void ComputeGaussianKernel(double sigma, Vec *kernel, Vec *derivative) {
  assert(sigma >= 0.0);

  // 0.004 implies a 3 pixel kernel with 1 pixel sigma.
  const float truncation_factor = 0.004f;

  // Calculate the kernel size based on sigma such that it is odd.
  float precisehalfwidth = GaussianInversePositive(truncation_factor, sigma);
  int width = lround(2*precisehalfwidth);
  if (width % 2 == 0) {
    width++;
  }
  // Calculate the gaussian kernel and its derivative.
  kernel->resize(width);
  derivative->resize(width);
  *kernel = 0.0;
  *derivative = 0.0;
  int halfwidth = width / 2;
  for (int i = -halfwidth; i <= halfwidth; ++i)  {
    (*kernel)(i + halfwidth) = Gaussian(i, sigma);
    (*derivative)(i + halfwidth) = GaussianDerivative(i, sigma);
  }
  // Since images should not get brighter or darker, normalize.
  NormalizeL1(kernel);
  // Normalize the derivative differently. See
  // www.cs.duke.edu/courses/spring03/cps296.1/handouts/Image%20Processing.pdf
  double factor = 0.;
  for (int i = -halfwidth; i <= halfwidth; ++i)  {
    factor -= i*(*derivative)(i+halfwidth);
  }
  *derivative /= factor;
}

void ConvolveHorizontal(const Array3Df &in,
                        const Vec &kernel,
                        Array3Df *out_pointer,
                        int plane) {
  int halfwidth = kernel.length() / 2;
  int num_columns = in.Width();
  int num_rows = in.Height();
  Array3Df &out = *out_pointer;
  if (plane == -1) {
    out.ResizeLike(in);
    plane = 0;
  }

  assert(kernel.length() % 2 == 1);
  assert(&in != out_pointer);

  for (int j = 0; j < num_rows; ++j)  {
    for (int i = 0; i < num_columns; ++i)  {
      double sum = 0.0;
      int l = 0;
      for (int k = kernel.length()-1; k >= 0; --k, ++l) {
        int ii = i - halfwidth + l;
        if (0 <= ii && ii < num_columns) {
          sum += in(j, ii) * kernel(k);
        }
      }
      out(j, i, plane) = sum;
    }
  }
}

// This could certainly be accelerated.
void ConvolveVertical(const Array3Df &in,
                      const Vec &kernel,
                      Array3Df *out_pointer,
                      int plane) {
  int halfwidth = kernel.length() / 2;
  int num_columns = in.Width();
  int num_rows = in.Height();
  Array3Df &out = *out_pointer;
  if (plane == -1) {
    out.ResizeLike(in);
    plane = 0;
  }

  assert(kernel.length() % 2 == 1);
  assert(&in != out_pointer);

  for (int i = 0; i < num_columns; ++i)  {
    for (int j = 0; j < num_rows; ++j)  {
      double sum = 0.0;
      int l = 0;
      for (int k = kernel.length()-1; k >= 0; --k, ++l) {
        int jj = j - halfwidth + l;
        if (0 <= jj && jj < num_rows) {
          sum += in(jj, i) * kernel(k);
        }
      }
      out(j, i, plane) = sum;
    }
  }
}

void ConvolveGaussian(const Array3Df &in,
                      double sigma,
                      Array3Df *out_pointer) {
  Vec kernel, derivative;
  ComputeGaussianKernel(sigma, &kernel, &derivative);

  Array3Df tmp;
  ConvolveVertical(in, kernel, &tmp);
  ConvolveHorizontal(tmp, kernel, out_pointer);
}

void BlurredImageAndDerivatives(const Array3Df &in,
                                double sigma,
                                Array3Df *blurred_image,
                                Array3Df *gradient_x,
                                Array3Df *gradient_y) {
  Vec kernel, derivative;
  ComputeGaussianKernel(sigma, &kernel, &derivative);
  Array3Df tmp;

  // Compute convolved image.
  ConvolveVertical(in, kernel, &tmp);
  ConvolveHorizontal(tmp, kernel, blurred_image);

  // Compute first derivative in x.
  ConvolveHorizontal(tmp, derivative, gradient_x);

  // Compute first derivative in y.
  ConvolveHorizontal(in, kernel, &tmp);
  ConvolveVertical(tmp, derivative, gradient_y);
}

// Compute the gaussian blur of an image and the derivatives of the blurred
// image, and store the results in three channels. Since the blurred value and
// gradients are closer in memory, this leads to better performance if all
// three values are needed at the same time.
void BlurredImageAndDerivativesChannels(const Array3Df &in,
                                        double sigma,
                                        Array3Df *blurred_and_gradxy) {
  assert(in.Depth() == 1);

  Vec kernel, derivative;
  ComputeGaussianKernel(sigma, &kernel, &derivative);

  // Compute convolved image.
  Array3Df tmp;
  ConvolveVertical(in, kernel, &tmp);
  blurred_and_gradxy->Resize(in.Height(), in.Width(), 3);
  ConvolveHorizontal(tmp, kernel, blurred_and_gradxy, 0);

  // Compute first derivative in x.
  ConvolveHorizontal(tmp, derivative, blurred_and_gradxy, 1);

  // Compute first derivative in y.
  ConvolveHorizontal(in, kernel, &tmp);
  ConvolveVertical(tmp, derivative, blurred_and_gradxy, 2);
}

void BoxFilterHorizontal(const Array3Df &in,
                         int window_size,
                         Array3Df *out_pointer) {
  Array3Df &out = *out_pointer;
  out.ResizeLike(in);
  int half_width = (window_size - 1) / 2;

  for (int k = 0; k < in.Depth(); ++k) {
    for (int i=0; i<in.Height(); ++i) {
      float sum = 0;
      // Init sum.
      for (int j=0; j<half_width; ++j) {
        sum += in(i, j, k);
      }
      // Fill left border.
      for (int j=0; j < half_width + 1; ++j) {
        sum += in(i, j + half_width, k);
        out(i, j, k) = sum;
      }
      // Fill interior.
      for (int j = half_width + 1; j<in.Width()-half_width; ++j) {
        sum -= in(i, j - half_width - 1, k);
        sum += in(i, j + half_width, k);
        out(i, j, k) = sum;
      }
      // Fill right border.
      for (int j = in.Width() - half_width; j<in.Width(); ++j) {
        sum -= in(i, j - half_width - 1, k);
        out(i, j, k) = sum;
      }
    }
  }
}

void BoxFilterVertical(const Array3Df &in,
                       int window_size,
                       Array3Df *out_pointer) {
  Array3Df &out = *out_pointer;
  out.ResizeLike(in);
  int half_width = (window_size - 1) / 2;

  for (int k = 0; k < in.Depth(); ++k) {
    for (int j = 0; j < in.Width(); ++j) {
      float sum = 0;
      // Init sum.
      for (int i=0; i<half_width; ++i) {
        sum += in(i, j, k);
      }
      // Fill left border.
      for (int i=0; i < half_width + 1; ++i) {
        sum += in(i + half_width, j, k);
        out(i, j, k) = sum;
      }
      // Fill interior.
      for (int i = half_width + 1; i<in.Height()-half_width; ++i) {
        sum -= in(i - half_width - 1, j, k);
        sum += in(i + half_width, j, k);
        out(i, j, k) = sum;
      }
      // Fill right border.
      for (int i = in.Height() - half_width; i<in.Height(); ++i) {
        sum -= in(i - half_width - 1, j, k);
        out(i, j, k) = sum;
      }
    }
  }
}

void BoxFilter(const Array3Df &in,
               int box_width,
               Array3Df *out) {
  Array3Df tmp;
  BoxFilterHorizontal(in, box_width, &tmp);
  BoxFilterVertical(tmp, box_width, out);
};

}  // namespace libmv
<commit_msg>Start switching to row, column notation.<commit_after>// Copyright (c) 2007, 2008 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include <cmath>

#include "libmv/image/image.h"
#include "libmv/image/convolve.h"

namespace libmv {

// Zero mean Gaussian.
double Gaussian(double x, double sigma) {
  return 1/sqrt(2*M_PI*sigma*sigma) * exp(-(x*x/2/sigma/sigma));
}
double GaussianDerivative(double x, double sigma) {
  return -x / sigma / sigma * Gaussian(x, sigma);
}
// Solve the inverse of the Gaussian for positive x.
double GaussianInversePositive(double y, double sigma) {
  return sqrt(-2 * sigma * sigma * log(y * sigma * sqrt(2*M_PI)));
}

// Compute a Gaussian kernel and derivative, such that you can take the
// derivitave of an image by convolving with the kernel horizontally then the
// derivative vertically to get (eg) the y derivative.
void ComputeGaussianKernel(double sigma, Vec *kernel, Vec *derivative) {
  assert(sigma >= 0.0);

  // 0.004 implies a 3 pixel kernel with 1 pixel sigma.
  const float truncation_factor = 0.004f;

  // Calculate the kernel size based on sigma such that it is odd.
  float precisehalfwidth = GaussianInversePositive(truncation_factor, sigma);
  int width = lround(2*precisehalfwidth);
  if (width % 2 == 0) {
    width++;
  }
  // Calculate the gaussian kernel and its derivative.
  kernel->resize(width);
  derivative->resize(width);
  *kernel = 0.0;
  *derivative = 0.0;
  int halfwidth = width / 2;
  for (int i = -halfwidth; i <= halfwidth; ++i)  {
    (*kernel)(i + halfwidth) = Gaussian(i, sigma);
    (*derivative)(i + halfwidth) = GaussianDerivative(i, sigma);
  }
  // Since images should not get brighter or darker, normalize.
  NormalizeL1(kernel);
  // Normalize the derivative differently. See
  // www.cs.duke.edu/courses/spring03/cps296.1/handouts/Image%20Processing.pdf
  double factor = 0.;
  for (int i = -halfwidth; i <= halfwidth; ++i)  {
    factor -= i*(*derivative)(i+halfwidth);
  }
  *derivative /= factor;
}

void ConvolveHorizontal(const Array3Df &in,
                        const Vec &kernel,
                        Array3Df *out_pointer,
                        int plane) {
  int halfwidth = kernel.length() / 2;
  int num_columns = in.Width();
  int num_rows = in.Height();
  Array3Df &out = *out_pointer;
  if (plane == -1) {
    out.ResizeLike(in);
    plane = 0;
  }

  assert(kernel.length() % 2 == 1);
  assert(&in != out_pointer);

  for (int r = 0; r < num_rows; ++r)  {
    for (int c = 0; c < num_columns; ++c)  {
      double sum = 0.0;
      int l = 0;
      for (int k = kernel.length() - 1; k >= 0; --k, ++l) {
        int cc = c - halfwidth + l;
        if (0 <= cc && cc < num_columns) {
          sum += in(r, cc) * kernel(k);
        }
      }
      out(r, c, plane) = sum;
    }
  }
}

// This could certainly be accelerated.
void ConvolveVertical(const Array3Df &in,
                      const Vec &kernel,
                      Array3Df *out_pointer,
                      int plane) {
  int halfwidth = kernel.length() / 2;
  int num_columns = in.Width();
  int num_rows = in.Height();
  Array3Df &out = *out_pointer;
  if (plane == -1) {
    out.ResizeLike(in);
    plane = 0;
  }

  assert(kernel.length() % 2 == 1);
  assert(&in != out_pointer);

  for (int i = 0; i < num_columns; ++i)  {
    for (int j = 0; j < num_rows; ++j)  {
      double sum = 0.0;
      int l = 0;
      for (int k = kernel.length()-1; k >= 0; --k, ++l) {
        int jj = j - halfwidth + l;
        if (0 <= jj && jj < num_rows) {
          sum += in(jj, i) * kernel(k);
        }
      }
      out(j, i, plane) = sum;
    }
  }
}

void ConvolveGaussian(const Array3Df &in,
                      double sigma,
                      Array3Df *out_pointer) {
  Vec kernel, derivative;
  ComputeGaussianKernel(sigma, &kernel, &derivative);

  Array3Df tmp;
  ConvolveVertical(in, kernel, &tmp);
  ConvolveHorizontal(tmp, kernel, out_pointer);
}

void BlurredImageAndDerivatives(const Array3Df &in,
                                double sigma,
                                Array3Df *blurred_image,
                                Array3Df *gradient_x,
                                Array3Df *gradient_y) {
  Vec kernel, derivative;
  ComputeGaussianKernel(sigma, &kernel, &derivative);
  Array3Df tmp;

  // Compute convolved image.
  ConvolveVertical(in, kernel, &tmp);
  ConvolveHorizontal(tmp, kernel, blurred_image);

  // Compute first derivative in x.
  ConvolveHorizontal(tmp, derivative, gradient_x);

  // Compute first derivative in y.
  ConvolveHorizontal(in, kernel, &tmp);
  ConvolveVertical(tmp, derivative, gradient_y);
}

// Compute the gaussian blur of an image and the derivatives of the blurred
// image, and store the results in three channels. Since the blurred value and
// gradients are closer in memory, this leads to better performance if all
// three values are needed at the same time.
void BlurredImageAndDerivativesChannels(const Array3Df &in,
                                        double sigma,
                                        Array3Df *blurred_and_gradxy) {
  assert(in.Depth() == 1);

  Vec kernel, derivative;
  ComputeGaussianKernel(sigma, &kernel, &derivative);

  // Compute convolved image.
  Array3Df tmp;
  ConvolveVertical(in, kernel, &tmp);
  blurred_and_gradxy->Resize(in.Height(), in.Width(), 3);
  ConvolveHorizontal(tmp, kernel, blurred_and_gradxy, 0);

  // Compute first derivative in x.
  ConvolveHorizontal(tmp, derivative, blurred_and_gradxy, 1);

  // Compute first derivative in y.
  ConvolveHorizontal(in, kernel, &tmp);
  ConvolveVertical(tmp, derivative, blurred_and_gradxy, 2);
}

void BoxFilterHorizontal(const Array3Df &in,
                         int window_size,
                         Array3Df *out_pointer) {
  Array3Df &out = *out_pointer;
  out.ResizeLike(in);
  int half_width = (window_size - 1) / 2;

  for (int k = 0; k < in.Depth(); ++k) {
    for (int i=0; i<in.Height(); ++i) {
      float sum = 0;
      // Init sum.
      for (int j=0; j<half_width; ++j) {
        sum += in(i, j, k);
      }
      // Fill left border.
      for (int j=0; j < half_width + 1; ++j) {
        sum += in(i, j + half_width, k);
        out(i, j, k) = sum;
      }
      // Fill interior.
      for (int j = half_width + 1; j<in.Width()-half_width; ++j) {
        sum -= in(i, j - half_width - 1, k);
        sum += in(i, j + half_width, k);
        out(i, j, k) = sum;
      }
      // Fill right border.
      for (int j = in.Width() - half_width; j<in.Width(); ++j) {
        sum -= in(i, j - half_width - 1, k);
        out(i, j, k) = sum;
      }
    }
  }
}

void BoxFilterVertical(const Array3Df &in,
                       int window_size,
                       Array3Df *out_pointer) {
  Array3Df &out = *out_pointer;
  out.ResizeLike(in);
  int half_width = (window_size - 1) / 2;

  for (int k = 0; k < in.Depth(); ++k) {
    for (int j = 0; j < in.Width(); ++j) {
      float sum = 0;
      // Init sum.
      for (int i=0; i<half_width; ++i) {
        sum += in(i, j, k);
      }
      // Fill left border.
      for (int i=0; i < half_width + 1; ++i) {
        sum += in(i + half_width, j, k);
        out(i, j, k) = sum;
      }
      // Fill interior.
      for (int i = half_width + 1; i<in.Height()-half_width; ++i) {
        sum -= in(i - half_width - 1, j, k);
        sum += in(i + half_width, j, k);
        out(i, j, k) = sum;
      }
      // Fill right border.
      for (int i = in.Height() - half_width; i<in.Height(); ++i) {
        sum -= in(i - half_width - 1, j, k);
        out(i, j, k) = sum;
      }
    }
  }
}

void BoxFilter(const Array3Df &in,
               int box_width,
               Array3Df *out) {
  Array3Df tmp;
  BoxFilterHorizontal(in, box_width, &tmp);
  BoxFilterVertical(tmp, box_width, out);
};

}  // namespace libmv
<|endoftext|>


<commit_before>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://www.visualizationlibrary.com                                               */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  All rights reserved.                                                              */
/*                                                                                */
/*  Redistribution and use in source and binary forms, with or without modification,  */
/*  are permitted provided that the following conditions are met:                     */
/*                                                                                */
/*  - Redistributions of source code must retain the above copyright notice, this     */
/*  list of conditions and the following disclaimer.                                  */
/*                                                                                */
/*  - 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.                      */
/*                                                                                */
/**************************************************************************************/

#ifndef MultiDrawElements_INCLUDE_ONCE
#define MultiDrawElements_INCLUDE_ONCE

#include <vl/Primitives.hpp>
#include <vl/Array.hpp>
#include <vl/Log.hpp>
#include <vl/Say.hpp>
#include <algorithm>

namespace vl
{
  //------------------------------------------------------------------------------
  // MultiDrawElements
  //------------------------------------------------------------------------------
  /**
   * Wrapper for the OpenGL function glMultiDrawElements(), see also http://www.opengl.org/sdk/docs/man/xhtml/glMultiDrawElements.xml for more information.
   *
  */
  template <typename index_type, GLenum Tgltype, class arr_type>
  class MultiDrawElements: public Primitives
  {
  public:
    virtual const char* className() { return "MultiDrawElements"; }

    MultiDrawElements(EPrimitiveType primitive = PT_TRIANGLES)
    {
      #ifndef NDEBUG
        mObjectName = className();
      #endif
      mType                    = primitive;
      mIndexBuffer             = new arr_type;
      mPrimitiveRestartIndex   = ~(index_type)0;
      mPrimitiveRestartEnabled = false;
    }

    MultiDrawElements& operator=(const MultiDrawElements& other)
    {
      Primitives::operator=(other);
      *indices() = *other.indices();
      mPrimitiveRestartEnabled = other.mPrimitiveRestartEnabled;
      mPrimitiveRestartIndex   = other.mPrimitiveRestartIndex;
      setCountVector(other.mCountVector);
      return *this;
    }

    virtual ref<Primitives> clone() const
    {
      ref<MultiDrawElements> de = new MultiDrawElements;
      *de = *this;
      return de;
    }

    virtual unsigned int handle() const { return indices()->gpuBuffer()->handle(); }

    virtual size_t indexCount() const { return indices()->size(); }

    virtual size_t indexCountGPU() const { return indices()->sizeGPU(); }

    virtual size_t index(int i) const { return (int)indices()->at(i); }

    arr_type* indices() { return mIndexBuffer.get(); }
    const arr_type* indices() const { return mIndexBuffer.get(); }

    virtual void updateVBOs(bool discard_local_data = false)
    {
      indices()->updateVBO(discard_local_data);
    }

    virtual void deleteVBOs()
    {
      indices()->gpuBuffer()->deleteGLBufferObject();
    }

    virtual void clearLocalBuffer()
    {
      indices()->gpuBuffer()->resize(0);
    }

    /** Returns the number of triangles contained in this primitive set.
      * \note This function returns -1 if primitive restart is enabled. */
    int triangleCount() const
    {
      if (primitiveRestartEnabled())
        return -1;

      int total_count = 0;
      for(size_t i=0; i<mCountVector.size(); ++i)
      {
        size_t count = mCountVector[i];
        switch( mType )
        {
          case PT_TRIANGLES: total_count += (count / 3);
          case PT_TRIANGLE_STRIP: total_count += (count - 2);
          case PT_TRIANGLE_FAN: total_count += (count - 2);
          case PT_QUADS: total_count += (count / 4 * 2);
          case PT_QUAD_STRIP: total_count += ( (count - 2) / 2 ) * 2;
          case PT_POLYGON: total_count += (count - 2);
          case PT_POINTS:
          case PT_LINES:
          case PT_LINE_LOOP:
          case PT_LINE_STRIP:
          default:
            break;
        }
      }

      return total_count;
    }

    /** Returns the number of lines contained in this primitive set.
      * \note This function returns -1 if primitive restart is enabled. */
    int lineCount() const
    {
      if (primitiveRestartEnabled())
        return -1;

      int total_count = 0;
      for(size_t i=0; i<mCountVector.size(); ++i)
      {
        size_t count = mCountVector[i];
        switch( mType )
        {
          case PT_LINES:      total_count += count / 2;
          case PT_LINE_LOOP:  total_count += count;
          case PT_LINE_STRIP: total_count += count - 1;
          default:
            break;
        }
      }

      return total_count;
    }

    /** Returns the number of points contained in this primitive set.
      * \note This function returns -1 if primitive restart is enabled. */
    int pointCount() const
    {
      if (primitiveRestartEnabled())
        return -1;

      int total_count = 0;
      for(size_t i=0; i<mCountVector.size(); ++i)
      {
        size_t count = mCountVector[i];
        switch( mType )
        {
        case PT_POINTS: total_count += count;
        default:
          break;
        }
      }

      return total_count;
    }

    /** Returns always false. */
    virtual bool getTriangle( size_t, unsigned int*) const
    {
      return false;
    }

    virtual void render(bool use_vbo) const
    {
      VL_CHECK(GLEW_VERSION_1_4);
      VL_CHECK(!use_vbo || (use_vbo && (GLEW_ARB_vertex_buffer_object||GLEW_VERSION_1_5||GLEW_VERSION_3_0)))
      use_vbo &= GLEW_ARB_vertex_buffer_object||GLEW_VERSION_1_5||GLEW_VERSION_3_0; // && indices()->gpuBuffer()->handle() && indexCountGPU();
      if ( !use_vbo && !indexCount() )
        return;

      // primitive restart enable
      if(primitiveRestartEnabled())
      {
        if(GLEW_VERSION_3_1)
        {
          glEnable(GL_PRIMITIVE_RESTART);
          glPrimitiveRestartIndex(primitiveRestartIndex());
        }
        else
        if(GLEW_NV_primitive_restart)
        {
          glEnable(GL_PRIMITIVE_RESTART_NV);
          glPrimitiveRestartIndexNV(primitiveRestartIndex());
        }
        else
        {
          vl::Log::error("MultiDrawElements error: primitive restart not supported by this OpenGL implementation!\n");
          VL_TRAP();
          return;
        }
      }

      if (use_vbo && indices()->gpuBuffer()->handle())
      {
        VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices()->gpuBuffer()->handle());
      }
      else
        VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

      if (use_vbo)
      {
        glMultiDrawElements(
          primitiveType(),
          (GLsizei*)&mCountVector[0],
          indices()->glType(),
          (const GLvoid**)&mNULLPointerVector[0], mCountVector.size()
        );
      }
      else
      {
        glMultiDrawElements(
          primitiveType(),
          (GLsizei*)&mCountVector[0],
          indices()->glType(),
          (const GLvoid**)&mPointerVector[0], mCountVector.size()
        );
      }

      // primitive restart disable
      if(primitiveRestartEnabled())
      {
        if(GLEW_VERSION_3_1)
          glDisable(GL_PRIMITIVE_RESTART);
        else
        if(GLEW_NV_primitive_restart)
          glDisable(GL_PRIMITIVE_RESTART_NV);
      }

      if (use_vbo && this->indices()->gpuBuffer()->handle())
        VL_glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
    }

    /** Sets the vector defining the length of each primitive and automatically computes the pointer
      * vectors used to exectue glMultiDrawElements(). */
    void setCountVector(const std::vector<GLsizei>& vcount)
    {
      mCountVector = vcount;

      // set all to null: used when VBO is active.
      mNULLPointerVector.resize( vcount.size() );

      // used when VBOs are not active.
      mPointerVector.clear();
      const index_type* ptr = (const index_type*)indices()->gpuBuffer()->ptr();
      for(size_t i=0; i<vcount.size(); ++i)
      {
        mPointerVector.push_back(ptr);
        ptr += vcount[i];
      }
      VL_CHECK( ptr - (const index_type*)indices()->gpuBuffer()->ptr() <= indexCount() );
    }

    /** The count vector used as 'count' parameter of glMultiDrawElements. */
    const std::vector<unsigned int>& countVector() const { return mCountVector; }

    /** The pointer vector used as 'indices' parameter of glMultiDrawElements. */
    const std::vector<index_type*>& pointerVector() const { return mPointerVector; }

    /** Returns the special index which idendifies a primitive restart. By default it is set to ~0 that is 0xFF, 0xFFFF, 0xFFFFFFFF respectively for ubyte, ushort, uint types. */
    GLuint primitiveRestartIndex() const { return mPrimitiveRestartIndex; }
    /** Sets the special index which idendifies a primitive restart. By default it is set to ~0 that is 0xFF, 0xFFFF, 0xFFFFFFFF respectively for ubyte, ushort, uint types. */
    void setPrimitiveRestartIndex(GLuint index) { mPrimitiveRestartIndex = index; }

    /** Returns whether the primitive-restart functionality is enabled or not. See http://www.opengl.org/registry/specs/NV/primitive_restart.txt */
    bool primitiveRestartEnabled() const { return mPrimitiveRestartEnabled; }

    /** Enables the primitive-restart functionality. See http://www.opengl.org/registry/specs/NV/primitive_restart.txt
      * \note Functions like triangleCount(), lineCount(), pointCount() and sortTriangles() should not be used when primitive restart is enabled. */
    void setPrimitiveRestartEnabled(bool enabled) { mPrimitiveRestartEnabled = enabled; }

  protected:
    ref< arr_type > mIndexBuffer;
    GLuint mPrimitiveRestartIndex;
    bool mPrimitiveRestartEnabled;

    std::vector<GLsizei>           mCountVector;
    std::vector<const index_type*> mPointerVector;
    std::vector<const index_type*> mNULLPointerVector;
  };
  //------------------------------------------------------------------------------
  // typedefs
  //------------------------------------------------------------------------------
  /** A MultiDrawElements using indices of type \p GLuint. */
  typedef MultiDrawElements<GLuint, GL_UNSIGNED_INT, ArrayUInt> MultiDrawElementsUInt;
  //------------------------------------------------------------------------------
  /** A MultiDrawElements using indices of type \p GLushort. */
  typedef MultiDrawElements<GLushort, GL_UNSIGNED_SHORT, ArrayUShort> MultiDrawElementsUShort;
  //------------------------------------------------------------------------------
  /** A MultiDrawElements using indices of type \p GLubyte. */
  typedef MultiDrawElements<GLubyte, GL_UNSIGNED_BYTE, ArrayUByte> MultiDrawElementsUByte;
  //------------------------------------------------------------------------------
}

#endif
<commit_msg>Added support to glMultiDrawElementsBaseVertex() and compilation fixes<commit_after>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://www.visualizationlibrary.com                                               */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  All rights reserved.                                                              */
/*                                                                                */
/*  Redistribution and use in source and binary forms, with or without modification,  */
/*  are permitted provided that the following conditions are met:                     */
/*                                                                                */
/*  - Redistributions of source code must retain the above copyright notice, this     */
/*  list of conditions and the following disclaimer.                                  */
/*                                                                                */
/*  - 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.                      */
/*                                                                                */
/**************************************************************************************/

#ifndef MultiDrawElements_INCLUDE_ONCE
#define MultiDrawElements_INCLUDE_ONCE

#include <vl/Primitives.hpp>
#include <vl/Array.hpp>
#include <vl/Log.hpp>
#include <vl/Say.hpp>
#include <algorithm>

namespace vl
{
  //------------------------------------------------------------------------------
  // MultiDrawElements
  //------------------------------------------------------------------------------
  /**
   * Wrapper for the OpenGL function glMultiDrawElements(), see also http://www.opengl.org/sdk/docs/man/xhtml/glMultiDrawElements.xml for more information.
   *
  */
  template <typename index_type, GLenum Tgltype, class arr_type>
  class MultiDrawElements: public Primitives
  {
  public:
    virtual const char* className() { return "MultiDrawElements"; }

    MultiDrawElements(EPrimitiveType primitive = PT_TRIANGLES)
    {
      #ifndef NDEBUG
        mObjectName = className();
      #endif
      mType                    = primitive;
      mIndexBuffer             = new arr_type;
      mPrimitiveRestartIndex   = ~(index_type)0;
      mPrimitiveRestartEnabled = false;
    }

    MultiDrawElements& operator=(const MultiDrawElements& other)
    {
      Primitives::operator=(other);
      *indices() = *other.indices();
      mPrimitiveRestartEnabled = other.mPrimitiveRestartEnabled;
      mPrimitiveRestartIndex   = other.mPrimitiveRestartIndex;
      setCountVector(other.mCountVector);
      return *this;
    }

    virtual ref<Primitives> clone() const
    {
      ref<MultiDrawElements> de = new MultiDrawElements;
      *de = *this;
      return de;
    }

    virtual unsigned int handle() const { return indices()->gpuBuffer()->handle(); }

    virtual size_t indexCount() const { return indices()->size(); }

    virtual size_t indexCountGPU() const { return indices()->sizeGPU(); }

    /** The index returned does not include the the base vertex. */
    virtual size_t index(int i) const
    {
      return indices()->at(i);
    }

    arr_type* indices() { return mIndexBuffer.get(); }
    const arr_type* indices() const { return mIndexBuffer.get(); }

    virtual void updateVBOs(bool discard_local_data = false)
    {
      indices()->updateVBO(discard_local_data);
    }

    virtual void deleteVBOs()
    {
      indices()->gpuBuffer()->deleteGLBufferObject();
    }

    virtual void clearLocalBuffer()
    {
      indices()->gpuBuffer()->resize(0);
    }

    /** Returns the number of triangles contained in this primitive set.
      * \note This function returns -1 if primitive restart is enabled. */
    int triangleCount() const
    {
      if (primitiveRestartEnabled())
        return -1;

      int total_count = 0;
      for(size_t i=0; i<mCountVector.size(); ++i)
      {
        size_t count = mCountVector[i];
        switch( mType )
        {
          case PT_TRIANGLES: total_count += (count / 3);
          case PT_TRIANGLE_STRIP: total_count += (count - 2);
          case PT_TRIANGLE_FAN: total_count += (count - 2);
          case PT_QUADS: total_count += (count / 4 * 2);
          case PT_QUAD_STRIP: total_count += ( (count - 2) / 2 ) * 2;
          case PT_POLYGON: total_count += (count - 2);
          case PT_POINTS:
          case PT_LINES:
          case PT_LINE_LOOP:
          case PT_LINE_STRIP:
          default:
            break;
        }
      }

      return total_count;
    }

    /** Returns the number of lines contained in this primitive set.
      * \note This function returns -1 if primitive restart is enabled. */
    int lineCount() const
    {
      if (primitiveRestartEnabled())
        return -1;

      int total_count = 0;
      for(size_t i=0; i<mCountVector.size(); ++i)
      {
        size_t count = mCountVector[i];
        switch( mType )
        {
          case PT_LINES:      total_count += count / 2;
          case PT_LINE_LOOP:  total_count += count;
          case PT_LINE_STRIP: total_count += count - 1;
          default:
            break;
        }
      }

      return total_count;
    }

    /** Returns the number of points contained in this primitive set.
      * \note This function returns -1 if primitive restart is enabled. */
    int pointCount() const
    {
      if (primitiveRestartEnabled())
        return -1;

      int total_count = 0;
      for(size_t i=0; i<mCountVector.size(); ++i)
      {
        size_t count = mCountVector[i];
        switch( mType )
        {
        case PT_POINTS: total_count += count;
        default:
          break;
        }
      }

      return total_count;
    }

    /** Returns always false. */
    virtual bool getTriangle( size_t, unsigned int*) const
    {
      return false;
    }

    virtual void render(bool use_vbo) const
    {
      VL_CHECK(GLEW_VERSION_1_4);
      VL_CHECK(!use_vbo || (use_vbo && (GLEW_ARB_vertex_buffer_object||GLEW_VERSION_1_5||GLEW_VERSION_3_0)))
      use_vbo &= GLEW_ARB_vertex_buffer_object||GLEW_VERSION_1_5||GLEW_VERSION_3_0; // && indices()->gpuBuffer()->handle() && indexCountGPU();
      if ( !use_vbo && !indexCount() )
        return;

      // primitive restart enable
      if(primitiveRestartEnabled())
      {
        if(GLEW_VERSION_3_1)
        {
          glEnable(GL_PRIMITIVE_RESTART);
          glPrimitiveRestartIndex(primitiveRestartIndex());
        }
        else
        if(GLEW_NV_primitive_restart)
        {
          glEnable(GL_PRIMITIVE_RESTART_NV);
          glPrimitiveRestartIndexNV(primitiveRestartIndex());
        }
        else
        {
          vl::Log::error("MultiDrawElements error: primitive restart not supported by this OpenGL implementation!\n");
          VL_TRAP();
          return;
        }
      }

      GLvoid **indices_ptr = (GLvoid**)&mPointerVector[0];
      if (use_vbo && indices()->gpuBuffer()->handle())
      {
        VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices()->gpuBuffer()->handle());
        indices_ptr = (GLvoid**)&mNULLPointerVector[0];
      }
      else
        VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

      if (baseVertices().size())
      {
        VL_CHECK( baseVertices().size() == pointerVector().size() )
        VL_CHECK( baseVertices().size() == countVector().size() )
        if (GLEW_ARB_draw_elements_base_vertex || GLEW_VERSION_3_1)
          glMultiDrawElementsBaseVertex(
            primitiveType(), (GLsizei*)&mCountVector[0], indices()->glType(), indices_ptr, mCountVector.size(), (GLint*)&mBaseVertices[0]
          );
        else
        {
          vl::Log::error("MultiDrawElements::render(): glMultiDrawElementsBaseVertex() not supported!\n"
            "OpenGL 3.1 or GL_ARB_draw_elements_base_vertex extension required.\n"
          );
        }
      }
      else
        glMultiDrawElements(
          primitiveType(), (GLsizei*)&mCountVector[0], indices()->glType(), (const GLvoid**)indices_ptr, mCountVector.size()
        );

      // primitive restart disable
      if(primitiveRestartEnabled())
      {
        if(GLEW_VERSION_3_1)
          glDisable(GL_PRIMITIVE_RESTART);
        else
        if(GLEW_NV_primitive_restart)
          glDisable(GL_PRIMITIVE_RESTART_NV);
      }

      if (use_vbo && this->indices()->gpuBuffer()->handle())
        VL_glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
    }

    /** Sets the vector defining the length of each primitive and automatically computes the pointer
      * vectors used to exectue glMultiDrawElements(). */
    void setCountVector(const std::vector<GLsizei>& vcount)
    {
      mCountVector = vcount;

      // set all to null: used when VBO is active.
      mNULLPointerVector.resize( vcount.size() );

      // used when VBOs are not active.
      mPointerVector.clear();
      const index_type* ptr = (const index_type*)indices()->gpuBuffer()->ptr();
      for(size_t i=0; i<vcount.size(); ++i)
      {
        mPointerVector.push_back(ptr);
        ptr += vcount[i];
      }
      VL_CHECK( ptr - (const index_type*)indices()->gpuBuffer()->ptr() <= indexCount() );
    }

    /** The count vector used as 'count' parameter of glMultiDrawElements. */
    const std::vector<GLsizei>& countVector() const { return mCountVector; }

    /** The pointer vector used as 'indices' parameter of glMultiDrawElements. */
    const std::vector<const index_type*>& pointerVector() const { return mPointerVector; }

    /** Returns the special index which idendifies a primitive restart. By default it is set to ~0 that is 0xFF, 0xFFFF, 0xFFFFFFFF respectively for ubyte, ushort, uint types. */
    GLuint primitiveRestartIndex() const { return mPrimitiveRestartIndex; }
    /** Sets the special index which idendifies a primitive restart. By default it is set to ~0 that is 0xFF, 0xFFFF, 0xFFFFFFFF respectively for ubyte, ushort, uint types. */
    void setPrimitiveRestartIndex(GLuint index) { mPrimitiveRestartIndex = index; }

    /** Returns whether the primitive-restart functionality is enabled or not. See http://www.opengl.org/registry/specs/NV/primitive_restart.txt */
    bool primitiveRestartEnabled() const { return mPrimitiveRestartEnabled; }

    /** Enables the primitive-restart functionality. See http://www.opengl.org/registry/specs/NV/primitive_restart.txt
      * \note Functions like triangleCount(), lineCount(), pointCount() and sortTriangles() should not be used when primitive restart is enabled. */
    void setPrimitiveRestartEnabled(bool enabled) { mPrimitiveRestartEnabled = enabled; }

    /** Returns the list of base vertices, one for each primitive. This will enable the use
      * of glMultiDrawElementsBaseVertex() to render a set of primitives.
      * See also http://www.opengl.org/sdk/docs/man3/xhtml/glMultiDrawElementsBaseVertex.xml */
    void setBaseVertices(const std::vector<GLint>& base_verts) { mBaseVertices = base_verts; }
    /** Returns the list of base vertices, one for each primitive. */
    const std::vector<GLint>& baseVertices() const { return mBaseVertices; }
    /** Returns the list of base vertices, one for each primitive. */
    std::vector<GLint>& baseVertices() { return mBaseVertices; }

  protected:
    ref< arr_type > mIndexBuffer;
    GLuint mPrimitiveRestartIndex;
    bool mPrimitiveRestartEnabled;

    std::vector<GLsizei>           mCountVector;
    std::vector<const index_type*> mPointerVector;
    std::vector<const index_type*> mNULLPointerVector;
    std::vector<GLint> mBaseVertices;
  };
  //------------------------------------------------------------------------------
  // typedefs
  //------------------------------------------------------------------------------
  /** A MultiDrawElements using indices of type \p GLuint. */
  typedef MultiDrawElements<GLuint, GL_UNSIGNED_INT, ArrayUInt> MultiDrawElementsUInt;
  //------------------------------------------------------------------------------
  /** A MultiDrawElements using indices of type \p GLushort. */
  typedef MultiDrawElements<GLushort, GL_UNSIGNED_SHORT, ArrayUShort> MultiDrawElementsUShort;
  //------------------------------------------------------------------------------
  /** A MultiDrawElements using indices of type \p GLubyte. */
  typedef MultiDrawElements<GLubyte, GL_UNSIGNED_BYTE, ArrayUByte> MultiDrawElementsUByte;
  //------------------------------------------------------------------------------
}

#endif
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"

#include "TestModule.h"
#include "EC_Dummy.h"
#include <Poco/ClassLibrary.h>
#include "EntityInterface.h"

namespace Test
{
    TestModule::TestModule() : ModuleInterfaceImpl(type_static_)
    {
    }

    TestModule::~TestModule()
    {
    }

    // virtual
    void TestModule::Load()
    {
        using namespace Test;
        DECLARE_MODULE_EC(EC_Dummy);

        LogInfo("Module " + Name() + " loaded.");
    }

    // virtual
    void TestModule::Unload()
    {
        LogInfo("Module " + Name() + " unloaded.");
    }

    // virtual
    void TestModule::Initialize()
    {
        framework_->GetServiceManager()->RegisterService(Foundation::Service::ST_Test, &test_service_);
        assert (framework_->GetServiceManager()->IsRegistered(Foundation::Service::ST_Test) &&
            "Failed to register test service");

        framework_->GetEventManager()->RegisterEventCategory("Test");

        LogInfo("Module " + Name() + " initialized.");
    }

    // virtual
    void TestModule::Uninitialize()
    {
        framework_->GetServiceManager()->UnregisterService(&test_service_);
        assert (framework_->GetServiceManager()->IsRegistered(Foundation::Service::ST_Test) == false &&
            "Failed to unregister test service");

        LogInfo("Module " + Name() + " uninitialized.");
    }

    // virtual
    void TestModule::Update(Core::f64 frametime)
    {
        LogInfo("");

        assert (VersionMajor() == GetFramework()->GetDefaultConfig().GetSetting<std::string>(Foundation::Framework::ConfigurationGroup(), "version_major"));
        assert (VersionMinor() == GetFramework()->GetDefaultConfig().GetSetting<std::string>(Foundation::Framework::ConfigurationGroup(), "version_minor"));

        // create new entity
        LogInfo("Constructing entity with component: " + Test::EC_Dummy::NameStatic() + ".");

        Foundation::SceneManagerServiceInterface *sceneManager =
            framework_->GetService<Foundation::SceneManagerServiceInterface>(Foundation::Service::ST_SceneManager);
        assert(sceneManager != NULL && "Failed to get SceneManager service");

        assert(sceneManager->HasScene("test_scene") == false && "Scene test_scene scene already exists!");
        Foundation::ScenePtr scene = sceneManager->CreateScene("test_scene");
        assert(scene.get() && "Failed to create scene" );
        assert(sceneManager->HasScene("test_scene") && "Failed to create scene");

        Foundation::EntityPtr entity = scene->CreateEntity(0);
        assert (entity.get() != 0 && "Failed to create entity.");
        assert (scene->HasEntity(entity->GetId()) && "Failed to add entity to scene properly!");

        Foundation::ComponentPtr component = framework_->GetComponentManager()->CreateComponent(Test::EC_Dummy::NameStatic());
        assert (component.get() != 0 && "Failed to create dummy component.");

        entity->AddEntityComponent(component);
        component = entity->GetComponent(component->Name());
        assert (component.get() != 0 && "Failed to get dummy component from entity.");

        int num_test_components = 0;
        for (Foundation::ComponentManager::const_iterator it =
             framework_->GetComponentManager()->Begin(Test::EC_Dummy::NameStatic()) ;
             it != framework_->GetComponentManager()->End(Test::EC_Dummy::NameStatic()) ;
             ++it)
        {
            assert (it->lock()->Name() == Test::EC_Dummy::NameStatic() && "Component iterator returned wrong component type.");
            num_test_components++;
        }
        assert (num_test_components == 1 && "Component iterator failed.");

        Foundation::ScenePtr cloned_scene = scene->Clone("Test clone scene");
        assert (sceneManager->HasScene("Test clone scene"));
        assert (cloned_scene->HasEntity(entity->GetId()) && "Failed to clone a scene");

        Foundation::EntityPtr cloned_entity = entity->Clone("Test clone scene");
        component = cloned_entity->GetComponent(component->Name());
        assert (component.get() != 0 && "Failed to clone an entity.");

        Foundation::EntityPtr cloned_entity2 = cloned_scene->GetEntity(cloned_entity->GetId());
        Foundation::EntityPtr entity2 = cloned_scene->CreateEntity(0);
        assert (*cloned_entity2.get() == *cloned_entity.get() && "EntityInterface operator== failed");
        assert (*entity.get() != *entity2.get() && "EntityInterface operator!= failed");
        assert (*cloned_entity.get() < *entity2.get() && "EntityInterface operator< failed");

        Foundation::ScenePtr scene2 = sceneManager->GetScene("test_scene");
        assert(*scene.get() == *scene2.get() && "SceneInterface operator== failed");
        assert(*scene.get() != *cloned_scene.get() && "SceneInterface operator!= failed");
        assert(*cloned_scene.get() < *scene.get() && "SceneInterface operator< failed");

        Foundation::SceneManager::iterator it = sceneManager->Begin();
        Foundation::SceneManager::iterator it_copy = it;
        int test_scenes = 0;
        for ( ; it_copy != sceneManager->End() ; ++it_copy)
        {
            if ((*it_copy)->Name() == "test_scene")
                test_scenes++;

            if ((*it_copy)->Name() == "Test clone scene")
                test_scenes++;
        }
        assert (test_scenes == 2 && "Scene iterator could not find all the scenes!");

        const Foundation::SceneManagerServiceInterface *const_sceneManager = const_cast<const Foundation::SceneManagerServiceInterface*>(sceneManager);
        Foundation::SceneManager::const_iterator c_it = const_sceneManager->Begin();
        Foundation::SceneManager::const_iterator c_it_copy = c_it;
        test_scenes = 0;
        for ( ; c_it_copy != const_sceneManager->End() ; ++c_it_copy)
        {
            if ((*c_it_copy)->Name() == "test_scene")
                test_scenes++;

            if ((*c_it_copy)->Name() == "Test clone scene")
                test_scenes++;
        }
        assert (test_scenes == 2 && "Const scene iterator could not find all the scenes!");

        Foundation::TestServiceInterface *test_service = framework_->GetServiceManager()->GetService<Foundation::TestServiceInterface>(Foundation::Service::ST_Test);
        assert (test_service != NULL);
        assert (test_service->Test());

        TestEvent test_event;
        test_event.test_value_ = 12345;
        framework_->GetEventManager()->SendEvent(framework_->GetEventManager()->QueryEventCategory("Test"), 0, NULL);
        framework_->GetEventManager()->SendEvent(framework_->GetEventManager()->QueryEventCategory("Test"), 1, &test_event);

        framework_->Exit();
        assert (framework_->IsExiting());

        LogInfo("");
    }
}

<commit_msg>Test for removing an entity component from entity.<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"

#include "TestModule.h"
#include "EC_Dummy.h"
#include <Poco/ClassLibrary.h>
#include "EntityInterface.h"

namespace Test
{
    TestModule::TestModule() : ModuleInterfaceImpl(type_static_)
    {
    }

    TestModule::~TestModule()
    {
    }

    // virtual
    void TestModule::Load()
    {
        using namespace Test;
        DECLARE_MODULE_EC(EC_Dummy);

        LogInfo("Module " + Name() + " loaded.");
    }

    // virtual
    void TestModule::Unload()
    {
        LogInfo("Module " + Name() + " unloaded.");
    }

    // virtual
    void TestModule::Initialize()
    {
        framework_->GetServiceManager()->RegisterService(Foundation::Service::ST_Test, &test_service_);
        assert (framework_->GetServiceManager()->IsRegistered(Foundation::Service::ST_Test) &&
            "Failed to register test service");

        framework_->GetEventManager()->RegisterEventCategory("Test");

        LogInfo("Module " + Name() + " initialized.");
    }

    // virtual
    void TestModule::Uninitialize()
    {
        framework_->GetServiceManager()->UnregisterService(&test_service_);
        assert (framework_->GetServiceManager()->IsRegistered(Foundation::Service::ST_Test) == false &&
            "Failed to unregister test service");

        LogInfo("Module " + Name() + " uninitialized.");
    }

    // virtual
    void TestModule::Update(Core::f64 frametime)
    {
        LogInfo("");

        assert (VersionMajor() == GetFramework()->GetDefaultConfig().GetSetting<std::string>(Foundation::Framework::ConfigurationGroup(), "version_major"));
        assert (VersionMinor() == GetFramework()->GetDefaultConfig().GetSetting<std::string>(Foundation::Framework::ConfigurationGroup(), "version_minor"));

        // create new entity
        LogInfo("Constructing entity with component: " + Test::EC_Dummy::NameStatic() + ".");

        Foundation::SceneManagerServiceInterface *sceneManager =
            framework_->GetService<Foundation::SceneManagerServiceInterface>(Foundation::Service::ST_SceneManager);
        assert(sceneManager != NULL && "Failed to get SceneManager service");

        assert(sceneManager->HasScene("test_scene") == false && "Scene test_scene scene already exists!");
        Foundation::ScenePtr scene = sceneManager->CreateScene("test_scene");
        assert(scene.get() && "Failed to create scene" );
        assert(sceneManager->HasScene("test_scene") && "Failed to create scene");

        Foundation::EntityPtr entity = scene->CreateEntity(0);
        assert (entity.get() != 0 && "Failed to create entity.");
        assert (scene->HasEntity(entity->GetId()) && "Failed to add entity to scene properly!");

        Foundation::ComponentPtr component = framework_->GetComponentManager()->CreateComponent(Test::EC_Dummy::NameStatic());
        assert (component.get() != 0 && "Failed to create dummy component.");

        entity->AddEntityComponent(component);
        component = entity->GetComponent(component->Name());
        assert (component.get() != 0 && "Failed to get dummy component from entity.");

        Foundation::ComponentPtr component_second = framework_->GetComponentManager()->CreateComponent(Test::EC_Dummy::NameStatic());
        entity->AddEntityComponent(component_second);
        component = entity->GetComponent(component_second->Name());
        assert (component.get() != 0 && "Failed to get dummy component from entity.");
        entity->RemoveEntityComponent(component_second);
        component_second.reset();

        int num_test_components = 0;
        for (Foundation::ComponentManager::const_iterator it =
             framework_->GetComponentManager()->Begin(Test::EC_Dummy::NameStatic()) ;
             it != framework_->GetComponentManager()->End(Test::EC_Dummy::NameStatic()) ;
             ++it)
        {
            assert (it->lock()->Name() == Test::EC_Dummy::NameStatic() && "Component iterator returned wrong component type.");
            num_test_components++;
        }
        assert (num_test_components == 1 && "Component iterator failed.");

        Foundation::ScenePtr cloned_scene = scene->Clone("Test clone scene");
        assert (sceneManager->HasScene("Test clone scene"));
        assert (cloned_scene->HasEntity(entity->GetId()) && "Failed to clone a scene");

        Foundation::EntityPtr cloned_entity = entity->Clone("Test clone scene");
        component = cloned_entity->GetComponent(component->Name());
        assert (component.get() != 0 && "Failed to clone an entity.");

        Foundation::EntityPtr cloned_entity2 = cloned_scene->GetEntity(cloned_entity->GetId());
        Foundation::EntityPtr entity2 = cloned_scene->CreateEntity(0);
        assert (*cloned_entity2.get() == *cloned_entity.get() && "EntityInterface operator== failed");
        assert (*entity.get() != *entity2.get() && "EntityInterface operator!= failed");
        assert (*cloned_entity.get() < *entity2.get() && "EntityInterface operator< failed");

        Foundation::ScenePtr scene2 = sceneManager->GetScene("test_scene");
        assert(*scene.get() == *scene2.get() && "SceneInterface operator== failed");
        assert(*scene.get() != *cloned_scene.get() && "SceneInterface operator!= failed");
        assert(*cloned_scene.get() < *scene.get() && "SceneInterface operator< failed");

        Foundation::SceneManager::iterator it = sceneManager->Begin();
        Foundation::SceneManager::iterator it_copy = it;
        int test_scenes = 0;
        for ( ; it_copy != sceneManager->End() ; ++it_copy)
        {
            if ((*it_copy)->Name() == "test_scene")
                test_scenes++;

            if ((*it_copy)->Name() == "Test clone scene")
                test_scenes++;
        }
        assert (test_scenes == 2 && "Scene iterator could not find all the scenes!");

        const Foundation::SceneManagerServiceInterface *const_sceneManager = const_cast<const Foundation::SceneManagerServiceInterface*>(sceneManager);
        Foundation::SceneManager::const_iterator c_it = const_sceneManager->Begin();
        Foundation::SceneManager::const_iterator c_it_copy = c_it;
        test_scenes = 0;
        for ( ; c_it_copy != const_sceneManager->End() ; ++c_it_copy)
        {
            if ((*c_it_copy)->Name() == "test_scene")
                test_scenes++;

            if ((*c_it_copy)->Name() == "Test clone scene")
                test_scenes++;
        }
        assert (test_scenes == 2 && "Const scene iterator could not find all the scenes!");

        Foundation::TestServiceInterface *test_service = framework_->GetServiceManager()->GetService<Foundation::TestServiceInterface>(Foundation::Service::ST_Test);
        assert (test_service != NULL);
        assert (test_service->Test());

        TestEvent test_event;
        test_event.test_value_ = 12345;
        framework_->GetEventManager()->SendEvent(framework_->GetEventManager()->QueryEventCategory("Test"), 0, NULL);
        framework_->GetEventManager()->SendEvent(framework_->GetEventManager()->QueryEventCategory("Test"), 1, &test_event);

        framework_->Exit();
        assert (framework_->IsExiting());

        LogInfo("");
    }
}

<|endoftext|>


<commit_before>// Filename: geomSprite.cxx
// Created by:  charles (13Jul00)
//
////////////////////////////////////////////////////////////////////

#include <datagram.h>
#include <datagramIterator.h>
#include <bamReader.h>
#include <bamWriter.h>
#include <ioPtaDatagramShort.h>
#include <ioPtaDatagramInt.h>
#include <ioPtaDatagramFloat.h>
#include <ioPtaDatagramLinMath.h>
#include <graphicsStateGuardianBase.h>

#include "geomSprite.h"

TypeHandle GeomSprite::_type_handle;

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite
//       Access: public
//  Description: constructor
////////////////////////////////////////////////////////////////////
GeomSprite::
GeomSprite(Texture *tex, bool alpha_disable) :
  _texture(tex), _alpha_disable(alpha_disable) {
  _x_texel_ratio.clear();
  _y_texel_ratio.clear();

  _theta_bind_type = G_OFF;
  // note that the other bind types are intentionally left
  // uninitialized; the arrays themselves can not be set without a
  // bind type.
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::make_copy
//       Access: Public, Virtual
//  Description: Returns a newly-allocated Geom that is a shallow copy
//               of this one.  It will be a different Geom pointer,
//               but its internal data may or may not be shared with
//               that of the original Geom.
////////////////////////////////////////////////////////////////////
Geom *GeomSprite::
make_copy() const {
  return new GeomSprite(*this);
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::print_draw_immediate
//       Access:
//  Description:
////////////////////////////////////////////////////////////////////
void GeomSprite::
print_draw_immediate(void) const {
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::draw_immediate
//       Access:
//  Description:
////////////////////////////////////////////////////////////////////
void GeomSprite::
draw_immediate(GraphicsStateGuardianBase *gsg) const {
  gsg->draw_sprite(this);
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::write_datagram
//       Access: Public
//  Description: Function to write the important information in
//               the particular object to a Datagram
////////////////////////////////////////////////////////////////////
void GeomSprite::
write_datagram(BamWriter *manager, Datagram &me) {
  Geom::write_datagram(manager, me);
  WRITE_PTA(manager, me, IPD_float::write_datagram, _x_texel_ratio);
  WRITE_PTA(manager, me, IPD_float::write_datagram, _y_texel_ratio);
  me.add_uint8(_x_bind_type);
  me.add_uint8(_y_bind_type);
  me.add_uint8(_alpha_disable);
  manager->write_pointer(me, _texture);
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::make_GeomSprite
//       Access: Protected
//  Description: Factory method to generate a GeomSprite object
////////////////////////////////////////////////////////////////////
TypedWriteable* GeomSprite::
make_GeomSprite(const FactoryParams &params) {
  GeomSprite *me = new GeomSprite;
  BamReader *manager;
  Datagram packet;

  parse_params(params, manager, packet);
  DatagramIterator scan(packet);

  me->fillin(scan, manager);
  me->make_dirty();
  me->config();
  return me;
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::fillin
//       Access: Protected
//  Description: Function that reads out of the datagram (or asks
//               manager to read) all of the data that is needed to
//               re-create this object and stores it in the appropiate
//               place
////////////////////////////////////////////////////////////////////
void GeomSprite::
fillin(DatagramIterator& scan, BamReader* manager) {
  Geom::fillin(scan, manager);
  READ_PTA(manager, scan, IPD_float::read_datagram, _x_texel_ratio);
  READ_PTA(manager, scan, IPD_float::read_datagram, _y_texel_ratio);
  _x_bind_type = (GeomBindType) scan.get_uint8();
  _y_bind_type = (GeomBindType) scan.get_uint8();
  _alpha_disable = (bool) scan.get_uint8();
  manager->read_pointer(scan, this);
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::register_with_factory
//       Access: Public, Static
//  Description: Factory method to generate a GeomSprite object
////////////////////////////////////////////////////////////////////
void GeomSprite::
register_with_read_factory(void) {
  BamReader::get_factory()->register_factory(get_class_type(), make_GeomSprite);
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::complete_pointers
//       Access: Public, Static
//  Description:
////////////////////////////////////////////////////////////////////
int GeomSprite::
complete_pointers(vector_typedWriteable &plist, BamReader *manager) {
  int index = Geom::complete_pointers(plist, manager);
  _texture = DCAST(Texture, plist[index]);

  return index + 1;
}
<commit_msg>get rid of cl warning<commit_after>// Filename: geomSprite.cxx
// Created by:  charles (13Jul00)
//
////////////////////////////////////////////////////////////////////

#include <datagram.h>
#include <datagramIterator.h>
#include <bamReader.h>
#include <bamWriter.h>
#include <ioPtaDatagramShort.h>
#include <ioPtaDatagramInt.h>
#include <ioPtaDatagramFloat.h>
#include <ioPtaDatagramLinMath.h>
#include <graphicsStateGuardianBase.h>

#include "geomSprite.h"

TypeHandle GeomSprite::_type_handle;

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite
//       Access: public
//  Description: constructor
////////////////////////////////////////////////////////////////////
GeomSprite::
GeomSprite(Texture *tex, bool alpha_disable) :
  _texture(tex), _alpha_disable(alpha_disable) {
  _x_texel_ratio.clear();
  _y_texel_ratio.clear();

  _theta_bind_type = G_OFF;
  // note that the other bind types are intentionally left
  // uninitialized; the arrays themselves can not be set without a
  // bind type.
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::make_copy
//       Access: Public, Virtual
//  Description: Returns a newly-allocated Geom that is a shallow copy
//               of this one.  It will be a different Geom pointer,
//               but its internal data may or may not be shared with
//               that of the original Geom.
////////////////////////////////////////////////////////////////////
Geom *GeomSprite::
make_copy() const {
  return new GeomSprite(*this);
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::print_draw_immediate
//       Access:
//  Description:
////////////////////////////////////////////////////////////////////
void GeomSprite::
print_draw_immediate(void) const {
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::draw_immediate
//       Access:
//  Description:
////////////////////////////////////////////////////////////////////
void GeomSprite::
draw_immediate(GraphicsStateGuardianBase *gsg) const {
  gsg->draw_sprite(this);
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::write_datagram
//       Access: Public
//  Description: Function to write the important information in
//               the particular object to a Datagram
////////////////////////////////////////////////////////////////////
void GeomSprite::
write_datagram(BamWriter *manager, Datagram &me) {
  Geom::write_datagram(manager, me);
  WRITE_PTA(manager, me, IPD_float::write_datagram, _x_texel_ratio);
  WRITE_PTA(manager, me, IPD_float::write_datagram, _y_texel_ratio);
  me.add_uint8(_x_bind_type);
  me.add_uint8(_y_bind_type);
  me.add_uint8(_alpha_disable);
  manager->write_pointer(me, _texture);
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::make_GeomSprite
//       Access: Protected
//  Description: Factory method to generate a GeomSprite object
////////////////////////////////////////////////////////////////////
TypedWriteable* GeomSprite::
make_GeomSprite(const FactoryParams &params) {
  GeomSprite *me = new GeomSprite;
  BamReader *manager;
  Datagram packet;

  parse_params(params, manager, packet);
  DatagramIterator scan(packet);

  me->fillin(scan, manager);
  me->make_dirty();
  me->config();
  return me;
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::fillin
//       Access: Protected
//  Description: Function that reads out of the datagram (or asks
//               manager to read) all of the data that is needed to
//               re-create this object and stores it in the appropiate
//               place
////////////////////////////////////////////////////////////////////
void GeomSprite::
fillin(DatagramIterator& scan, BamReader* manager) {
  Geom::fillin(scan, manager);
  READ_PTA(manager, scan, IPD_float::read_datagram, _x_texel_ratio);
  READ_PTA(manager, scan, IPD_float::read_datagram, _y_texel_ratio);
  _x_bind_type = (GeomBindType) scan.get_uint8();
  _y_bind_type = (GeomBindType) scan.get_uint8();
  _alpha_disable = (scan.get_uint8() !=0);
  manager->read_pointer(scan, this);
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::register_with_factory
//       Access: Public, Static
//  Description: Factory method to generate a GeomSprite object
////////////////////////////////////////////////////////////////////
void GeomSprite::
register_with_read_factory(void) {
  BamReader::get_factory()->register_factory(get_class_type(), make_GeomSprite);
}

////////////////////////////////////////////////////////////////////
//     Function: GeomSprite::complete_pointers
//       Access: Public, Static
//  Description:
////////////////////////////////////////////////////////////////////
int GeomSprite::
complete_pointers(vector_typedWriteable &plist, BamReader *manager) {
  int index = Geom::complete_pointers(plist, manager);
  _texture = DCAST(Texture, plist[index]);

  return index + 1;
}
<|endoftext|>


<commit_before>#include <cstdint>
#include <iostream>
#include <numeric> //std::iota
#include <stdexcept>

#include <adios2.h>

#include <gtest/gtest.h>

class ADIOSBZip2Wrapper : public ::testing::Test
{
public:
    ADIOSBZip2Wrapper() : adios(true), io(adios.DeclareIO("TestADIOSBZip2")) {}

protected:
    adios2::ADIOS adios;
    adios2::IO &io;
};

TEST_F(ADIOSBZip2Wrapper, UInt100)
{
    /** Application variable uints from 0 to 1000 */
    std::vector<unsigned int> myUInts(100);
    std::iota(myUInts.begin(), myUInts.end(), 0.f);
    const std::size_t Nx = myUInts.size();
    const std::size_t inputBytes = Nx * sizeof(unsigned int);

    // Define ADIOS variable
    auto &var_UInt = io.DefineVariable<unsigned int>("myUInts", {}, {}, {Nx},
                                                     adios2::ConstantDims);

    // Verify the return type is as expected
    ::testing::StaticAssertTypeEq<decltype(var_UInt),
                                  adios2::Variable<unsigned int> &>();

    // Define bzip2 transform
    adios2::Operator &adiosBZip2 =
        adios.DefineOperator("BZip2Compressor", "BZip2");

    const unsigned int bzip2ID =
        var_UInt.AddTransform(adiosBZip2, {{"BlockSize100K", "2"}});

    const std::size_t estimatedSize =
        adiosBZip2.BufferMaxSize(Nx * var_UInt.m_ElementSize);
    std::vector<char> compressedBuffer(estimatedSize);
    size_t compressedSize = adiosBZip2.Compress(
        myUInts.data(), var_UInt.m_Count, var_UInt.m_ElementSize,
        var_UInt.m_Type, compressedBuffer.data(),
        var_UInt.m_OperatorsInfo[bzip2ID].Parameters);

    EXPECT_LE(compressedSize, estimatedSize);

    compressedBuffer.resize(compressedSize);

    // Allocate original data size
    std::vector<unsigned int> decompressedBuffer(Nx);
    size_t decompressedSize = adiosBZip2.Decompress(
        compressedBuffer.data(), compressedSize, decompressedBuffer.data(),
        decompressedBuffer.size() * sizeof(unsigned int));
    ASSERT_EQ(decompressedSize, Nx);

    // testing data recovery
    for (size_t i = 0; i < Nx; ++i)
    {
        ASSERT_EQ(decompressedBuffer[i], myUInts[i]);
    }
}

TEST_F(ADIOSBZip2Wrapper, WrongParameterValue)
{
    /** Application variable uints from 0 to 1000 */
    std::vector<unsigned int> myUInts(100);
    std::iota(myUInts.begin(), myUInts.end(), 0.f);
    const std::size_t Nx = myUInts.size();
    const std::size_t inputBytes = Nx * sizeof(unsigned int);

    // Define ADIOS variable
    auto &var_UInt = io.DefineVariable<unsigned int>("myUInts", {}, {}, {Nx},
                                                     adios2::ConstantDims);

    // Verify the return type is as expected
    ::testing::StaticAssertTypeEq<decltype(var_UInt),
                                  adios2::Variable<unsigned int> &>();

    // Define bzip2 transform
    adios2::Operator &adiosBZip2 =
        adios.DefineOperator("BZip2Compressor", "BZip2");

    const unsigned int bzip2ID =
        var_UInt.AddTransform(adiosBZip2, {{"BlockSize100K", "10"}});

    const std::size_t estimatedSize =
        adiosBZip2.BufferMaxSize(Nx * var_UInt.m_ElementSize);
    std::vector<char> compressedBuffer(estimatedSize);

    EXPECT_THROW(size_t compressedSize = adiosBZip2.Compress(
                     myUInts.data(), var_UInt.m_Count, var_UInt.m_ElementSize,
                     var_UInt.m_Type, compressedBuffer.data(),
                     var_UInt.m_OperatorsInfo[bzip2ID].Parameters),
                 std::invalid_argument);
}

TEST_F(ADIOSBZip2Wrapper, WrongBZip2Name)
{
    /** Application variable uints from 0 to 1000 */
    std::vector<unsigned int> myUInts(100);
    std::iota(myUInts.begin(), myUInts.end(), 0.f);
    const std::size_t Nx = myUInts.size();
    const std::size_t inputBytes = Nx * sizeof(unsigned int);

    // Define ADIOS variable
    auto &var_UInt = io.DefineVariable<unsigned int>("myUInts", {}, {}, {Nx},
                                                     adios2::ConstantDims);

    // Verify the return type is as expected
    ::testing::StaticAssertTypeEq<decltype(var_UInt),
                                  adios2::Variable<unsigned int> &>();

    // Check bzip2 lower case and camel case
    EXPECT_NO_THROW(adios2::Operator &adiosBZip2 =
                        adios.DefineOperator("BZip2Compressor1", "bzip2"));
    EXPECT_NO_THROW(adios2::Operator &adiosBZip2 =
                        adios.DefineOperator("BZip2Compressor2", "BZip2"));
    EXPECT_THROW(adios2::Operator &adiosBZip2 =
                     adios.DefineOperator("BZip2Compressor3", "bzip"),
                 std::invalid_argument);
    EXPECT_THROW(adios2::Operator &adiosBZip2 =
                     adios.DefineOperator("BZip2Compressor4", "BZIP2"),
                 std::invalid_argument);
}
<commit_msg>Added a check for BZip2 decompression size<commit_after>#include <cstdint>
#include <iostream>
#include <numeric> //std::iota
#include <stdexcept>

#include <adios2.h>

#include <gtest/gtest.h>

class ADIOSBZip2Wrapper : public ::testing::Test
{
public:
    ADIOSBZip2Wrapper() : adios(true), io(adios.DeclareIO("TestADIOSBZip2")) {}

protected:
    adios2::ADIOS adios;
    adios2::IO &io;
};

TEST_F(ADIOSBZip2Wrapper, UInt100)
{
    /** Application variable uints from 0 to 1000 */
    std::vector<uint32_t> myUInts(100);
    std::iota(myUInts.begin(), myUInts.end(), 0.f);
    const std::size_t Nx = myUInts.size();
    const std::size_t inputBytes = Nx * sizeof(uint32_t);

    // Define ADIOS variable
    auto &var_UInt = io.DefineVariable<uint32_t>("myUInts", {}, {}, {Nx},
                                                 adios2::ConstantDims);

    // Verify the return type is as expected
    ::testing::StaticAssertTypeEq<decltype(var_UInt),
                                  adios2::Variable<uint32_t> &>();

    // Define bzip2 transform
    adios2::Operator &adiosBZip2 =
        adios.DefineOperator("BZip2Compressor", "BZip2");

    const unsigned int bzip2ID =
        var_UInt.AddTransform(adiosBZip2, {{"BlockSize100K", "2"}});

    const std::size_t estimatedSize =
        adiosBZip2.BufferMaxSize(Nx * var_UInt.m_ElementSize);
    std::vector<char> compressedBuffer(estimatedSize);
    size_t compressedSize = adiosBZip2.Compress(
        myUInts.data(), var_UInt.m_Count, var_UInt.m_ElementSize,
        var_UInt.m_Type, compressedBuffer.data(),
        var_UInt.m_OperatorsInfo[bzip2ID].Parameters);

    EXPECT_LE(compressedSize, estimatedSize);

    compressedBuffer.resize(compressedSize);

    // Allocate original data size
    std::vector<uint32_t> decompressedBuffer(Nx);
    size_t decompressedSize = adiosBZip2.Decompress(
        compressedBuffer.data(), compressedSize, decompressedBuffer.data(),
        decompressedBuffer.size() * sizeof(uint32_t));
    ASSERT_EQ(decompressedSize, inputBytes);

    // testing data recovery
    for (size_t i = 0; i < Nx; ++i)
    {
        ASSERT_EQ(decompressedBuffer[i], myUInts[i]);
    }
}

TEST_F(ADIOSBZip2Wrapper, WrongParameterValue)
{
    /** Application variable uints from 0 to 1000 */
    std::vector<unsigned int> myUInts(100);
    std::iota(myUInts.begin(), myUInts.end(), 0.f);
    const std::size_t Nx = myUInts.size();
    const std::size_t inputBytes = Nx * sizeof(unsigned int);

    // Define ADIOS variable
    auto &var_UInt = io.DefineVariable<unsigned int>("myUInts", {}, {}, {Nx},
                                                     adios2::ConstantDims);

    // Verify the return type is as expected
    ::testing::StaticAssertTypeEq<decltype(var_UInt),
                                  adios2::Variable<unsigned int> &>();

    // Define bzip2 transform
    adios2::Operator &adiosBZip2 =
        adios.DefineOperator("BZip2Compressor", "BZip2");

    const unsigned int bzip2ID =
        var_UInt.AddTransform(adiosBZip2, {{"BlockSize100K", "10"}});

    const std::size_t estimatedSize =
        adiosBZip2.BufferMaxSize(Nx * var_UInt.m_ElementSize);
    std::vector<char> compressedBuffer(estimatedSize);

    EXPECT_THROW(size_t compressedSize = adiosBZip2.Compress(
                     myUInts.data(), var_UInt.m_Count, var_UInt.m_ElementSize,
                     var_UInt.m_Type, compressedBuffer.data(),
                     var_UInt.m_OperatorsInfo[bzip2ID].Parameters),
                 std::invalid_argument);
}

TEST_F(ADIOSBZip2Wrapper, WrongBZip2Name)
{
    /** Application variable uints from 0 to 1000 */
    std::vector<unsigned int> myUInts(100);
    std::iota(myUInts.begin(), myUInts.end(), 0.f);
    const std::size_t Nx = myUInts.size();
    const std::size_t inputBytes = Nx * sizeof(unsigned int);

    // Define ADIOS variable
    auto &var_UInt = io.DefineVariable<unsigned int>("myUInts", {}, {}, {Nx},
                                                     adios2::ConstantDims);

    // Verify the return type is as expected
    ::testing::StaticAssertTypeEq<decltype(var_UInt),
                                  adios2::Variable<unsigned int> &>();

    // Check bzip2 lower case and camel case
    EXPECT_NO_THROW(adios2::Operator &adiosBZip2 =
                        adios.DefineOperator("BZip2Compressor1", "bzip2"));
    EXPECT_NO_THROW(adios2::Operator &adiosBZip2 =
                        adios.DefineOperator("BZip2Compressor2", "BZip2"));
    EXPECT_THROW(adios2::Operator &adiosBZip2 =
                     adios.DefineOperator("BZip2Compressor3", "bzip"),
                 std::invalid_argument);
    EXPECT_THROW(adios2::Operator &adiosBZip2 =
                     adios.DefineOperator("BZip2Compressor4", "BZIP2"),
                 std::invalid_argument);
}
<|endoftext|>


<commit_before>/*
 * libMaia - maiaXmlRpcClient.cpp
 * Copyright (c) 2007 Sebastian Wiedenroth <wiedi@frubar.net>
 *                and Karl Glatz
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "maiaXmlRpcClient.h"
#include "maiaFault.h"

MaiaXmlRpcClient::MaiaXmlRpcClient(QObject* parent) : QObject(parent),
	manager(this), request()
{

	request.setRawHeader("User-Agent", "libmaia 0.2");
	request.setHeader(QNetworkRequest::ContentTypeHeader, "text/xml");

	connect(&manager, SIGNAL(finished(QNetworkReply*)),
		this, SLOT(replyFinished(QNetworkReply*)));
}

MaiaXmlRpcClient::MaiaXmlRpcClient(QUrl url, QObject* parent) : QObject(parent),
	manager(this), request(url)
{
	request.setRawHeader("User-Agent", "libmaia 0.2");
	request.setHeader(QNetworkRequest::ContentTypeHeader, "text/xml");

	connect(&manager, SIGNAL(finished(QNetworkReply*)),
		this, SLOT(replyFinished(QNetworkReply*)));

	setUrl(url);
}

void MaiaXmlRpcClient::setUrl(QUrl url) {
	if(!url.isValid())
		return;

	request.setUrl(url);
}

QNetworkReply* MaiaXmlRpcClient::call(QString method, QList<QVariant> args,
							QObject* responseObject, const char* responseSlot,
							QObject* faultObject, const char* faultSlot) {
	MaiaObject* call = new MaiaObject(this);
	connect(call, SIGNAL(aresponse(QVariant &, QNetworkReply *)), responseObject, responseSlot);
	connect(call, SIGNAL(fault(int, const QString &, QNetworkReply *)), faultObject, faultSlot);

	QNetworkReply* reply = manager.post( request,
		call->prepareCall(method, args).toUtf8() );

	callmap[reply] = call;
	return reply;
}

void MaiaXmlRpcClient::replyFinished(QNetworkReply* reply) {
	QString response;
	if(!callmap.contains(reply))
		return;
	if(reply->error() != QNetworkReply::NoError) {
		MaiaFault fault(-32300, reply->errorString());
		response = fault.toString();
	} else {
		response = QString::fromUtf8(reply->readAll());
	}

	// parseResponse deletes the MaiaObject
	callmap[reply]->parseResponse(response, reply);
	delete reply;
	callmap.remove(reply);
}
<commit_msg>bugfix: use deleteLater() for the reply<commit_after>/*
 * libMaia - maiaXmlRpcClient.cpp
 * Copyright (c) 2007 Sebastian Wiedenroth <wiedi@frubar.net>
 *                and Karl Glatz
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "maiaXmlRpcClient.h"
#include "maiaFault.h"

MaiaXmlRpcClient::MaiaXmlRpcClient(QObject* parent) : QObject(parent),
	manager(this), request()
{

	request.setRawHeader("User-Agent", "libmaia 0.2");
	request.setHeader(QNetworkRequest::ContentTypeHeader, "text/xml");

	connect(&manager, SIGNAL(finished(QNetworkReply*)),
		this, SLOT(replyFinished(QNetworkReply*)));
}

MaiaXmlRpcClient::MaiaXmlRpcClient(QUrl url, QObject* parent) : QObject(parent),
	manager(this), request(url)
{
	request.setRawHeader("User-Agent", "libmaia 0.2");
	request.setHeader(QNetworkRequest::ContentTypeHeader, "text/xml");

	connect(&manager, SIGNAL(finished(QNetworkReply*)),
		this, SLOT(replyFinished(QNetworkReply*)));

	setUrl(url);
}

void MaiaXmlRpcClient::setUrl(QUrl url) {
	if(!url.isValid())
		return;

	request.setUrl(url);
}

QNetworkReply* MaiaXmlRpcClient::call(QString method, QList<QVariant> args,
							QObject* responseObject, const char* responseSlot,
							QObject* faultObject, const char* faultSlot) {
	MaiaObject* call = new MaiaObject(this);
	connect(call, SIGNAL(aresponse(QVariant &, QNetworkReply *)), responseObject, responseSlot);
	connect(call, SIGNAL(fault(int, const QString &, QNetworkReply *)), faultObject, faultSlot);

	QNetworkReply* reply = manager.post( request,
		call->prepareCall(method, args).toUtf8() );

	callmap[reply] = call;
	return reply;
}

void MaiaXmlRpcClient::replyFinished(QNetworkReply* reply) {
	QString response;
	if(!callmap.contains(reply))
		return;
	if(reply->error() != QNetworkReply::NoError) {
		MaiaFault fault(-32300, reply->errorString());
		response = fault.toString();
	} else {
		response = QString::fromUtf8(reply->readAll());
	}

	// parseResponse deletes the MaiaObject
	callmap[reply]->parseResponse(response, reply);
	reply->deleteLater();
	callmap.remove(reply);
}
<|endoftext|>