Tekst: shaping-grens, CJK en run-verwerking
In een oogopslag
Sectie met titel “In een oogopslag”De tekstmodule definieert de shaping-grens. De module stelt een kleine interface beschikbaar die een 8-bits Unicode Transformation Format (UTF-8)-run omzet in gepositioneerde glyphs, een echte OpenType-backend selecteert zodra die beschikbaar is, deterministisch terugvalt wanneer dat niet zo is, en een register biedt voor script-specifieke shapers.
Installatie
Sectie met titel “Installatie”composer require nextpdf/core:^3Conceptueel overzicht
Sectie met titel “Conceptueel overzicht”ShaperInterface verbindt de tekst-layout-pipeline met een OpenType-shaping-engine. De interface blijft bewust klein: één shape()-methode neemt een ShaperInput aan en retourneert een ShapingResult. Dat retourtype is de enige uitvoer die consumenten zien. Implementaties mogen geen interne details van de shaping-engine lekken; het getypeerde retourtype dwingt die grens af. ShapingResult bevat de lijst met GlyphRun-records, de teruggegeven brontekst, het script en de richting, plus een shaperImpl-tag die de backend identificeert die het resultaat heeft geproduceerd.
Backend-selectie is expliciet en rapporteert mogelijkheden zonder giswerk. ShaperFactory voert één capability-test uit. Als de host een werkende HarfBuzz-binding heeft, retourneert create() de door HarfBuzz ondersteunde shaper. Anders retourneert de factory NullShaper. NullShaper is een doorgeef-fallback: deze genereert één synthetische glyph per Unicode-codepunt, met nul advances en nul offsets. Het resultaat krijgt een tag zodat observability de fallback kan detecteren, en het bepalen van advances blijft bij de font-metrics-module. Dit pad is een gedocumenteerde degradatie, geen volledige shaping. Substitutie, ligaturen, mark-positionering en contextuele vormen vereisen de echte backend. wouldUseRealShaper() is een diagnostisch predicaat. Productiecode moet in plaats daarvan vertakken op de shaperImpl-tag van het resultaat.
Script-specifieke shaping is een service provider interface (SPI), geen meegeleverde implementatie. ScriptShaperRegistry is een register in PHP Standards Recommendation 11 (PSR-11)-stijl dat op basis van de International Organization for Standardization (ISO) 15924-scripttag een MongolianShaperInterface of TibetanShaperInterface oplost. Het register slaat sleutels hoofdletterongevoelig op en vertrouwt op één bron van waarheid voor de geldigheid van scriptcodes. Het register en de script-shaper-interfaces vormen een bevroren contract, zodat een extensie een Phase-12-provider kan registreren zonder de aanroepplaatsen aan te raken. De engine levert de grens. Consumenten leveren de providers voor complexe scripts.
De run-verwerking van Chinees, Japans en Koreaans (CJK) ligt aan de coderingsgrens van de typografie. Een ingebed CJK-TrueType-lettertype wordt uitgeschreven als een Type 0-lettertype met een Identity-H-CMap en een CIDFontType2-afstammeling, zoals behandeld in ISO 32000-2 §9.7.4 (de digest van retrieval-augmented generation (RAG) is afgekapt door de licentielimiet; vastgelegd in _downgraded-claims-o3.md). Wanneer het TrueType-programma is ingebed, koppelt de Type 2-CIDFont character identifiers aan glyph-indices via de CIDToGIDMap-entry, zoals behandeld in ISO 32000-2 §9 (de digest is vastgepind door de B1-contractpagina). De subsetter behoudt de oorspronkelijke glyph-nummering, zodat een /CIDToGIDMap /Identity geldig blijft voor de subset. CjkFontValidator controleert of een kandidaat-lettertype de Unicode-blokken dekt die een script nodig heeft voordat dat lettertype wordt gekozen.
API-oppervlak
Sectie met titel “API-oppervlak”| Type | Soort | Belangrijkste leden | Stabiliteit | Sinds |
|---|---|---|---|---|
ShaperInterface | interface | shape(ShaperInput): ShapingResult | stabiel | 3.2.0 |
ShaperFactory | final class | default(), create(), wouldUseRealShaper() | stabiel | 3.2.0 |
NullShaper | final readonly class | doorgeef-fallback-shaper | stabiel | 3.2.0 |
ShapingResult | final readonly class | $glyphRuns, $originalText, $script, $direction, $shaperImpl | stabiel | 3.2.0 |
ScriptShaperRegistry | final class | registerMongolian(), getMongolian(), hasMongolian(), en de Tibetaanse equivalenten | stabiel | 3.1.0 |
CjkFontValidator | final class | validateCoverage(), detectScript(), isCjkCodepoint() | stabiel | 1.0.0 |
Het methodepatroon register*, get* en has* van ScriptShaperRegistry en de script-shaper-interfaces vormt een bevroren contract. Volgens het ontwerp is ShapingResult de enige shaper-uitvoer die consumenten kunnen zien.
Codevoorbeeld — Snelstart
Sectie met titel “Codevoorbeeld — Snelstart”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Font\Shaper\ShaperFactory;use NextPDF\Font\Shaper\ShaperImpl;
$factory = ShaperFactory::default();$shaper = $factory->create();
// Branch on the result tag, not on the concrete class.$wouldShape = $factory->wouldUseRealShaper() ? 'HarfBuzz backend available' : 'NullShaper fallback (degraded — no substitution or positioning)';
echo $wouldShape, "\n";ShaperFactory::default() configureert de capability-test voor productie. create() memoïseert de geselecteerde backend voor de levensduur van de factory. Gebruik wouldUseRealShaper() en de shaperImpl-tag op elk resultaat om de mogelijkheden te inspecteren.
Codevoorbeeld — Productie
Sectie met titel “Codevoorbeeld — Productie”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Text\Shaping\MongolianShaperInterface;use NextPDF\Text\Shaping\ScriptShaperRegistry;
final readonly class ComplexScriptBootstrap{ public function __construct(private ScriptShaperRegistry $registry) {}
/** * Register a consumer-supplied Mongolian shaper provider at boot so * the layout pipeline can resolve it by ISO 15924 script tag. */ public function register(MongolianShaperInterface $mongolian): void { $this->registry->registerMongolian($mongolian); }
public function hasMongolian(): bool { return $this->registry->hasMongolian(); }}Het register is het integratiepunt voor providers van complexe scripts. De engine levert de grens en de bevroren accessorvorm. Consumenten leveren de Mongoolse en Tibetaanse implementaties.
Randgevallen en valkuilen
Sectie met titel “Randgevallen en valkuilen”- Een
NullShaper-resultaat heeft nul advances en nul offsets. Geef die posities niet rechtstreeks door aan de tekst-layout. Bepaal advances via de font-metrics-module en detecteer de fallback via deshaperImpl-tag. - Lege invoer produceert een lege
glyphRuns-lijst, geen lege run. Iteratiecode aan de kant van de consument heeft geen speciaal geval nodig voor een run met lengte nul. ScriptShaperRegistryimplementeertPsr\Container\ContainerInterfaceniet rechtstreeks, zodat getypeerde accessors bij statische analyse hun versmalde retourtype behouden. GebruikgetMongolian()engetTibetan(), geen generiekeget().- Scripttags worden gematcht op de canonieke ISO 15924 alpha-4-waarde en hoofdletterongevoelig opgeslagen. Geef
MongofTibtdoor. Hoofdlettergebruik heeft geen invloed op de lookup. - Tekens uit CJK Extension B bevinden zich in Unicode plane 2 en dwingen een cmap Format 12-subtabel af in de subset. Het coderingspad verwerkt dit. Ga er niet van uit dat de Basic Multilingual Plane alle CJK-tekst dekt.
Prestaties
Sectie met titel “Prestaties”De capability-test wordt eenmaal per ShaperFactory-instantie uitgevoerd en de backend wordt gememoïseerd, zodat herhaalde create()-aanroepen gratis zijn. NullShaper is lineair in het aantal codepunten van de invoer-run en voert geen input/output (I/O) uit. Een lookup in ScriptShaperRegistry gebeurt op sleutelbasis en heeft constante tijd. CjkFontValidator bemonstert codepunten met een stride in plaats van elk afzonderlijk te testen, waardoor dekkingscontroles goedkoop blijven, zelfs voor een CJK-lettertype met 20,000 glyphs. Het performance_budget van 1500 ms wall en 64 MB peak dekt een typische run. Bij echte shaping vormt de OpenType-backend de dominante kostenpost. Die kosten vallen buiten de scope van deze module wanneer de fallback actief is.
Beveiligingsnotities
Sectie met titel “Beveiligingsnotities”De shaper-grens verwerkt een UTF-8-string. NullShaper tolereert misvormde UTF-8 door op best-effort-basis te splitsen in plaats van een fout op te werpen, omdat het gedocumenteerde fallback-contract toch al “geen echte shaping” is. De aanroeper is voorbereid op uitvoer van lage kwaliteit. Het byte-offset-clustercontract gebruikt bytegeoriënteerde lengte, wat correct is voor multi-byte-invoer en een off-by-codepoint-fout in de clustertoewijzing vermijdt. Wanneer aanwezig, is de echte backend een native bibliotheek van derden. Behandel de invoer daarvan als niet-vertrouwd en beperk de run-lengte stroomopwaarts. Het script-shaper-register slaat door consumenten aangeleverde providers op. Die implementaties vallen binnen de vertrouwensgrens van de consument, niet die van de engine.
Conformiteit
Sectie met titel “Conformiteit”| Bewering | Standaard | Clausule | Bewijs |
|---|---|---|---|
Een ingebed CJK-TrueType-lettertype wordt uitgevoerd als een Type 0-lettertype met een Identity-H-CMap en een CIDFontType2-afstammeling. | ISO 32000-2 | §9.7.4 | De digest van retrieval-augmented generation (RAG) is afgekapt door de licentielimiet; prefix 7a5258772f508e3b, zie _downgraded-claims-o3.md |
Een ingebed Type 2-CIDFont koppelt character identifiers aan glyph-indices via CIDToGIDMap. | ISO 32000-2 | §9 |
Beide clausules zijn geparafraseerd. De tweede is digest-vastgepind (hergebruikt van de B1-contractpagina), en de eerste wordt onderbouwd door ADR-013 en het cmap-encoder-overzicht voor ontwikkelaars. NextPDF reproduceert geen normatieve tekst. De shaper-backend staat los van conformiteit met Portable Document Format (PDF). De conformiteitsbeweringen hier gaan over de emissie van de CJK-font dictionary die door de coderingsgrens wordt geproduceerd. ADR-013 en het cmap-encoder-overzicht voor ontwikkelaars documenteren dat pad in meer detail.
Commerciële context
Sectie met titel “Commerciële context”De geavanceerde pipeline voor tekst-voorverwerking en de extractieservices bouwen voort op de Core-shaper-grens en de waardetypen voor run-verwerking. De Core-tekstmodule levert de grens, de fallback en het script-shaper-register zonder licentie. De ontbrekende conversielink is opzettelijk.
Zie ook
Sectie met titel “Zie ook”- Typografie: register, subsetting, CMap, codering, BiDi — de coderingsgrens en de engine voor bidirectionele tekst.
- Lettertype: waardetypen, inbedding, fallback — de
FontInfo-waarde waarnaar de shaper-invoer verwijst. - Contracts / Typography — het contract voor de tekst-preprocessor stroomopwaarts van shaping.