<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2015 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "libmesh/libmesh_config.h"
#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS

// Local includes cont'd
#include "libmesh/face_inf_quad4.h"
#include "libmesh/fe_interface.h"
#include "libmesh/fe_type.h"
#include "libmesh/side.h"
#include "libmesh/edge_edge2.h"
#include "libmesh/edge_inf_edge2.h"

namespace libMesh
{

// ------------------------------------------------------------
// InfQuad4 class static member initializations
const unsigned int InfQuad4::side_nodes_map[3][2] =
  {
    {0, 1}, // Side 0
    {1, 3}, // Side 1
    {0, 2}  // Side 2
  };

#ifdef LIBMESH_ENABLE_AMR

const float InfQuad4::_embedding_matrix[2][4][4] =
  {
    // embedding matrix for child 0
    {
      // 0    1    2    3rd parent node
      {1.0, 0.0, 0.0, 0.0}, // 0th child node
      {0.5, 0.5, 0.0, 0.0}, // 1
      {0.0, 0.0, 1.0, 0.0}, // 2
      {0.0, 0.0, 0.5, 0.5}  // 3
    },

    // embedding matrix for child 1
    {
      // 0    1    2    3
      {0.5, 0.5, 0.0, 0.0}, // 0
      {0.0, 1.0, 0.0, 0.0}, // 1
      {0.0, 0.0, 0.5, 0.5}, // 2
      {0.0, 0.0, 0.0, 1.0}  // 3
    }
  };

#endif

// ------------------------------------------------------------
// InfQuad4 class member functions

bool InfQuad4::is_vertex(const unsigned int i) const
{
  if (i < 2)
    return true;
  return false;
}

bool InfQuad4::is_edge(const unsigned int i) const
{
  if (i < 2)
    return false;
  return true;
}

bool InfQuad4::is_face(const unsigned int) const
{
  return false;
}

bool InfQuad4::is_node_on_side(const unsigned int n,
                               const unsigned int s) const
{
  libmesh_assert_less (s, n_sides());
  for (unsigned int i = 0; i != 2; ++i)
    if (side_nodes_map[s][i] == n)
      return true;
  return false;
}

bool InfQuad4::contains_point (const Point& p, Real tol) const
{
  /*
   * make use of the fact that infinite elements do not
   * live inside the envelope.  Use a fast scheme to
   * check whether point \p p is inside or outside
   * our relevant part of the envelope.  Note that
   * this is not exclusive: the point may be outside
   * the envelope, but contained in another infinite element.
   * Therefore, if the distance is greater, do fall back
   * to the scheme of using FEInterface::inverse_map().
   */
  const Point my_origin (this->origin());

  /*
   * determine the minimal distance of the base from the origin
   * use size_sq() instead of size(), it is slightly faster
   */
  const Real min_distance_sq = std::min((Point(this->point(0)-my_origin)).size_sq(),
                                        (Point(this->point(1)-my_origin)).size_sq());

  /*
   * work with 1% allowable deviation.  Can still fall
   * back to the InfFE::inverse_map()
   */
  const Real conservative_p_dist_sq = 1.01 * (Point(p-my_origin).size_sq());

  if (conservative_p_dist_sq < min_distance_sq)
    {
      /*
       * the physical point is definitely not contained
       * in the element, return false.
       */
      return false;
    }
  else
    {
      /*
       * cannot say anything, fall back to the FEInterface::inverse_map()
       *
       * Declare a basic FEType.  Will use default in the base,
       * and something else (not important) in radial direction.
       */
      FEType fe_type(default_order());

      const Point mapped_point = FEInterface::inverse_map(dim(),
                                                          fe_type,
                                                          this,
                                                          p,
                                                          tol,
                                                          false);

      return FEInterface::on_reference_element(mapped_point, this->type(), tol);
    }
}

UniquePtr<Elem> InfQuad4::build_side (const unsigned int i,
                                      bool proxy) const
{
  // libmesh_assert_less (i, this->n_sides());

  if (proxy)
    {
      switch (i)
        {
          // base
        case 0:
          return UniquePtr<Elem>(new Side<Edge2,InfQuad4>(this,i));

          // ifem edges
        case 1:
        case 2:
          return UniquePtr<Elem>(new Side<InfEdge2,InfQuad4>(this,i));

        default:
          libmesh_error_msg("Invalid side i = " << i);
        }
    }

  else
    {
      // Create NULL pointer to be initialized, returned later.
      Elem* edge = NULL;

      switch (i)
        {
        case 0:
          {
            edge = new Edge2;
            edge->set_node(0) = this->get_node(0);
            edge->set_node(1) = this->get_node(1);
            break;
          }

        case 1:
          {
            // adjacent to another infinite element
            edge = new InfEdge2;
            edge->set_node(0) = this->get_node(1);
            edge->set_node(1) = this->get_node(3);
            break;
          }

        case 2:
          {
            // adjacent to another infinite element
            edge = new InfEdge2;
            edge->set_node(0) = this->get_node(0);
            edge->set_node(1) = this->get_node(2);
            break;
          }
        default:
          libmesh_error_msg("Invalid side i = " << i);
        }

      edge->subdomain_id() = this->subdomain_id();
      return UniquePtr<Elem>(edge);
    }

  libmesh_error_msg("We'll never get here!");
  return UniquePtr<Elem>();
}

void InfQuad4::connectivity(const unsigned int libmesh_dbg_var(sf),
                            const IOPackage iop,
                            std::vector<dof_id_type>& conn) const
{
  libmesh_assert_less (sf, this->n_sub_elem());
  libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);

  conn.resize(4);

  switch (iop)
    {
    case TECPLOT:
      {
        conn[0] = this->node(0)+1;
        conn[1] = this->node(1)+1;
        conn[2] = this->node(3)+1;
        conn[3] = this->node(2)+1;
        return;
      }
    case VTK:
      {
        conn[0] = this->node(0);
        conn[1] = this->node(1);
        conn[2] = this->node(3);
        conn[3] = this->node(2);
      }
    default:
      libmesh_error_msg("Unsupported IO package " << iop);
    }
}

} // namespace libMesh

#endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
<commit_msg>Refactor InfQuad4::build_side()<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2015 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "libmesh/libmesh_config.h"
#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS

// Local includes cont'd
#include "libmesh/face_inf_quad4.h"
#include "libmesh/fe_interface.h"
#include "libmesh/fe_type.h"
#include "libmesh/side.h"
#include "libmesh/edge_edge2.h"
#include "libmesh/edge_inf_edge2.h"

namespace libMesh
{

// ------------------------------------------------------------
// InfQuad4 class static member initializations
const unsigned int InfQuad4::side_nodes_map[3][2] =
  {
    {0, 1}, // Side 0
    {1, 3}, // Side 1
    {0, 2}  // Side 2
  };

#ifdef LIBMESH_ENABLE_AMR

const float InfQuad4::_embedding_matrix[2][4][4] =
  {
    // embedding matrix for child 0
    {
      // 0    1    2    3rd parent node
      {1.0, 0.0, 0.0, 0.0}, // 0th child node
      {0.5, 0.5, 0.0, 0.0}, // 1
      {0.0, 0.0, 1.0, 0.0}, // 2
      {0.0, 0.0, 0.5, 0.5}  // 3
    },

    // embedding matrix for child 1
    {
      // 0    1    2    3
      {0.5, 0.5, 0.0, 0.0}, // 0
      {0.0, 1.0, 0.0, 0.0}, // 1
      {0.0, 0.0, 0.5, 0.5}, // 2
      {0.0, 0.0, 0.0, 1.0}  // 3
    }
  };

#endif

// ------------------------------------------------------------
// InfQuad4 class member functions

bool InfQuad4::is_vertex(const unsigned int i) const
{
  if (i < 2)
    return true;
  return false;
}

bool InfQuad4::is_edge(const unsigned int i) const
{
  if (i < 2)
    return false;
  return true;
}

bool InfQuad4::is_face(const unsigned int) const
{
  return false;
}

bool InfQuad4::is_node_on_side(const unsigned int n,
                               const unsigned int s) const
{
  libmesh_assert_less (s, n_sides());
  for (unsigned int i = 0; i != 2; ++i)
    if (side_nodes_map[s][i] == n)
      return true;
  return false;
}

bool InfQuad4::contains_point (const Point& p, Real tol) const
{
  /*
   * make use of the fact that infinite elements do not
   * live inside the envelope.  Use a fast scheme to
   * check whether point \p p is inside or outside
   * our relevant part of the envelope.  Note that
   * this is not exclusive: the point may be outside
   * the envelope, but contained in another infinite element.
   * Therefore, if the distance is greater, do fall back
   * to the scheme of using FEInterface::inverse_map().
   */
  const Point my_origin (this->origin());

  /*
   * determine the minimal distance of the base from the origin
   * use size_sq() instead of size(), it is slightly faster
   */
  const Real min_distance_sq = std::min((Point(this->point(0)-my_origin)).size_sq(),
                                        (Point(this->point(1)-my_origin)).size_sq());

  /*
   * work with 1% allowable deviation.  Can still fall
   * back to the InfFE::inverse_map()
   */
  const Real conservative_p_dist_sq = 1.01 * (Point(p-my_origin).size_sq());

  if (conservative_p_dist_sq < min_distance_sq)
    {
      /*
       * the physical point is definitely not contained
       * in the element, return false.
       */
      return false;
    }
  else
    {
      /*
       * cannot say anything, fall back to the FEInterface::inverse_map()
       *
       * Declare a basic FEType.  Will use default in the base,
       * and something else (not important) in radial direction.
       */
      FEType fe_type(default_order());

      const Point mapped_point = FEInterface::inverse_map(dim(),
                                                          fe_type,
                                                          this,
                                                          p,
                                                          tol,
                                                          false);

      return FEInterface::on_reference_element(mapped_point, this->type(), tol);
    }
}

UniquePtr<Elem> InfQuad4::build_side (const unsigned int i,
                                      bool proxy) const
{
  // libmesh_assert_less (i, this->n_sides());

  if (proxy)
    {
      switch (i)
        {
          // base
        case 0:
          return UniquePtr<Elem>(new Side<Edge2,InfQuad4>(this,i));

          // ifem edges
        case 1:
        case 2:
          return UniquePtr<Elem>(new Side<InfEdge2,InfQuad4>(this,i));

        default:
          libmesh_error_msg("Invalid side i = " << i);
        }
    }

  else
    {
      // Create NULL pointer to be initialized, returned later.
      Elem* edge = NULL;

      switch (i)
        {
        case 0:
          {
            edge = new Edge2;
            break;
          }

          // adjacent to another infinite element
        case 1:
        case 2:
          {
            edge = new InfEdge2;
            break;
          }

        default:
          libmesh_error_msg("Invalid side i = " << i);
        }

      edge->subdomain_id() = this->subdomain_id();

      // Set the nodes
      for (unsigned n=0; n<edge->n_nodes(); ++n)
        edge->set_node(n) = this->get_node(InfQuad4::side_nodes_map[i][n]);

      return UniquePtr<Elem>(edge);
    }

  libmesh_error_msg("We'll never get here!");
  return UniquePtr<Elem>();
}

void InfQuad4::connectivity(const unsigned int libmesh_dbg_var(sf),
                            const IOPackage iop,
                            std::vector<dof_id_type>& conn) const
{
  libmesh_assert_less (sf, this->n_sub_elem());
  libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);

  conn.resize(4);

