private static Rectangle[] findLastLeftAndRightBoxes(Rectangle layoutBox, List<Rectangle> yLevelBoxes) { Rectangle lastLeftFloatAtY = null; Rectangle lastRightFloatAtY = null; float left = layoutBox.getLeft(); for (Rectangle box : yLevelBoxes) { if (box.getLeft() < left) { left = box.getLeft(); } } for (Rectangle box : yLevelBoxes) { if (left >= box.getLeft() && left < box.getRight()) { lastLeftFloatAtY = box; left = box.getRight(); } else { lastRightFloatAtY = box; } } return new Rectangle[] {lastLeftFloatAtY, lastRightFloatAtY}; }
private static Rectangle[] findLastLeftAndRightBoxes(Rectangle layoutBox, List<Rectangle> yLevelBoxes) { Rectangle lastLeftFloatAtY = null; Rectangle lastRightFloatAtY = null; float left = layoutBox.getLeft(); for (Rectangle box : yLevelBoxes) { if (box.getLeft() < left) { left = box.getLeft(); } } for (Rectangle box : yLevelBoxes) { if (left >= box.getLeft() && left < box.getRight()) { lastLeftFloatAtY = box; left = box.getRight(); } else { lastRightFloatAtY = box; } } return new Rectangle[] {lastLeftFloatAtY, lastRightFloatAtY}; }
protected List<Point> rectangleToPointsList(Rectangle rect) { List<Point> points = new ArrayList<>(); points.addAll(Arrays.asList(new Point(rect.getLeft(), rect.getBottom()), new Point(rect.getRight(), rect.getBottom()), new Point(rect.getRight(), rect.getTop()), new Point(rect.getLeft(), rect.getTop()))); return points; }
protected List<Point> rectangleToPointsList(Rectangle rect) { List<Point> points = new ArrayList<>(); points.addAll(Arrays.asList(new Point(rect.getLeft(), rect.getBottom()), new Point(rect.getRight(), rect.getBottom()), new Point(rect.getRight(), rect.getTop()), new Point(rect.getLeft(), rect.getTop()))); return points; }
static Float calculateLineShiftUnderFloats(List<Rectangle> floatRendererAreas, Rectangle layoutBox) { List<Rectangle> boxesAtYLevel = getBoxesAtYLevel(floatRendererAreas, layoutBox.getTop()); if (boxesAtYLevel.isEmpty()) { return null; } Rectangle[] lastLeftAndRightBoxes = findLastLeftAndRightBoxes(layoutBox, boxesAtYLevel); float left = lastLeftAndRightBoxes[0] != null ? lastLeftAndRightBoxes[0].getRight() : layoutBox.getLeft(); float right = lastLeftAndRightBoxes[1] != null ? lastLeftAndRightBoxes[1].getLeft() : layoutBox.getRight(); if (layoutBox.getLeft() < left || layoutBox.getRight() > right) { float maxLastFloatBottom; if (lastLeftAndRightBoxes[0] != null && lastLeftAndRightBoxes[1] != null) { maxLastFloatBottom = Math.max(lastLeftAndRightBoxes[0].getBottom(), lastLeftAndRightBoxes[1].getBottom()); } else if (lastLeftAndRightBoxes[0] != null) { maxLastFloatBottom = lastLeftAndRightBoxes[0].getBottom(); } else { maxLastFloatBottom = lastLeftAndRightBoxes[1].getBottom(); } return layoutBox.getTop() - maxLastFloatBottom + AbstractRenderer.EPS; } return null; }
static Float calculateLineShiftUnderFloats(List<Rectangle> floatRendererAreas, Rectangle layoutBox) { List<Rectangle> boxesAtYLevel = getBoxesAtYLevel(floatRendererAreas, layoutBox.getTop()); if (boxesAtYLevel.isEmpty()) { return null; } Rectangle[] lastLeftAndRightBoxes = findLastLeftAndRightBoxes(layoutBox, boxesAtYLevel); float left = lastLeftAndRightBoxes[0] != null ? lastLeftAndRightBoxes[0].getRight() : layoutBox.getLeft(); float right = lastLeftAndRightBoxes[1] != null ? lastLeftAndRightBoxes[1].getLeft() : layoutBox.getRight(); if (layoutBox.getLeft() < left || layoutBox.getRight() > right) { float maxLastFloatBottom; if (lastLeftAndRightBoxes[0] != null && lastLeftAndRightBoxes[1] != null) { maxLastFloatBottom = Math.max(lastLeftAndRightBoxes[0].getBottom(), lastLeftAndRightBoxes[1].getBottom()); } else if (lastLeftAndRightBoxes[0] != null) { maxLastFloatBottom = lastLeftAndRightBoxes[0].getBottom(); } else { maxLastFloatBottom = lastLeftAndRightBoxes[1].getBottom(); } return layoutBox.getTop() - maxLastFloatBottom + AbstractRenderer.EPS; } return null; }
void fixOccupiedAreaIfOverflowedX(OverflowPropertyValue overflowX, Rectangle layoutBox) { if (isOverflowFit(overflowX)) { return; } if ((occupiedArea.getBBox().getWidth() > layoutBox.getWidth() || occupiedArea.getBBox().getLeft() < layoutBox.getLeft())) { occupiedArea.getBBox().setX(layoutBox.getX()).setWidth(layoutBox.getWidth()); } }
right = lastLeftAndRightBoxes[1] != null ? lastLeftAndRightBoxes[1].getLeft() : Float.MAX_VALUE; if (left > right || left > layoutBox.getRight() || right < layoutBox.getLeft()) { left = layoutBox.getLeft(); right = left; } else { right = layoutBox.getRight(); if (left < layoutBox.getLeft()) { left = layoutBox.getLeft();
void fixOccupiedAreaIfOverflowedX(OverflowPropertyValue overflowX, Rectangle layoutBox) { if (isOverflowFit(overflowX)) { return; } if ((occupiedArea.getBBox().getWidth() > layoutBox.getWidth() || occupiedArea.getBBox().getLeft() < layoutBox.getLeft())) { occupiedArea.getBBox().setX(layoutBox.getX()).setWidth(layoutBox.getWidth()); } }
right = lastLeftAndRightBoxes[1] != null ? lastLeftAndRightBoxes[1].getLeft() : Float.MAX_VALUE; if (left > right || left > layoutBox.getRight() || right < layoutBox.getLeft()) { left = layoutBox.getLeft(); right = left; } else { right = layoutBox.getRight(); if (left < layoutBox.getLeft()) { left = layoutBox.getLeft();
if ((clearPropertyValue.equals(ClearPropertyValue.LEFT) || isBoth) && lastLeftAndRightBoxes[0] != null) { for (Rectangle floatBox : floatRendererAreas) { if (floatBox.getBottom() < lowestFloatBottom && floatBox.getLeft() <= lastLeftAndRightBoxes[0].getLeft()) { lowestFloatBottom = floatBox.getBottom();
if ((clearPropertyValue.equals(ClearPropertyValue.LEFT) || isBoth) && lastLeftAndRightBoxes[0] != null) { for (Rectangle floatBox : floatRendererAreas) { if (floatBox.getBottom() < lowestFloatBottom && floatBox.getLeft() <= lastLeftAndRightBoxes[0].getLeft()) { lowestFloatBottom = floatBox.getBottom();
/** * Create a new PdfArray. The array is filled with the four values of the Rectangle in the * following order: left, bottom, right, top. * * @param rectangle Rectangle whose 4 values will be added to the PdfArray */ public PdfArray(Rectangle rectangle) { list = new ArrayList<>(4); add(new PdfNumber(rectangle.getLeft())); add(new PdfNumber(rectangle.getBottom())); add(new PdfNumber(rectangle.getRight())); add(new PdfNumber(rectangle.getTop())); }
protected void applyAbsolutePosition(Rectangle parentRect) { Float top = this.getPropertyAsFloat(Property.TOP); Float bottom = this.getPropertyAsFloat(Property.BOTTOM); Float left = this.getPropertyAsFloat(Property.LEFT); Float right = this.getPropertyAsFloat(Property.RIGHT); if (left == null && right == null && BaseDirection.RIGHT_TO_LEFT.equals(this.<BaseDirection>getProperty(Property.BASE_DIRECTION))) { right = 0f; } if (top == null && bottom == null) { top = 0f; } try { if (right != null) { move(parentRect.getRight() - (float) right - occupiedArea.getBBox().getRight(), 0); } if (left != null) { move(parentRect.getLeft() + (float) left - occupiedArea.getBBox().getLeft(), 0); } if (top != null) { move(0, parentRect.getTop() - (float) top - occupiedArea.getBBox().getTop()); } if (bottom != null) { move(0, parentRect.getBottom() + (float) bottom - occupiedArea.getBBox().getBottom()); } } catch (Exception exc) { Logger logger = LoggerFactory.getLogger(AbstractRenderer.class); logger.error(MessageFormatUtil.format(LogMessageConstant.OCCUPIED_AREA_HAS_NOT_BEEN_INITIALIZED, "Absolute positioning might be applied incorrectly.")); } }
protected void applyAbsolutePosition(Rectangle parentRect) { Float top = this.getPropertyAsFloat(Property.TOP); Float bottom = this.getPropertyAsFloat(Property.BOTTOM); Float left = this.getPropertyAsFloat(Property.LEFT); Float right = this.getPropertyAsFloat(Property.RIGHT); if (left == null && right == null && BaseDirection.RIGHT_TO_LEFT.equals(this.<BaseDirection>getProperty(Property.BASE_DIRECTION))) { right = 0f; } if (top == null && bottom == null) { top = 0f; } try { if (right != null) { move(parentRect.getRight() - (float) right - occupiedArea.getBBox().getRight(), 0); } if (left != null) { move(parentRect.getLeft() + (float) left - occupiedArea.getBBox().getLeft(), 0); } if (top != null) { move(0, parentRect.getTop() - (float) top - occupiedArea.getBBox().getTop()); } if (bottom != null) { move(0, parentRect.getBottom() + (float) bottom - occupiedArea.getBBox().getBottom()); } } catch (Exception exc) { Logger logger = LoggerFactory.getLogger(AbstractRenderer.class); logger.error(MessageFormatUtil.format(LogMessageConstant.OCCUPIED_AREA_HAS_NOT_BEEN_INITIALIZED, "Absolute positioning might be applied incorrectly.")); } }
/** * This method creates {@link AffineTransform} instance that could be used * to rotate content inside the occupied area. Be aware that it should be used only after * layout rendering is finished and correct occupied area for the rotated element is calculated. * * @return {@link AffineTransform} that rotates the content and places it inside occupied area. */ protected AffineTransform createRotationTransformInsideOccupiedArea() { Float angle = this.<Float>getProperty(Property.ROTATION_ANGLE); AffineTransform rotationTransform = AffineTransform.getRotateInstance((float) angle); Rectangle contentBox = this.getOccupiedAreaBBox(); List<Point> rotatedContentBoxPoints = transformPoints(rectangleToPointsList(contentBox), rotationTransform); // Occupied area for rotated elements is already calculated on layout in such way to enclose rotated content; // therefore we can simply rotate content as is and then shift it to the occupied area. float[] shift = calculateShiftToPositionBBoxOfPointsAt(occupiedArea.getBBox().getLeft(), occupiedArea.getBBox().getTop(), rotatedContentBoxPoints); rotationTransform.preConcatenate(AffineTransform.getTranslateInstance(shift[0], shift[1])); return rotationTransform; }
outerBorderBox.getRight(), outerBorderBox.getBottom(), outerBorderBox.getLeft() };
/** * This method creates {@link AffineTransform} instance that could be used * to rotate content inside the occupied area. Be aware that it should be used only after * layout rendering is finished and correct occupied area for the rotated element is calculated. * * @return {@link AffineTransform} that rotates the content and places it inside occupied area. */ protected AffineTransform createRotationTransformInsideOccupiedArea() { Float angle = this.<Float>getProperty(Property.ROTATION_ANGLE); AffineTransform rotationTransform = AffineTransform.getRotateInstance((float) angle); Rectangle contentBox = this.getOccupiedAreaBBox(); List<Point> rotatedContentBoxPoints = transformPoints(rectangleToPointsList(contentBox), rotationTransform); // Occupied area for rotated elements is already calculated on layout in such way to enclose rotated content; // therefore we can simply rotate content as is and then shift it to the occupied area. float[] shift = calculateShiftToPositionBBoxOfPointsAt(occupiedArea.getBBox().getLeft(), occupiedArea.getBBox().getTop(), rotatedContentBoxPoints); rotationTransform.preConcatenate(AffineTransform.getTranslateInstance(shift[0], shift[1])); return rotationTransform; }