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

#include "content/browser/renderer_host/accelerated_surface_container_linux.h"

#include <X11/Xlib.h>
#include <X11/extensions/Xcomposite.h>

#include "base/lazy_instance.h"
#include "base/memory/scoped_ptr.h"
#include "third_party/angle/include/EGL/egl.h"
#include "third_party/angle/include/EGL/eglext.h"
#include "ui/gfx/gl/gl_bindings.h"
#include "ui/gfx/gl/gl_implementation.h"
#include "ui/gfx/gl/gl_surface_egl.h"
#include "ui/gfx/gl/gl_surface_glx.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/transform.h"

namespace {

class AcceleratedSurfaceContainerLinuxEGL
    : public AcceleratedSurfaceContainerLinux {
 public:
  explicit AcceleratedSurfaceContainerLinuxEGL(const gfx::Size& size);

  virtual bool Initialize(uint64* surface_id) OVERRIDE;

  // TextureGL implementation
  virtual void Draw(const ui::TextureDrawParams& params,
                    const gfx::Rect& clip_bounds_in_texture) OVERRIDE;

 private:
  virtual ~AcceleratedSurfaceContainerLinuxEGL();

  void* image_;

  DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerLinuxEGL);
};

class AcceleratedSurfaceContainerLinuxGLX
    : public AcceleratedSurfaceContainerLinux {
 public:
  explicit AcceleratedSurfaceContainerLinuxGLX(const gfx::Size& size);

  virtual bool Initialize(uint64* surface_id) OVERRIDE;

  // TextureGL implementation
  virtual void Draw(const ui::TextureDrawParams& params,
                    const gfx::Rect& clip_bounds_in_texture) OVERRIDE;

 protected:
  static bool InitializeOneOff();

  static base::LazyInstance<GLXFBConfig> fbconfig_;

 private:
  virtual ~AcceleratedSurfaceContainerLinuxGLX();

  XID pixmap_;
  XID glx_pixmap_;

  DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerLinuxGLX);
};

class AcceleratedSurfaceContainerLinuxOSMesa
    : public AcceleratedSurfaceContainerLinux {
 public:
  explicit AcceleratedSurfaceContainerLinuxOSMesa(const gfx::Size& size);

  virtual bool Initialize(uint64* surface_id) OVERRIDE;

  // TextureGL implementation
  virtual void Draw(const ui::TextureDrawParams& params,
                    const gfx::Rect& clip_bounds_in_texture) OVERRIDE;

  // Some implementations of this class use shared memory, this gives the handle
  // to the shared buffer, which is part of the surface container.
  // When shared memory is not used, this will return
  // TransportDIB::DefaultHandleValue().
  virtual TransportDIB::Handle Handle() const OVERRIDE;

 private:
  virtual ~AcceleratedSurfaceContainerLinuxOSMesa();

  scoped_ptr<TransportDIB> shared_mem_;

  DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerLinuxOSMesa);
};

class ScopedPtrXFree {
 public:
  void operator()(void* x) const {
    ::XFree(x);
  }
};

// static
base::LazyInstance<GLXFBConfig> AcceleratedSurfaceContainerLinuxGLX::fbconfig_(
    base::LINKER_INITIALIZED);

AcceleratedSurfaceContainerLinuxEGL::AcceleratedSurfaceContainerLinuxEGL(
    const gfx::Size& size)
    : AcceleratedSurfaceContainerLinux(size),
      image_(NULL) {
}

bool AcceleratedSurfaceContainerLinuxEGL::Initialize(uint64* surface_id) {
  ui::SharedResources* instance = ui::SharedResources::GetInstance();
  DCHECK(instance);
  instance->MakeSharedContextCurrent();

  image_ = eglCreateImageKHR(
      gfx::GLSurfaceEGL::GetHardwareDisplay(), EGL_NO_CONTEXT,
      EGL_NATIVE_PIXMAP_KHR, reinterpret_cast<void*>(*surface_id), NULL);

  glGenTextures(1, &texture_id_);
  glBindTexture(GL_TEXTURE_2D, texture_id_);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_);
  glFlush();

  return true;
}

AcceleratedSurfaceContainerLinuxEGL::~AcceleratedSurfaceContainerLinuxEGL() {
  ui::SharedResources* instance = ui::SharedResources::GetInstance();
  DCHECK(instance);
  instance->MakeSharedContextCurrent();

  eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), image_);
  glFlush();
}

void AcceleratedSurfaceContainerLinuxEGL::Draw(
    const ui::TextureDrawParams& params,
    const gfx::Rect& clip_bounds_in_texture) {
  ui::SharedResources* instance = ui::SharedResources::GetInstance();
  DCHECK(instance);

  ui::TextureDrawParams modified_params = params;
  modified_params.vertically_flipped = true;

  DrawInternal(*instance->program_no_swizzle(),
               modified_params,
               clip_bounds_in_texture);
}

AcceleratedSurfaceContainerLinuxGLX::AcceleratedSurfaceContainerLinuxGLX(
    const gfx::Size& size)
    : AcceleratedSurfaceContainerLinux(size),
      pixmap_(0),
      glx_pixmap_(0) {
}

bool AcceleratedSurfaceContainerLinuxGLX::Initialize(uint64* surface_id) {
  ui::SharedResources* instance = ui::SharedResources::GetInstance();
  DCHECK(instance);
  instance->MakeSharedContextCurrent();

  if (!AcceleratedSurfaceContainerLinuxGLX::InitializeOneOff())
    return false;

  // Create pixmap from window.
  // We receive a window here rather than a pixmap directly because drivers
  // require (or required) that the pixmap used to create the GL texture be
  // created in the same process as the texture.
  Display* dpy = instance->GetDisplay();
  pixmap_ = XCompositeNameWindowPixmap(dpy, *surface_id);

  // Wrap the pixmap in a GLXPixmap
  const int pixmapAttribs[] = {
    GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
    GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
    0
  };

  glx_pixmap_ = glXCreatePixmap(
      dpy, fbconfig_.Get(), pixmap_, pixmapAttribs);

  // Create texture.
  glGenTextures(1, &texture_id_);
  glBindTexture(GL_TEXTURE_2D, texture_id_);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

  return true;
}

AcceleratedSurfaceContainerLinuxGLX::~AcceleratedSurfaceContainerLinuxGLX() {
  ui::SharedResources* instance = ui::SharedResources::GetInstance();
  DCHECK(instance);
  instance->MakeSharedContextCurrent();

  Display* dpy = instance->GetDisplay();
  if (glx_pixmap_)
    glXDestroyGLXPixmap(dpy, glx_pixmap_);
  if (pixmap_)
    XFreePixmap(dpy, pixmap_);
}

void AcceleratedSurfaceContainerLinuxGLX::Draw(
    const ui::TextureDrawParams& params,
    const gfx::Rect& clip_bounds_in_texture) {
  ui::SharedResources* instance = ui::SharedResources::GetInstance();
  DCHECK(instance);

  Display* dpy = instance->GetDisplay();

  glBindTexture(GL_TEXTURE_2D, texture_id_);
  glXBindTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL);
  DrawInternal(*instance->program_no_swizzle(),
               params,
               clip_bounds_in_texture);
  glXReleaseTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT);
}

// static
bool AcceleratedSurfaceContainerLinuxGLX::InitializeOneOff()
{
  static bool initialized = false;
  if (initialized)
    return true;

  ui::SharedResources* instance = ui::SharedResources::GetInstance();
  DCHECK(instance);

  Display* dpy = instance->GetDisplay();
  int event_base, error_base;
  if (XCompositeQueryExtension(dpy, &event_base, &error_base)) {
    int major = 0, minor = 2;
    XCompositeQueryVersion(dpy, &major, &minor);
    if (major == 0 && minor < 2) {
      LOG(ERROR) << "Pixmap from window not supported.";
      return false;
    }
  }

  // Wrap the pixmap in a GLXPixmap
  int screen = DefaultScreen(dpy);
  XWindowAttributes gwa;
  XGetWindowAttributes(dpy, RootWindow(dpy, screen), &gwa);
  unsigned int visualid = XVisualIDFromVisual(gwa.visual);

  int nfbconfigs, config;
  scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> fbconfigs(
      glXGetFBConfigs(dpy, screen, &nfbconfigs));

  for (config = 0; config < nfbconfigs; config++) {
    XVisualInfo* visinfo = glXGetVisualFromFBConfig(
        dpy, fbconfigs.get()[config]);
    if (!visinfo || visinfo->visualid != visualid)
      continue;

    int value;
    glXGetFBConfigAttrib(dpy,
                         fbconfigs.get()[config],
                         GLX_DRAWABLE_TYPE,
                         &value);
    if (!(value & GLX_PIXMAP_BIT))
      continue;

    glXGetFBConfigAttrib(dpy,
                         fbconfigs.get()[config],
                         GLX_BIND_TO_TEXTURE_TARGETS_EXT,
                         &value);
    if (!(value & GLX_TEXTURE_2D_BIT_EXT))
      continue;

    glXGetFBConfigAttrib(dpy,
                         fbconfigs.get()[config],
                         GLX_BIND_TO_TEXTURE_RGB_EXT,
                         &value);
    if (value == GL_FALSE)
      continue;

    break;
  }

  if (config == nfbconfigs) {
    LOG(ERROR)
      << "Could not find configuration suitable for binding a pixmap "
      << "as a texture.";
    return false;
  }

  fbconfig_.Get() = fbconfigs.get()[config];

  initialized = true;
  return initialized;
}

AcceleratedSurfaceContainerLinuxOSMesa::AcceleratedSurfaceContainerLinuxOSMesa(
    const gfx::Size& size)
      : AcceleratedSurfaceContainerLinux(size) {
}

bool AcceleratedSurfaceContainerLinuxOSMesa::Initialize(uint64* surface_id) {
  static uint32 next_id = 1;

  ui::SharedResources* instance = ui::SharedResources::GetInstance();
  DCHECK(instance);
  instance->MakeSharedContextCurrent();

  // We expect to make the id here, so don't want the other end giving us one
  DCHECK_EQ(*surface_id, static_cast<uint64>(0));

  // It's possible that this ID gneration could clash with IDs from other
  // AcceleratedSurfaceContainerLinux* objects, however we should never have
  // ids active from more than one type at the same time, so we have free
  // reign of the id namespace.
  *surface_id = next_id++;

  shared_mem_.reset(
      TransportDIB::Create(size_.GetArea() * 4,  // GL_RGBA=4 B/px
                           *surface_id));
  // Create texture.
  glGenTextures(1, &texture_id_);
  glBindTexture(GL_TEXTURE_2D, texture_id_);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

  // we generate the ID to be used here.
  return true;
}

void AcceleratedSurfaceContainerLinuxOSMesa::Draw(
    const ui::TextureDrawParams& params,
    const gfx::Rect& clip_bounds_in_texture) {
  ui::SharedResources* instance = ui::SharedResources::GetInstance();
  DCHECK(instance);

  if (shared_mem_.get()) {
    glBindTexture(GL_TEXTURE_2D, texture_id_);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                 size_.width(), size_.height(), 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, shared_mem_->memory());

    DrawInternal(*instance->program_no_swizzle(),
                 params,
                 clip_bounds_in_texture);
  }
}

TransportDIB::Handle AcceleratedSurfaceContainerLinuxOSMesa::Handle() const {
  if (shared_mem_.get())
    return shared_mem_->handle();
  else
    return TransportDIB::DefaultHandleValue();
}

AcceleratedSurfaceContainerLinuxOSMesa::
    ~AcceleratedSurfaceContainerLinuxOSMesa() {
}

}  // namespace

AcceleratedSurfaceContainerLinux::AcceleratedSurfaceContainerLinux(
    const gfx::Size& size) : TextureGL(size) {
}

