diff --git a/trunk/src/com/jpexs/asdec/gui/TagPanel.java b/trunk/src/com/jpexs/asdec/gui/TagPanel.java
index aecfcc841..7a856601e 100644
--- a/trunk/src/com/jpexs/asdec/gui/TagPanel.java
+++ b/trunk/src/com/jpexs/asdec/gui/TagPanel.java
@@ -14,8 +14,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
-
package com.jpexs.asdec.gui;
import com.jpexs.asdec.SWF;
@@ -28,6 +26,11 @@ import com.jpexs.asdec.tags.DefineBitsLosslessTag;
import com.jpexs.asdec.tags.DefineBitsTag;
import com.jpexs.asdec.tags.DefineMorphShape2Tag;
import com.jpexs.asdec.tags.DefineMorphShapeTag;
+import com.jpexs.asdec.tags.DefineShape2Tag;
+import com.jpexs.asdec.tags.DefineShape3Tag;
+import com.jpexs.asdec.tags.DefineShape4Tag;
+import com.jpexs.asdec.tags.DefineShapeTag;
+import com.jpexs.asdec.tags.DefineSpriteTag;
import com.jpexs.asdec.tags.DefineTextTag;
import com.jpexs.asdec.tags.EndTag;
import com.jpexs.asdec.tags.JPEGTablesTag;
@@ -132,7 +135,7 @@ public class TagPanel extends JPanel implements ListSelectionListener {
swtPanel.setBackground(Color.white);
displayPanel.add(swtPanel, CARDFLASHPANEL);
}
- imagePanel = new ImagePanel();
+ imagePanel = new ImagePanel();
displayPanel.add(imagePanel, CARDIMAGEPANEL);
displayPanel.add(new JPanel(), CARDEMPTYPANEL);
CardLayout cl = (CardLayout) (displayPanel.getLayout());
@@ -217,8 +220,13 @@ public class TagPanel extends JPanel implements ListSelectionListener {
mat.hasScale = false;
mat.translateX = 0;
mat.translateY = 0;
- if (tagObj instanceof BoundedTag) {
- RECT r = ((BoundedTag) tagObj).getRect();
+ if ((tagObj instanceof BoundedTag) || (tagObj instanceof DefineSpriteTag)) {
+ RECT r = null;
+ if (tagObj instanceof DefineSpriteTag) {
+ r = ((DefineSpriteTag) tagObj).getRect(characters);
+ } else {
+ r = ((BoundedTag) tagObj).getRect();
+ }
mat.translateX = -r.Xmin;
mat.translateY = -r.Ymin;
mat.translateX = mat.translateX + width / 2 - r.getWidth() / 2;
diff --git a/trunk/src/com/jpexs/asdec/tags/DefineSpriteTag.java b/trunk/src/com/jpexs/asdec/tags/DefineSpriteTag.java
index 203ff1ad0..a3031e8a1 100644
--- a/trunk/src/com/jpexs/asdec/tags/DefineSpriteTag.java
+++ b/trunk/src/com/jpexs/asdec/tags/DefineSpriteTag.java
@@ -14,21 +14,24 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
-
package com.jpexs.asdec.tags;
import com.jpexs.asdec.Main;
import com.jpexs.asdec.SWFInputStream;
import com.jpexs.asdec.SWFOutputStream;
import com.jpexs.asdec.abc.CopyOutputStream;
+import com.jpexs.asdec.tags.base.BoundedTag;
import com.jpexs.asdec.tags.base.CharacterTag;
import com.jpexs.asdec.tags.base.Container;
+import com.jpexs.asdec.types.MATRIX;
+import com.jpexs.asdec.types.RECT;
+import java.awt.Point;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -57,6 +60,64 @@ public class DefineSpriteTag extends CharacterTag implements Container {
return spriteId;
}
+ private RECT getCharacterBounds(HashMap allCharacters, Set characters) {
+ RECT ret = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE,Integer.MIN_VALUE);
+ for (int c : characters) {
+ Tag t = allCharacters.get(c);
+ RECT r = null;
+ if (t instanceof BoundedTag) {
+ r = ((BoundedTag) t).getRect();
+ } else if (t instanceof DefineSpriteTag) {
+ r = ((DefineSpriteTag) t).getRect(allCharacters);
+ }
+ if (r != null) {
+ ret.Xmin = Math.min(r.Xmin, ret.Xmin);
+ ret.Ymin = Math.min(r.Ymin, ret.Ymin);
+ ret.Xmax = Math.max(r.Xmax, ret.Xmax);
+ ret.Ymax = Math.max(r.Ymax, ret.Ymax);
+ }
+ }
+ return ret;
+ }
+
+ public RECT getRect(HashMap characters) {
+ RECT ret = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE,Integer.MIN_VALUE);
+ for (Tag t : subTags) {
+ Set needed = t.getNeededCharacters();
+ if(needed.isEmpty()){
+ continue;
+ }
+ RECT r = getCharacterBounds(characters, needed);
+ MATRIX m = null;
+ if (t instanceof PlaceObjectTag) {
+ m = ((PlaceObjectTag) t).matrix;
+ }
+ if (t instanceof PlaceObject2Tag) {
+ if (((PlaceObject2Tag) t).placeFlagHasMatrix) {
+ m = ((PlaceObject2Tag) t).matrix;
+ }
+ }
+ if (t instanceof PlaceObject3Tag) {
+ if (((PlaceObject3Tag) t).placeFlagHasMatrix) {
+ m = ((PlaceObject3Tag) t).matrix;
+ }
+ }
+ if (m != null) {
+ Point topleft = m.apply(new Point(r.Xmin, r.Ymin));
+ Point bottomright = m.apply(new Point(r.Xmax, r.Ymax));
+ r.Xmin=Math.min(topleft.x,bottomright.x);
+ r.Ymin=Math.min(topleft.y,bottomright.y);
+ r.Xmax=Math.max(topleft.x,bottomright.x);
+ r.Ymax=Math.max(topleft.y,bottomright.y);
+ }
+ ret.Xmin = Math.min(r.Xmin, ret.Xmin);
+ ret.Ymin = Math.min(r.Ymin, ret.Ymin);
+ ret.Xmax = Math.max(r.Xmax, ret.Xmax);
+ ret.Ymax = Math.max(r.Ymax, ret.Ymax);
+ }
+ return ret;
+ }
+
/**
* Constructor
*
diff --git a/trunk/src/com/jpexs/asdec/types/LINESTYLEARRAY.java b/trunk/src/com/jpexs/asdec/types/LINESTYLEARRAY.java
index b751cc699..fd60c4f91 100644
--- a/trunk/src/com/jpexs/asdec/types/LINESTYLEARRAY.java
+++ b/trunk/src/com/jpexs/asdec/types/LINESTYLEARRAY.java
@@ -23,7 +23,7 @@ package com.jpexs.asdec.types;
* @author JPEXS
*/
public class LINESTYLEARRAY {
-
+
public LINESTYLE lineStyles[];
public LINESTYLE2 lineStyles2[];
}
diff --git a/trunk/src/com/jpexs/asdec/types/MATRIX.java b/trunk/src/com/jpexs/asdec/types/MATRIX.java
index 72d7efd0c..539c0ace4 100644
--- a/trunk/src/com/jpexs/asdec/types/MATRIX.java
+++ b/trunk/src/com/jpexs/asdec/types/MATRIX.java
@@ -14,10 +14,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
-
package com.jpexs.asdec.types;
+import java.awt.Point;
+
/**
* Represents a standard 2x3 transformation matrix of the sort commonly used in
* 2D graphics
@@ -66,4 +66,15 @@ public class MATRIX {
public String toString() {
return "[MATRIX scale:" + scaleX + "," + scaleY + ", rotate:" + rotateSkew0 + "," + rotateSkew1 + ", translate:" + translateX + "," + translateY + "]";
}
+
+ private float toFloat(int i){
+ return ((float)i)/(1<<16);
+ }
+
+ public Point apply(Point p) {
+ Point ret = new Point();
+ ret.x = (int)(p.x * (hasScale?toFloat(scaleX):1) + p.y * (hasRotate?toFloat(rotateSkew1):0) + translateX);
+ ret.y = (int) (p.x * (hasRotate?toFloat(rotateSkew0):0) + p.y * (hasScale?toFloat(scaleY):1) + translateY);
+ return ret;
+ }
}
diff --git a/trunk/src/com/jpexs/asdec/types/RGB.java b/trunk/src/com/jpexs/asdec/types/RGB.java
index f77caf15e..0ad1e12c0 100644
--- a/trunk/src/com/jpexs/asdec/types/RGB.java
+++ b/trunk/src/com/jpexs/asdec/types/RGB.java
@@ -46,4 +46,20 @@ public class RGB {
public RGB() {
}
+
+ public String toHexRGB(){
+ String rh=Integer.toHexString(red);
+ if(rh.length()<2){
+ rh="0"+rh;
+ }
+ String gh=Integer.toHexString(green);
+ if(gh.length()<2){
+ gh="0"+gh;
+ }
+ String bh=Integer.toHexString(blue);
+ if(bh.length()<2){
+ bh="0"+bh;
+ }
+ return "#"+rh+gh+bh;
+ }
}
diff --git a/trunk/src/com/jpexs/asdec/types/RGBA.java b/trunk/src/com/jpexs/asdec/types/RGBA.java
index c14ea2320..d69a14acf 100644
--- a/trunk/src/com/jpexs/asdec/types/RGBA.java
+++ b/trunk/src/com/jpexs/asdec/types/RGBA.java
@@ -41,4 +41,20 @@ public class RGBA {
* Alpha value defining opacity
*/
public int alpha;
+
+ public String toHexRGB(){
+ String rh=Integer.toHexString(red);
+ if(rh.length()<2){
+ rh="0"+rh;
+ }
+ String gh=Integer.toHexString(green);
+ if(gh.length()<2){
+ gh="0"+gh;
+ }
+ String bh=Integer.toHexString(blue);
+ if(bh.length()<2){
+ bh="0"+bh;
+ }
+ return "#"+rh+gh+bh;
+ }
}
diff --git a/trunk/src/com/jpexs/asdec/types/SHAPE.java b/trunk/src/com/jpexs/asdec/types/SHAPE.java
index 3d5a21ed5..a36981139 100644
--- a/trunk/src/com/jpexs/asdec/types/SHAPE.java
+++ b/trunk/src/com/jpexs/asdec/types/SHAPE.java
@@ -30,4 +30,17 @@ public class SHAPE {
public int numFillBits;
public int numLineBits;
public List shapeRecords;
+
+ /**
+ * EXPERIMENTAL
+ * @param shapeNum
+ * @return
+ */
+ public String toSVG(int shapeNum){
+ return SHAPERECORD.shapeToSVG(shapeNum,null, null, numFillBits, numLineBits, shapeRecords);
+ }
+
+ public RECT getBounds(){
+ return SHAPERECORD.getBounds(shapeRecords);
+ }
}
diff --git a/trunk/src/com/jpexs/asdec/types/SHAPEWITHSTYLE.java b/trunk/src/com/jpexs/asdec/types/SHAPEWITHSTYLE.java
index 0bb94f329..d52801ae0 100644
--- a/trunk/src/com/jpexs/asdec/types/SHAPEWITHSTYLE.java
+++ b/trunk/src/com/jpexs/asdec/types/SHAPEWITHSTYLE.java
@@ -32,4 +32,17 @@ public class SHAPEWITHSTYLE {
public int numFillBits;
public int numLineBits;
public List shapeRecords;
+
+ /**
+ * EXPERIMENTAL
+ * @param shapeNum
+ * @return
+ */
+ public String toSVG(int shapeNum){
+ return SHAPERECORD.shapeToSVG(shapeNum,fillStyles, lineStyles, numFillBits, numLineBits, shapeRecords);
+ }
+
+ public RECT getBounds(){
+ return SHAPERECORD.getBounds(shapeRecords);
+ }
}
diff --git a/trunk/src/com/jpexs/asdec/types/shaperecords/CurvedEdgeRecord.java b/trunk/src/com/jpexs/asdec/types/shaperecords/CurvedEdgeRecord.java
index df98ae77a..3a7663618 100644
--- a/trunk/src/com/jpexs/asdec/types/shaperecords/CurvedEdgeRecord.java
+++ b/trunk/src/com/jpexs/asdec/types/shaperecords/CurvedEdgeRecord.java
@@ -22,7 +22,7 @@ package com.jpexs.asdec.types.shaperecords;
*
* @author JPEXS
*/
-public class CurvedEdgeRecord implements SHAPERECORD {
+public class CurvedEdgeRecord extends SHAPERECORD {
public int typeFlag = 1;
public int straightFlag = 0;
diff --git a/trunk/src/com/jpexs/asdec/types/shaperecords/EndShapeRecord.java b/trunk/src/com/jpexs/asdec/types/shaperecords/EndShapeRecord.java
index e829fdc4e..ef68b9a1c 100644
--- a/trunk/src/com/jpexs/asdec/types/shaperecords/EndShapeRecord.java
+++ b/trunk/src/com/jpexs/asdec/types/shaperecords/EndShapeRecord.java
@@ -22,7 +22,7 @@ package com.jpexs.asdec.types.shaperecords;
*
* @author JPEXS
*/
-public class EndShapeRecord implements SHAPERECORD {
+public class EndShapeRecord extends SHAPERECORD {
public int typeFlag = 0;
public int endOfShape = 0;
diff --git a/trunk/src/com/jpexs/asdec/types/shaperecords/SHAPERECORD.java b/trunk/src/com/jpexs/asdec/types/shaperecords/SHAPERECORD.java
index 54e3732fe..e4af8cc7e 100644
--- a/trunk/src/com/jpexs/asdec/types/shaperecords/SHAPERECORD.java
+++ b/trunk/src/com/jpexs/asdec/types/shaperecords/SHAPERECORD.java
@@ -14,13 +14,250 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
-
package com.jpexs.asdec.types.shaperecords;
+import com.jpexs.asdec.types.FILLSTYLE;
+import com.jpexs.asdec.types.FILLSTYLEARRAY;
+import com.jpexs.asdec.types.LINESTYLE;
+import com.jpexs.asdec.types.LINESTYLE2;
+import com.jpexs.asdec.types.LINESTYLEARRAY;
+import com.jpexs.asdec.types.RECT;
+import com.jpexs.asdec.types.RGB;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
/**
*
* @author JPEXS
*/
-public interface SHAPERECORD {
+public abstract class SHAPERECORD {
+
+ public static float twipToPixel(int twip) {
+ return ((float) twip) / 20.0f;
+ }
+
+ private static class Path {
+ public LINESTYLE lineStyle;
+ public LINESTYLE2 lineStyle2;
+ public boolean useLineStyle2;
+ public FILLSTYLE fillStyle0;
+ public FILLSTYLE fillStyle1;
+ public String points;
+ }
+
+ public static RECT getBounds(List records){
+ int x = 0;
+ int y = 0;
+ int max_x = 0;
+ int max_y = 0;
+ int min_x = Integer.MAX_VALUE;
+ int min_y = Integer.MAX_VALUE;
+ boolean started = false;
+ for (SHAPERECORD r : records) {
+ if (r instanceof StyleChangeRecord) {
+ StyleChangeRecord scr = (StyleChangeRecord) r;
+ if (scr.stateMoveTo) {
+ x = scr.moveDeltaX;
+ y = scr.moveDeltaY;
+ started = true;
+ }
+ }
+ if (r instanceof StraightEdgeRecord) {
+ StraightEdgeRecord ser = (StraightEdgeRecord) r;
+ if (ser.generalLineFlag) {
+ x += ser.deltaX;
+ y += ser.deltaY;
+ started = true;
+ } else if (ser.vertLineFlag) {
+ y += ser.deltaY;
+ started = true;
+ } else {
+ x += ser.deltaX;
+ started = true;
+ }
+ }
+ if (r instanceof CurvedEdgeRecord) {
+ CurvedEdgeRecord cer = (CurvedEdgeRecord) r;
+ x += cer.controlDeltaX + cer.anchorDeltaX;
+ y += cer.controlDeltaY + cer.anchorDeltaY;
+ started = true;
+ }
+ if (x > max_x) {
+ max_x = x;
+ }
+ if (y > max_y) {
+ max_y = y;
+ }
+ if (started) {
+ if (y < min_y) {
+ min_y = y;
+ }
+ if (x < min_x) {
+ min_x = x;
+ }
+ }
+ }
+ return new RECT(min_x,max_x,min_y,max_y);
+ }
+
+ /**
+ * EXPERIMENTAL - convert shape to SVG
+ *
+ * TODO: Fix fill styles
+ *
+ * @param shapeNum
+ * @param fillStyles
+ * @param lineStylesList
+ * @param numFillBits
+ * @param numLineBits
+ * @param records
+ * @return Shape converted to SVG
+ */
+ public static String shapeToSVG(int shapeNum, FILLSTYLEARRAY fillStyles, LINESTYLEARRAY lineStylesList, int numFillBits, int numLineBits, List records) {
+ String ret = "";
+ List paths = new ArrayList();
+ Path path = new Path();
+ boolean styleChanged = false;
+ int x = 0;
+ int y = 0;
+ int max_x = 0;
+ int max_y = 0;
+ int min_x = Integer.MAX_VALUE;
+ int min_y = Integer.MAX_VALUE;
+ boolean started = false;
+ for (SHAPERECORD r : records) {
+ if (r instanceof StyleChangeRecord) {
+ StyleChangeRecord scr = (StyleChangeRecord) r;
+ if (scr.stateNewStyles) {
+ fillStyles = scr.fillStyles;
+ lineStylesList = scr.lineStyles;
+ numFillBits = scr.numFillBits;
+ numLineBits = scr.numLineBits;
+ }
+ if (scr.stateFillStyle0) {
+ styleChanged = true;
+ if (scr.fillStyle0 == 0) {
+ path.fillStyle0 = null;
+ } else {
+ path.fillStyle0 = fillStyles.fillStyles[scr.fillStyle0 - 1];
+ }
+ }
+ if (scr.stateFillStyle1) {
+ styleChanged = true;
+ if (scr.fillStyle1 == 0) {
+ path.fillStyle1 = null;
+ } else {
+ path.fillStyle1 = fillStyles.fillStyles[scr.fillStyle1 - 1];
+ }
+ }
+ if (scr.stateLineStyle) {
+ styleChanged = true;
+ if (shapeNum>=4) {
+ path.useLineStyle2 = true;
+ if (scr.lineStyle == 0) {
+ path.lineStyle2 = null;
+ } else {
+ path.lineStyle2 = lineStylesList.lineStyles2[scr.lineStyle - 1];
+ }
+ } else {
+ path.useLineStyle2 = false;
+ if (scr.lineStyle == 0) {
+ path.lineStyle = null;
+ } else {
+ path.lineStyle = lineStylesList.lineStyles[scr.lineStyle - 1];
+ }
+ }
+ }
+ if (scr.stateMoveTo) {
+ ret += "M " + twipToPixel(scr.moveDeltaX) + " " + twipToPixel(scr.moveDeltaY);
+ x = scr.moveDeltaX;
+ y = scr.moveDeltaY;
+
+ started = true;
+ }
+ } else if (styleChanged) {
+ styleChanged = false;
+ path.points = ret;
+ ret = "M " + twipToPixel(x) + " " + twipToPixel(y);
+ paths.add(path);
+ path = new Path();
+ }
+ if (r instanceof StraightEdgeRecord) {
+ StraightEdgeRecord ser = (StraightEdgeRecord) r;
+ if (ser.generalLineFlag) {
+ ret += "l " + twipToPixel(ser.deltaX) + " " + twipToPixel(ser.deltaY);
+ x += ser.deltaX;
+ y += ser.deltaY;
+ started = true;
+ } else if (ser.vertLineFlag) {
+ ret += "v " + twipToPixel(ser.deltaY);
+ y += ser.deltaY;
+ started = true;
+ } else {
+ ret += "h " + twipToPixel(ser.deltaX);
+ x += ser.deltaX;
+ started = true;
+ }
+ }
+ if (r instanceof CurvedEdgeRecord) {
+ CurvedEdgeRecord cer = (CurvedEdgeRecord) r;
+ ret += "q " + twipToPixel(cer.controlDeltaX) + " " + twipToPixel(cer.controlDeltaY) + " " + twipToPixel(cer.controlDeltaX + cer.anchorDeltaX) + " " + twipToPixel(cer.controlDeltaY + cer.anchorDeltaY);
+ x += cer.controlDeltaX + cer.anchorDeltaX;
+ y += cer.controlDeltaY + cer.anchorDeltaY;
+ started = true;
+ }
+ if (x > max_x) {
+ max_x = x;
+ }
+ if (y > max_y) {
+ max_y = y;
+ }
+ if (started) {
+ if (y < min_y) {
+ min_y = y;
+ }
+ if (x < min_x) {
+ min_x = x;
+ }
+ }
+ }
+ path.points = ret;
+ paths.add(path);
+ ret = "";
+ for (Path p : paths) {
+ String params = "";
+ String f = "";
+ if (p.fillStyle0 != null) {
+ if (p.fillStyle0.fillStyleType == FILLSTYLE.SOLID) {
+ f = " fill=\"" + ((shapeNum >= 3) ? p.fillStyle0.colorA.toHexRGB() : p.fillStyle0.color.toHexRGB()) + "\"";
+ }
+ } else if (p.fillStyle1 != null) {
+ if (p.fillStyle1.fillStyleType == FILLSTYLE.SOLID) {
+ f = " fill=\"" + ((shapeNum >= 3) ? p.fillStyle1.colorA.toHexRGB() : p.fillStyle1.color.toHexRGB()) + "\"";
+ }
+ }
+ if (p.fillStyle0 != null && p.fillStyle1 != null) {
+ Random rnd = new Random();
+ f = " fill=\"" + (new RGB(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256))).toHexRGB() + "\"";
+ }
+ params += f;
+ if ((!p.useLineStyle2) && p.lineStyle != null) {
+ params += " stroke=\"" + ((shapeNum >= 3) ? p.lineStyle.colorA.toHexRGB() : p.lineStyle.color.toHexRGB()) + "\"";
+ }
+ if (p.useLineStyle2 && p.lineStyle2 != null) {
+ params += " stroke-width=\"" + twipToPixel(p.lineStyle2.width) + "\" stroke=\"" + p.lineStyle2.color.toHexRGB() + "\"";
+ }
+ ret += "";
+ }
+ ret = " \n"
+ + "\n"
+ + "";
+ return ret;
+ }
}
diff --git a/trunk/src/com/jpexs/asdec/types/shaperecords/StraightEdgeRecord.java b/trunk/src/com/jpexs/asdec/types/shaperecords/StraightEdgeRecord.java
index addc3a2d8..f6c47ceb9 100644
--- a/trunk/src/com/jpexs/asdec/types/shaperecords/StraightEdgeRecord.java
+++ b/trunk/src/com/jpexs/asdec/types/shaperecords/StraightEdgeRecord.java
@@ -22,7 +22,7 @@ package com.jpexs.asdec.types.shaperecords;
*
* @author JPEXS
*/
-public class StraightEdgeRecord implements SHAPERECORD {
+public class StraightEdgeRecord extends SHAPERECORD {
public int typeFlag = 1;
public int straightFlag = 1;
diff --git a/trunk/src/com/jpexs/asdec/types/shaperecords/StyleChangeRecord.java b/trunk/src/com/jpexs/asdec/types/shaperecords/StyleChangeRecord.java
index ee0e992c7..6480795b0 100644
--- a/trunk/src/com/jpexs/asdec/types/shaperecords/StyleChangeRecord.java
+++ b/trunk/src/com/jpexs/asdec/types/shaperecords/StyleChangeRecord.java
@@ -25,7 +25,7 @@ import com.jpexs.asdec.types.LINESTYLEARRAY;
*
* @author JPEXS
*/
-public class StyleChangeRecord implements SHAPERECORD {
+public class StyleChangeRecord extends SHAPERECORD {
public int typeFlag = 0;
public boolean stateNewStyles;