import { type ClassDef } from "../../layout/structures/class-def.ts"; import { type Coverage } from "../../layout/structures/coverage.ts"; import { type DeviceOrVariationIndex } from "../../layout/structures/device.ts"; import { type FeatureList, type ScriptList } from "../../layout/structures/layout-common.ts"; import { SetDigest } from "../../layout/structures/set-digest.ts"; import type { GlyphId, GlyphPosition, int16, uint16 } from "../../types.ts"; import type { Reader } from "../binary/reader.ts"; import { type ChainingContextPosLookup, type ContextPosLookup } from "./gpos-contextual.ts"; import { type CursivePosSubtable, type MarkBasePosSubtable, type MarkLigaturePosSubtable, type MarkMarkPosSubtable } from "./gpos-mark.ts"; /** GPOS lookup types */ export declare enum GposLookupType { Single = 1, Pair = 2, Cursive = 3, MarkToBase = 4, MarkToLigature = 5, MarkToMark = 6, Context = 7, ChainingContext = 8, Extension = 9 } /** Value record - positioning adjustments */ export interface ValueRecord { xPlacement?: int16; yPlacement?: int16; xAdvance?: int16; yAdvance?: int16; xPlaDevice?: DeviceOrVariationIndex; yPlaDevice?: DeviceOrVariationIndex; xAdvDevice?: DeviceOrVariationIndex; yAdvDevice?: DeviceOrVariationIndex; } /** Value format flags */ export declare const ValueFormat: { readonly XPlacement: 1; readonly YPlacement: 2; readonly XAdvance: 4; readonly YAdvance: 8; readonly XPlaDevice: 16; readonly YPlaDevice: 32; readonly XAdvDevice: 64; readonly YAdvDevice: 128; }; /** Base interface for all GPOS lookups */ export interface GposLookup { type: GposLookupType; flag: uint16; markFilteringSet?: uint16; /** Bloom filter for fast O(1) glyph rejection */ digest: SetDigest; } /** Single adjustment lookup (Type 1) */ export interface SinglePosLookup extends GposLookup { type: GposLookupType.Single; subtables: SinglePosSubtable[]; } export interface SinglePosSubtable { format: 1 | 2; coverage: Coverage; valueFormat: uint16; value?: ValueRecord; values?: ValueRecord[]; } /** Pair adjustment lookup (Type 2) - kerning */ export interface PairPosLookup extends GposLookup { type: GposLookupType.Pair; subtables: PairPosSubtable[]; } export type PairPosSubtable = PairPosFormat1 | PairPosFormat2; export interface PairPosFormat1 { format: 1; coverage: Coverage; valueFormat1: uint16; valueFormat2: uint16; pairSets: PairSet[]; } export interface PairSet { pairValueRecords: PairValueRecord[]; } export interface PairValueRecord { secondGlyph: GlyphId; value1: ValueRecord; value2: ValueRecord; } export interface PairPosFormat2 { format: 2; coverage: Coverage; valueFormat1: uint16; valueFormat2: uint16; classDef1: ClassDef; classDef2: ClassDef; class1Count: uint16; class2Count: uint16; class1Records: Class1Record[]; } export interface Class1Record { class2Records: Class2Record[]; } export interface Class2Record { value1: ValueRecord; value2: ValueRecord; } /** Cursive attachment lookup (Type 3) */ export interface CursivePosLookup extends GposLookup { type: GposLookupType.Cursive; subtables: CursivePosSubtable[]; } /** Mark-to-base attachment lookup (Type 4) */ export interface MarkBasePosLookup extends GposLookup { type: GposLookupType.MarkToBase; subtables: MarkBasePosSubtable[]; } /** Mark-to-ligature attachment lookup (Type 5) */ export interface MarkLigaturePosLookup extends GposLookup { type: GposLookupType.MarkToLigature; subtables: MarkLigaturePosSubtable[]; } /** Mark-to-mark attachment lookup (Type 6) */ export interface MarkMarkPosLookup extends GposLookup { type: GposLookupType.MarkToMark; subtables: MarkMarkPosSubtable[]; } /** Union of all GPOS lookup types */ export type AnyGposLookup = SinglePosLookup | PairPosLookup | CursivePosLookup | MarkBasePosLookup | MarkLigaturePosLookup | MarkMarkPosLookup | ContextPosLookup | ChainingContextPosLookup; /** GPOS table */ export interface GposTable { version: { major: number; minor: number; }; scriptList: ScriptList; featureList: FeatureList; lookups: AnyGposLookup[]; } export type { Anchor, MarkArray } from "./gpos-mark.ts"; export declare function parseGpos(reader: Reader): GposTable; declare function parseGposLookup(reader: Reader): AnyGposLookup | null; declare function parseValueRecord(reader: Reader, valueFormat: uint16, subtableReader?: Reader): ValueRecord; declare function parseSinglePos(reader: Reader, subtableOffsets: number[]): SinglePosSubtable[]; declare function parsePairPos(reader: Reader, subtableOffsets: number[]): PairPosSubtable[]; declare function parseExtensionLookup(reader: Reader, subtableOffsets: number[], baseProps: { flag: uint16; markFilteringSet?: uint16; }): AnyGposLookup | null; export declare function getKerning(lookup: PairPosLookup, firstGlyph: GlyphId, secondGlyph: GlyphId): { xAdvance1: number; xAdvance2: number; } | null; /** * Apply kerning directly to positions, avoiding object allocation. * Returns true if kerning was applied, false otherwise. */ export declare function applyKerningDirect(lookup: PairPosLookup, firstGlyph: GlyphId, secondGlyph: GlyphId, pos1: GlyphPosition, pos2: GlyphPosition): boolean; export declare const __testing: { parseGposLookup: typeof parseGposLookup; parseExtensionLookup: typeof parseExtensionLookup; parseSinglePos: typeof parseSinglePos; parsePairPos: typeof parsePairPos; parseValueRecord: typeof parseValueRecord; };