TransportDIB::Handle AcceleratedSurfaceContainerLinux::Handle() const {
  return TransportDIB::DefaultHandleValue();
}

// static
AcceleratedSurfaceContainerLinux*
AcceleratedSurfaceContainerLinux::CreateAcceleratedSurfaceContainer(
    const gfx::Size& size) {
  switch (gfx::GetGLImplementation()) {
    case gfx::kGLImplementationDesktopGL:
      return new AcceleratedSurfaceContainerLinuxGLX(size);
    case gfx::kGLImplementationEGLGLES2:
      return new AcceleratedSurfaceContainerLinuxEGL(size);
    case gfx::kGLImplementationOSMesaGL:
      return new AcceleratedSurfaceContainerLinuxOSMesa(size);
    default:
      NOTREACHED();
      return NULL;
  }
}

void AcceleratedSurfaceContainerLinux::SetCanvas(
    const SkCanvas& canvas,
    const gfx::Point& origin,
    const gfx::Size& overall_size) {
  NOTREACHED();
}

<commit_msg>Unnecessary file.<commit_after><|endoftext|>


<commit_before>
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkOSFile.h"

#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifdef _WIN32
#include <direct.h>
#include <io.h>
#else
#include <unistd.h>
#endif

SkFILE* sk_fopen(const char path[], SkFILE_Flags flags)
{
    char    perm[4];
    char*   p = perm;

    if (flags & kRead_SkFILE_Flag)
        *p++ = 'r';
    if (flags & kWrite_SkFILE_Flag)
        *p++ = 'w';
    *p++ = 'b';
    *p = 0;

    SkFILE* f = (SkFILE*)::fopen(path, perm);
#if 0
    if (NULL == f)
        SkDebugf("sk_fopen failed for %s (%s), errno=%s\n", path, perm, strerror(errno));
#endif
    return f;
}

char* sk_fgets(char* str, int size, SkFILE* f) {
    return ::fgets(str, size, (FILE *)f);
}

int sk_feof(SkFILE *f) {
    return ::feof((FILE *)f);
}

size_t sk_fgetsize(SkFILE* f)
{
    SkASSERT(f);

    long curr = ::ftell((FILE*)f);       // remember where we are
    if (curr < 0) {
        return 0;
    }
    ::fseek((FILE*)f, 0, SEEK_END);         // go to the end
    long size = ::ftell((FILE*)f);        // record the size
    if (size < 0) {
        size = 0;
    }
    ::fseek((FILE*)f, curr, SEEK_SET);        // go back to our prev loc
    return size;
}

bool sk_frewind(SkFILE* f)
{
    SkASSERT(f);
    ::rewind((FILE*)f);
//  ::fseek((FILE*)f, 0, SEEK_SET);
    return true;
}

size_t sk_fread(void* buffer, size_t byteCount, SkFILE* f)
{
    SkASSERT(f);
    if (buffer == NULL)
    {
        size_t curr = ::ftell((FILE*)f);
        if ((long)curr == -1) {
            SkDEBUGF(("sk_fread: ftell(%p) returned -1 feof:%d ferror:%d\n", f, feof((FILE*)f), ferror((FILE*)f)));
            return 0;
        }
    //  ::fseek((FILE*)f, (long)(curr + byteCount), SEEK_SET);
        int err = ::fseek((FILE*)f, (long)byteCount, SEEK_CUR);
        if (err != 0) {
            SkDEBUGF(("sk_fread: fseek(%d) tell:%d failed with feof:%d ferror:%d returned:%d\n",
                        byteCount, curr, feof((FILE*)f), ferror((FILE*)f), err));
            return 0;
        }
        return byteCount;
    }
    else
        return ::fread(buffer, 1, byteCount, (FILE*)f);
}

size_t sk_fwrite(const void* buffer, size_t byteCount, SkFILE* f)
{
    SkASSERT(f);
    return ::fwrite(buffer, 1, byteCount, (FILE*)f);
}

void sk_fflush(SkFILE* f)
{
    SkASSERT(f);
    ::fflush((FILE*)f);
}

void sk_fclose(SkFILE* f)
{
    SkASSERT(f);
    ::fclose((FILE*)f);
}

bool sk_exists(const char *path)
{
#ifdef _WIN32
    return (0 == _access(path, 0));
#else
    return (0 == access(path, 0));
#endif
}

bool sk_isdir(const char *path)
{
    struct stat status;
    if (0 != stat(path, &status)) {
        return false;
    }
    return SkToBool(status.st_mode & S_IFDIR);
}

bool sk_mkdir(const char* path)
{
    if (sk_isdir(path)) {
        return true;
    }
    if (sk_exists(path)) {
        fprintf(stderr,
                "sk_mkdir: path '%s' already exists but is not a directory\n",
                path);
        return false;
    }

    int retval;
#ifdef _WIN32
    retval = _mkdir(path);
#else
    retval = mkdir(path, 0777);
#endif
    if (0 == retval) {
        return true;
    } else {
        fprintf(stderr, "sk_mkdir: error %d creating dir '%s'\n", errno, path);
        return false;
    }
}
<commit_msg>remove namespace qualifier for feof; it's making android unhappy<commit_after>
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkOSFile.h"

#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifdef _WIN32
#include <direct.h>
#include <io.h>
#else
#include <unistd.h>
#endif

SkFILE* sk_fopen(const char path[], SkFILE_Flags flags)
{
    char    perm[4];
    char*   p = perm;

    if (flags & kRead_SkFILE_Flag)
        *p++ = 'r';
    if (flags & kWrite_SkFILE_Flag)
        *p++ = 'w';
    *p++ = 'b';
    *p = 0;

    SkFILE* f = (SkFILE*)::fopen(path, perm);
#if 0
    if (NULL == f)
        SkDebugf("sk_fopen failed for %s (%s), errno=%s\n", path, perm, strerror(errno));
#endif
    return f;
}

char* sk_fgets(char* str, int size, SkFILE* f) {
    return ::fgets(str, size, (FILE *)f);
}

int sk_feof(SkFILE *f) {
    // no :: namespace qualifier because it breaks android
    return feof((FILE *)f);
}

size_t sk_fgetsize(SkFILE* f)
{
    SkASSERT(f);

    long curr = ::ftell((FILE*)f);       // remember where we are
    if (curr < 0) {
        return 0;
    }
    ::fseek((FILE*)f, 0, SEEK_END);         // go to the end
    long size = ::ftell((FILE*)f);        // record the size
    if (size < 0) {
        size = 0;
    }
    ::fseek((FILE*)f, curr, SEEK_SET);        // go back to our prev loc
    return size;
}

bool sk_frewind(SkFILE* f)
{
    SkASSERT(f);
    ::rewind((FILE*)f);
//  ::fseek((FILE*)f, 0, SEEK_SET);
    return true;
}

size_t sk_fread(void* buffer, size_t byteCount, SkFILE* f)
{
    SkASSERT(f);
    if (buffer == NULL)
    {
        size_t curr = ::ftell((FILE*)f);
        if ((long)curr == -1) {
            SkDEBUGF(("sk_fread: ftell(%p) returned -1 feof:%d ferror:%d\n", f, feof((FILE*)f), ferror((FILE*)f)));
            return 0;
        }
    //  ::fseek((FILE*)f, (long)(curr + byteCount), SEEK_SET);
        int err = ::fseek((FILE*)f, (long)byteCount, SEEK_CUR);
        if (err != 0) {
            SkDEBUGF(("sk_fread: fseek(%d) tell:%d failed with feof:%d ferror:%d returned:%d\n",
                        byteCount, curr, feof((FILE*)f), ferror((FILE*)f), err));
            return 0;
        }
        return byteCount;
    }
    else
        return ::fread(buffer, 1, byteCount, (FILE*)f);
}

size_t sk_fwrite(const void* buffer, size_t byteCount, SkFILE* f)
{
    SkASSERT(f);
    return ::fwrite(buffer, 1, byteCount, (FILE*)f);
}

void sk_fflush(SkFILE* f)
{
    SkASSERT(f);
    ::fflush((FILE*)f);
}

void sk_fclose(SkFILE* f)
{
    SkASSERT(f);
    ::fclose((FILE*)f);
}

bool sk_exists(const char *path)
{
#ifdef _WIN32
    return (0 == _access(path, 0));
#else
    return (0 == access(path, 0));
#endif
}

bool sk_isdir(const char *path)
{
    struct stat status;
    if (0 != stat(path, &status)) {
        return false;
    }
    return SkToBool(status.st_mode & S_IFDIR);
}

bool sk_mkdir(const char* path)
{
    if (sk_isdir(path)) {
        return true;
    }
    if (sk_exists(path)) {
        fprintf(stderr,
                "sk_mkdir: path '%s' already exists but is not a directory\n",
                path);
        return false;
    }

    int retval;
#ifdef _WIN32
    retval = _mkdir(path);
#else
    retval = mkdir(path, 0777);
#endif
    if (0 == retval) {
        return true;
    } else {
        fprintf(stderr, "sk_mkdir: error %d creating dir '%s'\n", errno, path);
        return false;
    }
}
<|endoftext|>


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

#include <string>
#include <cstdlib>
#include "pkcs11test.h"

using namespace std;  // So sue me

namespace pkcs11 {
namespace test {

class DigestTest : public ReadOnlySessionTest {
 public:
  DigestTest(CK_MECHANISM_TYPE mode, int digestsize)
    : mode_(mode),
      digestsize_(digestsize),
      mechanism_({mode_, NULL_PTR, 0}),
      datalen_(std::rand() % 1024),
      data_(randmalloc(datalen_)) {
    if (g_verbose) cout << "DATA:  " << hex_data(data_.get(), min(40, datalen_))
                        << ((datalen_>40) ? "..." : "") << endl;
  }

  string TestDigest() {
    CK_RV rv = g_fns->C_DigestInit(session_, &mechanism_);
    EXPECT_CKR_OK(rv);
    if (rv == CKR_MECHANISM_INVALID) return "unimplemented";
    CK_BYTE buffer[512];
    CK_ULONG digest_len = sizeof(buffer);
    EXPECT_CKR_OK(g_fns->C_Digest(session_, data_.get(), datalen_, buffer, &digest_len));
    EXPECT_EQ(digestsize_, digest_len);
    if (g_verbose) cout << "DIGEST: " << hex_data(buffer, digest_len) << endl;
    return string(reinterpret_cast<char*>(buffer), digest_len);
  }

  string TestDigestUpdate() {
    CK_RV rv = g_fns->C_DigestInit(session_, &mechanism_);
    EXPECT_CKR_OK(rv);
    if (rv == CKR_MECHANISM_INVALID) return "unimplemented";
    const int kChunkSize = 10;
    CK_BYTE_PTR p = data_.get();
    int dataleft = datalen_;
    int count = 0;
    while (dataleft > 0) {
      int size = min(kChunkSize, dataleft);
      EXPECT_CKR_OK(g_fns->C_DigestUpdate(session_, p, size));
      p += size;
      dataleft -= size;
      ++count;
    }

    CK_BYTE buffer[512];
    CK_ULONG digest_len = sizeof(buffer);
    EXPECT_CKR_OK(g_fns->C_DigestFinal(session_, buffer, &digest_len));
    EXPECT_EQ(digestsize_, digest_len);
    if (g_verbose) cout << "DIGEST: " << hex_data(buffer, digest_len) << endl;
    return string(reinterpret_cast<char*>(buffer), digest_len);
  }

