@@ -219,15 +219,15 @@ func genFieldTextAppearance(wa *model.PdfAnnotationWidget, ftxt *model.PdfFieldT
219219 return nil , err
220220 }
221221 width , height := rect .Width (), rect .Height ()
222+ bboxWidth , bboxHeight := width , height
222223
223- var rotation float64
224- if mkDict , has := core . GetDict ( wa . MK ); has {
224+ mkDict , has := core . GetDict ( wa . MK )
225+ if has {
225226 bsDict , _ := core .GetDict (wa .BS )
226227 err := style .applyAppearanceCharacteristics (mkDict , bsDict , nil )
227228 if err != nil {
228229 return nil , err
229230 }
230- rotation , _ = core .GetNumberAsFloat (mkDict .Get ("R" ))
231231 }
232232
233233 // Get and process the default appearance string (DA) operands.
@@ -252,26 +252,10 @@ func genFieldTextAppearance(wa *model.PdfAnnotationWidget, ftxt *model.PdfFieldT
252252 cc .Add_BMC ("Tx" )
253253 cc .Add_q ()
254254
255- bboxWidth , bboxHeight := width , height
256- if rotation != 0 {
257- // Calculate bounding box before rotation.
258- revRotation := - rotation
259- bbox := draw.Path {Points : []draw.Point {
260- draw .NewPoint (0 , 0 ).Rotate (revRotation ),
261- draw .NewPoint (width , 0 ).Rotate (revRotation ),
262- draw .NewPoint (0 , height ).Rotate (revRotation ),
263- draw .NewPoint (width , height ).Rotate (revRotation ),
264- }}.GetBoundingBox ()
265-
266- // Update width and height, as the appearance is generated based on
267- // the bounding of the annotation with no rotation.
268- width = bbox .Width
269- height = bbox .Height
270-
271- // Apply rotation.
272- cc .RotateDeg (rotation )
273- cc .Translate (bbox .X , bbox .Y )
274- }
255+ // Apply rotation if present.
256+ // Update width and height, as the appearance is generated based on
257+ // the bounding of the annotation with no rotation.
258+ width , height = style .applyRotation (mkDict , width , height , cc )
275259
276260 // Graphic state changes.
277261 cc .Add_BT ()
@@ -513,8 +497,10 @@ func genFieldTextCombAppearance(wa *model.PdfAnnotationWidget, ftxt *model.PdfFi
513497 return nil , err
514498 }
515499 width , height := rect .Width (), rect .Height ()
500+ bboxWidth , bboxHeight := width , height
516501
517- if mkDict , has := core .GetDict (wa .MK ); has {
502+ mkDict , has := core .GetDict (wa .MK )
503+ if has {
518504 bsDict , _ := core .GetDict (wa .BS )
519505 err := style .applyAppearanceCharacteristics (mkDict , bsDict , nil )
520506 if err != nil {
@@ -551,6 +537,11 @@ func genFieldTextCombAppearance(wa *model.PdfAnnotationWidget, ftxt *model.PdfFi
551537 cc .Add_BMC ("Tx" )
552538 cc .Add_q ()
553539
540+ // Apply rotation if present.
541+ // Update width and height, as the appearance is generated based on
542+ // the bounding of the annotation with no rotation.
543+ width , height = style .applyRotation (mkDict , width , height , cc )
544+
554545 // Graphic state changes.
555546 cc .Add_BT ()
556547
@@ -680,7 +671,7 @@ func genFieldTextCombAppearance(wa *model.PdfAnnotationWidget, ftxt *model.PdfFi
680671
681672 xform := model .NewXObjectForm ()
682673 xform .Resources = resources
683- xform .BBox = core .MakeArrayFromFloats ([]float64 {0 , 0 , width , height })
674+ xform .BBox = core .MakeArrayFromFloats ([]float64 {0 , 0 , bboxWidth , bboxHeight })
684675 xform .SetContentStream (cc .Bytes (), defStreamEncoder ())
685676
686677 apDict := core .MakeDict ()
@@ -702,6 +693,7 @@ func genFieldCheckboxAppearance(wa *model.PdfAnnotationWidget, fbtn *model.PdfFi
702693 return nil , err
703694 }
704695 width , height := rect .Width (), rect .Height ()
696+ bboxWidth , bboxHeight := width , height
705697
706698 common .Log .Debug ("Checkbox, wa BS: %v" , wa .BS )
707699
@@ -710,7 +702,8 @@ func genFieldCheckboxAppearance(wa *model.PdfAnnotationWidget, fbtn *model.PdfFi
710702 return nil , err
711703 }
712704
713- if mkDict , has := core .GetDict (wa .MK ); has {
705+ mkDict , has := core .GetDict (wa .MK )
706+ if has {
714707 bsDict , _ := core .GetDict (wa .BS )
715708 err := style .applyAppearanceCharacteristics (mkDict , bsDict , zapfdb )
716709 if err != nil {
@@ -732,6 +725,11 @@ func genFieldCheckboxAppearance(wa *model.PdfAnnotationWidget, fbtn *model.PdfFi
732725 drawAlignmentReticle (cc , style2 , width , height )
733726 }
734727
728+ // Apply rotation if present.
729+ // Update width and height, as the appearance is generated based on
730+ // the bounding of the annotation with no rotation.
731+ width , height = style .applyRotation (mkDict , width , height , cc )
732+
735733 fontsize := style .AutoFontSizeFraction * height
736734
737735 checkmetrics , ok := zapfdb .GetRuneMetrics (style .CheckmarkRune )
@@ -767,7 +765,7 @@ func genFieldCheckboxAppearance(wa *model.PdfAnnotationWidget, fbtn *model.PdfFi
767765
768766 xformOn .Resources = model .NewPdfPageResources ()
769767 xformOn .Resources .SetFontByName ("ZaDb" , zapfdb .ToPdfObject ())
770- xformOn .BBox = core .MakeArrayFromFloats ([]float64 {0 , 0 , width , height })
768+ xformOn .BBox = core .MakeArrayFromFloats ([]float64 {0 , 0 , bboxWidth , bboxHeight })
771769 xformOn .SetContentStream (cc .Bytes (), defStreamEncoder ())
772770 }
773771
@@ -777,7 +775,7 @@ func genFieldCheckboxAppearance(wa *model.PdfAnnotationWidget, fbtn *model.PdfFi
777775 if style .BorderSize > 0 {
778776 drawRect (cc , style , width , height )
779777 }
780- xformOff .BBox = core .MakeArrayFromFloats ([]float64 {0 , 0 , width , height })
778+ xformOff .BBox = core .MakeArrayFromFloats ([]float64 {0 , 0 , bboxWidth , bboxHeight })
781779 xformOff .SetContentStream (cc .Bytes (), defStreamEncoder ())
782780 }
783781
@@ -813,7 +811,8 @@ func genFieldComboboxAppearance(form *model.PdfAcroForm, wa *model.PdfAnnotation
813811 return nil , err
814812 }
815813
816- if mkDict , has := core .GetDict (wa .MK ); has {
814+ mkDict , has := core .GetDict (wa .MK )
815+ if has {
817816 bsDict , _ := core .GetDict (wa .BS )
818817 err := style .applyAppearanceCharacteristics (mkDict , bsDict , nil )
819818 if err != nil {
@@ -839,7 +838,7 @@ func genFieldComboboxAppearance(form *model.PdfAcroForm, wa *model.PdfAnnotation
839838 }
840839
841840 if len (optstr ) > 0 {
842- xform , err := makeComboboxTextXObjForm (fch .PdfField , width , height , optstr , style , daOps , form .DR )
841+ xform , err := makeComboboxTextXObjForm (fch .PdfField , width , height , optstr , style , daOps , form .DR , mkDict )
843842 if err != nil {
844843 return nil , err
845844 }
@@ -857,8 +856,9 @@ func genFieldComboboxAppearance(form *model.PdfAcroForm, wa *model.PdfAnnotation
857856// Make a text-based XObj Form.
858857func makeComboboxTextXObjForm (field * model.PdfField , width , height float64 ,
859858 text string , style AppearanceStyle , daOps * contentstream.ContentStreamOperations ,
860- dr * model.PdfPageResources ) (* model.XObjectForm , error ) {
859+ dr * model.PdfPageResources , mkDict * core. PdfObjectDictionary ) (* model.XObjectForm , error ) {
861860 resources := model .NewPdfPageResources ()
861+ bboxWidth , bboxHeight := width , height
862862
863863 cc := contentstream .NewContentCreator ()
864864 if style .BorderSize > 0 {
@@ -875,6 +875,11 @@ func makeComboboxTextXObjForm(field *model.PdfField, width, height float64,
875875 // Graphic state changes.
876876 cc .Add_BT ()
877877
878+ // Apply rotation if present.
879+ // Update width and height, as the appearance is generated based on
880+ // the bounding of the annotation with no rotation.
881+ width , height = style .applyRotation (mkDict , width , height , cc )
882+
878883 // Process DA operands.
879884 apFont , hasTf , err := style .processDA (field , daOps , dr , resources , cc )
880885 if err != nil {
@@ -950,7 +955,7 @@ func makeComboboxTextXObjForm(field *model.PdfField, width, height float64,
950955
951956 xform := model .NewXObjectForm ()
952957 xform .Resources = resources
953- xform .BBox = core .MakeArrayFromFloats ([]float64 {0 , 0 , width , height })
958+ xform .BBox = core .MakeArrayFromFloats ([]float64 {0 , 0 , bboxWidth , bboxHeight })
954959 xform .SetContentStream (cc .Bytes (), defStreamEncoder ())
955960
956961 return xform , nil
@@ -1067,6 +1072,40 @@ func (style *AppearanceStyle) applyAppearanceCharacteristics(mkDict *core.PdfObj
10671072 return nil
10681073}
10691074
1075+ // applyRotation applies the rotation specified by the MK dictionary,
1076+ // if present. The method returns the width and height of the annotation
1077+ // rectangle with no rotation.
1078+ func (style * AppearanceStyle ) applyRotation (mkDict * core.PdfObjectDictionary ,
1079+ width , height float64 , cc * contentstream.ContentCreator ) (float64 , float64 ) {
1080+ if ! style .AllowMK {
1081+ return width , height
1082+ }
1083+ if mkDict == nil {
1084+ return width , height
1085+ }
1086+
1087+ // Extract rotation from the MK dictionary.
1088+ rotation , _ := core .GetNumberAsFloat (mkDict .Get ("R" ))
1089+ if rotation == 0 {
1090+ return width , height
1091+ }
1092+
1093+ // Calculate bounding box before rotation.
1094+ revRotation := - rotation
1095+ bbox := draw.Path {Points : []draw.Point {
1096+ draw .NewPoint (0 , 0 ).Rotate (revRotation ),
1097+ draw .NewPoint (width , 0 ).Rotate (revRotation ),
1098+ draw .NewPoint (0 , height ).Rotate (revRotation ),
1099+ draw .NewPoint (width , height ).Rotate (revRotation ),
1100+ }}.GetBoundingBox ()
1101+
1102+ // Apply rotation.
1103+ cc .RotateDeg (rotation )
1104+ cc .Translate (bbox .X , bbox .Y )
1105+
1106+ return bbox .Width , bbox .Height
1107+ }
1108+
10701109// processDA adds the operands found in the field default appearance stream to
10711110// the provided content stream creator. It also provides a fallback font, based
10721111// on the configuration of the AppearanceStyle, if no valid font is specified
0 commit comments