  switch (iop)
    {
    case TECPLOT:
      {
        conn[0] = this->node(0)+1;
        conn[1] = this->node(1)+1;
        conn[2] = this->node(3)+1;
        conn[3] = this->node(2)+1;
        return;
      }
    case VTK:
      {
        conn[0] = this->node(0);
        conn[1] = this->node(1);
        conn[2] = this->node(3);
        conn[3] = this->node(2);
      }
    default:
      libmesh_error_msg("Unsupported IO package " << iop);
    }
}

} // namespace libMesh

#endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
<|endoftext|>


<commit_before>/******************************************************************************

    SDL Rectangle Primitive

  Copyright (c) 2013 Jeffrey Carpenter
  All rights reserved.

******************************************************************************/
#include "SDL_Rectangle.hpp"

nom::Rectangle::Rectangle ( void )
{
  this->coords = nom::Coords ( 0, 0, 0, 0 );
  this->color = nom::Color ( 0, 0, 0 );
}

nom::Rectangle::~Rectangle ( void )
{
  // ...
}

// Constructor variant for creating a rectangle from an existing type
// This is a "shallow" copy assignment
nom::Rectangle::Rectangle ( const nom::Rectangle& rect )
{
  this->coords = rect.coords;
  this->color = rect.color;
}

nom::Rectangle::Rectangle ( const nom::Coords& coords, const nom::Color& color )
{
  this->coords = coords;
  this->color = color;
}

void nom::Rectangle::Update ( void )
{
  // Stub
}

void nom::Rectangle::Draw ( void* video_buffer ) const
{
  SDL_Rect rectangle = getSDL_Rect ( this->coords );
  unsigned int rectangle_color = 0;
  SDL_Surface *buffer = static_cast<SDL_Surface*> ( video_buffer );

  rectangle_color = getColorAsInt ( buffer->format, this->color );

  if ( SDL_FillRect ( buffer, &rectangle, rectangle_color ) != 0 )
  {
NOMLIB_LOG_ERR ( SDL_GetError() );
    return;
  }

  // Destruct as soon as we are done to free memory
  // that could otherwise be held too long before
  // cleaned up, resulting in slow, but steady climb
  // in memory usage
  Rectangle::~Rectangle();
}
<commit_msg>Add fix for Linux GCC compile<commit_after>/******************************************************************************

    SDL Rectangle Primitive

  Copyright (c) 2013 Jeffrey Carpenter
  All rights reserved.

******************************************************************************/
#include "SDL_Rectangle.hpp"

nom::Rectangle::Rectangle ( void )
{
  this->coords = nom::Coords ( 0, 0, 0, 0 );
  this->color = nom::Color ( 0, 0, 0 );
}

nom::Rectangle::~Rectangle ( void )
{
  // ...
}

// Constructor variant for creating a rectangle from an existing type
// This is a "shallow" copy assignment
nom::Rectangle::Rectangle ( const nom::Rectangle& rect )
{
  this->coords = rect.coords;
  this->color = rect.color;
}

nom::Rectangle::Rectangle ( const nom::Coords& coords, const nom::Color& color )
{
  this->coords = coords;
  this->color = color;
}

void nom::Rectangle::Update ( void )
{
  // Stub
}

void nom::Rectangle::Draw ( void* video_buffer ) const
{
  SDL_Rect rectangle = getSDL_Rect ( this->coords );
  unsigned int rectangle_color = 0;
  SDL_Surface *buffer = static_cast<SDL_Surface*> ( video_buffer );

  rectangle_color = getColorAsInt ( buffer->format, this->color );

  if ( SDL_FillRect ( buffer, &rectangle, rectangle_color ) != 0 )
  {
NOMLIB_LOG_ERR ( SDL_GetError() );
    return;
  }

  // Destruct as soon as we are done to free memory
  // that could otherwise be held too long before
  // cleaned up, resulting in slow, but steady climb
  // in memory usage
#ifndef NOMLIB_SYSTEM_LINUX
  Rectangle::~Rectangle();
#endif
}
<|endoftext|>


<commit_before>#include "x_client_thumbnail_gl.hpp"

#include <xcb/composite.h>
#include <xcb/xcb_renderutil.h>

x_client_thumbnail::x_client_thumbnail(x_connection & c,
                                       const rectangle & rect,
                                       const xcb_window_t & window,
                                       std::shared_ptr<x_client> xclient)
      : _c(c)
{
  if (window == XCB_NONE && xclient == NULL) {
    throw std::invalid_argument(
        "x_client_thumbnail requires either window or xclient parameter");
  } else if (xclient == NULL) {
    _x_client = x_client_ptr(new x_client(_c, window));
  } else {
    _x_client = xclient;
  }

  update_rectangle(rect);

  _c.register_handler(_c.damage_event_id(), this);
  _c.register_handler(XCB_CONFIGURE_NOTIFY, this);

  _damage = xcb_generate_id(_c());

  configure_parent_pixmap();

  _thumbnail_window = xcb_generate_id(_c());
  xcb_colormap_t colormap = xcb_generate_id(_c());

  GLint gl_vi_attr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
  XVisualInfo * vi =
    glXChooseVisual(_c.dpy(), DefaultScreen(_c.dpy()), gl_vi_attr);

  xcb_create_colormap(_c(), XCB_COLORMAP_ALLOC_NONE, colormap,
                      _c.root_window(), vi->visualid);

  uint32_t valuemask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_COLORMAP;
  uint32_t valuelist[] = { 1, colormap, 0 };
  xcb_create_window(_c(), XCB_COPY_FROM_PARENT, _thumbnail_window,
                    _c.root_window(), 0, 0,
                    _x_client->rect().width(), _x_client->rect().height(),
                    0, XCB_WINDOW_CLASS_INPUT_OUTPUT, vi->visualid,
                    valuemask, valuelist);

  xcb_free_colormap(_c(), colormap);

  configure_gl(vi);
  init_gl_shader();
  delete vi;

  update();
}

x_client_thumbnail::~x_client_thumbnail(void)
{
  _c.deregister_handler(_c.damage_event_id(), this);
  _c.deregister_handler(XCB_CONFIGURE_NOTIFY, this);
  release_gl();
  xcb_free_pixmap(_c(), _parent_pixmap);
  xcb_destroy_window(_c(), _thumbnail_window);
}

void
x_client_thumbnail::show(void)
{
  xcb_damage_create(_c(), _damage, _x_client->window(),
                    XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY);
  configure_thumbnail_window();
  update();
}

void
x_client_thumbnail::hide(void)
{
  xcb_damage_destroy(_c(), _damage);
  xcb_unmap_window(_c(), _thumbnail_window);
}

void
x_client_thumbnail::select(void)
{
  _c.request_change_current_desktop(_x_client->net_wm_desktop());
  _c.request_change_active_window(_x_client->window());
}

void
x_client_thumbnail::update(void)
{
  update(0, 0, _rectangle.width(), _rectangle.height());
}

void
x_client_thumbnail::update(int x, int y, unsigned int width, unsigned int height)
{
  glXMakeCurrent(_c.dpy(), _thumbnail_window, _gl_ctx);

  glViewport(0, 0, _rectangle.width(), _rectangle.height());
  glClearColor(0.0, 0.0, 0.0, 1.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glBegin(GL_QUADS);
  glTexCoord2f(0.0, 0.0); glVertex3f(-1.0,  1.0, 0.0);
  glTexCoord2f(1.0, 0.0); glVertex3f( 1.0,  1.0, 0.0);
  glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, -1.0, 0.0);
  glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, -1.0, 0.0);
  glEnd();

  glXSwapBuffers(_c.dpy(), _thumbnail_window);
  glXMakeCurrent(_c.dpy(), XCB_NONE, NULL);
}

void
x_client_thumbnail::highlight(bool want_highlight)
{
  glXMakeCurrent(_c.dpy(), _thumbnail_window, _gl_ctx);
  if (want_highlight) {
    _c.glUseProgram(0);
  } else {
    _c.glUseProgram(_programs["grayscale_shader"]);
  }
  glXMakeCurrent(_c.dpy(), XCB_NONE, NULL);

  update();
}

bool
x_client_thumbnail::handle(xcb_generic_event_t * ge)
{
  bool result = false;
  if (_c.damage_event_id() == (ge->response_type & ~0x80)) {
    xcb_damage_notify_event_t * e = (xcb_damage_notify_event_t *)ge;
    xcb_damage_subtract(_c(), e->damage, XCB_NONE, XCB_NONE);
    update(e->area.x * _scale, e->area.y * _scale,
           e->area.width * _scale, e->area.height * _scale);
    result = true;

  } else if (XCB_CONFIGURE_NOTIFY == (ge->response_type & ~0x80)) {
    xcb_configure_notify_event_t * e = (xcb_configure_notify_event_t *)ge;
    if (e->window == _c.root_window()) {
      configure_parent_pixmap();
      release_gl();
      configure_gl();
      update();
    }
    result = true;
  }

  return result;
}

void
x_client_thumbnail::update_rectangle(const rectangle & rect)
{
  _scale = std::min((double)rect.width() / _x_client->rect().width(),
                    (double)rect.height() / _x_client->rect().height());
  _scale = std::min(1.0, _scale);

  _rectangle.x() = rect.x();
  _rectangle.y() = rect.y();
  _rectangle.width() = _x_client->rect().width() * _scale;
  _rectangle.height() = _x_client->rect().height() * _scale;
}

void
x_client_thumbnail::configure_thumbnail_window(void)
{
  uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y
                | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT
                | XCB_CONFIG_WINDOW_STACK_MODE;

  uint32_t values[] = { (uint32_t)_rectangle.x(),
                        (uint32_t)_rectangle.y(),
                        (uint32_t)_rectangle.width(),
                        (uint32_t)_rectangle.height(),
                        XCB_STACK_MODE_ABOVE };

  xcb_configure_window(_c(), _thumbnail_window, mask, values);
  xcb_map_window(_c(), _thumbnail_window);
}

void
x_client_thumbnail::configure_parent_pixmap(void)
{
  xcb_free_pixmap(_c(), _parent_pixmap);
  _parent_pixmap = xcb_generate_id(_c());
  xcb_composite_name_window_pixmap(_c(), _x_client->window(), _parent_pixmap);
}

void
x_client_thumbnail::configure_gl(XVisualInfo * vi)
{
  const int pixmap_config[] = {
    GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
    GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
    GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
    GLX_DOUBLEBUFFER, False,
    GLX_Y_INVERTED_EXT,
    None
  };

  const int pixmap_attr[] = {
    GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
    GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
    None
  };

  auto create_ctx = [this, &vi]()
  {
    _gl_ctx = glXCreateContext(_c.dpy(), vi, NULL, GL_TRUE);
  };

  if (vi == NULL) {
    GLint gl_vi_attr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
    vi = glXChooseVisual(_c.dpy(), DefaultScreen(_c.dpy()), gl_vi_attr);
    create_ctx();
    delete vi;
  } else {
    create_ctx();
  }

  glXMakeCurrent(_c.dpy(), _thumbnail_window, _gl_ctx);

  int config = 0;
  GLXFBConfig * _gl_configs =
    glXChooseFBConfig(_c.dpy(), 0, pixmap_config, &config);
  _thumbnail_gl_pixmap =
      glXCreatePixmap(_c.dpy(), _gl_configs[0], _parent_pixmap, pixmap_attr);
  delete _gl_configs;

  GLuint _thumbnail_gl_texture_id;
  glEnable(GL_TEXTURE_2D);
  glGenTextures(1, &_thumbnail_gl_texture_id);
  glBindTexture(GL_TEXTURE_2D, _thumbnail_gl_texture_id);
  _c.glXBindTexImageEXT(_c.dpy(), _thumbnail_gl_pixmap, GLX_FRONT_EXT, NULL);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

  glXMakeCurrent(_c.dpy(), XCB_NONE, NULL);
}

