1 goog.provide('FlappSWFShapeRecords');
2 goog.require('FlappSWFFillStyles');
4 goog.scope(function() {
9 FlappSWFShapeRecords = function(ibit) {
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);
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;
28 var edgeTypeArray = [];
29 var edges = [currentX, currentY];
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);
46 deltaX = ibit.sb(numBits + 2);
49 var x = currentX + deltaX;
50 var y = currentY + deltaY;
51 edgeTypeArray.push('S');
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);
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;
81 } else if (first6bits) { // Change (0XXXXX != 000000)
82 if (edgeTypeArray.length > 0) {
84 {fillStyle0:fillStyle0, fillStyle1:fillStyle1, lineStyle:lineStyle,
85 edgeTypes:edgeTypeArray.join(''),edges:edges,
86 minX:minX, maxX: maxX, minY:minY, maxY:maxY}
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;
96 var moveBits = ibit.ub(5);
97 currentX = ibit.sb(moveBits); // MoveDeltaX(?)
98 currentY = ibit.sb(moveBits); // MoveDeltaY(?)
100 if (stateFillStyle0) { //
101 fillStyle0 = ibit.ub(numFillBits);
103 if (stateFillStyle1) {
104 fillStyle1 = ibit.ub(numFillBits);
106 if (stateLineStyle) {
107 lineStyle = ibit.ub(numLineBits);
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]);
117 for (var i = 0, l = appendLineStyles.length ; i < l ; i++) {
118 lineStyles.push(appendLineStyles[i]);
121 var numBits = ibit.ui8();
122 numFillBits = numBits >> 4;
123 numLineBits = numBits & 0x0f;
125 if (stateFillStyle0 && fillStyle0) {
126 fillStyle0 += fillStyleBaseIndex;
128 if (stateFillStyle1 && fillStyle1) {
129 fillStyle1 += fillStyleBaseIndex;
131 if (stateLineStyle && lineStyle) {
132 lineStyle += lineStyleBaseIndex;
135 edges = [currentX, currentY];
136 minX = maxX = currentX;
137 minY = maxY = currentY;
140 if (edgeTypeArray.length > 0) {
142 {fillStyle0:fillStyle0, fillStyle1:fillStyle1, lineStyle:lineStyle,
143 edgeTypes:edgeTypeArray.join(''), edges:edges,
144 minX:minX, maxX: maxX, minY:minY, maxY:maxY});
149 FlappSWFShapeRecords.convertEdges = function(shapeRecords) {
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;
163 edgesArray = new Int32Array(l2);
164 for (i2 = 0 ; i2 < l2 ; i2++) {
165 edgesArray[i2] = edges[i2];
167 if (! (fillStyle0 in fillEdges)) {
168 fillEdges[fillStyle0] = [];
170 fillEdges[fillStyle0].push({types:edgeTypes,
172 prev:null, next:null,
173 minX:record.minX, maxX:record.maxX,
174 minY:record.minY, maxY:record.maxY});
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];
183 if (! (fillStyle1 in fillEdges)) {
184 fillEdges[fillStyle1] = [];
186 fillEdges[fillStyle1].push({types:edgeTypes.split('').reverse().join(''),
188 prev:null, next:null,
189 minX:record.minX, maxX:record.maxX,
190 minY:record.minY, maxY:record.maxY});
193 edgesArray = new Int32Array(l2);
194 for (i2 = 0 ; i2 < l2 ; i2++) {
195 edgesArray[i2] = edges[i2];
197 if (! (lineStyle in fillEdges)) {
198 fillEdges[lineStyle] = [];
200 lineEdges[lineStyle].push({types:edgeTypes,
202 minX:record.minX, maxX:record.maxX,
203 minY:record.minY, maxY:record.maxY});
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;
228 edgesInfoList.minX = minX;
229 edgesInfoList.maxX = maxX;
230 edgesInfoList.minY = minY;
231 edgesInfoList.maxY = maxY;
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;
251 edgesInfoList.minX = minX;
252 edgesInfoList.maxX = maxX;
253 edgesInfoList.minY = minY;
254 edgesInfoList.maxY = maxY;
256 return {fillEdges:fillEdges, lineEdges:lineEdges};
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) {
269 edges = edgesInfo.edges;
270 var edgesLastX = edges[edges.length - 2];
271 var edgesLastY = edges[edges.length - 1];
273 if ((edgesLastX === edges[0]) && (edgesLastY === edges[1])) {
274 edgesInfo.next = edgesInfo.prev = i;
277 for (i2 = 0; i2 < l ; i2++) {
278 var targetEdgesInfo = edgesInfoList[i2];
279 if (targetEdgesInfo.prev !== null) {
282 var targetEdges = targetEdgesInfo.edges;
283 if ((edgesLastX === targetEdges[0]) &&
284 (edgesLastY === targetEdges[1])){
286 targetEdgesInfo.prev = i;
291 console.warn("edges link not found");
295 // console.debug('fillEdges');
296 // console.debug(fillEdges);