CAM::PDF::GS - PDF graphic state


CAM-PDF documentation Contained in the CAM-PDF distribution.

Index


Code Index:

NAME

Top

CAM::PDF::GS - PDF graphic state

LICENSE

Top

See CAM::PDF.

SYNOPSIS

Top

    use CAM::PDF;
    my $pdf = CAM::PDF->new($filename);
    my $contentTree = $pdf->getPageContentTree(4);
    my $gs = $contentTree->computeGS();

DESCRIPTION

Top

This class is used to represent the graphic state at a point in the rendering flow of a PDF page. Much of the functionality is actually based in the parent class, CAM::PDF::GS::NoText.

Subclasses that want to do something useful with text should override the renderText() method.

CONVERSION FUNCTIONS

Top

$self->getCoords($node)

Computes device coordinates for the specified node. This implementation handles text-printing nodes, and hands all other types to the superclass.

$self->textToUser($x, $y)

Convert text coordinates (Tm) to user coordinates. Returns the converted X and Y.

$self->textToDevice($x, $y)

Convert text coordinates (Tm) to device coordinates. Returns the converted X and Y.

$self->textLineToUser($x, $y)

Convert text coordinates (Tlm) to user coordinates. Returns the converted X and Y.

$self->textLineToDevice($x, $y)

Convert text coordinates (Tlm) to device coordinates. Returns the converted X and Y.

$self->renderText($string, $width)

A general method for rendering strings, from Tj or TJ. This is a no-op, but subclasses may override.

$self->Tadvance($width)

Move the text cursor.

DATA FUNCTIONS

Top

$self->BT()
$self->Tf($fontname, $fontsize)
$self->Tstar()
$self->Tz($scale)
$self->Td($x, $y)
$self->TD($x, $y)
$self->Tj($string)
$self->TJ($arrayref)
$self->quote($string)
$self->doublequote($tw, $tc, $string)
$self->Tm($m1, $m2, $m3, $m4, $m5, $m6)

AUTHOR

Top

See CAM::PDF


CAM-PDF documentation Contained in the CAM-PDF distribution.
package CAM::PDF::GS;

use 5.006;
use strict;
use warnings;
use base qw(CAM::PDF::GS::NoText);

our $VERSION = '1.55';

my %text_cmds = map {$_ => 1} qw(TJ Tj quote doublequote);

sub getCoords
{
   my $self = shift;
   my $node = shift;

   if ($text_cmds{$node->{name}})
   {
      ## no critic (Bangs::ProhibitNumberedNames)
      my ($x1,$y1) = $self->userToDevice(@{$self->{last}});
      my ($x2,$y2) = $self->userToDevice(@{$self->{current}});
      return ($x1,$y1,$x2,$y2);
   }
   else
   {
      return $self->SUPER::getCoords($node);
   }
}

sub textToUser
{
   my $self = shift;
   my $x = shift;
   my $y = shift;

   return $self->dot($self->{Tm}, $x, $y);

}

sub textToDevice
{
   my $self = shift;
   my $x = shift;
   my $y = shift;

   return $self->userToDevice($self->textToUser($x, $y));
}

sub textLineToUser
{
   my $self = shift;
   my $x = shift;
   my $y = shift;

   return $self->dot($self->{Tlm}, $x, $y);
}

sub textLineToDevice
{
   my $self = shift;
   my $x = shift;
   my $y = shift;

   return $self->userToDevice($self->textLineToUser($x, $y));
}

sub renderText
{
   my $self = shift;
   my $string = shift;
   my $width = shift;

   # noop, override in subclasses
   return;
}

sub Tadvance
{
   my $self = shift;
   my $width = shift;

   my $tx = 0;
   my $ty = 0;
   if ($self->{wm} == 0)
   {
      $tx = ($width * $self->{Tfs} + $self->{Tc} + $self->{Tw}) * $self->{Tz};
   }
   else
   {
      $ty = $width * $self->{Tfs} + $self->{Tc} + $self->{Tw};
   }
   $self->{moved}->[0] += $tx;
   $self->{moved}->[1] += $ty;

   $self->applyMatrix([1,0,0,1,$tx,$ty], $self->{Tm});
   return;
}

sub BT
{
   my $self = shift;

   @{$self->{Tm}} = (1, 0, 0, 1, 0, 0);
   @{$self->{Tlm}} = (1, 0, 0, 1, 0, 0);
   return;
}

sub Tf
{
   my $self = shift;
   my $fontname = shift;
   my $fontsize = shift;

   $self->{Tf} = $fontname;
   $self->{Tfs} = $fontsize;
   $self->{refs}->{fm} = $self->{refs}->{doc}->getFontMetrics($self->{refs}->{properties}, $fontname);

   # TODO: support vertical text mode (wm = 1)
   $self->{wm} = 0;
   return;
}

sub Tstar
{
   my $self = shift;

   $self->Td(0, -$self->{TL});
   return;
}

sub Tz
{
   my $self = shift;
   my $scale = shift;

   $self->{Tz} = $scale/100.0;
   return;
}

sub Td
{
   my $self = shift;
   my $x = shift;
   my $y = shift;

   $self->applyMatrix([1,0,0,1,$x,$y], $self->{Tlm});
   @{$self->{Tm}} = @{$self->{Tlm}};
   return;
}

sub TD
{
   my $self = shift;
   my $x = shift;
   my $y = shift;

   $self->TL(-$y);
   $self->Td($x,$y);
   return;
}

sub Tj
{
   my $self = shift;
   my $string = shift;

   @{$self->{last}} = $self->textToUser(0,0);
   $self->_Tj($string);
   @{$self->{current}} = $self->textToUser(0,0);
   return;
}

sub _Tj
{
   my $self = shift;
   my $string = shift;

   if (!$self->{refs}->{fm})
   {
      die "No font metrics for font $self->{Tf}";
   }

   my @parts;
   if ($self->{mode} eq 'c' || $self->{wm} == 1)
   {
      @parts = split m//xms, $string;
   }
   else
   {
      @parts = ($string);
   }
   foreach my $substr (@parts)
   {
      my $dw = $self->{refs}->{doc}->getStringWidth($self->{refs}->{fm}, $substr);
      $self->renderText($substr, $dw);
      $self->Tadvance($dw);
   }
   return;
}

sub TJ
{
   my $self = shift;
   my $array = shift;

   @{$self->{last}} = $self->textToUser(0,0);
   foreach my $node (@{$array})
   {
      if ($node->{type} eq 'number')
      {
         my $dw = -$node->{value} / 1000.0;
         $self->Tadvance($dw);
      }
      else
      {
         $self->_Tj($node->{value});
      }
   }
   @{$self->{current}} = $self->textToUser(0,0);
   return;
}

sub quote
{
   my $self = shift;
   my $string = shift;

   @{$self->{last}} = $self->textToUser(0,0);
   $self->Tstar();
   $self->_Tj($string);
   @{$self->{current}} = $self->textToUser(0,0);
   return;
}

sub doublequote
{
   my $self = shift;
   $self->{Tw} = shift;
   $self->{Tc} = shift;
   my $string = shift;

   $self->quote($string);
   return;
}

sub Tm
{
   my ($self, @tm) = @_;

   @{$self->{Tm}} = @{$self->{Tlm}} = @tm;
   return;
}

1;
__END__