 private:
  const CK_MECHANISM_TYPE mode_;
  const int digestsize_;
  CK_MECHANISM mechanism_;
  const int datalen_;
  unique_ptr<CK_BYTE, freer> data_;
};

class Md5DigestTest : public DigestTest {
 public:
  Md5DigestTest(): DigestTest(CKM_MD5, 16) {}
};

TEST_F(Md5DigestTest, Digest) {
  string d1 = TestDigest();
  string d2 = TestDigestUpdate();
  EXPECT_EQ(hex_data(d1), hex_data(d2));
}

class Sha1DigestTest : public DigestTest {
 public:
  Sha1DigestTest(): DigestTest(CKM_SHA_1, 20) {}
};

TEST_F(Sha1DigestTest, Digest) {
  string d1 = TestDigest();
  string d2 = TestDigestUpdate();
  EXPECT_EQ(hex_data(d1), hex_data(d2));
}

class Sha256DigestTest : public DigestTest {
 public:
  Sha256DigestTest(): DigestTest(CKM_SHA256, 256/8) {}
};

TEST_F(Sha256DigestTest, Digest) {
  string d1 = TestDigest();
  string d2 = TestDigestUpdate();
  EXPECT_EQ(hex_data(d1), hex_data(d2));
}

}  // namespace test
}  // namespace pkcs11
<commit_msg>Cope with SHA-256 unimplemented<commit_after>// Copyright 2013-2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <cstdlib>
#include "pkcs11test.h"

using namespace std;  // So sue me

namespace pkcs11 {
namespace test {

class DigestTest : public ReadOnlySessionTest {
 public:
  DigestTest(CK_MECHANISM_TYPE mode, int digestsize)
    : mode_(mode),
      digestsize_(digestsize),
      mechanism_({mode_, NULL_PTR, 0}),
      datalen_(std::rand() % 1024),
      data_(randmalloc(datalen_)) {
    if (g_verbose) cout << "DATA:  " << hex_data(data_.get(), min(40, datalen_))
                        << ((datalen_>40) ? "..." : "") << endl;
  }

  string TestDigest() {
    CK_RV rv = g_fns->C_DigestInit(session_, &mechanism_);
    if (rv == CKR_MECHANISM_INVALID) return "unimplemented";
    EXPECT_CKR_OK(rv);
    CK_BYTE buffer[512];
    CK_ULONG digest_len = sizeof(buffer);
    EXPECT_CKR_OK(g_fns->C_Digest(session_, data_.get(), datalen_, buffer, &digest_len));
    EXPECT_EQ(digestsize_, digest_len);
    if (g_verbose) cout << "DIGEST: " << hex_data(buffer, digest_len) << endl;
    return string(reinterpret_cast<char*>(buffer), digest_len);
  }

  string TestDigestUpdate() {
    CK_RV rv = g_fns->C_DigestInit(session_, &mechanism_);
    if (rv == CKR_MECHANISM_INVALID) return "unimplemented";
    EXPECT_CKR_OK(rv);
    const int kChunkSize = 10;
    CK_BYTE_PTR p = data_.get();
    int dataleft = datalen_;
    int count = 0;
    while (dataleft > 0) {
      int size = min(kChunkSize, dataleft);
      EXPECT_CKR_OK(g_fns->C_DigestUpdate(session_, p, size));
      p += size;
      dataleft -= size;
      ++count;
    }

    CK_BYTE buffer[512];
    CK_ULONG digest_len = sizeof(buffer);
    EXPECT_CKR_OK(g_fns->C_DigestFinal(session_, buffer, &digest_len));
    EXPECT_EQ(digestsize_, digest_len);
    if (g_verbose) cout << "DIGEST: " << hex_data(buffer, digest_len) << endl;
    return string(reinterpret_cast<char*>(buffer), digest_len);
  }

 private:
  const CK_MECHANISM_TYPE mode_;
  const int digestsize_;
  CK_MECHANISM mechanism_;
  const int datalen_;
  unique_ptr<CK_BYTE, freer> data_;
};

class Md5DigestTest : public DigestTest {
 public:
  Md5DigestTest(): DigestTest(CKM_MD5, 16) {}
};

TEST_F(Md5DigestTest, Digest) {
  string d1 = TestDigest();
  string d2 = TestDigestUpdate();
  EXPECT_EQ(hex_data(d1), hex_data(d2));
}

class Sha1DigestTest : public DigestTest {
 public:
  Sha1DigestTest(): DigestTest(CKM_SHA_1, 20) {}
};

TEST_F(Sha1DigestTest, Digest) {
  string d1 = TestDigest();
  string d2 = TestDigestUpdate();
  EXPECT_EQ(hex_data(d1), hex_data(d2));
}

class Sha256DigestTest : public DigestTest {
 public:
  Sha256DigestTest(): DigestTest(CKM_SHA256, 256/8) {}
};

TEST_F(Sha256DigestTest, Digest) {
  string d1 = TestDigest();
  string d2 = TestDigestUpdate();
  if (d1 == "unimplemented" || d2 == "unimplemented") {
    TEST_SKIPPED("SHA-256 not implemented");
  }
  EXPECT_EQ(hex_data(d1), hex_data(d2));
}

}  // namespace test
}  // namespace pkcs11
<|endoftext|>


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

#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <SFML/System.hpp>
#include <SFML/Window.hpp>

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

#include "PhysicsFS.hpp"
#include "LuaState.hpp"

#include "App.hpp"
#include "State.hpp"

#include <cmath>

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

class PauseState : public State
{
public:
    PauseState() {}

protected:
    void onUpdate(sf::Time delta)
    {
    }

    bool onEvent(const sf::Event &event)
    {
        if (event.type == sf::Event::KeyPressed)
        {
            if (event.key.code == sf::Keyboard::Return)
            {
                throw App::Exit;
            }
            else if (event.key.code == sf::Keyboard::Escape)
            {
                exit();
            }
        }

        return false;
    }

    void draw(sf::RenderTarget &target, sf::RenderStates states) const
    {
        sf::RectangleShape rect(sf::Vector2f(target.getSize()));
        rect.setFillColor(sf::Color(0,0,0,128));
        target.draw(rect, states);
    }

    bool isOpaque() const { return false; }
};

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

class MyState : public State
{
public:
    MyState()
    {
        static const unsigned int numSides[10] = {
            90, 3, 4, 5, 6, 7, 8, 10, 12, 20
        };

        m_shapes.resize(10);

        for (unsigned int i = 0; i < 10; i++)
        {
            initShape(m_shapes[i], sf::Vector2f(80+150*((i+1)%5), 270+150*((i+1)/5)), 50, numSides[i]);
        }
    }

protected:
    void initShape(sf::ConvexShape &shape, const sf::Vector2f &position, float radius, unsigned int sides = 0)
    {
        if (sides < 3) sides = 3;

        static const float PI = 3.14159265359f;

        float angle = PI / float(sides);
        float step = angle * 2.f;

        shape.setPointCount(sides);

        for (unsigned int i = 0; i < sides; i++)
        {
            shape.setPoint(i, sf::Vector2f(radius*std::cos(angle), radius*std::sin(angle)));
            angle += step;
        }

        shape.setOutlineThickness(5);
        shape.setOutlineColor(sf::Color::Black);
        shape.setFillColor(sf::Color(160,160,160));
        shape.setPosition(position);
    }

    void onUpdate(sf::Time delta)
    {
        for (sf::Shape &shape : m_shapes)
        {
            shape.rotate(90.f * delta.asSeconds());
        }
    }

    bool onEvent(const sf::Event &event)
    {
        switch (event.type)
        {
            case sf::Event::KeyPressed:
            {
                switch (event.key.code)
                {
                    case sf::Keyboard::Num0:
                    case sf::Keyboard::Num1:
                    case sf::Keyboard::Num2:
                    case sf::Keyboard::Num3:
                    case sf::Keyboard::Num4:
                    case sf::Keyboard::Num5:
                    case sf::Keyboard::Num6:
                    case sf::Keyboard::Num7:
                    case sf::Keyboard::Num8:
                    case sf::Keyboard::Num9:
                    {
                        m_shapes[event.key.code - sf::Keyboard::Num0].
                            setFillColor(sf::Color::Red);
                        return true;
                    }

                    default: break;
                }
                break;
            }

            case sf::Event::KeyReleased:
            {
                switch (event.key.code)
                {
                    case sf::Keyboard::Num0:
                    case sf::Keyboard::Num1:
                    case sf::Keyboard::Num2:
                    case sf::Keyboard::Num3:
                    case sf::Keyboard::Num4:
                    case sf::Keyboard::Num5:
                    case sf::Keyboard::Num6:
                    case sf::Keyboard::Num7:
                    case sf::Keyboard::Num8:
                    case sf::Keyboard::Num9:
                    {
                        m_shapes[event.key.code - sf::Keyboard::Num0].
                            setFillColor(sf::Color::Green);
                        return true;
                    }

                    default: break;
                }
                break;
            }

            default: break;
        }

        return false;
    }

    void draw(sf::RenderTarget &target, sf::RenderStates states) const
    {
        target.clear(sf::Color(0x6688aa));
        for (const sf::Shape &shape : m_shapes)
        {
            target.draw(shape, states);
        }
    }

private:
    std::vector < sf::ConvexShape > m_shapes;
};

class MyApp : public App
{
public:
    MyApp()
    {
        setTargetFPS(120.f);
        setWindowStyle(sf::Style::Titlebar | sf::Style::Close);
    }

protected:
    void onStart()
    {
        createWindow();
        pushState(m_myState);
    }

    bool onEvent(const sf::Event &event)
    {
        switch (event.type)
        {
            case sf::Event::KeyPressed:
            {
                if (event.key.code == sf::Keyboard::Escape)
                {
                    if (getState() != &m_pauseState)
                    {
                        pushState(m_pauseState);
                        return true;
                    }
                }
                break;
            }
            default: break;
        }

        return false;
    }

private:
    PauseState m_pauseState;
    MyState m_myState;
};

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

extern "C"
int main (int argc, char **argv)
{
    PhysicsFS physfs(argv[0]);

    try
    {
        LuaState lua;

        try
        {
            lua.doFile("config.lua");
        }
        catch (LuaState::Error &exc)
        {
            sf::err() << "Config script error: " << exc.what() << "\n";
        }

        lua.loadSafeLibs();

        try
        {
            lua.doFile("init.lua");
        }
        catch (LuaState::Error &exc)
        {
            sf::err() << "Init script error: " << exc.what() << "\n";
            throw;
        }

        MyApp app;
        app.run();
    }
    catch (std::exception &exc)
    {
        sf::err() << "Unhandled exception: " << exc.what() << "\n";
    }

    return(0);
}

////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////

<commit_msg>Fix demo shape layout (finally)<commit_after>////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////

#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <SFML/System.hpp>
#include <SFML/Window.hpp>

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

#include "PhysicsFS.hpp"
#include "LuaState.hpp"

#include "App.hpp"
#include "State.hpp"

#include <cmath>

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

class PauseState : public State
{
public:
    PauseState() {}

protected:
    void onUpdate(sf::Time delta)
    {
    }

    bool onEvent(const sf::Event &event)
    {
        if (event.type == sf::Event::KeyPressed)
        {
            if (event.key.code == sf::Keyboard::Return)
            {
                throw App::Exit;
            }
            else if (event.key.code == sf::Keyboard::Escape)
            {
                exit();
            }
        }

        return false;
    }

    void draw(sf::RenderTarget &target, sf::RenderStates states) const
    {
        sf::RectangleShape rect(sf::Vector2f(target.getSize()));
        rect.setFillColor(sf::Color(0,0,0,128));
        target.draw(rect, states);
    }

    bool isOpaque() const { return false; }
};

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