void
x_client_thumbnail::init_gl_shader(void)
{
  std::string shader_name = "grayscale_shader";
  std::ifstream file("./grayscale.frag");
  std::string shader_source_str((std::istreambuf_iterator<char>(file)),
                                 std::istreambuf_iterator<char>());
  file.close();

  const GLchar * shader_source[]  = { shader_source_str.c_str() };
  const GLint shader_source_len[] = { (GLint)(shader_source_str.length()) };

  GLsizei log_length = 0, max_len = 1024;
  GLchar log_buffer[max_len];

  glXMakeCurrent(_c.dpy(), _thumbnail_window, _gl_ctx);

  GLuint shader = _c.glCreateShader(GL_FRAGMENT_SHADER);
  _c.glShaderSource(shader, 1, shader_source, shader_source_len);
  _c.glCompileShader(shader);

  _c.glGetShaderInfoLog(shader, max_len, &log_length, log_buffer);
  if (log_length > 0) {
    std::cerr << "Shader compilation failed:" << std::endl
              << log_buffer << std::endl;
  }

  _programs[shader_name] = _c.glCreateProgram();
  _c.glAttachShader(_programs[shader_name], shader);
  _c.glLinkProgram(_programs[shader_name]);
  _c.glUseProgram(_programs[shader_name]);

  _c.glGetProgramInfoLog(_programs[shader_name],
                         max_len, &log_length, log_buffer);
  if (log_length > 0) {
    std::cerr << "Program creation failed:" << std::endl
              << log_buffer << std::endl;
  }

  glXMakeCurrent(_c.dpy(), XCB_NONE, NULL);
}

void
x_client_thumbnail::release_gl(void)
{
  glXMakeCurrent(_c.dpy(), _thumbnail_window, _gl_ctx);
  _c.glXReleaseTexImageEXT(_c.dpy(), _thumbnail_gl_pixmap, GLX_FRONT_EXT);
  glXDestroyContext(_c.dpy(), _gl_ctx);
  glXMakeCurrent(_c.dpy(), None, NULL);
}

bool operator==(const x_client_thumbnail & thumbnail, const xcb_window_t & window)
{
  return *(thumbnail._x_client) == window;
}

bool operator==(const xcb_window_t & window, const x_client_thumbnail & thumbnail)
{
  return thumbnail == window;
}
<commit_msg>Initialize gl shaders after gl context got purged<commit_after>#include "x_client_thumbnail_gl.hpp"

#include <xcb/composite.h>
#include <xcb/xcb_renderutil.h>

x_client_thumbnail::x_client_thumbnail(x_connection & c,
                                       const rectangle & rect,
                                       const xcb_window_t & window,
                                       std::shared_ptr<x_client> xclient)
      : _c(c)
{
  if (window == XCB_NONE && xclient == NULL) {
    throw std::invalid_argument(
        "x_client_thumbnail requires either window or xclient parameter");
  } else if (xclient == NULL) {
    _x_client = x_client_ptr(new x_client(_c, window));
  } else {
    _x_client = xclient;
  }

  update_rectangle(rect);

  _c.register_handler(_c.damage_event_id(), this);
  _c.register_handler(XCB_CONFIGURE_NOTIFY, this);

  _damage = xcb_generate_id(_c());

  configure_parent_pixmap();

  _thumbnail_window = xcb_generate_id(_c());
  xcb_colormap_t colormap = xcb_generate_id(_c());

  GLint gl_vi_attr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
  XVisualInfo * vi =
    glXChooseVisual(_c.dpy(), DefaultScreen(_c.dpy()), gl_vi_attr);

  xcb_create_colormap(_c(), XCB_COLORMAP_ALLOC_NONE, colormap,
                      _c.root_window(), vi->visualid);

  uint32_t valuemask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_COLORMAP;
  uint32_t valuelist[] = { 1, colormap, 0 };
  xcb_create_window(_c(), XCB_COPY_FROM_PARENT, _thumbnail_window,
                    _c.root_window(), 0, 0,
                    _x_client->rect().width(), _x_client->rect().height(),
                    0, XCB_WINDOW_CLASS_INPUT_OUTPUT, vi->visualid,
                    valuemask, valuelist);

  xcb_free_colormap(_c(), colormap);

  configure_gl(vi);
  init_gl_shader();
  delete vi;

  update();
}

x_client_thumbnail::~x_client_thumbnail(void)
{
  _c.deregister_handler(_c.damage_event_id(), this);
  _c.deregister_handler(XCB_CONFIGURE_NOTIFY, this);
  release_gl();
  xcb_free_pixmap(_c(), _parent_pixmap);
  xcb_destroy_window(_c(), _thumbnail_window);
}

void
x_client_thumbnail::show(void)
{
  xcb_damage_create(_c(), _damage, _x_client->window(),
                    XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY);
  configure_thumbnail_window();
  update();
}

void
x_client_thumbnail::hide(void)
{
  xcb_damage_destroy(_c(), _damage);
  xcb_unmap_window(_c(), _thumbnail_window);
}

void
x_client_thumbnail::select(void)
{
  _c.request_change_current_desktop(_x_client->net_wm_desktop());
  _c.request_change_active_window(_x_client->window());
}

void
x_client_thumbnail::update(void)
{
  update(0, 0, _rectangle.width(), _rectangle.height());
}

void
x_client_thumbnail::update(int x, int y, unsigned int width, unsigned int height)
{
  glXMakeCurrent(_c.dpy(), _thumbnail_window, _gl_ctx);

  glViewport(0, 0, _rectangle.width(), _rectangle.height());
  glClearColor(0.0, 0.0, 0.0, 1.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glBegin(GL_QUADS);
  glTexCoord2f(0.0, 0.0); glVertex3f(-1.0,  1.0, 0.0);
  glTexCoord2f(1.0, 0.0); glVertex3f( 1.0,  1.0, 0.0);
  glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, -1.0, 0.0);
  glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, -1.0, 0.0);
  glEnd();

  glXSwapBuffers(_c.dpy(), _thumbnail_window);
  glXMakeCurrent(_c.dpy(), XCB_NONE, NULL);
}

void
x_client_thumbnail::highlight(bool want_highlight)
{
  glXMakeCurrent(_c.dpy(), _thumbnail_window, _gl_ctx);
  if (want_highlight) {
    _c.glUseProgram(0);
  } else {
    _c.glUseProgram(_programs["grayscale_shader"]);
  }
  glXMakeCurrent(_c.dpy(), XCB_NONE, NULL);

  update();
}

bool
x_client_thumbnail::handle(xcb_generic_event_t * ge)
{
  bool result = false;
  if (_c.damage_event_id() == (ge->response_type & ~0x80)) {
    xcb_damage_notify_event_t * e = (xcb_damage_notify_event_t *)ge;
    xcb_damage_subtract(_c(), e->damage, XCB_NONE, XCB_NONE);
    update(e->area.x * _scale, e->area.y * _scale,
           e->area.width * _scale, e->area.height * _scale);
    result = true;

  } else if (XCB_CONFIGURE_NOTIFY == (ge->response_type & ~0x80)) {
    xcb_configure_notify_event_t * e = (xcb_configure_notify_event_t *)ge;
    if (e->window == _c.root_window()) {
      configure_parent_pixmap();
      release_gl();
      configure_gl();
      init_gl_shader();
      update();
    }
    result = true;
  }

  return result;
}

void
x_client_thumbnail::update_rectangle(const rectangle & rect)
{
  _scale = std::min((double)rect.width() / _x_client->rect().width(),
                    (double)rect.height() / _x_client->rect().height());
  _scale = std::min(1.0, _scale);

  _rectangle.x() = rect.x();
  _rectangle.y() = rect.y();
  _rectangle.width() = _x_client->rect().width() * _scale;
  _rectangle.height() = _x_client->rect().height() * _scale;
}

void
x_client_thumbnail::configure_thumbnail_window(void)
{
  uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y
                | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT
                | XCB_CONFIG_WINDOW_STACK_MODE;

  uint32_t values[] = { (uint32_t)_rectangle.x(),
                        (uint32_t)_rectangle.y(),
                        (uint32_t)_rectangle.width(),
                        (uint32_t)_rectangle.height(),
                        XCB_STACK_MODE_ABOVE };

  xcb_configure_window(_c(), _thumbnail_window, mask, values);
  xcb_map_window(_c(), _thumbnail_window);
}

void
x_client_thumbnail::configure_parent_pixmap(void)
{
  xcb_free_pixmap(_c(), _parent_pixmap);
  _parent_pixmap = xcb_generate_id(_c());
  xcb_composite_name_window_pixmap(_c(), _x_client->window(), _parent_pixmap);
}

void
x_client_thumbnail::configure_gl(XVisualInfo * vi)
{
  const int pixmap_config[] = {
    GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
    GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
    GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
    GLX_DOUBLEBUFFER, False,
    GLX_Y_INVERTED_EXT,
    None
  };

  const int pixmap_attr[] = {
    GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
    GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
    None
  };

  auto create_ctx = [this, &vi]()
  {
    _gl_ctx = glXCreateContext(_c.dpy(), vi, NULL, GL_TRUE);
  };

  if (vi == NULL) {
    GLint gl_vi_attr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
    vi = glXChooseVisual(_c.dpy(), DefaultScreen(_c.dpy()), gl_vi_attr);
    create_ctx();
    delete vi;
  } else {
    create_ctx();
  }

  glXMakeCurrent(_c.dpy(), _thumbnail_window, _gl_ctx);

  int config = 0;
  GLXFBConfig * _gl_configs =
    glXChooseFBConfig(_c.dpy(), 0, pixmap_config, &config);
  _thumbnail_gl_pixmap =
      glXCreatePixmap(_c.dpy(), _gl_configs[0], _parent_pixmap, pixmap_attr);
  delete _gl_configs;

  GLuint _thumbnail_gl_texture_id;
  glEnable(GL_TEXTURE_2D);
  glGenTextures(1, &_thumbnail_gl_texture_id);
  glBindTexture(GL_TEXTURE_2D, _thumbnail_gl_texture_id);
  _c.glXBindTexImageEXT(_c.dpy(), _thumbnail_gl_pixmap, GLX_FRONT_EXT, NULL);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

  glXMakeCurrent(_c.dpy(), XCB_NONE, NULL);
}

void
x_client_thumbnail::init_gl_shader(void)
{
  std::string shader_name = "grayscale_shader";
  std::ifstream file("./grayscale.frag");
  std::string shader_source_str((std::istreambuf_iterator<char>(file)),
                                 std::istreambuf_iterator<char>());
  file.close();

  const GLchar * shader_source[]  = { shader_source_str.c_str() };
  const GLint shader_source_len[] = { (GLint)(shader_source_str.length()) };

  GLsizei log_length = 0, max_len = 1024;
  GLchar log_buffer[max_len];

  glXMakeCurrent(_c.dpy(), _thumbnail_window, _gl_ctx);

  GLuint shader = _c.glCreateShader(GL_FRAGMENT_SHADER);
  _c.glShaderSource(shader, 1, shader_source, shader_source_len);
  _c.glCompileShader(shader);

  _c.glGetShaderInfoLog(shader, max_len, &log_length, log_buffer);
  if (log_length > 0) {
    std::cerr << "Shader compilation failed:" << std::endl
              << log_buffer << std::endl;
  }

  _programs[shader_name] = _c.glCreateProgram();
  _c.glAttachShader(_programs[shader_name], shader);
  _c.glLinkProgram(_programs[shader_name]);
  _c.glUseProgram(_programs[shader_name]);

  _c.glGetProgramInfoLog(_programs[shader_name],
                         max_len, &log_length, log_buffer);
  if (log_length > 0) {
    std::cerr << "Program creation failed:" << std::endl
              << log_buffer << std::endl;
  }

  glXMakeCurrent(_c.dpy(), XCB_NONE, NULL);
}

