Skip to content

Add property to disable bevels on borders. #761

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,20 @@ public final class CSSName implements Comparable<CSSName> {
new PrimitivePropertyBuilders.BorderCollapse()
);

/**
* If this property is set to no-bevel then borders are rendered without
* bevels. This can be useful to avoid anti-aliasing.
*/
public final static CSSName FS_BORDER_RENDERING =
addProperty(
"-fs-border-rendering",
PRIMITIVE,
"auto",
INHERITS,
new PrimitivePropertyBuilders.FSBorderRendering()
);


/**
* Unique CSSName instance for fictitious property.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Map;

import com.openhtmltopdf.css.parser.FSColor;
import com.openhtmltopdf.css.parser.property.PrimitivePropertyBuilders;
import com.openhtmltopdf.css.style.CssContext;
import com.openhtmltopdf.css.style.FSDerivedValue;
import com.openhtmltopdf.util.XRRuntimeException;
Expand Down Expand Up @@ -262,6 +263,12 @@ public class IdentValue implements FSDerivedValue {
public static final IdentValue FOOTNOTE = addValue("footnote");
public static final IdentValue FS_FOOTNOTE_BODY = addValue("-fs-footnote-body");

/**
* Value for the -fs-border-rendering property.
* See {@link CSSName#FS_BORDER_RENDERING}
*/
public static final IdentValue NO_BEVEL = addValue("no-bevel");

