<commit_before>/*
 * Copyright 2016, Justin Carpentier, LAAS-CNRS
 *
 * This file is part of eigenpy.
 * eigenpy is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 * eigenpy is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.  You should
 * have received a copy of the GNU Lesser General Public License along
 * with eigenpy.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __eigenpy_memory_hpp__
#define __eigenpy_memory_hpp__

#include <boost/python.hpp>

/**
 * This section contains a convenience MACRO which allows an easy specialization of
 * Boost Python Object allocator for struct data types containing Eigen objects and requiring
 * strict alignment.
 *
 * This code was proposed as an stackoverflow answer:
 *     http://stackoverflow.com/questions/13177573/how-to-expose-aligned-class-with-boost-python/29694518
 * Leading to this page proposing the solution:
 *     http://fhtagn.net/prog/2015/04/16/quaternion_boost_python.html
 *
 */
#define EIGENPY_DEFINE_STRUCT_ALLOCATOR_SPECIALIZATION(...) \
namespace boost { namespace python { namespace objects { \
      template<> \
      struct instance< value_holder<__VA_ARGS__> > \
      { \
        typedef value_holder<__VA_ARGS__> Data; \
        PyObject_VAR_HEAD \
        PyObject* dict; \
        PyObject* weakrefs; \
        instance_holder* objects; \
         \
        typedef type_with_alignment< \
        ::boost::alignment_of<Data>::value  \
        >::type align_t; \
         \
        union \
        { \
          align_t align; \
          char bytes[sizeof(Data) + 16]; \
        } storage; \
      }; \
       \
      template<class Derived> \
      struct make_instance_impl<__VA_ARGS__, value_holder<__VA_ARGS__>, Derived> \
      { \
        typedef __VA_ARGS__ T; \
        typedef value_holder<__VA_ARGS__> Holder; \
        typedef objects::instance<Holder> instance_t; \
         \
        template <class Arg> \
        static inline PyObject* execute(Arg & x) \
        { \
          BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >)); \
           \
          PyTypeObject* type = Derived::get_class_object(x); \
           \
          if (type == 0) \
            return python::detail::none(); \
           \
          PyObject* raw_result = type->tp_alloc(type, objects::additional_instance_size<Holder>::value); \
          if (raw_result != 0) \
          { \
            python::detail::decref_guard protect(raw_result); \
            instance_t* instance = (instance_t*)(void*)raw_result; \
            Holder* holder = Derived::construct(&instance->storage, (PyObject*)instance, x); \
            holder->install(raw_result); \
             \
            Py_ssize_t holder_offset = reinterpret_cast<Py_ssize_t>(holder) \
            - reinterpret_cast<Py_ssize_t>(&instance->storage) \
            + offsetof(instance_t, storage); \
            Py_SIZE(instance) = holder_offset; \
             \
            protect.cancel(); \
          } \
          return raw_result; \
        } \
      }; \
       \
      template<> \
      struct make_instance<__VA_ARGS__, value_holder<__VA_ARGS__> > \
      : make_instance_impl<__VA_ARGS__, value_holder<__VA_ARGS__>, make_instance<__VA_ARGS__,value_holder<__VA_ARGS__> > > \
      { \
        template <class U> \
        static inline PyTypeObject* get_class_object(U &) \
        { \
          return converter::registered<__VA_ARGS__>::converters.get_class_object(); \
        } \
         \
        static inline value_holder<__VA_ARGS__>* construct(void* storage, PyObject* instance, reference_wrapper<__VA_ARGS__ const> x) \
        { \
          void* aligned_storage = reinterpret_cast<void*>((reinterpret_cast<size_t>(storage) & ~(size_t(15))) + 16); \
          value_holder<__VA_ARGS__>* new_holder = new (aligned_storage) value_holder<__VA_ARGS__>(instance, x); \
          return new_holder; \
        } \
      }; \
    }}}

#endif // __eigenpy_memory_hpp__
<commit_msg>[Memory] Remove useless warning<commit_after>/*
 * Copyright 2016, Justin Carpentier, LAAS-CNRS
 *
 * This file is part of eigenpy.
 * eigenpy is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 * eigenpy is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.  You should
 * have received a copy of the GNU Lesser General Public License along
 * with eigenpy.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __eigenpy_memory_hpp__
#define __eigenpy_memory_hpp__

#include <boost/python.hpp>

/**
 * This section contains a convenience MACRO which allows an easy specialization of
 * Boost Python Object allocator for struct data types containing Eigen objects and requiring
 * strict alignment.
 *
 * This code was proposed as an stackoverflow answer:
 *     http://stackoverflow.com/questions/13177573/how-to-expose-aligned-class-with-boost-python/29694518
 * Leading to this page proposing the solution:
 *     http://fhtagn.net/prog/2015/04/16/quaternion_boost_python.html
 *
 */
#define EIGENPY_DEFINE_STRUCT_ALLOCATOR_SPECIALIZATION(...) \
namespace boost { namespace python { namespace objects { \
      template<> \
      struct instance< value_holder<__VA_ARGS__> > \
      { \
        typedef value_holder<__VA_ARGS__> Data; \
        PyObject_VAR_HEAD \
        PyObject* dict; \
        PyObject* weakrefs; \
        instance_holder* objects; \
         \
        typedef type_with_alignment< \
        ::boost::alignment_of<Data>::value  \
        >::type align_t; \
         \
        union \
        { \
          align_t align; \
          char bytes[sizeof(Data) + 16]; \
        } storage; \
      }; \
       \
      template<class Derived> \
      struct make_instance_impl<__VA_ARGS__, value_holder<__VA_ARGS__>, Derived> \
      { \
        typedef __VA_ARGS__ T; \
        typedef value_holder<__VA_ARGS__> Holder; \
        typedef objects::instance<Holder> instance_t; \
         \
        template <class Arg> \
        static inline PyObject* execute(Arg & x) \
        { \
          BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >)); \
           \
          PyTypeObject* type = Derived::get_class_object(x); \
           \
          if (type == 0) \
            return python::detail::none(); \
           \
          PyObject* raw_result = type->tp_alloc(type, objects::additional_instance_size<Holder>::value); \
          if (raw_result != 0) \
          { \
            python::detail::decref_guard protect(raw_result); \
            instance_t* instance = (instance_t*)(void*)raw_result; \
            Holder* holder = Derived::construct(&instance->storage, (PyObject*)instance, x); \
            holder->install(raw_result); \
             \
            Py_ssize_t holder_offset = reinterpret_cast<Py_ssize_t>(holder) \
            - reinterpret_cast<Py_ssize_t>(&instance->storage) \
            + static_cast<Py_ssize_t>(offsetof(instance_t, storage)); \
            Py_SIZE(instance) = holder_offset; \
             \
            protect.cancel(); \
          } \
          return raw_result; \
        } \
      }; \
       \
      template<> \
      struct make_instance<__VA_ARGS__, value_holder<__VA_ARGS__> > \
      : make_instance_impl<__VA_ARGS__, value_holder<__VA_ARGS__>, make_instance<__VA_ARGS__,value_holder<__VA_ARGS__> > > \
      { \
        template <class U> \
        static inline PyTypeObject* get_class_object(U &) \
        { \
          return converter::registered<__VA_ARGS__>::converters.get_class_object(); \
        } \
         \
        static inline value_holder<__VA_ARGS__>* construct(void* storage, PyObject* instance, reference_wrapper<__VA_ARGS__ const> x) \
        { \
          void* aligned_storage = reinterpret_cast<void*>((reinterpret_cast<size_t>(storage) & ~(size_t(15))) + 16); \
          value_holder<__VA_ARGS__>* new_holder = new (aligned_storage) value_holder<__VA_ARGS__>(instance, x); \
          return new_holder; \
        } \
      }; \
    }}}

#endif // __eigenpy_memory_hpp__
<|endoftext|>


<commit_before>// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "lib/jxl/modular/transform/squeeze.h"

#include <stdlib.h>

#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/common.h"
#include "lib/jxl/modular/modular_image.h"
#include "lib/jxl/modular/transform/transform.h"

