<commit_before>/*
This file is part of KDE

  Copyright (C) 1998-2000 Waldo Bastian (bastian@kde.org)

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, 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <iostream>

#include <kapplication.h>
#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include <klocale.h>

#include <kcolordialog.h>
#include <kcolormimedata.h>
#include <QtGui/QClipboard>

static const char description[] =
	I18N_NOOP("KDE Color Chooser");

static const char version[] = "v1.0.1";

int main(int argc, char *argv[])
{
  KAboutData aboutData("kcolorchooser", 0, ki18n("KColorChooser"),
		version, ki18n(description), KAboutData::License_BSD,
		ki18n("(c) 2000, Waldo Bastian"));
  aboutData.addAuthor(ki18n("Waldo Bastian"),KLocalizedString(), "bastian@kde.org");
  KCmdLineArgs::init( argc, argv, &aboutData );

  KCmdLineOptions options;
  options.add("print", ki18n("Print the selected color to stdout"));
  options.add("color <color>", ki18n("Set initially selected color"));
  KCmdLineArgs::addCmdLineOptions( options );

  KApplication app;

  KColorDialog dlg;

  QColor color = KColorMimeData::fromMimeData( QApplication::clipboard()->mimeData( QClipboard::Clipboard ));
  if (!color.isValid()) {
    color = Qt::blue; // Just a color
  }
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
  if (args->isSet("color")) {
    QColor c = QColor(args->getOption("color"));
    if (c.isValid())
      color = c;
  }
  dlg.setColor(color);

  app.connect(&dlg, SIGNAL(finished()), SLOT(quit()));

  dlg.show();
  app.exec();

  const  QColor c = dlg.color();
  if ( args->isSet("print") && c.isValid() ) {
      std::cout << c.name().toUtf8().constData() << std::endl;
  }
  args->clear();
}
<commit_msg>Add Help button<commit_after>/*
This file is part of KDE

  Copyright (C) 1998-2000 Waldo Bastian (bastian@kde.org)

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, 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <iostream>

#include <kapplication.h>
#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include <klocale.h>

#include <kcolordialog.h>
#include <kcolormimedata.h>
#include <khelpmenu.h>

#include <QtGui/QClipboard>

static const char description[] =
	I18N_NOOP("KDE Color Chooser");

static const char version[] = "v1.0.1";

int main(int argc, char *argv[])
{
  KAboutData aboutData("kcolorchooser", 0, ki18n("KColorChooser"),
		version, ki18n(description), KAboutData::License_BSD,
		ki18n("(c) 2000, Waldo Bastian"));
  aboutData.addAuthor(ki18n("Waldo Bastian"),KLocalizedString(), "bastian@kde.org");
  aboutData.setProductName("kdelibs/kdeui");
  KCmdLineArgs::init( argc, argv, &aboutData );

  KCmdLineOptions options;
  options.add("print", ki18n("Print the selected color to stdout"));
  options.add("color <color>", ki18n("Set initially selected color"));
  KCmdLineArgs::addCmdLineOptions( options );

  KApplication app;

  KColorDialog dlg;

  KHelpMenu *help = new KHelpMenu(&dlg, &aboutData);

  QColor color = KColorMimeData::fromMimeData( QApplication::clipboard()->mimeData( QClipboard::Clipboard ));
  if (!color.isValid()) {
    color = Qt::blue; // Just a color
  }
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
  if (args->isSet("color")) {
    QColor c = QColor(args->getOption("color"));
    if (c.isValid())
      color = c;
  }
  dlg.setButtons(KDialog::Help | KDialog::Close);
  dlg.setButtonMenu(KDialog::Help, (QMenu *)(help->menu()));
  dlg.setColor(color);

  app.connect(&dlg, SIGNAL(finished()), SLOT(quit()));

  dlg.show();
  app.exec();

  const  QColor c = dlg.color();
  if ( args->isSet("print") && c.isValid() ) {
      std::cout << c.name().toUtf8().constData() << std::endl;
  }
  args->clear();
}
<|endoftext|>


<commit_before>#include "types.h"
#include "kernel.hh"
#include "spinlock.h"
#include "condvar.h"
#include "fs.h"
#include "stat.h"
#include "kalloc.hh"
#include "file.hh"
#include "bits.hh"
#include "amd64.h"
#include "cpu.hh"
#include "sampler.h"

#define LOGHEADER_SZ (sizeof(struct logheader) + \
                      sizeof(((struct logheader*)0)->cpu[0])*NCPU)

static volatile u64 selector;
static volatile u64 period;

struct pmu {
  void (*config)(u64 ctr, u64 sel, u64 val);
  u64 cntval_bits;
};
struct pmu pmu;

struct pmulog {
  u64 count;
  u64 capacity;
  struct pmuevent *event;
  __padout__;
} __mpalign__;

struct pmulog pmulog[NCPU] __mpalign__;

//
// AMD stuff
//
static void
amdconfig(u64 ctr, u64 sel, u64 val)
{
  writemsr(MSR_AMD_PERF_SEL0 | ctr, 0);
  writemsr(MSR_AMD_PERF_CNT0 | ctr, val);
  writemsr(MSR_AMD_PERF_SEL0 | ctr, sel);
}

struct pmu amdpmu = { amdconfig, 48 };

//
// Intel stuff
//
static void
intelconfig(u64 ctr, u64 sel, u64 val)
{
  writemsr(MSR_INTEL_PERF_SEL0 | ctr, 0);
  writemsr(MSR_INTEL_PERF_CNT0 | ctr, val);
  writemsr(MSR_INTEL_PERF_SEL0 | ctr, sel);
}

// XXX
struct pmu intelpmu = { intelconfig, 48 };

void
sampdump(void)
{
  for (int c = 0; c < NCPU; c++) {
    struct pmulog *l = &pmulog[c];
    cprintf("%u samples %lu\n", c, l->count);
    for (u64 i = 0; i < 4 && i < l->count; i++)
      cprintf(" %lx\n", l->event[i].rip);
  }
}

void
sampconf(void)
{
  pushcli();
  pmu.config(0, selector, -period);
  popcli();
}

void
sampstart(void)
{
  pushcli();
  for(struct cpu *c = cpus; c < cpus+ncpu; c++) {
    if(c == cpus+mycpu()->id)
      continue;
    lapic_sampconf(c->hwid);
  }
  sampconf();
  popcli();
}

static int
samplog(struct trapframe *tf)
{
  struct pmulog *l;
  struct pmuevent *e;
  l = &pmulog[mycpu()->id];

  if (l->count == l->capacity)
    return 0;

  e = &l->event[l->count];

  e->rip = tf->rip;
  getcallerpcs((void*)tf->rbp, e->trace, NELEM(e->trace));
  l->count++;
  return 1;
}

int
sampintr(struct trapframe *tf)
{
  // Acquire locks that we only acquire during NMI.
  // NMIs are disabled until the next iret.

  // Linux unmasks LAPIC.PC after every interrupt (perf_event.c)
  lapicpc(0);
  // Only level-triggered interrupts require an lapiceoi.

  u64 cnt = rdpmc(0);
  if (cnt & (1ULL << (pmu.cntval_bits - 1)))
    return 0;

  if (samplog(tf))
    pmu.config(0, selector, -period);

  return 1;
}

static int
readlog(char *dst, u32 off, u32 n)
{
  struct pmulog *q = &pmulog[NCPU];
  struct pmulog *p;
  int ret = 0;
  u64 cur = 0;

  for (p = &pmulog[0]; p != q && n != 0; p++) {
    u64 len = p->count * sizeof(struct pmuevent);
    char *buf = (char*)p->event;
    if (cur <= off && off < cur+len) {
      u64 boff = off-cur;
      u64 cc = MIN(len-boff, n);
      memmove(dst, buf+boff, cc);

      n -= cc;
      ret += cc;
      off += cc;
      dst += cc;
    }
    cur += len;
  }

  return ret;
}

static void
sampstat(struct inode *ip, struct stat *st)
{
  struct pmulog *q = &pmulog[NCPU];
  struct pmulog *p;
  u64 sz = 0;

  sz += LOGHEADER_SZ;
  for (p = &pmulog[0]; p != q; p++)
    sz += p->count * sizeof(struct pmuevent);

  st->dev = ip->dev;
  st->ino = ip->inum;
  st->type = ip->type;
  st->nlink = ip->nlink;
  st->size = sz;
}

static int
sampread(struct inode *ip, char *dst, u32 off, u32 n)
{
  struct pmulog *q = &pmulog[NCPU];
  struct pmulog *p;
  struct logheader *hdr;
  int ret;
  int i;

  ret = 0;
  if (off < LOGHEADER_SZ) {
    u64 len = LOGHEADER_SZ;
    u64 cc;

    hdr = (logheader*) kmalloc(len, "logheader");
    if (hdr == nullptr)
      return -1;
    hdr->ncpus = NCPU;
    i = 0;
    for (p = &pmulog[0]; p != q; p++) {
      u64 sz = p->count * sizeof(struct pmuevent);
      hdr->cpu[i].offset = len;
      hdr->cpu[i].size = sz;
      len += sz;
      i++;
    }

    cc = MIN(LOGHEADER_SZ-off, n);
    memmove(dst, (char*)hdr + off, cc);
    kmfree(hdr, LOGHEADER_SZ);

    n -= cc;
    ret += cc;
    off += cc;
    dst += cc;
  }

  if (off >= LOGHEADER_SZ)
    ret += readlog(dst, off-LOGHEADER_SZ, n);
  return ret;
}

static int
sampwrite(struct inode *ip, char *buf, u32 off, u32 n)
{
  struct sampconf *conf;

  if (n != sizeof(*conf))
    return -1;
  conf = (struct sampconf*)buf;

  switch(conf->op) {
  case SAMP_ENABLE:
    selector = conf->selector;
    period = conf->period;
    sampstart();
    break;
  case SAMP_DISABLE:
    selector = 0;
    period = 0;
    sampstart();
    break;
  }

  return n;
}

void
initsamp(void)
{
  if (myid() == mpbcpu()) {
    u32 name[4];
    char *s = (char *)name;
    name[3] = 0;

    cpuid(0, 0, &name[0], &name[2], &name[1]);
    if (VERBOSE)
      cprintf("%s\n", s);
    if (!strcmp(s, "AuthenticAMD"))
      pmu = amdpmu;
    else if (!strcmp(s, "GenuineIntel"))
      pmu = intelpmu;
    else
      panic("Unknown Manufacturer");
  }

  // enable RDPMC at CPL > 0
  u64 cr4 = rcr4();
  lcr4(cr4 | CR4_PCE);

  void *p = ksalloc(slab_perf);
  if (p == nullptr)
    panic("initprof: ksalloc");
  pmulog[myid()].event = (pmuevent*) p;
  pmulog[myid()].capacity = PERFSIZE / sizeof(struct pmuevent);

  devsw[SAMPLER].write = sampwrite;
  devsw[SAMPLER].read = sampread;
  devsw[SAMPLER].stat = sampstat;
}
<commit_msg>A hack to reset sampler counts<commit_after>#include "types.h"
#include "kernel.hh"
#include "spinlock.h"
#include "condvar.h"
#include "fs.h"
#include "stat.h"
#include "kalloc.hh"
#include "file.hh"
#include "bits.hh"
#include "amd64.h"
#include "cpu.hh"
#include "sampler.h"

#define LOGHEADER_SZ (sizeof(struct logheader) + \
                      sizeof(((struct logheader*)0)->cpu[0])*NCPU)

static volatile u64 selector;
static volatile u64 period;

struct pmu {
  void (*config)(u64 ctr, u64 sel, u64 val);
  u64 cntval_bits;
};
struct pmu pmu;

struct pmulog {
  u64 count;
  u64 capacity;
  struct pmuevent *event;
  __padout__;
} __mpalign__;

struct pmulog pmulog[NCPU] __mpalign__;

//
// AMD stuff
//
static void
amdconfig(u64 ctr, u64 sel, u64 val)
{
  writemsr(MSR_AMD_PERF_SEL0 | ctr, 0);
  writemsr(MSR_AMD_PERF_CNT0 | ctr, val);
  writemsr(MSR_AMD_PERF_SEL0 | ctr, sel);
}

struct pmu amdpmu = { amdconfig, 48 };

//
// Intel stuff
//
static void
intelconfig(u64 ctr, u64 sel, u64 val)
{
  writemsr(MSR_INTEL_PERF_SEL0 | ctr, 0);
  writemsr(MSR_INTEL_PERF_CNT0 | ctr, val);
  writemsr(MSR_INTEL_PERF_SEL0 | ctr, sel);
}

// XXX
struct pmu intelpmu = { intelconfig, 48 };

void
sampdump(void)
{
  for (int c = 0; c < NCPU; c++) {
    struct pmulog *l = &pmulog[c];
    cprintf("%u samples %lu\n", c, l->count);
    for (u64 i = 0; i < 4 && i < l->count; i++)
      cprintf(" %lx\n", l->event[i].rip);
  }
}

void
sampconf(void)
{
  pushcli();
  if (selector)
    pmulog[myid()].count = 0;
  pmu.config(0, selector, -period);
  popcli();
}

void
sampstart(void)
{
  pushcli();
  for(struct cpu *c = cpus; c < cpus+ncpu; c++) {
    if(c == cpus+mycpu()->id)
      continue;
    lapic_sampconf(c->hwid);
  }
  sampconf();
  popcli();
}

static int
samplog(struct trapframe *tf)
{
  struct pmulog *l;
  struct pmuevent *e;
  l = &pmulog[mycpu()->id];

  if (l->count == l->capacity)
    return 0;

  e = &l->event[l->count];

  e->rip = tf->rip;
  getcallerpcs((void*)tf->rbp, e->trace, NELEM(e->trace));
  l->count++;
  return 1;
}

int
sampintr(struct trapframe *tf)
{
  // Acquire locks that we only acquire during NMI.
  // NMIs are disabled until the next iret.

  // Linux unmasks LAPIC.PC after every interrupt (perf_event.c)
  lapicpc(0);
  // Only level-triggered interrupts require an lapiceoi.

  u64 cnt = rdpmc(0);
  if (cnt & (1ULL << (pmu.cntval_bits - 1)))
    return 0;

  if (samplog(tf))
    pmu.config(0, selector, -period);

  return 1;
}

static int
readlog(char *dst, u32 off, u32 n)
{
  struct pmulog *q = &pmulog[NCPU];
  struct pmulog *p;
  int ret = 0;
  u64 cur = 0;

  for (p = &pmulog[0]; p != q && n != 0; p++) {
    u64 len = p->count * sizeof(struct pmuevent);
    char *buf = (char*)p->event;
    if (cur <= off && off < cur+len) {
      u64 boff = off-cur;
      u64 cc = MIN(len-boff, n);
      memmove(dst, buf+boff, cc);

      n -= cc;
      ret += cc;
      off += cc;
      dst += cc;
    }
    cur += len;
  }

  return ret;
}

static void
sampstat(struct inode *ip, struct stat *st)
{
  struct pmulog *q = &pmulog[NCPU];
  struct pmulog *p;
  u64 sz = 0;

  sz += LOGHEADER_SZ;
  for (p = &pmulog[0]; p != q; p++)
    sz += p->count * sizeof(struct pmuevent);

  st->dev = ip->dev;
  st->ino = ip->inum;
  st->type = ip->type;
  st->nlink = ip->nlink;
  st->size = sz;
}

static int
sampread(struct inode *ip, char *dst, u32 off, u32 n)
{
  struct pmulog *q = &pmulog[NCPU];
  struct pmulog *p;
  struct logheader *hdr;
  int ret;
  int i;

  ret = 0;
  if (off < LOGHEADER_SZ) {
    u64 len = LOGHEADER_SZ;
    u64 cc;

    hdr = (logheader*) kmalloc(len, "logheader");
    if (hdr == nullptr)
      return -1;
    hdr->ncpus = NCPU;
    i = 0;
    for (p = &pmulog[0]; p != q; p++) {
      u64 sz = p->count * sizeof(struct pmuevent);
      hdr->cpu[i].offset = len;
      hdr->cpu[i].size = sz;
      len += sz;
      i++;
    }

    cc = MIN(LOGHEADER_SZ-off, n);
    memmove(dst, (char*)hdr + off, cc);
    kmfree(hdr, LOGHEADER_SZ);

    n -= cc;
    ret += cc;
    off += cc;
    dst += cc;
  }

  if (off >= LOGHEADER_SZ)
    ret += readlog(dst, off-LOGHEADER_SZ, n);
  return ret;
}

static int
sampwrite(struct inode *ip, char *buf, u32 off, u32 n)
{
  struct sampconf *conf;

  if (n != sizeof(*conf))
    return -1;
  conf = (struct sampconf*)buf;

  switch(conf->op) {
  case SAMP_ENABLE:
    selector = conf->selector;
    period = conf->period;
    sampstart();
    break;
  case SAMP_DISABLE:
    selector = 0;
    period = 0;
    sampstart();
    break;
  }

  return n;
}

void
initsamp(void)
{
  if (myid() == mpbcpu()) {
    u32 name[4];
    char *s = (char *)name;
    name[3] = 0;

    cpuid(0, 0, &name[0], &name[2], &name[1]);
    if (VERBOSE)
      cprintf("%s\n", s);
    if (!strcmp(s, "AuthenticAMD"))
      pmu = amdpmu;
    else if (!strcmp(s, "GenuineIntel"))
      pmu = intelpmu;
    else
      panic("Unknown Manufacturer");
  }

  // enable RDPMC at CPL > 0
  u64 cr4 = rcr4();
  lcr4(cr4 | CR4_PCE);

  void *p = ksalloc(slab_perf);
  if (p == nullptr)
    panic("initprof: ksalloc");
  pmulog[myid()].event = (pmuevent*) p;
  pmulog[myid()].capacity = PERFSIZE / sizeof(struct pmuevent);

  devsw[SAMPLER].write = sampwrite;
  devsw[SAMPLER].read = sampread;
  devsw[SAMPLER].stat = sampstat;
}
<|endoftext|>


<commit_before>#include "mugen_background.h"

#include <math.h>
#include <ostream>
#include <cstring>
#include <string>
#include <algorithm>
#include "globals.h"
#include "mugen_sprite.h"
#include "util/bitmap.h"

//static double pi = 3.14159265;

using namespace std;

static double interpolate(double f1, double f2, double p){
    return (f1 * (1.0 - p)) + (f2 * p);
}

static int calculateTile( int length, int width ){
    int loc = 0;
    for( int i = 1; ; ++i ){
	if( loc > length )return i;
	loc+=width;
    }
}

static void doParallax(Bitmap &bmp, Bitmap &work, int leftx, int lefty, int xoffset, double top, double bot, int yscalestart, double yscaledelta, double yoffset, bool mask){
    const int height = bmp.getHeight();
    const int w = bmp.getWidth();
    int movex = 0;
    //double z = 1.0 / z1;
    //const double z_add = ((1.0 / z2) - z) / (y2 - y1);

    Global::debug(3) << "background leftx " << leftx << endl;

    for (int localy = 0; localy < height; ++localy ){
	//int width = bmp.getWidth()*z;
        const double range = (double)localy / (double)height;
	const double scale = interpolate(top, bot, range) - top;
	//const double newHeight = height*((yscalestart+(yoffset*yscaledelta))/100);
	//const double yscale = (newHeight/height);
	movex = (int)(leftx + (leftx - xoffset) * scale);
	bmp.Stretch(work, 0, localy, w, 1,movex, lefty+localy, w,1);
	//z +=  z_add;
	//Global::debug(1) << "Height: " << height << " | yscalestart: " << yscalestart << " | yscaledelta: " << yscaledelta << " | yoffset: " << yoffset << " | New Height: " << newHeight << " | yscale: " << yscale << endl;
    }
}

// mugen background
MugenBackground::MugenBackground( const unsigned long int &ticker ):
type(Normal),
groupNumber(-1),
imageNumber(-1),
actionno(-1),
id(0),
layerno(0),
startx(0),
starty(0),
deltax(1),
deltay(1),
trans(None),
alphalow(0),
alphahigh(0),
mask(true),
tilex(0),
tiley(0),
tilespacingx(0),
tilespacingy(0),
windowdeltax(0),
windowdeltay(0),
xscaletop(0),
xscalebot(0),
yscalestart(100),
yscaledelta(100),
positionlink(false),
velocityx(0),
velocityy(0),
sinx_amp(0),
sinx_period(0),
sinx_offset(0),
sinx_angle(0),
siny_amp(0),
siny_period(0),
siny_offset(0),
siny_angle(0),
xoffset(0),
yoffset(0),
movex(0),
movey(0),
velx(0),
vely(0),
stageTicker( ticker ),
x(0),
y(0),
visible(true),
enabled(true),
controller_offsetx(0),
controller_offsety(0),
sprite(0),
spriteBmp(0),
action(0),
linked(0),
runLink(false){
}
MugenBackground::MugenBackground( const MugenBackground &copy ):
stageTicker( copy.stageTicker ){
}
MugenBackground::~MugenBackground(){
    // Kill the bmp
    if( spriteBmp )delete spriteBmp;
}
MugenBackground & MugenBackground::operator=( const MugenBackground &copy ){

    return *this;
}

void MugenBackground::logic( const double x, const double y, const double placementx, const double placementy ){
    if (enabled){
	movex = movey = 0;
	movex += x * deltax;
	movey += y * deltay;
	velx += velocityx;
	vely += velocityy;
	/* how much should sin_angle be incremented by each frame?
	* I think the total angle should be (ticks % sin_period) * 2pi / sin_period
	* M (decimal) is the magnitude in pixels (amp)
	* P (decimal) is the period in game ticks (period)
	* O (decimal) is the time offset in game ticks (offset)
	* From updates.txt:  M * sine ((ticks+O)/P * 2 * Pi)
	* sinx_amp * sin((stageTicker+sinx_offset)/sinx_period * 2 * pi)) ? useless it seems
	*/
	//sin_angle += 0.00005;
	sinx_angle += 0.00005;
	siny_angle += 0.00005;

	if( type == Anim ) action->logic();

	this->x = (int)(placementx + xoffset + movex + velx + controller_offsetx + sinx_amp * sin(sinx_angle*sinx_period + sinx_offset));
	this->y = (int)(placementy + yoffset + movey + vely + controller_offsety + siny_amp * sin(siny_angle*siny_period + siny_offset));
    }
}

