acro_that 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35e82f82af4a5ad469ce89111633daea2b86ca0f9a965282824c03bd5f9b8af6
4
- data.tar.gz: 47e8c25c2f8d1a9243ed9c6e5c85ba6f65aa1cc52b8abe62c3fdaed3a72f8361
3
+ metadata.gz: 31a0652c9e6d834244b0a296b017d82a1a77ef07666c3e4e1b482b622e1c80cd
4
+ data.tar.gz: 3af1db0522ab1a9a754afb6c1b297184c49ed05547093611d6f3dce838b1e782
5
5
  SHA512:
6
- metadata.gz: d20594b2b72776e4eea071d87036e2151cfcbb5a36f09d1b11ecd4d055168a613ba1d8fcd308b1748706b30c4ea6cc84742e2f895a21f594ef6c9a79351f5cc1
7
- data.tar.gz: fb36a88b91eced4f62b027f920e5233e626f4d469087fe7c46419091020324b9d92d0f5a70d55479064c93bd787513950b2ce84bbcb185834a706c7f83fa9555
6
+ metadata.gz: f2265b5ee6e1ae3ffd9421b0c3944bbe59c52f4e4d1c437a0a555764a36aa7ed23f8c7b0189eb4b7c4aa3703889f7eb58e8cd44232826060fc4bc7599b84504a
7
+ data.tar.gz: 9c90530b5041bd419f28a7c4f9f82829897bbb0a83bb2527ab93e0c90af862ddeed7f4a070f133daf1ab0a149faabf1b7b517c8bf5e11f5719f36050804d9ec3
data/.gitignore CHANGED
@@ -2,6 +2,8 @@
2
2
  .rspec_status
3
3
 
4
4
  *.pdf
5
+ *.png
6
+ *.jpg
5
7
  *.gem
6
8
 
7
9
  research/
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- acro_that (1.0.0)
4
+ acro_that (1.0.2)
5
5
  chunky_png (~> 1.4)
6
6
 
7
7
  GEM
@@ -77,7 +77,13 @@ module AcroThat
77
77
  field_flags = @metadata[:Ff] || 0
78
78
  dict += " /Ff #{field_flags}\n"
79
79
 
80
- dict += " /DA (/Helv 0 Tf 0 g)\n"
80
+ # Apply /DA from metadata for text fields only, or use default
81
+ if type == "/Tx" && @metadata[:DA]
82
+ da_value = DictScan.format_pdf_value(@metadata[:DA])
83
+ dict += " /DA #{da_value}\n"
84
+ else
85
+ dict += " /DA (/Helv 0 Tf 0 g)\n"
86
+ end
81
87
 
82
88
  # Check if this is a radio button (has Radio flag set)
83
89
  is_radio_field = field_flags.anybits?(32_768)
@@ -125,9 +131,10 @@ module AcroThat
125
131
  end
126
132
  end
127
133
 
128
- # Apply other metadata entries (excluding Ff which we handled above)
134
+ # Apply other metadata entries (excluding Ff and DA which we handled above)
129
135
  @metadata.each do |key, val|
130
136
  next if key == :Ff
137
+ next if key == :DA && type == "/Tx"
131
138
 
132
139
  pdf_key = DictScan.format_pdf_key(key)
133
140
  pdf_value = DictScan.format_pdf_value(val)
@@ -174,17 +181,23 @@ module AcroThat
174
181
  widget += " /Rect #{rect_array}\n"
175
182
  widget += " /F 4\n"
176
183
 
177
- widget += if is_radio
178
- " /MK << /BC [0.0] /BG [1.0] >>\n"
179
- else
180
- " /DA (/Helv 0 Tf 0 g)\n"
181
- end
184
+ # Apply /DA from metadata for text fields only, otherwise use default behavior
185
+ if is_radio
186
+ widget += " /MK << /BC [0.0] /BG [1.0] >>\n"
187
+ elsif type == "/Tx" && @metadata[:DA]
188
+ da_value = DictScan.format_pdf_value(@metadata[:DA])
189
+ widget += " /DA #{da_value}\n"
190
+ else
191
+ widget += " /DA (/Helv 0 Tf 0 g)\n"
192
+ end
182
193
 
