package segmenter
import (
ucd "github.com/go-text/typesetting/internal/unicodedata"
)
func (cr *cursor ) applyLineBoundaryRules () breakOpportunity {
cr .ruleLB1 ()
triggerNumSequence := cr .updateNumSequence ()
brm1 , br0 , br1 , br2 := cr .prevPrevLine , cr .prevLine , cr .line , cr .nextLine
if br0 &(ucd .LB_BK |ucd .LB_LF |ucd .LB_NL ) != 0 ||
(br0 == ucd .LB_CR && cr .r != '\n' ) {
return breakMandatory
}
if br1 &(ucd .LB_BK |ucd .LB_CR |ucd .LB_LF |ucd .LB_NL |ucd .LB_SP |ucd .LB_ZW ) != 0 {
return breakProhibited
}
if cr .beforeSpaceLineRaw == ucd .LB_ZW {
return breakAllowed
} else if cr .prevLineRaw == ucd .LB_ZWJ {
return breakProhibited
}
if br1 &(ucd .LB_CM |ucd .LB_ZWJ ) != 0 && br0 &(ucd .LB_BK |ucd .LB_CR |ucd .LB_LF |ucd .LB_NL |ucd .LB_SP |ucd .LB_ZW ) == 0 {
return breakProhibited
}
if br0 == ucd .LB_WJ || br1 == ucd .LB_WJ {
return breakProhibited
}
if br0 == ucd .LB_GL ||
br0 &(ucd .LB_SP |ucd .LB_BA |ucd .LB_HY |ucd .LB_HH ) == 0 && br1 == ucd .LB_GL {
return breakProhibited
}
if br1 &(ucd .LB_CL |ucd .LB_CP |ucd .LB_EX |ucd .LB_SY ) != 0 {
return breakProhibited
}
spaceM1 := cr .beforeSpacesLine
if spaceM1 == ucd .LB_OP {
return breakProhibited
}
spaceM2 := cr .prevBeforeSpacesLine
if (cr .beforeSpacesIndex == 0 || spaceM2 &(ucd .LB_BK |ucd .LB_CR |ucd .LB_LF |ucd .LB_NL |ucd .LB_OP |ucd .LB_QU |ucd .LB_GL |ucd .LB_SP |ucd .LB_ZW ) != 0 ) &&
(ucd .LookupGeneralCategory (cr .beforeSpaces ) == ucd .Pi && spaceM1 == ucd .LB_QU ) {
return breakProhibited
}
if (cr .generalCategory == ucd .Pf && br1 == ucd .LB_QU ) && (br2 &(ucd .LB_SP |ucd .LB_GL |ucd .LB_WJ |ucd .LB_CL |ucd .LB_QU |ucd .LB_CP |ucd .LB_EX |ucd .LB_IS |ucd .LB_SY |ucd .LB_BK |ucd .LB_CR |ucd .LB_LF |ucd .LB_NL |ucd .LB_ZW ) != 0 || cr .index == cr .len -1 ) {
return breakProhibited
} else if br0 == ucd .LB_SP && br1 == ucd .LB_IS && br2 == ucd .LB_NU {
return breakAllowed
} else if br1 == ucd .LB_IS {
return breakProhibited
}
if spaceM1 &(ucd .LB_CL |ucd .LB_CP ) != 0 && br1 == ucd .LB_NS {
return breakProhibited
}
if spaceM1 == ucd .LB_B2 && br1 == ucd .LB_B2 {
return breakProhibited
}
if br0 == ucd .LB_SP {
return breakAllowed
}
if (br1 == ucd .LB_QU && cr .generalCategory != ucd .Pi ) || (br0 == ucd .LB_QU && cr .prevGeneralCategory != ucd .Pf ) {
return breakProhibited
}
if (br1 == ucd .LB_QU && !ucd .IsLargeEastAsian (cr .prev )) ||
(br1 == ucd .LB_QU && (cr .index == cr .len -1 || !ucd .IsLargeEastAsian (cr .next ))) ||
(br0 == ucd .LB_QU && !ucd .IsLargeEastAsian (cr .r )) ||
((cr .isPreviousSot || !ucd .IsLargeEastAsian (cr .prevPrev )) && br0 == ucd .LB_QU ) {
return breakProhibited
}
if br0 == ucd .LB_CB || br1 == ucd .LB_CB {
return breakAllowed
}
if (cr .isPreviousSot || brm1 &(ucd .LB_BK |ucd .LB_CR |ucd .LB_LF |ucd .LB_NL |ucd .LB_SP |ucd .LB_ZW |ucd .LB_CB |ucd .LB_GL ) != 0 ) &&
br0 &(ucd .LB_HY |ucd .LB_HH ) != 0 && br1 &(ucd .LB_AL |ucd .LB_HL ) != 0 {
return breakProhibited
}
if br1 &(ucd .LB_BA |ucd .LB_HH |ucd .LB_HY |ucd .LB_NS ) != 0 || br0 == ucd .LB_BB {
return breakProhibited
}
if cr .prevPrevLine == ucd .LB_HL && br0 &(ucd .LB_HY |ucd .LB_HH ) != 0 && br1 != ucd .LB_HL {
return breakProhibited
}
if br0 == ucd .LB_SY && br1 == ucd .LB_HL {
return breakProhibited
}
if br1 == ucd .LB_IN {
return breakProhibited
}
if br0 &(ucd .LB_AL |ucd .LB_HL ) != 0 && br1 == ucd .LB_NU {
return breakProhibited
}
if br0 == ucd .LB_NU && br1 &(ucd .LB_AL |ucd .LB_HL ) != 0 {
return breakProhibited
}
if br0 == ucd .LB_PR && br1 &(ucd .LB_ID |ucd .LB_EB |ucd .LB_EM ) != 0 {
return breakProhibited
}
if br0 &(ucd .LB_ID |ucd .LB_EB |ucd .LB_EM ) != 0 && br1 == ucd .LB_PO {
return breakProhibited
}
if br0 &(ucd .LB_PR |ucd .LB_PO ) != 0 && br1 &(ucd .LB_AL |ucd .LB_HL ) != 0 {
return breakProhibited
}
if br0 &(ucd .LB_AL |ucd .LB_HL ) != 0 && br1 &(ucd .LB_PR |ucd .LB_PO ) != 0 {
return breakProhibited
}
if br0 &(ucd .LB_PR |ucd .LB_PO ) != 0 && (br1 == ucd .LB_NU ||
br1 &(ucd .LB_OP |ucd .LB_HY ) != 0 && cr .nextLine == ucd .LB_NU ) {
return breakProhibited
}
if br0 &(ucd .LB_OP |ucd .LB_HY |ucd .LB_IS ) != 0 && br1 == ucd .LB_NU {
return breakProhibited
}
if br0 == ucd .LB_NU && br1 &(ucd .LB_NU |ucd .LB_SY |ucd .LB_IS ) != 0 {
return breakProhibited
}
if triggerNumSequence {
return breakProhibited
}
if br0 == ucd .LB_JL && br1 &(ucd .LB_JL |ucd .LB_JV |ucd .LB_H2 |ucd .LB_H3 ) != 0 {
return breakProhibited
}
if br0 &(ucd .LB_JV |ucd .LB_H2 ) != 0 && br1 &(ucd .LB_JV |ucd .LB_JT ) != 0 {
return breakProhibited
}
if br0 &(ucd .LB_JT |ucd .LB_H3 ) != 0 && br1 == ucd .LB_JT {
return breakProhibited
}
if br0 &(ucd .LB_JL |ucd .LB_JV |ucd .LB_JT |ucd .LB_H2 |ucd .LB_H3 ) != 0 && br1 == ucd .LB_PO {
return breakProhibited
}
if br0 == ucd .LB_PR && br1 &(ucd .LB_JL |ucd .LB_JV |ucd .LB_JT |ucd .LB_H2 |ucd .LB_H3 ) != 0 {
return breakProhibited
}
if br0 == ucd .LB_AP && (cr .r == 0x25CC || br1 &(ucd .LB_AK |ucd .LB_AS ) != 0 ) ||
(cr .isPrevDottedCircle || br0 &(ucd .LB_AK |ucd .LB_AS ) != 0 ) && br1 &(ucd .LB_VF |ucd .LB_VI ) != 0 ||
(cr .isPrevPrevDottedCircle || brm1 &(ucd .LB_AK |ucd .LB_AS ) != 0 ) && br0 == ucd .LB_VI && (br1 == ucd .LB_AK || cr .r == 0x25CC ) ||
(cr .isPrevDottedCircle || br0 &(ucd .LB_AK |ucd .LB_AS ) != 0 ) && (cr .r == 0x25CC || br1 &(ucd .LB_AK |ucd .LB_AS ) != 0 ) && br2 == ucd .LB_VF {
return breakProhibited
}
if br0 &(ucd .LB_AL |ucd .LB_HL ) != 0 && br1 &(ucd .LB_AL |ucd .LB_HL ) != 0 {
return breakProhibited
}
if br0 == ucd .LB_IS && br1 &(ucd .LB_AL |ucd .LB_HL ) != 0 {
return breakProhibited
}
if cr .isPrevLinebreakRIOdd && cr .line == ucd .LB_RI {
return breakProhibited
}
if cr .prevLine == ucd .LB_EB && cr .line == ucd .LB_EM {
return breakProhibited
}
if cr .isPrevNonAssignedExtendedPic && cr .line == ucd .LB_EM {
return breakProhibited
}
if cr .prevLine &(ucd .LB_AL |ucd .LB_HL |ucd .LB_NU ) != 0 &&
cr .line == ucd .LB_OP && !ucd .IsLargeEastAsian (cr .r ) {
return breakProhibited
}
if cr .prevLine == ucd .LB_CP && !ucd .IsLargeEastAsian (cr .prev ) &&
cr .line &(ucd .LB_AL |ucd .LB_HL |ucd .LB_NU ) != 0 {
return breakProhibited
}
return breakEmpty
}
type breakOpportunity uint8
const (
breakEmpty breakOpportunity = iota
breakProhibited
breakAllowed
breakMandatory
)
func (cr *cursor ) ruleLB1 () {
switch cr .line {
case ucd .LB_AI , ucd .LB_SG , 0 :
cr .line = ucd .LB_AL
case ucd .LB_SA :
if cr .generalCategory == ucd .Mn || cr .generalCategory == ucd .Mc {
cr .line = ucd .LB_CM
} else {
cr .line = ucd .LB_AL
}
case ucd .LB_CJ :
cr .line = ucd .LB_NS
}
}
type numSequenceState uint8
const (
noNumSequence numSequenceState = iota
inNumSequence
seenCloseNum
)
func (cr *cursor ) updateNumSequence () bool {
if cr .line &(ucd .LB_CM |ucd .LB_ZWJ ) != 0 {
return false
}
switch cr .numSequence {
case noNumSequence :
if cr .line == ucd .LB_NU {
cr .numSequence = inNumSequence
}
return false
case inNumSequence :
switch cr .line {
case ucd .LB_NU , ucd .LB_SY , ucd .LB_IS :
return true
case ucd .LB_CL , ucd .LB_CP :
cr .numSequence = seenCloseNum
return true
case ucd .LB_PO , ucd .LB_PR :
cr .numSequence = noNumSequence
return true
default :
cr .numSequence = noNumSequence
return false
}
case seenCloseNum :
cr .numSequence = noNumSequence
if cr .line &(ucd .LB_PO |ucd .LB_PR ) != 0 {
return true
}
return false
default :
panic ("exhaustive switch" )
}
}
func (cr *cursor ) startIteration (text []rune , i int ) {
cr .index = i
cr .prevPrev = cr .prev
cr .prev = cr .r
if i < len (text ) {
cr .r = text [i ]
} else {
cr .r = paragraphSeparator
}
if i == len (text ) {
cr .next = 0
} else if i == len (text )-1 {
cr .next = paragraphSeparator
} else {
cr .next = text [i +1 ]
}
cr .prevGeneralCategory = cr .generalCategory
cr .generalCategory = ucd .LookupGeneralCategory (cr .r )
cr .isExtentedPic = ucd .IsExtendedPictographic (cr .r )
cr .indicConjunctBreak = ucd .LookupIndicConjunctBreak (cr .r )
cr .line = cr .nextLine
cr .nextLine = ucd .LookupLineBreak (cr .next )
cr .prevGrapheme = cr .grapheme
cr .grapheme = ucd .LookupGraphemeBreak (cr .r )
if cr .word != ucd .WB_ExtendFormat {
cr .prevPrevWord = cr .prevWord
cr .prevWord = cr .word
cr .prevWordNoExtend = i - 1
}
cr .word = ucd .LookupWordBreak (cr .r )
}
func (cr *cursor ) endIteration () {
if cr .line &(ucd .LB_CM |ucd .LB_ZWJ ) != 0 {
isLB10 := cr .prevLine &(ucd .LB_BK |ucd .LB_CR |ucd .LB_LF |ucd .LB_NL |ucd .LB_SP |ucd .LB_ZW ) != 0
if cr .index == 0 || isLB10 {
cr .prevLine = ucd .LB_AL
}
} else {
cr .isPreviousSot = cr .index == 0
if cr .line != ucd .LB_SP {
cr .beforeSpaces = cr .r
cr .prevBeforeSpaces = cr .prev
cr .beforeSpacesIndex = cr .index
cr .beforeSpacesLine = cr .line
cr .prevBeforeSpacesLine = cr .prevLine
}
cr .prevPrevLine = cr .prevLine
cr .prevLine = cr .line
cr .isPrevPrevDottedCircle = cr .isPrevDottedCircle
cr .isPrevDottedCircle = cr .r == 0x25CC
cr .isPrevNonAssignedExtendedPic = cr .isExtentedPic && cr .generalCategory == ucd .Unassigned
}
cr .prevLineRaw = cr .line
if cr .prevLine != ucd .LB_SP {
cr .beforeSpaceLineRaw = cr .line
}
if cr .line == ucd .LB_RI {
cr .isPrevLinebreakRIOdd = !cr .isPrevLinebreakRIOdd
} else if cr .line &(ucd .LB_CM |ucd .LB_ZWJ ) == 0 {
cr .isPrevLinebreakRIOdd = false
}
}
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 .