class MyState : public State
{
public:
    MyState()
    {
        static const unsigned int numSides[10] = {
            90, 3, 4, 5, 6, 7, 8, 10, 12, 20
        };

        m_shapes.resize(10);

        for (unsigned int i = 0; i < 10; i++)
        {
            int r = ((i+9)/5)%2, c = (i+9)%5;
            initShape(m_shapes[i], sf::Vector2f(80+150*c, 270+150*r), 50, numSides[i]);
        }
    }

protected:
    void initShape(sf::ConvexShape &shape, const sf::Vector2f &position, float radius, unsigned int sides = 0)
    {
        if (sides < 3) sides = 3;

        static const float PI = 3.14159265359f;

        float angle = PI / float(sides);
        float step = angle * 2.f;

        shape.setPointCount(sides);

        for (unsigned int i = 0; i < sides; i++)
        {
            shape.setPoint(i, sf::Vector2f(radius*std::cos(angle), radius*std::sin(angle)));
            angle += step;
        }

        shape.setOutlineThickness(5);
        shape.setOutlineColor(sf::Color::Black);
        shape.setFillColor(sf::Color(160,160,160));
        shape.setPosition(position);
    }

    void onUpdate(sf::Time delta)
    {
        for (sf::Shape &shape : m_shapes)
        {
            shape.rotate(90.f * delta.asSeconds());
        }
    }

    bool onEvent(const sf::Event &event)
    {
        switch (event.type)
        {
            case sf::Event::KeyPressed:
            {
                switch (event.key.code)
                {
                    case sf::Keyboard::Num0:
                    case sf::Keyboard::Num1:
                    case sf::Keyboard::Num2:
                    case sf::Keyboard::Num3:
                    case sf::Keyboard::Num4:
                    case sf::Keyboard::Num5:
                    case sf::Keyboard::Num6:
                    case sf::Keyboard::Num7:
                    case sf::Keyboard::Num8:
                    case sf::Keyboard::Num9:
                    {
                        m_shapes[event.key.code - sf::Keyboard::Num0].
                            setFillColor(sf::Color::Red);
                        return true;
                    }

                    default: break;
                }
                break;
            }

            case sf::Event::KeyReleased:
            {
                switch (event.key.code)
                {
                    case sf::Keyboard::Num0:
                    case sf::Keyboard::Num1:
                    case sf::Keyboard::Num2:
                    case sf::Keyboard::Num3:
                    case sf::Keyboard::Num4:
                    case sf::Keyboard::Num5:
                    case sf::Keyboard::Num6:
                    case sf::Keyboard::Num7:
                    case sf::Keyboard::Num8:
                    case sf::Keyboard::Num9:
                    {
                        m_shapes[event.key.code - sf::Keyboard::Num0].
                            setFillColor(sf::Color::Green);
                        return true;
                    }

                    default: break;
                }
                break;
            }

            default: break;
        }

        return false;
    }

    void draw(sf::RenderTarget &target, sf::RenderStates states) const
    {
        target.clear(sf::Color(0x6688aa));

        for (const sf::Shape &shape : m_shapes)
        {
            target.draw(shape, states);
        }
    }

private:
    std::vector < sf::ConvexShape > m_shapes;
};

class MyApp : public App
{
public:
    MyApp()
    {
        setTargetFPS(120.f);
        setWindowStyle(sf::Style::Titlebar | sf::Style::Close);
    }

protected:
    void onStart()
    {
        createWindow();
        pushState(m_myState);
    }

    bool onEvent(const sf::Event &event)
    {
        switch (event.type)
        {
            case sf::Event::KeyPressed:
            {
                if (event.key.code == sf::Keyboard::Escape)
                {
                    if (getState() != &m_pauseState)
                    {
                        pushState(m_pauseState);
                        return true;
                    }
                }
                break;
            }
            default: break;
        }

        return false;
    }

private:
    PauseState m_pauseState;
    MyState m_myState;
};

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

extern "C"
int main (int argc, char **argv)
{
    PhysicsFS physfs(argv[0]);

    try
    {
        LuaState lua;

        try
        {
            lua.doFile("config.lua");
        }
        catch (LuaState::Error &exc)
        {
            sf::err() << "Config script error: " << exc.what() << "\n";
        }

        lua.loadSafeLibs();

        try
        {
            lua.doFile("init.lua");
        }
        catch (LuaState::Error &exc)
        {
            sf::err() << "Init script error: " << exc.what() << "\n";
            throw;
        }

        MyApp app;
        app.run();
    }
    catch (std::exception &exc)
    {
        sf::err() << "Unhandled exception: " << exc.what() << "\n";
    }

    return(0);
}

////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////

<|endoftext|>


<commit_before>/*
 * Qumulus UML editor
 * Author: Randy Thiemann
 *
 */

#include "ToolBar.h"
#include <Gui/Widgets/MainWindow.h>

QUML_BEGIN_NAMESPACE_GW

#ifdef Q_OS_MAC
ToolBar::ToolBar() : mToolBar(new QMacUnifiedToolBar()) {}
#else
ToolBar::ToolBar() : mToolBar(new QToolBar()) {}
#endif

void ToolBar::showInWindow(MainWindow* w) {
    mWindow = w;
#ifdef Q_OS_MAC
    mToolBar->showInWindowForWidget(w);
#else
    w->addToolBar(mToolBar);
#endif
}

QuGW::MainWindow* ToolBar::window() {
    return mWindow;
}

QAction* ToolBar::addAction(const QIcon& icon, const QString& text) {
    return mToolBar->addAction(icon, text);
}

void ToolBar::addSeparator() {
    mToolBar->addSeparator();
}

#ifdef Q_OS_MAC
void ToolBar::addFlexibleSpace() {
    mToolBar->addStandardItem(QMacToolButton::FlexibleSpace);
}
#endif

QUML_END_NAMESPACE_GW

<commit_msg>Fix windows bug.<commit_after>/*
 * Qumulus UML editor
 * Author: Randy Thiemann
 *
 */

#include "ToolBar.h"
#include <Gui/Widgets/MainWindow.h>

QUML_BEGIN_NAMESPACE_GW

#ifdef Q_OS_MAC
ToolBar::ToolBar() : mToolBar(new QMacUnifiedToolBar()) {}
#else
ToolBar::ToolBar() : mToolBar(new QToolBar()) {}
#endif

void ToolBar::showInWindow(MainWindow* w) {
    mWindow = w;
#ifdef Q_OS_MAC
    mToolBar->showInWindowForWidget(w);
#else
    w->addToolBar(mToolBar.get());
#endif
}

QuGW::MainWindow* ToolBar::window() {
    return mWindow;
}

QAction* ToolBar::addAction(const QIcon& icon, const QString& text) {
    return mToolBar->addAction(icon, text);
}

void ToolBar::addSeparator() {
    mToolBar->addSeparator();
}

#ifdef Q_OS_MAC
void ToolBar::addFlexibleSpace() {
    mToolBar->addStandardItem(QMacToolButton::FlexibleSpace);
}
#endif

QUML_END_NAMESPACE_GW

<|endoftext|>


<commit_before>// Color.hh for Fluxbox Window Manager
// Copyright (c) 2002 Henrik Kinnunen (fluxbox@linuxmail.org)
//
// from Image.hh for Blackbox - an X11 Window manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// $Id: Color.hh,v 1.1 2002/07/23 16:23:15 fluxgen Exp $

#ifndef FBTK_COLOR_HH
#define FBTK_COLOR_HH

namespace FbTk {
/**
	Holds rgb color and pixel value
*/
class Color {
public:
	Color(unsigned char red = 0, unsigned char green = 0, unsigned char blue = 0):
	m_red(red),	m_green(green), m_blue(blue), m_pixel(0), m_allocated(false) { }

	inline void setAllocated(bool a) { m_allocated = a; }
	inline void setRGB(char red, char green, char blue) { m_red = red; m_green = green; m_blue = blue; }
	inline void setPixel(unsigned long pixel) { m_pixel = pixel; }

	inline bool isAllocated() const { return m_allocated; }

	inline unsigned char red() const { return m_red; }
	inline unsigned char green() const { return m_green; }
	inline unsigned char blue() const { return m_blue; }

	inline unsigned long pixel() const { return m_pixel; }

private:
	unsigned char m_red, m_green, m_blue;
	unsigned long m_pixel;
	bool m_allocated;
};

}; // end namespace FbTk

#endif // FBTK_COLOR_HH
<commit_msg>minor fixes<commit_after>// Color.hh for Fluxbox Window Manager
// Copyright (c) 2002 Henrik Kinnunen (fluxgen@users.sourceforge.net)
//
// from Image.hh for Blackbox - an X11 Window manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// $Id: Color.hh,v 1.2 2002/09/14 13:49:09 fluxgen Exp $

#ifndef FBTK_COLOR_HH
#define FBTK_COLOR_HH

#include "NotCopyable.hh"

namespace FbTk {
/**
	Holds rgb color and pixel value
*/
class Color {
public:
	Color();
	explicit Color(unsigned long pixel);
	Color(const Color &col_copy);
	Color(unsigned char red, unsigned char green, unsigned char blue, int screen);
	Color(const char *color_string, int screen);
	~Color();

	bool setFromString(const char *color_string, int screen);
	/// TODO don't like this
	void setPixel(unsigned long pixel) { m_pixel = pixel; }

	Color &operator = (const Color &col_copy);

	bool isAllocated() const { return m_allocated; }
	unsigned char red() const { return m_red; }
	unsigned char green() const { return m_green; }
	unsigned char blue() const { return m_blue; }
	unsigned long pixel() const { return m_pixel; }

private:
	void free();
	void copy(const Color &col);
	void allocate(unsigned char red, unsigned char green, unsigned char blue, int screen);
	inline void setAllocated(bool a) { m_allocated = a; }
	void setRGB(unsigned char red, unsigned char green, unsigned char blue);

	unsigned char m_red, m_green, m_blue;
	unsigned long m_pixel;
	bool m_allocated;
	int m_screen;
};

}; // end namespace FbTk

#endif // FBTK_COLOR_HH
<|endoftext|>


<commit_before>#pragma once

#include "Scene.hpp"
#include <SFML/Graphics.hpp>
#include <string>
#include <vector>
#include <map>

class Menu: public Scene
{
public:
	// Command enum defines the relative order of elements
	enum Command {LEVEL, EDITOR, OPTIONS, CREDITS, EXIT};
	const std::map<Command, std::string> cmdMap;
	struct Entry
	{
		Entry(std::string name, sf::Font& font, sf::Color color, unsigned int charSize, sf::Vector2f center, float angle, float radius, Command cmd):
			center(center),
			rotAngle(0),
			angle(angle),
			radius(radius),
			cmd(cmd)
		{
			text.setFont(font);
			text.setCharacterSize(charSize);
			text.setColor(color);
			text.setString(name);
		}
		void rotate(float angle)
		{
			rotAngle += angle;
		}
		void update(float percentage)
		{
			if (fabs(rotAngle) < 0.005f)
			{
				angle += rotAngle;
				rotAngle = 0.0f;
			}
			else
			{
				angle += percentage * rotAngle;
				rotAngle = (1.0f - percentage) * rotAngle;
			}

			sf::Vector2f textSize(text.getLocalBounds().width, text.getLocalBounds().height);
			sf::Vector2f dir(sin(angle), cos(angle));
			sf::Vector2f pos = center + dir * radius - textSize / 2.0f;
			text.setPosition(pos);
		}
		sf::Text text;
		const sf::Vector2f center;
		float rotAngle;
		float angle;
		const float radius;
		Command cmd;
	};