void MugenBackground::render( const int totalLength, const int totalHeight, Bitmap *work ){
    if (visible){
	switch( type ){
	    case Normal:{
		// Normal is a sprite
		// see if we need to tile this beyatch
		int tilexloc = x;
		const int width = spriteBmp->getWidth();
		const int height = spriteBmp->getHeight();
		bool dirx = false, diry = false;
		// Figure out total we need to tile (this crap doesn't work needs fix)
		const int repeath = (tilex > 0 ? (tilex > 1 ? tilex : ( calculateTile( totalLength, width ) ) ) : 1 );
		const int repeatv = ( tiley > 0 ? (tiley > 1 ? tiley : ( calculateTile( totalLength, height ) ) ) : 1 );
		const int addw = width + tilespacingx;
		const int addh = height + tilespacingy;
		// We need to repeat and wrap
		for( int h = 0; h < repeath; h++ ){
		    int tileyloc = y;
		    for( int v = 0; v < repeatv; v++ ){
			draw( tilexloc, tileyloc, *work );
			if( !diry )tileyloc += addh;
			else tileyloc -= addh;
			if( tileyloc >= work->getHeight() ){
			    diry = true;
			    tileyloc = y - addh;
			}
		    }
		    if( !dirx )tilexloc += addw;
		    else tilexloc -= addw;
		    if( tilexloc >= work->getWidth() ){
			dirx = true;
			tilexloc = x - addw;
		    }
		}
		break;
	    }
	    case Parallax:{
		// This is also a sprite but we must parallax it across the top and bottom to give the illusion of depth
		doParallax( *spriteBmp, *work, x, y, xoffset, xscaletop, xscalebot, yscalestart, yscaledelta, (movey-deltay), mask);
		break;
	    }
	    case Anim:{
		// there is no sprite use our action!
		//action->render( x, y, *work );
		// Need to tile as well
		int tilexloc = x;
		const int width = action->getCurrentFrame()->bmp->getWidth();
		const int height = action->getCurrentFrame()->bmp->getHeight();
		bool dirx = false, diry = false;
		// Figure out total we need to tile
		const int repeath = (tilex > 0 ? (tilex > 1 ? tilex : ( calculateTile( totalLength, width ) ) ) : 1 );
		const int repeatv = ( tiley > 0 ? (tiley > 1 ? tiley : ( calculateTile( totalLength, height ) ) ) : 1 );
		const int addw = tilespacingx;
		const int addh = tilespacingy;
		// We need to repeat and wrap
		for( int h = 0; h < repeath; h++ ){
		    int tileyloc = y;
		    for( int v = 0; v < repeatv; v++ ){
			action->render( tilexloc, tileyloc, *work );
			if( !diry )tileyloc += addh;
			else tileyloc -= addh;
			if( tileyloc >= work->getHeight() ){
			    diry = true;
			    tileyloc = y - addh;
			}
		    }
		    if( !dirx )tilexloc += addw;
		    else tilexloc -= addw;
		    if( tilexloc >= work->getWidth() ){
			dirx = true;
			tilexloc = x - addw;
		    }
		}
		break;
	    }
	    case Dummy:
		// Do nothing
	    default:
		break;
	}
    }
}

