<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* common headers */
#include "common.h"

/* interface headers */
#include "EvdevJoystick.h"

#ifdef HAVE_LINUX_INPUT_H

/* system headers */
#include <vector>
#include <string>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>

/* implementation headers */
#include "ErrorHandler.h"

#define test_bit(nr, addr) \
	(((1UL << ((nr) & 31)) & (((const unsigned int *) addr)[(nr) >> 5])) != 0)

bool             EvdevJoystick::isEvdevAvailable()
{
  /* Test whether this driver should be used without actually
   * loading it. Will return false if no event devices can be
   * located, or if it has been specifically disabled by setting
   * the environment variable BZFLAG_ENABLE_EVDEV=0
   */

  char *envvar = getenv("BZFLAG_ENABLE_EVDEV");
  if (envvar)
    return atoi(envvar) != 0;

  std::map<std::string,EvdevJoystickInfo> joysticks;
  scanForJoysticks(joysticks);
  return !joysticks.empty();
}

EvdevJoystick::EvdevJoystick()
{
  joystickfd = 0;
  currentJoystick = NULL;
  ff_rumble = new struct ff_effect;
  scanForJoysticks(joysticks);
}

EvdevJoystick::~EvdevJoystick()
{
  initJoystick("");
  delete ff_rumble;
}

void             EvdevJoystick::scanForJoysticks(std::map<std::string,
							EvdevJoystickInfo> &joysticks)
{
  joysticks.clear();

  const std::string inputdirName = "/dev/input";
  DIR* inputdir = opendir(inputdirName.c_str());
  if (!inputdir)
    return;

  struct dirent *dent;
  while ((dent = readdir(inputdir))) {
    EvdevJoystickInfo info;

    /* Does it look like an event device? */
    if (strncmp(dent->d_name, "event", 5))
      continue;

    /* Can we open it? */
    info.filename = inputdirName + "/" + dent->d_name;
    int fd = open(info.filename.c_str(), O_RDWR);
    if (!fd)
      continue;

    /* Does it look like a joystick? */
    if (!(collectJoystickBits(fd, info) && isJoystick(info))) {
      close(fd);
      continue;
    }

    /* Can we get its name? */
    char jsname[128];
    if (ioctl(fd, EVIOCGNAME(sizeof(jsname)-1), jsname) < 0) {
      close(fd);
      continue;
    }
    jsname[sizeof(jsname)-1] = '\0';

    close(fd);

    /* Yay, add it to our map.
     *
     * FIXME: we can't handle multiple joysticks with the same name yet.
     *        This could be fixed by disambiguating jsname if it already
     *        exists in 'joysticks', but the user would still have a hard
     *        time knowing which device to pick.
     */
    joysticks[jsname] = info;
  }

  closedir(inputdir);
}

bool                    EvdevJoystick::collectJoystickBits(int fd, struct EvdevJoystickInfo &info)
{
  /* Collect all the bitfields we're interested in from an event device
   * at the given file descriptor.
   */
  if (ioctl(fd, EVIOCGBIT(0, sizeof(info.evbit)), info.evbit) < 0)
    return false;
  if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(info.keybit)), info.keybit) < 0)
    return false;
  if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(info.absbit)), info.absbit) < 0)
    return false;
  if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(info.ffbit)), info.ffbit) < 0)
    return false;

  /* Collect information about our absolute axes */
  int axis;
  for (axis=0; axis<2; axis++) {
    if (ioctl(fd, EVIOCGABS(axis + ABS_X), &info.axis_info[axis]) < 0)
      return false;
  }

  return true;
}

bool			EvdevJoystick::isJoystick(struct EvdevJoystickInfo &info)
{
  /* Look at the capability bitfields in the given EvdevJoystickInfo, and
   * decide whether the device is indeed a joystick. This uses the same criteria
   * that SDL does- it at least needs X and Y axes, and one joystick-like button.
   */
  if (!test_bit(EV_KEY, info.evbit))
    return false;
  if (!(test_bit(BTN_TRIGGER, info.keybit) ||
	test_bit(BTN_A, info.keybit) ||
	test_bit(BTN_1, info.keybit)))
    return false;

  if (!test_bit(EV_ABS, info.evbit))
    return false;
  if (!(test_bit(ABS_X, info.absbit) &&
	test_bit(ABS_Y, info.absbit)))
    return false;

  return true;
}

void			EvdevJoystick::initJoystick(const char* joystickName)
{
  /* Close the previous joystick */
  ffResetRumble();
  if (joystickfd > 0)
    close(joystickfd);
  currentJoystick = NULL;
  joystickfd = 0;

  if (!strcmp(joystickName, "off") || !strcmp(joystickName, "")) {
    /* No joystick configured, we're done */
    return;
  }

  std::map<std::string,EvdevJoystickInfo>::iterator iter;
  iter = joysticks.find(joystickName);
  if (iter == joysticks.end()) {
    printError("The selected joystick no longer exists.");
    return;
  }

  /* Looks like we might have a valid joystick, try to open it */
  EvdevJoystickInfo *info = &iter->second;
  joystickfd = open(info->filename.c_str(), O_RDWR | O_NONBLOCK);
  if (joystickfd > 0) {
    /* Yay, it worked */
    currentJoystick = info;
  }
  else {
    printError("Error opening the selected joystick.");
  }

  buttons = 0;
}

bool			EvdevJoystick::joystick() const
{
  return currentJoystick != NULL;
}

void                    EvdevJoystick::poll()
{
  /* Read as many input events as are available, and update our current state
   */
  struct input_event ev;
  while (read(joystickfd, &ev, sizeof(ev)) > 0) {
    switch (ev.type) {

    case EV_ABS:
      switch (ev.code) {
      case ABS_X: currentJoystick->axis_info[0].value = ev.value; break;
      case ABS_Y: currentJoystick->axis_info[1].value = ev.value; break;
      }
      break;

    case EV_KEY:
      setButton(mapButton(ev.code), ev.value);
      break;

    }
  }
}

int                     EvdevJoystick::mapButton(int bit_num)
{
  /* Given an evdev button number, map it back to a small integer that most
   * people would consider the button's actual number. This also ensures
   * that we can fit all buttons in "buttons" as long as the number of buttons
   * is less than the architecture's word size ;)
   *
   * We just scan through the joystick's keybits, counting how many
   * set bits we encounter before this one. If the indicated bit isn't
   * set in keybits, this is a bad event and we return -1.
   * If this linear scan becomes a noticeable performance drain, this could
   * easily be precomputed and stored in an std:map.
   */
  int i;
  int button_num = 0;
  const int total_bits = sizeof(currentJoystick->keybit)*sizeof(unsigned long)*8;

  for (i=0; i<total_bits; i++) {
    if (i == bit_num)
      return button_num;
    if (test_bit(i, currentJoystick->keybit))
      button_num++;
  }
  return -1;
}

void                    EvdevJoystick::setButton(int button_num, int state)
{

  if (button_num >= 0) {
    int mask = 1<<button_num;
    if (state)
      buttons |= mask;
    else
      buttons &= ~mask;
  }
}

void			EvdevJoystick::getJoy(int& x, int& y)
{
  if (currentJoystick) {
    poll();

    int axes[2];
    int axis;
    int value;
    for (axis=0; axis<2; axis++) {

      /* Each axis gets scaled from evdev's reported minimum
       * and maximum into bzflag's [-1000, 1000] range.
       */
      value = currentJoystick->axis_info[axis].value;
      value -= currentJoystick->axis_info[axis].minimum;
      value = value * 2000 / (currentJoystick->axis_info[axis].maximum -
			      currentJoystick->axis_info[axis].minimum);
      value -= 1000;

      /* No cheating by modifying joystick drivers, or using some that rate
       * their maximum and minimum conservatively like the input spec allows.
       */
      if (value < -1000) value = -1000;
      if (value >  1000) value =  1000;

      /* All the cool kids are doing it... */
      value = (value * abs(value)) / 1000;

      axes[axis] = value;
    }
    x = axes[0];
    y = axes[1];
  }
  else {
    x = y = 0;
  }
}

unsigned long		EvdevJoystick::getJoyButtons()
{
  if (currentJoystick) {
    poll();
    return buttons;
  }
  else {
    return 0;
  }
}

void                    EvdevJoystick::getJoyDevices(std::vector<std::string>
						 &list) const
{
  std::map<std::string,EvdevJoystickInfo>::const_iterator i;
  for (i = joysticks.begin(); i != joysticks.end(); ++i)
    list.push_back(i->first);
}

bool                    EvdevJoystick::ffHasRumble() const
{
#ifdef HAVE_FF_EFFECT_RUMBLE
  if (!currentJoystick)
    return false;
  else
    return test_bit(EV_FF, currentJoystick->evbit) &&
           test_bit(FF_RUMBLE, currentJoystick->ffbit);
#else
  return false;
#endif
}

void                    EvdevJoystick::ffResetRumble()
{
#ifdef HAVE_FF_EFFECT_RUMBLE
  /* Erase old effects before closing a device,
   * if we had any, then initialize the ff_rumble struct.
   */
  if (ffHasRumble() && ff_rumble->id != -1) {

    /* Stop the effect first */
    struct input_event event;
    event.type = EV_FF;
    event.code = ff_rumble->id;
    event.value = 0;
    write(joystickfd, &event, sizeof(event));

    /* Erase the downloaded effect */
    ioctl(joystickfd, EVIOCRMFF, ff_rumble->id);
  }

  /* Reinit the ff_rumble struct. It starts out with
   * an id of -1, prompting the driver to assign us one.
   * Once that happens, we stick with the same effect slot
   * as long as we have the device open.
   */
  memset(ff_rumble, 0, sizeof(*ff_rumble));
  ff_rumble->type = FF_RUMBLE;
  ff_rumble->id = -1;
#endif
}

#ifdef HAVE_FF_EFFECT_RUMBLE
void                    EvdevJoystick::ffRumble(int count,
						float delay, float duration,
						float strong_motor,
						float weak_motor)
{
  if (!ffHasRumble())
    return;

  /* Stop the previous effect we were playing, if any */
  if (ff_rumble->id != -1) {
    struct input_event event;
    event.type = EV_FF;
    event.code = ff_rumble->id;
    event.value = 0;
    write(joystickfd, &event, sizeof(event));
  }

  if (count > 0) {
    /* Download an updated effect */
    ff_rumble->u.rumble.strong_magnitude = (int) (0xFFFF * strong_motor + 0.5);
    ff_rumble->u.rumble.weak_magnitude = (int) (0xFFFF * weak_motor + 0.5);
    ff_rumble->replay.length = (int) (duration * 1000 + 0.5);
    ff_rumble->replay.delay = (int) (delay * 1000 + 0.5);
    ioctl(joystickfd, EVIOCSFF, ff_rumble);

    /* Play it the indicated number of times */
    struct input_event event;
    event.type = EV_FF;
    event.code = ff_rumble->id;
    event.value = count;
    write(joystickfd, &event, sizeof(event));
  }
}
#else
void EvdevJoystick::ffRumble(int, float, float, float, float)
{
}
#endif

#endif /* HAVE_LINUX_INPUT_H */

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Some event driver are bugged, so prefer disabling it via BZDB forever<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* common headers */
#include "common.h"

/* interface headers */
#include "EvdevJoystick.h"

#ifdef HAVE_LINUX_INPUT_H

/* system headers */
#include <vector>
#include <string>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>

/* implementation headers */
#include "ErrorHandler.h"
#include "StateDatabase.h"

#define test_bit(nr, addr) \
	(((1UL << ((nr) & 31)) & (((const unsigned int *) addr)[(nr) >> 5])) != 0)

