diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/StyleReference.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/StyleReference.java index 563b3005a..fe2bcfac7 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/StyleReference.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/StyleReference.java @@ -39,6 +39,7 @@ import com.openhtmltopdf.css.sheet.PropertyDeclaration; import com.openhtmltopdf.css.sheet.Stylesheet; import com.openhtmltopdf.css.sheet.StylesheetInfo; +import com.openhtmltopdf.css.style.CalculatedStyle; import com.openhtmltopdf.extend.NamespaceHandler; import com.openhtmltopdf.extend.UserAgentCallback; import com.openhtmltopdf.extend.UserInterface; @@ -72,6 +73,17 @@ public StyleReference(UserAgentCallback userAgent) { _stylesheetFactory = new StylesheetFactoryImpl(userAgent); } + /** + * Gets the style of the root element, should be html tag. + */ + public CalculatedStyle getRootElementStyle() { + if (_context != null && _doc != null) { + return _context.getStyle(_doc.getDocumentElement()); + } else { + return null; + } + } + /** * Sets the documentContext attribute of the StyleReference object * diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/constants/ValueConstants.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/constants/ValueConstants.java index 51f49cdae..e363455f0 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/constants/ValueConstants.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/constants/ValueConstants.java @@ -151,6 +151,7 @@ public static boolean isAbsoluteUnit(short type) { return false; // refer to values known to the DerivedValue instance (tobe) case CSSPrimitiveValue.CSS_EMS: + case CSSPrimitiveValue.CSS_REMS: case CSSPrimitiveValue.CSS_EXS: // length case CSSPrimitiveValue.CSS_IN: diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/CSSParser.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/CSSParser.java index 5424de5f0..d90d147f7 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/CSSParser.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/CSSParser.java @@ -1383,6 +1383,7 @@ private List expr(boolean literal) throws IOException { case Token.URI: case Token.HASH: case Token.FUNCTION: + case Token.DIMENSION: PropertyValue term = term(literal); if (operatorToken != null) { term.setOperator(operatorToken); @@ -1462,7 +1463,19 @@ private PropertyValue term(boolean literal) throws IOException { case Token.TIME: case Token.FREQ: case Token.DIMENSION: - throw new CSSParseException("Unsupported CSS unit " + extractUnit(t), getCurrentLine()); + String unitType = extractUnit(t); + + if ("rem".equals(unitType)) { + result = new PropertyValue( + CSSPrimitiveValue.CSS_REMS, + sign*Float.parseFloat(extractNumber(t)), + sign(sign) + getTokenValue(t)); + next(); + skip_whitespace(); + } else { + throw new CSSParseException("Unsupported CSS unit " + unitType, getCurrentLine()); + } + break; case Token.NUMBER: result = new PropertyValue( CSSPrimitiveValue.CSS_NUMBER, diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/CSSPrimitiveValue.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/CSSPrimitiveValue.java index 990f4939e..e73bdf4db 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/CSSPrimitiveValue.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/CSSPrimitiveValue.java @@ -27,7 +27,10 @@ public interface CSSPrimitiveValue extends CSSValue { public static final short CSS_COUNTER = 23; public static final short CSS_RECT = 24; public static final short CSS_RGBCOLOR = 25; - + + /** rems unit, not official, added by danfickle. */ + public static final short CSS_REMS = 26; + public short getPrimitiveType(); public float getFloatValue(short unitType); public String getStringValue(); diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/property/AbstractPropertyBuilder.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/property/AbstractPropertyBuilder.java index 108b42f35..ccd20397d 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/property/AbstractPropertyBuilder.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/property/AbstractPropertyBuilder.java @@ -173,6 +173,7 @@ public static boolean isLengthHelper(CSSPrimitiveValue value) { || unit == CSSPrimitiveValue.CSS_PX || unit == CSSPrimitiveValue.CSS_IN || unit == CSSPrimitiveValue.CSS_CM || unit == CSSPrimitiveValue.CSS_MM || unit == CSSPrimitiveValue.CSS_PT || unit == CSSPrimitiveValue.CSS_PC + || unit == CSSPrimitiveValue.CSS_REMS || (unit == CSSPrimitiveValue.CSS_NUMBER && value.getFloatValue(CSSPrimitiveValue.CSS_IN) == 0.0f); } diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/style/derived/LengthValue.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/style/derived/LengthValue.java index 785bf6d9f..9ad16e622 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/style/derived/LengthValue.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/style/derived/LengthValue.java @@ -144,6 +144,19 @@ public static float calcFloatProportionalValue(CalculatedStyle style, } break; + case CSSPrimitiveValue.CSS_REMS: { + // The rem unit is the same as em except uses the font-size of the html element + // rather than the font-size of current/parent element. + CalculatedStyle htmlTagStyle = ctx.getCss().getRootElementStyle(); + if (htmlTagStyle == null) { + // The default font-size for the html tag is 16px. + absVal = relVal * 16f * ctx.getDotsPerPixel(); + } else { + FontSpecification htmlTagFontSpecification = htmlTagStyle.getFont(ctx); + absVal = relVal * htmlTagFontSpecification.size; + } + break; + } case CSSPrimitiveValue.CSS_EXS: // To convert EMS to pixels, we need the height of the lowercase 'Xx' character in the current // element... diff --git a/openhtmltopdf-examples/src/main/resources/visualtest/expected/issue-459-rem-unit-default.pdf b/openhtmltopdf-examples/src/main/resources/visualtest/expected/issue-459-rem-unit-default.pdf new file mode 100644 index 000000000..3279fb052 Binary files /dev/null and b/openhtmltopdf-examples/src/main/resources/visualtest/expected/issue-459-rem-unit-default.pdf differ diff --git a/openhtmltopdf-examples/src/main/resources/visualtest/html/issue-459-rem-unit-default.html b/openhtmltopdf-examples/src/main/resources/visualtest/html/issue-459-rem-unit-default.html new file mode 100644 index 000000000..8927e51a1 --- /dev/null +++ b/openhtmltopdf-examples/src/main/resources/visualtest/html/issue-459-rem-unit-default.html @@ -0,0 +1,20 @@ + + + + + + +
ONE
+
TWO
+ + diff --git a/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/visualregressiontests/VisualRegressionTest.java b/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/visualregressiontests/VisualRegressionTest.java index 8e55da7fb..28b639706 100644 --- a/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/visualregressiontests/VisualRegressionTest.java +++ b/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/visualregressiontests/VisualRegressionTest.java @@ -1007,6 +1007,15 @@ public void testIssue446LangSelector() throws IOException { assertTrue(vt.runTest("issue-446-lang-selector")); } + /** + * Tests that the rem unit work with a document that has no author + * font-size set on the html element (defaults to 16px). + */ + @Test + public void testIssue459RemUnitDefault() throws IOException { + assertTrue(vt.runTest("issue-459-rem-unit-default")); + } + /** * Tests what the CSS content property is capable of. */