void
x_client_thumbnail::release_gl(void)
{
  glXMakeCurrent(_c.dpy(), _thumbnail_window, _gl_ctx);
  _c.glXReleaseTexImageEXT(_c.dpy(), _thumbnail_gl_pixmap, GLX_FRONT_EXT);
  glXDestroyContext(_c.dpy(), _gl_ctx);
  glXMakeCurrent(_c.dpy(), None, NULL);
}

bool operator==(const x_client_thumbnail & thumbnail, const xcb_window_t & window)
{
  return *(thumbnail._x_client) == window;
}

bool operator==(const xcb_window_t & window, const x_client_thumbnail & thumbnail)
{
  return thumbnail == window;
}
<|endoftext|>


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

#include "unotools/accessiblestatesethelper.hxx"

#ifndef _RTL_UUID_H_
#include <rtl/uuid.h>
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#include <bitset>

// defines how many states the bitfield can contain
#define BITFIELDSIZE 30

using namespace ::utl;
using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::drafts::com::sun::star::accessibility;

class AccessibleStateSetHelperImpl
{
public:
    AccessibleStateSetHelperImpl();
    AccessibleStateSetHelperImpl(const AccessibleStateSetHelperImpl& rImpl);
    ~AccessibleStateSetHelperImpl();

    sal_Bool IsEmpty ()
        throw (uno::RuntimeException);
    sal_Bool Contains (sal_Int16 aState)
        throw (uno::RuntimeException);
    void AddState(sal_Int16 aState)
        throw (uno::RuntimeException);
    void RemoveState(sal_Int16 aState)
        throw (uno::RuntimeException);
    void Compare(const AccessibleStateSetHelperImpl* pComparativeValue,
                        AccessibleStateSetHelperImpl* pOldStates,
                        AccessibleStateSetHelperImpl* pNewStates)
        throw (uno::RuntimeException);

private:
    std::bitset<BITFIELDSIZE> maStates; //Bitfield
};

AccessibleStateSetHelperImpl::AccessibleStateSetHelperImpl()
{
}

AccessibleStateSetHelperImpl::AccessibleStateSetHelperImpl(const AccessibleStateSetHelperImpl& rImpl)
    : maStates(rImpl.maStates)
{
}

AccessibleStateSetHelperImpl::~AccessibleStateSetHelperImpl()
{
}

sal_Bool AccessibleStateSetHelperImpl::IsEmpty ()
    throw (uno::RuntimeException)
{
    return maStates.none();
}

sal_Bool AccessibleStateSetHelperImpl::Contains (sal_Int16 aState)
    throw (uno::RuntimeException)
{
    DBG_ASSERT(aState >= BITFIELDSIZE, "the statesset is to small")
    return maStates.test(aState);
}

void AccessibleStateSetHelperImpl::AddState(sal_Int16 aState)
    throw (uno::RuntimeException)
{
    DBG_ASSERT(aState >= BITFIELDSIZE, "the statesset is to small")
    maStates.set(aState);
}

void AccessibleStateSetHelperImpl::RemoveState(sal_Int16 aState)
    throw (uno::RuntimeException)
{
    DBG_ASSERT(aState >= BITFIELDSIZE, "the statesset is to small")
    maStates.set(aState, 0);
}

void AccessibleStateSetHelperImpl::Compare(
    const AccessibleStateSetHelperImpl* pComparativeValue,
        AccessibleStateSetHelperImpl* pOldStates,
        AccessibleStateSetHelperImpl* pNewStates)
    throw (uno::RuntimeException)
{
    if (pComparativeValue && pOldStates && pNewStates)
    {
        std::bitset<BITFIELDSIZE> aTempBitSet(maStates);
        aTempBitSet ^= pComparativeValue->maStates;
        pOldStates->maStates = aTempBitSet;
        pOldStates->maStates &= maStates;
        pNewStates->maStates = aTempBitSet;
        pNewStates->maStates &= pComparativeValue->maStates;
    }
}

//=====  internal  ============================================================

AccessibleStateSetHelper::AccessibleStateSetHelper ()
    : mpHelperImpl(NULL)
{
    mpHelperImpl = new AccessibleStateSetHelperImpl();
}

AccessibleStateSetHelper::AccessibleStateSetHelper (const AccessibleStateSetHelper& rHelper)
    : mpHelperImpl(NULL)
{
    if (rHelper.mpHelperImpl)
        mpHelperImpl = new AccessibleStateSetHelperImpl(*rHelper.mpHelperImpl);
    else
        mpHelperImpl = new AccessibleStateSetHelperImpl();
}

AccessibleStateSetHelper::~AccessibleStateSetHelper(void)
{
    delete mpHelperImpl;
}

//=====  XAccessibleStateSet  ==============================================

    /** Checks whether the current state set is empty.

        @return
            Returns <TRUE/> if there is no state in this state set and
            <FALSE/> if there is at least one state set in it.
    */
sal_Bool SAL_CALL AccessibleStateSetHelper::isEmpty ()
    throw (uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    return mpHelperImpl->IsEmpty();
}

    /** Checks if the given state is a member of the state set of this
        object.

        @param aState
            The state for which to check membership.  This has to be one of
            the constants of <type>AccessibleStateType</type>.

        @return
            Returns <TRUE/> if the given state is a memeber of this object's
            state set and <FALSE/> otherwise.
    */
sal_Bool SAL_CALL AccessibleStateSetHelper::contains (sal_Int16 aState)
    throw (uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    return mpHelperImpl->Contains(aState);
}

    /** Checks if all of the given states are in this object's state
        set.

        @param aStateSet
            This sequence of states is interpreted as set and every of its
            members, duplicates are ignored, is checked for membership in
            this object's state set.  Each state has to be one of the
            constants of <type>AccessibleStateType</type>.

        @return
            Returns <TRUE/> if all states of the given state set are members
            of this object's state set.  <FALSE/> is returned if at least
            one of the states in the given state is not a member of this
            object's state set.
    */
sal_Bool SAL_CALL AccessibleStateSetHelper::containsAll
    (const uno::Sequence<sal_Int16>& rStateSet)
    throw (uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    sal_Int32 nCount(rStateSet.getLength());
    const sal_Int16* pStates = rStateSet.getConstArray();
    sal_Int32 i = 0;
    sal_Bool bFound(sal_True);
    while (i < nCount)
    {
        bFound = mpHelperImpl->Contains(pStates[i]);
        i++;
    }
    return bFound;
}

void AccessibleStateSetHelper::AddState(sal_Int16 aState)
    throw (uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    mpHelperImpl->AddState(aState);
}

void AccessibleStateSetHelper::RemoveState(sal_Int16 aState)
    throw (uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    mpHelperImpl->RemoveState(aState);
}

void AccessibleStateSetHelper::Compare(
    const AccessibleStateSetHelper& rComparativeValue,
        AccessibleStateSetHelper& rOldStates,
        AccessibleStateSetHelper& rNewStates)
    throw (uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    mpHelperImpl->Compare(rComparativeValue.mpHelperImpl,
        rOldStates.mpHelperImpl, rNewStates.mpHelperImpl);
}

//=====  XTypeProvider  =======================================================

uno::Sequence< ::com::sun::star::uno::Type>
    AccessibleStateSetHelper::getTypes (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    const ::com::sun::star::uno::Type aTypeList[] = {
        ::getCppuType((const uno::Reference<
            XAccessibleStateSet>*)0),
        ::getCppuType((const uno::Reference<
            lang::XTypeProvider>*)0)
        };
    ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type>
        aTypeSequence (aTypeList, 2);
    return aTypeSequence;
}

uno::Sequence<sal_Int8> SAL_CALL
    AccessibleStateSetHelper::getImplementationId (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    static uno::Sequence<sal_Int8> aId;
    if (aId.getLength() == 0)
    {
        ::vos::OGuard aGuard (maMutex);
        aId.realloc (16);
        rtl_createUuid ((sal_uInt8 *)aId.getArray(), 0, sal_True);
    }
    return aId;
}
<commit_msg>#95584#; correct the assertion condition<commit_after>/*************************************************************************
 *
 *  $RCSfile: accessiblestatesethelper.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: sab $ $Date: 2002-02-21 12:43:12 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "unotools/accessiblestatesethelper.hxx"

#ifndef _RTL_UUID_H_
#include <rtl/uuid.h>
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#include <bitset>

// defines how many states the bitfield can contain
#define BITFIELDSIZE 30

using namespace ::utl;
using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::drafts::com::sun::star::accessibility;

class AccessibleStateSetHelperImpl
{
public:
    AccessibleStateSetHelperImpl();
    AccessibleStateSetHelperImpl(const AccessibleStateSetHelperImpl& rImpl);
    ~AccessibleStateSetHelperImpl();

    sal_Bool IsEmpty ()
        throw (uno::RuntimeException);
    sal_Bool Contains (sal_Int16 aState)
        throw (uno::RuntimeException);
    void AddState(sal_Int16 aState)
        throw (uno::RuntimeException);
    void RemoveState(sal_Int16 aState)
        throw (uno::RuntimeException);
    void Compare(const AccessibleStateSetHelperImpl* pComparativeValue,
                        AccessibleStateSetHelperImpl* pOldStates,
                        AccessibleStateSetHelperImpl* pNewStates)
        throw (uno::RuntimeException);

private:
    std::bitset<BITFIELDSIZE> maStates; //Bitfield
};

AccessibleStateSetHelperImpl::AccessibleStateSetHelperImpl()
{
}

AccessibleStateSetHelperImpl::AccessibleStateSetHelperImpl(const AccessibleStateSetHelperImpl& rImpl)
    : maStates(rImpl.maStates)
{
}

AccessibleStateSetHelperImpl::~AccessibleStateSetHelperImpl()
{
}

sal_Bool AccessibleStateSetHelperImpl::IsEmpty ()
    throw (uno::RuntimeException)
{
    return maStates.none();
}

sal_Bool AccessibleStateSetHelperImpl::Contains (sal_Int16 aState)
    throw (uno::RuntimeException)
{
    DBG_ASSERT(aState < BITFIELDSIZE, "the statesset is to small")
    return maStates.test(aState);
}

void AccessibleStateSetHelperImpl::AddState(sal_Int16 aState)
    throw (uno::RuntimeException)
{
    DBG_ASSERT(aState < BITFIELDSIZE, "the statesset is to small")
    maStates.set(aState);
}

void AccessibleStateSetHelperImpl::RemoveState(sal_Int16 aState)
    throw (uno::RuntimeException)
{
    DBG_ASSERT(aState < BITFIELDSIZE, "the statesset is to small")
    maStates.set(aState, 0);
}

void AccessibleStateSetHelperImpl::Compare(
    const AccessibleStateSetHelperImpl* pComparativeValue,
        AccessibleStateSetHelperImpl* pOldStates,
        AccessibleStateSetHelperImpl* pNewStates)
    throw (uno::RuntimeException)
{
    if (pComparativeValue && pOldStates && pNewStates)
    {
        std::bitset<BITFIELDSIZE> aTempBitSet(maStates);
        aTempBitSet ^= pComparativeValue->maStates;
        pOldStates->maStates = aTempBitSet;
        pOldStates->maStates &= maStates;
        pNewStates->maStates = aTempBitSet;
        pNewStates->maStates &= pComparativeValue->maStates;
    }
}

//=====  internal  ============================================================

AccessibleStateSetHelper::AccessibleStateSetHelper ()
    : mpHelperImpl(NULL)
{
    mpHelperImpl = new AccessibleStateSetHelperImpl();
}

