Source File
set_digest.go
Belonging Package
github.com/go-text/typesetting/harfbuzz
package harfbuzzimport ()// ported from src/hb-set-digest.hh Copyright © 2012 Google, Inc. Behdad Esfahbodconst (maskBits = 8 * 8 // 4 = size(setDigestLowestBits)mb1 = maskBits - 1one = maskT(1)all = ^maskT(0))type setType = gIDtype maskT uint64func addRangeTo( *maskT, , setType, uint) {if (>>)-(>>) >= mb1 {* = ^maskT(0)} else {:= one << (( >> ) & mb1):= one << (( >> ) & mb1)var maskTif < {= 1}* |= + ( - ) -}}/* This is a combination of digests that performs "best".* There is not much science to this: it's a result of intuition* and testing. */const (shift0 = 4shift1 = 0shift2 = 6)// The set-digests implement "filters" that support "approximate// member query". Conceptually these are like Bloom Filter and// Quotient Filter, however, much smaller, faster, and designed// to fit the requirements of our uses for glyph coverage queries.//// Our filters are highly accurate if the lookup covers fairly local// set of glyphs, but fully flooded and ineffective if coverage is// all over the place.//// The way these are used is that the filter is first populated by// a lookup's or subtable's Coverage table(s), and then when we// want to apply the lookup or subtable to a glyph, before trying// to apply, we ask the filter if the glyph may be covered. If it's// not, we return early. We can also match a digest against another// digest.//// We use these filters at three levels:// - If the digest for all the glyphs in the buffer as a whole// does not match the digest for the lookup, skip the lookup.// - For each glyph, if it doesn't match the lookup digest,// skip it.// - For each glyph, if it doesn't match the subtable digest,// skip it.//// The filter we use is a combination of three bits-pattern// filters. A bits-pattern filter checks a number of bits (5 or 6)// of the input number (glyph-id in most cases) and checks whether// its pattern is amongst the patterns of any of the accepted values.// The accepted patterns are represented as a "long" integer. Each// check is done using four bitwise operations only.type setDigest [3]maskT// add adds the given rune to the set.func ( *setDigest) ( setType) {[0] |= one << (( >> shift0) & mb1)[1] |= one << (( >> shift1) & mb1)[2] |= one << (( >> shift2) & mb1)}// addRange adds the given, inclusive range to the set,// in an efficient manner.func ( *setDigest) (, setType) {if [0] == all || [1] == all || [2] == all {return}addRangeTo(&[0], , , shift0)addRangeTo(&[1], , , shift1)addRangeTo(&[2], , , shift2)}// addArray is a convenience method to add// many runes.func ( *setDigest) ( []setType) {for , := range {.add()}}// mayHave performs an "approximate member query": if the return value// is `false`, then it is certain that `g` is not in the set.// Otherwise, we don't kwow, it might be a false positive.// Note that runes in the set are certain to return `true`.func ( setDigest) ( setType) bool {return [0]&(one<<((>>shift0)&mb1)) != 0 &&[1]&(one<<((>>shift1)&mb1)) != 0 &&[2]&(one<<((>>shift2)&mb1)) != 0}func ( setDigest) ( setDigest) bool {return [0]&[0] != 0 && [1]&[1] != 0 && [2]&[2] != 0}func ( *setDigest) ( tables.Coverage) {switch cov := .(type) {case tables.Coverage1:.addArray(.Glyphs)case tables.Coverage2:for , := range .Ranges {.addRange(.StartGlyphID, .EndGlyphID)}}}
![]() |
The pages are generated with Golds v0.8.7. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |