Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2024 Apryse Group NV
Authors: Apryse Software.
This program is offered under a commercial and under the AGPL license.
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
AGPL licensing:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
package com.itextpdf.layout.renderer;
import com.itextpdf.commons.utils.MessageFormatUtil;
import com.itextpdf.io.logs.IoLogMessageConstant;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.layout.LayoutArea;
import com.itextpdf.layout.layout.LayoutContext;
import com.itextpdf.layout.layout.LayoutResult;
import com.itextpdf.layout.layout.LineLayoutContext;
import com.itextpdf.layout.layout.LineLayoutResult;
import com.itextpdf.layout.layout.MinMaxWidthLayoutResult;
import com.itextpdf.layout.logs.LayoutLogMessageConstant;
import com.itextpdf.layout.margincollapse.MarginsCollapseHandler;
import com.itextpdf.layout.minmaxwidth.MinMaxWidth;
import com.itextpdf.layout.minmaxwidth.MinMaxWidthUtils;
import com.itextpdf.layout.properties.BaseDirection;
import com.itextpdf.layout.properties.ContinuousContainer;
import com.itextpdf.layout.properties.FloatPropertyValue;
import com.itextpdf.layout.properties.Leading;
import com.itextpdf.layout.properties.OverflowPropertyValue;
import com.itextpdf.layout.properties.ParagraphOrphansControl;
import com.itextpdf.layout.properties.ParagraphWidowsControl;
import com.itextpdf.layout.properties.Property;
import com.itextpdf.layout.properties.RenderingMode;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.UnitValue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class represents the {@link IRenderer renderer} object for a {@link Paragraph}
* object. It will draw the glyphs of the textual content on the {@link DrawContext}.
*/
public class ParagraphRenderer extends BlockRenderer {
protected List lines = null;
/**
* Creates a ParagraphRenderer from its corresponding layout object.
*
* @param modelElement the {@link com.itextpdf.layout.element.Paragraph} which this object should manage
*/
public ParagraphRenderer(Paragraph modelElement) {
super(modelElement);
}
/**
* {@inheritDoc}
*/
@Override
public LayoutResult layout(LayoutContext layoutContext) {
ParagraphOrphansControl orphansControl = this.getProperty(Property.ORPHANS_CONTROL);
ParagraphWidowsControl widowsControl = this.getProperty(Property.WIDOWS_CONTROL);
if (orphansControl != null || widowsControl != null) {
return OrphansWidowsLayoutHelper.orphansWidowsAwareLayout(this, layoutContext, orphansControl, widowsControl);
}
final LayoutResult layoutResult = directLayout(layoutContext);
updateParentLines(this);
updateParentLines((ParagraphRenderer) layoutResult.getSplitRenderer());
return layoutResult;
}
protected LayoutResult directLayout(LayoutContext layoutContext) {
boolean wasHeightClipped = false;
boolean wasParentsHeightClipped = layoutContext.isClippedHeight();
int pageNumber = layoutContext.getArea().getPageNumber();
boolean anythingPlaced = false;
boolean firstLineInBox = true;
LineRenderer currentRenderer = (LineRenderer) new LineRenderer().setParent(this);
Rectangle parentBBox = layoutContext.getArea().getBBox().clone();
MarginsCollapseHandler marginsCollapseHandler = null;
boolean marginsCollapsingEnabled = Boolean.TRUE.equals(getPropertyAsBoolean(Property.COLLAPSING_MARGINS));
if (marginsCollapsingEnabled) {
marginsCollapseHandler = new MarginsCollapseHandler(this, layoutContext.getMarginsCollapseInfo());
}
ContinuousContainer.setupContinuousContainerIfNeeded(this);
OverflowPropertyValue overflowX = this.getProperty(Property.OVERFLOW_X);
Boolean nowrapProp = this.getPropertyAsBoolean(Property.NO_SOFT_WRAP_INLINE);
currentRenderer.setProperty(Property.NO_SOFT_WRAP_INLINE, nowrapProp);
boolean notAllKidsAreFloats = false;
List floatRendererAreas = layoutContext.getFloatRendererAreas();
FloatPropertyValue floatPropertyValue = this.getProperty(Property.FLOAT);
float clearHeightCorrection = FloatingHelper.calculateClearHeightCorrection(this, floatRendererAreas,
parentBBox);
FloatingHelper.applyClearance(parentBBox, marginsCollapseHandler, clearHeightCorrection,
FloatingHelper.isRendererFloating(this));
Float blockWidth = retrieveWidth(parentBBox.getWidth());
if (FloatingHelper.isRendererFloating(this, floatPropertyValue)) {
blockWidth = FloatingHelper.adjustFloatedBlockLayoutBox(this, parentBBox, blockWidth, floatRendererAreas,
floatPropertyValue, overflowX);
floatRendererAreas = new ArrayList<>();
}
if (0 == childRenderers.size()) {
anythingPlaced = true;
currentRenderer = null;
}
boolean isPositioned = isPositioned();
Float rotation = this.getPropertyAsFloat(Property.ROTATION_ANGLE);
Float blockMaxHeight = retrieveMaxHeight();
OverflowPropertyValue overflowY = (null == blockMaxHeight || blockMaxHeight > parentBBox.getHeight())
&& !wasParentsHeightClipped
? OverflowPropertyValue.FIT
: this.getProperty(Property.OVERFLOW_Y);
if (rotation != null || isFixedLayout()) {
parentBBox.moveDown(AbstractRenderer.INF - parentBBox.getHeight()).setHeight(AbstractRenderer.INF);
}
if (rotation != null && !FloatingHelper.isRendererFloating(this)) {
blockWidth = RotationUtils.retrieveRotatedLayoutWidth(parentBBox.getWidth(), this);
}
if (marginsCollapsingEnabled) {
marginsCollapseHandler.startMarginsCollapse(parentBBox);
}
Border[] borders = getBorders();
UnitValue[] paddings = getPaddings();
float parentWidth = parentBBox.getWidth();
applyMargins(parentBBox, false);
applyBorderBox(parentBBox, borders, false);
if (isFixedLayout()) {
parentBBox.setX((float) this.getPropertyAsFloat(Property.LEFT));
}
applyPaddings(parentBBox, paddings, false);
float additionalWidth = parentWidth - parentBBox.getWidth();
applyWidth(parentBBox, blockWidth, overflowX);
wasHeightClipped = applyMaxHeight(parentBBox, blockMaxHeight, marginsCollapseHandler, false, wasParentsHeightClipped, overflowY);
MinMaxWidth minMaxWidth = new MinMaxWidth(additionalWidth);
AbstractWidthHandler widthHandler = new MaxMaxWidthHandler(minMaxWidth);
List areas;
if (isPositioned) {
areas = Collections.singletonList(parentBBox);
} else {
areas = initElementAreas(new LayoutArea(pageNumber, parentBBox));
}
occupiedArea = new LayoutArea(pageNumber, new Rectangle(parentBBox.getX(), parentBBox.getY() + parentBBox.getHeight(), parentBBox.getWidth(), 0));
shrinkOccupiedAreaForAbsolutePosition();
TargetCounterHandler.addPageByID(this);
int currentAreaPos = 0;
Rectangle layoutBox = areas.get(0).clone();
lines = new ArrayList<>();
for (IRenderer child : childRenderers) {
notAllKidsAreFloats = notAllKidsAreFloats || !FloatingHelper.isRendererFloating(child);
currentRenderer.addChild(child);
}
float lastYLine = layoutBox.getY() + layoutBox.getHeight();
float previousDescent = 0;
float lastLineBottomLeadingIndent = 0;
boolean onlyOverflowedFloatsLeft = false;
List inlineFloatsOverflowedToNextPage = new ArrayList<>();
boolean floatOverflowedToNextPageWithNothing = false;
// rectangles are compared by instances
Set nonChildFloatingRendererAreas = new HashSet<>(floatRendererAreas);
if (marginsCollapsingEnabled && childRenderers.size() > 0) {
// passing null is sufficient to notify that there is a kid, however we don't care about it and it's margins
marginsCollapseHandler.startChildMarginsHandling(null, layoutBox);
}
boolean includeFloatsInOccupiedArea = BlockFormattingContextUtil.isRendererCreateBfc(this);
while (currentRenderer != null) {
currentRenderer.setProperty(Property.TAB_DEFAULT, this.getPropertyAsFloat(Property.TAB_DEFAULT));
currentRenderer.setProperty(Property.TAB_STOPS, this.