bool             EvdevJoystick::isEvdevAvailable()
{
  /* Test whether this driver should be used without actually
   * loading it. Will return false if no event devices can be
   * located, or if it has been specifically disabled by setting
   * the environment variable BZFLAG_ENABLE_EVDEV=0
   */

  if (BZDB.isSet("enable_evdev") && !BZDB.isTrue("enable_evdev"))
    return false;

  std::map<std::string,EvdevJoystickInfo> joysticks;
  scanForJoysticks(joysticks);
  return !joysticks.empty();
}

EvdevJoystick::EvdevJoystick()
{
  joystickfd = 0;
  currentJoystick = NULL;
  ff_rumble = new struct ff_effect;
  scanForJoysticks(joysticks);
}

EvdevJoystick::~EvdevJoystick()
{
  initJoystick("");
  delete ff_rumble;
}

void             EvdevJoystick::scanForJoysticks(std::map<std::string,
							EvdevJoystickInfo> &joysticks)
{
  joysticks.clear();

  const std::string inputdirName = "/dev/input";
  DIR* inputdir = opendir(inputdirName.c_str());
  if (!inputdir)
    return;

  struct dirent *dent;
  while ((dent = readdir(inputdir))) {
    EvdevJoystickInfo info;

    /* Does it look like an event device? */
    if (strncmp(dent->d_name, "event", 5))
      continue;

    /* Can we open it? */
    info.filename = inputdirName + "/" + dent->d_name;
    int fd = open(info.filename.c_str(), O_RDWR);
    if (!fd)
      continue;

    /* Does it look like a joystick? */
    if (!(collectJoystickBits(fd, info) && isJoystick(info))) {
      close(fd);
      continue;
    }

    /* Can we get its name? */
    char jsname[128];
    if (ioctl(fd, EVIOCGNAME(sizeof(jsname)-1), jsname) < 0) {
      close(fd);
      continue;
    }
    jsname[sizeof(jsname)-1] = '\0';

    close(fd);

    /* Yay, add it to our map.
     *
     * FIXME: we can't handle multiple joysticks with the same name yet.
     *        This could be fixed by disambiguating jsname if it already
     *        exists in 'joysticks', but the user would still have a hard
     *        time knowing which device to pick.
     */
    joysticks[jsname] = info;
  }

  closedir(inputdir);
}

bool                    EvdevJoystick::collectJoystickBits(int fd, struct EvdevJoystickInfo &info)
{
  /* Collect all the bitfields we're interested in from an event device
   * at the given file descriptor.
   */
  if (ioctl(fd, EVIOCGBIT(0, sizeof(info.evbit)), info.evbit) < 0)
    return false;
  if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(info.keybit)), info.keybit) < 0)
    return false;
  if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(info.absbit)), info.absbit) < 0)
    return false;
  if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(info.ffbit)), info.ffbit) < 0)
    return false;

  /* Collect information about our absolute axes */
  int axis;
  for (axis=0; axis<2; axis++) {
    if (ioctl(fd, EVIOCGABS(axis + ABS_X), &info.axis_info[axis]) < 0)
      return false;
  }

  return true;
}

bool			EvdevJoystick::isJoystick(struct EvdevJoystickInfo &info)
{
  /* Look at the capability bitfields in the given EvdevJoystickInfo, and
   * decide whether the device is indeed a joystick. This uses the same criteria
   * that SDL does- it at least needs X and Y axes, and one joystick-like button.
   */
  if (!test_bit(EV_KEY, info.evbit))
    return false;
  if (!(test_bit(BTN_TRIGGER, info.keybit) ||
	test_bit(BTN_A, info.keybit) ||
	test_bit(BTN_1, info.keybit)))
    return false;

  if (!test_bit(EV_ABS, info.evbit))
    return false;
  if (!(test_bit(ABS_X, info.absbit) &&
	test_bit(ABS_Y, info.absbit)))
    return false;

  return true;
}

void			EvdevJoystick::initJoystick(const char* joystickName)
{
  /* Close the previous joystick */
  ffResetRumble();
  if (joystickfd > 0)
    close(joystickfd);
  currentJoystick = NULL;
  joystickfd = 0;

  if (!strcmp(joystickName, "off") || !strcmp(joystickName, "")) {
    /* No joystick configured, we're done */
    return;
  }

  std::map<std::string,EvdevJoystickInfo>::iterator iter;
  iter = joysticks.find(joystickName);
  if (iter == joysticks.end()) {
    printError("The selected joystick no longer exists.");
    return;
  }

  /* Looks like we might have a valid joystick, try to open it */
  EvdevJoystickInfo *info = &iter->second;
  joystickfd = open(info->filename.c_str(), O_RDWR | O_NONBLOCK);
  if (joystickfd > 0) {
    /* Yay, it worked */
    currentJoystick = info;
  }
  else {
    printError("Error opening the selected joystick.");
  }

  buttons = 0;
}

bool			EvdevJoystick::joystick() const
{
  return currentJoystick != NULL;
}

void                    EvdevJoystick::poll()
{
  /* Read as many input events as are available, and update our current state
   */
  struct input_event ev;
  while (read(joystickfd, &ev, sizeof(ev)) > 0) {
    switch (ev.type) {

    case EV_ABS:
      switch (ev.code) {
      case ABS_X: currentJoystick->axis_info[0].value = ev.value; break;
      case ABS_Y: currentJoystick->axis_info[1].value = ev.value; break;
      }
      break;

    case EV_KEY:
      setButton(mapButton(ev.code), ev.value);
      break;

    }
  }
}

int                     EvdevJoystick::mapButton(int bit_num)
{
  /* Given an evdev button number, map it back to a small integer that most
   * people would consider the button's actual number. This also ensures
   * that we can fit all buttons in "buttons" as long as the number of buttons
   * is less than the architecture's word size ;)
   *
   * We just scan through the joystick's keybits, counting how many
   * set bits we encounter before this one. If the indicated bit isn't
   * set in keybits, this is a bad event and we return -1.
   * If this linear scan becomes a noticeable performance drain, this could
   * easily be precomputed and stored in an std:map.
   */
  int i;
  int button_num = 0;
  const int total_bits = sizeof(currentJoystick->keybit)*sizeof(unsigned long)*8;

  for (i=0; i<total_bits; i++) {
    if (i == bit_num)
      return button_num;
    if (test_bit(i, currentJoystick->keybit))
      button_num++;
  }
  return -1;
}

void                    EvdevJoystick::setButton(int button_num, int state)
{

  if (button_num >= 0) {
    int mask = 1<<button_num;
    if (state)
      buttons |= mask;
    else
      buttons &= ~mask;
  }
}

void			EvdevJoystick::getJoy(int& x, int& y)
{
  if (currentJoystick) {
    poll();

    int axes[2];
    int axis;
    int value;
    for (axis=0; axis<2; axis++) {

      /* Each axis gets scaled from evdev's reported minimum
       * and maximum into bzflag's [-1000, 1000] range.
       */
      value = currentJoystick->axis_info[axis].value;
      value -= currentJoystick->axis_info[axis].minimum;
      value = value * 2000 / (currentJoystick->axis_info[axis].maximum -
			      currentJoystick->axis_info[axis].minimum);
      value -= 1000;

      /* No cheating by modifying joystick drivers, or using some that rate
       * their maximum and minimum conservatively like the input spec allows.
       */
      if (value < -1000) value = -1000;
      if (value >  1000) value =  1000;

      /* All the cool kids are doing it... */
      value = (value * abs(value)) / 1000;

      axes[axis] = value;
    }
    x = axes[0];
    y = axes[1];
  }
  else {
    x = y = 0;
  }
}

unsigned long		EvdevJoystick::getJoyButtons()
{
  if (currentJoystick) {
    poll();
    return buttons;
  }
  else {
    return 0;
  }
}

void                    EvdevJoystick::getJoyDevices(std::vector<std::string>
						 &list) const
{
  std::map<std::string,EvdevJoystickInfo>::const_iterator i;
  for (i = joysticks.begin(); i != joysticks.end(); ++i)
    list.push_back(i->first);
}

bool                    EvdevJoystick::ffHasRumble() const
{
#ifdef HAVE_FF_EFFECT_RUMBLE
  if (!currentJoystick)
    return false;
  else
    return test_bit(EV_FF, currentJoystick->evbit) &&
           test_bit(FF_RUMBLE, currentJoystick->ffbit);
#else
  return false;
#endif
}

void                    EvdevJoystick::ffResetRumble()
{
#ifdef HAVE_FF_EFFECT_RUMBLE
  /* Erase old effects before closing a device,
   * if we had any, then initialize the ff_rumble struct.
   */
  if (ffHasRumble() && ff_rumble->id != -1) {

    /* Stop the effect first */
    struct input_event event;
    event.type = EV_FF;
    event.code = ff_rumble->id;
    event.value = 0;
    write(joystickfd, &event, sizeof(event));

    /* Erase the downloaded effect */
    ioctl(joystickfd, EVIOCRMFF, ff_rumble->id);
  }

  /* Reinit the ff_rumble struct. It starts out with
   * an id of -1, prompting the driver to assign us one.
   * Once that happens, we stick with the same effect slot
   * as long as we have the device open.
   */
  memset(ff_rumble, 0, sizeof(*ff_rumble));
  ff_rumble->type = FF_RUMBLE;
  ff_rumble->id = -1;
#endif
}

#ifdef HAVE_FF_EFFECT_RUMBLE
void                    EvdevJoystick::ffRumble(int count,
						float delay, float duration,
						float strong_motor,
						float weak_motor)
{
  if (!ffHasRumble())
    return;

  /* Stop the previous effect we were playing, if any */
  if (ff_rumble->id != -1) {
    struct input_event event;
    event.type = EV_FF;
    event.code = ff_rumble->id;
    event.value = 0;
    write(joystickfd, &event, sizeof(event));
  }

  if (count > 0) {
    /* Download an updated effect */
    ff_rumble->u.rumble.strong_magnitude = (int) (0xFFFF * strong_motor + 0.5);
    ff_rumble->u.rumble.weak_magnitude = (int) (0xFFFF * weak_motor + 0.5);
    ff_rumble->replay.length = (int) (duration * 1000 + 0.5);
    ff_rumble->replay.delay = (int) (delay * 1000 + 0.5);
    ioctl(joystickfd, EVIOCSFF, ff_rumble);

    /* Play it the indicated number of times */
    struct input_event event;
    event.type = EV_FF;
    event.code = ff_rumble->id;
    event.value = count;
    write(joystickfd, &event, sizeof(event));
  }
}
#else
void EvdevJoystick::ffRumble(int, float, float, float, float)
{
}
#endif

#endif /* HAVE_LINUX_INPUT_H */

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "gitcommand.h"
#include "gitconstants.h"

#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/synchronousprocess.h>

#include <QtCore/QDebug>
#include <QtCore/QProcess>
#include <QtCore/QFuture>
#include <QtCore/QtConcurrentRun>
#include <QtCore/QFileInfo>
#include <QtCore/QCoreApplication>

Q_DECLARE_METATYPE(QVariant)

