diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index 591c4e25f4ef7b9780e6870b47f142c4998ecb4f..31540170256e9b30ce9c063c83d3752697c4f48f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -29,7 +29,6 @@ import com.oracle.truffle.r.library.fastrGrid.Unit.IsRelativeUnitNode;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutPos;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutSize;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -65,11 +64,11 @@ class DoSetViewPort extends RBaseNode {
         }
 
         GridDevice currentDevice = GridContext.getContext().getCurrentDevice();
-        DrawingContext deviceDrawingContext = GridState.getInitialGPar(currentDevice);
+        GPar gpar = GridState.getInitialGPar(currentDevice);
 
         RList parent = asListOrNull(pushedViewPort.getDataAt(ViewPort.PVP_PARENT));
         boolean doNotRecalculateParent = hasParent && !ViewPort.updateDeviceSizeInVP(parent, currentDevice);
-        calcViewportTransform(pushedViewPort, parent, doNotRecalculateParent, currentDevice, deviceDrawingContext);
+        calcViewportTransform(pushedViewPort, parent, doNotRecalculateParent, currentDevice, gpar);
 
         // TODO: clipping
         pushedVPData[ViewPort.PVP_CLIPRECT] = RDataFactory.createDoubleVector(new double[]{0, 0, 0, 0}, RDataFactory.COMPLETE_VECTOR);