void MugenBackground::preload( const int xaxis, const int yaxis ){
    // Do positionlink crap
    if (positionlink && !runLink){
	if (linked){
	    linked->setPositionLink(this);
	}
	runLink = true;
    }

    if(sprite){
	// Lets load our sprite
	spriteBmp = new Bitmap(Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength));
	// Set our initial offsets
	xoffset = 160 + (xaxis - sprite->x) + startx;
	yoffset = (yaxis - sprite->y) + starty;
	velx = vely = 0;
    }
    else{
	// Set our initial offsets
	xoffset = 160 + (xaxis) + startx;
	yoffset = (yaxis) + starty;
	velx = vely = 0;
    }
}

void MugenBackground::draw( const int ourx, const int oury, Bitmap &work ){
    // This needs to be a switch trans = None, Add, Add1, Sub1, Addalpha
    switch( trans ){
	case Addalpha:{
	    // Need to figure out blend correctly addalpha is given to two locations low and high ?
	    Bitmap::transBlender( 255, 255, 255, alphalow );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case Add:{
	    // this additive 100% I assume... not totally sure
	    Bitmap::addBlender( 255, 255, 255, 255 );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case Add1:{
	    // 50%
	    Bitmap::addBlender( 128, 128, 128, 255 );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case Sub:{
	    // Shadow effect
	    Bitmap::differenceBlender( 128, 128, 128, 255 );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case None:
	default:{
	    if( mask )spriteBmp->draw( ourx,oury, work );
	    else spriteBmp->Blit( ourx, oury, work );
	    break;
	}
    }
}

    // Lets do our positionlink stuff
void MugenBackground::setPositionLink(MugenBackground *bg){
    if (positionlink){
	if (linked){
	    linked->setPositionLink(bg);
	    return;
	}
    }
    bg->startx += startx;
    bg->starty += starty;
    bg->deltax = deltax;
    bg->deltay = deltay;
    bg->sinx_amp = sinx_amp;
    bg->sinx_offset = sinx_offset;
    bg->sinx_period = sinx_period;
    bg->siny_amp = siny_amp;
    bg->siny_offset = siny_offset;
    bg->siny_period = siny_period;
    bg->velocityx = velocityx;
    bg->velocityy = velocityy;

    //Global::debug(1) << "Positionlinked bg: " << bg->name << " set to x: " << bg->startx << " y: " << bg->starty << endl;
}

<commit_msg>Corrected parallax offset<commit_after>#include "mugen_background.h"

#include <math.h>
#include <ostream>
#include <cstring>
#include <string>
#include <algorithm>
#include "globals.h"
#include "mugen_sprite.h"
#include "util/bitmap.h"

//static double pi = 3.14159265;

using namespace std;

static double interpolate(double f1, double f2, double p){
    return (f1 * (1.0 - p)) + (f2 * p);
}

static int calculateTile( int length, int width ){
    int loc = 0;
    for( int i = 1; ; ++i ){
	if( loc > length )return i;
	loc+=width;
    }
}

static void doParallax(Bitmap &bmp, Bitmap &work, int leftx, int lefty, int xoffset, double top, double bot, int yscalestart, double yscaledelta, double yoffset, bool mask){
    const int height = bmp.getHeight();
    const int w = bmp.getWidth();
    int movex = 0;
    //double z = 1.0 / z1;
    //const double z_add = ((1.0 / z2) - z) / (y2 - y1);

    Global::debug(3) << "background leftx " << leftx << endl;

    for (int localy = 0; localy < height; ++localy ){
	//int width = bmp.getWidth()*z;
        const double range = (double)localy / (double)height;
	const double scale = interpolate(top, bot, range) - top;
	//const double newHeight = height*((yscalestart+(yoffset*yscaledelta))/100);
	//const double yscale = (newHeight/height);
	movex = (int)(leftx + (leftx - xoffset) * scale);
	bmp.Stretch(work, 0, localy, w, 1,movex, lefty+localy, w,1);
	//z +=  z_add;
	//Global::debug(1) << "Height: " << height << " | yscalestart: " << yscalestart << " | yscaledelta: " << yscaledelta << " | yoffset: " << yoffset << " | New Height: " << newHeight << " | yscale: " << yscale << endl;
    }
}

// mugen background
MugenBackground::MugenBackground( const unsigned long int &ticker ):
type(Normal),
groupNumber(-1),
imageNumber(-1),
actionno(-1),
id(0),
layerno(0),
startx(0),
starty(0),
deltax(1),
deltay(1),
trans(None),
alphalow(0),
alphahigh(0),
mask(true),
tilex(0),
tiley(0),
tilespacingx(0),
tilespacingy(0),
windowdeltax(0),
windowdeltay(0),
xscaletop(0),
xscalebot(0),
yscalestart(100),
yscaledelta(100),
positionlink(false),
velocityx(0),
velocityy(0),
sinx_amp(0),
sinx_period(0),
sinx_offset(0),
sinx_angle(0),
siny_amp(0),
siny_period(0),
siny_offset(0),
siny_angle(0),
xoffset(0),
yoffset(0),
movex(0),
movey(0),
velx(0),
vely(0),
stageTicker( ticker ),
x(0),
y(0),
visible(true),
enabled(true),
controller_offsetx(0),
controller_offsety(0),
sprite(0),
spriteBmp(0),
action(0),
linked(0),
runLink(false){
}
MugenBackground::MugenBackground( const MugenBackground &copy ):
stageTicker( copy.stageTicker ){
}
MugenBackground::~MugenBackground(){
    // Kill the bmp
    if( spriteBmp )delete spriteBmp;
}
MugenBackground & MugenBackground::operator=( const MugenBackground &copy ){

    return *this;
}

void MugenBackground::logic( const double x, const double y, const double placementx, const double placementy ){
    if (enabled){
	movex = movey = 0;
	movex += x * deltax;
	movey += y * deltay;
	velx += velocityx;
	vely += velocityy;
	/* how much should sin_angle be incremented by each frame?
	* I think the total angle should be (ticks % sin_period) * 2pi / sin_period
	* M (decimal) is the magnitude in pixels (amp)
	* P (decimal) is the period in game ticks (period)
	* O (decimal) is the time offset in game ticks (offset)
	* From updates.txt:  M * sine ((ticks+O)/P * 2 * Pi)
	* sinx_amp * sin((stageTicker+sinx_offset)/sinx_period * 2 * pi)) ? useless it seems
	*/
	//sin_angle += 0.00005;
	sinx_angle += 0.00005;
	siny_angle += 0.00005;

	if( type == Anim ) action->logic();

	this->x = (int)(placementx + xoffset + movex + velx + controller_offsetx + sinx_amp * sin(sinx_angle*sinx_period + sinx_offset));
	this->y = (int)(placementy + yoffset + movey + vely + controller_offsety + siny_amp * sin(siny_angle*siny_period + siny_offset));
    }
}

void MugenBackground::render( const int totalLength, const int totalHeight, Bitmap *work ){
    if (visible){
	switch( type ){
	    case Normal:{
		// Normal is a sprite
		// see if we need to tile this beyatch
		int tilexloc = x;
		const int width = spriteBmp->getWidth();
		const int height = spriteBmp->getHeight();
		bool dirx = false, diry = false;
		// Figure out total we need to tile (this crap doesn't work needs fix)
		const int repeath = (tilex > 0 ? (tilex > 1 ? tilex : ( calculateTile( totalLength, width ) ) ) : 1 );
		const int repeatv = ( tiley > 0 ? (tiley > 1 ? tiley : ( calculateTile( totalLength, height ) ) ) : 1 );
		const int addw = width + tilespacingx;
		const int addh = height + tilespacingy;
		// We need to repeat and wrap
		for( int h = 0; h < repeath; h++ ){
		    int tileyloc = y;
		    for( int v = 0; v < repeatv; v++ ){
			draw( tilexloc, tileyloc, *work );
			if( !diry )tileyloc += addh;
			else tileyloc -= addh;
			if( tileyloc >= work->getHeight() ){
			    diry = true;
			    tileyloc = y - addh;
			}
		    }
		    if( !dirx )tilexloc += addw;
		    else tilexloc -= addw;
		    if( tilexloc >= work->getWidth() ){
			dirx = true;
			tilexloc = x - addw;
		    }
		}
		break;
	    }
	    case Parallax:{
		// This is also a sprite but we must parallax it across the top and bottom to give the illusion of depth
		doParallax( *spriteBmp, *work, x, y, xoffset/2, xscaletop, xscalebot, yscalestart, yscaledelta, (movey-deltay), mask);
		break;
	    }
	    case Anim:{
		// there is no sprite use our action!
		//action->render( x, y, *work );
		// Need to tile as well
		int tilexloc = x;
		const int width = action->getCurrentFrame()->bmp->getWidth();
		const int height = action->getCurrentFrame()->bmp->getHeight();
		bool dirx = false, diry = false;
		// Figure out total we need to tile
		const int repeath = (tilex > 0 ? (tilex > 1 ? tilex : ( calculateTile( totalLength, width ) ) ) : 1 );
		const int repeatv = ( tiley > 0 ? (tiley > 1 ? tiley : ( calculateTile( totalLength, height ) ) ) : 1 );
		const int addw = tilespacingx;
		const int addh = tilespacingy;
		// We need to repeat and wrap
		for( int h = 0; h < repeath; h++ ){
		    int tileyloc = y;
		    for( int v = 0; v < repeatv; v++ ){
			action->render( tilexloc, tileyloc, *work );
			if( !diry )tileyloc += addh;
			else tileyloc -= addh;
			if( tileyloc >= work->getHeight() ){
			    diry = true;
			    tileyloc = y - addh;
			}
		    }
		    if( !dirx )tilexloc += addw;
		    else tilexloc -= addw;
		    if( tilexloc >= work->getWidth() ){
			dirx = true;
			tilexloc = x - addw;
		    }
		}
		break;
	    }
	    case Dummy:
		// Do nothing
	    default:
		break;
	}
    }
}

void MugenBackground::preload( const int xaxis, const int yaxis ){
    // Do positionlink crap
    if (positionlink && !runLink){
	if (linked){
	    linked->setPositionLink(this);
	}
	runLink = true;
    }

    if(sprite){
	// Lets load our sprite
	spriteBmp = new Bitmap(Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength));
	// Set our initial offsets
	xoffset = 160 + (xaxis - sprite->x) + startx;
	yoffset = (yaxis - sprite->y) + starty;
	velx = vely = 0;
    }
    else{
	// Set our initial offsets
	xoffset = 160 + (xaxis) + startx;
	yoffset = (yaxis) + starty;
	velx = vely = 0;
    }
}

void MugenBackground::draw( const int ourx, const int oury, Bitmap &work ){
    // This needs to be a switch trans = None, Add, Add1, Sub1, Addalpha
    switch( trans ){
	case Addalpha:{
	    // Need to figure out blend correctly addalpha is given to two locations low and high ?
	    Bitmap::transBlender( 255, 255, 255, alphalow );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case Add:{
	    // this additive 100% I assume... not totally sure
	    Bitmap::addBlender( 255, 255, 255, 255 );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case Add1:{
	    // 50%
	    Bitmap::addBlender( 128, 128, 128, 255 );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case Sub:{
	    // Shadow effect
	    Bitmap::differenceBlender( 128, 128, 128, 255 );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case None:
	default:{
	    if( mask )spriteBmp->draw( ourx,oury, work );
	    else spriteBmp->Blit( ourx, oury, work );
	    break;
	}
    }
}

    // Lets do our positionlink stuff
void MugenBackground::setPositionLink(MugenBackground *bg){
    if (positionlink){
	if (linked){
	    linked->setPositionLink(bg);
	    return;
	}
    }
    bg->startx += startx;
    bg->starty += starty;
    bg->deltax = deltax;
    bg->deltay = deltay;
    bg->sinx_amp = sinx_amp;
    bg->sinx_offset = sinx_offset;
    bg->sinx_period = sinx_period;
    bg->siny_amp = siny_amp;
    bg->siny_offset = siny_offset;
    bg->siny_period = siny_period;
    bg->velocityx = velocityx;
    bg->velocityy = velocityy;

    //Global::debug(1) << "Positionlinked bg: " << bg->name << " set to x: " << bg->startx << " y: " << bg->starty << endl;
}

<|endoftext|>


<commit_before>/*
 * Part of Appstream, a library for accessing AppStream on-disk database
 * Copyright 2014  Sune Vuorela <sune@vuorela.dk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "component.h"
#include "screenshot.h"
#include <QSharedData>
#include <QStringList>
#include <QUrl>
#include <QMultiHash>

using namespace Appstream;

class Appstream::ComponentData : public QSharedData {
    public:
        QStringList m_categories;
        QStringList m_compulsoryForDesktops;
        QString m_description;
        QString m_developerName;
        QStringList m_extends;
        QStringList m_extensions;
        QString m_icon;
        QString m_id;
        Component::Kind m_kind;
        QString m_name;
        QStringList m_packageNames;
        QString m_projectGroup;
        QString m_projectLicense;
        QString m_summary;
        QHash<QString, QUrl> m_iconUrls;
        QMultiHash<Component::UrlKind, QUrl> m_urls;
        QList<Appstream::Screenshot> m_screenshots;
        QMultiHash<Provides::Kind, Provides> m_provides;
        QHash<Component::BundleKind, QString> m_bundles;
        bool operator==(const ComponentData& other) const {
            if(m_categories != other.m_categories) {
                return false;
            }
            if(m_compulsoryForDesktops != other.m_compulsoryForDesktops) {
                return false;
            }
            if(m_description != other.m_description) {
                return false;
            }
            if(m_developerName != other.m_developerName) {
                return false;
            }
            if(m_extends != other.m_extends) {
                return false;
            }
            if(m_icon != other.m_icon) {
                return false;
            }
            if(m_iconUrls != other.m_iconUrls) {
                return false;
            }
            if(m_id != other.m_id) {
                return false;
            }
            if(m_kind != other.m_kind) {
                return false;
            }
            if(m_name != other.m_name) {
                return false;
            }
            if(m_packageNames != other.m_packageNames) {
                return false;
            }
            if(m_projectGroup != other.m_projectGroup) {
                return false;
            }
            if(m_projectLicense != other.m_projectLicense) {
                return false;
            }
            if(m_summary != other.m_summary) {
                return false;
            }
            if(m_urls != other.m_urls) {
                return false;
            }
            if(m_screenshots != other.m_screenshots) {
                return false;
            }
            if(m_provides != other.m_provides) {
                return false;
            }
            if(m_bundles != other.m_bundles) {
                return false;
            }

            // we don't check for m_extensions, since this is auto-generated and not a specific property of a component.

            return true;
        }
};

QStringList Component::categories() const {
    return d->m_categories;
}

QStringList Component::compulsoryForDesktops() const {
    return d->m_compulsoryForDesktops;
}

QString Component::description() const {
    return d->m_description;
}

QString Component::developerName() const {
    return d->m_developerName;
}

bool Component::hasCategory(const QString& category) const {
    return d->m_categories.contains(category);
}

QString Component::icon() const {
    return d->m_icon;
}

QUrl Component::iconUrl(const QSize& size) const {
    QString sizeStr;
    // if no size was specified, we assume 64x64
    if (size.isValid())
        sizeStr = QStringLiteral("%1x%2").arg(size.width()).arg(size.height());
    else
        sizeStr = QStringLiteral("64x64");
    return d->m_iconUrls.value(sizeStr);
}

QString Component::id() const {
    return d->m_id;
}

bool Component::isCompulsoryForDesktop(const QString& desktop) const {
    return d->m_compulsoryForDesktops.contains(desktop);
}

Component::Kind Component::kind() const {
    return d->m_kind;
}

QString Component::name() const {
    return d->m_name;
}

QStringList Component::packageNames() const {
    return d->m_packageNames;
}

QString Component::projectGroup() const {
    return d->m_projectGroup;
}

QString Component::projectLicense() const {
    return d->m_projectLicense;
}

void Component::setCategories(const QStringList& categories) {
    d->m_categories = categories;
}

void Component::setCompulsoryForDesktops(const QStringList& desktops) {
    d->m_compulsoryForDesktops = desktops;
}

void Component::setDescription(const QString& description) {
    d->m_description = description;
}

void Component::setDeveloperName(const QString& developerName) {
    d->m_developerName = developerName;
}

void Component::setIcon(const QString& icon) {
    d->m_icon = icon;
}

void Component::addIconUrl(const QUrl& iconUrl, const QSize& size) {
    QString sizeStr;
    // if no size was specified, we assume 64x64
    if (size.isValid())
        sizeStr = QStringLiteral("%1x%2").arg(size.width()).arg(size.height());
    else
        sizeStr = QStringLiteral("64x64");
    d->m_iconUrls.insert(sizeStr, iconUrl);
}

void Component::setId(const QString& id) {
    d->m_id = id;
}

void Component::setKind(Component::Kind kind) {
    d->m_kind = kind;
}

void Component::setName(const QString& name) {
    d->m_name = name;
}

void Component::setPackageNames(const QStringList& packageNames) {
    d->m_packageNames = packageNames;
}

void Component::setProjectGroup(const QString& group) {
    d->m_projectGroup = group;
}

void Component::setProjectLicense(const QString& license){
    d->m_projectLicense = license;
}

void Component::setSummary(const QString& summary){
    d->m_summary = summary;
}

QString Component::summary() const {
    return d->m_summary;
}

QStringList Component::extends() const {
    return d->m_extends;
}

void Component::setExtends(const QStringList& extends) {
    d->m_extends = extends;
}

QStringList Component::extensions() const {
    return d->m_extensions;
}

void Component::setExtensions(const QStringList& extensions) {
    d->m_extensions = extensions;
}

Component::Component(const Component& other) : d(other.d) {

}

Component::Component() : d(new ComponentData) {

}

Component& Component::operator=(const Component& other) {
    this->d = other.d;
    return *this;
}

void Component::setUrls(const QMultiHash< Component::UrlKind, QUrl >& urls) {
    d->m_urls = urls;
}
QList< QUrl > Component::urls(Component::UrlKind kind) const {
    return d->m_urls.values(kind);
}

QMultiHash< Component::UrlKind, QUrl > Component::urls() const {
    return d->m_urls;
}

void Component::setBundles(const QHash< Component::BundleKind, QString >& bundles) {
    d->m_bundles = bundles;
}
QString Component::bundle(Component::BundleKind kind) const {
    return d->m_bundles.value(kind);
}

QHash< Component::BundleKind, QString > Component::bundles() const {
    return d->m_bundles;
}

bool Component::operator==(const Component& other) {
    if(this->d == other.d) {
        return true;
    }
    if(this->d && other.d) {
        return *(this->d) == *other.d;
    }
    return false;
}

Component::~Component() = default;

typedef QHash<Component::Kind, QString> KindMap;
Q_GLOBAL_STATIC_WITH_ARGS(KindMap, kindMap, ( {
    { Component::KindAddon, QLatin1String("addon") },
    { Component::KindCodec, QLatin1String("codec") },
    { Component::KindDesktop, QLatin1String("desktop") },
    { Component::KindFont, QLatin1String("font") },
    { Component::KindGeneric, QLatin1String("generic") },
    { Component::KindInputmethod, QLatin1String("inputmethod") },
    { Component::KindAddon, QLatin1String("firmware") },
    { Component::KindUnknown, QLatin1String("unknown") }
    }
));

QString Component::kindToString(Component::Kind kind) {
    return kindMap->value(kind);
}

Component::Kind Component::stringToKind(const QString& kindString) {
    if(kindString ==  QLatin1String("generic")) {
        return KindGeneric;
    }
    if (kindString == QLatin1String("desktop")) {
        return KindDesktop;
    }
    if (kindString == QLatin1String("font")) {
        return KindFont;
    }
    if (kindString == QLatin1String("codec")) {
        return KindCodec;
    }
    if (kindString==QLatin1String("inputmethod")) {
        return KindInputmethod;
    }
    if (kindString == QLatin1String("addon")) {
        return KindAddon;
    }
    if (kindString == QLatin1String("firmware")) {
        return KindFirmware;
    }
    return KindUnknown;

}

void Component::setScreenshots(const QList< Screenshot >& screenshots) {
    d->m_screenshots = screenshots;
}

QList< Screenshot > Component::screenshots() const {
    return d->m_screenshots;
}

Component::UrlKind Component::stringToUrlKind(const QString& urlKindString) {
    if (urlKindString == QLatin1String("homepage")) {
        return UrlKindHomepage;
    }
    if (urlKindString == QLatin1String("bugtracker")) {
        return UrlKindBugtracker;
    }
    if (urlKindString == QLatin1String("faq")) {
        return UrlKindFaq;
    }
    if (urlKindString == QLatin1String("help")) {
        return UrlKindHelp;
    }
    if (urlKindString == QLatin1String("donation")) {
        return UrlKindDonation;
    }
    return UrlKindUnknown;
}

typedef QHash<Component::UrlKind, QString> UrlKindMap;
Q_GLOBAL_STATIC_WITH_ARGS(UrlKindMap, urlKindMap, ({
        { Component::UrlKindBugtracker, QLatin1String("bugtracker") },
        { Component::UrlKindDonation, QLatin1String("donation") },
        { Component::UrlKindFaq, QLatin1String("faq") },
        { Component::UrlKindHelp, QLatin1String("help") },
        { Component::UrlKindHomepage, QLatin1String("homepage") },
        { Component::UrlKindUnknown, QLatin1String("unknown") },
    }));

QString Component::urlKindToString(Component::UrlKind kind) {
    return urlKindMap->value(kind);
}

QString Component::bundleKindToString(Component::BundleKind kind) {
    switch (kind) {
        case Component::BundleKindLimba:
            return QStringLiteral("limba");
        case Component::BundleKindXdgApp:
            return QStringLiteral("xdg-app");
        default:
            return QString();
    }
}

Component::BundleKind Component::stringToBundleKind(const QString& bundleKindString) {
    if (bundleKindString == QLatin1String("limba")) {
        return BundleKindLimba;
    }
    if (bundleKindString == QLatin1String("xdg-app")) {
        return BundleKindXdgApp;
    }
    return BundleKindUnknown;
}

QList< Appstream::Provides > Component::provides() const {
    return d->m_provides.values();
}

QList<Appstream::Provides> Component::provides(Provides::Kind kind) const {
    return d->m_provides.values(kind);
}

void Component::setProvides(const QList<Appstream::Provides>& provides) {
    Q_FOREACH(const Appstream::Provides& provide, provides) {
        d->m_provides.insertMulti(provide.kind(), provide);
    }
}

bool Component::isValid() const
{
    return !d->m_name.isEmpty();
}

<commit_msg>qt: Properly check for component validity<commit_after>/*
 * Part of Appstream, a library for accessing AppStream on-disk database
 * Copyright 2014  Sune Vuorela <sune@vuorela.dk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "component.h"
#include "screenshot.h"
#include <QSharedData>
#include <QStringList>
#include <QUrl>
#include <QMultiHash>

using namespace Appstream;

class Appstream::ComponentData : public QSharedData {
    public:
        QStringList m_categories;
        QStringList m_compulsoryForDesktops;
        QString m_description;
        QString m_developerName;
        QStringList m_extends;
        QStringList m_extensions;
        QString m_icon;
        QString m_id;
        Component::Kind m_kind;
        QString m_name;
        QStringList m_packageNames;
        QString m_projectGroup;
        QString m_projectLicense;
        QString m_summary;
        QHash<QString, QUrl> m_iconUrls;
        QMultiHash<Component::UrlKind, QUrl> m_urls;
        QList<Appstream::Screenshot> m_screenshots;
        QMultiHash<Provides::Kind, Provides> m_provides;
        QHash<Component::BundleKind, QString> m_bundles;
        bool operator==(const ComponentData& other) const {
            if(m_categories != other.m_categories) {
                return false;
            }
            if(m_compulsoryForDesktops != other.m_compulsoryForDesktops) {
                return false;
            }
            if(m_description != other.m_description) {
                return false;
            }
            if(m_developerName != other.m_developerName) {
                return false;
            }
            if(m_extends != other.m_extends) {
                return false;
            }
            if(m_icon != other.m_icon) {
                return false;
            }
            if(m_iconUrls != other.m_iconUrls) {
                return false;
            }
            if(m_id != other.m_id) {
                return false;
            }
            if(m_kind != other.m_kind) {
                return false;
            }
            if(m_name != other.m_name) {
                return false;
            }
            if(m_packageNames != other.m_packageNames) {
                return false;
            }
            if(m_projectGroup != other.m_projectGroup) {
                return false;
            }
            if(m_projectLicense != other.m_projectLicense) {
                return false;
            }
            if(m_summary != other.m_summary) {
                return false;
            }
            if(m_urls != other.m_urls) {
                return false;
            }
            if(m_screenshots != other.m_screenshots) {
                return false;
            }
            if(m_provides != other.m_provides) {
                return false;
            }
            if(m_bundles != other.m_bundles) {
                return false;
            }

            // we don't check for m_extensions, since this is auto-generated and not a specific property of a component.

            return true;
        }
};

QStringList Component::categories() const {
    return d->m_categories;
}

QStringList Component::compulsoryForDesktops() const {
    return d->m_compulsoryForDesktops;
}

QString Component::description() const {
    return d->m_description;
}

QString Component::developerName() const {
    return d->m_developerName;
}

bool Component::hasCategory(const QString& category) const {
    return d->m_categories.contains(category);
}

QString Component::icon() const {
    return d->m_icon;
}

QUrl Component::iconUrl(const QSize& size) const {
    QString sizeStr;
    // if no size was specified, we assume 64x64
    if (size.isValid())
        sizeStr = QStringLiteral("%1x%2").arg(size.width()).arg(size.height());
    else
        sizeStr = QStringLiteral("64x64");
    return d->m_iconUrls.value(sizeStr);
}

QString Component::id() const {
    return d->m_id;
}

bool Component::isCompulsoryForDesktop(const QString& desktop) const {
    return d->m_compulsoryForDesktops.contains(desktop);
}

Component::Kind Component::kind() const {
    return d->m_kind;
}

QString Component::name() const {
    return d->m_name;
}

QStringList Component::packageNames() const {
    return d->m_packageNames;
}

QString Component::projectGroup() const {
    return d->m_projectGroup;
}

QString Component::projectLicense() const {
    return d->m_projectLicense;
}

void Component::setCategories(const QStringList& categories) {
    d->m_categories = categories;
}

void Component::setCompulsoryForDesktops(const QStringList& desktops) {
    d->m_compulsoryForDesktops = desktops;
}

void Component::setDescription(const QString& description) {
    d->m_description = description;
}

void Component::setDeveloperName(const QString& developerName) {
    d->m_developerName = developerName;
}

void Component::setIcon(const QString& icon) {
    d->m_icon = icon;
}

void Component::addIconUrl(const QUrl& iconUrl, const QSize& size) {
    QString sizeStr;
    // if no size was specified, we assume 64x64
    if (size.isValid())
        sizeStr = QStringLiteral("%1x%2").arg(size.width()).arg(size.height());
    else
        sizeStr = QStringLiteral("64x64");
    d->m_iconUrls.insert(sizeStr, iconUrl);
}

void Component::setId(const QString& id) {
    d->m_id = id;
}

void Component::setKind(Component::Kind kind) {
    d->m_kind = kind;
}

void Component::setName(const QString& name) {
    d->m_name = name;
}

void Component::setPackageNames(const QStringList& packageNames) {
    d->m_packageNames = packageNames;
}

void Component::setProjectGroup(const QString& group) {
    d->m_projectGroup = group;
}

void Component::setProjectLicense(const QString& license){
    d->m_projectLicense = license;
}

void Component::setSummary(const QString& summary){
    d->m_summary = summary;
}

QString Component::summary() const {
    return d->m_summary;
}

QStringList Component::extends() const {
    return d->m_extends;
}

void Component::setExtends(const QStringList& extends) {
    d->m_extends = extends;
}

QStringList Component::extensions() const {
    return d->m_extensions;
}

void Component::setExtensions(const QStringList& extensions) {
    d->m_extensions = extensions;
}

Component::Component(const Component& other) : d(other.d) {

}

Component::Component() : d(new ComponentData) {

}

Component& Component::operator=(const Component& other) {
    this->d = other.d;
    return *this;
}

void Component::setUrls(const QMultiHash< Component::UrlKind, QUrl >& urls) {
    d->m_urls = urls;
}
QList< QUrl > Component::urls(Component::UrlKind kind) const {
    return d->m_urls.values(kind);
}

QMultiHash< Component::UrlKind, QUrl > Component::urls() const {
    return d->m_urls;
}

void Component::setBundles(const QHash< Component::BundleKind, QString >& bundles) {
    d->m_bundles = bundles;
}
QString Component::bundle(Component::BundleKind kind) const {
    return d->m_bundles.value(kind);
}

QHash< Component::BundleKind, QString > Component::bundles() const {
    return d->m_bundles;
}

bool Component::operator==(const Component& other) {
    if(this->d == other.d) {
        return true;
    }
    if(this->d && other.d) {
        return *(this->d) == *other.d;
    }
    return false;
}

Component::~Component() = default;

typedef QHash<Component::Kind, QString> KindMap;
Q_GLOBAL_STATIC_WITH_ARGS(KindMap, kindMap, ( {
    { Component::KindAddon, QLatin1String("addon") },
    { Component::KindCodec, QLatin1String("codec") },
    { Component::KindDesktop, QLatin1String("desktop") },
    { Component::KindFont, QLatin1String("font") },
    { Component::KindGeneric, QLatin1String("generic") },
    { Component::KindInputmethod, QLatin1String("inputmethod") },
    { Component::KindAddon, QLatin1String("firmware") },
    { Component::KindUnknown, QLatin1String("unknown") }
    }
));

QString Component::kindToString(Component::Kind kind) {
    return kindMap->value(kind);
}

Component::Kind Component::stringToKind(const QString& kindString) {
    if(kindString ==  QLatin1String("generic")) {
        return KindGeneric;
    }
    if (kindString == QLatin1String("desktop")) {
        return KindDesktop;
    }
    if (kindString == QLatin1String("font")) {
        return KindFont;
    }
    if (kindString == QLatin1String("codec")) {
        return KindCodec;
    }
    if (kindString==QLatin1String("inputmethod")) {
        return KindInputmethod;
    }
    if (kindString == QLatin1String("addon")) {
        return KindAddon;
    }
    if (kindString == QLatin1String("firmware")) {
        return KindFirmware;
    }
    return KindUnknown;

}

void Component::setScreenshots(const QList< Screenshot >& screenshots) {
    d->m_screenshots = screenshots;
}

QList< Screenshot > Component::screenshots() const {
    return d->m_screenshots;
}

Component::UrlKind Component::stringToUrlKind(const QString& urlKindString) {
    if (urlKindString == QLatin1String("homepage")) {
        return UrlKindHomepage;
    }
    if (urlKindString == QLatin1String("bugtracker")) {
        return UrlKindBugtracker;
    }
    if (urlKindString == QLatin1String("faq")) {
        return UrlKindFaq;
    }
    if (urlKindString == QLatin1String("help")) {
        return UrlKindHelp;
    }
    if (urlKindString == QLatin1String("donation")) {
        return UrlKindDonation;
    }
    return UrlKindUnknown;
}

typedef QHash<Component::UrlKind, QString> UrlKindMap;
Q_GLOBAL_STATIC_WITH_ARGS(UrlKindMap, urlKindMap, ({
        { Component::UrlKindBugtracker, QLatin1String("bugtracker") },
        { Component::UrlKindDonation, QLatin1String("donation") },
        { Component::UrlKindFaq, QLatin1String("faq") },
        { Component::UrlKindHelp, QLatin1String("help") },
        { Component::UrlKindHomepage, QLatin1String("homepage") },
        { Component::UrlKindUnknown, QLatin1String("unknown") },
    }));

QString Component::urlKindToString(Component::UrlKind kind) {
    return urlKindMap->value(kind);
}

QString Component::bundleKindToString(Component::BundleKind kind) {
    switch (kind) {
        case Component::BundleKindLimba:
            return QStringLiteral("limba");
        case Component::BundleKindXdgApp:
            return QStringLiteral("xdg-app");
        default:
            return QString();
    }
}

Component::BundleKind Component::stringToBundleKind(const QString& bundleKindString) {
    if (bundleKindString == QLatin1String("limba")) {
        return BundleKindLimba;
    }
    if (bundleKindString == QLatin1String("xdg-app")) {
        return BundleKindXdgApp;
    }
    return BundleKindUnknown;
}

QList< Appstream::Provides > Component::provides() const {
    return d->m_provides.values();
}

QList<Appstream::Provides> Component::provides(Provides::Kind kind) const {
    return d->m_provides.values(kind);
}

void Component::setProvides(const QList<Appstream::Provides>& provides) {
    Q_FOREACH(const Appstream::Provides& provide, provides) {
        d->m_provides.insertMulti(provide.kind(), provide);
    }
}

bool Component::isValid() const
{
    return !d->m_id.isEmpty() &&
           !d->m_name.isEmpty() &&
           !d->m_summary.isEmpty();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008, 2009 Nokia Corporation.
 *
 * Contact: Marius Vollmer <marius.vollmer@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <QtTest/QtTest>
#include <QtCore>
#include "contextpropertyinfo.h"
#include "infobackend.h"

QMap <QString, QString> constructionStringMap;
QMap <QString, QString> typeMap;
QMap <QString, QString> docMap;
QMap <QString, QString> pluginMap;
QMap <QString, bool> providedMap;

/* Mocked infobackend */

InfoBackend* currentBackend = NULL;

InfoBackend* InfoBackend::instance(const QString &backendName)
{
    if (currentBackend)
        return currentBackend;
    else {
        currentBackend = new InfoBackend();
        return currentBackend;
    }
}

QString InfoBackend::constructionStringForKey(QString key) const
{
    if (constructionStringMap.contains(key))
        return constructionStringMap.value(key);
    else
        return QString();
}

QString InfoBackend::typeForKey(QString key) const
{
     if (typeMap.contains(key))
        return typeMap.value(key);
    else
        return QString();
}

QString InfoBackend::docForKey(QString key) const
{
    if (docMap.contains(key))
        return docMap.value(key);
    else
        return QString();
}

QString InfoBackend::pluginForKey(QString key) const
{
    if (pluginMap.contains(key))
        return pluginMap.value(key);
    else
        return QString();
}

bool InfoBackend::keyExists(QString key) const
{
    if (typeMap.contains(key))
        return true;
    else
        return false;
}

bool InfoBackend::keyProvided(QString key) const
{
    if (providedMap.contains(key))
        return providedMap.value(key);
    else
        return false;
}

void InfoBackend::connectNotify(const char *signal)
{
}

void InfoBackend::disconnectNotify(const char *signal)
{
}

void InfoBackend::fireKeysChanged(const QStringList& keys)
{
    emit keysChanged(keys);
}

void InfoBackend::fireKeysAdded(const QStringList& keys)
{
    emit keysAdded(keys);
}

void InfoBackend::fireKeysRemoved(const QStringList& keys)
{
    emit keysRemoved(keys);
}

void InfoBackend::fireKeyDataChanged(const QString& key)
{
    emit keyDataChanged(key);
}

/* ContextRegistryInfoUnitTest */

class ContextPropertyInfoUnitTest : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void key();
    void doc();
    void type();
    void exists();
    void provided();
    void providerDBusName();
    void providerDBusType();
    void plugin();
    void constructionString();
    void typeChanged();
    void providerChanged();
    void providedChanged();
    void pluginChanged();
};

void ContextPropertyInfoUnitTest::initTestCase()
{
    constructionStringMap.clear();
    constructionStringMap.insert("Battery.Charging", "system:org.freedesktop.ContextKit.contextd");
    constructionStringMap.insert("Media.NowPlaying", "session:com.nokia.musicplayer");

    typeMap.clear();
    typeMap.insert("Battery.Charging", "TRUTH");
    typeMap.insert("Media.NowPlaying", "STRING");

    docMap.clear();
    docMap.insert("Battery.Charging", "Battery.Charging doc");
    docMap.insert("Media.NowPlaying", "Media.NowPlaying doc");

    pluginMap.clear();
    pluginMap.insert("Battery.Charging", "contextkit-dbus");
    pluginMap.insert("Media.NowPlaying", "contextkit-dbus");

    providedMap.clear();
    providedMap.insert("Battery.Charging", true);
    providedMap.insert("Media.NowPlaying", true);
}

void ContextPropertyInfoUnitTest::key()
{
    ContextPropertyInfo p("Battery.Charging");
    QCOMPARE(p.key(), QString("Battery.Charging"));
}

void ContextPropertyInfoUnitTest::doc()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.doc(), QString("Battery.Charging doc"));
    QCOMPARE(p2.doc(), QString("Media.NowPlaying doc"));
    QCOMPARE(p3.doc(), QString());
}

void ContextPropertyInfoUnitTest::type()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.type(), QString("TRUTH"));
    QCOMPARE(p2.type(), QString("STRING"));
    QCOMPARE(p3.type(), QString());
}

void ContextPropertyInfoUnitTest::exists()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.exists(), true);
    QCOMPARE(p2.exists(), true);
    QCOMPARE(p3.exists(), false);
}