AccessibleStateSetHelper::AccessibleStateSetHelper (const AccessibleStateSetHelper& rHelper)
    : mpHelperImpl(NULL)
{
    if (rHelper.mpHelperImpl)
        mpHelperImpl = new AccessibleStateSetHelperImpl(*rHelper.mpHelperImpl);
    else
        mpHelperImpl = new AccessibleStateSetHelperImpl();
}

AccessibleStateSetHelper::~AccessibleStateSetHelper(void)
{
    delete mpHelperImpl;
}

//=====  XAccessibleStateSet  ==============================================

    /** Checks whether the current state set is empty.

        @return
            Returns <TRUE/> if there is no state in this state set and
            <FALSE/> if there is at least one state set in it.
    */
sal_Bool SAL_CALL AccessibleStateSetHelper::isEmpty ()
    throw (uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    return mpHelperImpl->IsEmpty();
}

    /** Checks if the given state is a member of the state set of this
        object.

        @param aState
            The state for which to check membership.  This has to be one of
            the constants of <type>AccessibleStateType</type>.

        @return
            Returns <TRUE/> if the given state is a memeber of this object's
            state set and <FALSE/> otherwise.
    */
sal_Bool SAL_CALL AccessibleStateSetHelper::contains (sal_Int16 aState)
    throw (uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    return mpHelperImpl->Contains(aState);
}

    /** Checks if all of the given states are in this object's state
        set.

        @param aStateSet
            This sequence of states is interpreted as set and every of its
            members, duplicates are ignored, is checked for membership in
            this object's state set.  Each state has to be one of the
            constants of <type>AccessibleStateType</type>.

        @return
            Returns <TRUE/> if all states of the given state set are members
            of this object's state set.  <FALSE/> is returned if at least
            one of the states in the given state is not a member of this
            object's state set.
    */
sal_Bool SAL_CALL AccessibleStateSetHelper::containsAll
    (const uno::Sequence<sal_Int16>& rStateSet)
    throw (uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    sal_Int32 nCount(rStateSet.getLength());
    const sal_Int16* pStates = rStateSet.getConstArray();
    sal_Int32 i = 0;
    sal_Bool bFound(sal_True);
    while (i < nCount)
    {
        bFound = mpHelperImpl->Contains(pStates[i]);
        i++;
    }
    return bFound;
}

void AccessibleStateSetHelper::AddState(sal_Int16 aState)
    throw (uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    mpHelperImpl->AddState(aState);
}

void AccessibleStateSetHelper::RemoveState(sal_Int16 aState)
    throw (uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    mpHelperImpl->RemoveState(aState);
}

void AccessibleStateSetHelper::Compare(
    const AccessibleStateSetHelper& rComparativeValue,
        AccessibleStateSetHelper& rOldStates,
        AccessibleStateSetHelper& rNewStates)
    throw (uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    mpHelperImpl->Compare(rComparativeValue.mpHelperImpl,
        rOldStates.mpHelperImpl, rNewStates.mpHelperImpl);
}

//=====  XTypeProvider  =======================================================

uno::Sequence< ::com::sun::star::uno::Type>
    AccessibleStateSetHelper::getTypes (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    const ::com::sun::star::uno::Type aTypeList[] = {
        ::getCppuType((const uno::Reference<
            XAccessibleStateSet>*)0),
        ::getCppuType((const uno::Reference<
            lang::XTypeProvider>*)0)
        };
    ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type>
        aTypeSequence (aTypeList, 2);
    return aTypeSequence;
}

uno::Sequence<sal_Int8> SAL_CALL
    AccessibleStateSetHelper::getImplementationId (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard (maMutex);
    static uno::Sequence<sal_Int8> aId;
    if (aId.getLength() == 0)
    {
        ::vos::OGuard aGuard (maMutex);
        aId.realloc (16);
        rtl_createUuid ((sal_uInt8 *)aId.getArray(), 0, sal_True);
    }
    return aId;
}
<|endoftext|>


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

#ifndef VK_IMAGE_VIEW_HPP_
#define VK_IMAGE_VIEW_HPP_

#include "VkDebug.hpp"
#include "VkFormat.h"
#include "VkObject.hpp"
#include "VkImage.hpp"

namespace vk
{

class ImageView : public Object<ImageView, VkImageView>
{
public:
	ImageView(const VkImageViewCreateInfo* pCreateInfo, void* mem);
	~ImageView() = delete;
	void destroy(const VkAllocationCallbacks* pAllocator);

	static size_t ComputeRequiredAllocationSize(const VkImageViewCreateInfo* pCreateInfo);

	void clear(const VkClearValue& clearValues, VkImageAspectFlags aspectMask, const VkRect2D& renderArea);
	void clear(const VkClearValue& clearValue, VkImageAspectFlags aspectMask, const VkClearRect& renderArea);
	void resolve(ImageView* resolveAttachment);

	VkImageViewType getType() const { return viewType; }
	Format getFormat() const { return format; }
	int getSampleCount() const { return image->getSampleCountFlagBits(); }
	int rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const { return image->rowPitchBytes(aspect, subresourceRange.baseMipLevel + mipLevel); }
	int slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const { return image->slicePitchBytes(aspect, subresourceRange.baseMipLevel + mipLevel); }
	int layerPitchBytes(VkImageAspectFlagBits aspect) const { return static_cast<int>(image->getLayerSize(aspect)); }
	VkExtent3D getMipLevelExtent(uint32_t mipLevel) const { return image->getMipLevelExtent(subresourceRange.baseMipLevel + mipLevel); }

	void *getOffsetPointer(const VkOffset3D& offset, VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
	bool hasDepthAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; }
	bool hasStencilAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; }

	const VkComponentMapping &getComponentMapping() const { return components; }
	const VkImageSubresourceRange &getSubresourceRange() const { return subresourceRange; }
	const size_t getImageSizeInBytes() const { return image->getMemoryRequirements().size; }

private:
	bool                          imageTypesMatch(VkImageType imageType) const;

	Image *const                  image = nullptr;
	const VkImageViewType         viewType = VK_IMAGE_VIEW_TYPE_2D;
	const Format                  format;
	const VkComponentMapping      components = {};
	const VkImageSubresourceRange subresourceRange = {};
};

static inline ImageView* Cast(VkImageView object)
{
	return reinterpret_cast<ImageView*>(object);
}

} // namespace vk

#endif // VK_IMAGE_VIEW_HPP_
<commit_msg>Remove useless const on ImageView::getImageSizeInBytes return value<commit_after>// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef VK_IMAGE_VIEW_HPP_
#define VK_IMAGE_VIEW_HPP_

#include "VkDebug.hpp"
#include "VkFormat.h"
#include "VkObject.hpp"
#include "VkImage.hpp"

namespace vk
{

class ImageView : public Object<ImageView, VkImageView>
{
public:
	ImageView(const VkImageViewCreateInfo* pCreateInfo, void* mem);
	~ImageView() = delete;
	void destroy(const VkAllocationCallbacks* pAllocator);

	static size_t ComputeRequiredAllocationSize(const VkImageViewCreateInfo* pCreateInfo);

	void clear(const VkClearValue& clearValues, VkImageAspectFlags aspectMask, const VkRect2D& renderArea);
	void clear(const VkClearValue& clearValue, VkImageAspectFlags aspectMask, const VkClearRect& renderArea);
	void resolve(ImageView* resolveAttachment);

	VkImageViewType getType() const { return viewType; }
	Format getFormat() const { return format; }
	int getSampleCount() const { return image->getSampleCountFlagBits(); }
	int rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const { return image->rowPitchBytes(aspect, subresourceRange.baseMipLevel + mipLevel); }
	int slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const { return image->slicePitchBytes(aspect, subresourceRange.baseMipLevel + mipLevel); }
	int layerPitchBytes(VkImageAspectFlagBits aspect) const { return static_cast<int>(image->getLayerSize(aspect)); }
	VkExtent3D getMipLevelExtent(uint32_t mipLevel) const { return image->getMipLevelExtent(subresourceRange.baseMipLevel + mipLevel); }

	void *getOffsetPointer(const VkOffset3D& offset, VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
	bool hasDepthAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; }
	bool hasStencilAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; }

	const VkComponentMapping &getComponentMapping() const { return components; }
	const VkImageSubresourceRange &getSubresourceRange() const { return subresourceRange; }
	size_t getImageSizeInBytes() const { return image->getMemoryRequirements().size; }

private:
	bool                          imageTypesMatch(VkImageType imageType) const;

	Image *const                  image = nullptr;
	const VkImageViewType         viewType = VK_IMAGE_VIEW_TYPE_2D;
	const Format                  format;
	const VkComponentMapping      components = {};
	const VkImageSubresourceRange subresourceRange = {};
};

static inline ImageView* Cast(VkImageView object)
{
	return reinterpret_cast<ImageView*>(object);
}

} // namespace vk

#endif // VK_IMAGE_VIEW_HPP_
<|endoftext|>


<commit_before>#include "xchainer/python/device.h"

#include <memory>
#include <sstream>

#include "xchainer/backend.h"
#include "xchainer/context.h"
#include "xchainer/device.h"

#include "xchainer/python/common.h"

namespace xchainer {

namespace py = pybind11;  // standard convention

class PyDeviceScope {
public:
    explicit PyDeviceScope(Device& target) : target_(target) {}
    void Enter() { scope_ = std::make_unique<DeviceScope>(target_); }
    void Exit(py::args args) {
        (void)args;  // unused
        scope_.reset();
    }

private:
    // TODO(beam2d): better to replace it by "optional"...
    std::unique_ptr<DeviceScope> scope_;
    Device& target_;
};

void InitXchainerDevice(pybind11::module& m) {
    py::class_<Device>(m, "Device")
        .def("__repr__", &Device::name)
        .def("synchronize", &Device::Synchronize)
        .def_property_readonly("name", &Device::name)
        .def_property_readonly("backend", &Device::backend, py::return_value_policy::reference)
        .def_property_readonly("context", &Device::context, py::return_value_policy::reference)
        .def_property_readonly("index", &Device::index);

    m.def("get_default_device", []() -> Device& { return GetDefaultDevice(); }, py::return_value_policy::reference);
    m.def("set_default_device", [](Device& device) { SetDefaultDevice(&device); });

    py::class_<PyDeviceScope>(m, "DeviceScope").def("__enter__", &PyDeviceScope::Enter).def("__exit__", &PyDeviceScope::Exit);
    m.def("device_scope", [](Device& device) { return PyDeviceScope(device); });
}

}  // namespace xchainer
<commit_msg>Allow setting default device by str in Python<commit_after>#include "xchainer/python/device.h"

#include <memory>
#include <sstream>
#include <string>

#include "xchainer/backend.h"
#include "xchainer/context.h"
#include "xchainer/device.h"

#include "xchainer/python/common.h"

namespace xchainer {

namespace py = pybind11;  // standard convention

class PyDeviceScope {
public:
    explicit PyDeviceScope(Device& target) : target_(target) {}
    void Enter() { scope_ = std::make_unique<DeviceScope>(target_); }
    void Exit(py::args args) {
        (void)args;  // unused
        scope_.reset();
    }

private:
    // TODO(beam2d): better to replace it by "optional"...
    std::unique_ptr<DeviceScope> scope_;
    Device& target_;
};

void InitXchainerDevice(pybind11::module& m) {
    py::class_<Device>(m, "Device")
        .def("__repr__", &Device::name)
        .def("synchronize", &Device::Synchronize)
        .def_property_readonly("name", &Device::name)
        .def_property_readonly("backend", &Device::backend, py::return_value_policy::reference)
        .def_property_readonly("context", &Device::context, py::return_value_policy::reference)
        .def_property_readonly("index", &Device::index);

    m.def("get_default_device", []() -> Device& { return GetDefaultDevice(); }, py::return_value_policy::reference);
    m.def("set_default_device", [](Device& device) { SetDefaultDevice(&device); });
    m.def("set_default_device", [](const std::string& device_id) { SetDefaultDevice(&GetDefaultContext().GetDevice(device_id)); });

    py::class_<PyDeviceScope>(m, "DeviceScope").def("__enter__", &PyDeviceScope::Enter).def("__exit__", &PyDeviceScope::Exit);
    m.def("device_scope", [](Device& device) { return PyDeviceScope(device); });
}

}  // namespace xchainer
<|endoftext|>


