OSDN Git Service

ec51e0175a17270d4e61d737535af189a6032a4f
[flapp/flapp.git] / src / swf / shaperecords.js
1 goog.provide('FlappSWFShapeRecords');
2 goog.require('FlappSWFFillStyles');
3
4 goog.scope(function() {
5
6 /**
7  * @constructor
8  */
9 FlappSWFShapeRecords = function(ibit) {
10     ;
11 };
12
13 FlappSWFShapeRecords.loadAndMarkEdgeLoop = function(code, ibit, fillStyles, lineStyles, numFillBits, numLineBits) {
14     var shapes = FlappSWFShapeRecords.load(code, ibit, fillStyles, lineStyles, numFillBits, numLineBits);
15     var edges = FlappSWFShapeRecords.convertEdges(shapes);
16     shapes = null ; // for GC
17     FlappSWFShapeRecords.markFillEdgeLoop(edges.fillEdges);
18     return edges;
19 }
20
21 FlappSWFShapeRecords.load = function(code, ibit, fillStyles, lineStyles, numFillBits, numLineBits) {
22     var shapeRecords = []; // [[fillstyle0, fillstyle1, linestyle, edgetypes, [edges]], [], ...]
23     var fillStyleBaseIndex = 0;
24     var lineStyleBaseIndex = 0;
25     var fillStyle0 = 0, fillStyle1 = 0, lineStyle = 0;
26     var currentX = 0, currentY = 0;
27     ibit.a();
28     var edgeTypeArray = [];
29     var edges = [currentX, currentY];
30     var first6bits;
31     while (first6bits = ibit.ub(6)) {
32         if (first6bits & 0x20) { // Edge (1XXXXX)
33             var numBits = first6bits & 0x0F;
34             if (first6bits & 0x10) { // Straight Edge (11XXXX)
35                 var deltaX = 0, deltaY = 0;
36                 var generalLine = ibit.b();
37                 if (generalLine) { // Straight Edge
38                     deltaX = ibit.sb(numBits + 2);
39                     deltaY = ibit.sb(numBits + 2);
40                 } else { // Straight Edge
41                     var vertLine = ibit.b();
42                     if (vertLine) { // Straight Edge
43                         deltaY = ibit.sb(numBits + 2);
44                     } else {
45                         deltaX = ibit.sb(numBits + 2);
46                     }
47                 }
48                 var x = currentX + deltaX;
49                 var y = currentY + deltaY;
50                 edgeTypeArray.push('S');
51                 edges.push(x, y);
52                 currentX = x;
53                 currentY = y;
54             } else { // Curved Edge (10XXXX)
55                 var controlDeltaX = ibit.sb(numBits + 2);
56                 var controlDeltaY = ibit.sb(numBits + 2);
57                 var anchorDeltaX = ibit.sb(numBits + 2);
58                 var anchorDeltaY = ibit.sb(numBits + 2);
59                 var controlX = currentX + controlDeltaX;
60                 var controlY = currentY + controlDeltaY;
61                 var anchorX = controlX + anchorDeltaX;
62                 var anchorY = controlY + anchorDeltaY;
63                 edgeTypeArray.push('C');
64                 edges.push(controlX, controlY,
65                     anchorX, anchorY);
66                 currentX = anchorX;
67                 currentY = anchorY;
68             }
69         } else if (first6bits) { // Change (0XXXXX != 000000)
70             if (edgeTypeArray.length > 1) {
71                 shapeRecords.push(
72                     {fillStyle0:fillStyle0, fillStyle1:fillStyle1, lineStyle:lineStyle,
73                      edgeTypes:edgeTypeArray.join(''),edges:edges}
74                 );
75             }
76             if (first6bits & 0x10) { // StateNewStyles
77                 fillStyleBaseIndex = fillStyles.length;
78                 lineStyleBaseIndex = lineStyles.length;
79                 var appendFillStyles = FlappSWFFillStyles.load(code, ibit);
80                 var appendLineStyles = FlappSWFLineStyles.load(code, ibit);
81                 var extendFillStyles = [];
82                 var extendLineStyles = [];
83                 for (var i = 0, l = fillStyles.length ; i < l ; i++) {
84                     extendFillStyles.push(fillStyles[i]);
85                 }
86                 for (var i = 0, l = appendFillStyles.length ; i < l ; i++) {
87                     extendFillStyles.push(appendFillStyles[i]);
88                 }
89                 for (var i = 0, l = lineStyles.length ; i < l ; i++) {
90                     extendLineStyles.push(lineStyles[i]);
91                 }
92                 for (var i = 0, l = appendLineStyles.length ; i < l ; i++) {
93                     extendLineStyles.push(appendLineStyles[i]);
94                 }
95                 fillStyles = extendFillStyles;
96                 lineStyles = extendFillStyles;
97                 ibit.a();
98                 var numBits = ibit.ui8();
99                 numFillBits = numBits >> 4;
100                 numLineBits = numBits & 0x0f;
101                 fillStyleBaseIndex = fillStyles.length;
102                 lineStyleBaseIndex = lineStyles.length;
103             }
104             if (first6bits & 1) { // StateMoveTo
105                 var moveBits = ibit.ub(5);
106                 currentX = ibit.sb(moveBits); // MoveDeltaX(?)
107                 currentY = ibit.sb(moveBits); // MoveDeltaY(?)
108             }
109             if (first6bits & 2) { // StateFillStyle0
110                 fillStyle0 = ibit.ub(numFillBits);
111                 if (fillStyle0) {
112                     fillStyle0 += fillStyleBaseIndex;
113                 }
114             }
115             if (first6bits & 4) { // StateFillStyle1
116                 fillStyle1 = ibit.ub(numFillBits);
117                 if (fillStyle1) {
118                     fillStyle1 += fillStyleBaseIndex;
119                 }
120             }
121             if (first6bits & 8) { // StateLineStyle
122                 lineStyle = ibit.ub(numLineBits);
123                 if (lineStyle) {
124                     lineStyle += lineStyleBaseIndex;
125                 }
126             }
127             edgeTypeArray = [];
128             edges = [currentX, currentY];
129         }
130     }
131     if (edgeTypeArray.length > 1) {
132         shapeRecords.push(
133             {fillStyle0:fillStyle0, fillStyle1:fillStyle1, lineStyle:lineStyle,
134              edgeTypes:edgeTypeArray.join(''), edges:edges}
135         );
136     }
137     return shapeRecords;
138 };
139
140 FlappSWFShapeRecords.convertEdges = function(shapeRecords) {
141     var i, l;
142     var fillEdges = {}; // fillStyle => []
143     var lineEdges = {}; // lineStyle => []
144     for (i = 0, l = shapeRecords.length ; i < l ; i++) {
145         var record = shapeRecords[i];
146         var i2, l2 = record.edges.length;
147         var fillStyle0 = record.fillStyle0;
148         var fillStyle1 = record.fillStyle1;
149         var lineStyle = record.lineStyle;
150         var edgeTypes = record.edgeTypes;
151         var edges = record.edges;
152         var edgesArray;
153         if (fillStyle0) {
154             edgesArray = new Int32Array(l2);
155             for (i2 = 0 ; i2 < l2 ; i2++) {
156                 edgesArray[i2] = edges[i2];
157             }
158             if (! (fillStyle0 in fillEdges)) {
159                 fillEdges[fillStyle0] = [];
160             }
161             fillEdges[fillStyle0].push({types:edgeTypes,
162                                         edges:edgesArray,
163                                         prev:null, next:null});
164         }
165         if (fillStyle1) {
166             var rl2 = l2; // reverse l2
167             edgesArray = new Int32Array(l2);
168             for (i2 = 0 ; i2 < l2 ; i2++) {
169                 edgesArray[i2] = edges[--rl2];
170             }
171             if (! (fillStyle1 in fillEdges)) {
172                 fillEdges[fillStyle1] = [];
173             }
174             fillEdges[fillStyle1].push({types:edgeTypes.split('').reverse().join(''),
175                                         edges:edgesArray,
176                                         prev:null, next:null});
177         }
178         if (lineStyle) {
179             edgesArray = new Int32Array(l2);
180             for (i2 = 0 ; i2 < l2 ; i2++) {
181                 edgesArray[i2] = edges[i2];
182             }
183             if (! (lineStyle in fillEdges)) {
184                 fillEdges[lineStyle] = [];
185             }
186             lineEdges[lineStyle].push({types:edgeTypes,
187                                        edges:edgesArray});
188         }
189     }
190     return {fillEdges:fillEdges, lineEdges:lineEdges};
191 }
192
193 FlappSWFShapeRecords.markFillEdgeLoop = function(fillEdges) {
194     var style, edgesInfoList;
195     var i, l, i2, edgesInfo, edges;
196     for (style in fillEdges) {
197         edgesInfoList = fillEdges[style];
198         for (i = 0, l = edgesInfoList.length ; i < l ; i++) {
199             edgesInfo = edgesInfoList[i];
200             edges = edgesInfo.edges;
201             var edgesLastX = edges[edges.length - 2];
202             var edgesLastY = edges[edges.length - 1];
203             for (i2 = 0; i2 < l ; i2++) {
204                 if (edgesInfo.prev !== null) {
205                     continue; // skip
206                 }
207                 var targetEdge = edgesInfoList[i2].edges;
208                 if ((edgesLastX === edges[0]) &&
209                     (edgesLastY === edges[1])){
210                     edgesInfo.next = i2;
211                     edgesInfoList[i2].prev = i;
212                     break;
213                 }
214             }
215             if (i2 === l) {
216                 console.warn("edges link not found");
217             }
218         }
219     }
220 }
221
222 });