Skip to content
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

#493 Auto extraction of SVG styles to pass to Batik SVG renderer. #515

Merged
merged 7 commits into from
Jul 21, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.openhtmltopdf.css.extend.lib.DOMTreeResolver;
import com.openhtmltopdf.css.newmatch.CascadedStyle;
import com.openhtmltopdf.css.newmatch.PageInfo;
import com.openhtmltopdf.css.newmatch.Selector;
import com.openhtmltopdf.css.parser.CSSPrimitiveValue;
import com.openhtmltopdf.css.sheet.PropertyDeclaration;
import com.openhtmltopdf.css.sheet.Stylesheet;
Expand Down Expand Up @@ -196,7 +197,16 @@ public CascadedStyle getCascadedStyle(Element e, boolean restyle) {
if (e == null) return CascadedStyle.emptyCascadedStyle;
return _matcher.getCascadedStyle(e, restyle);
}


/**
* Given an element, returns all selectors and their rulesets
* for its descendants. Useful for getting the styles that should be
* applied to SVG, etc.
*/
public String getCSSForAllDescendants(Element e) {
return _matcher.getCSSForAllDescendants(e);
}

public PageInfo getPageStyle(String pageName, String pseudoPage) {
return _matcher.getPageCascadedStyle(pageName, pseudoPage);
}
Expand Down Expand Up @@ -268,14 +278,7 @@ private List<StylesheetInfo> getStylesheets() {

return infos;
}

@Deprecated
public void removeStyle(Element e) {
if (_matcher != null) {
_matcher.removeStyle(e);
}
}


