From 1eb6cd964ad84f1e896310046b84d41e687174d8 Mon Sep 17 00:00:00 2001 From: Aditya Deepak Mahale Date: Wed, 23 Mar 2022 17:04:21 -0300 Subject: [PATCH 1/3] Extract a new class CounterLanguage from CounterFunction --- .../openhtmltopdf/layout/CounterFunction.java | 32 +++---------------- .../openhtmltopdf/layout/CounterLanguage.java | 28 ++++++++++++++++ 2 files changed, 32 insertions(+), 28 deletions(-) create mode 100644 openhtmltopdf-core/src/main/java/com/openhtmltopdf/layout/CounterLanguage.java diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/layout/CounterFunction.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/layout/CounterFunction.java index bed4bf311..3fff1b3ec 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/layout/CounterFunction.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/layout/CounterFunction.java @@ -41,30 +41,16 @@ public CounterFunction(List counterValues, String separator, IdentValue _listStyleType = listStyleType; } - private static String toRoman(int val) { - int[] ints = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; - String[] nums = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < ints.length; i++) { - int count = val / ints[i]; - for (int j = 0; j < count; j++) { - sb.append(nums[i]); - } - val -= ints[i] * count; - } - return sb.toString(); - } - public static String createCounterText(IdentValue listStyle, int listCounter) { String text; if (listStyle == IdentValue.LOWER_LATIN || listStyle == IdentValue.LOWER_ALPHA) { - text = toLatin(listCounter).toLowerCase(); + text = CounterLanguage.toLatin(listCounter).toLowerCase(); } else if (listStyle == IdentValue.UPPER_LATIN || listStyle == IdentValue.UPPER_ALPHA) { - text = toLatin(listCounter).toUpperCase(); + text = CounterLanguage.toLatin(listCounter).toUpperCase(); } else if (listStyle == IdentValue.LOWER_ROMAN) { - text = toRoman(listCounter).toLowerCase(); + text = CounterLanguage.toRoman(listCounter).toLowerCase(); } else if (listStyle == IdentValue.UPPER_ROMAN) { - text = toRoman(listCounter).toUpperCase(); + text = CounterLanguage.toRoman(listCounter).toUpperCase(); } else if (listStyle == IdentValue.DECIMAL_LEADING_ZERO) { text = (listCounter >= 10 ? "" : "0") + listCounter; } else { // listStyle == IdentValue.DECIMAL or anything else @@ -74,16 +60,6 @@ public static String createCounterText(IdentValue listStyle, int listCounter) { } - private static String toLatin(int val) { - String result = ""; - val -= 1; - while (val >= 0) { - int letter = val % 26; - val = val / 26 - 1; - result = ((char) (letter + 65)) + result; - } - return result; - } public String evaluate() { if (_counterValues == null) { return createCounterText(_listStyleType, _counterValue); diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/layout/CounterLanguage.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/layout/CounterLanguage.java new file mode 100644 index 000000000..ae463833a --- /dev/null +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/layout/CounterLanguage.java @@ -0,0 +1,28 @@ +package com.openhtmltopdf.layout; + +public class CounterLanguage { + static String toRoman(int val) { + int[] ints = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; + String[] nums = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ints.length; i++) { + int count = val / ints[i]; + for (int j = 0; j < count; j++) { + sb.append(nums[i]); + } + val -= ints[i] * count; + } + return sb.toString(); + } + + static String toLatin(int val) { + String result = ""; + val -= 1; + while (val >= 0) { + int letter = val % 26; + val = val / 26 - 1; + result = ((char) (letter + 65)) + result; + } + return result; + } +} \ No newline at end of file From a377547295669cd775660835db244145f52e590c Mon Sep 17 00:00:00 2001 From: Aditya Deepak Mahale Date: Wed, 23 Mar 2022 17:27:38 -0300 Subject: [PATCH 2/3] Pull up method isStatic by introducting a new layer ContentFunctionAbstract --- .../context/ContentFunctionAbstract.java | 9 +++++ .../context/ContentFunctionFactory.java | 34 ++++--------------- 2 files changed, 16 insertions(+), 27 deletions(-) create mode 100644 openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/ContentFunctionAbstract.java diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/ContentFunctionAbstract.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/ContentFunctionAbstract.java new file mode 100644 index 000000000..ac4143f79 --- /dev/null +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/ContentFunctionAbstract.java @@ -0,0 +1,9 @@ +package com.openhtmltopdf.context; + +import com.openhtmltopdf.css.extend.ContentFunction; + +public abstract class ContentFunctionAbstract implements ContentFunction { + public boolean isStatic() { + return false; + }; +} diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/ContentFunctionFactory.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/ContentFunctionFactory.java index b09ffe1b6..689e771d7 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/ContentFunctionFactory.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/ContentFunctionFactory.java @@ -67,11 +67,7 @@ public void registerFunction(ContentFunction function) { * Example: * content: "Page " counter(page) -fs-if-cut-off(" continued") " of " counter(pages); */ - private static class FsIfCutOffFunction implements ContentFunction { - @Override - public boolean isStatic() { - return false; - } + private static class FsIfCutOffFunction extends ContentFunctionAbstract { @Override public String calculate(LayoutContext c, FSFunction function) { @@ -99,11 +95,7 @@ public boolean canHandle(LayoutContext c, FSFunction function) { } } - private static abstract class PageNumberFunction implements ContentFunction { - @Override - public boolean isStatic() { - return false; - } + private static abstract class PageNumberFunction extends ContentFunctionAbstract { @Override public String calculate(LayoutContext c, FSFunction function) { @@ -153,7 +145,7 @@ protected boolean isCounter(FSFunction function, String counterName) { } } - private static class PageCounterFunction extends PageNumberFunction implements ContentFunction { + private static class PageCounterFunction extends PageNumberFunction { @Override public String calculate(RenderingContext c, FSFunction function, InlineText text) { int value = c.getRootLayer().getRelativePageNo(c) + 1; @@ -166,7 +158,7 @@ public boolean canHandle(LayoutContext c, FSFunction function) { } } - private static class PagesCounterFunction extends PageNumberFunction implements ContentFunction { + private static class PagesCounterFunction extends PageNumberFunction { @Override public String calculate(RenderingContext c, FSFunction function, InlineText text) { int value = c.getRootLayer().getRelativePageCount(c); @@ -183,11 +175,7 @@ public boolean canHandle(LayoutContext c, FSFunction function) { * Partially implements target counter as specified here: * http://www.w3.org/TR/2007/WD-css3-gcpm-20070504/#cross-references */ - private static class TargetCounterFunction implements ContentFunction { - @Override - public boolean isStatic() { - return false; - } + private static class TargetCounterFunction extends ContentFunctionAbstract { @Override public String calculate(RenderingContext c, FSFunction function, InlineText text) { @@ -265,11 +253,7 @@ public boolean canHandle(LayoutContext c, FSFunction function) { * is not resolved to an absolute url.
* We only support returning the content of the target element, not a specific pseudo element. */ - private static class TargetTextFunction implements ContentFunction { - @Override - public boolean isStatic() { - return false; - } + private static class TargetTextFunction extends ContentFunctionAbstract { @Override public boolean isCalculableAtLayout() { @@ -380,11 +364,7 @@ public boolean canHandle(LayoutContext c, FSFunction function) { * Partially implements leaders as specified here: * http://www.w3.org/TR/2007/WD-css3-gcpm-20070504/#leaders */ - public static class LeaderFunction implements ContentFunction { - @Override - public boolean isStatic() { - return false; - } + public static class LeaderFunction extends ContentFunctionAbstract { @Override public String calculate(RenderingContext c, FSFunction function, InlineText text) { From ab156f68ba6217a62783da54af8ffb23444409df Mon Sep 17 00:00:00 2001 From: Aditya Deepak Mahale Date: Wed, 23 Mar 2022 19:17:30 -0300 Subject: [PATCH 3/3] Extract a class and move methods from FSLinearGradient class --- .../css/style/derived/FSLinearGradient.java | 93 ++----------------- .../style/derived/FSLinearGradientUtil.java | 92 ++++++++++++++++++ 2 files changed, 98 insertions(+), 87 deletions(-) create mode 100644 openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/style/derived/FSLinearGradientUtil.java diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/style/derived/FSLinearGradient.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/style/derived/FSLinearGradient.java index d386ab6de..b58ad7aa3 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/style/derived/FSLinearGradient.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/style/derived/FSLinearGradient.java @@ -2,15 +2,11 @@ import java.util.ArrayList; import java.util.List; -import java.util.Objects; - import com.openhtmltopdf.css.constants.CSSName; -import com.openhtmltopdf.css.constants.Idents; import com.openhtmltopdf.css.parser.CSSPrimitiveValue; import com.openhtmltopdf.css.parser.FSColor; import com.openhtmltopdf.css.parser.FSFunction; import com.openhtmltopdf.css.parser.PropertyValue; -import com.openhtmltopdf.css.parser.property.AbstractPropertyBuilder; import com.openhtmltopdf.css.parser.property.Conversions; import com.openhtmltopdf.css.style.CalculatedStyle; import com.openhtmltopdf.css.style.CssContext; @@ -62,9 +58,9 @@ public String toString() { public FSLinearGradient(CalculatedStyle style, FSFunction function, int boxWidth, int boxHeight, CssContext ctx) { List params = function.getParameters(); - int stopsStartIndex = getStopsStartIndex(params); + int stopsStartIndex = FSLinearGradientUtil.getStopsStartIndex(params); - float prelimAngle = calculateAngle(params, stopsStartIndex); + float prelimAngle = FSLinearGradientUtil.calculateAngle(params, stopsStartIndex); prelimAngle = prelimAngle % 360f; if (prelimAngle < 0) { prelimAngle += 360f; @@ -75,10 +71,6 @@ public FSLinearGradient(CalculatedStyle style, FSFunction function, int boxWidth endPointsFromAngle(_angle, boxWidth, boxHeight); } - private float deg2rad(final float deg) { - return (float) Math.toRadians(deg); - } - // Compute the endpoints so that a gradient of the given angle // covers a box of the given size. // From: https://github.com/WebKit/webkit/blob/master/Source/WebCore/css/CSSGradientValue.cpp @@ -121,7 +113,7 @@ private void endPointsFromAngle(float angleDeg, final int w, final int h) { // angleDeg is a "bearing angle" (0deg = N, 90deg = E), // but tan expects 0deg = E, 90deg = N. - final float slope = (float) Math.tan(deg2rad(90 - angleDeg)); + final float slope = (float) Math.tan(FSLinearGradientUtil.deg2rad(90 - angleDeg)); // We find the endpoint by computing the intersection of the line formed by the // slope, @@ -163,11 +155,6 @@ private void endPointsFromAngle(float angleDeg, final int w, final int h) { y1 = (int) (halfHeight + endY); } - private boolean isLengthOrPercentage(PropertyValue value) { - return AbstractPropertyBuilder.isLengthHelper(value) || - value.getPrimitiveType() == CSSPrimitiveValue.CSS_PERCENTAGE; - } - private List calculateStopPoints( List params, CalculatedStyle style, CssContext ctx, float boxWidth, int stopsStartIndex) { @@ -183,7 +170,7 @@ private List calculateStopPoints( color = value.getFSColor(); } - if (i + 1 < params.size() && isLengthOrPercentage(params.get(i + 1))) { + if (i + 1 < params.size() && FSLinearGradientUtil.isLengthOrPercentage(params.get(i + 1))) { PropertyValue lengthValue = params.get(i + 1); float length = LengthValue.calcFloatProportionalValue(style, CSSName.BACKGROUND_IMAGE, "", @@ -207,7 +194,7 @@ private List calculateStopPoints( } else if (i == 0) { ret.add(new StopPoint(pt.getColor(), 0f)); } else if (i == points.size() - 1) { - float len = get100PercentDefaultStopLength(style, ctx, boxWidth); + float len = FSLinearGradientUtil.get100PercentDefaultStopLength(style, ctx, boxWidth); ret.add(new StopPoint(pt.getColor(), len)); } else { // Poo, we've got a length-less stop in the middle. @@ -219,7 +206,7 @@ private List calculateStopPoints( int prevWithLengthIndex = getPrevStopPointWithLengthIndex(points, i - 1); float nextLength = nextWithLengthIndex == -1 ? - get100PercentDefaultStopLength(style, ctx, boxWidth) : + FSLinearGradientUtil.get100PercentDefaultStopLength(style, ctx, boxWidth) : ((StopPoint) points.get(nextWithLengthIndex)).getLength(); float prevLength = prevWithLengthIndex == -1 ? 0 : @@ -254,11 +241,6 @@ private int getPrevStopPointWithLengthIndex(List points, return -1; } - private float get100PercentDefaultStopLength(CalculatedStyle style, CssContext ctx, float boxWidth) { - return LengthValue.calcFloatProportionalValue(style, CSSName.BACKGROUND_IMAGE, "100%", - 100f, CSSPrimitiveValue.CSS_PERCENTAGE, boxWidth, ctx); - } - private boolean isStopPointWithLength(IntermediateStopPoint pt) { return pt.getClass() == StopPoint.class; } @@ -272,69 +254,6 @@ private int getNextStopPointWithLengthIndex(List points, return -1; } - private int getStopsStartIndex(List params) { - if (Objects.equals(params.get(0).getStringValue(), "to")) { - int i = 1; - while (i < params.size() && - params.get(i).getStringValue() != null && - Idents.looksLikeABGPosition(params.get(i).getStringValue())) { - i++; - } - - return i; - } else { - return 1; - } - } - - /** - * Calculates the angle of the linear gradient in degrees. - */ - private float calculateAngle(List params, int stopsStartIndex) { - if (Objects.equals(params.get(0).getStringValue(), "to")) { - // The to keyword is followed by one or two position - // idents (in any order). - // linear-gradient( to left top, blue, red); - // linear-gradient( to top right, blue, red); - List positions = new ArrayList<>(2); - - for (int i = 1; i < stopsStartIndex; i++) { - positions.add(params.get(i).getStringValue()); - } - - if (positions.contains("top") && positions.contains("left")) - return 315f; - else if (positions.contains("top") && positions.contains("right")) - return 45f; - else if (positions.contains("bottom") && positions.contains("left")) - return 225f; - else if (positions.contains("bottom") && positions.contains("right")) - return 135f; - else if (positions.contains("bottom")) - return 180f; - else if (positions.contains("left")) - return 270f; - else if (positions.contains("right")) - return 90f; - else - return 0f; - } - else if (params.get(0).getPrimitiveType() == CSSPrimitiveValue.CSS_DEG) - { - // linear-gradient(45deg, ...) - return params.get(0).getFloatValue(); - } - else if (params.get(0).getPrimitiveType() == CSSPrimitiveValue.CSS_RAD) - { - // linear-gradient(2rad) - return params.get(0).getFloatValue() * (float) (180 / Math.PI); - } - else - { - return 0f; - } - } - public List getStopPoints() { return _stopPoints; } diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/style/derived/FSLinearGradientUtil.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/style/derived/FSLinearGradientUtil.java new file mode 100644 index 000000000..3e15a3509 --- /dev/null +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/style/derived/FSLinearGradientUtil.java @@ -0,0 +1,92 @@ +package com.openhtmltopdf.css.style.derived; + +import com.openhtmltopdf.css.constants.CSSName; +import com.openhtmltopdf.css.constants.Idents; +import com.openhtmltopdf.css.parser.CSSPrimitiveValue; +import com.openhtmltopdf.css.parser.PropertyValue; +import com.openhtmltopdf.css.parser.property.AbstractPropertyBuilder; +import com.openhtmltopdf.css.style.CalculatedStyle; +import com.openhtmltopdf.css.style.CssContext; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class FSLinearGradientUtil { + static float deg2rad(final float deg) { + return (float) Math.toRadians(deg); + } + + static boolean isLengthOrPercentage(PropertyValue value) { + return AbstractPropertyBuilder.isLengthHelper(value) || + value.getPrimitiveType() == CSSPrimitiveValue.CSS_PERCENTAGE; + } + + static int getStopsStartIndex(List params) { + if (Objects.equals(params.get(0).getStringValue(), "to")) { + int i = 1; + while (i < params.size() && + params.get(i).getStringValue() != null && + Idents.looksLikeABGPosition(params.get(i).getStringValue())) { + i++; + } + + return i; + } else { + return 1; + } + } + + static float get100PercentDefaultStopLength(CalculatedStyle style, CssContext ctx, float boxWidth) { + return LengthValue.calcFloatProportionalValue(style, CSSName.BACKGROUND_IMAGE, "100%", + 100f, CSSPrimitiveValue.CSS_PERCENTAGE, boxWidth, ctx); + } + + /** + * Calculates the angle of the linear gradient in degrees. + */ + static float calculateAngle(List params, int stopsStartIndex) { + if (Objects.equals(params.get(0).getStringValue(), "to")) { + // The to keyword is followed by one or two position + // idents (in any order). + // linear-gradient( to left top, blue, red); + // linear-gradient( to top right, blue, red); + List positions = new ArrayList<>(2); + + for (int i = 1; i < stopsStartIndex; i++) { + positions.add(params.get(i).getStringValue()); + } + + if (positions.contains("top") && positions.contains("left")) + return 315f; + else if (positions.contains("top") && positions.contains("right")) + return 45f; + else if (positions.contains("bottom") && positions.contains("left")) + return 225f; + else if (positions.contains("bottom") && positions.contains("right")) + return 135f; + else if (positions.contains("bottom")) + return 180f; + else if (positions.contains("left")) + return 270f; + else if (positions.contains("right")) + return 90f; + else + return 0f; + } + else if (params.get(0).getPrimitiveType() == CSSPrimitiveValue.CSS_DEG) + { + // linear-gradient(45deg, ...) + return params.get(0).getFloatValue(); + } + else if (params.get(0).getPrimitiveType() == CSSPrimitiveValue.CSS_RAD) + { + // linear-gradient(2rad) + return params.get(0).getFloatValue() * (float) (180 / Math.PI); + } + else + { + return 0f; + } + } +}