3939import com .itextpdf .forms .xfdf .XfdfObject ;
4040import com .itextpdf .forms .xfdf .XfdfObjectReadingUtils ;
4141import com .itextpdf .io .logs .IoLogMessageConstant ;
42+ import com .itextpdf .kernel .colors .Color ;
4243import com .itextpdf .kernel .colors .DeviceRgb ;
4344import com .itextpdf .kernel .geom .AffineTransform ;
4445import com .itextpdf .kernel .geom .Rectangle ;
7374public class XfdfMerge {
7475
7576 private static final Logger LOGGER = LoggerFactory .getLogger (XfdfMerge .class );
77+ private final Color DEFAULT_HIGHLIGHT_COLOR = new DeviceRgb (1f , 0.81f , 0f );
7678 private final PdfDocument pdfDocument ;
7779 private final Map <String , PdfAnnotation > annotMap = new HashMap <>();
7880 private final Map <String , List <PdfMarkupAnnotation >> replyMap = new HashMap <>();
@@ -109,19 +111,37 @@ private void mergeAnnotations(AnnotsObject annotsObject) {
109111 }
110112 }
111113
112- private void addCommonAnnotationAttributes (PdfAnnotation annotation , AnnotObject annotObject ) {
114+ private Color getAnnotColor (AnnotObject annotObject , Color defaultColor ) {
115+ String colorString = annotObject .getAttributeValue (XfdfConstants .COLOR );
116+ if (colorString != null ) {
117+ int [] rgbValues = XfdfObjectReadingUtils .convertColorFloatsFromString (colorString );
118+ return new DeviceRgb (rgbValues [0 ], rgbValues [1 ], rgbValues [2 ]);
119+ } else {
120+ return defaultColor ;
121+ }
122+ }
123+
124+ private void addCommonAnnotationAttributes (PdfAnnotation annotation , AnnotObject annotObject , Color color ) {
113125 annotation .setFlags (XfdfObjectReadingUtils .convertFlagsFromString (annotObject .getAttributeValue (XfdfConstants .FLAGS )));
114- annotation .setColor (XfdfObjectReadingUtils .convertColorFloatsFromString (annotObject .getAttributeValue (XfdfConstants .COLOR )));
115- annotation .setDate (new PdfString (annotObject .getAttributeValue (XfdfConstants .DATE )));
126+ annotation .setColor (color );
127+ String dateString = annotObject .getAttributeValue (XfdfConstants .DATE );
128+ if (dateString != null ) {
129+ annotation .setDate (new PdfString (dateString ));
130+ }
116131 String name = annotObject .getAttributeValue (XfdfConstants .NAME );
117- annotation .setName (new PdfString (name ));
118- annotMap .put (name , annotation );
119- // add pending replies
120- for (PdfMarkupAnnotation reply : replyMap .getOrDefault (name , Collections .emptyList ())) {
121- reply .setInReplyTo (annotation );
132+ if (name != null ) {
133+ annotation .setName (new PdfString (name ));
134+ annotMap .put (name , annotation );
135+ // add pending replies
136+ for (PdfMarkupAnnotation reply : replyMap .getOrDefault (name , Collections .emptyList ())) {
137+ reply .setInReplyTo (annotation );
138+ }
139+ replyMap .remove (name );
140+ }
141+ String titleString = annotObject .getAttributeValue (XfdfConstants .TITLE );
142+ if (titleString != null ) {
143+ annotation .setTitle (new PdfString (titleString ));
122144 }
123- replyMap .remove (name );
124- annotation .setTitle (new PdfString (annotObject .getAttributeValue (XfdfConstants .TITLE )));
125145 }
126146
127147 private void addPopupAnnotation (int page , PdfMarkupAnnotation parent , AnnotObject popup ) {
@@ -136,8 +156,14 @@ private void addPopupAnnotation(int page, PdfMarkupAnnotation parent, AnnotObjec
136156 }
137157
138158 private void addMarkupAnnotationAttributes (PdfMarkupAnnotation annotation , AnnotObject annotObject ) {
139- annotation .setCreationDate (new PdfString (annotObject .getAttributeValue (XfdfConstants .CREATION_DATE )));
140- annotation .setSubject (new PdfString (annotObject .getAttributeValue (XfdfConstants .SUBJECT )));
159+ String creationDateString = annotObject .getAttributeValue (XfdfConstants .CREATION_DATE );
160+ if (creationDateString != null ) {
161+ annotation .setCreationDate (new PdfString (creationDateString ));
162+ }
163+ String subjectString = annotObject .getAttributeValue (XfdfConstants .SUBJECT );
164+ if (subjectString != null ) {
165+ annotation .setSubject (new PdfString (subjectString ));
166+ }
141167 String intent = annotObject .getAttributeValue ("IT" );
142168 if (intent != null && !intent .isBlank ()) {
143169 annotation .setIntent (new PdfName (intent ));
@@ -193,14 +219,14 @@ private int readAnnotPage(AnnotObject annotObject) {
193219 return this .pageShift + page ;
194220 }
195221
196- private PdfFormXObject getCaretAppearance () {
222+ private PdfFormXObject getCaretAppearance (Color color ) {
197223 if (this .caretXObj != null ) {
198224 return this .caretXObj ;
199225 }
200226 // draw a caret on a 30x30 canvas
201227 this .caretXObj = new PdfFormXObject (new Rectangle (30 , 30 ));
202228 PdfCanvas canvas = new PdfCanvas (this .caretXObj , this .pdfDocument );
203- canvas .setFillColor (DeviceRgb . BLUE )
229+ canvas .setFillColor (color )
204230 .moveTo (15 , 30 )
205231 .curveTo (15 , 30 , 15 , 0 , 0 , 0 )
206232 .lineTo (30 , 0 )
@@ -210,16 +236,15 @@ private PdfFormXObject getCaretAppearance() {
210236 return this .caretXObj ;
211237 }
212238
213- private PdfFormXObject getCommentAppearance () {
239+ private PdfFormXObject getCommentAppearance (Color color ) {
214240 if (this .commentXObj != null ) {
215241 return this .commentXObj ;
216242 }
217243 // draw a speech bubble on a 30x30 canvas
218244 this .commentXObj = new PdfFormXObject (new Rectangle (30 , 30 ));
219245 PdfCanvas canvas = new PdfCanvas (this .commentXObj , this .pdfDocument );
220246
221- canvas .setFillColorRgb (1 , 1 , 0 )
222- .setLineWidth (0.85f )
247+ canvas .setFillColor (color ).setLineWidth (0.85f )
223248 .moveTo (6 , 27.5 )
224249 .curveTo (4.3 , 27.5 , 3 , 26.5 , 3 , 25 )
225250 .lineTo (3 , 12 )
@@ -235,65 +260,79 @@ private PdfFormXObject getCommentAppearance() {
235260 return this .commentXObj ;
236261 }
237262
238- private PdfTextMarkupAnnotation addTextMarkupAnnotationToPdf (PdfName subtype , AnnotObject annotObject ) {
263+ private void addTextMarkupAnnotationToPdf (PdfName subtype , AnnotObject annotObject , Color color ) {
239264 Rectangle rect = readAnnotRect (annotObject );
240265 float [] quads = readAnnotQuadPoints (annotObject );
241266 PdfTextMarkupAnnotation pdfAnnot = new PdfTextMarkupAnnotation (rect , subtype , quads );
242267
243- addCommonAnnotationAttributes (pdfAnnot , annotObject );
268+ addCommonAnnotationAttributes (pdfAnnot , annotObject , color );
244269 addMarkupAnnotationAttributes (pdfAnnot , annotObject );
245270 int page = readAnnotPage (annotObject );
246271 pdfDocument .getPage (page ).addAnnotation (pdfAnnot );
247272 addPopupAnnotation (page , pdfAnnot , annotObject .getPopup ());
248- return pdfAnnot ;
273+ }
274+
275+ private Color getDefaultColor (String annotName ) {
276+ switch (annotName ) {
277+ case XfdfConstants .TEXT :
278+ case XfdfConstants .HIGHLIGHT :
279+ return DEFAULT_HIGHLIGHT_COLOR ;
280+ case XfdfConstants .UNDERLINE :
281+ case XfdfConstants .STRIKEOUT :
282+ case XfdfConstants .SQUIGGLY :
283+ return DeviceRgb .RED ;
284+ case XfdfConstants .CARET :
285+ return DeviceRgb .BLUE ;
286+ default :
287+ return DeviceRgb .BLACK ;
288+ }
249289 }
250290
251291 private void addAnnotationToPdf (AnnotObject annotObject ) {
252292 String annotName = annotObject .getName ();
253293 int page ;
254294 if (annotName != null ) {
295+ Color color = getAnnotColor (annotObject , getDefaultColor (annotName ));
255296 switch (annotName ) {
256297 case XfdfConstants .TEXT :
257298 PdfTextAnnotation pdfTextAnnotation = new PdfTextAnnotation (readAnnotRect (annotObject ));
258- addCommonAnnotationAttributes (pdfTextAnnotation , annotObject );
299+ addCommonAnnotationAttributes (pdfTextAnnotation , annotObject , color );
259300 addMarkupAnnotationAttributes (pdfTextAnnotation , annotObject );
260301
261302 String icon = annotObject .getAttributeValue (XfdfConstants .ICON );
262303 if ("Comment" .equals (icon )) {
263- pdfTextAnnotation .setNormalAppearance (this .getCommentAppearance ().getPdfObject ());
304+ pdfTextAnnotation .setNormalAppearance (this .getCommentAppearance (color ).getPdfObject ());
264305 }
265306 pdfTextAnnotation .setIconName (new PdfName (icon ));
266- if (annotObject .getAttributeValue (XfdfConstants .STATE ) != null ) {
267- pdfTextAnnotation .setState (new PdfString (annotObject .getAttributeValue (XfdfConstants .STATE )));
307+ String stateString = annotObject .getAttributeValue (XfdfConstants .STATE );
308+ if (stateString != null ) {
309+ pdfTextAnnotation .setState (new PdfString (stateString ));
268310 }
269- if (annotObject .getAttributeValue (XfdfConstants .STATE_MODEL ) != null ) {
270- pdfTextAnnotation .setStateModel (new PdfString (annotObject .getAttributeValue (XfdfConstants .STATE_MODEL )));
311+ String stateModelString = annotObject .getAttributeValue (XfdfConstants .STATE_MODEL );
312+ if (stateModelString != null ) {
313+ pdfTextAnnotation .setStateModel (new PdfString (stateModelString ));
271314 }
272315
273316 page = readAnnotPage (annotObject );
274317 pdfDocument .getPage (page ).addAnnotation (pdfTextAnnotation );
275318 addPopupAnnotation (page , pdfTextAnnotation , annotObject .getPopup ());
276319 break ;
277320 case XfdfConstants .HIGHLIGHT :
278- addTextMarkupAnnotationToPdf (PdfName .Highlight , annotObject )
279- .setColor (new DeviceRgb (1f , 1f , 0 ));
321+ addTextMarkupAnnotationToPdf (PdfName .Highlight , annotObject , color );
280322 break ;
281323 case XfdfConstants .UNDERLINE :
282- addTextMarkupAnnotationToPdf (PdfName .Underline , annotObject )
283- .setColor (DeviceRgb .RED );
324+ addTextMarkupAnnotationToPdf (PdfName .Underline , annotObject , color );
284325 break ;
285326 case XfdfConstants .STRIKEOUT :
286- addTextMarkupAnnotationToPdf (PdfName .StrikeOut , annotObject )
287- .setColor (DeviceRgb .RED );
327+ addTextMarkupAnnotationToPdf (PdfName .StrikeOut , annotObject , color );
288328 break ;
289329 case XfdfConstants .SQUIGGLY :
290- addTextMarkupAnnotationToPdf (PdfName .Squiggly , annotObject )
291- .setColor (DeviceRgb .RED );
330+ addTextMarkupAnnotationToPdf (PdfName .Squiggly , annotObject , color );
292331 break ;
293332 case XfdfConstants .CARET :
294333 PdfCaretAnnotation caretAnnotation = new PdfCaretAnnotation (readAnnotRect (annotObject ));
295- caretAnnotation .setNormalAppearance (this .getCaretAppearance ().getPdfObject ());
296- addCommonAnnotationAttributes (caretAnnotation , annotObject );
334+ caretAnnotation .setNormalAppearance (this .getCaretAppearance (color ).getPdfObject ());
335+ addCommonAnnotationAttributes (caretAnnotation , annotObject , color );
297336 addMarkupAnnotationAttributes (caretAnnotation , annotObject );
298337 page = readAnnotPage (annotObject );
299338 pdfDocument .getPage (page ).addAnnotation (caretAnnotation );
0 commit comments