namespace Git {
namespace Internal {

static QString msgTermination(int exitCode, const QString &binaryPath, const QStringList &args)
{
    QString cmd = QFileInfo(binaryPath).baseName();
    if (!args.empty()) {
        cmd += QLatin1Char(' ');
        cmd += args.front();
    }
    return exitCode ?
            QCoreApplication::translate("GitCommand", "\n'%1' failed (exit code %2).\n").arg(cmd).arg(exitCode) :
            QCoreApplication::translate("GitCommand", "\n'%1' completed (exit code %2).\n").arg(cmd).arg(exitCode);
}

GitCommand::Job::Job(const QStringList &a, int t) :
    arguments(a),
    timeout(t)
{
    // Finished cookie is emitted via queued slot, needs metatype
    static const int qvMetaId = qRegisterMetaType<QVariant>();
    Q_UNUSED(qvMetaId)
}

GitCommand::GitCommand(const QStringList &binary,
                        const QString &workingDirectory,
                        const QStringList &environment,
                        const QVariant &cookie)  :
    m_binaryPath(binary.front()),
    m_basicArguments(binary),
    m_workingDirectory(workingDirectory),
    m_environment(environment),
    m_cookie(cookie),
    m_reportTerminationMode(NoReport)
{
    m_basicArguments.pop_front();
}

GitCommand::TerminationReportMode GitCommand::reportTerminationMode() const
{
    return m_reportTerminationMode;
}

void GitCommand::setTerminationReportMode(TerminationReportMode m)
{
    m_reportTerminationMode = m;
}

void GitCommand::addJob(const QStringList &arguments, int timeout)
{
    m_jobs.push_back(Job(arguments, timeout));
}

void GitCommand::execute()
{
    if (Git::Constants::debug)
        qDebug() << "GitCommand::execute" << m_workingDirectory << m_jobs.size();

    if (m_jobs.empty())
        return;

    // For some reason QtConcurrent::run() only works on this
    QFuture<void> task = QtConcurrent::run(this, &GitCommand::run);
    const QString taskName = QLatin1String("Git ") + m_jobs.front().arguments.at(0);

    Core::ICore::instance()->progressManager()->addTask(task, taskName,
                                     QLatin1String("Git.action"));
}

QString GitCommand::msgTimeout(int seconds)
{
    return tr("Error: Git timed out after %1s.").arg(seconds);
}

void GitCommand::run()
{
    if (Git::Constants::debug)
        qDebug() << "GitCommand::run" << m_workingDirectory << m_jobs.size();
    QProcess process;
    if (!m_workingDirectory.isEmpty())
        process.setWorkingDirectory(m_workingDirectory);

    process.setEnvironment(m_environment);

    QByteArray stdOut;
    QByteArray stdErr;
    QString error;

    const int count = m_jobs.size();
    int exitCode = -1;
    bool ok = true;
    for (int j = 0; j < count; j++) {
        if (Git::Constants::debug)
            qDebug() << "GitCommand::run" << j << '/' << count << m_jobs.at(j).arguments;

        process.start(m_binaryPath, m_basicArguments + m_jobs.at(j).arguments);
        if(!process.waitForStarted()) {
            ok = false;
            error += QString::fromLatin1("Error: \"%1\" could not be started: %2").arg(m_binaryPath, process.errorString());
            break;
        }

        process.closeWriteChannel();
        const int timeOutSeconds = m_jobs.at(j).timeout;
        if (!Utils::SynchronousProcess::readDataFromProcess(process, timeOutSeconds * 1000,
                                                            &stdOut, &stdErr)) {
            Utils::SynchronousProcess::stopProcess(process);
            ok = false;
            error += msgTimeout(timeOutSeconds);
            break;
        }

        error += QString::fromLocal8Bit(stdErr);
        exitCode = process.exitCode();
        switch (m_reportTerminationMode) {
        case NoReport:
            break;
        case ReportStdout:
            stdOut += msgTermination(exitCode, m_binaryPath, m_jobs.at(j).arguments).toUtf8();
            break;
        case ReportStderr:
            error += msgTermination(exitCode, m_binaryPath, m_jobs.at(j).arguments);
            break;
        }
    }

    // Special hack: Always produce output for diff
    if (ok && stdOut.isEmpty() && m_jobs.front().arguments.at(0) == QLatin1String("diff")) {
        stdOut += "The file does not differ from HEAD";
    } else {
        // @TODO: Remove, see below
        if (ok && m_jobs.front().arguments.at(0) == QLatin1String("status"))
            removeColorCodes(&stdOut);
    }

    if (ok && !stdOut.isEmpty())
        emit outputData(stdOut);

    if (!error.isEmpty())
        emit errorText(error);

    emit finished(ok, exitCode, m_cookie);
    if (ok)
        emit success();
    // As it is used asynchronously, we need to delete ourselves
    this->deleteLater();
}

// Clean output from carriage return and ANSI color codes.
// @TODO: Remove once all relevant commands support "--no-color",
//("status" is  missing it as of git 1.6.2)

void GitCommand::removeColorCodes(QByteArray *data)
{
    // Remove ansi color codes that look like "ESC[<stuff>m"
    const QByteArray ansiColorEscape("\033[");
    int escapePos = 0;
    while (true) {
        const int nextEscapePos = data->indexOf(ansiColorEscape, escapePos);
        if (nextEscapePos == -1)
            break;
        const int endEscapePos = data->indexOf('m', nextEscapePos + ansiColorEscape.size());
        if (endEscapePos != -1) {
            data->remove(nextEscapePos, endEscapePos - nextEscapePos + 1);
            escapePos = nextEscapePos;
        } else {
            escapePos = nextEscapePos + ansiColorEscape.size();
        }
    }
}

void GitCommand::setCookie(const QVariant &cookie)
{
    m_cookie = cookie;
}

QVariant GitCommand::cookie() const
{
    return m_cookie;
}

} // namespace Internal
} // namespace Git
<commit_msg>Git: Fix misleading status message.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "gitcommand.h"
#include "gitconstants.h"

#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/synchronousprocess.h>

#include <QtCore/QDebug>
#include <QtCore/QProcess>
#include <QtCore/QFuture>
#include <QtCore/QtConcurrentRun>
#include <QtCore/QFileInfo>
#include <QtCore/QCoreApplication>

Q_DECLARE_METATYPE(QVariant)

namespace Git {
namespace Internal {

static QString msgTermination(int exitCode, const QString &binaryPath, const QStringList &args)
{
    QString cmd = QFileInfo(binaryPath).baseName();
    if (!args.empty()) {
        cmd += QLatin1Char(' ');
        cmd += args.front();
    }
    return exitCode ?
            QCoreApplication::translate("GitCommand", "\n'%1' failed (exit code %2).\n").arg(cmd).arg(exitCode) :
            QCoreApplication::translate("GitCommand", "\n'%1' completed (exit code %2).\n").arg(cmd).arg(exitCode);
}

GitCommand::Job::Job(const QStringList &a, int t) :
    arguments(a),
    timeout(t)
{
    // Finished cookie is emitted via queued slot, needs metatype
    static const int qvMetaId = qRegisterMetaType<QVariant>();
    Q_UNUSED(qvMetaId)
}

GitCommand::GitCommand(const QStringList &binary,
                        const QString &workingDirectory,
                        const QStringList &environment,
                        const QVariant &cookie)  :
    m_binaryPath(binary.front()),
    m_basicArguments(binary),
    m_workingDirectory(workingDirectory),
    m_environment(environment),
    m_cookie(cookie),
    m_reportTerminationMode(NoReport)
{
    m_basicArguments.pop_front();
}

GitCommand::TerminationReportMode GitCommand::reportTerminationMode() const
{
    return m_reportTerminationMode;
}

void GitCommand::setTerminationReportMode(TerminationReportMode m)
{
    m_reportTerminationMode = m;
}

void GitCommand::addJob(const QStringList &arguments, int timeout)
{
    m_jobs.push_back(Job(arguments, timeout));
}

void GitCommand::execute()
{
    if (Git::Constants::debug)
        qDebug() << "GitCommand::execute" << m_workingDirectory << m_jobs.size();

    if (m_jobs.empty())
        return;

    // For some reason QtConcurrent::run() only works on this
    QFuture<void> task = QtConcurrent::run(this, &GitCommand::run);
    const QString taskName = QLatin1String("Git ") + m_jobs.front().arguments.at(0);

    Core::ICore::instance()->progressManager()->addTask(task, taskName,
                                     QLatin1String("Git.action"));
}

QString GitCommand::msgTimeout(int seconds)
{
    return tr("Error: Git timed out after %1s.").arg(seconds);
}

void GitCommand::run()
{
    if (Git::Constants::debug)
        qDebug() << "GitCommand::run" << m_workingDirectory << m_jobs.size();
    QProcess process;
    if (!m_workingDirectory.isEmpty())
        process.setWorkingDirectory(m_workingDirectory);

    process.setEnvironment(m_environment);

    QByteArray stdOut;
    QByteArray stdErr;
    QString error;

    const int count = m_jobs.size();
    int exitCode = -1;
    bool ok = true;
    for (int j = 0; j < count; j++) {
        if (Git::Constants::debug)
            qDebug() << "GitCommand::run" << j << '/' << count << m_jobs.at(j).arguments;

        process.start(m_binaryPath, m_basicArguments + m_jobs.at(j).arguments);
        if(!process.waitForStarted()) {
            ok = false;
            error += QString::fromLatin1("Error: \"%1\" could not be started: %2").arg(m_binaryPath, process.errorString());
            break;
        }

        process.closeWriteChannel();
        const int timeOutSeconds = m_jobs.at(j).timeout;
        if (!Utils::SynchronousProcess::readDataFromProcess(process, timeOutSeconds * 1000,
                                                            &stdOut, &stdErr)) {
            Utils::SynchronousProcess::stopProcess(process);
            ok = false;
            error += msgTimeout(timeOutSeconds);
            break;
        }

        error += QString::fromLocal8Bit(stdErr);
        exitCode = process.exitCode();
        switch (m_reportTerminationMode) {
        case NoReport:
            break;
        case ReportStdout:
            stdOut += msgTermination(exitCode, m_binaryPath, m_jobs.at(j).arguments).toUtf8();
            break;
        case ReportStderr:
            error += msgTermination(exitCode, m_binaryPath, m_jobs.at(j).arguments);
            break;
        }
    }

    // Special hack: Always produce output for diff
    if (ok && stdOut.isEmpty() && m_jobs.front().arguments.at(0) == QLatin1String("diff")) {
        stdOut += "No difference to HEAD";
    } else {
        // @TODO: Remove, see below
        if (ok && m_jobs.front().arguments.at(0) == QLatin1String("status"))
            removeColorCodes(&stdOut);
    }

    if (ok && !stdOut.isEmpty())
        emit outputData(stdOut);

    if (!error.isEmpty())
        emit errorText(error);

    emit finished(ok, exitCode, m_cookie);
    if (ok)
        emit success();
    // As it is used asynchronously, we need to delete ourselves
    this->deleteLater();
}

// Clean output from carriage return and ANSI color codes.
// @TODO: Remove once all relevant commands support "--no-color",
//("status" is  missing it as of git 1.6.2)

void GitCommand::removeColorCodes(QByteArray *data)
{
    // Remove ansi color codes that look like "ESC[<stuff>m"
    const QByteArray ansiColorEscape("\033[");
    int escapePos = 0;
    while (true) {
        const int nextEscapePos = data->indexOf(ansiColorEscape, escapePos);
        if (nextEscapePos == -1)
            break;
        const int endEscapePos = data->indexOf('m', nextEscapePos + ansiColorEscape.size());
        if (endEscapePos != -1) {
            data->remove(nextEscapePos, endEscapePos - nextEscapePos + 1);
            escapePos = nextEscapePos;
        } else {
            escapePos = nextEscapePos + ansiColorEscape.size();
        }
    }
}

void GitCommand::setCookie(const QVariant &cookie)
{
    m_cookie = cookie;
}

QVariant GitCommand::cookie() const
{
    return m_cookie;
}

} // namespace Internal
} // namespace Git
<|endoftext|>


<commit_before>#include "SkFontHost.h"
#include <math.h>