namespace jxl {

void InvHSqueeze(Image &input, int c, int rc, ThreadPool *pool) {
  const Channel &chin = input.channel[c];
  const Channel &chin_residual = input.channel[rc];
  // These must be valid since we ran MetaApply already.
  JXL_ASSERT(chin.w == DivCeil(chin.w + chin_residual.w, 2));
  JXL_ASSERT(chin.h == chin_residual.h);

  if (chin_residual.w == 0 || chin_residual.h == 0) {
    input.channel[c].hshift--;
    return;
  }

  Channel chout(chin.w + chin_residual.w, chin.h, chin.hshift - 1, chin.vshift);
  JXL_DEBUG_V(4,
              "Undoing horizontal squeeze of channel %i using residuals in "
              "channel %i (going from width %zu to %zu)",
              c, rc, chin.w, chout.w);
  RunOnPool(
      pool, 0, chin.h, ThreadPool::SkipInit(),
      [&](const int task, const int thread) {
        const size_t y = task;
        const pixel_type *JXL_RESTRICT p_residual = chin_residual.Row(y);
        const pixel_type *JXL_RESTRICT p_avg = chin.Row(y);
        pixel_type *JXL_RESTRICT p_out = chout.Row(y);

        // special case for x=0 so we don't have to check x>0
        pixel_type_w avg = p_avg[0];
        pixel_type_w next_avg = (1 < chin.w ? p_avg[1] : avg);
        pixel_type_w tendency = SmoothTendency(avg, avg, next_avg);
        pixel_type_w diff = p_residual[0] + tendency;
        pixel_type_w A =
            ((avg * 2) + diff + (diff > 0 ? -(diff & 1) : (diff & 1))) >> 1;
        pixel_type_w B = A - diff;
        p_out[0] = A;
        p_out[1] = B;

        for (size_t x = 1; x < chin_residual.w; x++) {
          pixel_type_w diff_minus_tendency = p_residual[x];
          pixel_type_w avg = p_avg[x];
          pixel_type_w next_avg = (x + 1 < chin.w ? p_avg[x + 1] : avg);
          pixel_type_w left = p_out[(x << 1) - 1];
          pixel_type_w tendency = SmoothTendency(left, avg, next_avg);
          pixel_type_w diff = diff_minus_tendency + tendency;
          pixel_type_w A =
              ((avg * 2) + diff + (diff > 0 ? -(diff & 1) : (diff & 1))) >> 1;
          p_out[x << 1] = A;
          pixel_type_w B = A - diff;
          p_out[(x << 1) + 1] = B;
        }
        if (chout.w & 1) p_out[chout.w - 1] = p_avg[chin.w - 1];
      },
      "InvHorizontalSqueeze");
  input.channel[c] = std::move(chout);
}

void InvVSqueeze(Image &input, int c, int rc, ThreadPool *pool) {
  const Channel &chin = input.channel[c];
  const Channel &chin_residual = input.channel[rc];
  // These must be valid since we ran MetaApply already.
  JXL_ASSERT(chin.h == DivCeil(chin.h + chin_residual.h, 2));
  JXL_ASSERT(chin.w == chin_residual.w);

  if (chin_residual.w == 0 || chin_residual.h == 0) {
    input.channel[c].vshift--;
    return;
  }

  // Note: chin.h >= chin_residual.h and at most 1 different.
  Channel chout(chin.w, chin.h + chin_residual.h, chin.hshift, chin.vshift - 1);
  JXL_DEBUG_V(
      4,
      "Undoing vertical squeeze of channel %i using residuals in channel "
      "%i (going from height %zu to %zu)",
      c, rc, chin.h, chout.h);

  intptr_t onerow_in = chin.plane.PixelsPerRow();
  intptr_t onerow_out = chout.plane.PixelsPerRow();
  constexpr int kColsPerThread = 64;
  RunOnPool(
      pool, 0, DivCeil(chin.w, kColsPerThread), ThreadPool::SkipInit(),
      [&](const int task, const int thread) {
        const size_t x0 = task * kColsPerThread;
        const size_t x1 = std::min((size_t)(task + 1) * kColsPerThread, chin.w);
        // We only iterate up to std::min(chin_residual.h, chin.h) which is
        // always chin_residual.h.
        for (size_t y = 0; y < chin_residual.h; y++) {
          const pixel_type *JXL_RESTRICT p_residual = chin_residual.Row(y);
          const pixel_type *JXL_RESTRICT p_avg = chin.Row(y);
          pixel_type *JXL_RESTRICT p_out = chout.Row(y << 1);
          for (size_t x = x0; x < x1; x++) {
            pixel_type_w diff_minus_tendency = p_residual[x];
            pixel_type_w avg = p_avg[x];

            pixel_type_w next_avg = avg;
            if (y + 1 < chin.h) next_avg = p_avg[x + onerow_in];
            pixel_type_w top =
                (y > 0 ? p_out[static_cast<ssize_t>(x) - onerow_out] : avg);
            pixel_type_w tendency = SmoothTendency(top, avg, next_avg);
            pixel_type_w diff = diff_minus_tendency + tendency;
            pixel_type_w out =
                ((avg * 2) + diff + (diff > 0 ? -(diff & 1) : (diff & 1))) >> 1;

            p_out[x] = out;
            // If the chin_residual.h == chin.h, the output has an even number
            // of rows so the next line is fine. Otherwise, this loop won't
            // write to the last output row which is handled separately.
            p_out[x + onerow_out] = p_out[x] - diff;
          }
        }
      },
      "InvVertSqueeze");

  if (chout.h & 1) {
    size_t y = chin.h - 1;
    const pixel_type *p_avg = chin.Row(y);
    pixel_type *p_out = chout.Row(y << 1);
    for (size_t x = 0; x < chin.w; x++) {
      p_out[x] = p_avg[x];
    }
  }
  input.channel[c] = std::move(chout);
}

void DefaultSqueezeParameters(std::vector<SqueezeParams> *parameters,
                              const Image &image) {
  int nb_channels = image.nb_channels;
  // maybe other transforms have been applied before, but let's assume the first
  // nb_channels channels still contain the 'main' data

  parameters->clear();
  size_t w = image.channel[image.nb_meta_channels].w;
  size_t h = image.channel[image.nb_meta_channels].h;
  JXL_DEBUG_V(7, "Default squeeze parameters for %zux%zu image: ", w, h);

  bool wide =
      (w >
       h);  // do horizontal first on wide images; vertical first on tall images

  if (nb_channels > 2 && image.channel[image.nb_meta_channels + 1].w == w &&
      image.channel[image.nb_meta_channels + 1].h == h) {
    // assume channels 1 and 2 are chroma, and can be squeezed first for 4:2:0
    // previews
    JXL_DEBUG_V(7, "(4:2:0 chroma), %zux%zu image", w, h);
    //        if (!wide) {
    //        parameters.push_back(0+2); // vertical chroma squeeze
    //        parameters.push_back(image.nb_meta_channels+1);
    //        parameters.push_back(image.nb_meta_channels+2);
    //        }
    SqueezeParams params;
    // horizontal chroma squeeze
    params.horizontal = true;
    params.in_place = false;
    params.begin_c = image.nb_meta_channels + 1;
    params.num_c = 2;
    parameters->push_back(params);
    params.horizontal = false;
    // vertical chroma squeeze
    parameters->push_back(params);
  }
  SqueezeParams params;
  params.begin_c = image.nb_meta_channels;
  params.num_c = nb_channels;
  params.in_place = true;

  if (!wide) {
    if (h > JXL_MAX_FIRST_PREVIEW_SIZE) {
      params.horizontal = false;
      parameters->push_back(params);
      h = (h + 1) / 2;
      JXL_DEBUG_V(7, "Vertical (%zux%zu), ", w, h);
    }
  }
  while (w > JXL_MAX_FIRST_PREVIEW_SIZE || h > JXL_MAX_FIRST_PREVIEW_SIZE) {
    if (w > JXL_MAX_FIRST_PREVIEW_SIZE) {
      params.horizontal = true;
      parameters->push_back(params);
      w = (w + 1) / 2;
      JXL_DEBUG_V(7, "Horizontal (%zux%zu), ", w, h);
    }
    if (h > JXL_MAX_FIRST_PREVIEW_SIZE) {
      params.horizontal = false;
      parameters->push_back(params);
      h = (h + 1) / 2;
      JXL_DEBUG_V(7, "Vertical (%zux%zu), ", w, h);
    }
  }
  JXL_DEBUG_V(7, "that's it");
}

Status CheckMetaSqueezeParams(const std::vector<SqueezeParams> &parameters,
                              int num_channels) {
  for (size_t i = 0; i < parameters.size(); i++) {
    int c1 = parameters[i].begin_c;
    int c2 = parameters[i].begin_c + parameters[i].num_c - 1;
    if (c1 < 0 || c1 > num_channels || c2 < 0 || c2 >= num_channels ||
        c2 < c1) {
      return JXL_FAILURE("Invalid channel range");
    }
  }
  return true;
}

Status MetaSqueeze(Image &image, std::vector<SqueezeParams> *parameters) {
  if (parameters->empty()) {
    DefaultSqueezeParameters(parameters, image);
  }
  JXL_RETURN_IF_ERROR(
      CheckMetaSqueezeParams(*parameters, image.channel.size()));

  for (size_t i = 0; i < parameters->size(); i++) {
    bool horizontal = (*parameters)[i].horizontal;
    bool in_place = (*parameters)[i].in_place;
    uint32_t beginc = (*parameters)[i].begin_c;
    uint32_t endc = (*parameters)[i].begin_c + (*parameters)[i].num_c - 1;

    uint32_t offset;
    if (in_place) {
      offset = endc + 1;
    } else {
      offset = image.channel.size();
    }
    for (uint32_t c = beginc; c <= endc; c++) {
      if (image.channel[c].hshift > 30 || image.channel[c].vshift > 30) {
        return JXL_FAILURE("Too many squeezes: shift > 30");
      }
      size_t w = image.channel[c].w;
      size_t h = image.channel[c].h;
      if (horizontal) {
        image.channel[c].w = (w + 1) / 2;
        image.channel[c].hshift++;
        w = w - (w + 1) / 2;
      } else {
        image.channel[c].h = (h + 1) / 2;
        image.channel[c].vshift++;
        h = h - (h + 1) / 2;
      }
      image.channel[c].shrink();
      Channel dummy(w, h);
      dummy.hshift = image.channel[c].hshift;
      dummy.vshift = image.channel[c].vshift;

      image.channel.insert(image.channel.begin() + offset + (c - beginc),
                           std::move(dummy));
    }
  }
  return true;
}

Status InvSqueeze(Image &input, std::vector<SqueezeParams> parameters,
                  ThreadPool *pool) {
  if (parameters.empty()) {
    DefaultSqueezeParameters(&parameters, input);
  }
  JXL_RETURN_IF_ERROR(CheckMetaSqueezeParams(parameters, input.channel.size()));

  for (int i = parameters.size() - 1; i >= 0; i--) {
    bool horizontal = parameters[i].horizontal;
    bool in_place = parameters[i].in_place;
    uint32_t beginc = parameters[i].begin_c;
    uint32_t endc = parameters[i].begin_c + parameters[i].num_c - 1;
    uint32_t offset;
    if (in_place) {
      offset = endc + 1;
    } else {
      offset = input.channel.size() + beginc - endc - 1;
    }
    for (uint32_t c = beginc; c <= endc; c++) {
      uint32_t rc = offset + c - beginc;
      if ((input.channel[c].w < input.channel[rc].w) ||
          (input.channel[c].h < input.channel[rc].h)) {
        return JXL_FAILURE("Corrupted squeeze transform");
      }
      if (horizontal) {
        InvHSqueeze(input, c, rc, pool);
      } else {
        InvVSqueeze(input, c, rc, pool);
      }
    }
    input.channel.erase(input.channel.begin() + offset,
                        input.channel.begin() + offset + (endc - beginc + 1));
  }
  return true;
}

}  // namespace jxl
<commit_msg>fix default squeeze params<commit_after>// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "lib/jxl/modular/transform/squeeze.h"

#include <stdlib.h>

#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/common.h"
#include "lib/jxl/modular/modular_image.h"
#include "lib/jxl/modular/transform/transform.h"

