package harfbuzz
import (
"fmt"
ot "github.com/go-text/typesetting/font/opentype"
"github.com/go-text/typesetting/font/opentype/tables"
ucd "github.com/go-text/typesetting/internal/unicodedata"
)
var _ otComplexShaper = (*complexShaperKhmer )(nil )
type complexShaperKhmer struct {
plan khmerShapePlan
}
var khmerFeatures = [...]otMapFeature {
{ot .NewTag ('p' , 'r' , 'e' , 'f' ), ffManualJoiners | ffPerSyllable },
{ot .NewTag ('b' , 'l' , 'w' , 'f' ), ffManualJoiners | ffPerSyllable },
{ot .NewTag ('a' , 'b' , 'v' , 'f' ), ffManualJoiners | ffPerSyllable },
{ot .NewTag ('p' , 's' , 't' , 'f' ), ffManualJoiners | ffPerSyllable },
{ot .NewTag ('c' , 'f' , 'a' , 'r' ), ffManualJoiners | ffPerSyllable },
{ot .NewTag ('p' , 'r' , 'e' , 's' ), ffGlobalManualJoiners },
{ot .NewTag ('a' , 'b' , 'v' , 's' ), ffGlobalManualJoiners },
{ot .NewTag ('b' , 'l' , 'w' , 's' ), ffGlobalManualJoiners },
{ot .NewTag ('p' , 's' , 't' , 's' ), ffGlobalManualJoiners },
}
const (
khmerPref = iota
khmerBlwf
khmerAbvf
khmerPstf
khmerCfar
khmerPres
khmerAbvs
khmerBlws
khmerPsts
khmerNumFeatures
khmerBasicFeatures = khmerPres
)
func (cs *complexShaperKhmer ) collectFeatures (plan *otShapePlanner ) {
map_ := &plan .otMap
map_ .addGSUBPause (setupSyllablesKhmer )
map_ .addGSUBPause (cs .reorderKhmer )
map_ .enableFeatureExt (ot .NewTag ('l' , 'o' , 'c' , 'l' ), ffPerSyllable , 1 )
map_ .enableFeatureExt (ot .NewTag ('c' , 'c' , 'm' , 'p' ), ffPerSyllable , 1 )
i := 0
for ; i < khmerBasicFeatures ; i ++ {
map_ .addFeatureExt (khmerFeatures [i ].tag , khmerFeatures [i ].flags , 1 )
}
map_ .addGSUBPause (nil )
for ; i < khmerNumFeatures ; i ++ {
map_ .addFeatureExt (khmerFeatures [i ].tag , khmerFeatures [i ].flags , 1 )
}
}
func (complexShaperKhmer ) overrideFeatures (plan *otShapePlanner ) {
map_ := &plan .otMap
map_ .enableFeature (ot .NewTag ('c' , 'l' , 'i' , 'g' ))
map_ .disableFeature (ot .NewTag ('l' , 'i' , 'g' , 'a' ))
}
type khmerShapePlan struct {
viramaGlyph GID
maskArray [khmerNumFeatures ]GlyphMask
}
func (cs *complexShaperKhmer ) dataCreate (plan *otShapePlan ) {
var khmerPlan khmerShapePlan
khmerPlan .viramaGlyph = ^GID (0 )
for i := range khmerPlan .maskArray {
if khmerFeatures [i ].flags &ffGLOBAL == 0 {
khmerPlan .maskArray [i ] = plan .otMap .getMask1 (khmerFeatures [i ].tag )
}
}
cs .plan = khmerPlan
}
func (cs *complexShaperKhmer ) setupMasks (_ *otShapePlan , buffer *Buffer , _ *Font ) {
info := buffer .Info
for i := range info {
setKhmerProperties (&info [i ])
}
}
func setKhmerProperties(info *GlyphInfo ) {
u := info .codepoint
type_ := indicGetCategories (u )
info .complexCategory = uint8 (type_ & 0xFF )
}
func setupSyllablesKhmer(_ *otShapePlan , _ *Font , buffer *Buffer ) bool {
findSyllablesKhmer (buffer )
iter , count := buffer .syllableIterator ()
for start , end := iter .next (); start < count ; start , end = iter .next () {
buffer .unsafeToBreak (start , end )
}
return false
}
func foundSyllableKhmer(syllableType uint8 , ts , te int , info []GlyphInfo , syllableSerial *uint8 ) {
for i := ts ; i < te ; i ++ {
info [i ].syllable = (*syllableSerial << 4 ) | syllableType
}
*syllableSerial ++
if *syllableSerial == 16 {
*syllableSerial = 1
}
}
func (khmerPlan *khmerShapePlan ) reorderConsonantSyllable (buffer *Buffer , start , end int ) {
info := buffer .Info
{
mask := khmerPlan .maskArray [khmerBlwf ] |
khmerPlan .maskArray [khmerAbvf ] |
khmerPlan .maskArray [khmerPstf ]
for i := start + 1 ; i < end ; i ++ {
info [i ].Mask |= mask
}
}
numCoengs := 0
for i := start + 1 ; i < end ; i ++ {
if info [i ].complexCategory == khmSM_ex_H && numCoengs <= 2 && i +1 < end {
numCoengs ++
if info [i +1 ].complexCategory == khmSM_ex_Ra {
for j := 0 ; j < 2 ; j ++ {
info [i +j ].Mask |= khmerPlan .maskArray [khmerPref ]
}
buffer .mergeClusters (start , i +2 )
t0 := info [i ]
t1 := info [i +1 ]
copy (info [start +2 :], info [start :i ])
info [start ] = t0
info [start +1 ] = t1
if khmerPlan .maskArray [khmerCfar ] != 0 {
for j := i + 2 ; j < end ; j ++ {
info [j ].Mask |= khmerPlan .maskArray [khmerCfar ]
}
}
numCoengs = 2
}
} else if info [i ].complexCategory == khmSM_ex_VPre {
buffer .mergeClusters (start , i +1 )
t := info [i ]
copy (info [start +1 :], info [start :i ])
info [start ] = t
}
}
}
func (cs *complexShaperKhmer ) reorderSyllableKhmer (buffer *Buffer , start , end int ) {
syllableType := buffer .Info [start ].syllable & 0x0F
switch syllableType {
case khmerBrokenCluster ,
khmerConsonantSyllable :
cs .plan .reorderConsonantSyllable (buffer , start , end )
}
}
func (cs *complexShaperKhmer ) reorderKhmer (_ *otShapePlan , font *Font , buffer *Buffer ) bool {
if debugMode {
fmt .Println ("KHMER - start reordering khmer" )
}
ret := syllabicInsertDottedCircles (font , buffer , khmerBrokenCluster , khmSM_ex_DOTTEDCIRCLE , -1 , -1 )
iter , count := buffer .syllableIterator ()
for start , end := iter .next (); start < count ; start , end = iter .next () {
cs .reorderSyllableKhmer (buffer , start , end )
}
if debugMode {
fmt .Println ("KHMER - end reordering khmer" )
}
return ret
}
func (complexShaperKhmer ) decompose (c *otNormalizeContext , ab rune ) (rune , rune , bool ) {
switch ab {
case 0x17BE :
return 0x17C1 , 0x17BE , true
case 0x17BF :
return 0x17C1 , 0x17BF , true
case 0x17C0 :
return 0x17C1 , 0x17C0 , true
case 0x17C4 :
return 0x17C1 , 0x17C4 , true
case 0x17C5 :
return 0x17C1 , 0x17C5 , true
}
return ucd .Decompose (ab )
}
func (complexShaperKhmer ) compose (_ *otNormalizeContext , a , b rune ) (rune , bool ) {
if ucd .LookupGeneralCategory (a ).IsMark () {
return 0 , false
}
return ucd .Compose (a , b )
}
func (complexShaperKhmer ) marksBehavior () (zeroWidthMarks , bool ) {
return zeroWidthMarksNone , false
}
func (complexShaperKhmer ) normalizationPreference () normalizationMode {
return nmComposedDiacriticsNoShortCircuit
}
func (complexShaperKhmer ) gposTag () tables .Tag { return 0 }
func (complexShaperKhmer ) preprocessText (*otShapePlan , *Buffer , *Font ) {}
func (complexShaperKhmer ) postprocessGlyphs (*otShapePlan , *Buffer , *Font ) {
}
func (complexShaperKhmer ) reorderMarks (*otShapePlan , *Buffer , int , int ) {}
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 .