// define this to use pre-compiled tables for gamma. This is slightly faster,
// and doesn't create any RW global memory, but means we cannot change the
// gamma at runtime.
#define USE_PREDEFINED_GAMMA_TABLES

#ifndef USE_PREDEFINED_GAMMA_TABLES
    // define this if you want to spew out the "C" code for the tables, given
    // the current values for SK_BLACK_GAMMA and SK_WHITE_GAMMA.
    #define DUMP_GAMMA_TABLESx
#endif

///////////////////////////////////////////////////////////////////////////////

#ifdef USE_PREDEFINED_GAMMA_TABLES

#include "sk_predefined_gamma.h"

#else   // use writable globals for gamma tables

static bool gGammaIsBuilt;
static uint8_t gBlackGamma[256], gWhiteGamma[256];

#define SK_BLACK_GAMMA     (1.4f)
#define SK_WHITE_GAMMA     (1/1.4f)

static void build_power_table(uint8_t table[], float ee)
{
    //    printf("------ build_power_table %g\n", ee);
    for (int i = 0; i < 256; i++)
    {
        float x = i / 255.f;
        //   printf(" %d %g", i, x);
        x = powf(x, ee);
        //   printf(" %g", x);
        int xx = SkScalarRound(SkFloatToScalar(x * 255));
        //   printf(" %d\n", xx);
        table[i] = SkToU8(xx);
    }
}

#ifdef DUMP_GAMMA_TABLES

#include "SkString.h"

static void dump_a_table(const char name[], const uint8_t table[],
                         float gamma) {
    SkDebugf("\n");
    SkDebugf("\/\/ Gamma table for %g\n", gamma);
    SkDebugf("static const uint8_t %s[] = {\n", name);
    for (int y = 0; y < 16; y++) {
        SkString line, tmp;
        for (int x = 0; x < 16; x++) {
            tmp.printf("0x%02X, ", *table++);
            line.append(tmp);
        }
        SkDebugf("    %s\n", line.c_str());
    }
    SkDebugf("};\n");
}

#endif

#endif

///////////////////////////////////////////////////////////////////////////////

void SkFontHost::GetGammaTables(const uint8_t* tables[2])
{
#ifndef USE_PREDEFINED_GAMMA_TABLES
    if (!gGammaIsBuilt)
    {
        build_power_table(gBlackGamma, SK_BLACK_GAMMA);
        build_power_table(gWhiteGamma, SK_WHITE_GAMMA);
        gGammaIsBuilt = true;

#ifdef DUMP_GAMMA_TABLES
        dump_a_table("gBlackGamma", gBlackGamma, SK_BLACK_GAMMA);
        dump_a_table("gWhiteGamma", gWhiteGamma, SK_WHITE_GAMMA);
#endif
    }
#endif
    tables[0] = gBlackGamma;
    tables[1] = gWhiteGamma;
}

// If the luminance is <= this value, then apply the black gamma table
#define BLACK_GAMMA_THRESHOLD   0x40

// If the luminance is >= this value, then apply the white gamma table
#define WHITE_GAMMA_THRESHOLD   0xC0

int SkFontHost::ComputeGammaFlag(const SkPaint& paint)
{
    if (paint.getShader() == NULL)
    {
        SkColor c = paint.getColor();
        int r = SkColorGetR(c);
        int g = SkColorGetG(c);
        int b = SkColorGetB(c);
        int luminance = (r * 2 + g * 5 + b) >> 3;

        if (luminance <= BLACK_GAMMA_THRESHOLD)
        {
        //    printf("------ black gamma for [%d %d %d]\n", r, g, b);
            return SkScalerContext::kGammaForBlack_Flag;
        }
        if (luminance >= WHITE_GAMMA_THRESHOLD)
        {
        //    printf("------ white gamma for [%d %d %d]\n", r, g, b);
            return SkScalerContext::kGammaForWhite_Flag;
        }
    }
    return 0;
}

<commit_msg>allow the gamma to be changed at runtime<commit_after>#include "SkFontHost.h"
#include <math.h>

// define this to use pre-compiled tables for gamma. This is slightly faster,
// and doesn't create any RW global memory, but means we cannot change the
// gamma at runtime.
//#define USE_PREDEFINED_GAMMA_TABLES

#ifndef USE_PREDEFINED_GAMMA_TABLES
    // define this if you want to spew out the "C" code for the tables, given
    // the current values for SK_BLACK_GAMMA and SK_WHITE_GAMMA.
    #define DUMP_GAMMA_TABLESx
#endif

///////////////////////////////////////////////////////////////////////////////

#include "SkGraphics.h"

// declared here, so we can link against it elsewhere
void skia_set_text_gamma(float blackGamma, float whiteGamma);

#ifdef USE_PREDEFINED_GAMMA_TABLES

#include "sk_predefined_gamma.h"

void skia_set_text_gamma(float blackGamma, float whiteGamma) {}

#else   // use writable globals for gamma tables

static void build_power_table(uint8_t table[], float ee)
{
    SkDebugf("------ build_power_table %g\n", ee);
    for (int i = 0; i < 256; i++)
    {
        float x = i / 255.f;
        //   printf(" %d %g", i, x);
        x = powf(x, ee);
        //   printf(" %g", x);
        int xx = SkScalarRound(SkFloatToScalar(x * 255));
        //   printf(" %d\n", xx);
        table[i] = SkToU8(xx);
    }
}

static bool gGammaIsBuilt;
static uint8_t gBlackGamma[256], gWhiteGamma[256];

static float gBlackGammaCoeff = 1.4f;
static float gWhiteGammaCoeff = 1/1.4f;

void skia_set_text_gamma(float blackGamma, float whiteGamma) {
    gBlackGammaCoeff = blackGamma;
    gWhiteGammaCoeff = whiteGamma;
    gGammaIsBuilt = false;
    SkGraphics::SetFontCacheUsed(0);
    build_power_table(gBlackGamma, gBlackGammaCoeff);
    build_power_table(gWhiteGamma, gWhiteGammaCoeff);
}

#ifdef DUMP_GAMMA_TABLES

#include "SkString.h"

static void dump_a_table(const char name[], const uint8_t table[],
                         float gamma) {
    SkDebugf("\n");
    SkDebugf("\/\/ Gamma table for %g\n", gamma);
    SkDebugf("static const uint8_t %s[] = {\n", name);
    for (int y = 0; y < 16; y++) {
        SkString line, tmp;
        for (int x = 0; x < 16; x++) {
            tmp.printf("0x%02X, ", *table++);
            line.append(tmp);
        }
        SkDebugf("    %s\n", line.c_str());
    }
    SkDebugf("};\n");
}

#endif

#endif

///////////////////////////////////////////////////////////////////////////////

void SkFontHost::GetGammaTables(const uint8_t* tables[2])
{
#ifndef USE_PREDEFINED_GAMMA_TABLES
    if (!gGammaIsBuilt)
    {
        build_power_table(gBlackGamma, gBlackGammaCoeff);
        build_power_table(gWhiteGamma, gWhiteGammaCoeff);
        gGammaIsBuilt = true;

#ifdef DUMP_GAMMA_TABLES
        dump_a_table("gBlackGamma", gBlackGamma, gBlackGammaCoeff);
        dump_a_table("gWhiteGamma", gWhiteGamma, gWhiteGammaCoeff);
#endif
    }
#endif
    tables[0] = gBlackGamma;
    tables[1] = gWhiteGamma;
}

// If the luminance is <= this value, then apply the black gamma table
#define BLACK_GAMMA_THRESHOLD   0x40

// If the luminance is >= this value, then apply the white gamma table
#define WHITE_GAMMA_THRESHOLD   0xC0

int SkFontHost::ComputeGammaFlag(const SkPaint& paint)
{
    if (paint.getShader() == NULL)
    {
        SkColor c = paint.getColor();
        int r = SkColorGetR(c);
        int g = SkColorGetG(c);
        int b = SkColorGetB(c);
        int luminance = (r * 2 + g * 5 + b) >> 3;

        if (luminance <= BLACK_GAMMA_THRESHOLD)
        {
        //    printf("------ black gamma for [%d %d %d]\n", r, g, b);
            return SkScalerContext::kGammaForBlack_Flag;
        }
        if (luminance >= WHITE_GAMMA_THRESHOLD)
        {
        //    printf("------ white gamma for [%d %d %d]\n", r, g, b);
            return SkScalerContext::kGammaForWhite_Flag;
        }
    }
    return 0;
}

<|endoftext|>


<commit_before>/// Gets a shared vector for a row
SHAREDVECTORN row(unsigned i)
{
  // get the starting offset
  const unsigned OFFSET = data() - _data.get();

  SHAREDVECTORN v;
  v._data = _data;
  v._start = OFFSET + i;
  v._inc = leading_dim();
  v._len = _columns;
  return v;
}

/// Gets a constant shared vector for a row
CONST_SHAREDVECTORN row(unsigned i) const
{
  // get the starting offset
  const unsigned OFFSET = data() - _data.get();

  CONST_SHAREDVECTORN v;
  v._data = _data;
  v._start = OFFSET + i;
  v._inc = leading_dim();
  v._len = _columns;
  return v;
}

/// Gets a shared vector for a column
SHAREDVECTORN column(unsigned i)
{
  // get the starting offset
  const unsigned OFFSET = data() - _data.get();

  SHAREDVECTORN v;
  v._data = _data;
  v._start = OFFSET + leading_dim() * i;
  v._inc = 1;
  v._len = _rows;
  return v;
}

/// Gets a shared vector for a column
CONST_SHAREDVECTORN column(unsigned i) const
{
  // get the starting offset
  const unsigned OFFSET = data() - _data.get();

  CONST_SHAREDVECTORN v;
  v._data = _data;
  v._start = OFFSET + leading_dim() * i;
  v._inc = 1;
  v._len = _rows;
  return v;
}

/// Gets a block as a shared matrix
SHAREDMATRIXN block(unsigned row_start, unsigned row_end, unsigned col_start, unsigned col_end)
{
  #ifndef NEXCEPT
  if (row_end < row_start || row_end > _rows || col_end < col_start || col_end > _columns)
    throw InvalidIndexException();
  #endif

  // determine the offset
  const unsigned OFFSET = data() - _data.get();

  SHAREDMATRIXN m;
  m._data = _data;
  m._rows = row_end - row_start;
  m._columns = col_end - col_start;
  m._ld = leading_dim();
  m._start = OFFSET + m._ld * col_start + row_start;
  return m;
}

/// Gets a block as a constant shared matrix
CONST_SHAREDMATRIXN block(unsigned row_start, unsigned row_end, unsigned col_start, unsigned col_end) const
{
  #ifndef NEXCEPT
  if (row_end < row_start || row_end > _rows || col_end < col_start || col_end > _columns)
    throw InvalidIndexException();
  #endif

  // determine the offset
  const unsigned OFFSET = data() - _data.get();

  CONST_SHAREDMATRIXN m;
  m._data = _data;
  m._rows = row_end - row_start;
  m._columns = col_end - col_start;
  m._ld = leading_dim();
  m._start = OFFSET + m._ld * col_start + row_start;
  return m;
}

/// Get an iterator to the beginning
ITERATOR begin()
{
  ITERATOR i;
  i._count = 0;
  i._sz = _rows*_columns;
  i._ld = leading_dim();
  i._rows = _rows;
  i._columns = _columns;
  i._data_start = i._current_data = data();
  return i;
}

/// Get an iterator to the end
ITERATOR end()
{
  ITERATOR i;
  i._sz = _rows*_columns;
  i._count = i._sz;
  i._ld = leading_dim();
  i._rows = _rows;
  i._columns = _columns;
  i._data_start = data();
  i._current_data = data() + i._ld*i._columns;
  return i;
}