namespace jxl {

void InvHSqueeze(Image &input, int c, int rc, ThreadPool *pool) {
  const Channel &chin = input.channel[c];
  const Channel &chin_residual = input.channel[rc];
  // These must be valid since we ran MetaApply already.
  JXL_ASSERT(chin.w == DivCeil(chin.w + chin_residual.w, 2));
  JXL_ASSERT(chin.h == chin_residual.h);

  if (chin_residual.w == 0 || chin_residual.h == 0) {
    input.channel[c].hshift--;
    return;
  }

  Channel chout(chin.w + chin_residual.w, chin.h, chin.hshift - 1, chin.vshift);
  JXL_DEBUG_V(4,
              "Undoing horizontal squeeze of channel %i using residuals in "
              "channel %i (going from width %zu to %zu)",
              c, rc, chin.w, chout.w);
  RunOnPool(
      pool, 0, chin.h, ThreadPool::SkipInit(),
      [&](const int task, const int thread) {
        const size_t y = task;
        const pixel_type *JXL_RESTRICT p_residual = chin_residual.Row(y);
        const pixel_type *JXL_RESTRICT p_avg = chin.Row(y);
        pixel_type *JXL_RESTRICT p_out = chout.Row(y);

        // special case for x=0 so we don't have to check x>0
        pixel_type_w avg = p_avg[0];
        pixel_type_w next_avg = (1 < chin.w ? p_avg[1] : avg);
        pixel_type_w tendency = SmoothTendency(avg, avg, next_avg);
        pixel_type_w diff = p_residual[0] + tendency;
        pixel_type_w A =
            ((avg * 2) + diff + (diff > 0 ? -(diff & 1) : (diff & 1))) >> 1;
        pixel_type_w B = A - diff;
        p_out[0] = A;
        p_out[1] = B;

        for (size_t x = 1; x < chin_residual.w; x++) {
          pixel_type_w diff_minus_tendency = p_residual[x];
          pixel_type_w avg = p_avg[x];
          pixel_type_w next_avg = (x + 1 < chin.w ? p_avg[x + 1] : avg);
          pixel_type_w left = p_out[(x << 1) - 1];
          pixel_type_w tendency = SmoothTendency(left, avg, next_avg);
          pixel_type_w diff = diff_minus_tendency + tendency;
          pixel_type_w A =
              ((avg * 2) + diff + (diff > 0 ? -(diff & 1) : (diff & 1))) >> 1;
          p_out[x << 1] = A;
          pixel_type_w B = A - diff;
          p_out[(x << 1) + 1] = B;
        }
        if (chout.w & 1) p_out[chout.w - 1] = p_avg[chin.w - 1];
      },
      "InvHorizontalSqueeze");
  input.channel[c] = std::move(chout);
}

void InvVSqueeze(Image &input, int c, int rc, ThreadPool *pool) {
  const Channel &chin = input.channel[c];
  const Channel &chin_residual = input.channel[rc];
  // These must be valid since we ran MetaApply already.
  JXL_ASSERT(chin.h == DivCeil(chin.h + chin_residual.h, 2));
  JXL_ASSERT(chin.w == chin_residual.w);

  if (chin_residual.w == 0 || chin_residual.h == 0) {
    input.channel[c].vshift--;
    return;
  }

  // Note: chin.h >= chin_residual.h and at most 1 different.
  Channel chout(chin.w, chin.h + chin_residual.h, chin.hshift, chin.vshift - 1);
  JXL_DEBUG_V(
      4,
      "Undoing vertical squeeze of channel %i using residuals in channel "
      "%i (going from height %zu to %zu)",
      c, rc, chin.h, chout.h);

  intptr_t onerow_in = chin.plane.PixelsPerRow();
  intptr_t onerow_out = chout.plane.PixelsPerRow();
  constexpr int kColsPerThread = 64;
  RunOnPool(
      pool, 0, DivCeil(chin.w, kColsPerThread), ThreadPool::SkipInit(),
      [&](const int task, const int thread) {
        const size_t x0 = task * kColsPerThread;
        const size_t x1 = std::min((size_t)(task + 1) * kColsPerThread, chin.w);
        // We only iterate up to std::min(chin_residual.h, chin.h) which is
        // always chin_residual.h.
        for (size_t y = 0; y < chin_residual.h; y++) {
          const pixel_type *JXL_RESTRICT p_residual = chin_residual.Row(y);
          const pixel_type *JXL_RESTRICT p_avg = chin.Row(y);
          pixel_type *JXL_RESTRICT p_out = chout.Row(y << 1);
          for (size_t x = x0; x < x1; x++) {
            pixel_type_w diff_minus_tendency = p_residual[x];
            pixel_type_w avg = p_avg[x];

            pixel_type_w next_avg = avg;
            if (y + 1 < chin.h) next_avg = p_avg[x + onerow_in];
            pixel_type_w top =
                (y > 0 ? p_out[static_cast<ssize_t>(x) - onerow_out] : avg);
            pixel_type_w tendency = SmoothTendency(top, avg, next_avg);
            pixel_type_w diff = diff_minus_tendency + tendency;
            pixel_type_w out =
                ((avg * 2) + diff + (diff > 0 ? -(diff & 1) : (diff & 1))) >> 1;

            p_out[x] = out;
            // If the chin_residual.h == chin.h, the output has an even number
            // of rows so the next line is fine. Otherwise, this loop won't
            // write to the last output row which is handled separately.
            p_out[x + onerow_out] = p_out[x] - diff;
          }
        }
      },
      "InvVertSqueeze");

  if (chout.h & 1) {
    size_t y = chin.h - 1;
    const pixel_type *p_avg = chin.Row(y);
    pixel_type *p_out = chout.Row(y << 1);
    for (size_t x = 0; x < chin.w; x++) {
      p_out[x] = p_avg[x];
    }
  }
  input.channel[c] = std::move(chout);
}

void DefaultSqueezeParameters(std::vector<SqueezeParams> *parameters,
                              const Image &image) {
  int nb_channels = image.channel.size() - image.nb_meta_channels;

  parameters->clear();
  size_t w = image.channel[image.nb_meta_channels].w;
  size_t h = image.channel[image.nb_meta_channels].h;
  JXL_DEBUG_V(7, "Default squeeze parameters for %zux%zu image: ", w, h);

  bool wide =
      (w >
       h);  // do horizontal first on wide images; vertical first on tall images

  if (nb_channels > 2 && image.channel[image.nb_meta_channels + 1].w == w &&
      image.channel[image.nb_meta_channels + 1].h == h) {
    // assume channels 1 and 2 are chroma, and can be squeezed first for 4:2:0
    // previews
    JXL_DEBUG_V(7, "(4:2:0 chroma), %zux%zu image", w, h);
    //        if (!wide) {
    //        parameters.push_back(0+2); // vertical chroma squeeze
    //        parameters.push_back(image.nb_meta_channels+1);
    //        parameters.push_back(image.nb_meta_channels+2);
    //        }
    SqueezeParams params;
    // horizontal chroma squeeze
    params.horizontal = true;
    params.in_place = false;
    params.begin_c = image.nb_meta_channels + 1;
    params.num_c = 2;
    parameters->push_back(params);
    params.horizontal = false;
    // vertical chroma squeeze
    parameters->push_back(params);
  }
  SqueezeParams params;
  params.begin_c = image.nb_meta_channels;
  params.num_c = nb_channels;
  params.in_place = true;

  if (!wide) {
    if (h > JXL_MAX_FIRST_PREVIEW_SIZE) {
      params.horizontal = false;
      parameters->push_back(params);
      h = (h + 1) / 2;
      JXL_DEBUG_V(7, "Vertical (%zux%zu), ", w, h);
    }
  }
  while (w > JXL_MAX_FIRST_PREVIEW_SIZE || h > JXL_MAX_FIRST_PREVIEW_SIZE) {
    if (w > JXL_MAX_FIRST_PREVIEW_SIZE) {
      params.horizontal = true;
      parameters->push_back(params);
      w = (w + 1) / 2;
      JXL_DEBUG_V(7, "Horizontal (%zux%zu), ", w, h);
    }
    if (h > JXL_MAX_FIRST_PREVIEW_SIZE) {
      params.horizontal = false;
      parameters->push_back(params);
      h = (h + 1) / 2;
      JXL_DEBUG_V(7, "Vertical (%zux%zu), ", w, h);
    }
  }
  JXL_DEBUG_V(7, "that's it");
}

Status CheckMetaSqueezeParams(const std::vector<SqueezeParams> &parameters,
                              int num_channels) {
  for (size_t i = 0; i < parameters.size(); i++) {
    int c1 = parameters[i].begin_c;
    int c2 = parameters[i].begin_c + parameters[i].num_c - 1;
    if (c1 < 0 || c1 > num_channels || c2 < 0 || c2 >= num_channels ||
        c2 < c1) {
      return JXL_FAILURE("Invalid channel range");
    }
  }
  return true;
}

Status MetaSqueeze(Image &image, std::vector<SqueezeParams> *parameters) {
  if (parameters->empty()) {
    DefaultSqueezeParameters(parameters, image);
  }
  JXL_RETURN_IF_ERROR(
      CheckMetaSqueezeParams(*parameters, image.channel.size()));

  for (size_t i = 0; i < parameters->size(); i++) {
    bool horizontal = (*parameters)[i].horizontal;
    bool in_place = (*parameters)[i].in_place;
    uint32_t beginc = (*parameters)[i].begin_c;
    uint32_t endc = (*parameters)[i].begin_c + (*parameters)[i].num_c - 1;

    uint32_t offset;
    if (in_place) {
      offset = endc + 1;
    } else {
      offset = image.channel.size();
    }
    for (uint32_t c = beginc; c <= endc; c++) {
      if (image.channel[c].hshift > 30 || image.channel[c].vshift > 30) {
        return JXL_FAILURE("Too many squeezes: shift > 30");
      }
      size_t w = image.channel[c].w;
      size_t h = image.channel[c].h;
      if (horizontal) {
        image.channel[c].w = (w + 1) / 2;
        image.channel[c].hshift++;
        w = w - (w + 1) / 2;
      } else {
        image.channel[c].h = (h + 1) / 2;
        image.channel[c].vshift++;
        h = h - (h + 1) / 2;
      }
      image.channel[c].shrink();
      Channel dummy(w, h);
      dummy.hshift = image.channel[c].hshift;
      dummy.vshift = image.channel[c].vshift;

      image.channel.insert(image.channel.begin() + offset + (c - beginc),
                           std::move(dummy));
    }
  }
  return true;
}

Status InvSqueeze(Image &input, std::vector<SqueezeParams> parameters,
                  ThreadPool *pool) {
  if (parameters.empty()) {
    DefaultSqueezeParameters(&parameters, input);
  }
  JXL_RETURN_IF_ERROR(CheckMetaSqueezeParams(parameters, input.channel.size()));

  for (int i = parameters.size() - 1; i >= 0; i--) {
    bool horizontal = parameters[i].horizontal;
    bool in_place = parameters[i].in_place;
    uint32_t beginc = parameters[i].begin_c;
    uint32_t endc = parameters[i].begin_c + parameters[i].num_c - 1;
    uint32_t offset;
    if (in_place) {
      offset = endc + 1;
    } else {
      offset = input.channel.size() + beginc - endc - 1;
    }
    for (uint32_t c = beginc; c <= endc; c++) {
      uint32_t rc = offset + c - beginc;
      if ((input.channel[c].w < input.channel[rc].w) ||
          (input.channel[c].h < input.channel[rc].h)) {
        return JXL_FAILURE("Corrupted squeeze transform");
      }
      if (horizontal) {
        InvHSqueeze(input, c, rc, pool);
      } else {
        InvVSqueeze(input, c, rc, pool);
      }
    }
    input.channel.erase(input.channel.begin() + offset,
                        input.channel.begin() + offset + (endc - beginc + 1));
  }
  return true;
}

}  // namespace jxl
<|endoftext|>