	Menu(Command initialCmd = LEVEL);
	Scene* processEvent(sf::Event event, sf::RenderWindow& window) override final;
	void update(sf::Time deltaT, sf::RenderWindow& window) override final;
	void draw(sf::RenderTarget& target) override final;
private:
	unsigned int nextPos(unsigned int pos, unsigned int size, bool clockWise);
	void rotate(bool clockWise);
	sf::Font _font;
	std::vector<Entry> _entries;
	unsigned int _currentEntry;
	std::vector<unsigned int> _levels;
	unsigned int _currentLevel;
};
<commit_msg>added comment<commit_after>#pragma once

#include "Scene.hpp"
#include <SFML/Graphics.hpp>
#include <string>
#include <vector>
#include <map>

class Menu: public Scene
{
public:
	// Command enum defines the relative order of elements
	enum Command {LEVEL, EDITOR, OPTIONS, CREDITS, EXIT};		// TODO move this to global?
	const std::map<Command, std::string> cmdMap;
	struct Entry
	{
		Entry(std::string name, sf::Font& font, sf::Color color, unsigned int charSize, sf::Vector2f center, float angle, float radius, Command cmd):
			center(center),
			rotAngle(0),
			angle(angle),
			radius(radius),
			cmd(cmd)
		{
			text.setFont(font);
			text.setCharacterSize(charSize);
			text.setColor(color);
			text.setString(name);
		}
		void rotate(float angle)
		{
			rotAngle += angle;
		}
		void update(float percentage)
		{
			if (fabs(rotAngle) < 0.005f)
			{
				angle += rotAngle;
				rotAngle = 0.0f;
			}
			else
			{
				angle += percentage * rotAngle;
				rotAngle = (1.0f - percentage) * rotAngle;
			}

			sf::Vector2f textSize(text.getLocalBounds().width, text.getLocalBounds().height);
			sf::Vector2f dir(sin(angle), cos(angle));
			sf::Vector2f pos = center + dir * radius - textSize / 2.0f;
			text.setPosition(pos);
		}
		sf::Text text;
		const sf::Vector2f center;
		float rotAngle;
		float angle;
		const float radius;
		Command cmd;
	};

	Menu(Command initialCmd = LEVEL);
	Scene* processEvent(sf::Event event, sf::RenderWindow& window) override final;
	void update(sf::Time deltaT, sf::RenderWindow& window) override final;
	void draw(sf::RenderTarget& target) override final;
private:
	unsigned int nextPos(unsigned int pos, unsigned int size, bool clockWise);
	void rotate(bool clockWise);
	sf::Font _font;
	std::vector<Entry> _entries;
	unsigned int _currentEntry;
	std::vector<unsigned int> _levels;
	unsigned int _currentLevel;
};
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------------------
** This software is implemented as part of the course
**     Algorithms in Bioinformatics - Trees and Structures Q2/2015
** at Aarhus Univerity Denmark.
**
** Days.cpp
** Implementation of the algorithm developed by Day as described in lecture 1 slide 23-27
**
** Author: Martin Storgaard, Konstantinos Mampentzidis and Henrik McQuoid Jespersen
** -----------------------------------------------------------------------------------*/
#include "Days.h"

/**
 * Reads the given input file and constructs the graph given as parameter. The file have to be on the following format:
 * n
 * 1 parent
 * 1 parent
 * 1 parent
 * ...
 * |adj| adj
 * |adj| adj
 * ...
 *
 * for example
 * 5
 * 1 2              4
 * 1 2             / \
 * 1 4            2   3
 * 3 0 1 4       / \
 * 2 2 3        0   1
 */
void Days::readFile(const char* file, vector<vector<size_t>> &graph) {
    ifstream fin;
    size_t size, i, j;
    bool expectInternalNode = false;

    fin.open(file,ios_base::in);
    if(!fin.is_open()) {
        cerr << "Could not open file " << file << endl;
        exit(EXIT_FAILURE);
    }
    fin>>size;
    graph.resize(size);

    for(i = 0; i < size; i++) {
        size_t tmpSize;
        fin >> tmpSize;
        if(tmpSize == 1 && expectInternalNode) {
            cerr << "All leaf nodes have to be first in the input file!" << endl;
            exit(EXIT_FAILURE);
        } else if(tmpSize == 1){
            numberOfLeaves++;
        } else {
            expectInternalNode = true;
        }
        for(j = 0; j < tmpSize; j++) {
            size_t tmpId;
            fin>>tmpId;
            graph[i].push_back(tmpId);
        }
    }
    fin.close();
   /*
    for(i=0;i<size;i++){

        for(j=0;j<graph[i].size();j++){
            cout<<graph[i][j]<<" ";
        }
        cout<<endl;

    }*/

}

/**
 * Sets the internal states corresponding to the two trees given as arguments
 */
void Days::initialize(const char *filename1, const char *filename2) {

    numberOfLeaves = 0;
    readFile(filename1, graph1);
    graph1NodeInfo.resize(graph1.size());
    readFile(filename2, graph2);
    graph2NodeInfo.resize(graph2.size());
    numberOfLeaves /= 2;
    dfsLabels.resize(numberOfLeaves, 0);

}

/**
 * Process the first tree (T1) according to Step 2 and Step 4 given in the slides in the first lecture, i.e. defines
 * the DF-numbering and calculating the intervals in all nodes.
 */
Days::node Days::step2(size_t curNode) {
    graph1NodeInfo[curNode].size = 0;
    graph1NodeInfo[curNode].minLabel = inf;
    graph1NodeInfo[curNode].maxLabel = 0;   //< Note that labeling starts at 1, thus no label can ever be 0

    if(curNode!=root && graph1[curNode].size() == 1) {
        // Set the DF-numbering/labeling at the given leaf
        dfsLabels[curNode] = step2Counter;
        // All leafs have size 1 and their label as minimum and maximum labels
        graph1NodeInfo[curNode].size = 1;
        graph1NodeInfo[curNode].minLabel = step2Counter;
        graph1NodeInfo[curNode].maxLabel = step2Counter;
        // Prepare for next leaf
        step2Counter++;
        return graph1NodeInfo[curNode];
    }
    visited[curNode] = true;

    for(size_t neighbour : graph1[curNode]){
        if(!visited[neighbour]){
            node info = step2(neighbour);
            // Update the current information
            graph1NodeInfo[curNode].minLabel = min(graph1NodeInfo[curNode].minLabel, info.minLabel);
            graph1NodeInfo[curNode].maxLabel = max(graph1NodeInfo[curNode].maxLabel, info.maxLabel);
            graph1NodeInfo[curNode].size += info.size;
        }
    }
    // The current node have now all information added
    return graph1NodeInfo[curNode];

}

/**
 *  Almost the same as Days::step2, but this only processes the second tree (T2). Instead of using new labels, we
 *  label all leafs to be the same as in the first tree.
 */
Days::node Days::step4(size_t curNode) {

    graph2NodeInfo[curNode].size = 0;
    graph2NodeInfo[curNode].minLabel = inf;
    graph2NodeInfo[curNode].maxLabel = 0;

    if(curNode!=root && graph2[curNode].size() == 1){
        graph2NodeInfo[curNode].size = 1;
        graph2NodeInfo[curNode].minLabel = dfsLabels[curNode];
        graph2NodeInfo[curNode].maxLabel = dfsLabels[curNode];
        return graph2NodeInfo[curNode];
    }

    visited[curNode] = true;

    for(size_t neighbour : graph2[curNode]){
        if(!visited[neighbour]){
            node info = step4(neighbour);
            graph2NodeInfo[curNode].minLabel = min(graph2NodeInfo[curNode].minLabel, info.minLabel);
            graph2NodeInfo[curNode].maxLabel = max(graph2NodeInfo[curNode].maxLabel, info.maxLabel);
            graph2NodeInfo[curNode].size += info.size;
        }
    }
    // The current node have now all information added
    return graph2NodeInfo[curNode];

}

size_t Days::run() {
    // Step 1, pick a common root
    // The input files are required to have all leafs first in the file, sorted such that they have the same order,
    // thus graph1[0] == graph2[0] holds
    root = 0;
    // Step 2, label all leafs in T1 a DF manner
    // Step 3, label all corresponding leaf nodes in T2 as for T1 (no-ops)
    // Step 4 (part 1), set all splits in T1
    step2Counter = 1;
    visited.resize(graph1.size(), false);
    step2(root);
    // Step 4 (part 2), find all splits in T2
    visited.assign(graph2.size(), false);
    step4(root);

    // Step 4 (part 3), find all shared splits between T1 and T2
    //TODO: use radix sort
    sort(graph1NodeInfo.begin(), graph1NodeInfo.end(), Days::comp());
    sort(graph2NodeInfo.begin(), graph2NodeInfo.end(), Days::comp());

//    size_t i;
//    for(i=0;i<graph1NodeInfo.size();i++){
//        cout<<"["<<graph1NodeInfo[i].minLabel<<","<<graph1NodeInfo[i].maxLabel<<","<<graph1NodeInfo[i].size<<"] ";
//    }
//    cout<<endl;
//    for(i=0;i<graph2NodeInfo.size();i++){
//        cout<<"["<<graph2NodeInfo[i].minLabel<<","<<graph2NodeInfo[i].maxLabel<<","<<graph2NodeInfo[i].size<<"] ";
//    }
//    cout<<endl;

    size_t t1, t2,sharedSplits = 0;
    const size_t size1 = graph1NodeInfo.size();
    const size_t size2 = graph2NodeInfo.size();

    t1=t2=0;
    while(t1 < size1 && t2 < size2){

        const node node1 = graph1NodeInfo[t1];
        const node node2 = graph2NodeInfo[t2];

        if(node1 == node2){
            if(node1.size == node2.size) {
                // node1 is always filled with consequently filled intervals, thus that size of node1 always indicates
                // a legal split
                sharedSplits++;
            }
            t1++;
            t2++;
        } else if(node1 < node2){
            t1++;
        } else{
            t2++;
        }

    }
    // The RF-distance is then "number of splits not found in both trees", which is equal to the number of splits
    // in both trees, minus all the shared splits between T1 and T2 minus all the shared splits in T2 and T1
    return size1 + size2 - 2*sharedSplits;
}
<commit_msg>Using fill to clear in visited vector, which uses  mmx registers to dump in 16 bytes at a time<commit_after>/* -------------------------------------------------------------------------------------
** This software is implemented as part of the course
**     Algorithms in Bioinformatics - Trees and Structures Q2/2015
** at Aarhus Univerity Denmark.
**
** Days.cpp
** Implementation of the algorithm developed by Day as described in lecture 1 slide 23-27
**
** Author: Martin Storgaard, Konstantinos Mampentzidis and Henrik McQuoid Jespersen
** -----------------------------------------------------------------------------------*/
#include "Days.h"

/**
 * Reads the given input file and constructs the graph given as parameter. The file have to be on the following format:
 * n
 * 1 parent
 * 1 parent
 * 1 parent
 * ...
 * |adj| adj
 * |adj| adj
 * ...
 *
 * for example
 * 5
 * 1 2              4
 * 1 2             / \
 * 1 4            2   3
 * 3 0 1 4       / \
 * 2 2 3        0   1
 */
void Days::readFile(const char* file, vector<vector<size_t>> &graph) {
    ifstream fin;
    size_t size, i, j;
    bool expectInternalNode = false;

    fin.open(file,ios_base::in);
    if(!fin.is_open()) {
        cerr << "Could not open file " << file << endl;
        exit(EXIT_FAILURE);
    }
    fin>>size;
    graph.resize(size);

    for(i = 0; i < size; i++) {
        size_t tmpSize;
        fin >> tmpSize;
        if(tmpSize == 1 && expectInternalNode) {
            cerr << "All leaf nodes have to be first in the input file!" << endl;
            exit(EXIT_FAILURE);
        } else if(tmpSize == 1){
            numberOfLeaves++;
        } else {
            expectInternalNode = true;
        }
        for(j = 0; j < tmpSize; j++) {
            size_t tmpId;
            fin>>tmpId;
            graph[i].push_back(tmpId);
        }
    }
    fin.close();
   /*
    for(i=0;i<size;i++){

        for(j=0;j<graph[i].size();j++){
            cout<<graph[i][j]<<" ";
        }
        cout<<endl;

    }*/

}