/// Get an iterator to the beginning
CONST_ITERATOR begin() const
{
  CONST_ITERATOR i;
  i._count = 0;
  i._sz = _rows*_columns;
  i._ld = leading_dim();
  i._rows = _rows;
  i._columns = _columns;
  i._data_start = i._current_data = data();
  return i;
}

/// Get an iterator to the end
CONST_ITERATOR end() const
{
  CONST_ITERATOR i;
  i._sz = _rows*_columns;
  i._count = i._sz;
  i._ld = leading_dim();
  i._rows = _rows;
  i._columns = _columns;
  i._data_start = data();
  i._current_data = data() + i._ld*i._columns;
  return i;
}

/// Sets a matrix from a vector
template <class V>
XMATRIXN& set(const V& v, Transposition trans)
{
  #ifndef NEXCEPT
  if (sizeof(data()) != sizeof(v.data()))
    throw DataMismatchException();
  #endif

  // resize the matrix
  if (trans == eNoTranspose)
    resize(v.size(), 1);
  else
    resize(1, v.size());

  if (_rows > 0 && _columns > 0)
    CBLAS::copy(v.size(), v.data(), 1, _data.get(), 1);

  return *this;
}

/// Determines the transpose of a matrix and stores the result in a given matrix
template <class M>
static M& transpose(const XMATRIXN& m, M& result)
{
  #ifndef NEXCEPT
  if (sizeof(m.data()) != sizeof(result.data()))
    throw DataMismatchException();
  #endif

  // resize the result
  result.resize(m.columns(), m.rows());

  const REAL* mdata = m.data();
  REAL* rdata = result.data();
  for  (unsigned i=0; i< m.rows(); i++)
    for (unsigned j=0; j< m.columns(); j++)
      rdata[i*result.leading_dim()+j] = mdata[j*m.leading_dim()+i];

  return result;
}

/// Adds m to *this in place
template <class M>
XMATRIXN& operator+=(const M& m)
{
  #ifndef NEXCEPT
  if (_rows != m.rows() || _columns != m.columns())
    throw MissizeException();
  if (sizeof(data()) != sizeof(m.data()))
    throw DataMismatchException();
  #endif

  if (_rows > 0 && _columns > 0)
    std::transform(begin(), end(), m.begin(), begin(), std::plus<REAL>());
  return *this;
}

/// Subtracts m from *this in place
template <class M>
XMATRIXN& operator-=(const M& m)
{
  #ifndef NEXCEPT
  if (_rows != m.rows() || _columns != m.columns())
    throw MissizeException();
  if (sizeof(data()) != sizeof(m.data()))
    throw DataMismatchException();
  #endif

  if (_rows > 0 && _columns > 0)
    std::transform(begin(), end(), m.begin(), begin(), std::minus<REAL>());
  return *this;
}

/// Multiplies the diagonal matrix formed from d by the matrix m
template <class V, class W>
static W& diag_mult(const V& d, const XMATRIXN& m, W& result)
{
  #ifndef NEXCEPT
  if (d.size() != m.rows())
    throw MissizeException();
  if (sizeof(d.data()) != sizeof(m.data()))
    throw DataMismatchException();
  #endif

  result.resize(d.size(), m.columns());
  for (unsigned i=0; i< m.columns(); i++)
    std::transform(d.begin(), d.end(), m.begin()+m.rows()*i, result.begin()+result.rows()*i, std::multiplies<REAL>());

  return result;
}

/// Multiplies the diagonal matrix formed from d by the matrix transpose(m)
template <class V, class W>
static W& diag_mult_transpose(const V& d, const XMATRIXN& m, W& result)
{
  #ifndef NEXCEPT
  if (d.size() != m.columns())
    throw MissizeException();
  if (sizeof(d.data()) != sizeof(m.data()))
    throw DataMismatchException();
  #endif

  // copy the transpose of m to the result
  XMATRIXN::transpose(m, result);

  // do the specified number of times
  for (unsigned i=0; i< m.rows(); i++)
    CBLAS::scal(d.size(), d[i], result.begin()+i, result.rows());

  return result;
}

/// Multiplies the diagonal matrix formed from d by the vector v
template <class V, class U, class W>
static W& diag_mult(const V& d, const U& v, W& result)
{
  #ifndef NEXCEPT
  if (d.size() != v.size())
    throw MissizeException();
  if (sizeof(d.data()) != sizeof(v.data()))
    throw DataMismatchException();
  if (sizeof(d.data()) != sizeof(result.data()))
    throw DataMismatchException();
  #endif

  result.resize(d.size());
  std::transform(d.begin(), d.end(), v.begin(), result.begin(), std::multiplies<REAL>());
  return result;
}

<commit_msg>Fixed compile bug in MatrixN::diag_mult_transpose()?<commit_after>/// Gets a shared vector for a row
SHAREDVECTORN row(unsigned i)
{
  // get the starting offset
  const unsigned OFFSET = data() - _data.get();

  SHAREDVECTORN v;
  v._data = _data;
  v._start = OFFSET + i;
  v._inc = leading_dim();
  v._len = _columns;
  return v;
}

/// Gets a constant shared vector for a row
CONST_SHAREDVECTORN row(unsigned i) const
{
  // get the starting offset
  const unsigned OFFSET = data() - _data.get();

  CONST_SHAREDVECTORN v;
  v._data = _data;
  v._start = OFFSET + i;
  v._inc = leading_dim();
  v._len = _columns;
  return v;
}

/// Gets a shared vector for a column
SHAREDVECTORN column(unsigned i)
{
  // get the starting offset
  const unsigned OFFSET = data() - _data.get();

  SHAREDVECTORN v;
  v._data = _data;
  v._start = OFFSET + leading_dim() * i;
  v._inc = 1;
  v._len = _rows;
  return v;
}

/// Gets a shared vector for a column
CONST_SHAREDVECTORN column(unsigned i) const
{
  // get the starting offset
  const unsigned OFFSET = data() - _data.get();

  CONST_SHAREDVECTORN v;
  v._data = _data;
  v._start = OFFSET + leading_dim() * i;
  v._inc = 1;
  v._len = _rows;
  return v;
}

/// Gets a block as a shared matrix
SHAREDMATRIXN block(unsigned row_start, unsigned row_end, unsigned col_start, unsigned col_end)
{
  #ifndef NEXCEPT
  if (row_end < row_start || row_end > _rows || col_end < col_start || col_end > _columns)
    throw InvalidIndexException();
  #endif

  // determine the offset
  const unsigned OFFSET = data() - _data.get();

  SHAREDMATRIXN m;
  m._data = _data;
  m._rows = row_end - row_start;
  m._columns = col_end - col_start;
  m._ld = leading_dim();
  m._start = OFFSET + m._ld * col_start + row_start;
  return m;
}

/// Gets a block as a constant shared matrix
CONST_SHAREDMATRIXN block(unsigned row_start, unsigned row_end, unsigned col_start, unsigned col_end) const
{
  #ifndef NEXCEPT
  if (row_end < row_start || row_end > _rows || col_end < col_start || col_end > _columns)
    throw InvalidIndexException();
  #endif

  // determine the offset
  const unsigned OFFSET = data() - _data.get();

  CONST_SHAREDMATRIXN m;
  m._data = _data;
  m._rows = row_end - row_start;
  m._columns = col_end - col_start;
  m._ld = leading_dim();
  m._start = OFFSET + m._ld * col_start + row_start;
  return m;
}

/// Get an iterator to the beginning
ITERATOR begin()
{
  ITERATOR i;
  i._count = 0;
  i._sz = _rows*_columns;
  i._ld = leading_dim();
  i._rows = _rows;
  i._columns = _columns;
  i._data_start = i._current_data = data();
  return i;
}

/// Get an iterator to the end
ITERATOR end()
{
  ITERATOR i;
  i._sz = _rows*_columns;
  i._count = i._sz;
  i._ld = leading_dim();
  i._rows = _rows;
  i._columns = _columns;
  i._data_start = data();
  i._current_data = data() + i._ld*i._columns;
  return i;
}

/// Get an iterator to the beginning
CONST_ITERATOR begin() const
{
  CONST_ITERATOR i;
  i._count = 0;
  i._sz = _rows*_columns;
  i._ld = leading_dim();
  i._rows = _rows;
  i._columns = _columns;
  i._data_start = i._current_data = data();
  return i;
}

/// Get an iterator to the end
CONST_ITERATOR end() const
{
  CONST_ITERATOR i;
  i._sz = _rows*_columns;
  i._count = i._sz;
  i._ld = leading_dim();
  i._rows = _rows;
  i._columns = _columns;
  i._data_start = data();
  i._current_data = data() + i._ld*i._columns;
  return i;
}

/// Sets a matrix from a vector
template <class V>
XMATRIXN& set(const V& v, Transposition trans)
{
  #ifndef NEXCEPT
  if (sizeof(data()) != sizeof(v.data()))
    throw DataMismatchException();
  #endif

  // resize the matrix
  if (trans == eNoTranspose)
    resize(v.size(), 1);
  else
    resize(1, v.size());

  if (_rows > 0 && _columns > 0)
    CBLAS::copy(v.size(), v.data(), 1, _data.get(), 1);

  return *this;
}

/// Determines the transpose of a matrix and stores the result in a given matrix
template <class M>
static M& transpose(const XMATRIXN& m, M& result)
{
  #ifndef NEXCEPT
  if (sizeof(m.data()) != sizeof(result.data()))
    throw DataMismatchException();
  #endif

  // resize the result
  result.resize(m.columns(), m.rows());

  const REAL* mdata = m.data();
  REAL* rdata = result.data();
  for  (unsigned i=0; i< m.rows(); i++)
    for (unsigned j=0; j< m.columns(); j++)
      rdata[i*result.leading_dim()+j] = mdata[j*m.leading_dim()+i];

  return result;
}

/// Adds m to *this in place
template <class M>
XMATRIXN& operator+=(const M& m)
{
  #ifndef NEXCEPT
  if (_rows != m.rows() || _columns != m.columns())
    throw MissizeException();
  if (sizeof(data()) != sizeof(m.data()))
    throw DataMismatchException();
  #endif

  if (_rows > 0 && _columns > 0)
    std::transform(begin(), end(), m.begin(), begin(), std::plus<REAL>());
  return *this;
}

/// Subtracts m from *this in place
template <class M>
XMATRIXN& operator-=(const M& m)
{
  #ifndef NEXCEPT
  if (_rows != m.rows() || _columns != m.columns())
    throw MissizeException();
  if (sizeof(data()) != sizeof(m.data()))
    throw DataMismatchException();
  #endif

  if (_rows > 0 && _columns > 0)
    std::transform(begin(), end(), m.begin(), begin(), std::minus<REAL>());
  return *this;
}

/// Multiplies the diagonal matrix formed from d by the matrix m
template <class V, class W>
static W& diag_mult(const V& d, const XMATRIXN& m, W& result)
{
  #ifndef NEXCEPT
  if (d.size() != m.rows())
    throw MissizeException();
  if (sizeof(d.data()) != sizeof(m.data()))
    throw DataMismatchException();
  #endif

  result.resize(d.size(), m.columns());
  for (unsigned i=0; i< m.columns(); i++)
    std::transform(d.begin(), d.end(), m.begin()+m.rows()*i, result.begin()+result.rows()*i, std::multiplies<REAL>());

  return result;
}