public List<FontFaceRule> getFontFaceRules() {
return _matcher.getFontFaceRules();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.openhtmltopdf.css.constants;

import java.util.Arrays;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;

/**
* This is a partial list of common SVG properties that are not present in
* the HTML renderer of this project. This list is here so we can suppress
* warnings for these properties.
*
* List from:
* https://css-tricks.com/svg-properties-and-css/
*/
public enum SVGProperty {
CLIP,
CLIP_PATH,
CLIP_RULE,
MASK,
FILTER,
STOP_COLOR,
STOP_OPACITY,
FILL,
FILL_RULE,
FILL_OPACITY,
MARKER,
MARKER_START,
MARKER_MID,
MARKER_END,
STROKE,
STROKE_DASHARRAY,
STROKE_DASHOFFSET,
STROKE_LINECAP,
STROKE_LINEJOIN,
STROKE_MITERLIMIT,
STROKE_OPACITY,
STROKE_WIDTH;

private static final Set<String> _set =
Arrays.stream(values())
.map(v -> v.name().toLowerCase(Locale.US).replace('_', '-'))
.collect(Collectors.toSet());

public static Set<String> properties() {
return _set;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
abstract class Condition {

abstract boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes);
abstract void toCSS(StringBuilder sb);

/**
* the CSS condition [attribute]
Expand Down Expand Up @@ -217,6 +218,17 @@ boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes) {

return compare(val, _value);
}

protected void toCSS(StringBuilder sb, String type) {
sb.append('[');
sb.append(_name);
sb.append(type);
sb.append('=');
sb.append('\"');
sb.append(_value);
sb.append('\"');
sb.append(']');
}
}

private static class AttributeExistsCondition extends AttributeCompareCondition {
Expand All @@ -241,6 +253,13 @@ boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes) {
protected boolean compare(String attrValue, String conditionValue) {
throw new UnsupportedOperationException();
}

@Override
void toCSS(StringBuilder sb) {
sb.append('[');
sb.append(_name);
sb.append(']');
}
}

private static class AttributeEqualsCondition extends AttributeCompareCondition {
Expand All @@ -252,6 +271,11 @@ private static class AttributeEqualsCondition extends AttributeCompareCondition
protected boolean compare(String attrValue, String conditionValue) {
return attrValue.equals(conditionValue);
}

@Override
void toCSS(StringBuilder sb) {
toCSS(sb, "");
}
}

private static class AttributePrefixCondition extends AttributeCompareCondition {
Expand All @@ -263,6 +287,11 @@ private static class AttributePrefixCondition extends AttributeCompareCondition
protected boolean compare(String attrValue, String conditionValue) {
return attrValue.startsWith(conditionValue);
}

@Override
void toCSS(StringBuilder sb) {
toCSS(sb, "^");
}
}

private static class AttributeSuffixCondition extends AttributeCompareCondition {
Expand All @@ -274,6 +303,11 @@ private static class AttributeSuffixCondition extends AttributeCompareCondition
protected boolean compare(String attrValue, String conditionValue) {
return attrValue.endsWith(conditionValue);
}

@Override
void toCSS(StringBuilder sb) {
toCSS(sb, "$");
}
}

private static class AttributeSubstringCondition extends AttributeCompareCondition {
Expand All @@ -285,8 +319,13 @@ private static class AttributeSubstringCondition extends AttributeCompareConditi
protected boolean compare(String attrValue, String conditionValue) {
return attrValue.indexOf(conditionValue) > -1;
}

@Override
void toCSS(StringBuilder sb) {
toCSS(sb, "*");
}
}

private static class AttributeMatchesListCondition extends AttributeCompareCondition {
AttributeMatchesListCondition(String namespaceURI, String name, String value) {
super(namespaceURI, name, value);
Expand All @@ -303,6 +342,11 @@ protected boolean compare(String attrValue, String conditionValue) {
}
return matched;
}

@Override
void toCSS(StringBuilder sb) {
toCSS(sb, "~");
}
}

private static class AttributeMatchesFirstPartCondition extends AttributeCompareCondition {
Expand All @@ -318,6 +362,11 @@ protected boolean compare(String attrValue, String conditionValue) {
}
return false;
}

@Override
void toCSS(StringBuilder sb) {
toCSS(sb, "|");
}
}

private static class ClassCondition extends Condition {
Expand All @@ -343,6 +392,12 @@ boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes) {
// in an XML DOM, space normalization in attributes is supposed to have happened already.
return (" " + c + " ").indexOf(_paddedClassName) != -1;
}

@Override
public void toCSS(StringBuilder sb) {
sb.append('.');
sb.append(_paddedClassName.substring(1, _paddedClassName.length() - 1));
}
}

private static class IDCondition extends Condition {
Expand All @@ -363,6 +418,12 @@ boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes) {
}
return true;
}

@Override
void toCSS(StringBuilder sb) {
sb.append('#');
sb.append(_id);
}
}

private static class LangCondition extends Condition {
Expand Down Expand Up @@ -390,6 +451,13 @@ boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes) {
}
return false;
}

@Override
void toCSS(StringBuilder sb) {
sb.append(":lang(");
sb.append(_lang);
sb.append(')');
}
}

private static class FirstChildCondition extends Condition {
Expand All @@ -401,6 +469,11 @@ private static class FirstChildCondition extends Condition {
boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes) {
return treeRes.isFirstChildElement(e);
}

@Override
void toCSS(StringBuilder sb) {
sb.append(":first-child");
}
}

private static class LastChildCondition extends Condition {
Expand All @@ -412,6 +485,11 @@ private static class LastChildCondition extends Condition {
boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes) {
return treeRes.isLastChildElement(e);
}

@Override
void toCSS(StringBuilder sb) {
sb.append(":last-child");
}
}

private static class NthChildCondition extends Condition {
Expand All @@ -420,10 +498,12 @@ private static class NthChildCondition extends Condition {

private final int a;
private final int b;
private final String input;

NthChildCondition(int a, int b) {
NthChildCondition(int a, int b, String input) {
this.a = a;
this.b = b;
this.input = input;
}

@Override
Expand All @@ -442,16 +522,23 @@ boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes) {
}
}

@Override
void toCSS(StringBuilder sb) {
sb.append(":nth-child(");
sb.append(input);
sb.append(')');
}

static NthChildCondition fromString(String number) {
number = number.trim().toLowerCase();

if ("even".equals(number)) {
return new NthChildCondition(2, 0);
return new NthChildCondition(2, 0, number);
} else if ("odd".equals(number)) {
return new NthChildCondition(2, 1);
return new NthChildCondition(2, 1, number);
} else {
try {
return new NthChildCondition(0, Integer.parseInt(number));
return new NthChildCondition(0, Integer.parseInt(number), number);
} catch (NumberFormatException e) {
Matcher m = pattern.matcher(number);

Expand All @@ -467,7 +554,7 @@ static NthChildCondition fromString(String number) {
b *= -1;
}

return new NthChildCondition(a, b);
return new NthChildCondition(a, b, number);
}
}
}
Expand All @@ -484,6 +571,11 @@ boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes) {
int position = treeRes.getPositionOfElement(e);
return position >= 0 && position % 2 == 0;
}

@Override
void toCSS(StringBuilder sb) {
sb.append(":nth-child(even)");
}
}

private static class OddChildCondition extends Condition {
Expand All @@ -496,6 +588,11 @@ boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes) {
int position = treeRes.getPositionOfElement(e);
return position >= 0 && position % 2 == 1;
}

@Override
void toCSS(StringBuilder sb) {
sb.append(":nth-child(odd)");
}
}

private static class LinkCondition extends Condition {
Expand All @@ -507,6 +604,11 @@ private static class LinkCondition extends Condition {
boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes) {
return attRes.isLink(e);
}

@Override
void toCSS(StringBuilder sb) {
sb.append(":link");
}
}

/**
Expand All @@ -521,6 +623,11 @@ private static class UnsupportedCondition extends Condition {
boolean matches(Object e, AttributeResolver attRes, TreeResolver treeRes) {
return false;
}

@Override
void toCSS(StringBuilder sb) {
// Nothing we can do...
}
}

private static String[] split(String s, char ch) {
Expand Down
Loading