@@ -87,37 +86,37 @@ class DoSetViewPort extends RBaseNode {
      * @param incremental If {@code true} it is assumed that we can just take the transformation
      *            matrix and other values from the parent without re-calculating them recursively.
      * @param device This method needs the device in order to convert units
-     * @param deviceDrawingContext This method needs to know the device default drawing context in
+     * @param deviceTopLevelGpar This method needs to know the device default drawing context in
      *            order to convert units for the top level view port
      */
     @TruffleBoundary
-    public void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, DrawingContext deviceDrawingContext) {
+    public void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, GPar deviceTopLevelGpar) {
         double[][] parentTransform;
         ViewPortContext parentContext;
         ViewPortLocation vpl;
         Size parentSize;
-        DrawingContext drawingContext;
+        GPar drawingContext;
         double parentAngle;
         if (parent == null || parent == RNull.instance) {
             parentTransform = TransformMatrix.identity();
             parentContext = ViewPortContext.createDefault();
             parentSize = new Size(device.getWidth(), device.getHeight());
             vpl = ViewPortLocation.fromViewPort(viewPort);
-            drawingContext = deviceDrawingContext;
+            drawingContext = deviceTopLevelGpar;
             parentAngle = 0;
         } else {
             assert parent instanceof RList : "inconsistent data: parent of a viewport must be a list";
             RList parentVPList = (RList) parent;
             Object[] parentData = parentVPList.getDataWithoutCopying();
             if (!incremental) {
-                calcViewportTransform(parentVPList, parentData[ViewPort.PVP_PARENT], false, device, deviceDrawingContext);
+                calcViewportTransform(parentVPList, parentData[ViewPort.PVP_PARENT], false, device, deviceTopLevelGpar);
             }
             parentSize = new Size(Unit.cmToInches(castScalar(parentData[ViewPort.PVP_WIDTHCM])), Unit.cmToInches(castScalar(parentData[ViewPort.PVP_HEIGHTCM])));
             parentTransform = fromFlat(castDoubleVector(parentData[ViewPort.PVP_TRANS]).materialize().getDataWithoutCopying());
             parentContext = ViewPortContext.fromViewPort(parentVPList);
             parentAngle = asDouble(parentData[ViewPort.PVP_ROTATION]);
 
-            drawingContext = GPar.asDrawingContext(asList(viewPort.getDataAt(ViewPort.PVP_PARENTGPAR)));
+            drawingContext = GPar.create(asList(viewPort.getDataAt(ViewPort.PVP_PARENTGPAR)));
             boolean noLayout = (isNull(viewPort.getDataAt(ViewPort.VP_VALIDLPOSROW)) && isNull(viewPort.getDataAt(ViewPort.VP_VALIDLPOSCOL))) || isNull(parentData[ViewPort.VP_LAYOUT]);
             if (noLayout) {
                 vpl = ViewPortLocation.fromViewPort(viewPort);
@@ -157,8 +156,7 @@ class DoSetViewPort extends RBaseNode {
         // Finally, allocate the rows and columns for this viewport's layout if it has one
         if (!isNull(viewPort.getDataAt(ViewPort.VP_LAYOUT))) {
             ViewPortContext vpCtx = ViewPortContext.fromViewPort(viewPort);
-            DrawingContext drawingCtx = GPar.asDrawingContext(asList(viewPort.getDataAt(ViewPort.PVP_GPAR)));
-            calcViewPortLayout(viewPort, new Size(width, height), vpCtx, device, drawingCtx);
+            calcViewPortLayout(viewPort, new Size(width, height), vpCtx, device, GPar.create(asList(viewPort.getDataAt(ViewPort.PVP_GPAR))));
         }
 
         Object[] viewPortData = viewPort.getDataWithoutCopying();
@@ -168,13 +166,13 @@ class DoSetViewPort extends RBaseNode {
         viewPortData[ViewPort.PVP_TRANS] = RDataFactory.createDoubleVector(flatten(transform), RDataFactory.COMPLETE_VECTOR, new int[]{3, 3});
     }
 
-    private void calcViewPortLayout(RList viewPort, Size size, ViewPortContext parentVPCtx, GridDevice device, DrawingContext drawingCtx) {
+    private void calcViewPortLayout(RList viewPort, Size size, ViewPortContext parentVPCtx, GridDevice device, GPar gpar) {
         LayoutSize layoutSize = LayoutSize.fromViewPort(viewPort);
         double[] npcWidths = new double[layoutSize.ncol];
         double[] npcHeights = new double[layoutSize.nrow];
         boolean[] relativeWidths = new boolean[layoutSize.ncol];
         boolean[] relativeHeights = new boolean[layoutSize.nrow];
-        UnitConversionContext conversionCtx = new UnitConversionContext(size, parentVPCtx, device, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(size, parentVPCtx, device, gpar);
 
         // For both dimensions we find out which units are other than "null" for those we can
         // immediately calculate the physical size in npcWidth/npcHeights. The reducedWidth/Height
@@ -195,8 +193,8 @@ class DoSetViewPort extends RBaseNode {
         int respect = RRuntime.asInteger(layoutAsList.getDataAt(ViewPort.LAYOUT_VRESPECT));
         int[] layoutRespectMat = ((RAbstractIntVector) layoutAsList.getDataAt(ViewPort.LAYOUT_MRESPECT)).materialize().getDataWithoutCopying();
         if ((reducedHeight > 0 || reducedWidth > 0) && respect > 0) {
-            double sumRelWidth = sumRelativeDimension(layoutWidths, relativeWidths, parentVPCtx, device, drawingCtx, true);
-            double sumRelHeight = sumRelativeDimension(layoutHeights, relativeHeights, parentVPCtx, device, drawingCtx, false);
+            double sumRelWidth = sumRelativeDimension(layoutWidths, relativeWidths, parentVPCtx, device, gpar, true);
+            double sumRelHeight = sumRelativeDimension(layoutHeights, relativeHeights, parentVPCtx, device, gpar, false);
             double tempWidth = reducedWidth;
             double tempHeight = reducedHeight;
             double denom;
@@ -250,8 +248,8 @@ class DoSetViewPort extends RBaseNode {
         }
 
         // Secondly, allocate remaining relative widths and heights in the remaining space
-        allocateRelativeDim(layoutSize, layoutWidths, npcWidths, relativeWidths, reducedWidth, respect, layoutRespectMat, device, drawingCtx, parentVPCtx, true);
-        allocateRelativeDim(layoutSize, layoutHeights, npcHeights, relativeHeights, reducedHeight, respect, layoutRespectMat, device, drawingCtx, parentVPCtx, false);
+        allocateRelativeDim(layoutSize, layoutWidths, npcWidths, relativeWidths, reducedWidth, respect, layoutRespectMat, device, gpar, parentVPCtx, true);
+        allocateRelativeDim(layoutSize, layoutHeights, npcHeights, relativeHeights, reducedHeight, respect, layoutRespectMat, device, gpar, parentVPCtx, false);
 
         // Create the result
         Object[] vpData = viewPort.getDataWithoutCopying();
@@ -260,9 +258,9 @@ class DoSetViewPort extends RBaseNode {
     }
 
     private void allocateRelativeDim(LayoutSize layoutSize, RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double reducedDim, int respect, int[] layoutRespectMat,
-                    GridDevice device, DrawingContext drawingCtx, ViewPortContext parentVPCtx, boolean isWidth) {
+                    GridDevice device, GPar gpar, ViewPortContext parentVPCtx, boolean isWidth) {
         assert relativeItems.length == npcItems.length;
-        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, drawingCtx, 1, 0);
+        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, gpar, 1, 0);
         double totalUnrespectedSize = 0;
         if (reducedDim > 0) {
             for (int i = 0; i < relativeItems.length; i++) {
@@ -311,9 +309,9 @@ class DoSetViewPort extends RBaseNode {
         return false;
     }
 
-    private double sumRelativeDimension(RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, DrawingContext drawingCtx,
+    private double sumRelativeDimension(RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, GPar gpar,
                     boolean isWidth) {
-        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, drawingCtx, 1, 0);
+        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, gpar, 1, 0);
         double totalWidth = 0;
         for (int i = 0; i < relativeItems.length; i++) {
             if (relativeItems[i]) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
index e177c722b19cefe51bc3679c57b7ba22255b7908..cda58b06a3b397ffdb2c31047af692a8d855f52b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
@@ -66,7 +66,7 @@ class DrawArrowsNode extends Node {
         arrowLength = Math.max(arrowLength, unitToInches.convertWidth(lengthVec, parentIndex, conversionCtx));
         // draw the arrows
         GridDevice device = conversionCtx.device;
-        DrawingContext drawingCtx = conversionCtx.drawingContext;
+        DrawingContext drawingCtx = conversionCtx.gpar.getDrawingContext(parentIndex);
         if (first && start) {
             drawArrow(drawingCtx, device, arrowType, x[startIndex], y[startIndex], x[startIndex + 1], y[startIndex + 1], angle, arrowLength);
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index 6f69df073cbb3035caf1effbb0d77ef62ec23009..de1e6a86ddf46357ab1ea4277748096595a9bc74 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -11,10 +11,12 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asString;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod;
 
 import java.util.Arrays;
+import java.util.function.Function;
 
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContextDefaults;
@@ -30,10 +32,20 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 /**
  * In the context of grid package, GPar is a list that contains the parameters for the drawing, like
- * line style, color, etc. This class wraps the list and provides type-safe access to its elements.
+ * line style, color, etc. This class wraps the list and provides way to convert it to
+ * {@link DrawingContext}. First create instance of {@link GPar} and then use
+ * {@link #getDrawingContext(int)} to get the drawing context. Note that grid's gpar can
+ * theoretically contain vector as the value of some graphical parameters, in such case, when
+ * drawing i-th element, e.g. i-th rectangle in {@link LRect}, we should use i-th (mod length)
+ * element of such vector. Note that this is sort of ignored in layout calculations, where we always
+ * take the first element. In other words, instance of {@link GPar} represents grid's gpar where the
+ * graphical parameter may be vectors, whereas {@link DrawingContext} is flattened view where it is
+ * already determined which index is used to access the vectors.
  */
 public final class GPar {
     private static final int GP_FILL = 0;
@@ -57,14 +69,21 @@ public final class GPar {
      * fontsize*cex*lineheight.
      */
     private static final int GP_LINEHEIGHT = 7;
+    /**
+     * In fact means font style: bold, italic, bolditalic or normal.
+     */
     private static final int GP_FONT = 8;
     private static final int GP_FONTFAMILY = 9;
     private static final int GP_ALPHA = 10;
     private static final int GP_LINEEND = 11;
     private static final int GP_LINEJOIN = 12;
     private static final int GP_LINEMITRE = 13;
+    /**
+     * Multiplier of line width {@link #GP_LWD}.
+     */
     private static final int GP_LEX = 14;
-    private static final int GP_FONTFACE = 15;
+
+    // Note: there is last slot "fontface" which is either unused at all, or only used in R code
     private static final int GP_LENGTH = 16;
     private static final String[] NAMES = new String[]{
                     "fill",
@@ -82,9 +101,43 @@ public final class GPar {
                     "linejoin",
                     "linemitre",
                     "lex",
-                    "fontface"  // TODO: could not find this name in grid sources
+                    "fontface"
     };
     private static final RStringVector NAMES_VECTOR = (RStringVector) RDataFactory.createStringVector(NAMES, RDataFactory.COMPLETE_VECTOR).makeSharedPermanent();
+    private final RList gpar;
+    // majority of gpar instances contains only scalar values, for those we make sure we do not
+    // create a new drawing context instance for every index.
+    private final boolean singleDrawingCtx;
+    private DrawingContext indexZeroDrawingCtx;
+
+    public GPar(RList gpar, boolean singleDrawingCtx) {
+        this.gpar = gpar;
+        this.gpar.makeSharedPermanent();
+        this.singleDrawingCtx = singleDrawingCtx;
+        indexZeroDrawingCtx = new GParDrawingContext(gpar, 0);
+    }
+
+    public static double getCex(RList gpar) {
+        return asDouble(gpar.getDataAt(GP_CEX));
+    }
+
+    public static GPar create(RList gpar) {
+        boolean singleDrawingCtx = true;
+        for (int i = 0; i < gpar.getLength(); i++) {
+            Object item = gpar.getDataAt(i);
+            if (item instanceof RAbstractVector) {
+                singleDrawingCtx &= ((RAbstractVector) item).getLength() == 1;
+            }
+        }
+        return new GPar(gpar, singleDrawingCtx);
+    }
+
+    public DrawingContext getDrawingContext(int cyclicIndex) {
+        if (singleDrawingCtx || cyclicIndex == 0) {
+            return indexZeroDrawingCtx;
+        }
+        return new GParDrawingContext(gpar, cyclicIndex);
+    }
 
     public static RList createNew(GridDevice device) {
         Object[] data = new Object[GP_LENGTH];
@@ -92,14 +145,14 @@ public final class GPar {
         Arrays.fill(data, RNull.instance);
         data[GP_COL] = defaults.color;
         data[GP_FILL] = defaults.fillColor;
-        data[GP_GAMMA] = newDoubleVec(0);
+        data[GP_GAMMA] = newDoubleVec(0);   // Note: we do not use this parameter
         data[GP_LTY] = "solid";
         data[GP_LWD] = newDoubleVec(1);
         data[GP_CEX] = newDoubleVec(1);
         data[GP_FONTSIZE] = newDoubleVec(16);
         data[GP_LINEHEIGHT] = newDoubleVec(1.2);
-        data[GP_FONT] = RDataFactory.createIntVectorFromScalar(1);  // TODO: font constants?
-        data[GP_FONTFAMILY] = ""; // means default font (probably)
+        data[GP_FONT] = RDataFactory.createIntVectorFromScalar(1);
+        data[GP_FONTFAMILY] = ""; // means default font
         data[GP_ALPHA] = newDoubleVec(1);
         data[GP_LINEEND] = "round";
         data[GP_LINEJOIN] = "round";
@@ -110,53 +163,46 @@ public final class GPar {
         return result;
     }
 
-    public static double getCex(RList gpar) {
-        return asDouble(gpar.getDataAt(GP_CEX));
-    }
-
-    public static DrawingContext asDrawingContext(RList gpar) {
-        return new GParDrawingContext(gpar);
-    }
-
     private static RAbstractDoubleVector newDoubleVec(double val) {
         return RDataFactory.createDoubleVectorFromScalar(val);
     }
 
     private static final class GParDrawingContext implements DrawingContext {
         private final Object[] data;
+        private final int index;
 
-        private GParDrawingContext(RList list) {
+        private GParDrawingContext(RList list, int index) {
             data = list.getDataWithoutCopying();
-            list.makeSharedPermanent();
+            this.index = index;
         }
 
         @Override
-        public GridLineType getLineType() {
-            Object lty = data[GP_LTY];
-            if (lty == null || lty == RNull.instance) {
-                return GridLineType.SOLID;
-            }
-            String name = RRuntime.asString(lty);
-            if (name != null) {
-                return lineTypeFromName(name);
-            }
-            RAbstractContainer ltyVec = asAbstractContainer(lty);
-            int num;
-            if (ltyVec.getLength() == 0) {
-                num = RRuntime.INT_NA;
-            } else if (ltyVec instanceof RAbstractDoubleVector) {
-                double realVal = ((RAbstractDoubleVector) ltyVec).getDataAt(0);
-                num = RRuntime.isNA(realVal) ? RRuntime.INT_NA : (int) realVal;
-            } else if (ltyVec instanceof RAbstractIntVector) {
-                num = ((RAbstractIntVector) ltyVec).getDataAt(0);
-            } else {
-                num = RRuntime.INT_NA;
-            }
+        public byte[] getLineType() {
+            return convertNamedValue(data[GP_LTY], LINE_STYLES.length - 1, "line type", GParDrawingContext::lineTypeFromName, num -> LINE_STYLES[num]);
+        }
+
+        @Override
+        public double getLineWidth() {
+            return asDouble(data[GP_LWD], index) * asDouble(data[GP_LEX], index);
+        }
 
-            if (RRuntime.isNA(num)) {
-                throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid line type.");
+        @Override
+        public GridLineJoin getLineJoin() {
+            return convertNamedValue(data[GP_LINEJOIN], GridLineJoin.LAST_VALUE, "line join", GParDrawingContext::lineJoinFromName, GridLineJoin::fromInt);
+        }
+
+        @Override
+        public GridLineEnd getLineEnd() {
+            return convertNamedValue(data[GP_LINEEND], GridLineEnd.LAST_VALUE, "line end", GParDrawingContext::lineEndFromName, GridLineEnd::fromInt);
+        }
+
+        @Override
+        public double getLineMitre() {
+            double value = asDouble(data[GP_LINEMITRE], index);
+            if (value < 1.) {
+                throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid line mitre.");
             }
-            return GridLineType.fromInt(num);
+            return value;
         }
 
         @Override
@@ -166,12 +212,22 @@ public final class GPar {
 
         @Override
         public double getFontSize() {
-            return asDouble(data[GP_FONTSIZE]) * asDouble(data[GP_CEX]);
+            return asDouble(data[GP_FONTSIZE], index) * asDouble(data[GP_CEX], index);
+        }
+
+        @Override
+        public GridFontStyle getFontStyle() {
+            return GridFontStyle.fromInt(GridUtils.asInt(data[GP_FONT], index));
+        }
+
+        @Override
+        public String getFontFamily() {
+            return GridUtils.asString(data[GP_FONTFAMILY], index);
         }
 
         @Override
         public double getLineHeight() {
-            return asDouble(data[GP_LINEHEIGHT]);
+            return asDouble(data[GP_LINEHEIGHT], index);
         }
 
         @Override
@@ -179,29 +235,129 @@ public final class GPar {
             return getGridColor(GP_FILL);
         }
 
-        private GridColor getGridColor(int index) {
-            return GridColorUtils.gridColorFromString(RRuntime.asString(data[index]));
+        /**
+         * Converts value to given enum type using either {@code nameMapper} for String values or
+         * {@code valueMapper} for integer value, which is first validated to be greater or equal to
+         * 0 and less or equal to the {@code maxValue} parameter. If {@code nameMapper} returns
+         * {@code null} or integer validation fails, error with given {@code propertyName} in the
+         * message is thrown.
+         */
+        public <T> T convertNamedValue(Object value, int maxValue, String propertyName, Function<String, T> nameMapper, Function<Integer, T> valueMapper) {
+            T result = null;
+            if (isStringValue(value)) {
+                String name = asString(value, index);
+                if (name != null) {
+                    result = nameMapper.apply(name);
+                }
+            } else {
+                int num = getIntAtMod(value, index);
+                if (RRuntime.isNA(num) || num < 0 || num > maxValue) {
+                    result = null;
+                } else {
+                    result = valueMapper.apply(num);
+                }
+            }
+            if (result == null) {
+                throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid " + propertyName);
+            }
+            return result;
         }
 
-        private GridLineType lineTypeFromName(String name) {
+        private GridColor getGridColor(int listIndex) {
+            GridColor color = GridColorUtils.gridColorFromString(GridUtils.asString(data[listIndex], index));
+            double alpha = asDouble(data[GP_ALPHA], index);
+            if (alpha != 1.) {
+                int newAlpha = Math.min(255, (int) (alpha * ((color.getAlpha() / 255.0) * 255)));
+                return new GridColor(color.getRed(), color.getGreen(), color.getBlue(), newAlpha);
+            } else {
+                return color;
+            }
+        }
+
+        private static final byte[] DASHED_LINE = new byte[]{4, 4};
+        private static final byte[] DOTTED_LINE = new byte[]{1, 3};
+        private static final byte[] DOTDASH_LINE = new byte[]{1, 3, 4, 3};
+        private static final byte[] LONGDASH_LINE = new byte[]{7, 3};
+        private static final byte[] TWODASH_LINE = new byte[]{2, 2, 6, 2};
+        private static final byte[][] LINE_STYLES = new byte[][]{DrawingContext.GRID_LINE_BLANK, DrawingContext.GRID_LINE_SOLID, DASHED_LINE, DOTTED_LINE, DOTDASH_LINE, LONGDASH_LINE, TWODASH_LINE};
+
+        private static byte[] lineTypeFromName(String name) {
             switch (name) {
                 case "solid":
-                    return GridLineType.SOLID;
+                    return DrawingContext.GRID_LINE_SOLID;
                 case "dashed":
-                    return GridLineType.DASHED;
+                    return DASHED_LINE;
                 case "dotted":
-                    return GridLineType.DOTTED;
+                    return DOTTED_LINE;
                 case "dotdashed":
-                    return GridLineType.DOTDASHED;
+                    return DOTDASH_LINE;
                 case "longdash":
-                    return GridLineType.LONGDASH;
+                    return LONGDASH_LINE;
                 case "twodash":
-                    return GridLineType.TWODASH;
+                    return TWODASH_LINE;
                 case "blank":
-                    return GridLineType.BLANK;
+                    return DrawingContext.GRID_LINE_BLANK;
+            }
+            byte[] result = new byte[name.length()];
+            for (int i = 0; i < name.length(); i++) {
+                result[i] = (byte) Character.digit(name.charAt(i), 16);
+                if (result[i] == -1) {
+                    return null;
+                }
+            }
+            return result;
+        }
+
+        private static GridLineEnd lineEndFromName(String name) {
+            switch (name) {
+                case "round":
+                    return GridLineEnd.ROUND;
+                case "butt":
+                    return GridLineEnd.BUTT;
+                case "square":
+                    return GridLineEnd.SQUARE;
+                default:
+                    return null;
+            }
+        }
+
+        private static GridLineJoin lineJoinFromName(String name) {
+            switch (name) {
+                case "round":
+                    return GridLineJoin.ROUND;
+                case "mitre":
+                    return GridLineJoin.MITRE;
+                case "bevel":
+                    return GridLineJoin.BEVEL;
                 default:
-                    // TODO: implement hex digits as line style
-                    throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected line type '" + name + "'.");
+                    return null;
+            }
+        }
+
+        private static boolean isStringValue(Object lty) {
+            return lty instanceof String || lty instanceof RAbstractStringVector;
+        }
+
+        // NA indicates error
+        private static int getIntAtMod(Object obj, int index) {
+            if (obj instanceof Integer) {
+                return (int) obj;
+            } else if (obj instanceof Double) {
+                return (int) ((double) obj);
+            } else if (!(obj instanceof RAbstractContainer)) {
+                return RRuntime.INT_NA;
+            }
+
+            RAbstractContainer value = (RAbstractContainer) obj;
+            if (value.getLength() == 0) {
+                return RRuntime.INT_NA;
+            } else if (value instanceof RAbstractDoubleVector) {
+                double realVal = getDataAtMod((RAbstractDoubleVector) value, index);
+                return RRuntime.isNA(realVal) ? RRuntime.INT_NA : (int) realVal;
+            } else if (value instanceof RAbstractIntVector) {
+                return getDataAtMod((RAbstractIntVector) value, index);
+            } else {
+                return RRuntime.INT_NA;
             }
         }
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index 2cceaeb82a9845570abd46d2f9f3b9386e55d9de..d2bc1d2830d9f0fa15e3d3b0df8f0813475080a0 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -51,10 +51,10 @@ public abstract class GridLinesNode extends Node {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         // Convert the list of vectors of indexes to type-safe array and calculate the max length of
         // the vectors.
@@ -67,7 +67,9 @@ public abstract class GridLinesNode extends Node {
 
         double[] xx = new double[maxIndexesLen + 1];    // plus one for polygons
         double[] yy = new double[maxIndexesLen + 1];
-        for (RAbstractIntVector unitIndexes : unitIndexesList) {
+        for (int unitIndexesListIdx = 0; unitIndexesListIdx < unitIndexesList.length; unitIndexesListIdx++) {
+            RAbstractIntVector unitIndexes = unitIndexesList[unitIndexesListIdx];
+            DrawingContext drawingCtx = gpar.getDrawingContext(unitIndexesListIdx);
             boolean oldIsFinite = false;
             int start = 0;
             int unitIndexesLen = unitIndexes.getLength();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index fbedb1f85323c1fcee0b6015e237fd051362ec4f..6774a7b7220676b3ded896ea99b0ed6c1efa01a6 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -11,7 +11,6 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -53,8 +52,12 @@ public final class GridState {
         gpar = GPar.createNew(currentDevice);
     }
 
-    public static DrawingContext getInitialGPar(GridDevice device) {
-        return GPar.asDrawingContext(GPar.createNew(device));
+    /**
+     * Returns something like a canonical gpar, or top level gpar. This is used when we need a
+     * context to do e.g. unit conversion, but we are in a situation that no context is available.
+     */
+    public static GPar getInitialGPar(GridDevice device) {
+        return GPar.create(GPar.createNew(device));
     }
 
     public RList getGpar() {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index b9d862b0fb7964f21d3a5771acafb996586db78c..594bca1676cf8ebb8534c19b5837c25cb4abeb77 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -95,10 +95,10 @@ public final class GridTextNode extends RBaseNode {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = GridUtils.maxLength(unitLength, x, y);
 
@@ -131,7 +131,7 @@ public final class GridTextNode extends RBaseNode {
             boolean doDraw = true;
             Rectangle trect = null;
             if (checkOverlap || !draw) {
-                trect = textRect(loc, hjust, vjust, rotation, text, drawingCtx, dev);
+                trect = textRect(loc, hjust, vjust, rotation, text, gpar.getDrawingContext(i), dev);
                 for (int j = 0; j < boundsCount; j++) {
                     if (trect.intersects(bounds[j])) {
                         doDraw = false;
@@ -145,7 +145,7 @@ public final class GridTextNode extends RBaseNode {
 
             // actual drawing
             if (draw && doDraw) {
-                text(loc.x, loc.y, text, hjust, vjust, rotation, drawingCtx, dev);
+                text(loc.x, loc.y, text, hjust, vjust, rotation, gpar.getDrawingContext(i), dev);
             }
 
             // or bounds checking
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index b57eaaa9942a29cb6a70e1ffdad36095a6c524cd..8b34ba02b15c72d564d0db91d85949090e5da066 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -26,6 +26,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 final class GridUtils {
@@ -161,6 +162,18 @@ final class GridUtils {
         throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non integer value " + val.getClass().getSimpleName());
     }
 
+    static String asString(Object val, int cyclicIndex) {
+        if (val instanceof String) {
+            return (String) val;
+        } else if (val instanceof RAbstractStringVector) {
+            RAbstractStringVector vec = (RAbstractStringVector) val;
+            if (vec.getLength() > 0) {
+                return vec.getDataAt(cyclicIndex % vec.getLength());
+            }
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non character value " + val.getClass().getSimpleName());
+    }
+
     static RAbstractIntVector asIntVector(Object value) {
         if (value instanceof Integer) {
             return RDataFactory.createIntVectorFromScalar((Integer) value);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
index 4d0183bf8f336f6a5c09ea215f8dca8686f8d445..07ff0d4e4044922888dbb6dd11ae21aeb72b3e72 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
@@ -17,7 +17,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -48,10 +47,10 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = GridUtils.maxLength(unitLength, xVec, yVec, radiusVec);
         for (int i = 0; i < length; i++) {
@@ -59,7 +58,7 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
             double radius = RMath.fmin2(radiusSizes.getWidth(), radiusSizes.getHeight());
             Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
             Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
-            dev.drawCircle(drawingCtx, loc.x, loc.y, radius);
+            dev.drawCircle(gpar.getDrawingContext(i), loc.x, loc.y, radius);
         }
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index b2300de6ab6313762a0eb3b1d9296566b7af1655..134def4c4e4395475982a20b3d7069f3a79e9522 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -23,7 +23,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.AxisOrDimension;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -57,10 +56,10 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = unitLength.execute(units);
         double[] result = new double[length];
@@ -94,7 +93,7 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
                 boolean isX = axisTo.isHorizontal();
                 double scalemin = isX ? vpContext.xscalemin : vpContext.yscalemin;
                 double scalemax = isX ? vpContext.xscalemax : vpContext.yscalemax;
-                result[i] = Unit.convertFromInches(inches, unitTo, vpToSize, scalemin, scalemax, axisTo.isDimension(), drawingCtx);
+                result[i] = Unit.convertFromInches(inches, unitTo, vpToSize, scalemin, scalemax, axisTo.isDimension(), gpar.getDrawingContext(i));
             }
         }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
index 82c23f06ae2e1d4bb9f76eff3c7c52e6aedac120..8a28365fc774f9f6c6f8f7114beef7dfc7c514cf 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
@@ -11,7 +11,6 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.InitViewPortNode;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index d4b71e0a5baadde23ac35c280a5362ba0fe7f908..477e1e4993e981d0ec48ffd8b75a979052541119 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -64,20 +64,22 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        RList gpar = ctx.getGridState().getGpar();
-        DrawingContext drawingCtx = GPar.asDrawingContext(gpar);
-        double cex = GPar.getCex(gpar);
+        RList gparList = ctx.getGridState().getGpar();
+        GPar gpar = GPar.create(gparList);
+        double cex = GPar.getCex(gparList);
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         // Note: unlike in other drawing primitives, we only consider length of x
         int length = unitLength.execute(xVec);
-        PointDrawingContext pointDrawingCtx = new PointDrawingContext(drawingCtx, drawingCtx.getFillColor(), drawingCtx.getFillColor());
+        DrawingContext initialDrawingCtx = gpar.getDrawingContext(0);
+        PointDrawingContext pointDrawingCtx = new PointDrawingContext(initialDrawingCtx, initialDrawingCtx.getFillColor(), initialDrawingCtx.getFillColor());
         for (int i = 0; i < length; i++) {
             Point loc = TransformMatrix.transLocation(Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx), vpTransform.transform);
             double size = unitToInches.convertWidth(sizeVec, i, conversionCtx);
             if (loc.isFinite() && Double.isFinite(size)) {
+                pointDrawingCtx = pointDrawingCtx.update(gpar.getDrawingContext(i));
                 pointDrawingCtx = drawSymbol(pointDrawingCtx, dev, cex, pchVec.getDataAt(i % pchVec.getLength()), size, loc.x, loc.y);
             }
         }
@@ -153,11 +155,38 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
             return new PointDrawingContext(inner, color, fillColor);
         }
 
+        private PointDrawingContext update(DrawingContext inner) {
+            if (this.inner == inner) {
+                return this;
+            }
+            return new PointDrawingContext(inner, this.color, this.fillColor);
+        }
+
         @Override
-        public GridLineType getLineType() {
+        public byte[] getLineType() {
             return inner.getLineType();
         }
 
+        @Override
+        public double getLineWidth() {
+            return inner.getLineWidth();
+        }
+
+        @Override
+        public GridLineJoin getLineJoin() {
+            return inner.getLineJoin();
+        }
+
+        @Override
+        public GridLineEnd getLineEnd() {
+            return inner.getLineEnd();
+        }
+
+        @Override
+        public double getLineMitre() {
+            return inner.getLineMitre();
+        }
+
         @Override
         public GridColor getColor() {
             return color;
@@ -168,6 +197,16 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
             return inner.getFontSize();
         }
 
+        @Override
+        public GridFontStyle getFontStyle() {
+            return inner.getFontStyle();
+        }
+
+        @Override
+        public String getFontFamily() {
+            return inner.getFontFamily();
+        }
+
         @Override
         public double getLineHeight() {
             return inner.getLineHeight();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
index a666b07edeab7b1d149f15aef7d7e945bdabf69e..7c69b09329958ebcea04cf4367605b532d63a9d4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -19,7 +19,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -53,10 +52,10 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = GridUtils.maxLength(unitLength, xVec, yVec, wVec, hVec);
         for (int i = 0; i < length; i++) {
@@ -66,7 +65,7 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
             Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
             Point transLoc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
             Point loc = transLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
-            dev.drawRect(drawingCtx, loc.x, loc.y, size.getWidth(), size.getHeight());
+            dev.drawRect(gpar.getDrawingContext(i), loc.x, loc.y, size.getWidth(), size.getHeight());
         }
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
index 1a3dda410ed2fef75fcde352584f3f42e18df404..c2e1cf10babae9bfc5f52036450dbb3ac3b6baa2 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -17,7 +17,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -59,10 +58,10 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = GridUtils.maxLength(unitLength, x0, y0, x1, y1);
         double[] xx = new double[2];
@@ -77,7 +76,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
             xx[1] = loc2.x;
             yy[0] = loc1.y;
             yy[1] = loc2.y;
-            dev.drawPolyLines(drawingCtx, xx, yy, 0, 2);
+            dev.drawPolyLines(gpar.getDrawingContext(i), xx, yy, 0, 2);
             if (arrow != null) {
                 drawArrowsNode.drawArrows(xx, yy, 0, 2, i, arrow, true, true, conversionCtx);
             }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 4cb343dfbff085c8f8d78422d5d458984d28a2da..3c2095610389f3b951c4a40fa66765c7c4bdb2ce 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -183,7 +183,7 @@ public class Unit {
         }
     }
 
-    private static double convertToInches(double value, int unitId, RList data, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
+    private static double convertToInches(double value, int index, int unitId, RList data, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
         double vpSize = ctx.getViewPortSize(axisOrDim);
         switch (unitId) {
             case INCHES:
@@ -201,16 +201,16 @@ public class Unit {
                 return value / (CM_IN_INCH * 10);
             case CHAR:
             case MYCHAR:
-                return (value * ctx.drawingContext.getFontSize()) / INCH_TO_POINTS_FACTOR;
+                return (value * ctx.gpar.getDrawingContext(index).getFontSize()) / INCH_TO_POINTS_FACTOR;
             case LINES:
             case MYLINES:
-                return (value * ctx.drawingContext.getFontSize() * ctx.drawingContext.getLineHeight()) / INCH_TO_POINTS_FACTOR;
+                return (value * ctx.gpar.getDrawingContext(index).getFontSize() * ctx.gpar.getDrawingContext(index).getLineHeight()) / INCH_TO_POINTS_FACTOR;
             case STRINGWIDTH:
             case MYSTRINGWIDTH:
-                return ctx.device.getStringWidth(ctx.drawingContext, RRuntime.asString(data.getDataAt(0)));
+                return ctx.device.getStringWidth(ctx.gpar.getDrawingContext(index), RRuntime.asString(data.getDataAt(0)));
             case STRINGHEIGHT:
             case MYSTRINGHEIGHT:
-                return ctx.device.getStringHeight(ctx.drawingContext, RRuntime.asString(data.getDataAt(0)));
+                return ctx.device.getStringHeight(ctx.gpar.getDrawingContext(index), RRuntime.asString(data.getDataAt(0)));
             case NULL:
                 return evaluateNullUnit(value, vpSize, ctx.nullLayoutMode, ctx.nullArithmeticMode);
             default:
@@ -423,20 +423,20 @@ public class Unit {
     public static final class UnitConversionContext {
         public final Size viewPortSize;
         public final ViewPortContext viewPortContext;
-        public final DrawingContext drawingContext;
+        public final GPar gpar;
         public final GridDevice device;
         public final int nullLayoutMode;
         public final int nullArithmeticMode;
 
-        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, GridDevice device, DrawingContext drawingContext) {
-            this(viewPortSize, viewPortContext, device, drawingContext, 0, 0);
+        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, GridDevice device, GPar gpar) {
+            this(viewPortSize, viewPortContext, device, gpar, 0, 0);
         }
 
-        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, GridDevice device, DrawingContext drawingContext, int nullLMode, int nullAMode) {
+        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, GridDevice device, GPar gpar, int nullLMode, int nullAMode) {
             this.viewPortSize = viewPortSize;
             this.viewPortContext = viewPortContext;
             this.device = device;
-            this.drawingContext = drawingContext;
+            this.gpar = gpar;
             this.nullLayoutMode = nullLMode;
             this.nullArithmeticMode = nullAMode;
         }
@@ -495,7 +495,7 @@ public class Unit {
                 RList grobList = asList(value.getAttr(UNIT_ATTR_DATA));
                 return getGrobUnitToInchesNode().execute(scalarValue, unitId, grobList.getDataAt(index % grobList.getLength()), ctx);
             }
-            return convertToInches(scalarValue, unitId, asListOrNull(value.getAttr(UNIT_ATTR_DATA)), ctx, axisOrDim);
+            return convertToInches(scalarValue, index, unitId, asListOrNull(value.getAttr(UNIT_ATTR_DATA)), ctx, axisOrDim);
         }
 
         @Specialization(guards = "isUnitList(value)")
@@ -548,7 +548,7 @@ public class Unit {
 
         // Note the catch: newNullAMode is applied only if the axisOrDim is dimension
         private static UnitConversionContext getNewCtx(UnitConversionContext ctx, AxisOrDimension axisOrDim, int newNullAMode) {
-            return new UnitConversionContext(ctx.viewPortSize, ctx.viewPortContext, ctx.device, ctx.drawingContext, ctx.nullLayoutMode,
+            return new UnitConversionContext(ctx.viewPortSize, ctx.viewPortContext, ctx.device, ctx.gpar, ctx.nullLayoutMode,
                             axisOrDim.isDimension() ? newNullAMode : ctx.nullArithmeticMode);
         }
 
@@ -628,7 +628,7 @@ public class Unit {
                         double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
                         result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
                     } else {
-                        UnitConversionContext newConversionCtx = new UnitConversionContext(vpTransform.size, vpContext, conversionCtx.device, GPar.asDrawingContext(currentGP));
+                        UnitConversionContext newConversionCtx = new UnitConversionContext(vpTransform.size, vpContext, conversionCtx.device, GPar.create(currentGP));
                         initUnitToInchesNode();
                         if (unitId == GROBWIDTH) {
                             result = unitToInchesNode.convertWidth((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
index f85a04b4c446380eb41c4c2724692f4214e59215..e36fcac3d78bd24259a48f13998d6451b50baef4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
@@ -30,7 +30,7 @@ import java.util.ArrayList;
  * methods open/draw a 2D graphics buffer, while the buffer is open, any drawing is done in the
  * buffer not on the screen and we also record any drawing code to be able to replay it if the
  * buffer happens to loose contents, which is a possibility mentioned in the documentation. Note: we
- * rely on the fact that {@linkl DrawingContext} is immutable.
+ * rely on the fact that {@link DrawingContext} is immutable.
  */
 public class BufferedJFrameDevice implements GridDevice {
     private final JFrameDevice inner;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
index b3baf6db3cbbc86c93dfafeca313c5b5e77b581f..2986d9ffba8f4133eafbfc4dc56672905d80965f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
@@ -29,29 +29,86 @@ package com.oracle.truffle.r.library.fastrGrid.device;
 public interface DrawingContext {
     double INCH_TO_POINTS_FACTOR = 72.27;
 
-    enum GridLineType {
-        // The order is important!
-        BLANK,
-        SOLID,
-        DASHED,
-        DOTTED,
-        DOTDASHED,
-        LONGDASH,
-        TWODASH;
-
-        private static final int LINE_TYPES_COUNT = 7;
-        private static final GridLineType[] allValues = values();
-
-        public static GridLineType fromInt(int num) {
-            if (num == -1) {
-                return BLANK;
-            }
-            assert num >= 1;
-            return allValues[(num - 1) % LINE_TYPES_COUNT + 1];
+    String FONT_FAMILY_MONO = "mono";
+    String FONT_FAMILY_SANS = "sans";
+    String FONT_FAMILY_SERIF = "serif";
+
+    byte[] GRID_LINE_BLANK = null;
+    byte[] GRID_LINE_SOLID = new byte[0];
+
+    enum GridFontStyle {
+        PLAIN,
+        BOLD,
+        ITALIC,
+        BOLDITALIC,
+        /**
+         * Supposed to be symbol font in Adobe symbol encoding.
+         */
+        SYMBOL;
+
+        /**
+         * Return enum's value corresponding to R's value.
+         */
+        public static GridFontStyle fromInt(int num) {
+            assert num > 0 && num <= SYMBOL.ordinal() + 1;
+            return values()[num - 1];
+        }
+    }
+
+    enum GridLineJoin {
+        ROUND,
+        MITRE,
+        BEVEL;
+
+        public static final int LAST_VALUE = BEVEL.ordinal();
+
+        /**
+         * Return enum's value corresponding to R's value.
+         */
+        public static GridLineJoin fromInt(int num) {
+            return values()[num];
         }
     }
 
-    GridLineType getLineType();
+    enum GridLineEnd {
+        ROUND,
+        BUTT,
+        SQUARE;
+
+        public static final int LAST_VALUE = SQUARE.ordinal();
+
+        /**
+         * Return enum's value corresponding to R's value.
+         */
+        public static GridLineEnd fromInt(int num) {
+            return values()[num];
+        }
+    }
+
+    /**
+     * Returns either one of the constants {@link #GRID_LINE_BLANK} or {@link #GRID_LINE_SOLID} or
+     * an array with a pattern consisting of lengths. Lengths at odd positions are dashes and
+     * lengths at the even positions are spaces between them, the pattern should be interpreted as
+     * cyclic. Example: '3,2,10,1' means 3 units of line, 2 units of space, 10 units of line, 1 unit
+     * of space and repeat. The unit here can be device dependent, but should be something "small",
+     * like a pixel.
+     */
+    byte[] getLineType();
+
+    /**
+     * Line width in multiplies of what is considered the basic "thin" line for given device.
+     */
+    double getLineWidth();
+
+    GridLineJoin getLineJoin();
+
+    GridLineEnd getLineEnd();
+
+    /**
+     * The mitre limit, larger than 1, default is 10. The unit should be interpreted the way as in
+     * {@link #getLineType()}.
+     */
+    double getLineMitre();
 
     /**
      * Drawing color of shape borders, lines and text.
@@ -65,6 +122,15 @@ public interface DrawingContext {
      */
     double getFontSize();
 
+    GridFontStyle getFontStyle();
+
+    /**
+     * Gets the font family name. The standard values that any device must implement are "serif",
+     * "sans" and "mono". On top of that the device can recognize name of any font that it can
+     * support.
+     */
+    String getFontFamily();
+
     /**
      * Gets the height of a line in multiplies of the base line height.
      */
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
index 4b42cdce8cc4db3f9ff42e759f6a1f73a12f229c..6b1c9451bd8a4998b61875b0fca15285633ff7ec 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
@@ -58,10 +58,7 @@ public class GridColor {
 
     @Override
     public boolean equals(Object obj) {
-        if (!(obj instanceof GridColor)) {
-            return false;
-        }
-        return value == ((GridColor) obj).value;
+        return obj instanceof GridColor && value == ((GridColor) obj).value;
     }
 
     @Override
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index 2ac24f74a69f39b470acd028cf1724c54ef24a9d..b27f820139042752633e1a55cba6f4a4f3ac2850 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -28,6 +28,7 @@ import java.awt.BasicStroke;
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Dimension;
+import java.awt.Font;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.HeadlessException;
@@ -46,7 +47,9 @@ import java.util.function.Supplier;
 import javax.swing.JFrame;
 import javax.swing.JPanel;
 
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineType;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridFontStyle;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineEnd;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineJoin;
 import com.oracle.truffle.r.runtime.RInternalError;
 
 public class JFrameDevice implements GridDevice {
@@ -59,11 +62,6 @@ public class JFrameDevice implements GridDevice {
 
     private static BasicStroke solidStroke;
     private static BasicStroke blankStroke;
-    private static BasicStroke dashedStroke;
-    private static BasicStroke longdashedStroke;
-    private static BasicStroke twodashedStroke;
-    private static BasicStroke dotdashedStroke;
-    private static BasicStroke dottedStroke;
 
     private FastRFrame currentFrame;
     private Graphics2D graphics;
@@ -116,7 +114,7 @@ public class JFrameDevice implements GridDevice {
             tr.translate((float) (leftX * POINTS_IN_INCH), (float) (currentFrame.getContentPane().getHeight() - bottomY * POINTS_IN_INCH));
             tr.rotate(-rotationAnticlockWise);
             graphics.setTransform(tr);
-            setFontSize(ctx);
+            setFont(ctx);
             graphics.drawString(text, 0, 0);
             return null;
         });
@@ -136,7 +134,7 @@ public class JFrameDevice implements GridDevice {
     public double getStringWidth(DrawingContext ctx, String text) {
         setContext(ctx);
         return noTranform(() -> {
-            setFontSize(ctx);
+            setFont(ctx);
             int swingUnits = graphics.getFontMetrics(graphics.getFont()).stringWidth(text);
             return swingUnits / POINTS_IN_INCH;
         });
@@ -146,7 +144,7 @@ public class JFrameDevice implements GridDevice {
     public double getStringHeight(DrawingContext ctx, String text) {
         setContext(ctx);
         return noTranform(() -> {
-            setFontSize(ctx);
+            setFont(ctx);
             int swingUnits = graphics.getFont().getSize();
             return swingUnits / POINTS_IN_INCH;
         });
@@ -178,12 +176,45 @@ public class JFrameDevice implements GridDevice {
 
     private void setContext(DrawingContext ctx) {
         graphics.setColor(fromGridColor(ctx.getColor()));
-        graphics.setStroke(fromGridLineType(ctx.getLineType()));
+        graphics.setStroke(getStrokeFromCtx(ctx));
     }
 
-    private void setFontSize(DrawingContext ctx) {
+    private void setFont(DrawingContext ctx) {
         float fontSize = (float) ((ctx.getFontSize() / INCH_TO_POINTS_FACTOR) * POINTS_IN_INCH);
-        graphics.setFont(graphics.getFont().deriveFont(fontSize));
+        Font font = new Font(getFontName(ctx.getFontFamily()), getAwtFontStyle(ctx.getFontStyle()), 1).deriveFont(fontSize);
+        graphics.setFont(font);
+    }
+
+    private String getFontName(String gridFontFamily) {
+        if (gridFontFamily == null) {
+            return null;
+        }
+        switch (gridFontFamily) {
+            case DrawingContext.FONT_FAMILY_MONO:
+                return Font.MONOSPACED;
+            case DrawingContext.FONT_FAMILY_SANS:
+                return Font.SANS_SERIF;
+            case DrawingContext.FONT_FAMILY_SERIF:
+                return Font.SERIF;
+            case "":
+                return null;
+        }
+        return gridFontFamily;
+    }
+
+    private int getAwtFontStyle(GridFontStyle fontStyle) {
+        switch (fontStyle) {
+            case PLAIN:
+                return Font.PLAIN;
+            case BOLD:
+                return Font.BOLD;
+            case ITALIC:
+                return Font.ITALIC;
+            case BOLDITALIC:
+                return Font.BOLD | Font.ITALIC;
+            default:
+                throw RInternalError.shouldNotReachHere("unexpected value of GridFontStyle enum");
+        }
     }
 
     private <T> T noTranform(Supplier<T> action) {
@@ -198,24 +229,50 @@ public class JFrameDevice implements GridDevice {
         return new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
     }
 
-    private static BasicStroke fromGridLineType(GridLineType type) {
-        switch (type) {
-            case SOLID:
+    private static BasicStroke getStrokeFromCtx(DrawingContext ctx) {
+        byte[] type = ctx.getLineType();
+        double width = ctx.getLineWidth();
+        int lineJoin = fromGridLineJoin(ctx.getLineJoin());
+        float lineMitre = (float) ctx.getLineMitre();
+        int endCap = fromGridLineEnd(ctx.getLineEnd());
+        if (type == DrawingContext.GRID_LINE_BLANK) {
+            return blankStroke;
+        } else if (type == DrawingContext.GRID_LINE_SOLID) {
+            if (width == 1. && solidStroke.getLineJoin() == lineJoin && solidStroke.getMiterLimit() == lineMitre && solidStroke.getEndCap() == endCap) {
                 return solidStroke;
-            case BLANK:
-                return blankStroke;
-            case DASHED:
-                return dashedStroke;
-            case DOTDASHED:
-                return dotdashedStroke;
-            case DOTTED:
-                return dottedStroke;
-            case TWODASH:
-                return twodashedStroke;
-            case LONGDASH:
-                return longdashedStroke;
+            }
+            return new BasicStroke((float) (width / POINTS_IN_INCH), endCap, lineJoin, lineMitre);
+        }
+        float[] pattern = new float[type.length];
+        for (int i = 0; i < pattern.length; i++) {
+            pattern[i] = (float) (type[i] / POINTS_IN_INCH);
+        }
+        return new BasicStroke((float) (width / POINTS_IN_INCH), endCap, lineJoin, lineMitre, pattern, 0f);
+    }
+
+    private static int fromGridLineEnd(GridLineEnd lineEnd) {
+        switch (lineEnd) {
+            case ROUND:
+                return BasicStroke.CAP_ROUND;
+            case BUTT:
+                return BasicStroke.CAP_BUTT;
+            case SQUARE:
+                return BasicStroke.CAP_SQUARE;
+            default:
+                throw RInternalError.shouldNotReachHere("unexpected value of GridLineEnd enum");
+        }
+    }
+
+    private static int fromGridLineJoin(GridLineJoin lineJoin) {
+        switch (lineJoin) {
+            case BEVEL:
+                return BasicStroke.JOIN_BEVEL;
+            case MITRE:
+                return BasicStroke.JOIN_MITER;
+            case ROUND:
+                return BasicStroke.JOIN_ROUND;
             default:
-                throw RInternalError.shouldNotReachHere("unexpected value of GridLineType enum");
+                throw RInternalError.shouldNotReachHere("unexpected value of GridLineJoin enum");
         }
     }
 
@@ -223,16 +280,8 @@ public class JFrameDevice implements GridDevice {
         if (solidStroke != null) {
             return;
         }
-        float defaultWidth = (float) (1. / POINTS_IN_INCH);
-        float dashSize = (float) (10. / POINTS_IN_INCH);
-        float dotSize = (float) (2. / POINTS_IN_INCH);
         solidStroke = new BasicStroke((float) (1f / POINTS_IN_INCH));
         blankStroke = new BasicStroke(0f);
-        dashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dashSize}, 0f);
-        dottedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dotSize}, 0f);
-        dotdashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dotSize, dashSize}, 0f);
-        twodashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dashSize / 2f, dashSize}, 0f);
-        longdashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{2f * dashSize}, 0f);
     }
 
     static class FastRFrame extends JFrame {