<commit_before>#include "math/Compression.h"

#include "Test.h"

using namespace PR;

PR_BEGIN_TESTCASE(Compression)
PR_TEST("unorm16")
{
	float f   = 0.5f;
	unorm16 s = to_unorm16(f);
	float r   = from_unorm16(s);

	PR_CHECK_NEARLY_EQ(r, f);
}

PR_TEST("snorm16")
{
	float f   = -0.25f;
	snorm16 s = to_snorm16(f);
	float r   = from_snorm16(s);

	PR_CHECK_NEARLY_EQ(r, f);
}

PR_TEST("oct 1")
{
	Vector3f d(1, 0, 0);
	Vector2f o = to_oct(d);
	Vector3f r = from_oct(o);

	PR_CHECK_NEARLY_EQ(r, d);
}

PR_TEST("oct 2")
{
	Vector3f d(0, -1, 0);
	Vector2f o = to_oct(d);
	Vector3f r = from_oct(o);

	PR_CHECK_NEARLY_EQ(r, d);
}

PR_TEST("oct 3")
{
	Vector3f d(0.707107f, 0, 0.707107f);
	Vector2f o = to_oct(d);
	Vector3f r = from_oct(o);

	PR_CHECK_NEARLY_EQ(r, d);
}

PR_END_TESTCASE()

// MAIN
PRT_BEGIN_MAIN
PRT_TESTCASE(Compression);
PRT_END_MAIN<commit_msg>fixed test error<commit_after>#include "math/Compression.h"

#define PRT_EPSILON (0.00001f)
#include "Test.h"

using namespace PR;

PR_BEGIN_TESTCASE(Compression)
PR_TEST("unorm16")
{
	float f   = 0.5f;
	unorm16 s = to_unorm16(f);
	float r   = from_unorm16(s);

	PR_CHECK_NEARLY_EQ(r, f);
}

PR_TEST("snorm16")
{
	float f   = -0.25f;
	snorm16 s = to_snorm16(f);
	float r   = from_snorm16(s);

	PR_CHECK_NEARLY_EQ(r, f);
}

PR_TEST("oct 1")
{
	Vector3f d(1, 0, 0);
	Vector2f o = to_oct(d);
	Vector3f r = from_oct(o);

	PR_CHECK_NEARLY_EQ(r, d);
}

PR_TEST("oct 2")
{
	Vector3f d(0, -1, 0);
	Vector2f o = to_oct(d);
	Vector3f r = from_oct(o);

	PR_CHECK_NEARLY_EQ(r, d);
}

PR_TEST("oct 3")
{
	Vector3f d(0.707107f, 0, 0.707107f);
	Vector2f o = to_oct(d);
	Vector3f r = from_oct(o);

	PR_CHECK_NEARLY_EQ(r, d);
}

PR_END_TESTCASE()

// MAIN
PRT_BEGIN_MAIN
PRT_TESTCASE(Compression);
PRT_END_MAIN<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>

#include <list>
#include <string>

#include <process/clock.hpp>

#include <stout/os.hpp>
#include <stout/strings.hpp>

#include "configurator/configurator.hpp"

#include "tests/environment.hpp"
#include "tests/filter.hpp"

using std::list;
using std::string;

namespace mesos {
namespace internal {
namespace tests {

// A simple test event listener that makes sure to resume the clock
// after each test even if the previous test had a partial result
// (i.e., an ASSERT_* failed).
class ClockTestEventListener : public ::testing::EmptyTestEventListener
{
public:
  virtual void OnTestEnd(const ::testing::TestInfo&)
  {
    if (process::Clock::paused()) {
      process::Clock::resume();
    }
  }
};

// Returns true if we should enable the provided test. Similar to how
// tests can be disabled using the 'DISABLED_' prefix on a test case
// name or test name, we use 'ROOT_' and 'CGROUPS_' prefixes to only
// enable tests based on whether or not the current user is root or
// cgroups support is detected. Both 'ROOT_' and 'CGROUPS_' can be
// composed in any order, but must come after 'DISABLED_'. In
// addition, we disable tests that attempt to use the CgroupsIsolator
// type parameter if the current user is not root or cgroups is not
// supported.
// TODO(benh): Provide a generic way to enable/disable tests by
// registering "filter" functions.
static bool enable(const ::testing::TestInfo& test)
{
  // First check the test case name and test name.
  list<string> names;
  names.push_back(test.test_case_name());
  names.push_back(test.name());

  foreach (const string& name, names) {
    if (strings::contains(name, "ROOT_") && os::user() != "root") {
      return false;
    }

    if (strings::contains(name, "CGROUPS_") && !os::exists("/proc/cgroups")) {
      return false;
    }
  }

  // Now check the type parameter.
  if (test.type_param() != NULL) {
    const string& type = test.type_param();
    if (strings::contains(type, "CgroupsIsolator") &&
        (os::user() != "root" || !os::exists("/proc/cgroups"))) {
      return false;
    }
  }

  return true;
}

// We use the constructor to setup specific tests by updating the
// gtest filter. We do this so that we can selectively run tests that
// require root or specific OS support (e.g., cgroups). Note that this
// should not effect any other filters that have been put in place
// either on the command line or via an environment variable.
// N.B. This MUST be done _before_ invoking RUN_ALL_TESTS.
Environment::Environment()
{
  // First we split the current filter into positive and negative
  // components (which are separated by a '-').
  const string& filter = ::testing::GTEST_FLAG(filter);
  string positive;
  string negative;

  size_t dash = filter.find('-');
  if (dash != string::npos) {
    positive = filter.substr(0, dash);
    negative = filter.substr(dash + 1);
  } else {
    positive = filter;
  }

  // Use universal filter if not specified.
  if (positive.empty()) {
    positive = "*";
  }

  // Construct the filter string to handle system or platform specific tests.
  ::testing::UnitTest* unitTest = ::testing::UnitTest::GetInstance();
  for (int i = 0; i < unitTest->total_test_case_count(); i++) {
    const ::testing::TestCase* testCase = unitTest->GetTestCase(i);
    for (int j = 0; j < testCase->total_test_count(); j++) {
      const ::testing::TestInfo* testInfo = testCase->GetTestInfo(j);

      if (!enable(*testCase->GetTestInfo(j))) {
        // Append 'TestCase.TestName:'.
        negative.append(testInfo->test_case_name());
        negative.append(".");
        negative.append(testInfo->name());
        negative.append(":");
      }
    }
  }

  // Now update the gtest flag.
  ::testing::GTEST_FLAG(filter) = positive + "-" + negative;
}

void Environment::SetUp()
{
  // Clear any MESOS_ environment variables so they don't affect our tests.
  Configurator::clearMesosEnvironmentVars();

  // Add our test event listeners.
  ::testing::TestEventListeners& listeners =
    ::testing::UnitTest::GetInstance()->listeners();

  listeners.Append(new FilterTestEventListener());
  listeners.Append(new ClockTestEventListener());
}

void Environment::TearDown() {}

} // namespace tests {
} // namespace internal {
} // namespace mesos {

<commit_msg>Fixed a bug where a filter specified via --gtest_filter (or GTEST_FILTER) was not properly included in the filter we construct based on the environment.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>

#include <list>
#include <string>

#include <process/clock.hpp>

#include <stout/os.hpp>
#include <stout/strings.hpp>

#include "configurator/configurator.hpp"

#include "tests/environment.hpp"
#include "tests/filter.hpp"

using std::list;
using std::string;