<commit_before>//**************************************************************************************************
//
//     OSSIM Open Source Geospatial Data Processing Library
//     See top level LICENSE.txt file for license information
//
//**************************************************************************************************

#include "ossimPotraceUtil.h"
#include <ossim/base/ossimApplicationUsage.h>
#include <ossim/imaging/ossimImageHandlerRegistry.h>
#include <ossim/imaging/ossimImageSourceSequencer.h>
#include <ossim/base/ossimKeywordNames.h>
#include <sstream>

using namespace std;

const char* ossimPotraceUtil::DESCRIPTION =
      "Computes vector representation of input raster image.";

static const string MODE_KW = "mode";

ossimPotraceUtil::ossimPotraceUtil()
:  m_mode (LINESTRING)
{
}

ossimPotraceUtil::~ossimPotraceUtil()
{
}

void ossimPotraceUtil::setUsage(ossimArgumentParser& ap)
{
   // Add global usage options.
   ossimUtility::setUsage(ap);

   // Set the general usage:
   ossimApplicationUsage* au = ap.getApplicationUsage();
   ossimString usageString = ap.getApplicationName();
   usageString += " [options] <input-raster-file> [<output-vector-file>]";
   au->setCommandLineUsage(usageString);

   // Set the command line options:
   au->addCommandLineOption("--mode polygon|linestring",
         "Specifies whether to represent foreground-background boundary as polygons or line-strings"
         ". Polygons are closed regions surrounding either null or non-null pixels. Most viewers "
         "will represent polygons as solid blobs. Line-strings only outline the boundary but do not"
         " maintain sense of \"insideness\"");
}

bool ossimPotraceUtil::initialize(ossimArgumentParser& ap)
{
   string ts1;
   ossimArgumentParser::ossimParameter sp1(ts1);

   if (!ossimUtility::initialize(ap))
      return false;

   if ( ap.read("--mode", sp1))
      m_kwl.addPair(MODE_KW, ts1);

   // Remaining argument is input and output file names:
   if (ap.argc() > 1)
   {
      m_kwl.add(ossimKeywordNames::IMAGE_FILE_KW, ap.argv()[1]);
      if (ap.argc() > 2)
         m_kwl.add(ossimKeywordNames::OUTPUT_FILE_KW, ap.argv()[2]);
   }
   else
   {
      setUsage(ap);
      ap.reportError("Missing input raster filename.");
      ap.writeErrorMessages(ossimNotify(ossimNotifyLevel_NOTICE));
      return false;
   }

   initialize(m_kwl);
   return true;
}

void ossimPotraceUtil::initialize(const ossimKeywordlist& kwl)
{
   ossimString value;
   ostringstream xmsg;

   // Don't copy KWL if member KWL passed in:
   if (&kwl != &m_kwl)
   {
      // Start with clean options keyword list.
      m_kwl.clear();
      m_kwl.addList( kwl, true );
   }

   value = m_kwl.findKey(MODE_KW);
   if (value.contains("polygon"))
      m_mode = POLYGON;
   else if (value.contains("linestring"))
      m_mode = LINESTRING;
   else
   {
      xmsg <<"ossimPotraceUtil:"<<__LINE__<<" Unallowed mode requested: <"<<value<<">."
            <<endl;
      throw(xmsg.str());
   }

   m_inputRasterFname = m_kwl.findKey(ossimKeywordNames::IMAGE_FILE_KW);

   m_outputVectorFname = m_kwl.findKey(ossimKeywordNames::OUTPUT_FILE_KW);
   if (m_outputVectorFname.empty())
   {
      m_outputVectorFname = m_inputRasterFname;
      m_outputVectorFname.setExtension("json");
   }

   ossimUtility::initialize(kwl);

   m_bitmapFname = m_inputRasterFname;
   m_bitmapFname.setExtension("pbm");
}

bool ossimPotraceUtil::execute()
{
   // Open input image:
   m_inputHandler = ossimImageHandlerRegistry::instance()->open(m_inputRasterFname, 1, 0);
   if (!m_inputHandler.valid())
   {
      cout <<"ossimPotraceUtil:"<<__LINE__<<" Could not open input file <"<<m_inputRasterFname<<">"
            <<endl;
      return false;
   }
   // Vector coordinates are in image space. Need to convert to geographic lat/lon:
   ossimRefPtr<ossimImageGeometry> geom = m_inputHandler->getImageGeometry();
   if (!geom.valid())
   {
      cout <<"ossimPotraceUtil:"<<__LINE__<<" Encountered null image geometry!"<<endl;
      return false;
   }

   // Convert raster to bitmap:
   potrace_bitmap_t* potraceBitmap = convertToBitmap();
   if (!potraceBitmap)
      return false;

   // Perform vectorization:
   potrace_param_t* potraceParam = potrace_param_default();
   potraceParam->turdsize = 10;
   potraceParam->alphamax = 0;
   potrace_state_t* potraceOutput = potrace_trace(potraceParam, potraceBitmap);
   if (!potraceOutput)
   {
      cout <<"ossimPotraceUtil:"<<__LINE__<<" Null pointer returned from potrace_trace!"<<endl;
      return false;
   }

   potrace_path_t* potracePaths = potraceOutput->plist;
   potrace_path_t* path = potracePaths;
   ossimDpt imgPt;
   ossimGpt gndPt;
   while (path)
   {
      int numSegments = path->curve.n;
      for (int i=0; i<numSegments; ++i)
      {
         // Convert up 3 possible vertices per segment
         for (int v=0; v<3; ++v)
         {
            if ((v == 0) && (path->curve.tag[i] = POTRACE_CORNER))
               continue;

            imgPt.x = path->curve.c[i][v].x;
            imgPt.y = path->curve.c[i][v].y;
            geom->localToWorld(imgPt, gndPt);
            path->curve.c[i][v].x = gndPt.lon;
            path->curve.c[i][v].y = gndPt.lat;
         }
      }
      path = path->next;
   }

   // Write to output vector file:
   if (!writeGeoJSON(potracePaths))
      return false;

   // Release memory:
   potrace_state_free(potraceOutput);
   //free(potraceBitmap->map);
   delete potraceBitmap;
   free(potraceParam);

   return true;
}

void ossimPotraceUtil::getKwlTemplate(ossimKeywordlist& kwl)
{
   kwl.add(MODE_KW.c_str(), "polygom|linestring");
   kwl.add(ossimKeywordNames::IMAGE_FILE_KW, "<input-raster-file>");
   kwl.add(ossimKeywordNames::OUTPUT_FILE_KW, "<output-vector-file>");
}

potrace_bitmap_t* ossimPotraceUtil::convertToBitmap()
{
   potrace_bitmap_t* potraceBitmap = new potrace_bitmap_t;

   // Determine output bitmap size to even word boundary:
   ossimIrect rect = m_inputHandler->getImageRectangle();
   potraceBitmap->w = rect.width();
   potraceBitmap->h = rect.height();
   int pixelsPerWord = 8 * sizeof(int*);
   potraceBitmap->dy = (int) ceil((double)rect.width()/pixelsPerWord);

   // Allocate the bitmap memory:
   unsigned long bufLength = potraceBitmap->dy*potraceBitmap->h;
   potraceBitmap->map = new potrace_word[bufLength];

   // Prepare to sequence over all input image tiles and fill the bitmap image:
   ossimRefPtr<ossimImageSourceSequencer> sequencer =
         new ossimImageSourceSequencer(m_inputHandler.get());
   ossimRefPtr<ossimImageData> tile = sequencer->getNextTile();
   double null_pix = tile->getNullPix(0);
   unsigned long offset=0;

   // Loop to fill bitmap buffer:
   while (tile.valid())
   {
      ossimIpt pt (tile->getOrigin());
      ossimIpt lastPt (pt.x + tile->getWidth() - 1, pt.y + tile->getHeight() - 1);

      // Nested loops over all pixels in input tile:
      for (; pt.y <= lastPt.y; ++pt.y)
      {
         offset = tile->getOrigin().x/pixelsPerWord + pt.y*potraceBitmap->dy;
         for (pt.x = tile->getOrigin().x; pt.x <= lastPt.x; )
         {
            // Loop to pack a word buffer with pixel on (non-null) or off bit in proper positions:
            unsigned long wordBuf = 0;
            for (int bitpos=pixelsPerWord-1; bitpos>=0; --bitpos)
            {
               unsigned long pixel = (tile->getPix(pt) != null_pix) ? 1 : 0;
               wordBuf |= pixel << bitpos;
               ++pt.x;
               if (pt.x > lastPt.x)
                  break;
            }
            potraceBitmap->map[offset++] = wordBuf;
         }
      }

      tile = sequencer->getNextTile();
   }

   return potraceBitmap;
}

bool ossimPotraceUtil::writeGeoJSON(potrace_path_t* vectorList)
{
   FILE* outFile = fopen(m_outputVectorFname.chars(), "w");
   if (!outFile)
   {
      cout <<"ossimPotraceUtil:"<<__LINE__<<" Could not open output file <"<<m_outputVectorFname
            <<"> for writing."<<endl;
      return false;
   }

   potrace_geojson(outFile, vectorList, (int) (m_mode == POLYGON));

   return true;
}
<commit_msg>made param optional<commit_after>//**************************************************************************************************
//
//     OSSIM Open Source Geospatial Data Processing Library
//     See top level LICENSE.txt file for license information
//
//**************************************************************************************************

#include "ossimPotraceUtil.h"
#include <ossim/base/ossimApplicationUsage.h>
#include <ossim/imaging/ossimImageHandlerRegistry.h>
#include <ossim/imaging/ossimImageSourceSequencer.h>
#include <ossim/base/ossimKeywordNames.h>
#include <sstream>

using namespace std;

const char* ossimPotraceUtil::DESCRIPTION =
      "Computes vector representation of input raster image.";

static const string MODE_KW = "mode";

ossimPotraceUtil::ossimPotraceUtil()
:  m_mode (LINESTRING)
{
}

ossimPotraceUtil::~ossimPotraceUtil()
{
}

void ossimPotraceUtil::setUsage(ossimArgumentParser& ap)
{
   // Add global usage options.
   ossimUtility::setUsage(ap);

   // Set the general usage:
   ossimApplicationUsage* au = ap.getApplicationUsage();
   ossimString usageString = ap.getApplicationName();
   usageString += " [options] <input-raster-file> [<output-vector-file>]";
   au->setCommandLineUsage(usageString);

   // Set the command line options:
   au->addCommandLineOption("--mode polygon|linestring",
         "Specifies whether to represent foreground-background boundary as polygons or line-strings"
         ". Polygons are closed regions surrounding either null or non-null pixels. Most viewers "
         "will represent polygons as solid blobs. Line-strings only outline the boundary but do not"
         " maintain sense of \"insideness\"");
}