void ContextPropertyInfoUnitTest::provided()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.provided(), true);
    QCOMPARE(p2.provided(), true);
    QCOMPARE(p3.provided(), false);
}

void ContextPropertyInfoUnitTest::providerDBusName()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.providerDBusName(), QString("org.freedesktop.ContextKit.contextd"));
    QCOMPARE(p2.providerDBusName(), QString("com.nokia.musicplayer"));
    QCOMPARE(p3.providerDBusName(), QString());
}

void ContextPropertyInfoUnitTest::providerDBusType()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.providerDBusType(), QDBusConnection::SystemBus);
    QCOMPARE(p2.providerDBusType(), QDBusConnection::SessionBus);
    QCOMPARE(p3.providerDBusType(), QDBusConnection::SessionBus);
}

void ContextPropertyInfoUnitTest::plugin()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.plugin(), QString("contextkit-dbus"));
    QCOMPARE(p2.plugin(), QString("contextkit-dbus"));
    QCOMPARE(p3.plugin(), QString());
}

void ContextPropertyInfoUnitTest::constructionString()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.constructionString(), QString("system:org.freedesktop.ContextKit.contextd"));
    QCOMPARE(p2.constructionString(), QString("session:com.nokia.musicplayer"));
    QCOMPARE(p3.constructionString(), QString());
}