/**
 * Sets the internal states corresponding to the two trees given as arguments
 */
void Days::initialize(const char *filename1, const char *filename2) {

    numberOfLeaves = 0;
    readFile(filename1, graph1);
    graph1NodeInfo.resize(graph1.size());
    readFile(filename2, graph2);
    graph2NodeInfo.resize(graph2.size());
    numberOfLeaves /= 2;
    dfsLabels.resize(numberOfLeaves, 0);

}

/**
 * Process the first tree (T1) according to Step 2 and Step 4 given in the slides in the first lecture, i.e. defines
 * the DF-numbering and calculating the intervals in all nodes.
 */
Days::node Days::step2(size_t curNode) {
    graph1NodeInfo[curNode].size = 0;
    graph1NodeInfo[curNode].minLabel = inf;
    graph1NodeInfo[curNode].maxLabel = 0;   //< Note that labeling starts at 1, thus no label can ever be 0

    if(curNode!=root && graph1[curNode].size() == 1) {
        // Set the DF-numbering/labeling at the given leaf
        dfsLabels[curNode] = step2Counter;
        // All leafs have size 1 and their label as minimum and maximum labels
        graph1NodeInfo[curNode].size = 1;
        graph1NodeInfo[curNode].minLabel = step2Counter;
        graph1NodeInfo[curNode].maxLabel = step2Counter;
        // Prepare for next leaf
        step2Counter++;
        return graph1NodeInfo[curNode];
    }
    visited[curNode] = true;

    for(size_t neighbour : graph1[curNode]){
        if(!visited[neighbour]){
            node info = step2(neighbour);
            // Update the current information
            graph1NodeInfo[curNode].minLabel = min(graph1NodeInfo[curNode].minLabel, info.minLabel);
            graph1NodeInfo[curNode].maxLabel = max(graph1NodeInfo[curNode].maxLabel, info.maxLabel);
            graph1NodeInfo[curNode].size += info.size;
        }
    }
    // The current node have now all information added
    return graph1NodeInfo[curNode];

}

/**
 *  Almost the same as Days::step2, but this only processes the second tree (T2). Instead of using new labels, we
 *  label all leafs to be the same as in the first tree.
 */
Days::node Days::step4(size_t curNode) {

    graph2NodeInfo[curNode].size = 0;
    graph2NodeInfo[curNode].minLabel = inf;
    graph2NodeInfo[curNode].maxLabel = 0;

    if(curNode!=root && graph2[curNode].size() == 1){
        graph2NodeInfo[curNode].size = 1;
        graph2NodeInfo[curNode].minLabel = dfsLabels[curNode];
        graph2NodeInfo[curNode].maxLabel = dfsLabels[curNode];
        return graph2NodeInfo[curNode];
    }

    visited[curNode] = true;

    for(size_t neighbour : graph2[curNode]){
        if(!visited[neighbour]){
            node info = step4(neighbour);
            graph2NodeInfo[curNode].minLabel = min(graph2NodeInfo[curNode].minLabel, info.minLabel);
            graph2NodeInfo[curNode].maxLabel = max(graph2NodeInfo[curNode].maxLabel, info.maxLabel);
            graph2NodeInfo[curNode].size += info.size;
        }
    }
    // The current node have now all information added
    return graph2NodeInfo[curNode];

}

size_t Days::run() {
    // Step 1, pick a common root
    // The input files are required to have all leafs first in the file, sorted such that they have the same order,
    // thus graph1[0] == graph2[0] holds
    root = 0;
    // Step 2, label all leafs in T1 a DF manner
    // Step 3, label all corresponding leaf nodes in T2 as for T1 (no-ops)
    // Step 4 (part 1), set all splits in T1
    step2Counter = 1;
    visited.resize(graph1.size(), false);
    step2(root);
    // Step 4 (part 2), find all splits in T2
    fill(visited.begin(), visited.begin()+graph2.size(), false);
//    visited.assign(graph2.size(), false);
    step4(root);

    // Step 4 (part 3), find all shared splits between T1 and T2
    //TODO: use radix sort
    sort(graph1NodeInfo.begin(), graph1NodeInfo.end(), Days::comp());
    sort(graph2NodeInfo.begin(), graph2NodeInfo.end(), Days::comp());

//    size_t i;
//    for(i=0;i<graph1NodeInfo.size();i++){
//        cout<<"["<<graph1NodeInfo[i].minLabel<<","<<graph1NodeInfo[i].maxLabel<<","<<graph1NodeInfo[i].size<<"] ";
//    }
//    cout<<endl;
//    for(i=0;i<graph2NodeInfo.size();i++){
//        cout<<"["<<graph2NodeInfo[i].minLabel<<","<<graph2NodeInfo[i].maxLabel<<","<<graph2NodeInfo[i].size<<"] ";
//    }
//    cout<<endl;

    size_t t1, t2,sharedSplits = 0;
    const size_t size1 = graph1NodeInfo.size();
    const size_t size2 = graph2NodeInfo.size();

    t1=t2=0;
    while(t1 < size1 && t2 < size2){

        const node node1 = graph1NodeInfo[t1];
        const node node2 = graph2NodeInfo[t2];

        if(node1 == node2){
            if(node1.size == node2.size) {
                // node1 is always filled with consequently filled intervals, thus that size of node1 always indicates
                // a legal split
                sharedSplits++;
            }
            t1++;
            t2++;
        } else if(node1 < node2){
            t1++;
        } else{
            t2++;
        }

    }
    // The RF-distance is then "number of splits not found in both trees", which is equal to the number of splits
    // in both trees, minus all the shared splits between T1 and T2 minus all the shared splits in T2 and T1
    return size1 + size2 - 2*sharedSplits;
}
<|endoftext|>


<commit_before>//=============================================================================
//File Name: Shooter.cpp
//Description: Provides an interface to the dual-motored shooter and its
//             encoder; it also has an interface for a PID loop
//Author: FRC Team 3512, Spartatroniks
//=============================================================================

#include "Shooter.hpp"
#include <cmath>
#include <cfloat>

const float Shooter::maxSpeed = 5000.f;

Shooter::Shooter( UINT32 motor1 , UINT32 motor2 ,
        UINT32 encChannel , UINT32 encTeeth , float encGearRatio ) :
        m_shooterMotor1( motor1 ) ,
        m_shooterMotor2( motor2 ) ,
        m_shooterEncoder( encChannel , encTeeth , encGearRatio ) ,
        m_shooterPID( 0.f , 0.f , 0.f , 1.f / maxSpeed , this , this , 0.5f ) ,
        m_setpoint( 0.f ) ,
        m_isShooting( false ) ,
        m_controlMode( Manual ) ,
        m_negativeOutputAllowed( true ) ,
        m_P( m_shooterPID.GetP() ) ,
        m_I( m_shooterPID.GetI() ) ,
        m_D( m_shooterPID.GetD() ) ,
        m_F( m_shooterPID.GetF() ) {
    m_shooterPID.SetOutputRange( -1.f , 1.f );
    m_shooterPID.SetTolerance( 0.f );

    m_shooterPID.SetSetpoint( m_setpoint );

    m_shooterEncoder.start();
    m_shooterPID.Enable();
    start();
}

Shooter::~Shooter() {

}

void Shooter::start() {
    m_shooterPID.Enable();
    m_shooterPID.SetSetpoint( m_setpoint );

    m_isShooting = true;
}

void Shooter::stop() {
    m_shooterPID.Reset();

    m_isShooting = false;
}

bool Shooter::isShooting() {
    return m_isShooting;
}

bool Shooter::isReady() {
    return std::fabs(getRPM() - m_setpoint) < 100 && m_isShooting;
}

void Shooter::setRPM( float wheelSpeed ) {
    if ( m_isShooting ) {
        m_setpoint = wheelSpeed;
        m_shooterPID.SetSetpoint( m_setpoint );
    }
}

void Shooter::setScale( float scaleFactor ) {
    if ( m_isShooting ) {
        // Limit 'scaleFactor' to a value between 0 and 1 inclusive
        if ( scaleFactor < 0.f ) {
            scaleFactor = 0.f;
        }
        if ( scaleFactor > 1.f ) {
            scaleFactor = 1.f;
        }

        m_setpoint = scaleFactor * maxSpeed;
        m_shooterPID.SetSetpoint( m_setpoint );
    }
}

float Shooter::getRPM() {
    return m_shooterEncoder.getRPM();
}

float Shooter::getTargetRPM() {
    return m_setpoint;
}

bool Shooter::negativeOutputAllowed() {
    return m_negativeOutputAllowed;
}

void Shooter::setControlMode( ControlMode mode ) {
    m_controlMode = mode;

    if ( mode == Manual ) {
        m_shooterPID.SetPID( 0.f , 0.f , 0.f , m_F );
    }
    else {
        m_shooterPID.SetPID( m_P , m_I , m_D , 0.f );
    }
}

Shooter::ControlMode Shooter::getControlMode() {
    return m_controlMode;
}

void Shooter::setPID( float p , float i , float d ) {
    m_P = p;
    m_I = i;
    m_D = d;

    // Updates PID constants for PIDController object internally
    setControlMode( getControlMode() );
}

double Shooter::PIDGet() {
    if ( m_shooterEncoder.getRPM() < 100.f && m_negativeOutputAllowed ) {
        m_shooterPID.SetOutputRange( 0.f , 1.f );
        m_negativeOutputAllowed = false;
    }
    else if ( m_shooterEncoder.getRPM() >= 500.f && !m_negativeOutputAllowed ) {
        m_shooterPID.SetOutputRange( -1.f , 1.f );
        m_negativeOutputAllowed = true;
    }

    return m_shooterEncoder.getRPM();
}

void Shooter::PIDWrite( float output ) {
    /* Ouputs are negated because the motor controllers require a negative
     * number to make the shooter wheel spin in the correct direction
     */
    switch ( m_controlMode ) {
    case PID: {
        m_shooterMotor1.Set( -output );
        m_shooterMotor2.Set( -output );

        break;
    }

    case BangBang: {
        if ( m_shooterEncoder.getRPM() >= m_setpoint ) {
            m_shooterMotor1.Set( 0.f );
            m_shooterMotor2.Set( 0.f );
        }
        else {
            m_shooterMotor1.Set( -1.f );
            m_shooterMotor2.Set( -1.f );
        }

        break;
    }

    /* The only non-zero term in "Manual" is F, which turns off error
     * correction and responds only to the input given by the user.
     */
    case Manual: {
        m_shooterMotor1.Set( -output );
        m_shooterMotor2.Set( -output );

        break;
    }
    }
}
<commit_msg>Commit before 2013 bag-up<commit_after>//=============================================================================
//File Name: Shooter.cpp
//Description: Provides an interface to the dual-motored shooter and its
//             encoder; it also has an interface for a PID loop
//Author: FRC Team 3512, Spartatroniks
//=============================================================================

#include "Shooter.hpp"
#include <cmath>
#include <cfloat>

const float Shooter::maxSpeed = 5000.f;

