Skip to content

Commit

Permalink
Merge pull request #515 from danfickle/svg_styles
Browse files Browse the repository at this point in the history
#493 Auto extraction of SVG styles to pass to Batik SVG renderer.
  • Loading branch information
danfickle authored Jul 21, 2020
2 parents cbb81da + 33ad1b5 commit 9343409
Show file tree
Hide file tree
Showing 17 changed files with 752 additions and 189 deletions.
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

0 comments on commit 9343409

Please sign in to comment.