void ContextPropertyInfoUnitTest::typeChanged()
{
    ContextPropertyInfo p("Battery.Charging");
    QSignalSpy spy(&p, SIGNAL(typeChanged(QString)));

    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 0);

    typeMap.insert("Battery.Charging", "INT");
    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 1);
    QList<QVariant> args = spy.takeFirst();
    QCOMPARE(args.at(0).toString(), QString("INT"));
}

void ContextPropertyInfoUnitTest::providerChanged()
{
    ContextPropertyInfo p("Battery.Charging");
    QSignalSpy spy(&p, SIGNAL(providerChanged(QString)));

    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 0);

    constructionStringMap.insert("Battery.Charging", "system:org.freedesktop.ContextKit.robot");
    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 1);
    QList<QVariant> args = spy.takeFirst();
    QCOMPARE(args.at(0).toString(), QString("org.freedesktop.ContextKit.robot"));
}

void ContextPropertyInfoUnitTest::providedChanged()
{
    ContextPropertyInfo p("Battery.Charging");
    QSignalSpy spy(&p, SIGNAL(providedChanged(bool)));

    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 0);

    providedMap.insert("Battery.Charging", false);
    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 1);
    QList<QVariant> args = spy.takeFirst();
}

void ContextPropertyInfoUnitTest::pluginChanged()
{
    ContextPropertyInfo p("Battery.Charging");
    QSignalSpy spy1(&p, SIGNAL(pluginChanged(QString, QString)));
    QSignalSpy spy2(&p, SIGNAL(providerChanged(QString)));

    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy1.count(), 0);
    QCOMPARE(spy2.count(), 0);

    pluginMap.insert("Battery.Charging", "test.so");
    constructionStringMap.insert("Battery.Charging", "secret:something");
    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy1.count(), 1);
    QList<QVariant> args1 = spy1.takeFirst();
    QCOMPARE(args1.at(0).toString(), QString("test.so"));
    QCOMPARE(args1.at(1).toString(), QString("secret:something"));

    QCOMPARE(spy2.count(), 1);
    QList<QVariant> args2 = spy2.takeFirst();
    QCOMPARE(args2.at(0).toString(), QString(""));
}

