File: soft_mask.rb

package info (click to toggle)
ruby-prawn 2.1.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 3,220 kB
  • ctags: 826
  • sloc: ruby: 14,469; sh: 43; makefile: 18
file content (93 lines) | stat: -rw-r--r-- 2,231 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# encoding: utf-8
#
# soft_mask.rb : Implements soft-masking
#
# Copyright September 2012, Alexander Mankuta. All Rights Reserved.
#
# This is free software. Please see the LICENSE and COPYING files for details.
#

module Prawn
  # The Prawn::SoftMask module is used to create arbitrary transparency in
  # document. Using a soft mask allows creating more visually rich documents.
  #
  # You must group soft mask and graphics it's applied to under
  # save_graphics_state because soft mask is a part of graphic state in PDF.
  #
  # Example:
  #   pdf.save_graphics_state do
  #     pdf.soft_mask do
  #       pdf.fill_color "444444"
  #       pdf.fill_polygon [0, 40], [60, 10], [120, 40], [60, 68]
  #     end
  #     pdf.fill_color '000000'
  #     pdf.fill_rectangle [0, 50], 120, 68
  #   end
  #
  module SoftMask
    # @group Stable API

    def soft_mask(&block)
      renderer.min_version(1.4)

      group_attrs = ref!(
        :Type => :Group,
        :S => :Transparency,
        :CS => :DeviceRGB,
        :I => false,
        :K => false
      )

      group = ref!(
        :Type => :XObject,
        :Subtype => :Form,
        :BBox => state.page.dimensions,
        :Group => group_attrs
      )

      state.page.stamp_stream(group, &block)

      mask = ref!(
        :Type => :Mask,
        :S => :Luminosity,
        :G => group
      )

      g_state = ref!(
        :Type => :ExtGState,
        :SMask => mask,

        :AIS => false,
        :BM => :Normal,
        :OP => false,
        :op => false,
        :OPM => 1,
        :SA => true
      )

      registry_key = {
        :bbox => state.page.dimensions,
        :mask => [group.stream.filters.normalized, group.stream.filtered_stream],
        :page => state.page_count
      }.hash

      if soft_mask_registry[registry_key]
        renderer.add_content "/#{soft_mask_registry[registry_key]} gs"
      else
        masks = page.resources[:ExtGState] ||= {}
        id = masks.empty? ? 'GS1' : masks.keys.sort.last.succ
        masks[id] = g_state

        soft_mask_registry[registry_key] = id

        renderer.add_content "/#{id} gs"
      end
    end

    private

    def soft_mask_registry
      @soft_mask_registry ||= {}
    end
  end
end