Class: Ucode::Glyphs::SourceConfig::CoverageAssertion

Inherits:
Object
  • Object
show all
Defined in:
lib/ucode/glyphs/source_config/coverage_assertion.rb

Overview

Development-time walker that asks: "for every assigned codepoint in this Unicode version, does at least one Tier 1 source's cmap cover it?" Codepoints with no Tier 1 coverage are recorded in a GapReport.

This is a curation review tool, not a build gate. The universal-set build (TODO 24) still runs and falls through to pillars 1-3 for any gap; this report just makes the gaps visible to a human curator.

Dependencies are injected so the walker stays pure:

  • source_map — typed Models::GlyphSourceMap from #map.
  • database — open Database for the Unicode version being audited. Supplies the assigned-codepoint ranges.
  • cmaps — any object responding to covers?(GlyphSource, Integer) => Boolean. Default: RealFonts::CmapCache, which lazily loads each referenced font's cmap via fontisan.

The walker never raises for a missing font or a failed cmap load — those codepoints are recorded as gaps. A missing font is itself a curation finding.

Instance Method Summary collapse

Constructor Details

#initialize(source_map:, database:, cmaps:, unicode_version: nil) ⇒ CoverageAssertion

Returns a new instance of CoverageAssertion.

Parameters:



43
44
45
46
47
48
49
# File 'lib/ucode/glyphs/source_config/coverage_assertion.rb', line 43

def initialize(source_map:, database:, cmaps:,
               unicode_version: nil)
  @source_map = source_map
  @database = database
  @cmaps = cmaps
  @unicode_version = unicode_version || database.ucd_version
end

Instance Method Details

#callGapReport

Returns:



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ucode/glyphs/source_config/coverage_assertion.rb', line 52

def call
  gaps = Hash.new { |h, k| h[k] = [] }
  total = 0

  @database.block_entries.each do |range|
    block_id = range.name
    sources = @source_map.sources_for(block_id)
    next if sources.empty? # uncurated block; not a gap, just unconfigured

    (range.first_cp..range.last_cp).each do |cp|
      next if sources.any? { |src| @cmaps.covers?(src, cp) }

      gaps[block_id] << cp
      total += 1
    end
  end

  GapReport.new(
    unicode_version: @unicode_version,
    generated_at: Time.now.utc.iso8601,
    gaps_by_block: gaps.freeze,
    total_gaps: total,
  )
end