Shooter::Shooter( UINT32 motor1 , UINT32 motor2 ,
        UINT32 encChannel , UINT32 encTeeth , float encGearRatio ) :
        m_shooterMotor1( motor1 ) ,
        m_shooterMotor2( motor2 ) ,
        m_shooterEncoder( encChannel , encTeeth , encGearRatio ) ,
        m_shooterPID( 0.f , 0.f , 0.f , 1.f / maxSpeed , this , this , 0.5f ) ,
        m_setpoint( 0.f ) ,
        m_isShooting( false ) ,
        m_controlMode( Manual ) ,
        m_negativeOutputAllowed( true ) ,
        m_P( m_shooterPID.GetP() ) ,
        m_I( m_shooterPID.GetI() ) ,
        m_D( m_shooterPID.GetD() ) ,
        m_F( m_shooterPID.GetF() ) {
    m_shooterPID.SetOutputRange( -1.f , 1.f );
    m_shooterPID.SetTolerance( 0.f );

    m_shooterPID.SetSetpoint( m_setpoint );

    m_shooterEncoder.start();
    m_shooterPID.Enable();
    start();
}

Shooter::~Shooter() {

}

void Shooter::start() {
    m_shooterPID.Enable();
    m_shooterPID.SetSetpoint( m_setpoint );

    m_isShooting = true;
}

void Shooter::stop() {
    m_shooterPID.Reset();

    m_isShooting = false;
}

bool Shooter::isShooting() {
    return m_isShooting;
}

bool Shooter::isReady() {
    return std::fabs(getRPM() - m_setpoint) < 100 && m_isShooting;
}

void Shooter::setRPM( float wheelSpeed ) {
    if ( m_isShooting ) {
        m_setpoint = wheelSpeed;
        m_shooterPID.SetSetpoint( m_setpoint );
    }
}

void Shooter::setScale( float scaleFactor ) {
    if ( m_isShooting ) {
        // Limit 'scaleFactor' to a value between 0 and 1 inclusive
        if ( scaleFactor < 0.f ) {
            scaleFactor = 0.f;
        }
        if ( scaleFactor > 1.f ) {
            scaleFactor = 1.f;
        }

        m_setpoint = scaleFactor * maxSpeed;
        m_shooterPID.SetSetpoint( m_setpoint );
    }
}

float Shooter::getRPM() {
    return m_shooterEncoder.getRPM();
}

<<<<<<< HEAD
float Shooter::getTargetRPM() {
    return m_setpoint;
}

bool Shooter::negativeOutputAllowed() {
    return m_negativeOutputAllowed;
=======
void Shooter::enableControl() {
    //if ( getControlMode() == PID ) {
        m_shooterPID.Enable();
    //}
}

void Shooter::disableControl() {
    //if ( getControlMode() == PID ) {
        m_shooterPID.Disable();
    //}
>>>>>>> Commit before 2013 bag-up
}

void Shooter::setControlMode( ControlMode mode ) {
    m_controlMode = mode;

    if ( mode == Manual ) {
        m_shooterPID.SetPID( 0.f , 0.f , 0.f , m_F );
    }
    else {
        m_shooterPID.SetPID( m_P , m_I , m_D , 0.f );
    }
}

Shooter::ControlMode Shooter::getControlMode() {
    return m_controlMode;
}

void Shooter::setPID( float p , float i , float d ) {
    m_P = p;
    m_I = i;
    m_D = d;

    // Updates PID constants for PIDController object internally
    setControlMode( getControlMode() );
}

double Shooter::PIDGet() {
    if ( m_shooterEncoder.getRPM() < 100.f && m_negativeOutputAllowed ) {
        m_shooterPID.SetOutputRange( 0.f , 1.f );
        m_negativeOutputAllowed = false;
    }
    else if ( m_shooterEncoder.getRPM() >= 500.f && !m_negativeOutputAllowed ) {
        m_shooterPID.SetOutputRange( -1.f , 1.f );
        m_negativeOutputAllowed = true;
    }

    return m_shooterEncoder.getRPM();
}

void Shooter::PIDWrite( float output ) {
    /* Ouputs are negated because the motor controllers require a negative
     * number to make the shooter wheel spin in the correct direction
     */
    switch ( m_controlMode ) {
    case PID: {
        m_shooterMotor1.Set( -output );
        m_shooterMotor2.Set( -output );

        break;
    }

    case BangBang: {
        if ( m_shooterEncoder.getRPM() >= m_setpoint ) {
            m_shooterMotor1.Set( 0.f );
            m_shooterMotor2.Set( 0.f );
        }
        else {
            m_shooterMotor1.Set( -1.f );
            m_shooterMotor2.Set( -1.f );
        }

        break;
<<<<<<< HEAD
    }

    /* The only non-zero term in "Manual" is F, which turns off error
     * correction and responds only to the input given by the user.
     */
    case Manual: {
        m_shooterMotor1.Set( -output );
        m_shooterMotor2.Set( -output );

        break;
=======
>>>>>>> Commit before 2013 bag-up
    }
    }
}
<|endoftext|>


<commit_before>#include <Game.h>

Game& Game::getGame(const std::string& _name) {
    static Game* instance = new Game(_name);
    INFO("Getting Game instance");
    return *instance;
}

Game::Game(const std::string& _name) {
    INFO("Initializing new Game: %s", _name.c_str());
    config.name = _name;

    std::string iniFilename = config.name;
    iniFilename.append(".ini");

    INIReader reader(iniFilename);
    INFO("Reading config from '%s'", iniFilename.c_str());
    if (reader.ParseError() < 0) {
        ERR("Can't load '%s', using defaults", iniFilename.c_str());
    } else {
        // 1200x675 is a 16:9 window that fits inside a 1366x768 screen on most systems
        config.width = (unsigned int) std::abs(reader.GetInteger("game", "width", (long) config.width));
        config.height = (unsigned int) std::abs(reader.GetInteger("game", "height", (long) config.height));
        config.fullscreen = reader.GetBoolean("game", "fullscreen", config.fullscreen);
        config.useDesktopSize = reader.GetBoolean("game", "useDesktopSize", config.useDesktopSize);
        config.deadZone = static_cast<float>(reader.GetReal("game", "deadZone", config.deadZone));
        config.keySpeed = static_cast<float>(reader.GetReal("game", "keySpeed", config.keySpeed));
    }
    INFO("--Config--");
    INFO("width = %d", config.width);
    INFO("height = %d", config.height);
    INFO("fullscreen = %s", (config.fullscreen ? "true" : "false"));
    INFO("useDesktopSize = %s", (config.useDesktopSize ? "true" : "false"));
    INFO("deadZone = %f", config.deadZone);
    INFO("keySpeed = %f", config.keySpeed);
    INFO("--End config--");

    INFO("Creating %dx%d render target", renderWidth, renderHeight);
    screen.create(renderWidth, renderHeight);

    createWindow(config.fullscreen);

    spritesMutex.lock();
    player = new GamePlayer;
    player->setPosition(renderWidth * 1 / 2, renderHeight * 3 / 4);
    sprites.push_back(player);
    spritesMutex.unlock();
    INFO("Loaded player");

    isReady = true;
    INFO("Initialized");
}

bool Game::ready() {
    return isReady;
}

void Game::createWindow(bool shouldFullscreen) {
    unsigned int flags = 0;
    sf::VideoMode mode;
    config.fullscreen = shouldFullscreen;
    if (config.fullscreen) {
        INFO("Going fullscreen");
        window.setMouseCursorVisible(false);
        if (config.useDesktopSize) {
            INFO("Setting fullscreen mode (using desktop size): %dx%d",
                 sf::VideoMode::getDesktopMode().width,
                 sf::VideoMode::getDesktopMode().height);
            mode = sf::VideoMode::getDesktopMode();
        } else {
            INFO("Setting fullscreen mode: %dx%d", config.width, config.height);
            mode = sf::VideoMode(config.width, config.height);
        }
        flags = sf::Style::Fullscreen;
    } else {
        INFO("Setting windowed mode: %dx%d", config.width, config.height);
        window.setMouseCursorVisible(true);
        mode = sf::VideoMode(config.width, config.height);
        flags = sf::Style::Titlebar | sf::Style::Close | sf::Style::Resize;
    }
    windowMutex.lock();
    window.create(mode, config.name, flags);
    if (!window.isOpen()) {
        ERR("Could not create main window");
        exit(EXIT_FAILURE);
    }
    sf::ContextSettings settings = window.getSettings();
    INFO("Using OpenGL %d.%d", settings.majorVersion, settings.minorVersion);

    // initialize the view
    view = window.getDefaultView();
    view.setSize(renderWidth, renderHeight);
    view.setCenter(renderWidth / 2, renderHeight / 2);
    window.setView(view);
    INFO("Enabling V-sync");
    window.setVerticalSyncEnabled(true);
    // scale the viewport to maintain good aspect
    adjustAspect(window.getSize());
    windowMutex.unlock();
}

void Game::adjustAspect(sf::Event::SizeEvent newSize) {
    // save the new window size since this came from a resize event
    // not from initialization or a fullscreen toggle
    config.width = newSize.width;
    config.height = newSize.height;
    // do the calculation
    adjustAspect(sf::Vector2u(newSize.width, newSize.height));
}

void Game::adjustAspect(sf::Vector2u newSize) {
    // compute the current aspect
    float currentRatio = (float) newSize.x / (float) newSize.y;
    // used to offset and scale the viewport to maintain 16:9 aspect
    float widthScale = 1.0f;
    float widthOffset = 0.0f;
    float heightScale = 1.0f;
    float heightOffset = 0.0f;
    // used to compare and compute aspect ratios
    // for logging
    std::string isSixteenNine = "16:9";
    if (currentRatio > 16.0f / 9.0f) {
        // we are wider
        isSixteenNine = "wide";
        widthScale = newSize.y * (16.0f / 9.0f) / newSize.x;
        widthOffset = (1.0f - widthScale) / 2.0f;
    } else if (currentRatio < 16.0f / 9.0f) {
        // we are narrower
        isSixteenNine = "narrow";
        heightScale = newSize.x * (9.0f / 16.0f) / newSize.y;
        heightOffset = (1.0f - heightScale) / 2.0f;
    }
    INFO("Adjusting aspect for window size ", newSize.x, newSize.y);
    INFO("Setting %s viewport (wo:%f, ho:%f; ws:%f, hs: %f", isSixteenNine.c_str(),
         widthOffset, heightOffset, widthScale, heightScale);
    view.setViewport(sf::FloatRect(widthOffset, heightOffset, widthScale, heightScale));
    windowMutex.lock();
    window.setView(view);
    windowMutex.unlock();

}

void Game::processEvents() {
    static sf::Event event;

    while (window.pollEvent(event)) {
        switch (event.type) {
            case sf::Event::Closed:
                INFO("Window closed");
                window.close();
                break;
            case sf::Event::Resized:
                adjustAspect(event.size);
                break;
            case sf::Event::KeyPressed:
                handleKeyPress(event);
                break;
            case sf::Event::KeyReleased:
                handleKeyRelease(event);
                break;
            default:
                break;
        }
    }
}

void Game::handleKeyPress(const sf::Event& event) {
    switch (event.key.code) {
        case sf::Keyboard::Escape:
            INFO("GamePlayer exited");
            window.close();
            break;
        case sf::Keyboard::Return:
            if (event.key.alt) {
                createWindow(!config.fullscreen);
            }
            break;
        default:
            break;
    }
}

void Game::handleKeyRelease(const sf::Event& event) const {
    switch (event.key.code) {
        default:
            break;
    }
}

void Game::updateControls() {
    float x, y = 0;

    float joy0_X = sf::Joystick::getAxisPosition(0, sf::Joystick::X);
    float joy0_y = sf::Joystick::getAxisPosition(0, sf::Joystick::Y);
    x = fabs(joy0_X) < config.deadZone ? 0 : joy0_X;
    y = fabs(joy0_y) < config.deadZone ? 0 : joy0_y;

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
        y += -config.keySpeed;
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
        x += config.keySpeed;
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
        y += config.keySpeed;
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
        x += -config.keySpeed;
    }
    spritesMutex.lock();
    player->moveBy(x, y);
    spritesMutex.unlock();

}

