@@ -257,7 +257,7 @@ export interface ShapingAttrs {
257257 style : Style ;
258258}
259259
260- const hyphenCache = new Map < string , Int32Array > ( ) ;
260+ const hyphenCache = new Map < string , { glyphs : Int32Array ; codepoint : string } > ( ) ;
261261
262262export function getFontMetrics ( inline : Inline ) {
263263 const strutCascade = getLangCascade ( inline . style , 'en' ) ;
@@ -277,18 +277,18 @@ function loadHyphen(item: ShapedItem) {
277277 const key = createHyphenCacheKey ( item ) ;
278278
279279 if ( ! hyphenCache . has ( key ) ) {
280- hyphenCache . set ( key , new Int32Array ( 0 ) ) ;
280+ hyphenCache . set ( key , { codepoint : '' , glyphs : new Int32Array ( 0 ) } ) ;
281281
282- for ( const hyphen of HyphenCodepointsToTry ) {
282+ for ( const codepoint of HyphenCodepointsToTry ) {
283283 const buf = hb . createBuffer ( ) ;
284284 buf . setClusterLevel ( 1 ) ;
285- buf . addText ( hyphen ) ;
285+ buf . addText ( codepoint ) ;
286286 buf . guessSegmentProperties ( ) ;
287287 hb . shape ( item . face . hbfont , buf ) ;
288288 const glyphs = buf . extractGlyphs ( ) ;
289289 buf . destroy ( ) ;
290290 if ( glyphs [ G_ID ] ) {
291- hyphenCache . set ( key , glyphs ) ;
291+ hyphenCache . set ( key , { codepoint , glyphs} ) ;
292292 break ;
293293 }
294294 }
@@ -1700,7 +1700,24 @@ export class Paragraph {
17001700 this . buffer = EmptyBuffer ;
17011701 }
17021702
1703- slice ( start : number , end : number ) {
1703+ sliceRenderText ( item : ShapedItem , start : number , end : number ) {
1704+ if ( this . ifc . hasSoftHyphen ( ) ) {
1705+ const mark = item . end ( ) - 1 ;
1706+ const hyphen = getHyphen ( item ) ;
1707+ if (
1708+ mark >= start &&
1709+ mark < end &&
1710+ this . string [ mark ] === '\u00ad' && // softHyphenCharacter
1711+ hyphen
1712+ ) {
1713+ const first = this . string . slice ( start , mark ) ;
1714+ const second = this . string . slice ( mark + 1 , end ) ;
1715+ const glyphIndex = item . attrs . level & 1 ? 0 : item . glyphs . length - G_SZ ;
1716+ if ( hyphen . glyphs [ G_ID ] === item . glyphs [ glyphIndex + G_ID ] ) {
1717+ return first + hyphen . codepoint + second ;
1718+ }
1719+ }
1720+ }
17041721 return this . string . slice ( start , end ) ;
17051722 }
17061723
@@ -1715,7 +1732,7 @@ export class Paragraph {
17151732
17161733 this . items . splice ( itemIndex + 1 , 0 , right ) ;
17171734 if ( this . string [ offset - 1 ] === '\u00ad' /* softHyphenCharacter */ ) {
1718- const hyphen = getHyphen ( left ) ;
1735+ const hyphen = getHyphen ( left ) ?. glyphs ;
17191736 if ( hyphen ?. length ) {
17201737 const glyphs = new Int32Array ( left . glyphs . length + hyphen . length ) ;
17211738 if ( left . attrs . level & 1 ) {
@@ -1733,10 +1750,6 @@ export class Paragraph {
17331750 }
17341751 left . glyphs = glyphs ;
17351752 }
1736- // TODO 1: this sucks, but it's probably still better than using a Uint16Array
1737- // and having to convert back to strings for the browser canvas backend
1738- // TODO 2: the hyphen character could also be HYPHEN MINUS
1739- this . string = this . string . slice ( 0 , offset - 1 ) + /* U+2010 */ '‐' + this . string . slice ( offset ) ;
17401753 }
17411754 }
17421755
@@ -2303,7 +2316,7 @@ export class Paragraph {
23032316 bfc . getLocalVacancyForLine ( bfc , blockOffset , blockSize , vacancy ) ;
23042317
23052318 if ( this . string [ mark . position - 1 ] === '\u00ad' && ! mark . isBreakForced ) {
2306- const glyphs = getHyphen ( item ) ;
2319+ const glyphs = getHyphen ( item ) ?. glyphs ;
23072320 const { face : { hbface : { upem} } , attrs : { style : { fontSize} } } = item ;
23082321 if ( glyphs ?. length ) {
23092322 let w = 0 ;
0 commit comments