namespace mesos {
namespace internal {
namespace tests {

// A simple test event listener that makes sure to resume the clock
// after each test even if the previous test had a partial result
// (i.e., an ASSERT_* failed).
class ClockTestEventListener : public ::testing::EmptyTestEventListener
{
public:
  virtual void OnTestEnd(const ::testing::TestInfo&)
  {
    if (process::Clock::paused()) {
      process::Clock::resume();
    }
  }
};

// Returns true if we should enable the provided test. Similar to how
// tests can be disabled using the 'DISABLED_' prefix on a test case
// name or test name, we use 'ROOT_' and 'CGROUPS_' prefixes to only
// enable tests based on whether or not the current user is root or
// cgroups support is detected. Both 'ROOT_' and 'CGROUPS_' can be
// composed in any order, but must come after 'DISABLED_'. In
// addition, we disable tests that attempt to use the CgroupsIsolator
// type parameter if the current user is not root or cgroups is not
// supported.
// TODO(benh): Provide a generic way to enable/disable tests by
// registering "filter" functions.
static bool enable(const ::testing::TestInfo& test)
{
  // First check the test case name and test name.
  list<string> names;
  names.push_back(test.test_case_name());
  names.push_back(test.name());

  foreach (const string& name, names) {
    if (strings::contains(name, "ROOT_") && os::user() != "root") {
      return false;
    }

    if (strings::contains(name, "CGROUPS_") && !os::exists("/proc/cgroups")) {
      return false;
    }
  }

  // Now check the type parameter.
  if (test.type_param() != NULL) {
    const string& type = test.type_param();
    if (strings::contains(type, "CgroupsIsolator") &&
        (os::user() != "root" || !os::exists("/proc/cgroups"))) {
      return false;
    }
  }

  return true;
}

// We use the constructor to setup specific tests by updating the
// gtest filter. We do this so that we can selectively run tests that
// require root or specific OS support (e.g., cgroups). Note that this
// should not effect any other filters that have been put in place
// either on the command line or via an environment variable.
// N.B. This MUST be done _before_ invoking RUN_ALL_TESTS.
Environment::Environment()
{
  // First we split the current filter into enabled and disabled tests
  // (which are separated by a '-').
  const string& filter = ::testing::GTEST_FLAG(filter);
  string enabled;
  string disabled;

  size_t dash = filter.find('-');
  if (dash != string::npos) {
    enabled = filter.substr(0, dash);
    disabled = filter.substr(dash + 1);
  } else {
    enabled = filter;
  }

  // Use universal filter if not specified.
  if (enabled.empty()) {
    enabled = "*";
  }

  // Ensure disabled tests end with ":" separator before we add more.
  if (!disabled.empty() && !strings::endsWith(disabled, ":")) {
    disabled += ":";
  }

  // Construct the filter string to handle system or platform specific tests.
  ::testing::UnitTest* unitTest = ::testing::UnitTest::GetInstance();
  for (int i = 0; i < unitTest->total_test_case_count(); i++) {
    const ::testing::TestCase* testCase = unitTest->GetTestCase(i);
    for (int j = 0; j < testCase->total_test_count(); j++) {
      const ::testing::TestInfo* testInfo = testCase->GetTestInfo(j);

      if (!enable(*testCase->GetTestInfo(j))) {
        // Append 'TestCase.TestName:'.
        disabled.append(testInfo->test_case_name());
        disabled.append(".");
        disabled.append(testInfo->name());
        disabled.append(":");
      }
    }
  }

  // Now update the gtest flag.
  ::testing::GTEST_FLAG(filter) = enabled + "-" + disabled;
}

void Environment::SetUp()
{
  // Clear any MESOS_ environment variables so they don't affect our tests.
  Configurator::clearMesosEnvironmentVars();

  // Add our test event listeners.
  ::testing::TestEventListeners& listeners =
    ::testing::UnitTest::GetInstance()->listeners();

  listeners.Append(new FilterTestEventListener());
  listeners.Append(new ClockTestEventListener());
}

void Environment::TearDown() {}

} // namespace tests {
} // namespace internal {
} // namespace mesos {

<|endoftext|>


<commit_before>/* OpenSceneGraph example, osgdrawinstanced.
*
*  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 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.
*/
//
// This code is copyright (c) 2008 Skew Matrix Software LLC. You may use
// the code under the licensing terms described above.
//

#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Geometry>
#include <osg/Texture2D>

#include <osgDB/WriteFile>

#include <iostream>

void
createDAIGeometry( osg::Geometry& geom, int nInstances=1 )
{
    const float halfDimX( .5 );
    const float halfDimZ( .5 );

    osg::Vec3Array* v = new osg::Vec3Array;
    v->resize( 4 );
    geom.setVertexArray( v );

    // Geometry for a single quad.
    (*v)[ 0 ] = osg::Vec3( -halfDimX, 0., -halfDimZ );
    (*v)[ 1 ] = osg::Vec3( halfDimX, 0., -halfDimZ );
    (*v)[ 2 ] = osg::Vec3( halfDimX, 0., halfDimZ );
    (*v)[ 3 ] = osg::Vec3( -halfDimX, 0., halfDimZ );

    // Use the DrawArraysInstanced PrimitiveSet and tell it to draw 1024 instances.
    geom.addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 4, nInstances ) );
}

osg::StateSet*
createStateSet()
{
    osg::ref_ptr< osg::StateSet > ss = new osg::StateSet;

    // Create a vertex program that references the gl_InstanceID to
    // render each instance uniquely. gl_InstanceID will be in the range
    // 0 to numInstances-1 (1023 in our case).
    std::string vertexSource =
        "uniform sampler2D osgLogo; \n"
        "uniform float osg_SimulationTime; \n"

        "void main() \n"
        "{ \n"
            // Using the instance ID, generate "texture coords" for this instance.
            "vec2 tC; \n"
            "const float r = gl_InstanceID / 32.; \n"
            "tC.s = fract( r ); tC.t = floor( r ) / 32.; \n"
            // Get the color from the OSG logo.
            "gl_FrontColor = texture2D( osgLogo, tC ); \n"

            // Use the (scaled) tex coord to translate the position of the vertices.
            "vec4 pos = vec4( tC.s * 48., 0., tC.t * 48., 1. ); \n"

            // Compute a rotation angle from the instanceID and elapsed time.
            "float timeOffset = gl_InstanceID / (32. * 32.); \n"
            "float angle = ( osg_SimulationTime - timeOffset ) * 6.283; \n"
            "float sa = sin( angle ); \n"
            "float ca = cos( angle ); \n"
            // New orientation, rotate around z axis.
            "vec4 newX = vec4( ca, sa, 0., 0. ); \n"
            "vec4 newY = vec4( sa, ca, 0., 0. ); \n"
            "vec4 newZ = vec4( 0., 0., 1., 0. ); \n"
            "mat4 mV = mat4( newX, newY, newZ, pos ); \n"
            "gl_Position = ( gl_ModelViewProjectionMatrix * mV * gl_Vertex ); \n"
        "} \n";

    osg::ref_ptr< osg::Shader > vertexShader = new osg::Shader();
    vertexShader->setType( osg::Shader::VERTEX );
    vertexShader->setShaderSource( vertexSource );

    osg::ref_ptr< osg::Program > program = new osg::Program();
    program->addShader( vertexShader.get() );

    ss->setAttribute( program.get(),
        osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );

    osg::ref_ptr< osg::Image> iLogo = osgDB::readImageFile( "Images/osg128.png" );
    if( !iLogo.valid() )
    {
        osg::notify( osg::ALWAYS ) << "Can't open image file osg128.png" << std::endl;
        return( NULL );
    }
    osg::Texture2D* texLogo = new osg::Texture2D( iLogo.get() );
    texLogo->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR );
    texLogo->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR );

    ss->setTextureAttribute( 0, texLogo );

    osg::ref_ptr< osg::Uniform > texLogoUniform =
        new osg::Uniform( "osgLogo", 0 );
    ss->addUniform( texLogoUniform.get() );

    return( ss.release() );
}

int main( int argc, char **argv )
{
    osg::ArgumentParser arguments(&argc, argv);

   // Make a scene graph consisting of a single Geode, containing
    // a single Geometry, and a single PrimitiveSet.
    osg::ref_ptr< osg::Geode > geode = new osg::Geode;

    osg::ref_ptr< osg::Geometry > geom = new osg::Geometry;
    // Configure the Geometry for use with EXT_draw_arrays:
    // DL off and buffer objects on.
    geom->setUseDisplayList( false );
    geom->setUseVertexBufferObjects( true );
    // OSG has no clue where out vertex shader will place the geometric data,
    // so specify an initial bound to allow proper culling and near/far computation.
    osg::BoundingBox bb( -1., -.1, -1., 49., 1., 49. );
    geom->setInitialBound( bb );
    // Add geometric data and the PrimitiveSet. Specify numInstances as 32*32 or 1024.
    createDAIGeometry( *geom, 32*32 );
    geode->addDrawable( geom.get() );

    // Create a StateSet to render the instanced Geometry.
    osg::ref_ptr< osg::StateSet > ss = createStateSet();
    geode->setStateSet( ss.get() );

    // osgDB::writeNodeFile(*geode, "instanced.osg");

    osgViewer::Viewer viewer(arguments);
    viewer.setSceneData( geode.get() );
    return viewer.run();
}
<commit_msg>Tweaks to shader to fix warnings on with ATI drivers<commit_after>/* OpenSceneGraph example, osgdrawinstanced.
*
*  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 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.
*/
//
// This code is copyright (c) 2008 Skew Matrix Software LLC. You may use
// the code under the licensing terms described above.
//

#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Geometry>
#include <osg/Texture2D>

#include <osgDB/WriteFile>

#include <iostream>

void
createDAIGeometry( osg::Geometry& geom, int nInstances=1 )
{
    const float halfDimX( .5 );
    const float halfDimZ( .5 );

    osg::Vec3Array* v = new osg::Vec3Array;
    v->resize( 4 );
    geom.setVertexArray( v );

    // Geometry for a single quad.
    (*v)[ 0 ] = osg::Vec3( -halfDimX, 0., -halfDimZ );
    (*v)[ 1 ] = osg::Vec3( halfDimX, 0., -halfDimZ );
    (*v)[ 2 ] = osg::Vec3( halfDimX, 0., halfDimZ );
    (*v)[ 3 ] = osg::Vec3( -halfDimX, 0., halfDimZ );

    // Use the DrawArraysInstanced PrimitiveSet and tell it to draw 1024 instances.
    geom.addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 4, nInstances ) );
}