/**
* Constructor for the IdentValue object
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.*;

public class PrimitivePropertyBuilders {

// none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset
public static final BitSet BORDER_STYLES = setFor(
new IdentValue[] { IdentValue.NONE, IdentValue.HIDDEN, IdentValue.DOTTED,
Expand Down Expand Up @@ -112,7 +113,7 @@ public class PrimitivePropertyBuilders {
public static final PropertyBuilder MARGIN = new LengthLikeWithAuto();
public static final PropertyBuilder PADDING = new NonNegativeLengthLike();

static BitSet setFor(IdentValue[] values) {
static BitSet setFor(IdentValue... values) {
BitSet result = new BitSet(IdentValue.getIdentCount());
for (int i = 0; i < values.length; i++) {
IdentValue ident = values[i];
Expand Down Expand Up @@ -530,6 +531,16 @@ protected BitSet getAllowed() {
}
}

public static class FSBorderRendering extends SingleIdent {
final BitSet ALLOWED = setFor(IdentValue.AUTO, IdentValue.NO_BEVEL);

@Override
protected BitSet getAllowed() {
return ALLOWED;
}
}


public static class BorderTopColor extends GenericColor {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,11 @@
import com.openhtmltopdf.css.style.CssContext;
import com.openhtmltopdf.newtable.CollapsedBorderValue;

/**
* Created by IntelliJ IDEA.
* User: patrick
* Date: Oct 21, 2005
* Time: 3:24:04 PM
* To change this template use File | Settings | File Templates.
*/
public class BorderPropertySet extends RectPropertySet {
public static final BorderPropertySet EMPTY_BORDER = new BorderPropertySet(0.0f, 0.0f, 0.0f, 0.0f);

public static final BorderPropertySet EMPTY_BORDER = new BorderPropertySet(true, 0.0f, 0.0f, 0.0f, 0.0f);

private boolean _allowBevel;

private IdentValue _topStyle;
private IdentValue _rightStyle;
private IdentValue _bottomStyle;
Expand All @@ -34,8 +29,9 @@ public class BorderPropertySet extends RectPropertySet {
private BorderRadiusCorner _bottomRight;
private BorderRadiusCorner _bottomLeft;

public BorderPropertySet(BorderPropertySet border) {
this(border.top(), border.right(), border.bottom(), border.left());
private BorderPropertySet(BorderPropertySet border) {
this(border.isBevelAllowed(), border.top(), border.right(), border.bottom(), border.left());

this._topStyle = border.topStyle();
this._rightStyle = border.rightStyle();
this._bottomStyle = border.bottomStyle();
Expand All @@ -45,13 +41,15 @@ public BorderPropertySet(BorderPropertySet border) {
this._rightColor = border.rightColor();
this._bottomColor = border.bottomColor();
this._leftColor = border.leftColor();

this._topLeft = border._topLeft;
this._topRight = border._topRight;
this._bottomLeft = border._bottomLeft;
this._bottomRight = border._bottomRight;
}
public BorderPropertySet(

private BorderPropertySet(
boolean allowBevel,
float top,
float right,
float bottom,
Expand All @@ -61,45 +59,52 @@ public BorderPropertySet(
BorderRadiusCorner bottomRightCorner,
BorderRadiusCorner bottomLeftCorner
) {
this._allowBevel = allowBevel;

this._top = top;
this._right = right;
this._bottom = bottom;
this._left = left;

this._topLeft = topLeftCorner;
this._topRight = topRightCorner;
this._bottomLeft = bottomLeftCorner;
this._bottomRight = bottomRightCorner;
}

public BorderPropertySet(
boolean allowBevel,
float top,
float right,
float bottom,
float left
) {
this._allowBevel = allowBevel;

this._top = top;
this._right = right;
this._bottom = bottom;
this._left = left;

this._topLeft = new BorderRadiusCorner();
this._topRight = new BorderRadiusCorner();
this._bottomLeft = new BorderRadiusCorner();
this._bottomRight = new BorderRadiusCorner();
}

public BorderPropertySet(
boolean allowBevel,
CollapsedBorderValue top,
CollapsedBorderValue right,
CollapsedBorderValue bottom,
CollapsedBorderValue left
) {
this( top.width(),
this(allowBevel,
top.width(),
right.width(),
bottom.width(),
left.width());

this._topStyle = top.style();
this._rightStyle = right.style();
this._bottomStyle = bottom.style();
Expand All @@ -108,8 +113,8 @@ public BorderPropertySet(
this._topColor = top.color();
this._rightColor = right.color();
this._bottomColor = bottom.color();
this._leftColor = left.color();
this._leftColor = left.color();

this._topLeft = new BorderRadiusCorner();
this._topRight = new BorderRadiusCorner();
this._bottomLeft = new BorderRadiusCorner();
Expand All @@ -120,6 +125,8 @@ private BorderPropertySet(
CalculatedStyle style,
CssContext ctx
) {
_allowBevel = style.isIdent(CSSName.FS_BORDER_RENDERING, IdentValue.AUTO);

_top = ( style.isIdent(CSSName.BORDER_TOP_STYLE, IdentValue.NONE) ||
style.isIdent(CSSName.BORDER_TOP_STYLE, IdentValue.HIDDEN)
?
Expand All @@ -136,7 +143,7 @@ private BorderPropertySet(
style.isIdent(CSSName.BORDER_LEFT_STYLE, IdentValue.HIDDEN)
?
0 : style.getFloatPropertyProportionalHeight(CSSName.BORDER_LEFT_WIDTH, 0, ctx));

_topColor = style.asColor(CSSName.BORDER_TOP_COLOR);
_rightColor = style.asColor(CSSName.BORDER_RIGHT_COLOR);
_bottomColor = style.asColor(CSSName.BORDER_BOTTOM_COLOR);
Expand All @@ -146,12 +153,7 @@ private BorderPropertySet(
_rightStyle = style.getIdent(CSSName.BORDER_RIGHT_STYLE);
_bottomStyle = style.getIdent(CSSName.BORDER_BOTTOM_STYLE);
_leftStyle = style.getIdent(CSSName.BORDER_LEFT_STYLE);
/*
_topLeft = new BorderRadiusCorner(style.valueByName(CSSName.BORDER_TOP_LEFT_RADIUS), ctx);
_topRight = new BorderRadiusCorner(style.valueByName(CSSName.BORDER_TOP_RIGHT_RADIUS), ctx);
_bottomLeft = new BorderRadiusCorner(style.valueByName(CSSName.BORDER_BOTTOM_LEFT_RADIUS), ctx);
_bottomRight = new BorderRadiusCorner(style.valueByName(CSSName.BORDER_BOTTOM_RIGHT_RADIUS), ctx);
*/

_topLeft = new BorderRadiusCorner(CSSName.BORDER_TOP_LEFT_RADIUS, style, ctx);
_topRight = new BorderRadiusCorner(CSSName.BORDER_TOP_RIGHT_RADIUS, style, ctx);
_bottomLeft = new BorderRadiusCorner(CSSName.BORDER_BOTTOM_LEFT_RADIUS, style, ctx);
Expand Down Expand Up @@ -200,6 +202,13 @@ public String toString() {
return "BorderPropertySet[top=" + _top + ",right=" + _right + ",bottom=" + _bottom + ",left=" + _left + "]";
}

/**
* See {@link CSSName#FS_BORDER_RENDERING}
*/
public boolean isBevelAllowed() {
return this._allowBevel;
}

public boolean noTop() {
return this._topStyle == IdentValue.NONE || (int) _top == 0;
}
Expand Down Expand Up @@ -247,16 +256,16 @@ public FSColor bottomColor() {
public FSColor leftColor() {
return _leftColor;
}

public boolean hasHidden() {
return _topStyle == IdentValue.HIDDEN || _rightStyle == IdentValue.HIDDEN ||
_bottomStyle == IdentValue.HIDDEN || _leftStyle == IdentValue.HIDDEN;
}
}

public boolean hasBorderRadius() {
return getTopLeft().hasRadius() || getTopRight().hasRadius() || getBottomLeft().hasRadius() || getBottomRight().hasRadius();
}

public BorderRadiusCorner getBottomRight() {
return _bottomRight;
}
Expand Down Expand Up @@ -288,10 +297,10 @@ public BorderRadiusCorner getTopLeft() {
public void setTopLeft(BorderRadiusCorner topLeft) {
this._topLeft = topLeft;
}

public BorderPropertySet normalizedInstance(Rectangle bounds) {
float factor = 1;

// top
factor = Math.min(factor, bounds.width / getSideWidth(_topLeft, _topRight, bounds.width));
// bottom
Expand All @@ -300,36 +309,32 @@ public BorderPropertySet normalizedInstance(Rectangle bounds) {
factor = Math.min(factor, bounds.height / getSideWidth(_topRight, _bottomRight, bounds.height));
// left
factor = Math.min(factor, bounds.height / getSideWidth(_bottomLeft, _bottomRight, bounds.height));
BorderPropertySet newPropSet = new BorderPropertySet(_top, _right, _bottom, _left,

BorderPropertySet newPropSet = new BorderPropertySet(true, _top, _right, _bottom, _left,
new BorderRadiusCorner(factor*_topLeft.getMaxLeft(bounds.height), factor*_topLeft.getMaxRight(bounds.width)),
new BorderRadiusCorner(factor*_topRight.getMaxLeft(bounds.width), factor*_topRight.getMaxRight(bounds.height)),
new BorderRadiusCorner(factor*_bottomRight.getMaxLeft(bounds.height), factor*_bottomRight.getMaxRight(bounds.width)),
new BorderRadiusCorner(factor*_bottomLeft.getMaxLeft(bounds.width), factor*_bottomLeft.getMaxRight(bounds.height)));

newPropSet._topColor = _topColor;
newPropSet._rightColor = _rightColor;
newPropSet._bottomColor = _bottomColor;
newPropSet._leftColor = _leftColor;

newPropSet._topStyle = _topStyle;
newPropSet._rightStyle = _rightStyle;
newPropSet._bottomStyle = _bottomStyle;
newPropSet._leftStyle = _leftStyle;

return newPropSet;
}

/**
* helper function for normalizeBorderRadius. Gets the max side width for each of the corners or the side width whichever is larger
* @param left
* @param right
* @param sideWidth
* @return
* Helper function for normalizeBorderRadius. Gets the max side width for each
* of the corners or the side width whichever is larger.
*/
private float getSideWidth(BorderRadiusCorner left, BorderRadiusCorner right, float sideWidth) {
return Math.max(sideWidth, left.getMaxRight(sideWidth) + right.getMaxLeft(sideWidth));
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,19 @@ public void calcCollapsedBorder(CssContext c) {
CollapsedBorderValue right = collapsedRightBorder(c);
CollapsedBorderValue bottom = collapsedBottomBorder(c);
CollapsedBorderValue left = collapsedLeftBorder(c);

_collapsedPaintingBorder = new BorderPropertySet(top, right, bottom, left);


boolean allowBevel = getStyle().isIdent(CSSName.FS_BORDER_RENDERING, IdentValue.AUTO);

_collapsedPaintingBorder = new BorderPropertySet(allowBevel, top, right, bottom, left);

// Give the extra pixel to top and left.
top.setWidth((top.width()+1)/2);
right.setWidth(right.width()/2);
bottom.setWidth(bottom.width()/2);
left.setWidth((left.width()+1)/2);
_collapsedLayoutBorder = new BorderPropertySet(top, right, bottom, left);

_collapsedLayoutBorder = new BorderPropertySet(allowBevel, top, right, bottom, left);

_collapsedBorderTop = top;
_collapsedBorderRight = right;
_collapsedBorderBottom = bottom;
Expand Down
Loading