@@ -225,66 +225,7 @@ byte[] convertToBytes(String text, TextRenderingOptions options) {
225225 } else {
226226 //ivs font handler,Simply judge whether it is IVS font or not
227227 if (mayContainIVS (text )) {
228- glyph = new char [len * 2 ];
229- for (int k = 0 ; k < len ; ) {
230- int baseCp ;
231- int charCount ;
232- if (k < len - 1 && Character .isHighSurrogate (text .charAt (k ))
233- && Character .isLowSurrogate (text .charAt (k + 1 ))) {
234- baseCp = Character .toCodePoint (text .charAt (k ), text .charAt (k + 1 ));
235- charCount = 2 ;
236- } else {
237- baseCp = text .charAt (k );
238- charCount = 1 ;
239- }
240-
241- int vsCp = -1 ;
242- int vsCharCount = 0 ;
243- int nextIndex = k + charCount ;
244-
245- if (nextIndex < len ) {
246- int potentialVs = text .charAt (nextIndex );
247- if (isVariationSelector (potentialVs )) {
248- vsCp = potentialVs ;
249- vsCharCount = 1 ;
250- }
251- else if (nextIndex < len - 1
252- && Character .isHighSurrogate (text .charAt (nextIndex ))
253- && Character .isLowSurrogate (text .charAt (nextIndex + 1 ))) {
254- int potentialVsPair = Character .toCodePoint (
255- text .charAt (nextIndex ), text .charAt (nextIndex + 1 ));
256- if (isVariationSelector (potentialVsPair )) {
257- vsCp = potentialVsPair ;
258- vsCharCount = 2 ;
259- }
260- }
261- }
262-
263- if (vsCp != -1 ) {
264- int [] format14Metrics = this .ttu .getFormat14MetricsTT (baseCp , vsCp );
265- if (format14Metrics != null ) {
266- int gl = format14Metrics [0 ];
267- if (!this .longTag .containsKey (gl )) {
268- this .longTag .put (gl , new int []{gl , format14Metrics [1 ], baseCp , vsCp });
269- }
270- glyph [i ++] = (char ) gl ;
271- k += charCount + vsCharCount ;
272- continue ;
273- }
274- }
275- metrics = this .ttu .getMetricsTT (baseCp );
276- if (metrics != null ) {
277- int gl = metrics [0 ];
278- if (!this .longTag .containsKey (gl )) {
279- this .longTag .put (gl , new int []{gl , metrics [1 ], baseCp });
280- }
281- glyph [i ++] = (char ) gl ;
282- }
283-
284- k += charCount ;
285- }
286- glyph = Arrays .copyOfRange (glyph , 0 , i );
287- b = convertCharsToBytes (glyph );
228+ b = handleIvsText (text , len , i );
288229 break ;
289230 }
290231 String fileName = ((TrueTypeFontUnicode ) getBaseFont ()).fileName ;
@@ -482,4 +423,121 @@ public boolean isSubset() {
482423 public void setSubset (boolean subset ) {
483424 this .subset = subset ;
484425 }
426+
427+ /**
428+ * handle ivs text
429+ */
430+ private byte [] handleIvsText (String text , int len , int startIndex ) {
431+ char [] glyph = new char [len * 2 ];
432+ int glyphIndex = startIndex ;
433+ int k = 0 ;
434+
435+ while (k < len ) {
436+ CodePointInfo baseChar = parseCodePoint (text , k , len );
437+ CodePointInfo vsChar = parseVariationSelector (text , k + baseChar .charCount , len );
438+ int skipCount = baseChar .charCount ;
439+ if (vsChar != null ) {
440+ glyphIndex = addIvsGlyph (baseChar .codePoint , vsChar .codePoint , glyph , glyphIndex );
441+ skipCount += vsChar .charCount ;
442+ } else {
443+ glyphIndex = addDefaultGlyph (baseChar .codePoint , glyph , glyphIndex );
444+ }
445+ k += skipCount ;
446+ }
447+
448+ glyph = Arrays .copyOfRange (glyph , 0 , glyphIndex );
449+ return convertCharsToBytes (glyph );
450+ }
451+
452+ private CodePointInfo parseCodePoint (String text , int index , int len ) {
453+ if (index < len - 1
454+ && Character .isHighSurrogate (text .charAt (index ))
455+ && Character .isLowSurrogate (text .charAt (index + 1 ))) {
456+ // Surrogate pair
457+ int codePoint = Character .toCodePoint (text .charAt (index ), text .charAt (index + 1 ));
458+ return new CodePointInfo (codePoint , 2 );
459+ } else {
460+ // BMP
461+ return new CodePointInfo (text .charAt (index ), 1 );
462+ }
463+ }
464+
465+ private CodePointInfo parseVariationSelector (String text , int index , int len ) {
466+ if (index >= len ) {
467+ return null ;
468+ }
469+
470+ char currentChar = text .charAt (index );
471+
472+ // single char IVS
473+ if (isVariationSelector (currentChar )) {
474+ return new CodePointInfo (currentChar , 1 );
475+ }
476+
477+ // surrogate pair IVS
478+ if (index < len - 1
479+ && Character .isHighSurrogate (currentChar )
480+ && Character .isLowSurrogate (text .charAt (index + 1 ))) {
481+ int codePoint = Character .toCodePoint (currentChar , text .charAt (index + 1 ));
482+ if (isVariationSelector (codePoint )) {
483+ return new CodePointInfo (codePoint , 2 );
484+ }
485+ }
486+
487+ return null ;
488+ }
489+
490+ private int addIvsGlyph (int baseCp , int vsCp , char [] glyph , int glyphIndex ) {
491+ int [] format14Metrics = this .ttu .getFormat14MetricsTT (baseCp , vsCp );
492+
493+ if (format14Metrics != null ) {
494+ int glyphId = format14Metrics [0 ];
495+ cacheGlyphMetrics (glyphId , format14Metrics [1 ], baseCp , vsCp );
496+ glyph [glyphIndex ++] = (char ) glyphId ;
497+ return glyphIndex ;
498+ }
499+
500+ // fallback
501+ return addDefaultGlyph (baseCp , glyph , glyphIndex );
502+ }
503+
504+ private int addDefaultGlyph (int codePoint , char [] glyph , int glyphIndex ) {
505+ int [] metrics = this .ttu .getMetricsTT (codePoint );
506+
507+ if (metrics != null ) {
508+ int glyphId = metrics [0 ];
509+ cacheGlyphMetrics (glyphId , metrics [1 ], codePoint );
510+ glyph [glyphIndex ++] = (char ) glyphId ;
511+ }
512+
513+ return glyphIndex ;
514+ }
515+
516+ /**
517+ * cache IVS glyph metrics info
518+ */
519+ private void cacheGlyphMetrics (int glyphId , int width , int baseCp ) {
520+ if (!this .longTag .containsKey (glyphId )) {
521+ this .longTag .put (glyphId , new int []{glyphId , width , baseCp });
522+ }
523+ }
524+
525+ /**
526+ * cache IVS glyph metrics info
527+ */
528+ private void cacheGlyphMetrics (int glyphId , int width , int baseCp , int vsCp ) {
529+ if (!this .longTag .containsKey (glyphId )) {
530+ this .longTag .put (glyphId , new int []{glyphId , width , baseCp , vsCp });
531+ }
532+ }
533+
534+ private static class CodePointInfo {
535+ final int codePoint ;
536+ final int charCount ;
537+
538+ CodePointInfo (int codePoint , int charCount ) {
539+ this .codePoint = codePoint ;
540+ this .charCount = charCount ;
541+ }
542+ }
485543}
0 commit comments