1717package org .sejda .sambox .pdmodel .font ;
1818
1919import static java .util .Objects .nonNull ;
20+ import static java .util .Optional .ofNullable ;
2021
2122import java .io .IOException ;
2223import java .io .InputStream ;
3132import org .sejda .sambox .cos .COSNumber ;
3233import org .sejda .sambox .cos .COSObjectable ;
3334import org .sejda .sambox .cos .COSStream ;
35+ import org .sejda .sambox .pdmodel .common .PDDictionaryWrapper ;
3436import org .sejda .sambox .util .Vector ;
3537import org .slf4j .Logger ;
3638import org .slf4j .LoggerFactory ;
4446 *
4547 * @author Ben Litchfield
4648 */
47- public abstract class PDCIDFont implements COSObjectable , PDFontLike , PDVectorFont
49+ public abstract class PDCIDFont extends PDDictionaryWrapper
50+ implements COSObjectable , PDFontLike , PDVectorFont
4851{
4952 private static final Logger LOG = LoggerFactory .getLogger (PDCIDFont .class );
5053
5154 protected final PDType0Font parent ;
5255
5356 private Map <Integer , Float > widths ;
54- private float defaultWidth ;
57+ private float defaultWidth = - 1F ;
5558 private float averageWidth ;
5659
5760 private final Map <Integer , Float > verticalDisplacementY = new HashMap <>(); // w1y
5861 private final Map <Integer , Vector > positionVectors = new HashMap <>(); // v
5962 private float [] dw2 = new float [] { 880 , -1000 };
6063
61- protected final COSDictionary dict ;
62- private PDFontDescriptor fontDescriptor ;
63-
6464 /**
6565 * Constructor.
6666 *
6767 * @param fontDictionary The font dictionary according to the PDF specification.
6868 */
6969 PDCIDFont (COSDictionary fontDictionary , PDType0Font parent )
7070 {
71- this . dict = fontDictionary ;
71+ super ( fontDictionary ) ;
7272 this .parent = parent ;
7373 readWidths ();
7474 readVerticalDisplacements ();
@@ -78,7 +78,7 @@ private void readWidths()
7878 {
7979 // see 9.7.4.3, "Glyph Metrics in CIDFonts"
8080 widths = new HashMap <>();
81- COSArray wArray = dict .getDictionaryObject (COSName .W , COSArray .class );
81+ COSArray wArray = getCOSObject () .getDictionaryObject (COSName .W , COSArray .class );
8282 if (nonNull (wArray ))
8383 {
8484 int size = wArray .size ();
@@ -98,8 +98,11 @@ private void readWidths()
9898 int arraySize = array .size ();
9999 for (int i = 0 ; i < arraySize ; i ++)
100100 {
101- COSNumber width = (COSNumber ) array .getObject (i );
102- widths .put (startRange + i , width .floatValue ());
101+ COSNumber width = array .getObject (i , COSNumber .class );
102+ if (nonNull (width ))
103+ {
104+ widths .put (startRange + i , width .floatValue ());
105+ }
103106 }
104107 }
105108 else
@@ -132,7 +135,7 @@ private void readWidths()
132135 private void readVerticalDisplacements ()
133136 {
134137 // default position vector and vertical displacement vector
135- COSArray dw2Array = dict .getDictionaryObject (COSName .DW2 , COSArray .class );
138+ COSArray dw2Array = getCOSObject () .getDictionaryObject (COSName .DW2 , COSArray .class );
136139 if (nonNull (dw2Array ))
137140 {
138141 dw2 = new float [2 ];
@@ -146,7 +149,7 @@ private void readVerticalDisplacements()
146149 }
147150
148151 // vertical metrics for individual CIDs.
149- COSArray w2Array = dict .getDictionaryObject (COSName .W2 , COSArray .class );
152+ COSArray w2Array = getCOSObject () .getDictionaryObject (COSName .W2 , COSArray .class );
150153 if (nonNull (w2Array ))
151154 {
152155 for (int i = 0 ; i < w2Array .size (); i ++)
@@ -182,20 +185,14 @@ private void readVerticalDisplacements()
182185 }
183186 }
184187
185- @ Override
186- public COSDictionary getCOSObject ()
187- {
188- return dict ;
189- }
190-
191188 /**
192189 * The PostScript name of the font.
193190 *
194191 * @return The postscript name of the font.
195192 */
196193 public String getBaseFont ()
197194 {
198- return dict .getNameAsString (COSName .BASE_FONT );
195+ return getCOSObject () .getNameAsString (COSName .BASE_FONT );
199196 }
200197
201198 @ Override
@@ -207,20 +204,12 @@ public String getName()
207204 @ Override
208205 public PDFontDescriptor getFontDescriptor ()
209206 {
210- if (fontDescriptor == null )
211- {
212- COSDictionary fd = dict .getDictionaryObject (COSName .FONT_DESC , COSDictionary .class );
213- if (fd != null )
214- {
215- fontDescriptor = new PDFontDescriptor (fd );
216- }
217- }
218- return fontDescriptor ;
207+ return ofNullable (
208+ getCOSObject ().getDictionaryObject (COSName .FONT_DESC , COSDictionary .class )).map (
209+ PDFontDescriptor ::new ).orElse (null );
219210 }
220211
221212 /**
222- * Returns the Type 0 font which is the parent of this font.
223- *
224213 * @return parent Type 0 font
225214 */
226215 public final PDType0Font getParent ()
@@ -229,31 +218,22 @@ public final PDType0Font getParent()
229218 }
230219
231220 /**
232- * This will get the default width. The default value for the default width is 1000.
233- *
234- * @return The default width for the glyphs in this font.
221+ * @return The default width for the glyphs in this font or 1000 if nothing is set.
235222 */
236- private float getDefaultWidth ()
223+ public float getDefaultWidth ()
237224 {
238- if (defaultWidth == 0 )
225+ if (defaultWidth == - 1 )
239226 {
240- COSNumber number = dict .getDictionaryObject (COSName .DW , COSNumber .class );
241- if (nonNull (number ))
242- {
243- defaultWidth = number .floatValue ();
244- }
245- else
246- {
247- defaultWidth = 1000 ;
248- }
227+ defaultWidth = ofNullable (
228+ getCOSObject ().getDictionaryObject (COSName .DW , COSNumber .class )).map (
229+ COSNumber ::floatValue ).orElse (1000F );
249230 }
250231 return defaultWidth ;
251232 }
252233
253234 /**
254- * Returns the default position vector (v).
255- *
256235 * @param cid CID
236+ * @return the default position vector (v).
257237 */
258238 private Vector getDefaultPositionVector (int cid )
259239 {
@@ -262,12 +242,7 @@ private Vector getDefaultPositionVector(int cid)
262242
263243 private float getWidthForCID (int cid )
264244 {
265- Float width = widths .get (cid );
266- if (width == null )
267- {
268- width = getDefaultWidth ();
269- }
270- return width ;
245+ return ofNullable (widths .get (cid )).orElseGet (this ::getDefaultWidth );
271246 }
272247
273248 @ Override
@@ -352,18 +327,13 @@ public float getAverageFontWidth()
352327 }
353328
354329 /**
355- * Returns the CIDSystemInfo, or null if it is missing (which isn't allowed but could happen).
330+ * @return the CIDSystemInfo, or null if it is missing (which isn't allowed but could happen).
356331 */
357332 public PDCIDSystemInfo getCIDSystemInfo ()
358333 {
359- COSDictionary cidSystemInfoDict = dict .getDictionaryObject (COSName .CIDSYSTEMINFO ,
360- COSDictionary .class );
361-
362- if (nonNull (cidSystemInfoDict ))
363- {
364- return new PDCIDSystemInfo (cidSystemInfoDict );
365- }
366- return null ;
334+ return ofNullable (
335+ getCOSObject ().getDictionaryObject (COSName .CIDSYSTEMINFO , COSDictionary .class )).map (
336+ PDCIDSystemInfo ::new ).orElse (null );
367337 }
368338
369339 /**
@@ -398,7 +368,7 @@ public PDCIDSystemInfo getCIDSystemInfo()
398368 final int [] readCIDToGIDMap () throws IOException
399369 {
400370 int [] cid2gid = null ;
401- COSBase map = dict .getDictionaryObject (COSName .CID_TO_GID_MAP );
371+ COSBase map = getCOSObject () .getDictionaryObject (COSName .CID_TO_GID_MAP );
402372 if (map instanceof COSStream stream )
403373 {
404374
0 commit comments