/// Multiplies the diagonal matrix formed from d by the matrix transpose(m)
template <class V, class W>
static W& diag_mult_transpose(const V& d, const XMATRIXN& m, W& result)
{
  #ifndef NEXCEPT
  if (d.size() != m.columns())
    throw MissizeException();
  if (sizeof(d.data()) != sizeof(m.data()))
    throw DataMismatchException();
  #endif

  // copy the transpose of m to the result
  XMATRIXN::transpose(m, result);

  // do the specified number of times
  for (unsigned i=0; i< m.rows(); i++)
    CBLAS::scal(d.size(), d[i], result.data()+i, result.lda());

  return result;
}

/// Multiplies the diagonal matrix formed from d by the vector v
template <class V, class U, class W>
static W& diag_mult(const V& d, const U& v, W& result)
{
  #ifndef NEXCEPT
  if (d.size() != v.size())
    throw MissizeException();
  if (sizeof(d.data()) != sizeof(v.data()))
    throw DataMismatchException();
  if (sizeof(d.data()) != sizeof(result.data()))
    throw DataMismatchException();
  #endif

  result.resize(d.size());
  std::transform(d.begin(), d.end(), v.begin(), result.begin(), std::multiplies<REAL>());
  return result;
}

<|endoftext|>


<commit_before>/****************************************************************************
 *   Copyright (C) 2012-2015 by Savoir-Faire Linux                          *
 *   Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com>      *
 *                                                                          *
 *   This library is free software; you can redistribute it and/or          *
 *   modify it under the terms of the GNU Lesser General Public             *
 *   License as published by the Free Software Foundation; either           *
 *   version 2.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 General Public License      *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/
#include "directrenderer.h"

#include <QtCore/QDebug>
#include <QtCore/QMutex>
#include <QtCore/QThread>
#include <QtCore/QTime>
#include <QtCore/QTimer>

#include <cstring>

#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#endif

#include "private/videorenderermanager.h"
#include "video/resolution.h"
#include "private/videorenderer_p.h"

namespace Video {

class DirectRendererPrivate : public QObject
{
   Q_OBJECT
public:
   DirectRendererPrivate(Video::DirectRenderer* parent);
private:
//    Video::DirectRenderer* q_ptr;
};

}

Video::DirectRendererPrivate::DirectRendererPrivate(Video::DirectRenderer* parent) : QObject(parent)/*, q_ptr(parent)*/
{
}

///Constructor
Video::DirectRenderer::DirectRenderer(const QByteArray& id, const QSize& res): Renderer(id, res), d_ptr(new DirectRendererPrivate(this))
{
   setObjectName("Video::DirectRenderer:"+id);
}

///Destructor
Video::DirectRenderer::~DirectRenderer()
{
}

void Video::DirectRenderer::startRendering()
{
   Video::Renderer::d_ptr->m_isRendering = true;
   emit started();
}
void Video::DirectRenderer::stopRendering ()
{
   Video::Renderer::d_ptr->m_isRendering = false;
   emit stopped();
}

void Video::DirectRenderer::onNewFrame(const std::shared_ptr<std::vector<unsigned char> >& frame, int w, int h)
{
   if (!isRendering()) {
      return;
   }

   Video::Renderer::d_ptr->m_pSize.setWidth(w);
   Video::Renderer::d_ptr->m_pSize.setHeight(h);
   Video::Renderer::d_ptr->m_pSFrame = frame;
   emit frameUpdated();
}

Video::Renderer::ColorSpace Video::DirectRenderer::colorSpace() const
{
   return Video::Renderer::ColorSpace::RGBA;
}

#include <directrenderer.moc>
<commit_msg>video: return the correct colorspace<commit_after>/****************************************************************************
 *   Copyright (C) 2012-2015 by Savoir-Faire Linux                          *
 *   Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com>      *
 *                                                                          *
 *   This library is free software; you can redistribute it and/or          *
 *   modify it under the terms of the GNU Lesser General Public             *
 *   License as published by the Free Software Foundation; either           *
 *   version 2.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 General Public License      *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/
#include "directrenderer.h"

#include <QtCore/QDebug>
#include <QtCore/QMutex>
#include <QtCore/QThread>
#include <QtCore/QTime>
#include <QtCore/QTimer>

#include <cstring>

#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#endif

#include "private/videorenderermanager.h"
#include "video/resolution.h"
#include "private/videorenderer_p.h"

namespace Video {

class DirectRendererPrivate : public QObject
{
   Q_OBJECT
public:
   DirectRendererPrivate(Video::DirectRenderer* parent);
private:
//    Video::DirectRenderer* q_ptr;
};

}

Video::DirectRendererPrivate::DirectRendererPrivate(Video::DirectRenderer* parent) : QObject(parent)/*, q_ptr(parent)*/
{
}

///Constructor
Video::DirectRenderer::DirectRenderer(const QByteArray& id, const QSize& res): Renderer(id, res), d_ptr(new DirectRendererPrivate(this))
{
   setObjectName("Video::DirectRenderer:"+id);
}

///Destructor
Video::DirectRenderer::~DirectRenderer()
{
}

void Video::DirectRenderer::startRendering()
{
   Video::Renderer::d_ptr->m_isRendering = true;
   emit started();
}
void Video::DirectRenderer::stopRendering ()
{
   Video::Renderer::d_ptr->m_isRendering = false;
   emit stopped();
}

void Video::DirectRenderer::onNewFrame(const std::shared_ptr<std::vector<unsigned char> >& frame, int w, int h)
{
   if (!isRendering()) {
      return;
   }

   Video::Renderer::d_ptr->m_pSize.setWidth(w);
   Video::Renderer::d_ptr->m_pSize.setHeight(h);
   Video::Renderer::d_ptr->m_pSFrame = frame;
   emit frameUpdated();
}

Video::Renderer::ColorSpace Video::DirectRenderer::colorSpace() const
{
#ifdef Q_OS_DARWIN
   return Video::Renderer::ColorSpace::RGBA;
#else
   return Video::Renderer::ColorSpace::BGRA;
#endif
}

#include <directrenderer.moc>
<|endoftext|>


<commit_before>#ifndef OSRM_CONTRACTOR_FILES_HPP
#define OSRM_CONTRACTOR_FILES_HPP

#include "contractor/query_graph.hpp"

#include "util/serialization.hpp"

#include "storage/io.hpp"

namespace osrm
{
namespace contractor
{
namespace files
{

// reads .osrm.hsgr file
template<storage::Ownership Ownership>
inline void readGraph(const boost::filesystem::path &path,
                      unsigned &checksum,
                      detail::QueryGraph<Ownership> &graph)
{
    const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
    storage::io::FileReader reader{path, fingerprint};

    reader.ReadInto(checksum);
    util::serialization::read(reader, graph);
}

// writes .osrm.hsgr file
template<storage::Ownership Ownership>
inline void writeGraph(const boost::filesystem::path &path,
                       unsigned checksum,
                       const detail::QueryGraph<Ownership> &graph)
{
    const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
    storage::io::FileWriter writer{path, fingerprint};

    writer.WriteOne(checksum);
    util::serialization::write(writer, graph);
}

}
}
}

#endif
<commit_msg>Fix readGraph to not use UseSharedMemory<commit_after>#ifndef OSRM_CONTRACTOR_FILES_HPP
#define OSRM_CONTRACTOR_FILES_HPP

#include "contractor/query_graph.hpp"

#include "util/serialization.hpp"

#include "storage/io.hpp"

namespace osrm
{
namespace contractor
{
namespace files
{

// reads .osrm.hsgr file
template <typename QueryGraphT>
inline void readGraph(const boost::filesystem::path &path, unsigned &checksum, QueryGraphT &graph)
{
    static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
                      std::is_same<QueryGraph, QueryGraphT>::value,
                  "graph must be of type QueryGraph<>");

    const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
    storage::io::FileReader reader{path, fingerprint};

    reader.ReadInto(checksum);
    util::serialization::read(reader, graph);
}

// writes .osrm.hsgr file
template <typename QueryGraphT>
inline void
writeGraph(const boost::filesystem::path &path, unsigned checksum, const QueryGraphT &graph)
{
    static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
                      std::is_same<QueryGraph, QueryGraphT>::value,
                  "graph must be of type QueryGraph<>");
    const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
    storage::io::FileWriter writer{path, fingerprint};

    writer.WriteOne(checksum);
    util::serialization::write(writer, graph);
}
}
}
}

#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_IMAGE_ANY_HPP
#define MAPNIK_IMAGE_ANY_HPP

#include <mapnik/image.hpp>
#include <mapnik/image_null.hpp>
#include <mapnik/util/variant.hpp>

namespace mapnik {

using image_base = util::variant<image_null,
                                 image_rgba8,
                                 image_gray8,
                                 image_gray8s,
                                 image_gray16,
                                 image_gray16s,
                                 image_gray32,
                                 image_gray32s,
                                 image_gray32f,
                                 image_gray64,
                                 image_gray64s,
                                 image_gray64f>;

struct MAPNIK_DECL image_any : image_base
{
    image_any() = default;

    image_any(int width,
              int height,
              image_dtype type = image_dtype_rgba8,
              bool initialize = true,
              bool premultiplied = false,
              bool painted = false);

    template <typename T>
        image_any(T && data) noexcept
        : image_base(std::move(data)) {}

    unsigned char const* bytes() const;
    unsigned char* bytes();
    std::size_t width() const;
    std::size_t height() const;
    bool get_premultiplied() const;
    bool painted() const;
    std::size_t size() const;
    std::size_t row_size() const;
    double get_offset() const;
    double get_scaling() const;
    image_dtype get_dtype() const;
    void set_offset(double val);
    void set_scaling(double val);
};

MAPNIK_DECL image_any create_image_any(int width,
                                       int height,
                                       image_dtype type = image_dtype_rgba8,
                                       bool initialize = true,
                                       bool premultiplied = false,
                                       bool painted = false);

} // end mapnik ns

#endif // MAPNIK_IMAGE_ANY_HPP
<commit_msg>fix variable shadowing in image_any<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_IMAGE_ANY_HPP
#define MAPNIK_IMAGE_ANY_HPP

#include <mapnik/image.hpp>
#include <mapnik/image_null.hpp>
#include <mapnik/util/variant.hpp>

namespace mapnik {

using image_base = util::variant<image_null,
                                 image_rgba8,
                                 image_gray8,
                                 image_gray8s,
                                 image_gray16,
                                 image_gray16s,
                                 image_gray32,
                                 image_gray32s,
                                 image_gray32f,
                                 image_gray64,
                                 image_gray64s,
                                 image_gray64f>;

struct MAPNIK_DECL image_any : image_base
{
    image_any() = default;

    image_any(int width,
              int height,
              image_dtype type = image_dtype_rgba8,
              bool initialize = true,
              bool premultiplied = false,
              bool painted = false);

    template <typename T>
        image_any(T && _data) noexcept
        : image_base(std::move(_data)) {}

    unsigned char const* bytes() const;
    unsigned char* bytes();
    std::size_t width() const;
    std::size_t height() const;
    bool get_premultiplied() const;
    bool painted() const;
    std::size_t size() const;
    std::size_t row_size() const;
    double get_offset() const;
    double get_scaling() const;
    image_dtype get_dtype() const;
    void set_offset(double val);
    void set_scaling(double val);
};

MAPNIK_DECL image_any create_image_any(int width,
                                       int height,
                                       image_dtype type = image_dtype_rgba8,
                                       bool initialize = true,
                                       bool premultiplied = false,
                                       bool painted = false);

} // end mapnik ns

#endif // MAPNIK_IMAGE_ANY_HPP
<|endoftext|>


<commit_before>#ifndef INCLUDED_U5E_UTF32_NATIVE_HPP
#define INCLUDED_U5E_UTF32_NATIVE_HPP

#include <type_traits>
#include <u5e/encoding_assertion.hpp>
#include <u5e/codepoint.hpp>

