fontisan 0.2.7 → 0.2.9
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 +4 -4
- data/.rubocop.yml +103 -0
- data/.rubocop_todo.yml +65 -361
- data/CHANGELOG.md +116 -0
- data/Gemfile +1 -1
- data/README.adoc +106 -27
- data/Rakefile +12 -7
- data/benchmark/variation_quick_bench.rb +1 -1
- data/docs/APPLE_LEGACY_FONTS.adoc +173 -0
- data/docs/COLLECTION_VALIDATION.adoc +143 -0
- data/docs/COLOR_FONTS.adoc +127 -0
- data/docs/DOCUMENTATION_SUMMARY.md +141 -0
- data/docs/FONT_HINTING.adoc +9 -1
- data/docs/VALIDATION.adoc +254 -0
- data/docs/WOFF_WOFF2_FORMATS.adoc +94 -0
- data/lib/fontisan/cli.rb +45 -13
- data/lib/fontisan/collection/dfont_builder.rb +2 -1
- data/lib/fontisan/commands/convert_command.rb +2 -4
- data/lib/fontisan/commands/info_command.rb +3 -3
- data/lib/fontisan/commands/pack_command.rb +2 -1
- data/lib/fontisan/commands/validate_command.rb +157 -6
- data/lib/fontisan/converters/collection_converter.rb +22 -13
- data/lib/fontisan/converters/svg_generator.rb +2 -1
- data/lib/fontisan/converters/woff2_encoder.rb +6 -6
- data/lib/fontisan/converters/woff_writer.rb +3 -1
- data/lib/fontisan/font_loader.rb +7 -6
- data/lib/fontisan/formatters/text_formatter.rb +18 -14
- data/lib/fontisan/hints/hint_converter.rb +1 -1
- data/lib/fontisan/hints/hint_validator.rb +13 -10
- data/lib/fontisan/hints/truetype_instruction_analyzer.rb +15 -8
- data/lib/fontisan/hints/truetype_instruction_generator.rb +1 -1
- data/lib/fontisan/models/collection_validation_report.rb +104 -0
- data/lib/fontisan/models/font_report.rb +24 -0
- data/lib/fontisan/models/validation_report.rb +7 -2
- data/lib/fontisan/open_type_font.rb +18 -425
- data/lib/fontisan/optimizers/charstring_rewriter.rb +1 -1
- data/lib/fontisan/optimizers/subroutine_optimizer.rb +6 -2
- data/lib/fontisan/sfnt_font.rb +699 -0
- data/lib/fontisan/sfnt_table.rb +264 -0
- data/lib/fontisan/subset/glyph_mapping.rb +2 -0
- data/lib/fontisan/subset/table_subsetter.rb +2 -2
- data/lib/fontisan/tables/cblc.rb +8 -4
- data/lib/fontisan/tables/cff/index.rb +2 -0
- data/lib/fontisan/tables/cff.rb +6 -3
- data/lib/fontisan/tables/cff2/private_dict_blend_handler.rb +1 -1
- data/lib/fontisan/tables/cff2.rb +1 -1
- data/lib/fontisan/tables/cmap.rb +5 -5
- data/lib/fontisan/tables/cmap_table.rb +231 -0
- data/lib/fontisan/tables/glyf.rb +8 -10
- data/lib/fontisan/tables/glyf_table.rb +255 -0
- data/lib/fontisan/tables/head.rb +3 -3
- data/lib/fontisan/tables/head_table.rb +111 -0
- data/lib/fontisan/tables/hhea.rb +4 -4
- data/lib/fontisan/tables/hhea_table.rb +255 -0
- data/lib/fontisan/tables/hmtx_table.rb +191 -0
- data/lib/fontisan/tables/loca_table.rb +212 -0
- data/lib/fontisan/tables/maxp.rb +2 -2
- data/lib/fontisan/tables/maxp_table.rb +258 -0
- data/lib/fontisan/tables/name.rb +1 -1
- data/lib/fontisan/tables/name_table.rb +176 -0
- data/lib/fontisan/tables/os2.rb +8 -8
- data/lib/fontisan/tables/os2_table.rb +329 -0
- data/lib/fontisan/tables/post.rb +2 -2
- data/lib/fontisan/tables/post_table.rb +183 -0
- data/lib/fontisan/tables/sbix.rb +5 -4
- data/lib/fontisan/true_type_font.rb +12 -464
- data/lib/fontisan/utilities/checksum_calculator.rb +0 -44
- data/lib/fontisan/validation/collection_validator.rb +4 -2
- data/lib/fontisan/validators/basic_validator.rb +11 -21
- data/lib/fontisan/validators/font_book_validator.rb +29 -50
- data/lib/fontisan/validators/opentype_validator.rb +24 -28
- data/lib/fontisan/validators/validator.rb +87 -66
- data/lib/fontisan/validators/web_font_validator.rb +16 -21
- data/lib/fontisan/version.rb +1 -1
- data/lib/fontisan/woff2/glyf_transformer.rb +31 -8
- data/lib/fontisan/woff2/hmtx_transformer.rb +2 -1
- data/lib/fontisan/woff2/table_transformer.rb +4 -2
- data/lib/fontisan/woff2_font.rb +4 -2
- data/lib/fontisan/woff_font.rb +46 -30
- data/lib/fontisan.rb +2 -2
- data/scripts/compare_stack_aware.rb +1 -1
- data/scripts/measure_optimization.rb +1 -2
- metadata +23 -2
|
@@ -138,7 +138,8 @@ module Fontisan
|
|
|
138
138
|
num_glyphs = maxp_table.num_glyphs
|
|
139
139
|
|
|
140
140
|
# Parse hmtx table
|
|
141
|
-
advance_widths, lsbs = parse_hmtx_table(hmtx_data, num_h_metrics,
|
|
141
|
+
advance_widths, lsbs = parse_hmtx_table(hmtx_data, num_h_metrics,
|
|
142
|
+
num_glyphs)
|
|
142
143
|
|
|
143
144
|
# Build transformed hmtx table
|
|
144
145
|
build_transformed_hmtx(advance_widths, lsbs, num_h_metrics, num_glyphs)
|
|
@@ -388,7 +389,8 @@ module Fontisan
|
|
|
388
389
|
# @param num_h_metrics [Integer] Number of hMetric entries
|
|
389
390
|
# @param num_glyphs [Integer] Total number of glyphs
|
|
390
391
|
# @return [String] Transformed hmtx data
|
|
391
|
-
def build_transformed_hmtx(advance_widths, lsbs, num_h_metrics,
|
|
392
|
+
def build_transformed_hmtx(advance_widths, lsbs, num_h_metrics,
|
|
393
|
+
num_glyphs)
|
|
392
394
|
data = String.new(encoding: Encoding::BINARY)
|
|
393
395
|
|
|
394
396
|
# Flags: Use proportional encoding (not explicit) and explicit LSBs
|
data/lib/fontisan/woff2_font.rb
CHANGED
|
@@ -666,7 +666,8 @@ module Fontisan
|
|
|
666
666
|
offset += padding
|
|
667
667
|
end
|
|
668
668
|
|
|
669
|
-
# Write table directory
|
|
669
|
+
# Write table directory (all entries first)
|
|
670
|
+
# rubocop:disable Style/CombinableLoops - Must write directory entries first, then data
|
|
670
671
|
table_records.each do |record|
|
|
671
672
|
sfnt_data << record[:tag].ljust(4, "\x00")
|
|
672
673
|
sfnt_data << [record[:checksum]].pack("N")
|
|
@@ -674,7 +675,7 @@ module Fontisan
|
|
|
674
675
|
sfnt_data << [record[:length]].pack("N")
|
|
675
676
|
end
|
|
676
677
|
|
|
677
|
-
#
|
|
678
|
+
# Then write all table data with padding
|
|
678
679
|
table_records.each do |record|
|
|
679
680
|
sfnt_data << record[:data]
|
|
680
681
|
|
|
@@ -683,6 +684,7 @@ module Fontisan
|
|
|
683
684
|
Constants::TABLE_ALIGNMENT
|
|
684
685
|
sfnt_data << ("\x00" * padding) if padding.positive?
|
|
685
686
|
end
|
|
687
|
+
# rubocop:enable Style/CombinableLoops
|
|
686
688
|
|
|
687
689
|
# Update checksumAdjustment in head table
|
|
688
690
|
update_checksum_in_memory(sfnt_data, table_records)
|
data/lib/fontisan/woff_font.rb
CHANGED
|
@@ -438,12 +438,13 @@ module Fontisan
|
|
|
438
438
|
io.write("\x00" * padding) if padding.positive?
|
|
439
439
|
end
|
|
440
440
|
|
|
441
|
+
# Update checksum adjustment in head table BEFORE closing file
|
|
442
|
+
# This avoids Windows file locking issues when Tempfiles are used
|
|
443
|
+
update_checksum_adjustment_in_io(io)
|
|
444
|
+
|
|
441
445
|
io.pos
|
|
442
446
|
end
|
|
443
447
|
|
|
444
|
-
# Update checksum adjustment in head table
|
|
445
|
-
update_checksum_adjustment_in_file(output_path)
|
|
446
|
-
|
|
447
448
|
File.size(output_path)
|
|
448
449
|
end
|
|
449
450
|
|
|
@@ -458,43 +459,58 @@ module Fontisan
|
|
|
458
459
|
[search_range, entry_selector, range_shift]
|
|
459
460
|
end
|
|
460
461
|
|
|
461
|
-
# Update checksumAdjustment field in head table
|
|
462
|
+
# Update checksumAdjustment field in head table using an open IO object
|
|
462
463
|
#
|
|
463
|
-
# @param
|
|
464
|
+
# @param io [IO] Open IO object positioned at start of file
|
|
464
465
|
# @return [void]
|
|
465
|
-
def
|
|
466
|
-
#
|
|
466
|
+
def update_checksum_adjustment_in_io(io)
|
|
467
|
+
# Save current position
|
|
468
|
+
current_pos = io.pos
|
|
469
|
+
|
|
470
|
+
# Find head table position in the file
|
|
467
471
|
head_offset = nil
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
break
|
|
482
|
-
end
|
|
472
|
+
io.seek(4) # Skip sfnt_version
|
|
473
|
+
num_tables = io.read(2).unpack1("n")
|
|
474
|
+
io.seek(12) # Start of table directory
|
|
475
|
+
|
|
476
|
+
num_tables.times do
|
|
477
|
+
tag = io.read(4)
|
|
478
|
+
io.read(4) # checksum
|
|
479
|
+
offset = io.read(4).unpack1("N")
|
|
480
|
+
io.read(4) # length
|
|
481
|
+
|
|
482
|
+
if tag == Constants::HEAD_TAG
|
|
483
|
+
head_offset = offset
|
|
484
|
+
break
|
|
483
485
|
end
|
|
484
486
|
end
|
|
485
487
|
|
|
486
488
|
return unless head_offset
|
|
487
489
|
|
|
488
|
-
#
|
|
489
|
-
|
|
490
|
-
|
|
490
|
+
# Rewind to calculate checksum from the beginning
|
|
491
|
+
io.rewind
|
|
492
|
+
|
|
493
|
+
# Calculate checksum directly from IO to avoid Windows Tempfile issues
|
|
494
|
+
checksum = Utilities::ChecksumCalculator.calculate_checksum_from_io(io)
|
|
491
495
|
|
|
492
|
-
|
|
493
|
-
|
|
496
|
+
# Calculate adjustment
|
|
497
|
+
adjustment = Utilities::ChecksumCalculator.calculate_adjustment(checksum)
|
|
494
498
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
499
|
+
# Write adjustment to head table (offset 8 within head table)
|
|
500
|
+
io.seek(head_offset + 8)
|
|
501
|
+
io.write([adjustment].pack("N"))
|
|
502
|
+
|
|
503
|
+
# Restore original position
|
|
504
|
+
io.seek(current_pos)
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
# Update checksumAdjustment field in head table
|
|
508
|
+
#
|
|
509
|
+
# @param path [String] Path to the font file
|
|
510
|
+
# @return [void]
|
|
511
|
+
def update_checksum_adjustment_in_file(path)
|
|
512
|
+
File.open(path, "r+b") do |io|
|
|
513
|
+
update_checksum_adjustment_in_io(io)
|
|
498
514
|
end
|
|
499
515
|
end
|
|
500
516
|
end
|
data/lib/fontisan.rb
CHANGED
|
@@ -112,6 +112,8 @@ require_relative "fontisan/models/scripts_info"
|
|
|
112
112
|
require_relative "fontisan/models/features_info"
|
|
113
113
|
require_relative "fontisan/models/all_scripts_features_info"
|
|
114
114
|
require_relative "fontisan/models/validation_report"
|
|
115
|
+
require_relative "fontisan/models/font_report"
|
|
116
|
+
require_relative "fontisan/models/collection_validation_report"
|
|
115
117
|
require_relative "fontisan/models/font_export"
|
|
116
118
|
require_relative "fontisan/models/collection_font_summary"
|
|
117
119
|
require_relative "fontisan/models/collection_info"
|
|
@@ -319,8 +321,6 @@ module Fontisan
|
|
|
319
321
|
end
|
|
320
322
|
|
|
321
323
|
class << self
|
|
322
|
-
private
|
|
323
|
-
|
|
324
324
|
# Get loading mode for validation profile
|
|
325
325
|
#
|
|
326
326
|
# Temporarily disabled - will be reimplemented with new DSL framework
|
|
@@ -153,7 +153,7 @@ def main
|
|
|
153
153
|
puts "\nStack-Aware Efficiency: #{efficiency_ratio}% of normal optimization"
|
|
154
154
|
end
|
|
155
155
|
|
|
156
|
-
time_overhead = ((stack_aware[:time] / unoptimized[:time] - 1) * 100).round(2)
|
|
156
|
+
time_overhead = (((stack_aware[:time] / unoptimized[:time]) - 1) * 100).round(2)
|
|
157
157
|
puts "\nProcessing Time Overhead:"
|
|
158
158
|
puts " Stack-Aware vs Unoptimized: +#{time_overhead}%"
|
|
159
159
|
|
|
@@ -96,8 +96,7 @@ def print_summary(results)
|
|
|
96
96
|
puts "\n\n#{'=' * 80}"
|
|
97
97
|
puts "SUMMARY TABLE"
|
|
98
98
|
puts "=" * 80
|
|
99
|
-
puts
|
|
100
|
-
"Font", "Glyphs", "Before", "After", "Saved", "Reduction")
|
|
99
|
+
puts "Font Glyphs Before After Saved Reduction"
|
|
101
100
|
puts "-" * 80
|
|
102
101
|
|
|
103
102
|
results.each do |r|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fontisan
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01-
|
|
11
|
+
date: 2026-01-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|
|
@@ -111,14 +111,21 @@ files:
|
|
|
111
111
|
- ".rspec"
|
|
112
112
|
- ".rubocop.yml"
|
|
113
113
|
- ".rubocop_todo.yml"
|
|
114
|
+
- CHANGELOG.md
|
|
114
115
|
- Gemfile
|
|
115
116
|
- LICENSE
|
|
116
117
|
- README.adoc
|
|
117
118
|
- Rakefile
|
|
118
119
|
- benchmark/variation_quick_bench.rb
|
|
120
|
+
- docs/APPLE_LEGACY_FONTS.adoc
|
|
121
|
+
- docs/COLLECTION_VALIDATION.adoc
|
|
122
|
+
- docs/COLOR_FONTS.adoc
|
|
123
|
+
- docs/DOCUMENTATION_SUMMARY.md
|
|
119
124
|
- docs/EXTRACT_TTC_MIGRATION.md
|
|
120
125
|
- docs/FONT_HINTING.adoc
|
|
126
|
+
- docs/VALIDATION.adoc
|
|
121
127
|
- docs/VARIABLE_FONT_OPERATIONS.adoc
|
|
128
|
+
- docs/WOFF_WOFF2_FORMATS.adoc
|
|
122
129
|
- exe/fontisan
|
|
123
130
|
- fontisan.gemspec
|
|
124
131
|
- lib/fontisan.rb
|
|
@@ -203,12 +210,14 @@ files:
|
|
|
203
210
|
- lib/fontisan/models/collection_font_summary.rb
|
|
204
211
|
- lib/fontisan/models/collection_info.rb
|
|
205
212
|
- lib/fontisan/models/collection_list_info.rb
|
|
213
|
+
- lib/fontisan/models/collection_validation_report.rb
|
|
206
214
|
- lib/fontisan/models/color_glyph.rb
|
|
207
215
|
- lib/fontisan/models/color_layer.rb
|
|
208
216
|
- lib/fontisan/models/color_palette.rb
|
|
209
217
|
- lib/fontisan/models/features_info.rb
|
|
210
218
|
- lib/fontisan/models/font_export.rb
|
|
211
219
|
- lib/fontisan/models/font_info.rb
|
|
220
|
+
- lib/fontisan/models/font_report.rb
|
|
212
221
|
- lib/fontisan/models/font_summary.rb
|
|
213
222
|
- lib/fontisan/models/glyph_info.rb
|
|
214
223
|
- lib/fontisan/models/glyph_outline.rb
|
|
@@ -251,6 +260,8 @@ files:
|
|
|
251
260
|
- lib/fontisan/pipeline/strategies/preserve_strategy.rb
|
|
252
261
|
- lib/fontisan/pipeline/transformation_pipeline.rb
|
|
253
262
|
- lib/fontisan/pipeline/variation_resolver.rb
|
|
263
|
+
- lib/fontisan/sfnt_font.rb
|
|
264
|
+
- lib/fontisan/sfnt_table.rb
|
|
254
265
|
- lib/fontisan/subset/builder.rb
|
|
255
266
|
- lib/fontisan/subset/glyph_mapping.rb
|
|
256
267
|
- lib/fontisan/subset/options.rb
|
|
@@ -292,6 +303,7 @@ files:
|
|
|
292
303
|
- lib/fontisan/tables/cff2/table_reader.rb
|
|
293
304
|
- lib/fontisan/tables/cff2/variation_data_extractor.rb
|
|
294
305
|
- lib/fontisan/tables/cmap.rb
|
|
306
|
+
- lib/fontisan/tables/cmap_table.rb
|
|
295
307
|
- lib/fontisan/tables/colr.rb
|
|
296
308
|
- lib/fontisan/tables/cpal.rb
|
|
297
309
|
- lib/fontisan/tables/cvar.rb
|
|
@@ -302,20 +314,29 @@ files:
|
|
|
302
314
|
- lib/fontisan/tables/glyf/curve_converter.rb
|
|
303
315
|
- lib/fontisan/tables/glyf/glyph_builder.rb
|
|
304
316
|
- lib/fontisan/tables/glyf/simple_glyph.rb
|
|
317
|
+
- lib/fontisan/tables/glyf_table.rb
|
|
305
318
|
- lib/fontisan/tables/gpos.rb
|
|
306
319
|
- lib/fontisan/tables/gsub.rb
|
|
307
320
|
- lib/fontisan/tables/gvar.rb
|
|
308
321
|
- lib/fontisan/tables/head.rb
|
|
322
|
+
- lib/fontisan/tables/head_table.rb
|
|
309
323
|
- lib/fontisan/tables/hhea.rb
|
|
324
|
+
- lib/fontisan/tables/hhea_table.rb
|
|
310
325
|
- lib/fontisan/tables/hmtx.rb
|
|
326
|
+
- lib/fontisan/tables/hmtx_table.rb
|
|
311
327
|
- lib/fontisan/tables/hvar.rb
|
|
312
328
|
- lib/fontisan/tables/layout_common.rb
|
|
313
329
|
- lib/fontisan/tables/loca.rb
|
|
330
|
+
- lib/fontisan/tables/loca_table.rb
|
|
314
331
|
- lib/fontisan/tables/maxp.rb
|
|
332
|
+
- lib/fontisan/tables/maxp_table.rb
|
|
315
333
|
- lib/fontisan/tables/mvar.rb
|
|
316
334
|
- lib/fontisan/tables/name.rb
|
|
335
|
+
- lib/fontisan/tables/name_table.rb
|
|
317
336
|
- lib/fontisan/tables/os2.rb
|
|
337
|
+
- lib/fontisan/tables/os2_table.rb
|
|
318
338
|
- lib/fontisan/tables/post.rb
|
|
339
|
+
- lib/fontisan/tables/post_table.rb
|
|
319
340
|
- lib/fontisan/tables/sbix.rb
|
|
320
341
|
- lib/fontisan/tables/svg.rb
|
|
321
342
|
- lib/fontisan/tables/variation_common.rb
|