diff --git a/echosvg-awt-util/src/main/java/io/sf/carte/echosvg/ext/awt/color/ColorContext.java b/echosvg-awt-util/src/main/java/io/sf/carte/echosvg/ext/awt/color/ColorContext.java new file mode 100644 index 000000000..3ef376f11 --- /dev/null +++ b/echosvg-awt-util/src/main/java/io/sf/carte/echosvg/ext/awt/color/ColorContext.java @@ -0,0 +1,36 @@ +/* + + See the NOTICE file distributed with this work for additional + information regarding copyright ownership. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + */ +package io.sf.carte.echosvg.ext.awt.color; + +import java.awt.color.ColorSpace; + +/** + * AWT color context. + */ +public interface ColorContext { + + /** + * The target color space. + * + * @return the color space, or {@code null} if the color space is the default + * sRGB. + */ + ColorSpace getColorSpace(); + +} diff --git a/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/CSSColorSpaces.java b/echosvg-awt-util/src/main/java/io/sf/carte/echosvg/ext/awt/color/StandardColorSpaces.java similarity index 65% rename from echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/CSSColorSpaces.java rename to echosvg-awt-util/src/main/java/io/sf/carte/echosvg/ext/awt/color/StandardColorSpaces.java index 8a2e51380..7bd0c0f9a 100644 --- a/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/CSSColorSpaces.java +++ b/echosvg-awt-util/src/main/java/io/sf/carte/echosvg/ext/awt/color/StandardColorSpaces.java @@ -16,7 +16,7 @@ limitations under the License. */ -package io.sf.carte.echosvg.bridge; +package io.sf.carte.echosvg.ext.awt.color; import java.awt.Color; import java.awt.color.ColorSpace; @@ -28,7 +28,7 @@ /** * Predefined ICC color spaces. */ -class CSSColorSpaces { +public class StandardColorSpaces { private static ICC_ColorSpace a98rgb; @@ -38,81 +38,99 @@ class CSSColorSpaces { private static ICC_ColorSpace rec2020; - CSSColorSpaces() { + private static ICC_ColorSpace xyzD65; + + StandardColorSpaces() { super(); } + /** + * Get the A98 RGB color space. + * + * @return the instance of the color space. + */ public static ICC_ColorSpace getA98RGB() { - ICC_Profile prof; if (a98rgb == null) { - try (InputStream is = CSSColorSpaces.class.getResourceAsStream( - "color/profiles/A98RGBCompat-v4.icc")) { - prof = ICC_Profile.getInstance(is); - } catch (IOException e) { - e.printStackTrace(); - return null; - } - a98rgb = new ICC_ColorSpace(prof); + a98rgb = loadColorSpace("profiles/A98RGBCompat-v4.icc"); } return a98rgb; } + /** + * Get the ProPhoto RGB color space. + * + * @return the instance of the color space. + */ public static ICC_ColorSpace getProphotoRGB() { - ICC_Profile prof; if (prophotoRGB == null) { - try (InputStream is = CSSColorSpaces.class.getResourceAsStream( - "color/profiles/WideGamutPhoto-v4.icc")) { - prof = ICC_Profile.getInstance(is); - } catch (IOException e) { - e.printStackTrace(); - return null; - } - prophotoRGB = new ICC_ColorSpace(prof); + prophotoRGB = loadColorSpace("profiles/WideGamutPhoto-v4.icc"); } return prophotoRGB; } + /** + * Get the Display P3 color space. + * + * @return the instance of the color space. + */ public static ICC_ColorSpace getDisplayP3() { - ICC_Profile prof; if (displayP3 == null) { - try (InputStream is = CSSColorSpaces.class.getResourceAsStream( - "color/profiles/Display P3.icc")) { - prof = ICC_Profile.getInstance(is); - } catch (IOException e) { - e.printStackTrace(); - return null; - } - displayP3 = new ICC_ColorSpace(prof); + displayP3 = loadColorSpace("profiles/Display P3.icc"); } return displayP3; } + /** + * Get the ITU recommendation bt.2020 color space. + * + * @return the instance of the color space. + */ public static ICC_ColorSpace getRec2020() { - ICC_Profile prof; if (rec2020 == null) { - try (InputStream is = CSSColorSpaces.class.getResourceAsStream( - "color/profiles/ITU-R_BT2020.icc")) { - prof = ICC_Profile.getInstance(is); - } catch (IOException e) { - e.printStackTrace(); - return null; - } - rec2020 = new ICC_ColorSpace(prof); + rec2020 = loadColorSpace("profiles/ITU-R_BT2020.icc"); } return rec2020; } /** - * Merge the two color spaces. + * Get the XYZ color space with a D65 white. + * + * @return the instance of the color space. + */ + public static ICC_ColorSpace getXYZ_D65() { + if (xyzD65 == null) { + xyzD65 = loadColorSpace("profiles/D65_XYZ.icc"); + } + return xyzD65; + } + + private static ICC_ColorSpace loadColorSpace(String resource) { + ICC_Profile prof; + try (InputStream is = StandardColorSpaces.class.getResourceAsStream(resource)) { + prof = ICC_Profile.getInstance(is); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + return new ICC_ColorSpace(prof); + } + + /** + * Do an approximate merge of the two color spaces. + * + * The merged color space must enclose the first space, and should be the + * smallest merge that is able to represent the given color. That color is + * intended to be represented by the second color space (although currently may + * not be expressed in that space). * * @param colorSpace1 the first color space, or {@code null}. * @param colorSpace2 the second color space. Cannot be equal to colorSpace1 * (check that before calling). - * @param color the color that needs to be represented by the merged - * space. - * @return the recommended merged color space, or {@code null} if sRGB is recommended. + * @param color a color that needs to be represented by the merged space. + * @return the recommended merged color space, or {@code null} if sRGB is + * recommended. */ - static ColorSpace mergeColorSpace(ColorSpace colorSpace1, ColorSpace colorSpace2, Color color) { + public static ColorSpace mergeColorSpace(ColorSpace colorSpace1, ColorSpace colorSpace2, Color color) { // For a reasoning, you may want to look at // https://upload.wikimedia.org/wikipedia/commons/b/b3/CIE1931xy_gamut_comparison_of_sRGB_P3_Rec2020.svg if (colorSpace1 == null) { @@ -146,7 +164,7 @@ static ColorSpace mergeColorSpace(ColorSpace colorSpace1, ColorSpace colorSpace2 } /** - * Determine which color space is the most adequate to represent the given + * Determine which RGB color space is the most adequate to represent the given * color, starting with sRGB and then giving precedence to the supplied color * space over others. * @@ -154,7 +172,7 @@ static ColorSpace mergeColorSpace(ColorSpace colorSpace1, ColorSpace colorSpace2 * @param colorSpace the suggested color space. * @return the recommended color space, or {@code null} if it is sRGB. */ - static ColorSpace containerRGBSpace(Color xyz, ColorSpace colorSpace) { + public static ColorSpace containerRGBSpace(Color xyz, ColorSpace colorSpace) { // Verify whether xyz is in sRGB gamut, otherwise check P3, A98, rec2020, prophoto. ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); if (isInGamut(xyz, cs)) { @@ -195,8 +213,8 @@ static ColorSpace containerRGBSpace(Color xyz, ColorSpace colorSpace) { * This method is only approximate. *
* - * @param color the color to check. - * @param space the color space. Cannot be {@code null}. + * @param color the color to check (cannot be {@code null}). + * @param space the color space (cannot be {@code null}). * @return {@code false} if the color may not be representable in the given * color space. */ @@ -207,7 +225,7 @@ private static boolean isInGamut(Color color, ColorSpace space) { for (float comp : comps) { if (comp <= min || comp >= max) { - // Symptom that the color is at the edge of the gamut + // Symptom that the color is outside or at the edge of the gamut return false; } } diff --git a/echosvg-bridge/src/main/resources/io/sf/carte/echosvg/bridge/color/profiles/A98RGBCompat-v4.icc b/echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/A98RGBCompat-v4.icc similarity index 100% rename from echosvg-bridge/src/main/resources/io/sf/carte/echosvg/bridge/color/profiles/A98RGBCompat-v4.icc rename to echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/A98RGBCompat-v4.icc diff --git a/echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/D65_XYZ.icc b/echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/D65_XYZ.icc new file mode 100644 index 000000000..8f200f32f Binary files /dev/null and b/echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/D65_XYZ.icc differ diff --git a/echosvg-bridge/src/main/resources/io/sf/carte/echosvg/bridge/color/profiles/Display P3.icc b/echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/Display P3.icc similarity index 100% rename from echosvg-bridge/src/main/resources/io/sf/carte/echosvg/bridge/color/profiles/Display P3.icc rename to echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/Display P3.icc diff --git a/echosvg-bridge/src/main/resources/io/sf/carte/echosvg/bridge/color/profiles/ITU-R_BT2020.icc b/echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/ITU-R_BT2020.icc similarity index 100% rename from echosvg-bridge/src/main/resources/io/sf/carte/echosvg/bridge/color/profiles/ITU-R_BT2020.icc rename to echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/ITU-R_BT2020.icc diff --git a/echosvg-bridge/src/main/resources/io/sf/carte/echosvg/bridge/color/profiles/NOTICE.txt b/echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/NOTICE.txt similarity index 70% rename from echosvg-bridge/src/main/resources/io/sf/carte/echosvg/bridge/color/profiles/NOTICE.txt rename to echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/NOTICE.txt index 6b3bee480..e00ee86f8 100644 --- a/echosvg-bridge/src/main/resources/io/sf/carte/echosvg/bridge/color/profiles/NOTICE.txt +++ b/echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/NOTICE.txt @@ -4,5 +4,5 @@ file. The Display P3 profile was made by Apple and was obtained from color.org (ICC). -The profile for the ITU-R Recommendation BT.2020 was also obtained from -color.org (ICC). +The profiles for the ITU-R Recommendation BT.2020 and XYZ-D65 were also obtained +from color.org (ICC). diff --git a/echosvg-bridge/src/main/resources/io/sf/carte/echosvg/bridge/color/profiles/WideGamutPhoto-v4.icc b/echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/WideGamutPhoto-v4.icc similarity index 100% rename from echosvg-bridge/src/main/resources/io/sf/carte/echosvg/bridge/color/profiles/WideGamutPhoto-v4.icc rename to echosvg-awt-util/src/main/resources/io/sf/carte/echosvg/ext/awt/color/profiles/WideGamutPhoto-v4.icc diff --git a/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/BridgeContext.java b/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/BridgeContext.java index 546cec4bc..4ffd38da1 100644 --- a/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/BridgeContext.java +++ b/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/BridgeContext.java @@ -70,6 +70,8 @@ import io.sf.carte.echosvg.dom.events.NodeEventTarget; import io.sf.carte.echosvg.dom.svg.SVGContext; import io.sf.carte.echosvg.dom.xbl.XBLManager; +import io.sf.carte.echosvg.ext.awt.color.StandardColorSpaces; +import io.sf.carte.echosvg.ext.awt.color.ColorContext; import io.sf.carte.echosvg.gvt.CompositeGraphicsNode; import io.sf.carte.echosvg.gvt.GraphicsNode; import io.sf.carte.echosvg.script.Interpreter; @@ -92,7 +94,7 @@ * @author For later modifications, see Git history. * @version $Id$ */ -public class BridgeContext implements ErrorConstants, CSSContext, Closeable { +public class BridgeContext implements ErrorConstants, CSSContext, ColorContext, Closeable { /** * The document is bridge context is dedicated to. @@ -410,16 +412,19 @@ public CSSEngine getCSSEngineForElement(Element e) { */ public void updateColorSpace(Color color, ColorSpace csRGB) { if (colorSpace != csRGB) { - colorSpace = CSSColorSpaces.mergeColorSpace(colorSpace, csRGB, color); + colorSpace = StandardColorSpaces.mergeColorSpace(colorSpace, csRGB, color); } } + // ColorContext ////////////////////////////////////////////////////////// + /** * Get the recommended color space for this context. * * @return the recommended color space, or {@code null} if the color space is * the default sRGB. */ + @Override public ColorSpace getColorSpace() { return colorSpace; } diff --git a/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/PaintServer.java b/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/PaintServer.java index 3a79cdac2..8482d810c 100644 --- a/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/PaintServer.java +++ b/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/PaintServer.java @@ -43,6 +43,7 @@ import io.sf.carte.echosvg.css.engine.value.svg.ICCColor; import io.sf.carte.echosvg.css.engine.value.svg12.DeviceColor; import io.sf.carte.echosvg.css.engine.value.svg12.ICCNamedColor; +import io.sf.carte.echosvg.ext.awt.color.StandardColorSpaces; import io.sf.carte.echosvg.gvt.CompositeShapePainter; import io.sf.carte.echosvg.gvt.FillShapePainter; import io.sf.carte.echosvg.gvt.GraphicsNode; @@ -172,7 +173,7 @@ public static ShapePainter convertFillAndStroke(Element e, ShapeNode node, Bridg return null; Paint fillPaint = convertFillPaint(e, node, ctx); - FillShapePainter fp = new FillShapePainter(shape); + FillShapePainter fp = new FillShapePainter(shape, ctx); fp.setPaint(fillPaint); Stroke stroke = convertStroke(e); @@ -180,7 +181,7 @@ public static ShapePainter convertFillAndStroke(Element e, ShapeNode node, Bridg return fp; Paint strokePaint = convertStrokePaint(e, node, ctx); - StrokeShapePainter sp = new StrokeShapePainter(shape); + StrokeShapePainter sp = new StrokeShapePainter(shape, ctx); sp.setStroke(stroke); sp.setPaint(strokePaint); @@ -200,7 +201,7 @@ public static ShapePainter convertStrokePainter(Element e, ShapeNode node, Bridg return null; Paint strokePaint = convertStrokePaint(e, node, ctx); - StrokeShapePainter sp = new StrokeShapePainter(shape); + StrokeShapePainter sp = new StrokeShapePainter(shape, ctx); sp.setStroke(stroke); sp.setPaint(strokePaint); return sp; @@ -577,22 +578,22 @@ public static Color convertColor(RGBColorValue c, float opacity) { public static Color convertColor(ColorFunction c, float opacity, BridgeContext ctx) { switch (c.getCSSColorSpace()) { case ColorValue.CS_DISPLAY_P3: - ICC_ColorSpace space = CSSColorSpaces.getDisplayP3(); + ICC_ColorSpace space = StandardColorSpaces.getDisplayP3(); Color color = convert3Color(space, c, opacity); ctx.updateColorSpace(color, space); return color; case ColorValue.CS_A98_RGB: - space = CSSColorSpaces.getA98RGB(); + space = StandardColorSpaces.getA98RGB(); color = convert3Color(space, c, opacity); ctx.updateColorSpace(color, space); return color; case ColorValue.CS_PROPHOTO_RGB: - space = CSSColorSpaces.getProphotoRGB(); + space = StandardColorSpaces.getProphotoRGB(); color = convert3Color(space, c, opacity); ctx.updateColorSpace(color, space); return color; case ColorValue.CS_REC2020: - space = CSSColorSpaces.getRec2020(); + space = StandardColorSpaces.getRec2020(); color = convert3Color(space, c, opacity); ctx.updateColorSpace(color, space); return color; @@ -610,7 +611,7 @@ public static Color convertColor(ColorFunction c, float opacity, BridgeContext c float a = resolveAlphaComponent(c.getAlpha()); cs = ColorSpace.getInstance(ColorSpace.CS_CIEXYZ); color = new Color(cs, xyzd50, a * opacity); - cs = CSSColorSpaces.containerRGBSpace(color, ctx.getColorSpace()); + cs = StandardColorSpaces.containerRGBSpace(color, ctx.getColorSpace()); if (cs != null) { ctx.updateColorSpace(color, cs); } @@ -618,7 +619,7 @@ public static Color convertColor(ColorFunction c, float opacity, BridgeContext c case ColorValue.CS_XYZ_D50: cs = ColorSpace.getInstance(ColorSpace.CS_CIEXYZ); color = convert3Color(cs, c, opacity); - cs = CSSColorSpaces.containerRGBSpace(color, ctx.getColorSpace()); + cs = StandardColorSpaces.containerRGBSpace(color, ctx.getColorSpace()); if (cs != null) { ctx.updateColorSpace(color, cs); } diff --git a/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/SVGTextElementBridge.java b/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/SVGTextElementBridge.java index ee9cd9aa7..c4cbd8486 100644 --- a/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/SVGTextElementBridge.java +++ b/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/SVGTextElementBridge.java @@ -610,7 +610,7 @@ protected void computeLaidoutText(BridgeContext ctx, Element e, GraphicsNode nod // Now get the real paint into - this needs to // wait until the text node is laidout so we can get // objectBoundingBox info. - TextPaintInfo pi = new TextPaintInfo(); + TextPaintInfo pi = new TextPaintInfo(ctx); setBaseTextPaintInfo(pi, e, node, ctx); // This get's Overline/underline info. setDecorationTextPaintInfo(pi, e); @@ -759,7 +759,7 @@ protected void rebuildACI() { TextPaintInfo pi, oldPI; if (cssProceedElement == e) { - pi = new TextPaintInfo(); + pi = new TextPaintInfo(ctx); setBaseTextPaintInfo(pi, e, node, ctx); setDecorationTextPaintInfo(pi, e); oldPI = elemTPI.get(e); @@ -1455,10 +1455,10 @@ protected Map+ * Original author: Thierry Kormann. + * For later modifications, see Git history. + *
* @version $Id$ */ -public class FillShapePainter implements ShapePainter { - - /** - * The Shape to be painted. - */ - protected Shape shape; - - /** - * The paint attribute used to fill the shape. - */ - protected Paint paint; +public class FillShapePainter extends PaintShapePainter { /** * Constructs a newFillShapePainter
that can be used to fill a
* Shape
.
*
* @param shape Shape to be painted by this painter Should not be null.
+ * @param ctx the color context. Cannot be {@code null}.
*/
- public FillShapePainter(Shape shape) {
- if (shape == null)
- throw new IllegalArgumentException("Shape can not be null!");
-
- this.shape = shape;
+ public FillShapePainter(Shape shape, ColorContext ctx) {
+ super(shape, ctx);
}
/**
* Sets the paint used to fill a shape.
*
- * @param newPaint the paint object used to fill the shape
+ * @param newPaint the paint object used to fill the shape.
*/
public void setPaint(Paint newPaint) {
- this.paint = newPaint;
+ super.setPaint(newPaint);
}
/**
- * Gets the paint used to draw the outline of the shape.
+ * Gets the paint used to fill the shape.
*/
public Paint getPaint() {
- return paint;
+ return super.getPaint();
}
/**
@@ -80,7 +72,7 @@ public Paint getPaint() {
@Override
public void paint(Graphics2D g2d) {
if (paint != null) {
- g2d.setPaint(paint);
+ g2d.setPaint(getPaint());
g2d.fill(shape);
}
}
@@ -147,28 +139,4 @@ public boolean inSensitiveArea(Point2D pt) {
return shape.contains(pt);
}
- /**
- * Sets the Shape this shape painter is associated with.
- *
- * @param shape new shape this painter should be associated with. Should not be
- * null.
- */
- @Override
- public void setShape(Shape shape) {
- if (shape == null) {
- throw new IllegalArgumentException();
- }
- this.shape = shape;
- }
-
- /**
- * Gets the Shape this shape painter is associated with.
- *
- * @return shape associated with this Painter.
- */
- @Override
- public Shape getShape() {
- return shape;
- }
-
}
diff --git a/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/PaintShapePainter.java b/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/PaintShapePainter.java
new file mode 100644
index 000000000..1ace011de
--- /dev/null
+++ b/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/PaintShapePainter.java
@@ -0,0 +1,123 @@
+/*
+
+ See the NOTICE file distributed with this work for additional
+ information regarding copyright ownership.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ */
+package io.sf.carte.echosvg.gvt;
+
+import java.awt.Color;
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.color.ColorSpace;
+
+import io.sf.carte.echosvg.ext.awt.color.ColorContext;
+
+/**
+ * A shape painter that has a paint.
+ *
+ * @version $Id$
+ */
+abstract class PaintShapePainter implements ShapePainter {
+
+ /**
+ * The Shape to be painted.
+ */
+ protected Shape shape;
+
+ /**
+ * The paint attribute used to fill or stroke the shape.
+ */
+ protected Paint paint;
+
+ /**
+ * The color context.
+ */
+ private ColorContext context;
+
+ /**
+ * Constructs a new PaintShapePainter
that can be used to color a
+ * Shape
.
+ *
+ * @param shape Shape to be painted by this painter Should not be null.
+ * @param ctx the color context. Cannot be {@code null}.
+ */
+ protected PaintShapePainter(Shape shape, ColorContext ctx) {
+ if (shape == null)
+ throw new IllegalArgumentException("Shape can not be null!");
+ if (ctx == null)
+ throw new IllegalArgumentException("Color context can not be null!");
+
+ this.shape = shape;
+ this.context = ctx;
+ }
+
+ /**
+ * Sets the paint used to fill or stroke a shape.
+ *
+ * @param newPaint the paint object used to fill the shape
+ */
+ public void setPaint(Paint newPaint) {
+ this.paint = newPaint;
+ }
+
+ /**
+ * Gets the paint used to fill or draw the outline of the shape.
+ */
+ public Paint getPaint() {
+ if (paint instanceof Color) {
+ Color color = (Color) paint;
+ ColorSpace space = color.getColorSpace();
+ ColorSpace targetSpace = context.getColorSpace();
+ if (targetSpace == null) {
+ // sRGB
+ if (!space.isCS_sRGB()) {
+ float[] comp = color.getRGBComponents(null);
+ color = new Color(comp[0], comp[1], comp[2], comp[3]);
+ }
+ } else {
+ color = new Color(targetSpace, color.getColorComponents(targetSpace, null),
+ color.getAlpha() / 255f);
+ }
+ return color;
+ }
+ return paint;
+ }
+
+ /**
+ * Sets the Shape this shape painter is associated with.
+ *
+ * @param shape new shape this painter should be associated with. Should not be
+ * null.
+ */
+ @Override
+ public void setShape(Shape shape) {
+ if (shape == null) {
+ throw new IllegalArgumentException();
+ }
+ this.shape = shape;
+ }
+
+ /**
+ * Gets the Shape this shape painter is associated with.
+ *
+ * @return shape associated with this Painter.
+ */
+ @Override
+ public Shape getShape() {
+ return shape;
+ }
+
+}
diff --git a/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/StrokeShapePainter.java b/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/StrokeShapePainter.java
index 36561938d..d17c91fb9 100644
--- a/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/StrokeShapePainter.java
+++ b/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/StrokeShapePainter.java
@@ -25,19 +25,18 @@
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
+import io.sf.carte.echosvg.ext.awt.color.ColorContext;
+
/**
* A shape painter that can be used to draw the outline of a shape.
*
- * @author Thierry Kormann
- * @author For later modifications, see Git history.
+ * + * Original author: Thierry Kormann. + * For later modifications, see Git history. + *
* @version $Id$ */ -public class StrokeShapePainter implements ShapePainter { - - /** - * Shape painted by this painter. - */ - protected Shape shape; +public class StrokeShapePainter extends PaintShapePainter { /** * Stroked version of the shape. @@ -49,22 +48,15 @@ public class StrokeShapePainter implements ShapePainter { */ protected Stroke stroke; - /** - * The paint attribute used to draw the outline of the shape. - */ - protected Paint paint; - /** * Constructs a newShapePainter
that can be used to draw the
* outline of a Shape
.
*
* @param shape shape to be painted by this painter. Should not be null.
+ * @param ctx the color context. Cannot be {@code null}.
*/
- public StrokeShapePainter(Shape shape) {
- if (shape == null) {
- throw new IllegalArgumentException();
- }
- this.shape = shape;
+ public StrokeShapePainter(Shape shape, ColorContext ctx) {
+ super(shape, ctx);
}
/**
@@ -97,7 +89,7 @@ public void setPaint(Paint newPaint) {
* Gets the paint used to draw the outline of the shape.
*/
public Paint getPaint() {
- return paint;
+ return super.getPaint();
}
/**
@@ -108,7 +100,7 @@ public Paint getPaint() {
@Override
public void paint(Graphics2D g2d) {
if (stroke != null && paint != null) {
- g2d.setPaint(paint);
+ g2d.setPaint(getPaint());
g2d.setStroke(stroke);
g2d.draw(shape);
}
@@ -198,21 +190,8 @@ public boolean inSensitiveArea(Point2D pt) {
*/
@Override
public void setShape(Shape shape) {
- if (shape == null) {
- throw new IllegalArgumentException();
- }
- this.shape = shape;
+ super.setShape(shape);
this.strokedShape = null;
}
- /**
- * Gets the Shape this shape painter is associated with.
- *
- * @return shape associated with this painter.
- */
- @Override
- public Shape getShape() {
- return shape;
- }
-
}
diff --git a/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/font/AWTGVTGlyphVector.java b/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/font/AWTGVTGlyphVector.java
index baec99bbf..82ad4de4d 100644
--- a/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/font/AWTGVTGlyphVector.java
+++ b/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/font/AWTGVTGlyphVector.java
@@ -793,9 +793,9 @@ public void draw(Graphics2D graphics2D, AttributedCharacterIterator aci) {
if (!tpi.visible)
return;
- Paint fillPaint = tpi.fillPaint;
+ Paint fillPaint = tpi.getFillPaint();
Stroke stroke = tpi.strokeStroke;
- Paint strokePaint = tpi.strokePaint;
+ Paint strokePaint = tpi.getStrokePaint();
if ((fillPaint == null) && ((strokePaint == null) || (stroke == null)))
return;
diff --git a/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/font/Glyph.java b/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/font/Glyph.java
index 2c055be5e..22d7c28c5 100644
--- a/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/font/Glyph.java
+++ b/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/font/Glyph.java
@@ -19,6 +19,7 @@
package io.sf.carte.echosvg.gvt.font;
import java.awt.Graphics2D;
+import java.awt.Paint;
import java.awt.Shape;
import java.awt.font.GlyphMetrics;
import java.awt.geom.AffineTransform;
@@ -359,15 +360,16 @@ public void draw(Graphics2D graphics2D) {
// paint the dShape first
if ((dShape != null) && (tpi != null)) {
Shape tShape = tr.createTransformedShape(dShape);
- if (tpi.fillPaint != null) {
- graphics2D.setPaint(tpi.fillPaint);
+ Paint fillPaint = tpi.getFillPaint();
+ if (fillPaint != null) {
+ graphics2D.setPaint(fillPaint);
graphics2D.fill(tShape);
}
// check if we need to draw the outline of this glyph
if (tpi.strokeStroke != null && tpi.strokePaint != null) {
graphics2D.setStroke(tpi.strokeStroke);
- graphics2D.setPaint(tpi.strokePaint);
+ graphics2D.setPaint(tpi.getStrokePaint());
graphics2D.draw(tShape);
}
}
diff --git a/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/text/TextPaintInfo.java b/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/text/TextPaintInfo.java
index d9c906d9f..d7487c09d 100644
--- a/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/text/TextPaintInfo.java
+++ b/echosvg-gvt/src/main/java/io/sf/carte/echosvg/gvt/text/TextPaintInfo.java
@@ -18,9 +18,13 @@
*/
package io.sf.carte.echosvg.gvt.text;
+import java.awt.Color;
import java.awt.Composite;
import java.awt.Paint;
import java.awt.Stroke;
+import java.awt.color.ColorSpace;
+
+import io.sf.carte.echosvg.ext.awt.color.ColorContext;
/**
* One line Class Desc
@@ -53,7 +57,13 @@ public class TextPaintInfo {
public int startChar, endChar;
- public TextPaintInfo() {
+ /**
+ * The color context.
+ */
+ private ColorContext context;
+
+ public TextPaintInfo(ColorContext context) {
+ this.context = context;
}
public TextPaintInfo(TextPaintInfo pi) {
@@ -80,6 +90,7 @@ public void set(TextPaintInfo pi) {
this.strikethroughStroke = null;
this.visible = false;
+ this.context = null;
} else {
this.fillPaint = pi.fillPaint;
this.strokePaint = pi.strokePaint;
@@ -99,7 +110,88 @@ public void set(TextPaintInfo pi) {
this.strikethroughStroke = pi.strikethroughStroke;
this.visible = pi.visible;
+ this.context = pi.context;
+ }
+ }
+
+ public Paint getFillPaint() {
+ if (fillPaint instanceof Color) {
+ Color color = (Color) fillPaint;
+ ColorSpace space = color.getColorSpace();
+ ColorSpace targetSpace = context.getColorSpace();
+ if (targetSpace == null) {
+ // sRGB
+ if (!space.isCS_sRGB()) {
+ float[] comp = color.getRGBComponents(null);
+ color = new Color(comp[0], comp[1], comp[2], comp[3]);
+ }
+ } else {
+ color = new Color(targetSpace, color.getColorComponents(targetSpace, null),
+ color.getAlpha() / 255f);
+ }
+ return color;
}
+ return fillPaint;
+ }
+
+ public void setFillPaint(Paint fillPaint) {
+ this.fillPaint = fillPaint;
+ }
+
+ public Paint getStrokePaint() {
+ return strokePaint;
+ }
+
+ public void setStrokePaint(Paint strokePaint) {
+ this.strokePaint = strokePaint;
+ }
+
+ public Paint getUnderlinePaint() {
+ return underlinePaint;
+ }
+
+ public void setUnderlinePaint(Paint underlinePaint) {
+ this.underlinePaint = underlinePaint;
+ }
+
+ public Paint getUnderlineStrokePaint() {
+ return underlineStrokePaint;
+ }
+
+ public void setUnderlineStrokePaint(Paint underlineStrokePaint) {
+ this.underlineStrokePaint = underlineStrokePaint;
+ }
+
+ public Paint getOverlinePaint() {
+ return overlinePaint;
+ }
+
+ public void setOverlinePaint(Paint overlinePaint) {
+ this.overlinePaint = overlinePaint;
+ }
+
+ public Paint getOverlineStrokePaint() {
+ return overlineStrokePaint;
+ }
+
+ public void setOverlineStrokePaint(Paint overlineStrokePaint) {
+ this.overlineStrokePaint = overlineStrokePaint;
+ }
+
+ public Paint getStrikethroughPaint() {
+ return strikethroughPaint;
+ }
+
+ public void setStrikethroughPaint(Paint strikethroughPaint) {
+ this.strikethroughPaint = strikethroughPaint;
+ }
+
+ public Paint getStrikethroughStrokePaint() {
+ return strikethroughStrokePaint;
+ }
+
+ public void setStrikethroughStrokePaint(Paint strikethroughStrokePaint) {
+ this.strikethroughStrokePaint = strikethroughStrokePaint;
}
public static boolean equivilent(TextPaintInfo tpi1, TextPaintInfo tpi2) {
diff --git a/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/SamplesSpecRenderingTest.java b/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/SamplesSpecRenderingTest.java
index 4d7d9a236..53ef9c2a4 100644
--- a/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/SamplesSpecRenderingTest.java
+++ b/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/SamplesSpecRenderingTest.java
@@ -59,7 +59,6 @@ public void testColorProfile() throws TranscoderException, IOException {
test("samples/tests/spec/color/colorProfile.svg");
}
- @Disabled
@Test
public void testColorProfiles() throws TranscoderException, IOException {
testNV("samples/tests/spec/color/colorProfiles.svg");
diff --git a/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/StyleBypassRenderingTest.java b/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/StyleBypassRenderingTest.java
index 54bc0eba8..1b03a9f29 100644
--- a/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/StyleBypassRenderingTest.java
+++ b/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/StyleBypassRenderingTest.java
@@ -279,6 +279,11 @@ public void testColorProfile() throws TranscoderException, IOException {
test("samples/tests/spec/color/colorProfile.svg");
}
+ @Test
+ public void testColorProfiles() throws TranscoderException, IOException {
+ testNV("samples/tests/spec/color/colorProfiles.svg");
+ }
+
@Test
public void testColors() throws TranscoderException, IOException {
test("samples/tests/spec/color/colors.svg");
diff --git a/samples/tests/spec/color/colorProfiles-ref.svg b/samples/tests/spec/color/colorProfiles-ref.svg
new file mode 100644
index 000000000..13c905041
--- /dev/null
+++ b/samples/tests/spec/color/colorProfiles-ref.svg
@@ -0,0 +1,87 @@
+
+
diff --git a/samples/tests/spec/color/colorProfiles.svg b/samples/tests/spec/color/colorProfiles.svg
index 6f1e80dc9..54697969b 100644
--- a/samples/tests/spec/color/colorProfiles.svg
+++ b/samples/tests/spec/color/colorProfiles.svg
@@ -1,5 +1,5 @@
-