OSDN Git Service

typo 修正: targetEdgesIngo => targetEdgesInfo
[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     var minX, minY, maxX, maxY;
32     while (first6bits = ibit.ub(6)) {
33         if (first6bits & 0x20) { // Edge (1XXXXX)
34             var numBits = first6bits & 0x0F;
35             if (first6bits & 0x10) { // Straight Edge (11XXXX)
36                 var deltaX = 0, deltaY = 0;
37                 var generalLine = ibit.b();
38                 if (generalLine) { // Straight Edge
39                     deltaX = ibit.sb(numBits + 2);
40                     deltaY = ibit.sb(numBits + 2);
41                 } else { // Straight Edge
42                     var vertLine = ibit.b();
43                     if (vertLine) { // Straight Edge
44                         deltaY = ibit.sb(numBits + 2);
45                     } else {
46                         deltaX = ibit.sb(numBits + 2);
47                     }
48                 }
49                 var x = currentX + deltaX;
50                 var y = currentY + deltaY;
51                 edgeTypeArray.push('S');
52                 edges.push(x, y);
53                 currentX = x;
54                 currentY = y;
55                 if (minX > x) minX = x;
56                 if (maxX < x) maxX = x;
57                 if (minY > y) minY = y;
58                 if (maxY < y) maxY = y;
59             } else { // Curved Edge (10XXXX)
60                 var controlDeltaX = ibit.sb(numBits + 2);
61                 var controlDeltaY = ibit.sb(numBits + 2);
62                 var anchorDeltaX = ibit.sb(numBits + 2);
63                 var anchorDeltaY = ibit.sb(numBits + 2);
64                 var controlX = currentX + controlDeltaX;
65                 var controlY = currentY + controlDeltaY;
66                 var anchorX = controlX + anchorDeltaX;
67                 var anchorY = controlY + anchorDeltaY;
68                 edgeTypeArray.push('C');
69                 edges.push(controlX, controlY, anchorX, anchorY);
70                 currentX = anchorX;
71                 currentY = anchorY;
72                 if (minX > controlX) minX = controlX;
73                 if (maxX < controlX) maxX = controlX;
74                 if (minY > controlY) minY = controlY;
75                 if (maxY < controlY) maxY = controlY;
76                 if (minX > anchorX) minX = anchorX;
77                 if (maxX < anchorX) maxX = anchorX;
78                 if (minY > anchorY) minY = anchorY;
79                 if (maxY < anchorY) maxY = anchorY;
80             }
81         } else if (first6bits) { // Change (0XXXXX != 000000)
82             if (edgeTypeArray.length > 0) {
83                 shapeRecords.push(
84                     {fillStyle0:fillStyle0, fillStyle1:fillStyle1, lineStyle:lineStyle,
85                      edgeTypes:edgeTypeArray.join(''),edges:edges,
86                      minX:minX, maxX: maxX, minY:minY, maxY:maxY}
87                 );
88             }
89             var stateNewStyles  = first6bits & 0x10;
90             var stateLineStyle  = first6bits &    8;
91             var stateFillStyle1 = first6bits &    4;
92             var stateFillStyle0 = first6bits &    2;
93             var stateMoveTo     = first6bits &    1;
94
95             if (stateMoveTo) {
96                 var moveBits = ibit.ub(5);
97                 currentX = ibit.sb(moveBits); // MoveDeltaX(?)
98                 currentY = ibit.sb(moveBits); // MoveDeltaY(?)
99             }
100             if (stateFillStyle0) { // 
101                 fillStyle0 = ibit.ub(numFillBits);
102             }
103             if (stateFillStyle1) {
104                 fillStyle1 = ibit.ub(numFillBits);
105             }
106             if (stateLineStyle) {
107                 lineStyle = ibit.ub(numLineBits);
108             }
109             if (stateNewStyles) {
110                 fillStyleBaseIndex = fillStyles.length;
111                 lineStyleBaseIndex = lineStyles.length;
112                 var appendFillStyles = FlappSWFFillStyles.load(code, ibit);
113                 var appendLineStyles = FlappSWFLineStyles.load(code, ibit);
114                 for (var i = 0, l = appendFillStyles.length ; i < l ; i++) {
115                     fillStyles.push(appendFillStyles[i]);
116                 }
117                 for (var i = 0, l = appendLineStyles.length ; i < l ; i++) {
118                     lineStyles.push(appendLineStyles[i]);
119                 }
120                 ibit.a();
121                 var numBits = ibit.ui8();
122                 numFillBits = numBits >> 4;
123                 numLineBits = numBits & 0x0f;
124             }
125             if (stateFillStyle0 && fillStyle0) { 
126                 fillStyle0 += fillStyleBaseIndex;
127             }
128             if (stateFillStyle1 && fillStyle1) {
129                 fillStyle1 += fillStyleBaseIndex;
130             }
131             if (stateLineStyle && lineStyle) {
132                 lineStyle += lineStyleBaseIndex;
133             }
134             edgeTypeArray = [];
135             edges = [currentX, currentY];
136             minX = maxX = currentX;
137             minY = maxY = currentY;
138         }
139     }
140     if (edgeTypeArray.length > 0) {
141         shapeRecords.push(
142             {fillStyle0:fillStyle0, fillStyle1:fillStyle1, lineStyle:lineStyle,
143              edgeTypes:edgeTypeArray.join(''), edges:edges,
144              minX:minX, maxX: maxX, minY:minY, maxY:maxY});
145     }
146     return shapeRecords;
147 };
148
149 FlappSWFShapeRecords.convertEdges = function(shapeRecords) {
150     var i, l;
151     var fillEdges = {}; // fillStyle => []
152     var lineEdges = {}; // lineStyle => []
153     for (i = 0, l = shapeRecords.length ; i < l ; i++) {
154         var record = shapeRecords[i];
155         var i2, l2 = record.edges.length;
156         var fillStyle0 = record.fillStyle0;
157         var fillStyle1 = record.fillStyle1;
158         var lineStyle = record.lineStyle;
159         var edgeTypes = record.edgeTypes;
160         var edges = record.edges;
161         var edgesArray;
162         if (fillStyle0) {
163             edgesArray = new Int32Array(l2);
164             for (i2 = 0 ; i2 < l2 ; i2++) {
165                 edgesArray[i2] = edges[i2];
166             }
167             if (! (fillStyle0 in fillEdges)) {
168                 fillEdges[fillStyle0] = [];
169             }
170             fillEdges[fillStyle0].push({types:edgeTypes,
171                                         edges:edgesArray,
172                                         prev:null, next:null,
173                                         minX:record.minX, maxX:record.maxX,
174                                         minY:record.minY, maxY:record.maxY});
175         }
176         if (fillStyle1) {
177             var rl2 = l2; // reverse l2
178             edgesArray = new Int32Array(l2);
179             for (i2 = 0 ; i2 < l2 ; i2 += 2) {
180                 edgesArray[i2+1] = edges[--rl2];
181                 edgesArray[i2] = edges[--rl2];
182             }
183             if (! (fillStyle1 in fillEdges)) {
184                 fillEdges[fillStyle1] = [];
185             }
186             fillEdges[fillStyle1].push({types:edgeTypes.split('').reverse().join(''),
187                                         edges:edgesArray,
188                                         prev:null, next:null,
189                                         minX:record.minX, maxX:record.maxX,
190                                         minY:record.minY, maxY:record.maxY});
191         }
192         if (lineStyle) {
193             edgesArray = new Int32Array(l2);
194             for (i2 = 0 ; i2 < l2 ; i2++) {
195                 edgesArray[i2] = edges[i2];
196             }
197             if (! (lineStyle in fillEdges)) {
198                 fillEdges[lineStyle] = [];
199             }
200             lineEdges[lineStyle].push({types:edgeTypes,
201                                        edges:edgesArray,
202                                        minX:record.minX, maxX:record.maxX,
203                                        minY:record.minY, maxY:record.maxY});
204         }
205     }
206     // max, min, X, Y
207     var minX, maxX, minY, maxY;
208     var minX2, maxX2, minY2, maxY2;
209     var edgesInfoList, edgesInfo0, edgesInfo;
210     for (var style in fillEdges) {
211         edgesInfoList = fillEdges[style];
212         edgesInfo0 = edgesInfoList[0];
213         minX = edgesInfo0.minX;
214         maxX = edgesInfo0.maxX;
215         minY = edgesInfo0.minY;
216         maxY = edgesInfo0.maxY;
217         for (i = 0, l = edgesInfoList.length ; i < l ; i++) {
218             edgesInfo = edgesInfoList[i];
219             minX2 = edgesInfo.minX;
220             maxX2 = edgesInfo.maxX;
221             minY2 = edgesInfo.minY;
222             maxY2 = edgesInfo.maxY;
223             if (minX > minX2) minX = minX2;
224             if (maxX < maxX2) maxX = maxX2;
225             if (minY > minY2) minX = minY2;
226             if (maxY < maxY2) maxX = maxY2;
227         }
228         edgesInfoList.minX = minX;
229         edgesInfoList.maxX = maxX;
230         edgesInfoList.minY = minY;
231         edgesInfoList.maxY = maxY;
232     }
233     for (var style in lineEdges) {
234         edgesInfoList = lineEdges[style];
235         edgesInfo0 = edgesInfoList[0];
236         minX = edgesInfo0.minX;
237         maxX = edgesInfo0.maxX;
238         minY = edgesInfo0.minY;
239         maxY = edgesInfo0.maxY;
240         for (i = 0, l = edgesInfoList.length ; i < l ; i++) {
241             edgesInfo = edgesInfoList[i];
242             minX2 = edgesInfo.minX;
243             maxX2 = edgesInfo.maxX;
244             minY2 = edgesInfo.minY;
245             maxY2 = edgesInfo.maxY;
246             if (minX > minX2) minX = minX2;
247             if (maxX < maxX2) maxX = maxX2;
248             if (minY > minY2) minX = minY2;
249             if (maxY < maxY2) maxX = maxY2;
250         }       
251         edgesInfoList.minX = minX;
252         edgesInfoList.maxX = maxX;
253         edgesInfoList.minY = minY;
254         edgesInfoList.maxY = maxY;
255     }
256     return {fillEdges:fillEdges, lineEdges:lineEdges};
257 }
258
259 FlappSWFShapeRecords.markFillEdgeLoop = function(fillEdges) {
260     var style, edgesInfoList;
261     var i, l, i2, edgesInfo, edges;
262     for (style in fillEdges) {
263         edgesInfoList = fillEdges[style];
264         for (i = 0, l = edgesInfoList.length ; i < l ; i++) {
265             edgesInfo = edgesInfoList[i];
266             if (edgesInfo.next !== null) {
267                 continue; // skip
268             }
269             edges = edgesInfo.edges;
270             var edgesLastX = edges[edges.length - 2];
271             var edgesLastY = edges[edges.length - 1];
272             // self loop check
273             if ((edgesLastX === edges[0]) && (edgesLastY === edges[1])) {
274                 edgesInfo.next = edgesInfo.prev = i;
275                 continue;
276             }
277             for (i2 = 0; i2 < l ; i2++) {
278                 var targetEdgesInfo = edgesInfoList[i2];
279                 if (targetEdgesInfo.prev !== null) {
280                     continue;
281                 }
282                 var targetEdges = targetEdgesInfo.edges;
283                 if ((edgesLastX === targetEdges[0]) &&
284                     (edgesLastY === targetEdges[1])){
285                     edgesInfo.next = i2;
286                     targetEdgesInfo.prev = i;
287                     break;
288                 }
289             }
290             if (i2 === l) {
291                 console.warn("edges link not found");
292             }
293         }
294     }
295 //    console.debug('fillEdges');
296 //    console.debug(fillEdges);
297 }
298
299 });