[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

Re: [MacPerl] Under the microscope...



> >Better late than never, right?
> 
> Absolutely -- and it works perfectly :-)
> 
> The near instantaneous redraw on an 'update' does give a very nice
> demonstration of the power of offscreen graphics doesn't it?

Here's a new version that allows you to navigate through the fractal.

BTW, anyone know how to generate the Mandelbrot set?

#!perl -w

# Col_Z^3 (GWorld) v1.1
# by Kevin Reid <kpreid@ibm.net>
# Original by Alan Fry
# 
# Requires MacPerl 5.2.1a1 or later and "19-May-98
# versions of QuickDraw and QDOffscreen"
#
# Click in window to move and zoom in.
# Option-click to move and zoom out.
# Click zoom box to reset view.
#
# Version History
# 1.1
#   * Aded mouse navigation
#   * Added interlaced drawing
#   * Added info in title bar
# 1.0
#   * Initial release


use Mac::Windows;
use Mac::QuickDraw;
use Mac::QDOffscreen;
use Mac::Events;
use strict;

use vars qw(
  $Window
  $OrigP $OffP
  $OrigD $OffD
  $GWorld
  $PixMap

  $CurRow $Drawn

  $ViewX $ViewY $ViewMag
);

sub ltwh {new Rect ($_[0], $_[1], $_[0] + $_[2], $_[1] + $_[3])}

sub Width () {400}
sub Height () {300}
sub Interlace () {10}
sub Background () {new RGBColor((0)x3)}

$Drawn = $CurRow = 0;

my $cr = 0.5;
my $ci = 0;

$ViewX = 0;
$ViewY = 0;
$ViewMag = 50;

{
  my $srect = GetMainDevice()->gdRect;
  my $winrect = new Rect (0, 0, Width, Height);
  $Window = new MacColorWindow (
    OffsetRect($winrect,
      $srect->left + ($srect->right - $srect->left - $winrect->right) / 2,
      $srect->top + ($srect->bottom - $srect->top - $winrect->bottom) / 2,
    ),
    '', 1, zoomNoGrow, 1);
  $Window->sethook(drawgrowicon => sub {});
  SetTitle();
}

($OrigP, $OrigD) = GetGWorld();
$GWorld = NewGWorld(0, $Window->window->portRect);
SetGWorld($GWorld);
($OffP, $OffD) = GetGWorld();
$PixMap = GetGWorldPixMap($GWorld);
LockPixels($PixMap);
RGBBackColor(Background);
EraseRect $GWorld->portRect;

$Window->sethook(redraw => sub {
  LockPixels($PixMap) if $Drawn;
  my $rect = $Window->window->visRgn->rgnBBox;
  CopyBits($GWorld->portBits, $Window->window->portBits,
           $rect, $rect, 0);
  UnlockPixels($PixMap) if $Drawn;
});
$Window->sethook(click => sub {
  my $pt = $_[1];
  $ViewX = $ViewX + ($pt->h - Width/2) / $ViewMag;
  $ViewY = $ViewY + ($pt->v - Height/2) / $ViewMag;
  $ViewMag = $ViewMag * (($Mac::Events::CurrentEvent->modifiers & optionKey) ? 1/3 : 3);
  Redraw();
});
$Window->sethook(zoom => sub {
  my ($my, $pt, $part) = @_;
  TrackBox($my->window, $pt, $part) or return;
  $ViewX = 0;
  $ViewY = 0;
  $ViewMag = 50;
  Redraw();
  1;
});
$Window->sethook(cursor => sub {SetCursor(crossCursor)});

while ($Window->window) {
  DrawSome() unless $Drawn;
  WaitNextEvent;
}

sub DrawSome {
  SetGWorld($OffP, $OffD);
  my $y = ($CurRow*Interlace % Height) + int($CurRow / (Height/Interlace));
  for (my $x = 0; $x < Width; $x++) {
    RGBForeColor CalcPt($x, $y);
    MoveTo $x, $y;
    LineTo $x, $y + (Interlace - int($CurRow / (Height/Interlace))) - 1;
  }
  $CurRow++; 

  SetGWorld($OrigP, $OrigD);
  SetPort $Window->window;
  my $rect = new Rect (0, $y, Width, $y+Interlace);
  CopyBits($GWorld->portBits, $Window->window->portBits,
           $rect, $rect, 0);
  #$Window->redraw;
  SetTitle();

  if ($CurRow > Height) {
    $Drawn = 1;
    UnlockPixels($PixMap);
  }
}

sub CalcPt {
  my ($x, $y) = @_;
  return CalcPt2(($x - Width/2) / $ViewMag + $ViewX, ($y - Height/2) / $ViewMag + $ViewY);
}

sub CalcPt2 {
  my ($j, $k) = @_;
  my ($a, $b, $c, $d, $z);
  $a = $j;
  $b = $k;
  for (1..10) {
    $c = ($a*$a - 3*$b*$b)*$a+$cr;
    $d = (3*$a*$a - $b*$b)*$b+$ci;
    $a = $c;
    $b = $d;
    $z = $a*$a + $b*$b;
    last if $z > 100;
  }
  my $int = 1.45 - 0.09772*log($z);
  $int = 0 if $int < 0;
  if    (abs($a) < 10) {return RGBColor->new((1-abs($a)/10)*65335, 0, 0)}
  elsif (abs($b) < 10) {return RGBColor->new(0, (1-abs($b)/10)*65335, 0)}
  else                 {return RGBColor->new(0, 0, $int*65535)}
}

sub SetTitle {
  SetWTitle $Window->window, 
    sprintf ("X: %5f, Y: %5f, Mag: %d", $ViewX, $ViewY, $ViewMag)
     . ($Drawn ? '' : ", @{[sprintf '%3d', $CurRow/Height*100]}%");
}

sub Redraw {
  LockPixels($PixMap) if $Drawn;
  $CurRow = $Drawn = 0;
  SetGWorld($OffP, $OffD);
  EraseRect $GWorld->portRect;
  SetGWorld($OrigP, $OrigD);
  SetPort $Window->window;
  $Window->redraw;
}

END {
   $Window->dispose       if defined $Window;
   UnlockPixels($PixMap)  if defined $PixMap;
   DisposeGWorld($GWorld) if defined $GWorld;
}

__END__

-- 
 Kevin Reid: |    Macintosh:      
  "I'm me."  | Think different.

===== Want to unsubscribe from this list?
===== Send mail with body "unsubscribe" to macperl-request@macperl.org