namespace u5e {
  /**
   * u5e::utf32_native
   *
   * The native utf32 encoding is built with the native 32 bit
   * integer type. It is specially more useful for cases where
   * you need to do extensive manipulation on text, since it
   * allows you to have constant random access time.
   */
  template <typename BUFFERTYPE>
  class utf32_native {
    encoding_assertion<BUFFERTYPE, int> _assertion;
  public:
    // value_type is always codepoint
    typedef codepoint value_type;
    // pointer to encoded_buffer
    typedef utf32_native<BUFFERTYPE>* pointer;
    // const pointer to encoded_buffer
    typedef const utf32_native<BUFFERTYPE>* const_pointer;
    // reference to encoded_buffer
    typedef utf32_native<BUFFERTYPE>& reference;
    // size type is always size_t, regardless of encoding, in order to
    // isolate the knowledge of the encoding from the user code
    typedef std::size_t size_type;
    // difference type is always ptrdiff_t, regardrless of encoding,
    // in order to isolate the knowledge of the encoding from the user
    // code
    typedef std::ptrdiff_t difference_type;

    // since this is the native utf32, we can just delegate this
    typedef typename BUFFERTYPE::iterator iterator;
    typedef typename BUFFERTYPE::reverse_iterator reverse_iterator;
    typedef typename BUFFERTYPE::const_iterator const_iterator;
    typedef typename BUFFERTYPE::const_reverse_iterator const_reverse_iterator;

    /**
     * Constructors
     */
    utf32_native() = default;
    utf32_native(const BUFFERTYPE& raw_buffer)
      : raw_buffer(raw_buffer) { };
    utf32_native<BUFFERTYPE>& operator=(const utf32_native<BUFFERTYPE> &other) = delete;

    inline iterator begin() {
      return iterator(raw_buffer.begin());
    }

    inline iterator end() {
      return iterator(raw_buffer.end());
    }

  private:
    // raw buffer as specified by the storage type
    BUFFERTYPE raw_buffer;
  };
}

#endif
<commit_msg>add cbegin/cend to utf32_native<commit_after>#ifndef INCLUDED_U5E_UTF32_NATIVE_HPP
#define INCLUDED_U5E_UTF32_NATIVE_HPP

#include <type_traits>
#include <u5e/encoding_assertion.hpp>
#include <u5e/codepoint.hpp>

namespace u5e {
  /**
   * u5e::utf32_native
   *
   * The native utf32 encoding is built with the native 32 bit
   * integer type. It is specially more useful for cases where
   * you need to do extensive manipulation on text, since it
   * allows you to have constant random access time.
   */
  template <typename BUFFERTYPE>
  class utf32_native {
    encoding_assertion<BUFFERTYPE, int> _assertion;
  public:
    // value_type is always codepoint
    typedef codepoint value_type;
    // pointer to encoded_buffer
    typedef utf32_native<BUFFERTYPE>* pointer;
    // const pointer to encoded_buffer
    typedef const utf32_native<BUFFERTYPE>* const_pointer;
    // reference to encoded_buffer
    typedef utf32_native<BUFFERTYPE>& reference;
    // size type is always size_t, regardless of encoding, in order to
    // isolate the knowledge of the encoding from the user code
    typedef std::size_t size_type;
    // difference type is always ptrdiff_t, regardrless of encoding,
    // in order to isolate the knowledge of the encoding from the user
    // code
    typedef std::ptrdiff_t difference_type;

    // since this is the native utf32, we can just delegate this
    typedef typename BUFFERTYPE::iterator iterator;
    typedef typename BUFFERTYPE::reverse_iterator reverse_iterator;
    typedef typename BUFFERTYPE::const_iterator const_iterator;
    typedef typename BUFFERTYPE::const_reverse_iterator const_reverse_iterator;

    /**
     * Constructors
     */
    utf32_native() = default;
    utf32_native(const BUFFERTYPE& raw_buffer)
      : raw_buffer(raw_buffer) { };
    utf32_native<BUFFERTYPE>& operator=(const utf32_native<BUFFERTYPE> &other) = delete;

    inline iterator begin() {
      return iterator(raw_buffer.begin());
    }

    inline iterator end() {
      return iterator(raw_buffer.end());
    }

    inline const_iterator cbegin() {
      return const_iterator(raw_buffer.cbegin());
    }

    inline const_iterator cend() {
      return const_iterator(raw_buffer.cend());
    }

  private:
    // raw buffer as specified by the storage type
    BUFFERTYPE raw_buffer;
  };
}

#endif
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
/// \file  test_helper.hpp
//----------------------------------------------------------------------------
/// \brief Unit test helping routines.
//----------------------------------------------------------------------------
// Author:  Serge Aleynikov
// Created: 2010-01-06
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.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

***** END LICENSE BLOCK *****
*/

#ifndef _UTXX_TEST_HELPER_HPP_
#define _UTXX_TEST_HELPER_HPP_

#include <boost/test/unit_test.hpp>

#define BOOST_CURRENT_TEST_NAME \
  boost::unit_test::framework::current_test_case().p_name->c_str()

#define UTXX_REQUIRE_NO_THROW(Expr)     \
    try { Expr; }                       \
    catch (std::exception const& e) {   \
      BOOST_MESSAGE(e.what());          \
      BOOST_REQUIRE_NO_THROW(Expr);     \
    }

#define UTXX_CHECK_NO_THROW(Expr)       \
    try { Expr; }                       \
    catch (std::exception const& e) {   \
      BOOST_MESSAGE(e.what());          \
      BOOST_CHECK_NO_THROW(Expr);       \
    }

namespace utxx {

inline long env(const char* a_var, long a_default) {
    const char* p = getenv(a_var);
    return p ? atoi(p) : a_default;
}

inline bool get_test_argv(const std::string& a_opt,
                          const std::string& a_long_opt = "") {
    int    argc = boost::unit_test::framework::master_test_suite().argc;
    char** argv = boost::unit_test::framework::master_test_suite().argv;

    if (a_opt.empty() && a_long_opt.empty()) return false;

    auto same = [=](const std::string& a, int i) {
        return !a.empty() && a == argv[i];
    };

    for (int i=1; i < argc; i++) {
        if (same(a_opt,      i)) return true;
        if (same(a_long_opt, i)) return true;
    }

    return false;
}

inline bool get_test_argv(const std::string& a_opt,
                          const std::string& a_long_opt,
                          std::string& a_value) {
    int    argc = boost::unit_test::framework::master_test_suite().argc;
    char** argv = boost::unit_test::framework::master_test_suite().argv;

    if (a_opt.empty() && a_long_opt.empty()) return false;

    auto same = [=](const std::string& a, int i) {
        return !a.empty() && a == argv[i] &&
               (i < argc-1 && argv[i+1][i] != '-');
    };

    for (int i=1; i < argc; i++) {
        if (same(a_opt,      i)) { a_value = argv[++i]; return true; }
        if (same(a_long_opt, i)) { a_value = argv[++i]; return true; }
    }

    return false;
}

} // namespace utxx::test

#endif // _UTXX_TEST_HELPER_HPP_

<commit_msg>Add include with unit_test parameters<commit_after>//----------------------------------------------------------------------------
/// \file  test_helper.hpp
//----------------------------------------------------------------------------
/// \brief Unit test helping routines.
//----------------------------------------------------------------------------
// Author:  Serge Aleynikov
// Created: 2010-01-06
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.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

***** END LICENSE BLOCK *****
*/

#pragma once

#include <boost/test/unit_test.hpp>
#include <boost/test/detail/unit_test_parameters.hpp>

#define BOOST_CURRENT_TEST_NAME \
  boost::unit_test::framework::current_test_case().p_name->c_str()

#define UTXX_REQUIRE_NO_THROW(Expr)     \
    try { Expr; }                       \
    catch (std::exception const& e) {   \
      BOOST_MESSAGE(e.what());          \
      BOOST_REQUIRE_NO_THROW(Expr);     \
    }

#define UTXX_CHECK_NO_THROW(Expr)       \
    try { Expr; }                       \
    catch (std::exception const& e) {   \
      BOOST_MESSAGE(e.what());          \
      BOOST_CHECK_NO_THROW(Expr);       \
    }

namespace utxx {

inline long env(const char* a_var, long a_default) {
    const char* p = getenv(a_var);
    return p ? atoi(p) : a_default;
}

inline bool get_test_argv(const std::string& a_opt,
                          const std::string& a_long_opt = "") {
    int    argc = boost::unit_test::framework::master_test_suite().argc;
    char** argv = boost::unit_test::framework::master_test_suite().argv;

    if (a_opt.empty() && a_long_opt.empty()) return false;

    auto same = [=](const std::string& a, int i) {
        return !a.empty() && a == argv[i];
    };

    for (int i=1; i < argc; i++) {
        if (same(a_opt,      i)) return true;
        if (same(a_long_opt, i)) return true;
    }

    return false;
}

inline bool get_test_argv(const std::string& a_opt,
                          const std::string& a_long_opt,
                          std::string& a_value) {
    int    argc = boost::unit_test::framework::master_test_suite().argc;
    char** argv = boost::unit_test::framework::master_test_suite().argv;

    if (a_opt.empty() && a_long_opt.empty()) return false;

    auto same = [=](const std::string& a, int i) {
        return !a.empty() && a == argv[i] &&
               (i < argc-1 && argv[i+1][i] != '-');
    };

    for (int i=1; i < argc; i++) {
        if (same(a_opt,      i)) { a_value = argv[++i]; return true; }
        if (same(a_long_opt, i)) { a_value = argv[++i]; return true; }
    }

    return false;
}

} // namespace utxx::test<|endoftext|>