#include "contextpropertyinfounittest.moc"
QTEST_MAIN(ContextPropertyInfoUnitTest);
<commit_msg>DBus type changed.<commit_after>/*
 * Copyright (C) 2008, 2009 Nokia Corporation.
 *
 * Contact: Marius Vollmer <marius.vollmer@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <QtTest/QtTest>
#include <QtCore>
#include "contextpropertyinfo.h"
#include "infobackend.h"

QMap <QString, QString> constructionStringMap;
QMap <QString, QString> typeMap;
QMap <QString, QString> docMap;
QMap <QString, QString> pluginMap;
QMap <QString, bool> providedMap;

/* Mocked infobackend */

InfoBackend* currentBackend = NULL;

InfoBackend* InfoBackend::instance(const QString &backendName)
{
    if (currentBackend)
        return currentBackend;
    else {
        currentBackend = new InfoBackend();
        return currentBackend;
    }
}

QString InfoBackend::constructionStringForKey(QString key) const
{
    if (constructionStringMap.contains(key))
        return constructionStringMap.value(key);
    else
        return QString();
}

QString InfoBackend::typeForKey(QString key) const
{
     if (typeMap.contains(key))
        return typeMap.value(key);
    else
        return QString();
}

QString InfoBackend::docForKey(QString key) const
{
    if (docMap.contains(key))
        return docMap.value(key);
    else
        return QString();
}