bool ossimPotraceUtil::initialize(ossimArgumentParser& ap)
{
   string ts1;
   ossimArgumentParser::ossimParameter sp1(ts1);

   if (!ossimUtility::initialize(ap))
      return false;

   if ( ap.read("--mode", sp1))
      m_kwl.addPair(MODE_KW, ts1);

   // Remaining argument is input and output file names:
   if (ap.argc() > 1)
   {
      m_kwl.add(ossimKeywordNames::IMAGE_FILE_KW, ap.argv()[1]);
      if (ap.argc() > 2)
         m_kwl.add(ossimKeywordNames::OUTPUT_FILE_KW, ap.argv()[2]);
   }
   else
   {
      setUsage(ap);
      ap.reportError("Missing input raster filename.");
      ap.writeErrorMessages(ossimNotify(ossimNotifyLevel_NOTICE));
      return false;
   }

   initialize(m_kwl);
   return true;
}

void ossimPotraceUtil::initialize(const ossimKeywordlist& kwl)
{
   ossimString value;
   ostringstream xmsg;

   // Don't copy KWL if member KWL passed in:
   if (&kwl != &m_kwl)
   {
      // Start with clean options keyword list.
      m_kwl.clear();
      m_kwl.addList( kwl, true );
   }

   value = m_kwl.findKey(MODE_KW);
   if (value.contains("polygon"))
      m_mode = POLYGON;
   else if (value.contains("linestring"))
      m_mode = LINESTRING;
   else if (!value.empty())
   {
      xmsg <<"ossimPotraceUtil:"<<__LINE__<<" Unallowed mode requested: <"<<value<<">."
            <<endl;
      throw(xmsg.str());
   }

   m_inputRasterFname = m_kwl.findKey(ossimKeywordNames::IMAGE_FILE_KW);

   m_outputVectorFname = m_kwl.findKey(ossimKeywordNames::OUTPUT_FILE_KW);
   if (m_outputVectorFname.empty())
   {
      m_outputVectorFname = m_inputRasterFname;
      m_outputVectorFname.setExtension("json");
   }

   ossimUtility::initialize(kwl);

   m_bitmapFname = m_inputRasterFname;
   m_bitmapFname.setExtension("pbm");
}

bool ossimPotraceUtil::execute()
{
   // Open input image:
   m_inputHandler = ossimImageHandlerRegistry::instance()->open(m_inputRasterFname, 1, 0);
   if (!m_inputHandler.valid())
   {
      cout <<"ossimPotraceUtil:"<<__LINE__<<" Could not open input file <"<<m_inputRasterFname<<">"
            <<endl;
      return false;
   }
   // Vector coordinates are in image space. Need to convert to geographic lat/lon:
   ossimRefPtr<ossimImageGeometry> geom = m_inputHandler->getImageGeometry();
   if (!geom.valid())
   {
      cout <<"ossimPotraceUtil:"<<__LINE__<<" Encountered null image geometry!"<<endl;
      return false;
   }

   // Convert raster to bitmap:
   potrace_bitmap_t* potraceBitmap = convertToBitmap();
   if (!potraceBitmap)
      return false;

   // Perform vectorization:
   potrace_param_t* potraceParam = potrace_param_default();
   potraceParam->turdsize = 10;
   potraceParam->alphamax = 0;
   potrace_state_t* potraceOutput = potrace_trace(potraceParam, potraceBitmap);
   if (!potraceOutput)
   {
      cout <<"ossimPotraceUtil:"<<__LINE__<<" Null pointer returned from potrace_trace!"<<endl;
      return false;
   }

   potrace_path_t* potracePaths = potraceOutput->plist;
   potrace_path_t* path = potracePaths;
   ossimDpt imgPt;
   ossimGpt gndPt;
   while (path)
   {
      int numSegments = path->curve.n;
      for (int i=0; i<numSegments; ++i)
      {
         // Convert up 3 possible vertices per segment
         for (int v=0; v<3; ++v)
         {
            if ((v == 0) && (path->curve.tag[i] = POTRACE_CORNER))
               continue;

            imgPt.x = path->curve.c[i][v].x;
            imgPt.y = path->curve.c[i][v].y;
            geom->localToWorld(imgPt, gndPt);
            path->curve.c[i][v].x = gndPt.lon;
            path->curve.c[i][v].y = gndPt.lat;
         }
      }
      path = path->next;
   }

   // Write to output vector file:
   if (!writeGeoJSON(potracePaths))
      return false;

   // Release memory:
   potrace_state_free(potraceOutput);
   //free(potraceBitmap->map);
   delete potraceBitmap;
   free(potraceParam);

   return true;
}

void ossimPotraceUtil::getKwlTemplate(ossimKeywordlist& kwl)
{
   kwl.add(MODE_KW.c_str(), "polygom|linestring");
   kwl.add(ossimKeywordNames::IMAGE_FILE_KW, "<input-raster-file>");
   kwl.add(ossimKeywordNames::OUTPUT_FILE_KW, "<output-vector-file>");
}

potrace_bitmap_t* ossimPotraceUtil::convertToBitmap()
{
   potrace_bitmap_t* potraceBitmap = new potrace_bitmap_t;

   // Determine output bitmap size to even word boundary:
   ossimIrect rect = m_inputHandler->getImageRectangle();
   potraceBitmap->w = rect.width();
   potraceBitmap->h = rect.height();
   int pixelsPerWord = 8 * sizeof(int*);
   potraceBitmap->dy = (int) ceil((double)rect.width()/pixelsPerWord);

   // Allocate the bitmap memory:
   unsigned long bufLength = potraceBitmap->dy*potraceBitmap->h;
   potraceBitmap->map = new potrace_word[bufLength];

   // Prepare to sequence over all input image tiles and fill the bitmap image:
   ossimRefPtr<ossimImageSourceSequencer> sequencer =
         new ossimImageSourceSequencer(m_inputHandler.get());
   ossimRefPtr<ossimImageData> tile = sequencer->getNextTile();
   double null_pix = tile->getNullPix(0);
   unsigned long offset=0;

   // Loop to fill bitmap buffer:
   while (tile.valid())
   {
      ossimIpt pt (tile->getOrigin());
      ossimIpt lastPt (pt.x + tile->getWidth() - 1, pt.y + tile->getHeight() - 1);

      // Nested loops over all pixels in input tile:
      for (; pt.y <= lastPt.y; ++pt.y)
      {
         offset = tile->getOrigin().x/pixelsPerWord + pt.y*potraceBitmap->dy;
         for (pt.x = tile->getOrigin().x; pt.x <= lastPt.x; )
         {
            // Loop to pack a word buffer with pixel on (non-null) or off bit in proper positions:
            unsigned long wordBuf = 0;
            for (int bitpos=pixelsPerWord-1; bitpos>=0; --bitpos)
            {
               unsigned long pixel = (tile->getPix(pt) != null_pix) ? 1 : 0;
               wordBuf |= pixel << bitpos;
               ++pt.x;
               if (pt.x > lastPt.x)
                  break;
            }
            potraceBitmap->map[offset++] = wordBuf;
         }
      }

      tile = sequencer->getNextTile();
   }

   return potraceBitmap;
}

bool ossimPotraceUtil::writeGeoJSON(potrace_path_t* vectorList)
{
   FILE* outFile = fopen(m_outputVectorFname.chars(), "w");
   if (!outFile)
   {
      cout <<"ossimPotraceUtil:"<<__LINE__<<" Could not open output file <"<<m_outputVectorFname
            <<"> for writing."<<endl;
      return false;
   }

   potrace_geojson(outFile, vectorList, (int) (m_mode == POLYGON));

   return true;
}
<|endoftext|>


<commit_before>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * Licensed under the MIT license (see LICENSE).
 */
#include <stdlib.h>
#include <assert.h>
#include "barchart.h"
#include "domain.h"

/**
 * todo:
 *  - stacked
 *  - labels inside/outside
 *  - calculate domain
 */
namespace fnordmetric {

BarChart::BarChart() :
    orientation_(O_HORIZONTAL),
    stacked_(false) {}

void BarChart::draw(ChartRenderTarget* target) {
  prepareData();

  /* draw the bars */
  switch (orientation_) {
    case O_VERTICAL:
      drawVerticalBars(target);
      break;
    case O_HORIZONTAL:
      drawHorizontalBars(target);
      break;
  }

  target->finishChart();
}

void BarChart::prepareData() {
  /* setup our value domain */
  y_domain = Domain(0, 40, false);

  for (const auto& series : getSeries()) {
    // FIXPAUL this could be O(N) but is O(N*2)
    for (const auto& datum : series->getData()) {
      const auto& x_val = datum[0];
      const auto& y_val = datum[1];

      BarData* bar_data = nullptr;
      for (auto& candidate : data_) {
        if (candidate.x == x_val) {
          bar_data = &candidate;
        }
      }

      if (bar_data == nullptr) {
        data_.emplace_back();
        bar_data = &data_.back();
        bar_data->x = x_val;
      }

      bar_data->ys.push_back(scaleValue(&y_val, &y_domain));
    }
  }
}

std::pair<double, double> BarChart::scaleValue(
    const query::SValue* value,
    const Domain* domain) const {
  switch (value->getType()) {
    case query::SValue::T_INTEGER:
      return std::pair<double, double>(
          domain->scale(0.0f),
          domain->scale(value->getInteger()));
    case query::SValue::T_FLOAT:
      return std::pair<double, double>(
          domain->scale(0.0f),
          domain->scale(value->getFloat()));
    default:
      assert(0); // FIXPAUL
  }
}

void BarChart::drawVerticalBars(ChartRenderTarget* target) {
  target->beginChart(width_, height_, "chart bar vertical");
  Drawable::draw(target);

  /* calculate bar width and padding */
  auto bar_width = (inner_width_ / data_.size()) * (1.0f - kBarPadding);
  auto bar_padding = (inner_width_ / data_.size()) * (kBarPadding * 0.5f);
  bar_width -= bar_padding / data_.size() * 2;

  /* draw the bars */
  std::vector<double> x_ticks = {0.0f};
  std::vector<std::pair<double, std::string>> x_labels;
  auto draw_x = padding_left_ + bar_padding;
  auto draw_width = bar_width;
  for (const auto& bar : data_) {
    draw_x += bar_padding;

    /* single series */
    if (getSeries().size() == 1) {
      auto& y_val = bar.ys[0];
      auto y_min = y_val.first;
      auto y_max = y_val.second;
      auto draw_y = padding_top_ + ((1.0f - y_max) * inner_height_);
      auto draw_height = (1.0f - ((1.0f - y_max) + y_min)) * inner_height_;
      target->drawRect(draw_x, draw_y, draw_width, draw_height, colorName(0));
    }

    /* multi series stacked */
    else if (stacked_) {
    }

    /* multi series unstacked */
    else {
      auto num_series = getSeries().size();
      auto draw_x_multi = draw_x;
      auto draw_width_multi = draw_width / num_series;
      for (int i = 0; i < bar.ys.size(); i++) {
        auto& y_val = bar.ys[i];
        auto y_min = y_val.first;
        auto y_max = y_val.second;
        auto draw_y = padding_top_ + ((1.0f - y_max) * inner_height_);
        auto draw_height = (1.0f - ((1.0f - y_max) + y_min)) * inner_height_;
        target->drawRect(
            draw_x_multi,
            draw_y,
            draw_width_multi * (1.0f - kBarPadding * 0.5f),
            draw_height,
            colorName(i));
        draw_x_multi += (draw_width_multi * (1.0f + kBarPadding * 0.5f));
      }
    }

    x_labels.push_back(std::make_pair((
        draw_x - padding_left_ + bar_width * 0.5f) / inner_width_,
        format::svalueToHuman(bar.x)));
    draw_x += bar_width + bar_padding;
    x_ticks.push_back((draw_x - padding_left_) / inner_width_);
  }
  x_ticks.back() = 1.0f;

  if (show_axis_[LEFT]) {
    drawLeftAxis(target, &y_domain);
  }

  if (show_axis_[RIGHT]) {
    drawRightAxis(target, &y_domain);
  }

  if (show_axis_[BOTTOM]) {
    drawBottomAxis(target, x_ticks, x_labels);
  }

  if (show_axis_[TOP]) {
    drawTopAxis(target, &y_domain);
  }
}

void BarChart::drawHorizontalBars(ChartRenderTarget* target) {
  target->beginChart(width_, height_, "chart bar horizontal");
  Drawable::draw(target);

  /* calculate bar width and padding */
  auto bar_height = (inner_height_ / data_.size()) * (1.0f - kBarPadding);
  auto bar_padding = (inner_height_ / data_.size()) * (kBarPadding * 0.5f);
  bar_height -= bar_padding / data_.size() * 2;

  /* draw the bars */
  std::vector<double> y_ticks = {0.0f};
  std::vector<std::pair<double, std::string>> y_labels;
  auto draw_y = padding_top_ + bar_padding;
  auto draw_height = bar_height;
  for (const auto& bar : data_) {
    draw_y += bar_padding;

    /* single series */
    if (getSeries().size() == 1) {
      auto& y_val = bar.ys[0];
      auto y_min = y_val.first;
      auto y_max = y_val.second;
      auto draw_x = padding_left_ + y_min * inner_width_;
      auto draw_width = (y_max - y_min) * inner_width_;
      target->drawRect(draw_x, draw_y, draw_width, draw_height, colorName(0));
    }

    /* multi series stacked */
    else if (stacked_) {
    }

    /* multi series unstacked */
    else {
      auto num_series = getSeries().size();
      auto draw_y_multi = draw_y;
      auto draw_height_multi = draw_height / num_series;
      for (int i = 0; i < bar.ys.size(); i++) {
        auto& y_val = bar.ys[i];
        auto y_min = y_val.first;
        auto y_max = y_val.second;
        auto draw_x = padding_left_ + y_min * inner_width_;
        auto draw_width = (y_max - y_min) * inner_width_;
        target->drawRect(
            draw_x,
            draw_y_multi,
            draw_width,
            draw_height_multi * (1.0f - kBarPadding * 0.5f),
            colorName(i));
        draw_y_multi += (draw_height_multi * (1.0f + kBarPadding * 0.5f));
      }
    }

    y_labels.push_back(std::make_pair((
        draw_y - padding_top_ + bar_height * 0.5f) / inner_height_,
        format::svalueToHuman(bar.x)));
    draw_y += bar_height + bar_padding;
    y_ticks.push_back((draw_y - padding_top_) / inner_height_);
  }
  y_ticks.back() = 1.0f;

  if (show_axis_[LEFT]) {
    drawLeftAxis(target, y_ticks, y_labels);
  }

  if (show_axis_[RIGHT]) {
    drawRightAxis(target, y_ticks, y_labels);
  }

  if (show_axis_[BOTTOM]) {
    drawBottomAxis(target, &y_domain);
  }

  if (show_axis_[TOP]) {
    drawTopAxis(target, &y_domain);
  }
}

}
<commit_msg>stacked bar charts :)<commit_after>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * Licensed under the MIT license (see LICENSE).
 */
