#!/usr/bin/perl -w
use Qt 2.0;
$seed = 0.353535353535;
$KINDA_RAND_MAX = 32767;
sub kindaRand {
$seed *= 147;
$seed -= int($seed);
return int($seed * ($KINDA_RAND_MAX + 1));
}
sub velocity {
my $i = shift;
my $velmax = 10;
my $velmin = 4;
if($i == 1 || $i == 2) {
$i = (kindaRand()&0x7fff % $velmax)/3 + $velmin;
} else {
$i = (kindaRand()&0x7fff % $velmax) + $velmin;
}
return $i;
}
#
# Draw polygon on desktop.
#
sub poly {
my $d = Qt::Application::desktop();
$d->setBackgroundColor(Qt::white);
my $maxpoints = 5;
my $maxcurves = 8;
my @xvel;
my @yvel;
my $head = 0;
my $tail = -$maxcurves + 2;
my @a;
my $p;
my $r = $d->rect();
for(0..$maxcurves-1) {
$a[$_] = Qt::PointArray->new;
$a[$_]->resize($maxpoints);
}
$p = $a[0];
for(0..$maxpoints-1) {
$p->setPoint($_, (kindaRand()&0x7fff) % $r->width(),
(kindaRand()&0x7fff) % $r->height());
$xvel[$_] = velocity($_);
$yvel[$_] = velocity($_);
}
my $paint = Qt::Painter->new;
$paint->begin($d);
for(my $ntimes = 0; $ntimes < 2000; $ntimes++) {
$paint->setBrush(Qt::Color->new(kindaRand()%360, 180, 255, Qt::Color::Hsv));
$paint->drawPolygon($a[$head]);
$tail = 0 if ++$tail >= $maxcurves;
my($minx, $maxx) = ($r->left(), $r->right());
my($miny, $maxy) = ($r->top(), $r->bottom());
my($x, $y);
$p = $a[$head];
$head = 0 if ++$head >= $maxcurves;
for(0..$maxpoints-1) {
$p->point($_, $x, $y);
$x += $xvel[$_];
$y += $yvel[$_];
if($x > $maxx) {
$x = $maxx - ($x - $maxx + 1);
$xvel[$_] = -velocity($_);
}
if($x <= $minx) {
$x = $minx + ($minx - $x + 1);
$xvel[$_] = velocity($_);
}
if($y >= $maxy) {
$y = $maxy - ($y - $maxy + 1);
$yvel[$_] = -velocity($_);
}
if($y <= $miny) {
$y = $miny + ($miny - $y + 1);
$yvel[$_] = velocity($_);
}
$a[$head]->setPoint($_, $x, $y);
}
}
$paint->end();
}
#
# Rotate pattern on desktop.
#
sub rotate {
my $i;
my $w = 64;
my $h = 64;
my $image = Qt::Image->new($w, $h, 8, 128);
for($i = 0; $i < 128; $i++) {
$image->setColor($i, Qt::Color::rgb($i,0,0));
}
for(my $y = 0; $y < $h; $y++) {
my $p = $image->scanLine($y);
for(my $x = 0; $x < $w; $x++) {
$$p[$x] = ($x+$y)%128;
}
}
my $pm = Qt::Pixmap->new($image);
$pm->optimize(1);
my $d = Qt::Application::desktop();
for($i = 0; $i <= 360; $i += 2) {
my $m = Qt::WMatrix->new;
$m->rotate($i);
my $rpm = $pm->xForm($m);
$d->setBackgroundPixmap($rpm);
$d->update();
}
}
#
# Generates a marble-like pattern in pm.
#
sub generateStone {
my $pm = shift;
my($c1, $c2, $c3) = @_;
my $p = Qt::Painter->new;
my $p1 = Qt::Pen->new($c1);
my $p2 = Qt::Pen->new($c2);
my $p3 = Qt::Pen->new($c3);
$p->begin($pm);
my $width = $pm->width();
my $height = $pm->height();
my $r;
my($i, $j);
my $krmD3 = $KINDA_RAND_MAX / 3;
my $krmD3T2 = $KINDA_RAND_MAX / 3 * 2;
for($i = 0; $i < $width; $i++) {
for($j = 0; $j < $height; $j++) {
$r = kindaRand();
if($r < $krmD3) {
$p->setPen($p1);
} elsif($r < $krmD3T2) {
$p->setPen($p2);
} else {
$p->setPen($p3);
}
$p->drawPoint($i, $j);
}
}
$p->end();
}
sub drawShadeText {
my $p = shift;
my $x = shift;
my $y = shift;
my $text = shift;
my $topColor = shift;
my $bottomColor = shift;
my $sw = @_ ? shift : 2;
return unless $p->isActive();
$p->setPen($bottomColor);
$p->drawText($x+$sw, $y+$sw, $text);
$p->setPen($topColor);
$p->drawText($x, $y, $text);
}
package DesktopWidget;
use Qt 2.0;
@ISA = qw(Qt::Widget);
sub new {
my $s = shift;
my $self = shift->SUPER::new(@_[0..1], Qt::WType_Desktop |
Qt::WPaintDesktop);
$self->{'text'} = $s;
return $self;
}
sub paintEvent {
my $c1 = $self->backgroundColor();
my $c2 = $c1->light(104);
my $c3 = $c1->dark(106);
unless(exists $self->{'pm'}) {
my $pm = $self->{'pm'} = Qt::Pixmap->new(64, 64);
generateStone($pm, $c1, $c2, $c3);
$self->setBackgroundPixmap($pm);
$self->update();
}
my $br = $self->fontMetrics()->boundingRect($self->{'text'});
my $offscreen = Qt::Pixmap->new($br->width(), $br->height());
my $x = $self->width()/2 - $br->width()/2;
my $y = $self->height()/2 - $br->height()/2;
$offscreen->fill($self, $x, $y);
my $p = Qt::Painter->new;
$p->begin($offscreen);
main::drawShadeText($p, -$br->x(), -$br->y(), $self->{'text'}, $c2, $c3, 3);
$p->end();
$self->bitBlt($x, $y, $offscreen);
}
package main;
import Qt::app;
sub desktopWidget {
my $t = DesktopWidget->new(@_);
$t->update();
$app->exec();
}
sub desktopText {
my $s = @_ ? shift : 'PerlQt rocks';
my $border = 20;
my $c1 = Qt::Application::palette()->normal()->background();
my $c2 = $c1->light(104);
my $c3 = $c1->dark(106);
my $pm = Qt::Pixmap->new(10, 10);
my $p = Qt::Painter->new;
$p->begin($pm);
my $r = $p->fontMetrics()->boundingRect($s);
$p->end();
my $appWidth = Qt::Application::desktop()->width();
my $appHeight = Qt::Application::desktop()->height();
if($r->width() > $appWidth - $border*2) {
$r->setWidth($appWidth - $border*2);
}
if($r->height() > $appHeight - $border*2) {
$r->setHeight($appHeight - $border*2);
}
$pm->resize($r->size() + Qt::Size->new($border*2, $border*2));
generateStone($pm, $c1, $c2, $c3);
$p->begin($pm);
drawShadeText($p, -$r->x() + $border, -$r->y() + $border, $s, $c2, $c3);
$p->end();
Qt::Application::desktop()->setBackgroundPixmap($pm);
}
#
# The program starts here.
#
use Qt 2.0;
if(@ARGV) {
my $f = Qt::Font->new('Charter', 96, Qt::Font::Black);
$f->setStyleHint(Qt::Font::Times);
Qt::Application::setFont($f);
}
$validOptions = 0;
if(@ARGV == 1) {
$validOptions = 1;
if($ARGV[0] eq '-poly') {
poly();
} elsif($ARGV[0] eq '-rotate') {
rotate();
} elsif($ARGV[0] eq '-perlqt') {
desktopText();
} elsif($ARGV[0] eq '-perlqtwidget') {
desktopWidget();
} else {
$validOptions = 0;
}
} elsif(@ARGV == 2) {
$validOptions = 1;
if($ARGV[0] eq '-shadetext') {
desktopText($ARGV[1]);
} elsif($ARGV[0] eq '-shadewidget') {
desktopWidget($ARGV[1]);
} else {
$validOptions = 0;
}
}
die <<CROAK unless $validOptions;
Usage:
$0 -poly
$0 -rotate
$0 -perlqt
$0 -perlqtwidget
$0 -shadetext <text>
$0 -shadewidget <text>
CROAK