QString InfoBackend::pluginForKey(QString key) const
{
    if (pluginMap.contains(key))
        return pluginMap.value(key);
    else
        return QString();
}

bool InfoBackend::keyExists(QString key) const
{
    if (typeMap.contains(key))
        return true;
    else
        return false;
}

bool InfoBackend::keyProvided(QString key) const
{
    if (providedMap.contains(key))
        return providedMap.value(key);
    else
        return false;
}

void InfoBackend::connectNotify(const char *signal)
{
}

void InfoBackend::disconnectNotify(const char *signal)
{
}

void InfoBackend::fireKeysChanged(const QStringList& keys)
{
    emit keysChanged(keys);
}

void InfoBackend::fireKeysAdded(const QStringList& keys)
{
    emit keysAdded(keys);
}

void InfoBackend::fireKeysRemoved(const QStringList& keys)
{
    emit keysRemoved(keys);
}

void InfoBackend::fireKeyDataChanged(const QString& key)
{
    emit keyDataChanged(key);
}

/* ContextRegistryInfoUnitTest */

class ContextPropertyInfoUnitTest : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void key();
    void doc();
    void type();
    void exists();
    void provided();
    void providerDBusName();
    void providerDBusType();
    void plugin();
    void constructionString();
    void typeChanged();
    void providerChanged();
    void providedChanged();
    void pluginChanged();
    void dbusTypeChanged();
};

void ContextPropertyInfoUnitTest::initTestCase()
{
    constructionStringMap.clear();
    constructionStringMap.insert("Battery.Charging", "system:org.freedesktop.ContextKit.contextd");
    constructionStringMap.insert("Media.NowPlaying", "session:com.nokia.musicplayer");

    typeMap.clear();
    typeMap.insert("Battery.Charging", "TRUTH");
    typeMap.insert("Media.NowPlaying", "STRING");

    docMap.clear();
    docMap.insert("Battery.Charging", "Battery.Charging doc");
    docMap.insert("Media.NowPlaying", "Media.NowPlaying doc");

    pluginMap.clear();
    pluginMap.insert("Battery.Charging", "contextkit-dbus");
    pluginMap.insert("Media.NowPlaying", "contextkit-dbus");

    providedMap.clear();
    providedMap.insert("Battery.Charging", true);
    providedMap.insert("Media.NowPlaying", true);
}

void ContextPropertyInfoUnitTest::key()
{
    ContextPropertyInfo p("Battery.Charging");
    QCOMPARE(p.key(), QString("Battery.Charging"));
}

void ContextPropertyInfoUnitTest::doc()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.doc(), QString("Battery.Charging doc"));
    QCOMPARE(p2.doc(), QString("Media.NowPlaying doc"));
    QCOMPARE(p3.doc(), QString());
}

void ContextPropertyInfoUnitTest::type()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.type(), QString("TRUTH"));
    QCOMPARE(p2.type(), QString("STRING"));
    QCOMPARE(p3.type(), QString());
}

void ContextPropertyInfoUnitTest::exists()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.exists(), true);
    QCOMPARE(p2.exists(), true);
    QCOMPARE(p3.exists(), false);
}

void ContextPropertyInfoUnitTest::provided()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.provided(), true);
    QCOMPARE(p2.provided(), true);
    QCOMPARE(p3.provided(), false);
}

void ContextPropertyInfoUnitTest::providerDBusName()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.providerDBusName(), QString("org.freedesktop.ContextKit.contextd"));
    QCOMPARE(p2.providerDBusName(), QString("com.nokia.musicplayer"));
    QCOMPARE(p3.providerDBusName(), QString());
}

void ContextPropertyInfoUnitTest::providerDBusType()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.providerDBusType(), QDBusConnection::SystemBus);
    QCOMPARE(p2.providerDBusType(), QDBusConnection::SessionBus);
    QCOMPARE(p3.providerDBusType(), QDBusConnection::SessionBus);
}

void ContextPropertyInfoUnitTest::plugin()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.plugin(), QString("contextkit-dbus"));
    QCOMPARE(p2.plugin(), QString("contextkit-dbus"));
    QCOMPARE(p3.plugin(), QString());
}

void ContextPropertyInfoUnitTest::constructionString()
{
    ContextPropertyInfo p1("Battery.Charging");
    ContextPropertyInfo p2("Media.NowPlaying");
    ContextPropertyInfo p3("Does.Not.Exist");
    QCOMPARE(p1.constructionString(), QString("system:org.freedesktop.ContextKit.contextd"));
    QCOMPARE(p2.constructionString(), QString("session:com.nokia.musicplayer"));
    QCOMPARE(p3.constructionString(), QString());
}

void ContextPropertyInfoUnitTest::typeChanged()
{
    ContextPropertyInfo p("Battery.Charging");
    QSignalSpy spy(&p, SIGNAL(typeChanged(QString)));

    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 0);

    typeMap.insert("Battery.Charging", "INT");
    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 1);
    QList<QVariant> args = spy.takeFirst();
    QCOMPARE(args.at(0).toString(), QString("INT"));
}

void ContextPropertyInfoUnitTest::providerChanged()
{
    ContextPropertyInfo p("Battery.Charging");
    QSignalSpy spy(&p, SIGNAL(providerChanged(QString)));

    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 0);

    constructionStringMap.insert("Battery.Charging", "system:org.freedesktop.ContextKit.robot");
    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 1);
    QList<QVariant> args = spy.takeFirst();
    QCOMPARE(args.at(0).toString(), QString("org.freedesktop.ContextKit.robot"));
}

void ContextPropertyInfoUnitTest::providedChanged()
{
    ContextPropertyInfo p("Battery.Charging");
    QSignalSpy spy(&p, SIGNAL(providedChanged(bool)));

    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 0);

    providedMap.insert("Battery.Charging", false);
    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 1);
    QList<QVariant> args = spy.takeFirst();
}

