@@ -199,13 +199,12 @@ else if (!font.isEmbedded() && !font.isStandard14())
199199 // complex text layout
200200 if (font instanceof PDType0Font )
201201 {
202- PDType0Font pdType0Font = (PDType0Font ) font ;
203- GsubData gsubData = pdType0Font .getGsubData ();
202+ PDType0Font type0Font = (PDType0Font ) font ;
203+ GsubData gsubData = type0Font .getGsubData ();
204204 if (gsubData != GsubData .NO_DATA_FOUND )
205205 {
206- GsubWorker gsubWorker = gsubWorkerFactory .getGsubWorker (pdType0Font .getCmapLookup (),
207- gsubData );
208- gsubWorkers .put ((PDType0Font ) font , gsubWorker );
206+ GsubWorker gsubWorker = gsubWorkerFactory .getGsubWorker (type0Font .getCmapLookup (), gsubData );
207+ gsubWorkers .put (type0Font , gsubWorker );
209208 }
210209 else
211210 {
@@ -292,16 +291,15 @@ protected void showTextInternal(String text) throws IOException
292291 byte [] encodedText = null ;
293292 if (font instanceof PDType0Font )
294293 {
295-
296294 GsubWorker gsubWorker = gsubWorkers .get (font );
297295 if (gsubWorker != null )
298296 {
299- PDType0Font pdType0Font = (PDType0Font ) font ;
297+ PDType0Font type0Font = (PDType0Font ) font ;
300298 Set <Integer > glyphIds = new HashSet <>();
301- encodedText = encodeForGsub (gsubWorker , glyphIds , pdType0Font , text );
302- if (pdType0Font .willBeSubset ())
299+ encodedText = encodeForGsub (gsubWorker , glyphIds , type0Font , text );
300+ if (type0Font .willBeSubset ())
303301 {
304- pdType0Font .addGlyphsToSubset (glyphIds );
302+ type0Font .addGlyphsToSubset (glyphIds );
305303 }
306304 }
307305 }
@@ -706,7 +704,7 @@ public void setStrokingColor(Color color) throws IOException
706704 /**
707705 * Set the stroking color in the DeviceRGB color space. Range is 0..1.
708706 *
709- * @param r The red value
707+ * @param r The red value.
710708 * @param g The green value.
711709 * @param b The blue value.
712710 * @throws IOException If an IO error occurs while writing to the stream.
@@ -1641,41 +1639,61 @@ public void setTextRise(float rise) throws IOException
16411639 writeOperator (OperatorName .SET_TEXT_RISE );
16421640 }
16431641
1642+ /**
1643+ * Retrieve the encoded glyph IDs for the characters in the specified text, after applying any
1644+ * relevant GSUB rules. The glyph IDs used are also added to the specified glyph ID set.
1645+ *
1646+ * @param gsubWorker The GSUB worker which defines the GSUB transformations to apply.
1647+ * @param glyphIds The set of glyph IDs which is to be populated with the glyph IDs found in the
1648+ * text.
1649+ * @param font The font whose cmap table will be used to map characters to glyph IDs.
1650+ * @param text The text which is being converted from characters to glyph IDs.
1651+ * @return The encoded glyph IDs for the characters in the specified text, after applying any
1652+ * relevant GSUB rules.
1653+ * @throws IOException If there is an error during encoding.
1654+ * @throws IllegalStateException If we cannot find a glyph ID for any characters in the
1655+ * specified text.
1656+ */
16441657 private byte [] encodeForGsub (GsubWorker gsubWorker ,
1645- Set <Integer > glyphIds , PDType0Font font , String text ) throws IOException
1658+ Set <Integer > glyphIds , PDType0Font font , String text ) throws IOException
16461659 {
1647- // break the entire chunk of text into words by splitting it with space
1660+ ByteArrayOutputStream out = new ByteArrayOutputStream ( 2 * text . length ());
16481661 String [] words = StringUtil .tokenizeOnSpace (text );
1649-
1650- ByteArrayOutputStream out = new ByteArrayOutputStream ();
1651-
16521662 for (String word : words )
16531663 {
1654- if (word == null )
1664+ if (word . length () == 1 && word . isBlank ()) // PDFBOX-5823: optimization
16551665 {
1656- continue ;
1657- }
1658- if (word .length () == 1 && word .isBlank ())
1659- {
1660- out .write (font .encode (word ));
1666+ out .writeBytes (font .encode (word ));
16611667 }
16621668 else
16631669 {
16641670 glyphIds .addAll (applyGSUBRules (gsubWorker , out , font , word ));
16651671 }
16661672 }
1667-
16681673 return out .toByteArray ();
16691674 }
16701675
1671- private List <Integer > applyGSUBRules (GsubWorker gsubWorker , ByteArrayOutputStream out , PDType0Font font , String word ) throws IOException
1676+ /**
1677+ * Retrieve the glyph IDs for the characters in the specified word, after applying any relevant
1678+ * GSUB rules. The encoded glyph IDs are also written to the specified output stream.
1679+ *
1680+ * @param gsubWorker The GSUB worker which defines the GSUB transformations to apply.
1681+ * @param out The output stream to write the glyph IDs to.
1682+ * @param font The font whose cmap table will be used to map characters to glyph IDs.
1683+ * @param word The word which is being converted from characters to glyph IDs.
1684+ * @return The glyph IDs for the characters in the specified word, after applying any relevant
1685+ * GSUB rules.
1686+ * @throws IllegalStateException If we cannot find a glyph ID for any characters in the
1687+ * specified word.
1688+ */
1689+ private List <Integer > applyGSUBRules (GsubWorker gsubWorker , ByteArrayOutputStream out , PDType0Font font , String word )
16721690 {
1673- int [] codePointArray = word .codePoints ().toArray ();
1674- List <Integer > originalGlyphIds = new ArrayList <>(word . codePointCount ( 0 , word . length ()) );
1691+ int [] codePoints = word .codePoints ().toArray ();
1692+ List <Integer > originalGlyphIds = new ArrayList <>(codePoints . length );
16751693 CmapLookup cmapLookup = font .getCmapLookup ();
16761694
1677- // convert characters into glyphIds
1678- for (int codePoint : codePointArray )
1695+ // convert characters into glyph IDs
1696+ for (int codePoint : codePoints )
16791697 {
16801698 int glyphId = cmapLookup .getGlyphId (codePoint );
16811699 if (glyphId <= 0 )
@@ -1700,14 +1718,13 @@ else if (Character.isValidCodePoint(codePoint))
17001718 originalGlyphIds .add (glyphId );
17011719 }
17021720
1721+ // transform glyph IDs, write them to the output stream
17031722 List <Integer > glyphIdsAfterGsub = gsubWorker .applyTransforms (originalGlyphIds );
1704-
17051723 for (Integer glyphId : glyphIdsAfterGsub )
17061724 {
1707- out .write (font .encodeGlyphId (glyphId ));
1725+ out .writeBytes (font .encodeGlyphId (glyphId ));
17081726 }
17091727
17101728 return glyphIdsAfterGsub ;
1711-
17121729 }
17131730}
0 commit comments