From 7249fd6e4d4442b0d26dc6873f684c39d64c8379 Mon Sep 17 00:00:00 2001 From: NathanSweet Date: Mon, 3 Jun 2019 16:26:46 +0200 Subject: [PATCH] [libgdx] Binary format, added a string table. The binary export for a project with many attachment keys went from 3.5MB to 640KB (63.7KB zipped!). --- .../spine/SkeletonBinary.java | 133 ++++++++++-------- 1 file changed, 76 insertions(+), 57 deletions(-) diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java index 3b0a62f85..e96c73abd 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java @@ -133,43 +133,7 @@ public class SkeletonBinary { SkeletonData skeletonData = new SkeletonData(); skeletonData.name = file.nameWithoutExtension(); - DataInput input = new DataInput(file.read(512)) { - private char[] chars = new char[32]; - - public String readString () throws IOException { - int byteCount = readInt(true); - switch (byteCount) { - case 0: - return null; - case 1: - return ""; - } - byteCount--; - if (chars.length < byteCount) chars = new char[byteCount]; - char[] chars = this.chars; - int charCount = 0; - for (int i = 0; i < byteCount;) { - int b = read(); - switch (b >> 4) { - case -1: - throw new EOFException(); - case 12: - case 13: - chars[charCount++] = (char)((b & 0x1F) << 6 | read() & 0x3F); - i += 2; - break; - case 14: - chars[charCount++] = (char)((b & 0x0F) << 12 | (read() & 0x3F) << 6 | read() & 0x3F); - i += 3; - break; - default: - chars[charCount++] = (char)b; - i++; - } - } - return new String(chars, 0, charCount); - } - }; + SkeletonInput input = new SkeletonInput(file); try { skeletonData.hash = input.readString(); if (skeletonData.hash.isEmpty()) skeletonData.hash = null; @@ -194,6 +158,12 @@ public class SkeletonBinary { int n; Object[] o; + // Strings. + input.strings = new Array(n = input.readInt(true)); + o = input.strings.setSize(n); + for (int i = 0; i < n; i++) + o[i] = input.readString(); + // Bones. o = skeletonData.bones.setSize(n = input.readInt(true)); for (int i = 0; i < n; i++) { @@ -225,7 +195,7 @@ public class SkeletonBinary { int darkColor = input.readInt(); if (darkColor != -1) Color.rgb888ToColor(data.darkColor = new Color(), darkColor); - data.attachmentName = input.readString(); + data.attachmentName = input.readStringRef(); data.blendMode = BlendMode.values[input.readInt(true)]; o[i] = data; } @@ -328,7 +298,7 @@ public class SkeletonBinary { // Events. o = skeletonData.events.setSize(n = input.readInt(true)); for (int i = 0; i < n; i++) { - EventData data = new EventData(input.readString()); + EventData data = new EventData(input.readStringRef()); data.intValue = input.readInt(false); data.floatValue = input.readFloat(); data.stringValue = input.readString(); @@ -356,10 +326,10 @@ public class SkeletonBinary { return skeletonData; } - private Skin readSkin (DataInput input, SkeletonData skeletonData, boolean defaultSkin, boolean nonessential) + private Skin readSkin (SkeletonInput input, SkeletonData skeletonData, boolean defaultSkin, boolean nonessential) throws IOException { - Skin skin = new Skin(defaultSkin ? "default" : input.readString()); + Skin skin = new Skin(defaultSkin ? "default" : input.readStringRef()); if (!defaultSkin) { Object[] bones = skeletonData.bones.setSize(input.readInt(true)); @@ -378,7 +348,7 @@ public class SkeletonBinary { for (int i = 0, n = input.readInt(true); i < n; i++) { int slotIndex = input.readInt(true); for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { - String name = input.readString(); + String name = input.readStringRef(); Attachment attachment = readAttachment(input, skeletonData, skin, slotIndex, name, nonessential); if (attachment != null) skin.setAttachment(slotIndex, name, attachment); } @@ -386,17 +356,17 @@ public class SkeletonBinary { return skin; } - private Attachment readAttachment (DataInput input, SkeletonData skeletonData, Skin skin, int slotIndex, String attachmentName, - boolean nonessential) throws IOException { + private Attachment readAttachment (SkeletonInput input, SkeletonData skeletonData, Skin skin, int slotIndex, + String attachmentName, boolean nonessential) throws IOException { float scale = this.scale; - String name = input.readString(); + String name = input.readStringRef(); if (name == null) name = attachmentName; AttachmentType type = AttachmentType.values[input.readByte()]; switch (type) { case region: { - String path = input.readString(); + String path = input.readStringRef(); float rotation = input.readFloat(); float x = input.readFloat(); float y = input.readFloat(); @@ -435,7 +405,7 @@ public class SkeletonBinary { return box; } case mesh: { - String path = input.readString(); + String path = input.readStringRef(); int color = input.readInt(); int vertexCount = input.readInt(true); float[] uvs = readFloatArray(input, vertexCount << 1, 1); @@ -470,10 +440,10 @@ public class SkeletonBinary { return mesh; } case linkedmesh: { - String path = input.readString(); + String path = input.readStringRef(); int color = input.readInt(); - String skinName = input.readString(); - String parent = input.readString(); + String skinName = input.readStringRef(); + String parent = input.readStringRef(); boolean inheritDeform = input.readBoolean(); float width = 0, height = 0; if (nonessential) { @@ -547,7 +517,7 @@ public class SkeletonBinary { return null; } - private Vertices readVertices (DataInput input, int vertexCount) throws IOException { + private Vertices readVertices (SkeletonInput input, int vertexCount) throws IOException { int verticesLength = vertexCount << 1; Vertices vertices = new Vertices(); if (!input.readBoolean()) { @@ -571,7 +541,7 @@ public class SkeletonBinary { return vertices; } - private float[] readFloatArray (DataInput input, int n, float scale) throws IOException { + private float[] readFloatArray (SkeletonInput input, int n, float scale) throws IOException { float[] array = new float[n]; if (scale == 1) { for (int i = 0; i < n; i++) @@ -583,7 +553,7 @@ public class SkeletonBinary { return array; } - private short[] readShortArray (DataInput input) throws IOException { + private short[] readShortArray (SkeletonInput input) throws IOException { int n = input.readInt(true); short[] array = new short[n]; for (int i = 0; i < n; i++) @@ -591,7 +561,7 @@ public class SkeletonBinary { return array; } - private Animation readAnimation (DataInput input, String name, SkeletonData skeletonData) { + private Animation readAnimation (SkeletonInput input, String name, SkeletonData skeletonData) { Array timelines = new Array(32); float scale = this.scale; float duration = 0; @@ -608,7 +578,7 @@ public class SkeletonBinary { AttachmentTimeline timeline = new AttachmentTimeline(frameCount); timeline.slotIndex = slotIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) - timeline.setFrame(frameIndex, input.readFloat(), input.readString()); + timeline.setFrame(frameIndex, input.readFloat(), input.readStringRef()); timelines.add(timeline); duration = Math.max(duration, timeline.getFrames()[frameCount - 1]); break; @@ -769,7 +739,7 @@ public class SkeletonBinary { for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { int slotIndex = input.readInt(true); for (int iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { - VertexAttachment attachment = (VertexAttachment)skin.getAttachment(slotIndex, input.readString()); + VertexAttachment attachment = (VertexAttachment)skin.getAttachment(slotIndex, input.readStringRef()); boolean weighted = attachment.getBones() != null; float[] vertices = attachment.getVertices(); int deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; @@ -872,7 +842,7 @@ public class SkeletonBinary { return new Animation(name, timelines, duration); } - private void readCurve (DataInput input, int frameIndex, CurveTimeline timeline) throws IOException { + private void readCurve (SkeletonInput input, int frameIndex, CurveTimeline timeline) throws IOException { switch (input.readByte()) { case CURVE_STEPPED: timeline.setStepped(frameIndex); @@ -891,4 +861,53 @@ public class SkeletonBinary { int[] bones; float[] vertices; } + + static class SkeletonInput extends DataInput { + private char[] chars = new char[32]; + Array strings; + + public SkeletonInput (FileHandle file) { + super(file.read(512)); + } + + /** @return May be null. */ + public String readStringRef () throws IOException { + int index = readInt(true); + return index == 0 ? null : strings.get(index - 1); + } + + public String readString () throws IOException { + int byteCount = readInt(true); + switch (byteCount) { + case 0: + return null; + case 1: + return ""; + } + byteCount--; + if (chars.length < byteCount) chars = new char[byteCount]; + char[] chars = this.chars; + int charCount = 0; + for (int i = 0; i < byteCount;) { + int b = read(); + switch (b >> 4) { + case -1: + throw new EOFException(); + case 12: + case 13: + chars[charCount++] = (char)((b & 0x1F) << 6 | read() & 0x3F); + i += 2; + break; + case 14: + chars[charCount++] = (char)((b & 0x0F) << 12 | (read() & 0x3F) << 6 | read() & 0x3F); + i += 3; + break; + default: + chars[charCount++] = (char)b; + i++; + } + } + return new String(chars, 0, charCount); + } + } }