@@ -335,6 +335,33 @@ public virtual TransparentColor GetPropertyAsTransparentColor(int property) {
335335 return this . GetProperty < TransparentColor > ( property ) ;
336336 }
337337
338+ /// <summary>Returns a property with a certain key, as a floating point value.</summary>
339+ /// <param name="property">
340+ /// an
341+ /// <see cref="iText.Layout.Properties.Property">enum value</see>
342+ /// </param>
343+ /// <returns>
344+ /// a
345+ /// <see cref="float?"/>
346+ /// </returns>
347+ public virtual float ? GetPropertyAsFloat ( int property ) {
348+ return NumberUtil . AsFloat ( this . GetProperty < Object > ( property ) ) ;
349+ }
350+
351+ /// <summary>Returns a property with a certain key, as a floating point value.</summary>
352+ /// <param name="property">
353+ /// an
354+ /// <see cref="iText.Layout.Properties.Property">enum value</see>
355+ /// </param>
356+ /// <param name="defaultValue">default value to be returned if property is not found</param>
357+ /// <returns>
358+ /// a
359+ /// <see cref="float?"/>
360+ /// </returns>
361+ public virtual float ? GetPropertyAsFloat ( int property , float ? defaultValue ) {
362+ return NumberUtil . AsFloat ( this . GetProperty < Object > ( property , defaultValue ) ) ;
363+ }
364+
338365 /// <summary>Returns a property with a certain key, as a boolean value.</summary>
339366 /// <param name="property">
340367 /// an
@@ -348,6 +375,19 @@ public virtual TransparentColor GetPropertyAsTransparentColor(int property) {
348375 return this . GetProperty < bool ? > ( property ) ;
349376 }
350377
378+ /// <summary>Returns a property with a certain key, as an integer value.</summary>
379+ /// <param name="property">
380+ /// an
381+ /// <see cref="iText.Layout.Properties.Property">enum value</see>
382+ /// </param>
383+ /// <returns>
384+ /// a
385+ /// <see cref="int?"/>
386+ /// </returns>
387+ public virtual int ? GetPropertyAsInteger ( int property ) {
388+ return NumberUtil . AsInteger ( this . GetProperty < Object > ( property ) ) ;
389+ }
390+
351391 /// <summary>Returns a string representation of the renderer.</summary>
352392 /// <returns>
353393 /// a
@@ -857,53 +897,37 @@ protected internal virtual Rectangle ApplyBorderBox(Rectangle rect, Border[] bor
857897 return rect . ApplyMargins < Rectangle > ( topWidth , rightWidth , bottomWidth , leftWidth , reverse ) ;
858898 }
859899
860- protected internal virtual void ApplyAbsolutePosition ( Rectangle rect ) {
900+ protected internal virtual void ApplyAbsolutePosition ( Rectangle parentRect ) {
861901 float ? top = this . GetPropertyAsFloat ( Property . TOP ) ;
862902 float ? bottom = this . GetPropertyAsFloat ( Property . BOTTOM ) ;
863903 float ? left = this . GetPropertyAsFloat ( Property . LEFT ) ;
864904 float ? right = this . GetPropertyAsFloat ( Property . RIGHT ) ;
865- float initialHeight = rect . GetHeight ( ) ;
866- float initialWidth = rect . GetWidth ( ) ;
867- float ? minHeight = this . GetPropertyAsFloat ( Property . MIN_HEIGHT ) ;
868- if ( minHeight != null && rect . GetHeight ( ) < ( float ) minHeight ) {
869- float difference = ( float ) minHeight - rect . GetHeight ( ) ;
870- rect . MoveDown ( difference ) . SetHeight ( rect . GetHeight ( ) + difference ) ;
905+ if ( left == null && right == null && BaseDirection . RIGHT_TO_LEFT . Equals ( this . GetProperty < BaseDirection ? > ( Property
906+ . BASE_DIRECTION ) ) ) {
907+ right = 0f ;
871908 }
872- if ( top != null ) {
873- rect . SetHeight ( rect . GetHeight ( ) - ( float ) top ) ;
874- }
875- if ( left != null ) {
876- rect . SetX ( rect . GetX ( ) + ( float ) left ) . SetWidth ( rect . GetWidth ( ) - ( float ) left ) ;
909+ if ( top == null && bottom == null ) {
910+ top = 0f ;
877911 }
878- if ( right != null ) {
879- UnitValue width = this . GetProperty < UnitValue > ( Property . WIDTH ) ;
880- if ( left == null && width != null ) {
881- float widthValue = width . IsPointValue ( ) ? width . GetValue ( ) : ( width . GetValue ( ) * initialWidth ) ;
882- float placeLeft = rect . GetWidth ( ) - widthValue ;
883- if ( placeLeft > 0 ) {
884- float computedRight = Math . Min ( placeLeft , ( float ) right ) ;
885- rect . SetX ( rect . GetX ( ) + rect . GetWidth ( ) - computedRight - widthValue ) ;
886- }
912+ try {
913+ if ( right != null ) {
914+ Move ( parentRect . GetRight ( ) - ( float ) right - occupiedArea . GetBBox ( ) . GetRight ( ) , 0 ) ;
887915 }
888- else {
889- if ( width == null ) {
890- rect . SetWidth ( rect . GetWidth ( ) - ( float ) right ) ;
891- }
916+ if ( left != null ) {
917+ Move ( parentRect . GetLeft ( ) + ( float ) left - occupiedArea . GetBBox ( ) . GetLeft ( ) , 0 ) ;
892918 }
893- }
894- if ( bottom != null ) {
895- if ( minHeight != null ) {
896- rect . SetHeight ( ( float ) minHeight + ( float ) bottom ) ;
919+ if ( top != null ) {
920+ Move ( 0 , parentRect . GetTop ( ) - ( float ) top - occupiedArea . GetBBox ( ) . GetTop ( ) ) ;
897921 }
898- else {
899- float minHeightValue = rect . GetHeight ( ) - ( float ) bottom ;
900- float ? currentMaxHeight = this . GetPropertyAsFloat ( Property . MAX_HEIGHT ) ;
901- if ( currentMaxHeight != null ) {
902- minHeightValue = Math . Min ( minHeightValue , ( float ) currentMaxHeight ) ;
903- }
904- SetProperty ( Property . MIN_HEIGHT , minHeightValue ) ;
922+ if ( bottom != null ) {
923+ Move ( 0 , parentRect . GetBottom ( ) + ( float ) bottom - occupiedArea . GetBBox ( ) . GetBottom ( ) ) ;
905924 }
906925 }
926+ catch ( ArgumentNullException ) {
927+ ILogger logger = LoggerFactory . GetLogger ( typeof ( iText . Layout . Renderer . AbstractRenderer ) ) ;
928+ logger . Error ( MessageFormatUtil . Format ( iText . IO . LogMessageConstant . OCCUPIED_AREA_HAS_NOT_BEEN_INITIALIZED ,
929+ "Absolute positioning might be applied incorrectly." ) ) ;
930+ }
907931 }
908932
909933 protected internal virtual void ApplyRelativePositioningTranslation ( bool reverse ) {
@@ -1211,9 +1235,9 @@ protected internal virtual float[] CalculateShiftToPositionBBoxOfPointsAt(float
12111235 }
12121236
12131237 protected internal virtual void OverrideHeightProperties ( ) {
1214- float ? height = this . GetPropertyAsFloat ( Property . HEIGHT ) ;
1215- float ? maxHeight = this . GetPropertyAsFloat ( Property . MAX_HEIGHT ) ;
1216- float ? minHeight = this . GetPropertyAsFloat ( Property . MIN_HEIGHT ) ;
1238+ float ? height = this . GetPropertyAsFloat < float > ( Property . HEIGHT ) ;
1239+ float ? maxHeight = this . GetPropertyAsFloat < float > ( Property . MAX_HEIGHT ) ;
1240+ float ? minHeight = this . GetPropertyAsFloat < float > ( Property . MIN_HEIGHT ) ;
12171241 if ( null != height ) {
12181242 if ( null == maxHeight || height < maxHeight ) {
12191243 maxHeight = height ;
@@ -1271,6 +1295,37 @@ internal static bool NoAbsolutePositionInfo(IRenderer renderer) {
12711295 ( Property . LEFT ) && ! renderer . HasProperty ( Property . RIGHT ) ;
12721296 }
12731297
1298+ internal static float ? GetPropertyAsFloat ( IRenderer renderer , int property ) {
1299+ return NumberUtil . AsFloat ( renderer . GetProperty < Object > ( property ) ) ;
1300+ }
1301+
1302+ internal static void ApplyGeneratedAccessibleAttributes ( TagTreePointer tagPointer , PdfDictionary attributes
1303+ ) {
1304+ if ( attributes == null ) {
1305+ return ;
1306+ }
1307+ // TODO if taggingPointer.getProperties will always write directly to struct elem, use it instead (add addAttributes overload with index)
1308+ PdfStructElem structElem = tagPointer . GetDocument ( ) . GetTagStructureContext ( ) . GetPointerStructElem ( tagPointer
1309+ ) ;
1310+ PdfObject structElemAttr = structElem . GetAttributes ( false ) ;
1311+ if ( structElemAttr == null || ! structElemAttr . IsDictionary ( ) && ! structElemAttr . IsArray ( ) ) {
1312+ structElem . SetAttributes ( attributes ) ;
1313+ }
1314+ else {
1315+ if ( structElemAttr . IsDictionary ( ) ) {
1316+ PdfArray attrArr = new PdfArray ( ) ;
1317+ attrArr . Add ( attributes ) ;
1318+ attrArr . Add ( structElemAttr ) ;
1319+ structElem . SetAttributes ( attrArr ) ;
1320+ }
1321+ else {
1322+ // isArray
1323+ PdfArray attrArr = ( PdfArray ) structElemAttr ;
1324+ attrArr . Add ( 0 , attributes ) ;
1325+ }
1326+ }
1327+ }
1328+
12741329 internal virtual void ShrinkOccupiedAreaForAbsolutePosition ( ) {
12751330 // In case of absolute positioning and not specified left, right, width values, the parent box is shrunk to fit
12761331 // the children. It does not occupy all the available width if it does not need to.
@@ -1335,29 +1390,58 @@ internal virtual PdfFont ResolveFirstPdfFont(String font, FontProvider provider,
13351390 ( ) ) ;
13361391 }
13371392
1338- internal static void ApplyGeneratedAccessibleAttributes ( TagTreePointer tagPointer , PdfDictionary attributes
1339- ) {
1340- if ( attributes == null ) {
1341- return ;
1393+ internal virtual void ApplyAbsolutePositionIfNeeded ( LayoutContext layoutContext ) {
1394+ if ( IsAbsolutePosition ( ) ) {
1395+ ApplyAbsolutePosition ( layoutContext is PositionedLayoutContext ? ( ( PositionedLayoutContext ) layoutContext ) .
1396+ GetParentOccupiedArea ( ) . GetBBox ( ) : layoutContext . GetArea ( ) . GetBBox ( ) ) ;
13421397 }
1343- // TODO if taggingPointer.getProperties will always write directly to struct elem, use it instead (add addAttributes overload with index)
1344- PdfStructElem structElem = tagPointer . GetDocument ( ) . GetTagStructureContext ( ) . GetPointerStructElem ( tagPointer
1345- ) ;
1346- PdfObject structElemAttr = structElem . GetAttributes ( false ) ;
1347- if ( structElemAttr == null || ! structElemAttr . IsDictionary ( ) && ! structElemAttr . IsArray ( ) ) {
1348- structElem . SetAttributes ( attributes ) ;
1398+ }
1399+
1400+ internal virtual void PreparePositionedRendererAndAreaForLayout ( IRenderer childPositionedRenderer , Rectangle
1401+ fullBbox , Rectangle parentBbox ) {
1402+ float ? left = GetPropertyAsFloat ( childPositionedRenderer , Property . LEFT ) ;
1403+ float ? right = GetPropertyAsFloat ( childPositionedRenderer , Property . RIGHT ) ;
1404+ float ? top = GetPropertyAsFloat ( childPositionedRenderer , Property . TOP ) ;
1405+ float ? bottom = GetPropertyAsFloat ( childPositionedRenderer , Property . BOTTOM ) ;
1406+ childPositionedRenderer . SetParent ( this ) ;
1407+ AdjustPositionedRendererLayoutBoxWidth ( childPositionedRenderer , fullBbox , left , right ) ;
1408+ if ( System . Convert . ToInt32 ( LayoutPosition . ABSOLUTE ) . Equals ( childPositionedRenderer . GetProperty < int ? > ( Property
1409+ . POSITION ) ) ) {
1410+ UpdateMinHeightForAbsolutelyPositionedRenderer ( childPositionedRenderer , parentBbox , top , bottom ) ;
13491411 }
1350- else {
1351- if ( structElemAttr . IsDictionary ( ) ) {
1352- PdfArray attrArr = new PdfArray ( ) ;
1353- attrArr . Add ( attributes ) ;
1354- attrArr . Add ( structElemAttr ) ;
1355- structElem . SetAttributes ( attrArr ) ;
1412+ }
1413+
1414+ private void UpdateMinHeightForAbsolutelyPositionedRenderer ( IRenderer renderer , Rectangle parentRendererBox
1415+ , float ? top , float ? bottom ) {
1416+ if ( top != null && bottom != null && ! renderer . HasProperty ( Property . HEIGHT ) ) {
1417+ float ? currentMaxHeight = GetPropertyAsFloat ( renderer , Property . MAX_HEIGHT ) ;
1418+ float ? currentMinHeight = GetPropertyAsFloat ( renderer , Property . MIN_HEIGHT ) ;
1419+ float resolvedMinHeight = Math . Max ( 0 , parentRendererBox . GetTop ( ) - ( float ) top - parentRendererBox . GetBottom
1420+ ( ) - ( float ) bottom ) ;
1421+ if ( currentMinHeight != null ) {
1422+ resolvedMinHeight = Math . Max ( resolvedMinHeight , ( float ) currentMinHeight ) ;
13561423 }
1357- else {
1358- // isArray
1359- PdfArray attrArr = ( PdfArray ) structElemAttr ;
1360- attrArr . Add ( 0 , attributes ) ;
1424+ if ( currentMaxHeight != null ) {
1425+ resolvedMinHeight = Math . Min ( resolvedMinHeight , ( float ) currentMaxHeight ) ;
1426+ }
1427+ renderer . SetProperty ( Property . MIN_HEIGHT , resolvedMinHeight ) ;
1428+ }
1429+ }
1430+
1431+ private void AdjustPositionedRendererLayoutBoxWidth ( IRenderer renderer , Rectangle fullBbox , float ? left , float ?
1432+ right ) {
1433+ if ( left != null ) {
1434+ fullBbox . SetWidth ( fullBbox . GetWidth ( ) - ( float ) left ) . SetX ( fullBbox . GetX ( ) + ( float ) left ) ;
1435+ }
1436+ if ( right != null ) {
1437+ fullBbox . SetWidth ( fullBbox . GetWidth ( ) - ( float ) right ) ;
1438+ }
1439+ if ( left == null && right == null && ! renderer . HasProperty ( Property . WIDTH ) ) {
1440+ // Other, non-block renderers won't occupy full width anyway
1441+ MinMaxWidth minMaxWidth = renderer is BlockRenderer ? ( ( BlockRenderer ) renderer ) . GetMinMaxWidth ( MinMaxWidthUtils
1442+ . GetMax ( ) ) : null ;
1443+ if ( minMaxWidth != null && minMaxWidth . GetMaxWidth ( ) < fullBbox . GetWidth ( ) ) {
1444+ fullBbox . SetWidth ( minMaxWidth . GetMaxWidth ( ) + iText . Layout . Renderer . AbstractRenderer . EPS ) ;
13611445 }
13621446 }
13631447 }
0 commit comments