<commit_before>/**
 * @file lldockcontrol.cpp
 * @brief Creates a panel of a specific kind for a toast
 *
 * $LicenseInfo:firstyear=2000&license=viewergpl$
 *
 * Copyright (c) 2000-2009, Linden Research, Inc.
 *
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 *
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at
 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 *
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 *
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "linden_common.h"

#include "lldockcontrol.h"
#include "lldockablefloater.h"

LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
		const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) :
		mDockWidget(dockWidget), mDockableFloater(dockableFloater), mDockTongue(dockTongue)
{
	mDockAt = dockAt;

	if (dockableFloater->isDocked())
	{
		on();
	}
	else
	{
		off();
	}

	if (!(get_allowed_rect_callback))
	{
		mGetAllowedRectCallback = boost::bind(&LLDockControl::getAllowedRect, this, _1);
	}
	else
	{
		mGetAllowedRectCallback = get_allowed_rect_callback;
	}

	if (dockWidget != NULL)
	{
		repositionDockable();
	}

	if (mDockWidget != NULL)
	{
		mDockWidgetVisible = isDockVisible();
	}
	else
	{
		mDockWidgetVisible = false;
	}
}

LLDockControl::~LLDockControl()
{
}

void LLDockControl::setDock(LLView* dockWidget)
{
	mDockWidget = dockWidget;
	if (mDockWidget != NULL)
	{
		repositionDockable();
		mDockWidgetVisible = isDockVisible();
	}
	else
	{
		mDockWidgetVisible = false;
	}
}

void LLDockControl::getAllowedRect(LLRect& rect)
{
	rect = mDockableFloater->getRootView()->getRect();
}

void LLDockControl::repositionDockable()
{
	LLRect dockRect = mDockWidget->calcScreenRect();
	LLRect rootRect;
	mGetAllowedRectCallback(rootRect);

	// recalculate dockable position if dock position changed, dock visibility changed,
	// root view rect changed or recalculation is forced
	if (mPrevDockRect != dockRect  || mDockWidgetVisible != isDockVisible()
			|| mRootRect != rootRect || mRecalculateDocablePosition)
	{
		// undock dockable and off() if dock not visible
		if (!isDockVisible())
		{
			mDockableFloater->setDocked(false);
			// force off() since dockable may not have dockControll at this time
			off();
			LLDockableFloater* dockable_floater =
					dynamic_cast<LLDockableFloater*> (mDockableFloater);
			if(dockable_floater != NULL)
			{
				dockable_floater->onDockHidden();
			}
		}
		else
		{
			if(mEnabled)
			{
				moveDockable();
			}
			LLDockableFloater* dockable_floater =
					dynamic_cast<LLDockableFloater*> (mDockableFloater);
			if(dockable_floater != NULL)
			{
				dockable_floater->onDockShown();
			}
		}

		mPrevDockRect = dockRect;
		mRootRect = rootRect;
		mRecalculateDocablePosition = false;
		mDockWidgetVisible = isDockVisible();
	}
}

bool LLDockControl::isDockVisible()
{
	bool res = true;

	if (mDockWidget != NULL)
	{
		//we should check all hierarchy
		res = mDockWidget->isInVisibleChain();
		if (res)
		{
			LLRect dockRect = mDockWidget->calcScreenRect();

			switch (mDockAt)
			{
			case LEFT: // to keep compiler happy
				break;
			case TOP:
				// check is dock inside parent rect
				LLRect dockParentRect =
						mDockWidget->getParent()->calcScreenRect();
				if (dockRect.mRight <= dockParentRect.mLeft
						|| dockRect.mLeft >= dockParentRect.mRight)
				{
					res = false;
				}
				break;
			}
		}
	}

	return res;
}

void LLDockControl::moveDockable()
{
	// calculate new dockable position
	LLRect dockRect = mDockWidget->calcScreenRect();
	LLRect rootRect;
	mGetAllowedRectCallback(rootRect);

	bool use_tongue = false;
	LLDockableFloater* dockable_floater =
			dynamic_cast<LLDockableFloater*> (mDockableFloater);
	if (dockable_floater != NULL)
	{
		use_tongue = dockable_floater->getUseTongue();
	}

	LLRect dockableRect = mDockableFloater->calcScreenRect();
	S32 x = 0;
	S32 y = 0;
	LLRect dockParentRect;
	switch (mDockAt)
	{
	case LEFT:
		x = dockRect.mLeft;
		y = dockRect.mTop + mDockTongue->getHeight() + dockableRect.getHeight();
		// check is dockable inside root view rect
		if (x < rootRect.mLeft)
		{
			x = rootRect.mLeft;
		}
		if (x + dockableRect.getWidth() > rootRect.mRight)
		{
			x = rootRect.mRight - dockableRect.getWidth();
		}

		mDockTongueX = x + dockableRect.getWidth()/2 - mDockTongue->getWidth() / 2;

		mDockTongueY = dockRect.mTop;
		break;

	case TOP:
		x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
		y = dockRect.mTop + dockableRect.getHeight();
		// unique docking used with dock tongue, so add tongue height o the Y coordinate
		if (use_tongue)
		{
			y += mDockTongue->getHeight();
		}

		// check is dockable inside root view rect
		if (x < rootRect.mLeft)
		{
			x = rootRect.mLeft;
		}
		if (x + dockableRect.getWidth() > rootRect.mRight)
		{
			x = rootRect.mRight - dockableRect.getWidth();
		}

		// calculate dock tongue position
		dockParentRect = mDockWidget->getParent()->calcScreenRect();
		if (dockRect.getCenterX() < dockParentRect.mLeft)
		{
			mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
		}
		else if (dockRect.getCenterX() > dockParentRect.mRight)
		{
			mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
		}
		else
		{
			mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
		}
		mDockTongueY = dockRect.mTop;

		break;
	}

	// move dockable
	dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(),
			dockableRect.getHeight());
	LLRect localDocableParentRect;
	mDockableFloater->getParent()->screenRectToLocal(dockableRect,
			&localDocableParentRect);
	mDockableFloater->setRect(localDocableParentRect);

	mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY,
			&mDockTongueX, &mDockTongueY);

}

void LLDockControl::on()
{
	 if (isDockVisible())
	{
		mEnabled = true;
		mRecalculateDocablePosition = true;
	}
}

void LLDockControl::off()
{
	mEnabled = false;
}

void LLDockControl::forceRecalculatePosition()
{
	mRecalculateDocablePosition = true;
}

void LLDockControl::drawToungue()
{
	bool use_tongue = false;
	LLDockableFloater* dockable_floater =
			dynamic_cast<LLDockableFloater*> (mDockableFloater);
	if (dockable_floater != NULL)
	{
		use_tongue = dockable_floater->getUseTongue();
	}

	if (mEnabled && use_tongue)
	{
		mDockTongue->draw(mDockTongueX, mDockTongueY);
	}
}

<commit_msg>CID-344<commit_after>/**
 * @file lldockcontrol.cpp
 * @brief Creates a panel of a specific kind for a toast
 *
 * $LicenseInfo:firstyear=2000&license=viewergpl$
 *
 * Copyright (c) 2000-2009, Linden Research, Inc.
 *
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 *
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at
 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 *
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 *
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "linden_common.h"

#include "lldockcontrol.h"
#include "lldockablefloater.h"

LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
		const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) :
		mDockWidget(dockWidget),
		mDockableFloater(dockableFloater),
		mDockTongue(dockTongue),
		mDockTongueX(0),
		mDockTongueY(0)
{
	mDockAt = dockAt;

	if (dockableFloater->isDocked())
	{
		on();
	}
	else
	{
		off();
	}

	if (!(get_allowed_rect_callback))
	{
		mGetAllowedRectCallback = boost::bind(&LLDockControl::getAllowedRect, this, _1);
	}
	else
	{
		mGetAllowedRectCallback = get_allowed_rect_callback;
	}

	if (dockWidget != NULL)
	{
		repositionDockable();
	}

	if (mDockWidget != NULL)
	{
		mDockWidgetVisible = isDockVisible();
	}
	else
	{
		mDockWidgetVisible = false;
	}
}

LLDockControl::~LLDockControl()
{
}

void LLDockControl::setDock(LLView* dockWidget)
{
	mDockWidget = dockWidget;
	if (mDockWidget != NULL)
	{
		repositionDockable();
		mDockWidgetVisible = isDockVisible();
	}
	else
	{
		mDockWidgetVisible = false;
	}
}

void LLDockControl::getAllowedRect(LLRect& rect)
{
	rect = mDockableFloater->getRootView()->getRect();
}

void LLDockControl::repositionDockable()
{
	LLRect dockRect = mDockWidget->calcScreenRect();
	LLRect rootRect;
	mGetAllowedRectCallback(rootRect);

	// recalculate dockable position if dock position changed, dock visibility changed,
	// root view rect changed or recalculation is forced
	if (mPrevDockRect != dockRect  || mDockWidgetVisible != isDockVisible()
			|| mRootRect != rootRect || mRecalculateDocablePosition)
	{
		// undock dockable and off() if dock not visible
		if (!isDockVisible())
		{
			mDockableFloater->setDocked(false);
			// force off() since dockable may not have dockControll at this time
			off();
			LLDockableFloater* dockable_floater =
					dynamic_cast<LLDockableFloater*> (mDockableFloater);
			if(dockable_floater != NULL)
			{
				dockable_floater->onDockHidden();
			}
		}
		else
		{
			if(mEnabled)
			{
				moveDockable();
			}
			LLDockableFloater* dockable_floater =
					dynamic_cast<LLDockableFloater*> (mDockableFloater);
			if(dockable_floater != NULL)
			{
				dockable_floater->onDockShown();
			}
		}

		mPrevDockRect = dockRect;
		mRootRect = rootRect;
		mRecalculateDocablePosition = false;
		mDockWidgetVisible = isDockVisible();
	}
}

bool LLDockControl::isDockVisible()
{
	bool res = true;

	if (mDockWidget != NULL)
	{
		//we should check all hierarchy
		res = mDockWidget->isInVisibleChain();
		if (res)
		{
			LLRect dockRect = mDockWidget->calcScreenRect();

			switch (mDockAt)
			{
			case LEFT: // to keep compiler happy
				break;
			case TOP:
				// check is dock inside parent rect
				LLRect dockParentRect =
						mDockWidget->getParent()->calcScreenRect();
				if (dockRect.mRight <= dockParentRect.mLeft
						|| dockRect.mLeft >= dockParentRect.mRight)
				{
					res = false;
				}
				break;
			}
		}
	}

	return res;
}

void LLDockControl::moveDockable()
{
	// calculate new dockable position
	LLRect dockRect = mDockWidget->calcScreenRect();
	LLRect rootRect;
	mGetAllowedRectCallback(rootRect);

	bool use_tongue = false;
	LLDockableFloater* dockable_floater =
			dynamic_cast<LLDockableFloater*> (mDockableFloater);
	if (dockable_floater != NULL)
	{
		use_tongue = dockable_floater->getUseTongue();
	}

	LLRect dockableRect = mDockableFloater->calcScreenRect();
	S32 x = 0;
	S32 y = 0;
	LLRect dockParentRect;
	switch (mDockAt)
	{
	case LEFT:
		x = dockRect.mLeft;
		y = dockRect.mTop + mDockTongue->getHeight() + dockableRect.getHeight();
		// check is dockable inside root view rect
		if (x < rootRect.mLeft)
		{
			x = rootRect.mLeft;
		}
		if (x + dockableRect.getWidth() > rootRect.mRight)
		{
			x = rootRect.mRight - dockableRect.getWidth();
		}

		mDockTongueX = x + dockableRect.getWidth()/2 - mDockTongue->getWidth() / 2;

		mDockTongueY = dockRect.mTop;
		break;

	case TOP:
		x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
		y = dockRect.mTop + dockableRect.getHeight();
		// unique docking used with dock tongue, so add tongue height o the Y coordinate
		if (use_tongue)
		{
			y += mDockTongue->getHeight();
		}

		// check is dockable inside root view rect
		if (x < rootRect.mLeft)
		{
			x = rootRect.mLeft;
		}
		if (x + dockableRect.getWidth() > rootRect.mRight)
		{
			x = rootRect.mRight - dockableRect.getWidth();
		}

		// calculate dock tongue position
		dockParentRect = mDockWidget->getParent()->calcScreenRect();
		if (dockRect.getCenterX() < dockParentRect.mLeft)
		{
			mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
		}
		else if (dockRect.getCenterX() > dockParentRect.mRight)
		{
			mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
		}
		else
		{
			mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
		}
		mDockTongueY = dockRect.mTop;

		break;
	}

	// move dockable
	dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(),
			dockableRect.getHeight());
	LLRect localDocableParentRect;
	mDockableFloater->getParent()->screenRectToLocal(dockableRect,
			&localDocableParentRect);
	mDockableFloater->setRect(localDocableParentRect);

	mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY,
			&mDockTongueX, &mDockTongueY);

}

void LLDockControl::on()
{
	 if (isDockVisible())
	{
		mEnabled = true;
		mRecalculateDocablePosition = true;
	}
}

void LLDockControl::off()
{
	mEnabled = false;
}

void LLDockControl::forceRecalculatePosition()
{
	mRecalculateDocablePosition = true;
}

void LLDockControl::drawToungue()
{
	bool use_tongue = false;
	LLDockableFloater* dockable_floater =
			dynamic_cast<LLDockableFloater*> (mDockableFloater);
	if (dockable_floater != NULL)
	{
		use_tongue = dockable_floater->getUseTongue();
	}

	if (mEnabled && use_tongue)
	{
		mDockTongue->draw(mDockTongueX, mDockTongueY);
	}
}

<|endoftext|>