Class: HexaPDF::Layout::Style::LinkLayer

Inherits:
Object
  • Object
show all
Defined in:
lib/hexapdf/layout/style.rb

Overview

The LinkLayer class provides support for linking to in-document or remote destinations for Style objects using link annotations. Typical use cases would be linking to a (named) destination on a different page or executing a URI action.

See: PDF2.0 s12.5.6.5, Layers, HexaPDF::Type::Annotations::Link

Instance Method Summary collapse

Constructor Details

#initialize(dest: nil, uri: nil, file: nil, action: nil, border: false, border_color: nil) ⇒ LinkLayer

Creates a new LinkLayer object.

The following arguments are allowed (note that only one of dest, uri, file or action may be specified):

dest

The destination array or a name of a named destination for in-document links. If neither dest, uri, file nor action is specified, it is assumed that the box has a custom property named ‘link’ which is used for the destination.

uri

The URI to link to.

file

The file that should be opened or, if it refers to an application, the application that should be launched. Can either be a string or a Filespec object. Also see: HexaPDF::Type::FileSpecification.

action

The PDF action that should be executed.

border

If set to true, a standard border is used. Also accepts an array that adheres to the rules for annotation borders.

border_color

Defines the border color. Can be an array with 0 (transparent), 1 (grayscale), 3 (RGB) or 4 (CMYK) values.

Examples:

LinkLayer.new(dest: [page, :XYZ, nil, nil, nil], border: true)
LinkLayer.new(uri: "https://my.example.com/path", border: [5 5 2])
LinkLayer.new     # use 'link' custom box property for dest


513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
# File 'lib/hexapdf/layout/style.rb', line 513

def initialize(dest: nil, uri: nil, file: nil, action: nil, border: false, border_color: nil)
  if dest && (uri || file || action) || uri && (file || action) || file && action
    raise ArgumentError, "Only one of dest, uri, file or action is allowed"
  end
  @dest = dest
  @action = if uri
              {S: :URI, URI: uri}
            elsif file
              {S: :Launch, F: file, NewWindow: true}
            elsif action
              action
            end
  @border = case border
            when false then [0, 0, 0]
            when true then nil
            when Array then border
            else raise ArgumentError, "Invalid value for border: #{border}"
            end
  @border_color = border_color
end

Instance Method Details

#call(canvas, box) ⇒ Object

Creates the needed link annotation if possible, i.e. if the context of the canvas is a page.



536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
# File 'lib/hexapdf/layout/style.rb', line 536

def call(canvas, box)
  return unless canvas.context.type == :Page
  @dest = box.properties['link'] unless @dest || @action

  page = canvas.context
  matrix = canvas.graphics_state.ctm
  quad_points = [*matrix.evaluate(0, 0), *matrix.evaluate(box.width, 0),
                 *matrix.evaluate(box.width, box.height), *matrix.evaluate(0, box.height)]
  x_minmax = quad_points.values_at(0, 2, 4, 6).minmax
  y_minmax = quad_points.values_at(1, 3, 5, 7).minmax
  border_color = case @border_color
                 when [], nil
                   @border_color
                 else
                   canvas.color_from_specification(@border_color).components
                 end
  annot = {
    Subtype: :Link,
    Rect: [x_minmax[0], y_minmax[0], x_minmax[1], y_minmax[1]],
    QuadPoints: quad_points,
    Dest: @dest,
    A: @action,
    Border: @border,
    C: border_color,
  }
  (page[:Annots] ||= []) << page.document.add(annot)
end