183
194
  @metadata.each do |key, val|
184
195
  pdf_key = DictScan.format_pdf_key(key)
185
196
  pdf_value = DictScan.format_pdf_value(val)
186
197
  next if ["/F", "/V"].include?(pdf_key)
187
198
  next if is_radio && ["/Ff", "/DA"].include?(pdf_key)
199
+ # Skip /DA for text fields since we already handled it above
200
+ next if pdf_key == "/DA" && type == "/Tx"
188
201
 
189
202
  widget += " #{pdf_key} #{pdf_value}\n"
190
203
  end
@@ -47,29 +47,64 @@ module AcroThat
47
47
  # Sort offsets and group consecutive objects into subsections
48
48
  sorted = @offsets.sort_by { |num, gen, _offset| [num, gen] }
49
49
 
50
- i = 0
51
- while i < sorted.length
52
- first_num = sorted[i][0]
53
-
54
- # Find consecutive run
55
- run_length = 1
56
- while (i + run_length) < sorted.length &&
57
- sorted[i + run_length][0] == first_num + run_length &&
58
- sorted[i + run_length][1] == sorted[i][1]
59
- run_length += 1
60
- end
61
-
62
- # Write subsection header
63
- xref << "#{first_num} #{run_length}\n".b
50
+ # Find max object number to determine Size
51
+ max_obj_num = sorted.map { |num, _gen, _offset| num }.max || 0
64
52
 
65
- # Write entries in this subsection
66
- run_length.times do |j|
67
- offset = sorted[i + j][2]
68
- gen = sorted[i + j][1]
69
- xref << format("%010d %05d n \n", offset, gen).b
53
+ # Build xref entries covering all objects from 0 to max_obj_num
54
+ # Missing objects are marked as free (type 'f')
55
+ i = 0
56
+ current_obj = 0
57
+
58
+ while current_obj <= max_obj_num
59
+ # Find next existing object
60
+ next_existing = sorted.find { |num, _gen, _offset| num >= current_obj }
61
+
62
+ if next_existing && next_existing[0] == current_obj
63
+ # Object exists - find consecutive run of existing objects
64
+ first_num = current_obj
65
+ run_length = 1
66
+
67
+ while (i + run_length) < sorted.length &&
68
+ sorted[i + run_length][0] == first_num + run_length &&
69
+ sorted[i + run_length][1] == sorted[i][1]
70
+ run_length += 1
71
+ end
72
+
73
+ # Write subsection header
74
+ xref << "#{first_num} #{run_length}\n".b
75
+
76
+ # Write entries in this subsection
77
+ run_length.times do |j|
78
+ offset = sorted[i + j][2]
79
+ gen = sorted[i + j][1]
80
+ xref << format("%010d %05d n \n", offset, gen).b
81
+ end
82
+
83
+ i += run_length
84
+ current_obj = first_num + run_length
85
+ else
86
+ # Object doesn't exist - find consecutive run of missing objects
87
+ first_missing = current_obj
88
+ missing_count = 1
89
+
90
+ while current_obj + missing_count <= max_obj_num
91
+ check_obj = current_obj + missing_count
92
+ if sorted.any? { |num, _gen, _offset| num == check_obj }
93
+ break
94
+ end
95
+ missing_count += 1
96
+ end
97
+
98
+ # Write subsection header for missing objects
99
+ xref << "#{first_missing} #{missing_count}\n".b
100
+
101
+ # Write free entries
102
+ missing_count.times do
103
+ xref << "0000000000 65535 f \n".b
104
+ end
105
+
106
+ current_obj = first_missing + missing_count
70
107
  end
71
-
72
- i += run_length
73
108
  end
74
109
 
75
110
  @buffer << xref
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AcroThat
4
- VERSION = "1.0.1"
4
+ VERSION = "1.0.3"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acro_that
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Wynkoop
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-11-06 00:00:00.000000000 Z
11
+ date: 2025-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chunky_png