osg::StateSet*
createStateSet()
{
    osg::ref_ptr< osg::StateSet > ss = new osg::StateSet;

    // Create a vertex program that references the gl_InstanceID to
    // render each instance uniquely. gl_InstanceID will be in the range
    // 0 to numInstances-1 (1023 in our case).
    std::string vertexSource =
        "uniform sampler2D osgLogo; \n"
        "uniform float osg_SimulationTime; \n"

        "void main() \n"
        "{ \n"
            // Using the instance ID, generate "texture coords" for this instance.
            "vec2 tC; \n"
            "float r = float(gl_InstanceID) / 32.; \n"
            "tC.s = fract( r ); tC.t = floor( r ) / 32.; \n"
            // Get the color from the OSG logo.
            "gl_FrontColor = texture2D( osgLogo, tC ); \n"

            // Use the (scaled) tex coord to translate the position of the vertices.
            "vec4 pos = vec4( tC.s * 48., 0., tC.t * 48., 1. ); \n"

            // Compute a rotation angle from the instanceID and elapsed time.
            "float timeOffset = gl_InstanceID / (32. * 32.); \n"
            "float angle = ( osg_SimulationTime - timeOffset ) * 6.283; \n"
            "float sa = sin( angle ); \n"
            "float ca = cos( angle ); \n"
            // New orientation, rotate around z axis.
            "vec4 newX = vec4( ca, sa, 0., 0. ); \n"
            "vec4 newY = vec4( sa, ca, 0., 0. ); \n"
            "vec4 newZ = vec4( 0., 0., 1., 0. ); \n"
            "mat4 mV = mat4( newX, newY, newZ, pos ); \n"
            "gl_Position = ( gl_ModelViewProjectionMatrix * mV * gl_Vertex ); \n"
        "} \n";

    osg::ref_ptr< osg::Shader > vertexShader = new osg::Shader();
    vertexShader->setType( osg::Shader::VERTEX );
    vertexShader->setShaderSource( vertexSource );

    osg::ref_ptr< osg::Program > program = new osg::Program();
    program->addShader( vertexShader.get() );

    ss->setAttribute( program.get(),
        osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );

    osg::ref_ptr< osg::Image> iLogo = osgDB::readImageFile( "Images/osg128.png" );
    if( !iLogo.valid() )
    {
        osg::notify( osg::ALWAYS ) << "Can't open image file osg128.png" << std::endl;
        return( NULL );
    }
    osg::Texture2D* texLogo = new osg::Texture2D( iLogo.get() );
    texLogo->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR );
    texLogo->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR );

    ss->setTextureAttribute( 0, texLogo );

    osg::ref_ptr< osg::Uniform > texLogoUniform =
        new osg::Uniform( "osgLogo", 0 );
    ss->addUniform( texLogoUniform.get() );

    return( ss.release() );
}

int main( int argc, char **argv )
{
    osg::ArgumentParser arguments(&argc, argv);

   // Make a scene graph consisting of a single Geode, containing
    // a single Geometry, and a single PrimitiveSet.
    osg::ref_ptr< osg::Geode > geode = new osg::Geode;

    osg::ref_ptr< osg::Geometry > geom = new osg::Geometry;
    // Configure the Geometry for use with EXT_draw_arrays:
    // DL off and buffer objects on.
    geom->setUseDisplayList( false );
    geom->setUseVertexBufferObjects( true );
    // OSG has no clue where out vertex shader will place the geometric data,
    // so specify an initial bound to allow proper culling and near/far computation.
    osg::BoundingBox bb( -1., -.1, -1., 49., 1., 49. );
    geom->setInitialBound( bb );
    // Add geometric data and the PrimitiveSet. Specify numInstances as 32*32 or 1024.
    createDAIGeometry( *geom, 32*32 );
    geode->addDrawable( geom.get() );

    // Create a StateSet to render the instanced Geometry.
    osg::ref_ptr< osg::StateSet > ss = createStateSet();
    geode->setStateSet( ss.get() );

    // osgDB::writeNodeFile(*geode, "instanced.osg");

    osgViewer::Viewer viewer(arguments);
    viewer.setSceneData( geode.get() );
    return viewer.run();
}
<|endoftext|>