void ContextPropertyInfoUnitTest::pluginChanged()
{
    ContextPropertyInfo p("Battery.Charging");
    QSignalSpy spy1(&p, SIGNAL(pluginChanged(QString, QString)));
    QSignalSpy spy2(&p, SIGNAL(providerChanged(QString)));

    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy1.count(), 0);
    QCOMPARE(spy2.count(), 0);

    pluginMap.insert("Battery.Charging", "test.so");
    constructionStringMap.insert("Battery.Charging", "secret:something");
    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy1.count(), 1);
    QList<QVariant> args1 = spy1.takeFirst();
    QCOMPARE(args1.at(0).toString(), QString("test.so"));
    QCOMPARE(args1.at(1).toString(), QString("secret:something"));

    QCOMPARE(spy2.count(), 1);
    QList<QVariant> args2 = spy2.takeFirst();
    QCOMPARE(args2.at(0).toString(), QString(""));
}

void ContextPropertyInfoUnitTest::dbusTypeChanged()
{
    ContextPropertyInfo p("Battery.Charging");
    QSignalSpy spy(&p, SIGNAL(providerDBusTypeChanged(QDBusConnection::BusType)));

    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    QCOMPARE(spy.count(), 0);

    constructionStringMap.insert("Battery.Charging", "session:org.freedesktop.ContextKit.contextd");
    currentBackend->fireKeyDataChanged(QString("Battery.Charging"));

    // WE DON'T EMIT THE DBUS TYPE CHANGED ANYMORE!
    QCOMPARE(spy.count(), 0);
}

#include "contextpropertyinfounittest.moc"
QTEST_MAIN(ContextPropertyInfoUnitTest);
<|endoftext|>


<commit_before>#include "InjectOpenGLIntrinsics.h"
#include "IRMutator.h"
#include "IROperator.h"
#include "CodeGen_GPU_Dev.h"
#include "Substitute.h"

namespace Halide {
namespace Internal {

using std::string;
using std::vector;

class InjectOpenGLIntrinsics : public IRMutator {
public:
    InjectOpenGLIntrinsics()
        : inside_kernel_loop(false) {
    }
    Scope<int> scope;
    bool inside_kernel_loop;
private:
    using IRMutator::visit;

    void visit(const Provide *provide) {
        if (!inside_kernel_loop) {
            IRMutator::visit(provide);
            return;
        }

        internal_assert(provide->values.size() == 1) << "GLSL currently only supports single-valued stores.\n";
        user_assert(provide->args.size() == 3) << "GLSL stores requires three coordinates.\n";

        // Create glsl_texture_store(name, name.buffer, x, y, c, value)
        // intrinsic.
        vector<Expr> args(6);
        args[0] = provide->name;
        args[1] = Variable::make(Handle(), provide->name + ".buffer");
        for (size_t i = 0; i < provide->args.size(); i++) {
            args[i + 2] = provide->args[i];
        }
        args[5] = mutate(provide->values[0]);
        stmt = Evaluate::make(
            Call::make(args[5].type(), Call::glsl_texture_store, args, Call::Intrinsic));
    }

    void visit(const Call *call) {
        if (!inside_kernel_loop || call->call_type == Call::Intrinsic) {
            IRMutator::visit(call);
            return;
        }

        string name = call->name;
        if (call->call_type == Call::Halide && call->func.outputs() > 1) {
            name = name + '.' + int_to_string(call->value_index);
        }

        user_assert(call->args.size() == 3) << "GLSL loads requires three coordinates.\n";

        // Create glsl_texture_load(name, name.buffer, x, y, c) intrinsic.
        vector<Expr> args(5);
        args[0] = call->name;
        args[1] = Variable::make(Handle(), call->name + ".buffer");
        for (size_t i = 0; i < call->args.size(); i++) {
            string d = int_to_string(i);
            string min_name = name + ".min." + d;
            string min_name_constrained = min_name + ".constrained";
            if (scope.contains(min_name_constrained)) {
                min_name = min_name_constrained;
            }
            string extent_name = name + ".extent." + d;
            string extent_name_constrained = extent_name + ".constrained";
            if (scope.contains(extent_name_constrained)) {
                extent_name = extent_name_constrained;
            }

            Expr min = Variable::make(Int(32), min_name);
            Expr extent = Variable::make(Int(32), extent_name);

            // Normalize the two spatial coordinates x,y
            args[i + 2] = (i < 2)
                ? (Cast::make(Float(32), call->args[i] - min) + 0.5f) / extent
                : call->args[i] - min;
        }

        expr = Call::make(call->type, Call::glsl_texture_load,
                          args, Call::Intrinsic,
                          Function(), 0, call->image, call->param);
    }

    void visit(const LetStmt *let) {
        // Discover constrained versions of things.
        bool constrained_version_exists = ends_with(let->name, ".constrained");
        if (constrained_version_exists) {
            scope.push(let->name, 0);
        }

        IRMutator::visit(let);

        if (constrained_version_exists) {
            scope.pop(let->name);
        }
    }

    void visit(const For *loop) {
        bool old_kernel_loop = inside_kernel_loop;
        if (loop->for_type == For::Parallel &&
            CodeGen_GPU_Dev::is_gpu_block_var(loop->name)) {
            inside_kernel_loop = true;
        }
        IRMutator::visit(loop);
        inside_kernel_loop = old_kernel_loop;
    }
};

// Rewrite all GPU loops to have a min of zero
class ZeroGPULoopMins : public IRMutator {
    using IRMutator::visit;

    void visit(const For *op) {
        IRMutator::visit(op);
        if (CodeGen_GPU_Dev::is_gpu_var(op->name) && !is_zero(op->min)) {
            op = stmt.as<For>();
            internal_assert(op);
            Expr adjusted = Variable::make(Int(32), op->name) + op->min;
            Stmt body = substitute(op->name, adjusted, op->body);
            stmt = For::make(op->name, 0, op->extent, op->for_type, body);
        }
    }
};

Stmt inject_opengl_intrinsics(Stmt s) {
    ZeroGPULoopMins z;
    s = z.mutate(s);
    InjectOpenGLIntrinsics gl;
    return gl.mutate(s);
}

}
}
<commit_msg>Don't convert Extern calls to GLSL intrinsics<commit_after>#include "InjectOpenGLIntrinsics.h"
#include "IRMutator.h"
#include "IROperator.h"
#include "CodeGen_GPU_Dev.h"
#include "Substitute.h"

namespace Halide {
namespace Internal {

using std::string;
using std::vector;

class InjectOpenGLIntrinsics : public IRMutator {
public:
    InjectOpenGLIntrinsics()
        : inside_kernel_loop(false) {
    }
    Scope<int> scope;
    bool inside_kernel_loop;
private:
    using IRMutator::visit;

    void visit(const Provide *provide) {
        if (!inside_kernel_loop) {
            IRMutator::visit(provide);
            return;
        }

        internal_assert(provide->values.size() == 1) << "GLSL currently only supports single-valued stores.\n";
        user_assert(provide->args.size() == 3) << "GLSL stores requires three coordinates.\n";

        // Create glsl_texture_store(name, name.buffer, x, y, c, value)
        // intrinsic.
        vector<Expr> args(6);
        args[0] = provide->name;
        args[1] = Variable::make(Handle(), provide->name + ".buffer");
        for (size_t i = 0; i < provide->args.size(); i++) {
            args[i + 2] = provide->args[i];
        }
        args[5] = mutate(provide->values[0]);
        stmt = Evaluate::make(
            Call::make(args[5].type(), Call::glsl_texture_store, args, Call::Intrinsic));
    }

    void visit(const Call *call) {
        if (!inside_kernel_loop ||
            call->call_type == Call::Intrinsic || call->call_type == Call::Extern) {
            IRMutator::visit(call);
            return;
        }

        string name = call->name;
        if (call->call_type == Call::Halide && call->func.outputs() > 1) {
            name = name + '.' + int_to_string(call->value_index);
        }

        user_assert(call->args.size() == 3) << "GLSL loads requires three coordinates.\n";

        // Create glsl_texture_load(name, name.buffer, x, y, c) intrinsic.
        vector<Expr> args(5);
        args[0] = call->name;
        args[1] = Variable::make(Handle(), call->name + ".buffer");
        for (size_t i = 0; i < call->args.size(); i++) {
            string d = int_to_string(i);
            string min_name = name + ".min." + d;
            string min_name_constrained = min_name + ".constrained";
            if (scope.contains(min_name_constrained)) {
                min_name = min_name_constrained;
            }
            string extent_name = name + ".extent." + d;
            string extent_name_constrained = extent_name + ".constrained";
            if (scope.contains(extent_name_constrained)) {
                extent_name = extent_name_constrained;
            }

            Expr min = Variable::make(Int(32), min_name);
            Expr extent = Variable::make(Int(32), extent_name);

            // Normalize the two spatial coordinates x,y
            args[i + 2] = (i < 2)
                ? (Cast::make(Float(32), call->args[i] - min) + 0.5f) / extent
                : call->args[i] - min;
        }

        expr = Call::make(call->type, Call::glsl_texture_load,
                          args, Call::Intrinsic,
                          Function(), 0, call->image, call->param);
    }

    void visit(const LetStmt *let) {
        // Discover constrained versions of things.
        bool constrained_version_exists = ends_with(let->name, ".constrained");
        if (constrained_version_exists) {
            scope.push(let->name, 0);
        }

        IRMutator::visit(let);

        if (constrained_version_exists) {
            scope.pop(let->name);
        }
    }

    void visit(const For *loop) {
        bool old_kernel_loop = inside_kernel_loop;
        if (loop->for_type == For::Parallel &&
            CodeGen_GPU_Dev::is_gpu_block_var(loop->name)) {
            inside_kernel_loop = true;
        }
        IRMutator::visit(loop);
        inside_kernel_loop = old_kernel_loop;
    }
};

// Rewrite all GPU loops to have a min of zero
class ZeroGPULoopMins : public IRMutator {
    using IRMutator::visit;

    void visit(const For *op) {
        IRMutator::visit(op);
        if (CodeGen_GPU_Dev::is_gpu_var(op->name) && !is_zero(op->min)) {
            op = stmt.as<For>();
            internal_assert(op);
            Expr adjusted = Variable::make(Int(32), op->name) + op->min;
            Stmt body = substitute(op->name, adjusted, op->body);
            stmt = For::make(op->name, 0, op->extent, op->for_type, body);
        }
    }
};

Stmt inject_opengl_intrinsics(Stmt s) {
    ZeroGPULoopMins z;
    s = z.mutate(s);
    InjectOpenGLIntrinsics gl;
    return gl.mutate(s);
}

}
}
<|endoftext|>