void Game::updateWorld(sf::Time elapsed) {
    spritesMutex.lock();
    const int millis = elapsed.asMilliseconds();
    for (auto sprite : sprites) {
        sprite->update(millis);
    }
    spritesMutex.unlock();
}

void Game::run(void) {
    window.setActive(false);
    sf::Thread renderThread(&Game::renderLoop, this);
    renderThread.launch();

    sf::Clock gameClock;
    sf::Time elapsedTime;
//    sf::Int32 updateTime;
    INFO("Starting %s", config.name.c_str());
    while (window.isOpen()) {
        elapsedTime = gameClock.restart();
        processEvents();
        updateControls();
        updateWorld(elapsedTime);
        sf::sleep(sf::milliseconds(16));
//        updateTime = elapsedTime.asMilliseconds();
//        DBUG("Update time: %d ms", updateTime);
    }
    INFO("Stopped");
}

void Game::renderLoop(void) {
    sf::Int32 frameTime;
    sf::Clock renderClock;
    window.setActive(true);
    renderClock.restart();
    while (window.isOpen()) {
        // blank the render target to black
        screen.clear(sf::Color::Black);
        // render all the normal sprites
        spritesMutex.lock();
        for (const auto sprite : sprites) {
            screen.draw(*sprite);
        }
        spritesMutex.unlock();
        // update the target
        screen.display();
        windowMutex.lock();
        // blank the window to gray
        window.clear(sf::Color(128, 128, 128));
        // copy render target to window
        window.draw(sf::Sprite(screen.getTexture()));
        // update thw window
        window.display();
        windowMutex.unlock();
        frameTime = renderClock.restart().asMilliseconds();
        DBUG("Frame time: %d ms", frameTime);
    }
}<commit_msg>Keep track of average update and frame times.<commit_after>#include <Game.h>

Game& Game::getGame(const std::string& _name) {
    static Game* instance = new Game(_name);
    INFO("Getting Game instance");
    return *instance;
}

Game::Game(const std::string& _name) {
    INFO("Initializing new Game: %s", _name.c_str());
    config.name = _name;

    std::string iniFilename = config.name;
    iniFilename.append(".ini");

    INIReader reader(iniFilename);
    INFO("Reading config from '%s'", iniFilename.c_str());
    if (reader.ParseError() < 0) {
        ERR("Can't load '%s', using defaults", iniFilename.c_str());
    } else {
        // 1200x675 is a 16:9 window that fits inside a 1366x768 screen on most systems
        config.width = (unsigned int) std::abs(reader.GetInteger("game", "width", (long) config.width));
        config.height = (unsigned int) std::abs(reader.GetInteger("game", "height", (long) config.height));
        config.fullscreen = reader.GetBoolean("game", "fullscreen", config.fullscreen);
        config.useDesktopSize = reader.GetBoolean("game", "useDesktopSize", config.useDesktopSize);
        config.deadZone = static_cast<float>(reader.GetReal("game", "deadZone", config.deadZone));
        config.keySpeed = static_cast<float>(reader.GetReal("game", "keySpeed", config.keySpeed));
    }
    INFO("--Config--");
    INFO("width = %d", config.width);
    INFO("height = %d", config.height);
    INFO("fullscreen = %s", (config.fullscreen ? "true" : "false"));
    INFO("useDesktopSize = %s", (config.useDesktopSize ? "true" : "false"));
    INFO("deadZone = %f", config.deadZone);
    INFO("keySpeed = %f", config.keySpeed);
    INFO("--End config--");

    INFO("Creating %dx%d render target", renderWidth, renderHeight);
    screen.create(renderWidth, renderHeight);

    createWindow(config.fullscreen);

    spritesMutex.lock();
    player = new GamePlayer;
    player->setPosition(renderWidth * 1 / 2, renderHeight * 3 / 4);
    sprites.push_back(player);
    spritesMutex.unlock();
    INFO("Loaded player");

    isReady = true;
    INFO("Initialized");
}

bool Game::ready() {
    return isReady;
}

void Game::createWindow(bool shouldFullscreen) {
    unsigned int flags = 0;
    sf::VideoMode mode;
    config.fullscreen = shouldFullscreen;
    if (config.fullscreen) {
        INFO("Going fullscreen");
        window.setMouseCursorVisible(false);
        if (config.useDesktopSize) {
            INFO("Setting fullscreen mode (using desktop size): %dx%d",
                 sf::VideoMode::getDesktopMode().width,
                 sf::VideoMode::getDesktopMode().height);
            mode = sf::VideoMode::getDesktopMode();
        } else {
            INFO("Setting fullscreen mode: %dx%d", config.width, config.height);
            mode = sf::VideoMode(config.width, config.height);
        }
        flags = sf::Style::Fullscreen;
    } else {
        INFO("Setting windowed mode: %dx%d", config.width, config.height);
        window.setMouseCursorVisible(true);
        mode = sf::VideoMode(config.width, config.height);
        flags = sf::Style::Titlebar | sf::Style::Close | sf::Style::Resize;
    }
    windowMutex.lock();
    window.create(mode, config.name, flags);
    if (!window.isOpen()) {
        ERR("Could not create main window");
        exit(EXIT_FAILURE);
    }
    sf::ContextSettings settings = window.getSettings();
    INFO("Using OpenGL %d.%d", settings.majorVersion, settings.minorVersion);

    // initialize the view
    view = window.getDefaultView();
    view.setSize(renderWidth, renderHeight);
    view.setCenter(renderWidth / 2, renderHeight / 2);
    window.setView(view);
    INFO("Enabling V-sync");
    window.setVerticalSyncEnabled(true);
    // scale the viewport to maintain good aspect
    adjustAspect(window.getSize());
    windowMutex.unlock();
}

void Game::adjustAspect(sf::Event::SizeEvent newSize) {
    // save the new window size since this came from a resize event
    // not from initialization or a fullscreen toggle
    config.width = newSize.width;
    config.height = newSize.height;
    // do the calculation
    adjustAspect(sf::Vector2u(newSize.width, newSize.height));
}

void Game::adjustAspect(sf::Vector2u newSize) {
    // compute the current aspect
    float currentRatio = (float) newSize.x / (float) newSize.y;
    // used to offset and scale the viewport to maintain 16:9 aspect
    float widthScale = 1.0f;
    float widthOffset = 0.0f;
    float heightScale = 1.0f;
    float heightOffset = 0.0f;
    // used to compare and compute aspect ratios
    // for logging
    std::string isSixteenNine = "16:9";
    if (currentRatio > 16.0f / 9.0f) {
        // we are wider
        isSixteenNine = "wide";
        widthScale = newSize.y * (16.0f / 9.0f) / newSize.x;
        widthOffset = (1.0f - widthScale) / 2.0f;
    } else if (currentRatio < 16.0f / 9.0f) {
        // we are narrower
        isSixteenNine = "narrow";
        heightScale = newSize.x * (9.0f / 16.0f) / newSize.y;
        heightOffset = (1.0f - heightScale) / 2.0f;
    }
    INFO("Adjusting aspect for window size ", newSize.x, newSize.y);
    INFO("Setting %s viewport (wo:%f, ho:%f; ws:%f, hs: %f", isSixteenNine.c_str(),
         widthOffset, heightOffset, widthScale, heightScale);
    view.setViewport(sf::FloatRect(widthOffset, heightOffset, widthScale, heightScale));
    windowMutex.lock();
    window.setView(view);
    windowMutex.unlock();

}

void Game::processEvents() {
    static sf::Event event;

    while (window.pollEvent(event)) {
        switch (event.type) {
            case sf::Event::Closed:
                INFO("Window closed");
                window.close();
                break;
            case sf::Event::Resized:
                adjustAspect(event.size);
                break;
            case sf::Event::KeyPressed:
                handleKeyPress(event);
                break;
            case sf::Event::KeyReleased:
                handleKeyRelease(event);
                break;
            default:
                break;
        }
    }
}

void Game::handleKeyPress(const sf::Event& event) {
    switch (event.key.code) {
        case sf::Keyboard::Escape:
            INFO("GamePlayer exited");
            window.close();
            break;
        case sf::Keyboard::Return:
            if (event.key.alt) {
                createWindow(!config.fullscreen);
            }
            break;
        default:
            break;
    }
}

void Game::handleKeyRelease(const sf::Event& event) const {
    switch (event.key.code) {
        default:
            break;
    }
}

void Game::updateControls() {
    float x, y = 0;

    float joy0_X = sf::Joystick::getAxisPosition(0, sf::Joystick::X);
    float joy0_y = sf::Joystick::getAxisPosition(0, sf::Joystick::Y);
    x = fabs(joy0_X) < config.deadZone ? 0 : joy0_X;
    y = fabs(joy0_y) < config.deadZone ? 0 : joy0_y;

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
        y += -config.keySpeed;
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
        x += config.keySpeed;
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
        y += config.keySpeed;
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
        x += -config.keySpeed;
    }
    spritesMutex.lock();
    player->moveBy(x, y);
    spritesMutex.unlock();

}

void Game::updateWorld(sf::Time elapsed) {
    spritesMutex.lock();
    const int millis = elapsed.asMilliseconds();
    for (auto sprite : sprites) {
        sprite->update(millis);
    }
    spritesMutex.unlock();
}

void Game::run(void) {
    window.setActive(false);
    sf::Thread renderThread(&Game::renderLoop, this);
    renderThread.launch();

    INFO("Initializing eventLoop");
    sf::Clock gameClock;
    sf::Time elapsedTime;
    sf::Int32 lastUpdateTime;
    sf::Int32 totalUpdateTime = 0;
    sf::Int32 averageUpdateTime;
    sf::Int32 updateCount = 0;
    INFO("Starting eventLoop");
    while (window.isOpen()) {
        elapsedTime = gameClock.restart();
        processEvents();
        updateControls();
        updateWorld(elapsedTime);
        lastUpdateTime = gameClock.getElapsedTime().asMilliseconds();
        totalUpdateTime += lastUpdateTime;
        averageUpdateTime = totalUpdateTime / ++updateCount;
        if (updateCount % 100 == 0) {
            DBUG("Average update time: %d ms", averageUpdateTime);
        }
        sf::sleep(sf::milliseconds(16));
    }
    INFO("Stopped eventLoop");
}

void Game::renderLoop(void) {
    INFO("Initializing renderLoop");
    sf::Clock frameClock;
    sf::Int32 lastFrameTime;
    sf::Int32 averageFrameTime;
    sf::Int32 totalFrameTime = 0;
    sf::Int32 frameCount = 0;
    window.setActive(true);
    INFO("Starting renderLoop");
    while (window.isOpen()) {
        frameClock.restart();
        // blank the render target to black
        screen.clear(sf::Color::Black);
        // render all the normal sprites
        spritesMutex.lock();
        for (const auto sprite : sprites) {
            screen.draw(*sprite);
        }
        spritesMutex.unlock();
        // update the target
        screen.display();
        windowMutex.lock();
        // blank the window to gray
        window.clear(sf::Color(128, 128, 128));
        // copy render target to window
        window.draw(sf::Sprite(screen.getTexture()));
        // update thw window
        window.display();
        windowMutex.unlock();
        lastFrameTime = frameClock.getElapsedTime().asMilliseconds();
        totalFrameTime += lastFrameTime;
        averageFrameTime = totalFrameTime / ++frameCount;
        if (frameCount % 100 == 0) {
            DBUG("Average frame time: %d ms", averageFrameTime);
        }
    }
    INFO("Stopped renderLoop");
}<|endoftext|>