<commit_before>/*
 *      Author: Michael Camilleri
 *
 * Copyright (c) 2016, University Of Edinburgh
 * 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.
 *  * Neither the name of  nor the names of its contributors may be used to
 *    endorse or promote products derived from this software without specific
 *    prior written permission.
 *
 * 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 OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "Identity.h"

REGISTER_TASKMAP_TYPE("Identity", exotica::Identity);

namespace exotica
{
  Identity::Identity()
  {

  }

  void Identity::update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi)
  {
      if(phi.rows() != jointMap.size()) throw_named("Wrong size of phi!");
      for(int i=0;i<jointMap.size();i++)
      {
          phi(i) = x(jointMap[i]) - jointRef(i);
      }
  }

  void Identity::update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi, Eigen::MatrixXdRef J)
  {
      if(phi.rows() != jointMap.size()) throw_named("Wrong size of phi!");
      if(J.rows() != jointMap.size() || J.cols() != N) throw_named("Wrong size of J! " << N);
      J.setZero();
      for(int i=0;i<jointMap.size();i++)
      {
          phi(i) = jointRef(i) - x(jointMap[i]);
          J(i, jointMap[i]) = 1.0;
      }
  }

  void Identity::update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi, Eigen::VectorXdRef phidot, Eigen::MatrixXdRef J, Eigen::MatrixXdRef Jdot)
  {
      if(phi.rows() != jointMap.size()) throw_named("Wrong size of phi!");
      if(J.rows() != jointMap.size() || J.cols() != N) throw_named("Wrong size of J! " << N);
      if(Jdot.rows() != jointMap.size() || Jdot.cols() != N) throw_named("Wrong size of J! " << N);
      J.setZero();
      Jdot.setZero();
      for(int i=0;i<jointMap.size();i++)
      {
          phi(i) = jointRef(i) - x(jointMap[i]);
          phidot(i) = jointRef(i+jointMap.size()) - x(jointMap[i]+N);
          J(i, jointMap[i]) = 1.0;
          Jdot(i, jointMap[i]) = 1.0;
      }
  }

  void Identity::Instantiate(IdentityInitializer& init)
  {
      init_ = init;
  }

  void Identity::assignScene(Scene_ptr scene)
  {
      scene_ = scene;
      Initialize();
  }

  void Identity::Initialize()
  {
      N = scene_->getSolver().getNumJoints();
      if(init_.JointRef.rows()>0)
      {
          jointRef = init_.JointRef;
          if(init_.JointMap.size()>0)
          {
              jointMap = init_.JointMap;
              if(jointMap.size()!=jointRef.rows()) throw_named("Incorrect joint map size!");
          }
          else
          {
              jointMap.resize(jointRef.rows());
              for (int i = 0; i < jointRef.rows(); i++) jointMap[i] = i;
          }
      }
      else
      {
          jointRef = Eigen::VectorXd::Zero(N);
          jointMap.resize(N);
          for (int i = 0; i < N; i++) jointMap[i] = i;
      }
  }

  int Identity::taskSpaceDim()
  {
      return jointMap.size();
  }
}
<commit_msg>Fixed Identity initialization<commit_after>/*
 *      Author: Michael Camilleri
 *
 * Copyright (c) 2016, University Of Edinburgh
 * 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.
 *  * Neither the name of  nor the names of its contributors may be used to
 *    endorse or promote products derived from this software without specific
 *    prior written permission.
 *
 * 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 OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "Identity.h"

REGISTER_TASKMAP_TYPE("Identity", exotica::Identity);

namespace exotica
{
  Identity::Identity()
  {

  }

  void Identity::update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi)
  {
      if(phi.rows() != jointMap.size()) throw_named("Wrong size of phi!");
      for(int i=0;i<jointMap.size();i++)
      {
          phi(i) = x(jointMap[i]) - jointRef(i);
      }
  }

  void Identity::update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi, Eigen::MatrixXdRef J)
  {
      if(phi.rows() != jointMap.size()) throw_named("Wrong size of phi!");
      if(J.rows() != jointMap.size() || J.cols() != N) throw_named("Wrong size of J! " << N);
      J.setZero();
      for(int i=0;i<jointMap.size();i++)
      {
          phi(i) = x(jointMap[i]) - jointRef(i);
          J(i, jointMap[i]) = 1.0;
      }
  }

  void Identity::update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi, Eigen::VectorXdRef phidot, Eigen::MatrixXdRef J, Eigen::MatrixXdRef Jdot)
  {
      if(phi.rows() != jointMap.size()) throw_named("Wrong size of phi!");
      if(J.rows() != jointMap.size() || J.cols() != N) throw_named("Wrong size of J! " << N);
      if(Jdot.rows() != jointMap.size() || Jdot.cols() != N) throw_named("Wrong size of J! " << N);
      J.setZero();
      Jdot.setZero();
      for(int i=0;i<jointMap.size();i++)
      {
          phi(i) = x(jointMap[i]) - jointRef(i);
          phidot(i) = x(jointMap[i]+N) - jointRef(i+jointMap.size());
          J(i, jointMap[i]) = 1.0;
          Jdot(i, jointMap[i]) = 1.0;
      }
  }

  void Identity::Instantiate(IdentityInitializer& init)
  {
      init_ = init;
  }

  void Identity::assignScene(Scene_ptr scene)
  {
      scene_ = scene;
      Initialize();
  }

  void Identity::Initialize()
  {
      N = std::max(scene_->getSolver().getNumJoints(), (int)init_.JointMap.size());
      if(init_.JointMap.size()>0)
      {
          jointMap = init_.JointMap;
      }
      else
      {
          jointMap.resize(N);
          for (int i = 0; i < N; i++) jointMap[i] = i;
      }

      if(init_.JointRef.rows()>0)
      {
          jointRef = init_.JointRef;
          if(jointRef.rows()!=N) throw_named("Invalid joint reference size! Expecting " << N);
      }
      else
      {
          jointRef = Eigen::VectorXd::Zero(N);
      }

  }

  int Identity::taskSpaceDim()
  {
      return jointMap.size();
  }
}
<|endoftext|>


<commit_before>#include "OI.h"

#include "Commands/Shooter/ToggleShooter.h"
#include "Commands/Shooter/KillShooter.h"
#include "Commands/TurHop/AltitudeDirCont.h"
#include "Commands/TurHop/Fire.h"
#include "Commands/TurHop/Load.h"
#include "Commands/TurHop/RotateHopper.h"

OI::OI() {
	// Process operator interface input here.
	stick = new Joystick(1);

	raiseTur = new JoystickButton(stick, 2);
	lowerTur = new JoystickButton(stick, 1);
	fire = new JoystickButton(stick, 6);
	loader = new JoystickButton(stick, 5);
	speedToggler = new JoystickButton(stick, 4);
	killShooter = new JoystickButton(stick, 3);

	raiseTur->WhileHeld(new AltitudeDirCont(true));
	lowerTur->WhileHeld(new AltitudeDirCont(false));
	fire->WhileHeld(new Fire());
	load->WhenPressed(new Load());
	speedToggler->WhenPressed(new ToggleShooter());
	killShooter->WhenPressed(new KillShooter());
}
double OI::GetStick(int stickNum)
{
	switch(stickNum)
	{
	default:
		return stick->GetRawAxis(2);
	case 1:
		return stick->GetRawAxis(2);
	case 2:
		return stick->GetRawAxis(5);
	}
}
<commit_msg>fixed typo<commit_after>#include "OI.h"

#include "Commands/Shooter/ToggleShooter.h"
#include "Commands/Shooter/KillShooter.h"
#include "Commands/TurHop/AltitudeDirCont.h"
#include "Commands/TurHop/Fire.h"
#include "Commands/TurHop/Load.h"
#include "Commands/TurHop/RotateHopper.h"

OI::OI() {
	// Process operator interface input here.
	stick = new Joystick(1);

	raiseTur = new JoystickButton(stick, 2);
	lowerTur = new JoystickButton(stick, 1);
	fire = new JoystickButton(stick, 6);
	loader = new JoystickButton(stick, 5);
	speedToggler = new JoystickButton(stick, 4);
	killShooter = new JoystickButton(stick, 3);

	raiseTur->WhileHeld(new AltitudeDirCont(true));
	lowerTur->WhileHeld(new AltitudeDirCont(false));
	fire->WhileHeld(new Fire());
	loader->WhenPressed(new Load());
	speedToggler->WhenPressed(new ToggleShooter());
	killShooter->WhenPressed(new KillShooter());
}
double OI::GetStick(int stickNum)
{
	switch(stickNum)
	{
	default:
		return stick->GetRawAxis(2);
	case 1:
		return stick->GetRawAxis(2);
	case 2:
		return stick->GetRawAxis(5);
	}
}
<|endoftext|>


<commit_before>#include "tag-database-sqlite.h"
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlError>
#include <QVariant>
#include "logger.h"

TagDatabaseSqlite::TagDatabaseSqlite(QString typeFile, QString tagFile)
	: TagDatabase(typeFile), m_tagFile(tagFile)
{}

bool TagDatabaseSqlite::load()
{
	// Don't reload databases
	if (m_database.isOpen())
		return true;

	// Load tag types
	if (!TagDatabase::load())
		return false;

	// Load and connect to the database
	m_database = QSqlDatabase::addDatabase("QSQLITE");
	m_database.setDatabaseName("release/sites/Danbooru/e621.net/tags.db");
	if (!m_database.open())
		return false;

	// Create schema if necessary
	QSqlQuery createQuery(m_database);
	createQuery.prepare("CREATE TABLE IF NOT EXISTS tags (tag VARCHAR(255), ttype INT);");
	if (!createQuery.exec())
		return false;

	return true;
}

bool TagDatabaseSqlite::save()
{
	return true;
}

void TagDatabaseSqlite::setTags(const QList<Tag> &tags)
{
	// Inverted tag type map to get the tag type ID from its name
	QMap<QString, int> tagTypes;
	for (int typeId : m_tagTypes.keys())
		tagTypes.insert(m_tagTypes[typeId].name(), typeId);

	QSqlQuery clearQuery(m_database);
	clearQuery.prepare("DELETE FROM tags");
	if (!clearQuery.exec())
	{
		log(QString("SQL error when clearing tags: %1").arg(clearQuery.lastError().text()), Logger::Error);
		return;
	}

	if (!m_database.transaction())
		return;

	QSqlQuery addQuery(m_database);
	addQuery.prepare("INSERT INTO tags (tag, ttype) VALUES (:tag, :ttype)");

	for (Tag tag : tags)
	{
		QString type = tag.type().name();
		addQuery.bindValue(":tag", tag.text());
		addQuery.bindValue(":ttype", tagTypes.contains(type) ? tagTypes[type] : -1);
		if (!addQuery.exec())
		{
			log(QString("SQL error when adding tag: %1").arg(addQuery.lastError().text()), Logger::Error);
			return;
		}
	}

	if (!m_database.commit())
		return;
}

TagType TagDatabaseSqlite::getTagType(QString tag) const
{
	QSqlQuery query(m_database);
	query.prepare("SELECT tag, ttype FROM tags WHERE tag IN (:tags)");
	query.bindValue(":tags", QStringList() << tag);
	if (!query.exec())
	{
		log(QString("SQL error when getting tags: %1").arg(query.lastError().text()), Logger::Error);
		return TagType("unknown");
	}

	int idTtype = query.record().indexOf("ttype");
	if (!query.first())
		return TagType("unknown");

	return m_tagTypes[query.value(idTtype).toInt()];
}
<commit_msg>Load correct tag file for Sqlite<commit_after>#include "tag-database-sqlite.h"
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlError>
#include <QVariant>
#include "logger.h"

TagDatabaseSqlite::TagDatabaseSqlite(QString typeFile, QString tagFile)
	: TagDatabase(typeFile), m_tagFile(tagFile)
{}

bool TagDatabaseSqlite::load()
{
	// Don't reload databases
	if (m_database.isOpen())
		return true;

	// Load tag types
	if (!TagDatabase::load())
		return false;

	// Load and connect to the database
	m_database = QSqlDatabase::addDatabase("QSQLITE");
	m_database.setDatabaseName(m_tagFile);
	if (!m_database.open())
		return false;

	// Create schema if necessary
	QSqlQuery createQuery(m_database);
	createQuery.prepare("CREATE TABLE IF NOT EXISTS tags (tag VARCHAR(255), ttype INT);");
	if (!createQuery.exec())
		return false;

	return true;
}

bool TagDatabaseSqlite::save()
{
	return true;
}

void TagDatabaseSqlite::setTags(const QList<Tag> &tags)
{
	// Inverted tag type map to get the tag type ID from its name
	QMap<QString, int> tagTypes;
	for (int typeId : m_tagTypes.keys())
		tagTypes.insert(m_tagTypes[typeId].name(), typeId);

	QSqlQuery clearQuery(m_database);
	clearQuery.prepare("DELETE FROM tags");
	if (!clearQuery.exec())
	{
		log(QString("SQL error when clearing tags: %1").arg(clearQuery.lastError().text()), Logger::Error);
		return;
	}

	if (!m_database.transaction())
		return;

	QSqlQuery addQuery(m_database);
	addQuery.prepare("INSERT INTO tags (tag, ttype) VALUES (:tag, :ttype)");

	for (Tag tag : tags)
	{
		QString type = tag.type().name();
		addQuery.bindValue(":tag", tag.text());
		addQuery.bindValue(":ttype", tagTypes.contains(type) ? tagTypes[type] : -1);
		if (!addQuery.exec())
		{
			log(QString("SQL error when adding tag: %1").arg(addQuery.lastError().text()), Logger::Error);
			return;
		}
	}

	if (!m_database.commit())
		return;
}

TagType TagDatabaseSqlite::getTagType(QString tag) const
{
	QSqlQuery query(m_database);
	query.prepare("SELECT tag, ttype FROM tags WHERE tag IN (:tags)");
	query.bindValue(":tags", QStringList() << tag);
	if (!query.exec())
	{
		log(QString("SQL error when getting tags: %1").arg(query.lastError().text()), Logger::Error);
		return TagType("unknown");
	}

	int idTtype = query.record().indexOf("ttype");
	if (!query.first())
		return TagType("unknown");

	return m_tagTypes[query.value(idTtype).toInt()];
}
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2015 Inviwo Foundation
 * All rights reserved.
 *
 * 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 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 OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/qt/widgets/properties/filepropertywidgetqt.h>
#include <inviwo/qt/widgets/inviwofiledialog.h>

#include <warn/push>
#include <warn/ignore/all>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#include <QStandardPaths>
#else
#include <QDesktopServices>
#endif

#include <QDir>
#include <QFileDialog>
#include <QList>
#include <QSettings>
#include <QUrl>
#include <warn/pop>

namespace inviwo {

FilePropertyWidgetQt::FilePropertyWidgetQt(FileProperty* property)
    : PropertyWidgetQt(property), property_(property) {
    generateWidget();
    updateFromProperty();
}

void FilePropertyWidgetQt::generateWidget() {
    QHBoxLayout* hLayout = new QHBoxLayout();
    setSpacingAndMargins(hLayout);
    setLayout(hLayout);

    label_ = new EditableLabelQt(this, property_);
    hLayout->addWidget(label_);

    QHBoxLayout* hWidgetLayout = new QHBoxLayout();
    hWidgetLayout->setContentsMargins(0, 0, 0, 0);
    QWidget* widget = new QWidget();
    widget->setLayout(hWidgetLayout);

    lineEdit_ = new QLineEdit(this);
    lineEdit_->setReadOnly(true);

    QSizePolicy sp = lineEdit_->sizePolicy();
    sp.setHorizontalStretch(3);
    lineEdit_->setSizePolicy(sp);

    openButton_ = new QToolButton(this);
    openButton_->setIcon(QIcon(":/icons/open.png"));
    hWidgetLayout->addWidget(lineEdit_);
    hWidgetLayout->addWidget(openButton_);

    sp = widget->sizePolicy();
    sp.setHorizontalStretch(3);
    widget->setSizePolicy(sp);

    hLayout->addWidget(widget);
    connect(openButton_, SIGNAL(pressed()), this, SLOT(setPropertyValue()));
}

void FilePropertyWidgetQt::setPropertyValue() {
    std::string path{property_->get()};
    if (!path.empty()) {
        // only accept path if it exists
        if (filesystem::directoryExists(path)) {
            // TODO: replace with filesystem:: functionality!
            path = QDir(QString::fromStdString(path)).absolutePath().toStdString();
        }
    }

    // Setup Extensions
    std::vector<FileExtension> filters = property_->getNameFilters();
    InviwoFileDialog importFileDialog(this, property_->getDisplayName(),
                                      property_->getContentType(), path);

    for (const auto& filter : filters) importFileDialog.addExtension(filter);

    switch (property_->getAcceptMode()) {
        case FileProperty::AcceptMode::Save:
            importFileDialog.setAcceptMode(QFileDialog::AcceptSave);
            break;

        case FileProperty::AcceptMode::Open:
            importFileDialog.setAcceptMode(QFileDialog::AcceptOpen);
            break;

        default:
            importFileDialog.setAcceptMode(QFileDialog::AcceptOpen);
    }

    switch (property_->getFileMode()) {
        case FileProperty::FileMode::AnyFile:
            importFileDialog.setFileMode(QFileDialog::AnyFile);
            break;

        case FileProperty::FileMode::ExistingFile:
            importFileDialog.setFileMode(QFileDialog::ExistingFile);
            break;

        case FileProperty::FileMode::Directory:
            importFileDialog.setFileMode(QFileDialog::Directory);
            break;

        case FileProperty::FileMode::ExistingFiles:
            importFileDialog.setFileMode(QFileDialog::ExistingFiles);
            break;

        case FileProperty::FileMode::DirectoryOnly:
            importFileDialog.setFileMode(QFileDialog::DirectoryOnly);
            break;

        default:
            importFileDialog.setFileMode(QFileDialog::AnyFile);
            break;
    }

    if (importFileDialog.exec()) {
        QString path = importFileDialog.selectedFiles().at(0);
        property_->set(path.toStdString());
    }

    updateFromProperty();
}

bool FilePropertyWidgetQt::requestFile() {
   setPropertyValue();
   return !property_->get().empty();
}

void FilePropertyWidgetQt::updateFromProperty() {
    lineEdit_->setText(QFileInfo(QString::fromStdString(property_->get())).fileName());
}

}  // namespace
<commit_msg>FilePropertyWidgetQT: Check if path is a file or a directory. If it is a file we need the file directory of that path for QT to open the correct path in the file dialog (closes issue inviwo/inviwo-dev#1104)<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2015 Inviwo Foundation
 * All rights reserved.
 *
 * 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 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 OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/qt/widgets/properties/filepropertywidgetqt.h>
#include <inviwo/qt/widgets/inviwofiledialog.h>

#include <warn/push>
#include <warn/ignore/all>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#include <QStandardPaths>
#else
#include <QDesktopServices>
#endif

#include <QDir>
#include <QFileDialog>
#include <QList>
#include <QSettings>
#include <QUrl>
#include <warn/pop>

namespace inviwo {

FilePropertyWidgetQt::FilePropertyWidgetQt(FileProperty* property)
    : PropertyWidgetQt(property), property_(property) {
    generateWidget();
    updateFromProperty();
}

void FilePropertyWidgetQt::generateWidget() {
    QHBoxLayout* hLayout = new QHBoxLayout();
    setSpacingAndMargins(hLayout);
    setLayout(hLayout);

    label_ = new EditableLabelQt(this, property_);
    hLayout->addWidget(label_);

    QHBoxLayout* hWidgetLayout = new QHBoxLayout();
    hWidgetLayout->setContentsMargins(0, 0, 0, 0);
    QWidget* widget = new QWidget();
    widget->setLayout(hWidgetLayout);

    lineEdit_ = new QLineEdit(this);
    lineEdit_->setReadOnly(true);

    QSizePolicy sp = lineEdit_->sizePolicy();
    sp.setHorizontalStretch(3);
    lineEdit_->setSizePolicy(sp);

    openButton_ = new QToolButton(this);
    openButton_->setIcon(QIcon(":/icons/open.png"));
    hWidgetLayout->addWidget(lineEdit_);
    hWidgetLayout->addWidget(openButton_);

    sp = widget->sizePolicy();
    sp.setHorizontalStretch(3);
    widget->setSizePolicy(sp);

    hLayout->addWidget(widget);
    connect(openButton_, SIGNAL(pressed()), this, SLOT(setPropertyValue()));
}

void FilePropertyWidgetQt::setPropertyValue() {
    std::string path{ property_->get() };

    if (!path.empty()) {
        if (filesystem::directoryExists(path)) {  // if a folder is selected
            // TODO: replace with filesystem:: functionality!
            path = QDir(QString::fromStdString(path)).absolutePath().toStdString();
        } else if (filesystem::fileExists(path)) {
            // if a file is selected, set path the the folder, not the file
            path = QDir(QString::fromStdString(filesystem::getFileDirectory(path)))
                       .absolutePath()
                       .toStdString();
        }
    }

    // Setup Extensions
    std::vector<FileExtension> filters = property_->getNameFilters();
    InviwoFileDialog importFileDialog(this, property_->getDisplayName(),
                                      property_->getContentType(), path);

    for (const auto& filter : filters) importFileDialog.addExtension(filter);

    switch (property_->getAcceptMode()) {
        case FileProperty::AcceptMode::Save:
            importFileDialog.setAcceptMode(QFileDialog::AcceptSave);
            break;

        case FileProperty::AcceptMode::Open:
            importFileDialog.setAcceptMode(QFileDialog::AcceptOpen);
            break;

        default:
            importFileDialog.setAcceptMode(QFileDialog::AcceptOpen);
    }

    switch (property_->getFileMode()) {
        case FileProperty::FileMode::AnyFile:
            importFileDialog.setFileMode(QFileDialog::AnyFile);
            break;

        case FileProperty::FileMode::ExistingFile:
            importFileDialog.setFileMode(QFileDialog::ExistingFile);
            break;

        case FileProperty::FileMode::Directory:
            importFileDialog.setFileMode(QFileDialog::Directory);
            break;

        case FileProperty::FileMode::ExistingFiles:
            importFileDialog.setFileMode(QFileDialog::ExistingFiles);
            break;

        case FileProperty::FileMode::DirectoryOnly:
            importFileDialog.setFileMode(QFileDialog::DirectoryOnly);
            break;

        default:
            importFileDialog.setFileMode(QFileDialog::AnyFile);
            break;
    }

    if (importFileDialog.exec()) {
        QString path = importFileDialog.selectedFiles().at(0);
        property_->set(path.toStdString());
    }

    updateFromProperty();
}

bool FilePropertyWidgetQt::requestFile() {
   setPropertyValue();
   return !property_->get().empty();
}

void FilePropertyWidgetQt::updateFromProperty() {
    lineEdit_->setText(QFileInfo(QString::fromStdString(property_->get())).fileName());
}

}  // namespace
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "timer.hpp"
#include "scheduler.hpp"
#include "logging.hpp"
#include "kernel.hpp"   //suspend_boot

#include "drivers/pit.hpp"
#include "drivers/hpet.hpp"

#include "fs/sysfs.hpp"

namespace {

uint64_t _timer_ticks = 0;
uint64_t _timer_seconds = 0;
uint64_t _timer_frequency = 0;

volatile uint64_t _timer_countdown = 0;

std::string sysfs_uptime(){
    return std::to_string(timer::seconds());
}

bool find_hw_timer(){
    if(hpet::install()){
        return true;
    } else {
        logging::logf(logging::log_level::DEBUG, "timer: Unable to install HPET driver\n");
    }

    if(pit::install()){
        return true;
    } else {
        logging::logf(logging::log_level::DEBUG, "timer: Unable to install PIT driver\n");
    }

    return false;
}

} //End of anonymous namespace

void timer::install(){
    if(!find_hw_timer()){
        logging::logf(logging::log_level::ERROR, "Unable to install any timer driver\n");
        suspend_boot();
    }

    sysfs::set_dynamic_value("/sys/", "uptime", &sysfs_uptime);
}

void timer::tick(){
    ++_timer_ticks;

    if(_timer_countdown != 0){
        --_timer_countdown;
    }

    scheduler::tick();

    if(_timer_ticks % frequency() == 0){
        ++_timer_seconds;
    }
}

uint64_t timer::ticks(){
    return _timer_ticks;
}

uint64_t timer::seconds(){
    return _timer_seconds;
}

uint64_t timer::frequency(){
    return _timer_frequency;
}

void timer::frequency(uint64_t freq){
    _timer_frequency = freq;

    logging::logf(logging::log_level::DEBUG, "timer: Frequency set to %u Hz\n", freq);
}
<commit_msg>Remove legacy countdown<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "timer.hpp"
#include "scheduler.hpp"
#include "logging.hpp"
#include "kernel.hpp"   //suspend_boot

#include "drivers/pit.hpp"
#include "drivers/hpet.hpp"

#include "fs/sysfs.hpp"

namespace {

uint64_t _timer_ticks = 0;
uint64_t _timer_seconds = 0;
uint64_t _timer_frequency = 0;

std::string sysfs_uptime(){
    return std::to_string(timer::seconds());
}

bool find_hw_timer(){
    if(hpet::install()){
        return true;
    } else {
        logging::logf(logging::log_level::DEBUG, "timer: Unable to install HPET driver\n");
    }

    if(pit::install()){
        return true;
    } else {
        logging::logf(logging::log_level::DEBUG, "timer: Unable to install PIT driver\n");
    }

    return false;
}

} //End of anonymous namespace

void timer::install(){
    if(!find_hw_timer()){
        logging::logf(logging::log_level::ERROR, "Unable to install any timer driver\n");
        suspend_boot();
    }

    sysfs::set_dynamic_value("/sys/", "uptime", &sysfs_uptime);
}

void timer::tick(){
    ++_timer_ticks;

    scheduler::tick();

    if(_timer_ticks % frequency() == 0){
        ++_timer_seconds;
    }
}

uint64_t timer::ticks(){
    return _timer_ticks;
}

uint64_t timer::seconds(){
    return _timer_seconds;
}

uint64_t timer::frequency(){
    return _timer_frequency;
}

void timer::frequency(uint64_t freq){
    _timer_frequency = freq;

    logging::logf(logging::log_level::DEBUG, "timer: Frequency set to %u Hz\n", freq);
}
<|endoftext|>