#include <stdlib.h>
#include <assert.h>
#include "barchart.h"
#include "domain.h"

/**
 * todo:
 *  - labels inside/outside
 *  - calculate domain
 */
namespace fnordmetric {

BarChart::BarChart() :
    orientation_(O_VERTICAL),
    stacked_(false) {}

void BarChart::draw(ChartRenderTarget* target) {
  prepareData();

  /* draw the bars */
  switch (orientation_) {
    case O_VERTICAL:
      drawVerticalBars(target);
      break;
    case O_HORIZONTAL:
      drawHorizontalBars(target);
      break;
  }

  target->finishChart();
}

void BarChart::prepareData() {
  /* setup our value domain */
  y_domain = Domain(0, 40, false);

  for (const auto& series : getSeries()) {
    // FIXPAUL this could be O(N) but is O(N*2)
    for (const auto& datum : series->getData()) {
      const auto& x_val = datum[0];
      const auto& y_val = datum[1];

      BarData* bar_data = nullptr;
      for (auto& candidate : data_) {
        if (candidate.x == x_val) {
          bar_data = &candidate;
        }
      }

      if (bar_data == nullptr) {
        data_.emplace_back();
        bar_data = &data_.back();
        bar_data->x = x_val;
      }

      bar_data->ys.push_back(scaleValue(&y_val, &y_domain));
    }
  }
}

std::pair<double, double> BarChart::scaleValue(
    const query::SValue* value,
    const Domain* domain) const {
  switch (value->getType()) {
    case query::SValue::T_INTEGER:
      return std::pair<double, double>(
          domain->scale(0.0f),
          domain->scale(value->getInteger()));
    case query::SValue::T_FLOAT:
      return std::pair<double, double>(
          domain->scale(0.0f),
          domain->scale(value->getFloat()));
    default:
      assert(0); // FIXPAUL
  }
}

void BarChart::drawVerticalBars(ChartRenderTarget* target) {
  target->beginChart(width_, height_, "chart bar vertical");
  Drawable::draw(target);

  /* calculate bar width and padding */
  auto bar_width = (inner_width_ / data_.size()) * (1.0f - kBarPadding);
  auto bar_padding = (inner_width_ / data_.size()) * (kBarPadding * 0.5f);
  bar_width -= bar_padding / data_.size() * 2;

  /* draw the bars */
  std::vector<double> x_ticks = {0.0f};
  std::vector<std::pair<double, std::string>> x_labels;
  auto draw_x = padding_left_ + bar_padding;
  auto draw_width = bar_width;
  for (const auto& bar : data_) {
    draw_x += bar_padding;

    /* single series */
    if (getSeries().size() == 1) {
      auto& y_val = bar.ys[0];
      auto y_min = y_val.first;
      auto y_max = y_val.second;
      auto draw_y = padding_top_ + ((1.0f - y_max) * inner_height_);
      auto draw_height = (1.0f - ((1.0f - y_max) + y_min)) * inner_height_;
      target->drawRect(draw_x, draw_y, draw_width, draw_height, colorName(0));
    }

    /* multi series stacked */
    else if (stacked_) {
      double y_min = 0.0f;
      double y_max = 0.0f;
      for (int i = 0; i < bar.ys.size(); i++) {
        auto& y_val = bar.ys[i];
        y_max += y_val.second - y_val.first;
        auto draw_y = padding_top_ + ((1.0f - y_max) * inner_height_);
        auto draw_height = (1.0f - ((1.0f - y_max) + y_min)) * inner_height_;
        target->drawRect(draw_x, draw_y, draw_width, draw_height, colorName(i));
        y_min += y_val.second - y_val.first;
      }
    }

    /* multi series unstacked */
    else {
      auto num_series = getSeries().size();
      auto draw_x_multi = draw_x;
      auto draw_width_multi = draw_width / num_series;
      for (int i = 0; i < bar.ys.size(); i++) {
        auto& y_val = bar.ys[i];
        auto y_min = y_val.first;
        auto y_max = y_val.second;
        auto draw_y = padding_top_ + ((1.0f - y_max) * inner_height_);
        auto draw_height = (1.0f - ((1.0f - y_max) + y_min)) * inner_height_;
        target->drawRect(
            draw_x_multi,
            draw_y,
            draw_width_multi * (1.0f - kBarPadding * 0.5f),
            draw_height,
            colorName(i));
        draw_x_multi += (draw_width_multi * (1.0f + kBarPadding * 0.5f));
      }
    }

    x_labels.push_back(std::make_pair((
        draw_x - padding_left_ + bar_width * 0.5f) / inner_width_,
        format::svalueToHuman(bar.x)));
    draw_x += bar_width + bar_padding;
    x_ticks.push_back((draw_x - padding_left_) / inner_width_);
  }
  x_ticks.back() = 1.0f;

  if (show_axis_[LEFT]) {
    drawLeftAxis(target, &y_domain);
  }

  if (show_axis_[RIGHT]) {
    drawRightAxis(target, &y_domain);
  }

  if (show_axis_[BOTTOM]) {
    drawBottomAxis(target, x_ticks, x_labels);
  }

  if (show_axis_[TOP]) {
    drawTopAxis(target, &y_domain);
  }
}

void BarChart::drawHorizontalBars(ChartRenderTarget* target) {
  target->beginChart(width_, height_, "chart bar horizontal");
  Drawable::draw(target);

  /* calculate bar width and padding */
  auto bar_height = (inner_height_ / data_.size()) * (1.0f - kBarPadding);
  auto bar_padding = (inner_height_ / data_.size()) * (kBarPadding * 0.5f);
  bar_height -= bar_padding / data_.size() * 2;

  /* draw the bars */
  std::vector<double> y_ticks = {0.0f};
  std::vector<std::pair<double, std::string>> y_labels;
  auto draw_y = padding_top_ + bar_padding;
  auto draw_height = bar_height;
  for (const auto& bar : data_) {
    draw_y += bar_padding;

    /* single series */
    if (getSeries().size() == 1) {
      auto& y_val = bar.ys[0];
      auto y_min = y_val.first;
      auto y_max = y_val.second;
      auto draw_x = padding_left_ + y_min * inner_width_;
      auto draw_width = (y_max - y_min) * inner_width_;
      target->drawRect(draw_x, draw_y, draw_width, draw_height, colorName(0));
    }

    /* multi series stacked */
    else if (stacked_) {
      double y_min = 0.0f;
      double y_max = 0.0f;
      for (int i = 0; i < bar.ys.size(); i++) {
        auto& y_val = bar.ys[i];
        y_max += y_val.second - y_val.first;
        auto draw_x = padding_left_ + y_min * inner_width_;
        auto draw_width = (y_max - y_min) * inner_width_;
        target->drawRect(draw_x, draw_y, draw_width, draw_height, colorName(i));
        y_min += y_val.second - y_val.first;
      }
    }

    /* multi series unstacked */
    else {
      auto num_series = getSeries().size();
      auto draw_y_multi = draw_y;
      auto draw_height_multi = draw_height / num_series;
      for (int i = 0; i < bar.ys.size(); i++) {
        auto& y_val = bar.ys[i];
        auto y_min = y_val.first;
        auto y_max = y_val.second;
        auto draw_x = padding_left_ + y_min * inner_width_;
        auto draw_width = (y_max - y_min) * inner_width_;
        target->drawRect(
            draw_x,
            draw_y_multi,
            draw_width,
            draw_height_multi * (1.0f - kBarPadding * 0.5f),
            colorName(i));
        draw_y_multi += (draw_height_multi * (1.0f + kBarPadding * 0.5f));
      }
    }

    y_labels.push_back(std::make_pair((
        draw_y - padding_top_ + bar_height * 0.5f) / inner_height_,
        format::svalueToHuman(bar.x)));
    draw_y += bar_height + bar_padding;
    y_ticks.push_back((draw_y - padding_top_) / inner_height_);
  }
  y_ticks.back() = 1.0f;

  if (show_axis_[LEFT]) {
    drawLeftAxis(target, y_ticks, y_labels);
  }

  if (show_axis_[RIGHT]) {
    drawRightAxis(target, y_ticks, y_labels);
  }

  if (show_axis_[BOTTOM]) {
    drawBottomAxis(target, &y_domain);
  }

  if (show_axis_[TOP]) {
    drawTopAxis(target, &y_domain);
  }
}

}
<|endoftext|>