1//
2// Some tests for the Drawing API
3// Build with:
4//	makeswf -o DrawingApi.swf DrawingApi.as
5// Run with:
6//	firefox DrawingApi.swf
7// Or:
8//	gnash DrawingApi.swf
9//
10//
11// Click the mouse button to turn the cursor shape into a mask and back.
12// Press a number on the keyboard to switch between "pages" of the drawing.
13// We currently have pages 1, 2, 3, 4.
14// All pages are tested automatically.
15//
16// '-' and '+' decrement and increment _alpha
17// 'h' toggles _visible
18//
19
20
21#include "../actionscript.all/check.as"
22
23// Make Matrix visible for easier gradient tests.
24ASSetPropFlags(_global, "flash", 0, 5248);
25
26printBounds = function(b)
27{
28	return ''+Math.round(b.xMin*100)/100+','+Math.round(b.yMin*100)/100+' '+Math.round(b.xMax*100)/100+','+Math.round(b.yMax*100)/100;
29};
30
31// Can draw both on a dynamically-created movie...
32createEmptyMovieClip("a", 10);
33// ... or on a statically-created one
34//a = _root;
35
36red = new Object();
37red.valueOf = function() { return 0xFF0000; };
38
39thick = new Object();
40thick.valueOf = function() { return 20; };
41
42halftransparent = new Object();
43halftransparent.valueOf = function() { return 50; };
44
45// Draw a circle with given center and radius
46// Uses 8 curves to approximate the circle
47drawCircle = function (where, x, y, rad)
48{
49        var ctl = Math.sin(24*Math.PI/180)*rad;
50        var cos = Math.cos(45*Math.PI/180)*rad;
51        var sin = Math.sin(45*Math.PI/180)*rad;
52
53        with (where)
54        {
55                moveTo(x, y-rad);
56                curveTo(x+ctl, y-rad, x+cos, y-sin);
57                curveTo(x+rad, y-ctl, x+rad, y);
58                curveTo(x+rad, y+ctl, x+cos, y+sin);
59                curveTo(x+ctl, y+rad, x, y+rad);
60                curveTo(x-ctl, y+rad, x-cos, y+sin);
61                curveTo(x-rad, y+ctl, x-rad, y);
62                curveTo(x-rad, y-ctl, x-cos, y-sin);
63                curveTo(x-ctl, y-rad, x, y-rad);
64        }
65};
66
67
68with (a)
69{
70	clear();
71
72	bnd = printBounds(a.getBounds());
73	if ( bnd == "6710886.35,6710886.35 6710886.35,6710886.35" ) {
74		trace("PASSED: getBounds() returns "+bnd+" after clear");
75	} else {
76		trace("FAILED: getBounds() returns "+bnd+" after clear");
77	}
78
79	// The thick red line
80	lineStyle(thick, red, 100);
81	moveTo(100, 100);
82
83	bnd = printBounds(a.getBounds());
84	check_equals(bnd, "6710886.35,6710886.35 6710886.35,6710886.35");
85
86	lineTo(200, 200);
87
88	bnd = printBounds(a.getBounds());
89	check_equals(bnd, "80,80 220,220");  // line is 20 pixels thick..
90
91	// The hairlined horizontal black line
92	lineStyle(0, 0x000000, 100);
93	moveTo(220, 180);
94
95	bnd = printBounds(a.getBounds());
96	check_equals(bnd, "80,80 220,220");  // neither line style change nore moveTo change the bounds
97
98	lineTo(280, 180);
99
100	bnd = printBounds(a.getBounds());
101	check_equals(bnd, "80,80 280,220");  // now hairlined line from 220,180 to 280,180 was added
102
103	// The violet line
104	moveTo(100, 200);
105	lineStyle(5, 0xFF00FF, halftransparent);
106
107	bnd = printBounds(a.getBounds());
108	check_equals(bnd, "80,80 280,220"); // line style change and moveTo don't change anything
109
110	lineTo(200, 250);
111
112	bnd = printBounds(a.getBounds());
113	check_equals(bnd, "80,80 280,255"); // line thinkness is now 5, so 250 gets to 255
114
115	// The yellow line
116	lineStyle(10, 0xFFFF00, 100);
117	lineTo(400, 200);
118
119	bnd = printBounds(a.getBounds());
120	check_equals(bnd, "80,80 410,260"); // line thinkness of 10 adds to x (now 410) and to starting point y (was 250)
121
122	// The green curve
123	lineStyle(8, 0x00FF00, 100);
124	curveTo(400, 120, 300, 100);
125	check( ! hitTest(376, 180, true) );
126	check( hitTest(376, 139, true) );
127
128	bnd = printBounds(a.getBounds());
129	check_equals(bnd, "80,80 410,260"); // the curve is all inside the current bounds
130
131	// Transparent line
132	lineStyle();
133	lineTo(80, 100);
134
135	// The black thick vertical line
136	lineStyle(20);
137	lineTo(80, 150);
138
139	bnd = printBounds(a.getBounds());
140	check_equals(bnd, "60,80 410,260"); // new thinkness of 20 moves our left margin
141
142	// The ugly blue-fill red-stroke thingy
143	moveTo(80, 180);
144	lineStyle(2, 0xFF0000);
145	beginFill(0x0000FF, 100);
146	lineTo(50, 180);
147
148	bnd = printBounds(a.getBounds());
149	check_equals(bnd, "48,80 410,260"); // we get left to 50-thickness(2) now
150
151	curveTo(20, 200, 50, 250);
152
153	bnd = printBounds(a.getBounds());
154	check_equals(bnd, "18,80 410,260"); // we get left to 20-thickness(2) now
155
156	lineTo(100, 250);
157	lineTo(80, 180);
158	endFill();
159	lineTo(50, 150);
160
161	// The clockwise blue-stroke, cyan-fill square
162	moveTo(200, 100);
163	lineStyle(1, 0x00FF00);
164	beginFill(0x00FFFF, 100);
165	lineTo(200, 120);
166	lineTo(180, 120);
167	lineTo(180, 100);
168	lineTo(200, 100);
169	endFill();
170
171	bnd = printBounds(a.getBounds());
172	check_equals(bnd, "18,80 410,260"); // nothing new..
173
174	// The counter-clockwise cyan-stroke, green-fill (alpha 50) square
175	moveTo(230, 100);
176	lineStyle(1, 0x00FFFF);
177	beginFill(0x00FF00, 50);
178	lineTo(210, 100);
179	lineTo(210, 120);
180	lineTo(230, 120);
181	lineTo(230, 100);
182	endFill();
183
184	// The clockwise green-stroke, violet-fill square, with move after beginFill
185	lineStyle(1, 0x00FF00);
186	beginFill(0xFF00FF, 100);
187	moveTo(260, 100);
188	lineTo(260, 120);
189	lineTo(240, 120);
190	lineTo(240, 100);
191	lineTo(260, 100);
192	endFill();
193
194	// The green circle
195	lineStyle(8, 0x000000);
196	beginFill(0x00FF00, 100);
197	drawCircle(a, 330, 160, 35);
198	endFill();
199
200	bnd = printBounds(a.getBounds());
201	check_equals(bnd, "18,80 410,260"); // nothing new..
202
203	createEmptyMovieClip("zshape", 1);
204	with (zshape)
205	{
206		// The Z-shaped 3 edges stroke
207		//
208		//
209		//   0-----1--+
210		//            |
211		//            2
212		//            |
213		//            |
214		//            +--3----4
215		//
216		lineStyle(4, 0);
217		x = 223; y=145;
218		moveTo(x, y);
219		lineTo(x+20, y+0);
220		lineTo(x+20, y+20);
221		lineTo(x+50, y+20);
222	}
223	bnd = printBounds(zshape.getBounds());
224	check_equals(bnd, "219,141 277,169");
225	//                "223,145 273,165" + 4 for thickness
226	check_equals( typeof(zshape.hitTest), 'function' );
227	check( zshape.hitTest(223, 145, true) ); // 0
228	check( zshape.hitTest((223+10), (145+0), true) ); // 1
229	check( zshape.hitTest((223+20), (145+5), true) ); // 2
230	check( zshape.hitTest((223+25), (145+20), true) ); // 3
231	check( zshape.hitTest(273, 165, true) ); // 4
232
233	// The ugly orange stroke / light brown fill
234	// expected to auto-close on endFill()
235	createEmptyMovieClip("x", 20);
236	with (x)
237	{
238		lineStyle(6, 0xFF8800);
239		beginFill(0x888800, 100);
240		moveTo(100, 100);
241		//lineTo("string", NaN); // equivalent to 0, 0
242		lineTo(0, 0);
243		//curveTo(100, "string", Object, 100); // equivalent to 100, 0, 0, 100
244		curveTo(100, 0, 0 ,100);
245		//moteTo(undefined, 0); // equivalent to 0, 0
246		//moveTo(0,0); ???
247		//lineTo(100, null); // equivalent to 100, 0
248		lineTo(100, 0);
249		endFill();
250	}
251	x._x = 100;
252	x._y = 150;
253	x._xscale = 30;
254	x._yscale = 30;
255
256	check( x.hitTest(126, 168, true) );
257	check( x.hitTest(112, 158, true) );
258
259    // COMPATIBLITY NOTE:
260    // flashplayer 10.0.12.10 for linux fails this, whereas 9.0.115.0 doesn't
261	check( x.hitTest(122, 157, true) );
262
263	check( ! x.hitTest(120, 155, true) );
264	check( x.hitTest(120, 155, false) );
265	check( ! x.hitTest(116, 177, true) );
266	check( x.hitTest(116, 177, false) );
267}
268
269// Make the MovieClip "active" (grabbing mouse events)
270// This allows testing of fill styles and "thick" lines
271a.onRollOver = function() {};
272
273frameno = 0;
274a.createEmptyMovieClip("b", 2);
275a.onEnterFrame = function()
276{
277	if ( ++frameno > 8 )
278	{
279		//this.clear();
280		frameno = 0;
281		ret = delete this.onEnterFrame;
282		if ( ret ) {
283			trace("PASSED: delete this.onEnterFrame returned "+ret);
284		} else {
285			trace("FAILED: delete this.onEnterFrame returned "+ret);
286		}
287	}
288	else
289	{
290                // #40315: test that we don't crash without a line style.
291                this.b.lineTo(10, 20);
292
293		this.b.clear();
294		this.b.lineStyle(2, 0xFF0000);
295		this.b.beginFill(0xFFFF00, 100);
296		drawCircle(this.b, (50*frameno), 280, 10);
297		this.b.endFill();
298	}
299};
300
301//---------------------------------------------------------------------------
302// Some invalid shapes, get there hitting the right-arrow
303//---------------------------------------------------------------------------
304
305createEmptyMovieClip("inv", 100);
306with(inv)
307{
308	// Crossing edge
309	createEmptyMovieClip("inv1", 1);
310	with (inv1)
311	{
312		moveTo(10, 10);
313		beginFill(0xFF0000);
314		lineTo(20, 10);
315		lineTo(10, 20);
316		lineTo(20, 20);
317		endFill(); // should close to 10,10
318	}
319	inv1._xscale = inv1._yscale = 400;
320	inv1.onRollOver = function() {};
321
322	// Four intersecting edges  (like in "four in a row")
323	createEmptyMovieClip("inv2", 2);
324	with (inv2)
325	{
326		lineStyle(0, 0); // hairline
327		beginFill(0x00FF00);
328
329		moveTo(10, 8);
330		lineTo(10, 20);
331
332		moveTo(8, 10);
333		lineTo(20, 10);
334
335		moveTo(18, 8);
336		lineTo(18, 20);
337
338		moveTo(8, 18);
339		lineTo(20, 18);
340
341	}
342	inv2._xscale = inv2._yscale = 400; inv2._x = 100;
343	inv2.onRollOver = function() {};
344
345	// Opposite el shapes
346	createEmptyMovieClip("inv3", 3);
347	with (inv3)
348	{
349		lineStyle(0, 0); // hairline
350		beginFill(0x00FF00);
351
352		moveTo(10, 8);
353		lineTo(10, 20);
354		lineTo(2, 20);
355
356		moveTo(18, 8);
357		lineTo(18, 20);
358		lineTo(26, 20);
359
360	}
361	inv3._xscale = inv3._yscale = 400; inv3._y = 100;
362	inv3.onRollOver = function() {};
363
364	check(  inv3.hitTest((8*4), 100 + (18*4), true)  );  // Inside the left autofill
365	check( !inv3.hitTest((4*4), 100 + (10*4), true)  );  // Outside the left autofill (but in the boundaries)
366	check(  inv3.hitTest((4*4), 100 + (10*4), false) );  // Outside the left autofill (but in the boundaries)
367
368	check(  inv3.hitTest((20*4), 100 + (18*4), true)  );  // Inside the right autofill
369	check( !inv3.hitTest((24*4), 100 + (10*4), true)  );  // Outside the right autofill (but in the boundaries)
370	check(  inv3.hitTest((24*4), 100 + (10*4), false) );  // Outside the right autofill (but in the boundaries)
371
372	// Nested squares (inner is an hole)
373	// Both squares are defined in counterclockwise order
374	createEmptyMovieClip("inv4", 4);
375	with (inv4)
376	{
377		lineStyle(0, 0); // hairline
378		beginFill(0x00FF00);
379
380		moveTo(10, 10);
381		lineTo(10, 20);
382		lineTo(20, 20);
383		lineTo(20, 10);
384		lineTo(10, 10);
385
386		moveTo(12, 12);
387		lineTo(12, 18);
388		lineTo(18, 18);
389		lineTo(18, 12);
390		lineTo(12, 12);
391	}
392	inv4._xscale = inv4._yscale = 400;
393	inv4._y = 100; inv4._x = 100;
394	inv4.onRollOver = function() {};
395
396	// check that a point inside the hole doesn't hit the shape
397	// (gnash fails due to bogus point_test, or missing normalization)
398	check( ! inv4.hitTest(100 + (15*4), 100 + (15*4), true) );
399
400	// while a points on the border do hit it
401	check( inv4.hitTest(100 + (11*4), 100 + (11*4), true) );  // Upper-Left
402	check( inv4.hitTest(100 + (11*4), 100 + (14*4), true) );  // Center-Left
403	check( inv4.hitTest(100 + (11*4), 100 + (19*4), true) );  // Lower-Left
404	check( inv4.hitTest(100 + (14*4), 100 + (19*4), true) );  // Lower-Center
405	check( inv4.hitTest(100 + (19*4), 100 + (19*4), true) );  // Lower-Right
406	check( inv4.hitTest(100 + (19*4), 100 + (14*4), true) );  // Center-Right
407	check( inv4.hitTest(100 + (19*4), 100 + (11*4), true) );  // Upper-Right
408	check( inv4.hitTest(100 + (14*4), 100 + (11*4), true) );  // Upper-Center
409
410	// Nested squares (inner is an hole)
411	// Outer square counterclockwise order, inner in closwise order
412	// NOTE that there's no difference with inv4 in rendering and hit test
413	createEmptyMovieClip("inv5", 5);
414	with (inv5)
415	{
416		lineStyle(0, 0); // hairline
417		beginFill(0x00FF00);
418
419		moveTo(10, 10);
420		lineTo(10, 20);
421		lineTo(20, 20);
422		lineTo(20, 10);
423		lineTo(10, 10);
424
425		moveTo(12, 12);
426		lineTo(18, 12);
427		lineTo(18, 18);
428		lineTo(12, 18);
429		lineTo(12, 12);
430	}
431	inv5._xscale = inv5._yscale = 400;
432	inv5._y = 100; inv5._x = 150;
433	inv5.onRollOver = function() {};
434
435	// check that a point inside the hole doesn't hit the shape
436	// (gnash fails due to bogus point_test, or missing normalization)
437	check( ! inv5.hitTest(150 + (15*4), 100 + (15*4), true) );
438
439	// while a points on the border do hit it
440	check( inv5.hitTest(150 + (11*4), 100 + (11*4), true) );  // Upper-Left
441	check( inv5.hitTest(150 + (11*4), 100 + (14*4), true) );  // Center-Left
442	check( inv5.hitTest(150 + (11*4), 100 + (19*4), true) );  // Lower-Left
443	check( inv5.hitTest(150 + (14*4), 100 + (19*4), true) );  // Lower-Center
444	check( inv5.hitTest(150 + (19*4), 100 + (19*4), true) );  // Lower-Right
445	check( inv5.hitTest(150 + (19*4), 100 + (14*4), true) );  // Center-Right
446	check( inv5.hitTest(150 + (19*4), 100 + (11*4), true) );  // Upper-Right
447	check( inv5.hitTest(150 + (14*4), 100 + (11*4), true) );  // Upper-Center
448
449	// Nested squares (this time we call beginFill again before the move)
450	// Outer square counterclockwise order, inner in clockwise order
451	// This time, the inner square will NOT be considered an hole !
452	createEmptyMovieClip("inv6", 6);
453	with (inv6)
454	{
455		lineStyle(0, 0); // hairline
456		beginFill(0x00FF00);
457
458		moveTo(10, 10);
459		lineTo(10, 20);
460		lineTo(20, 20);
461		lineTo(20, 10);
462		lineTo(10, 10);
463
464		// this forces endFill call, which triggers finalization of previous path (I think)
465		beginFill(0x00FF00);
466
467		moveTo(12, 12);
468		lineTo(18, 12);
469		lineTo(18, 18);
470		lineTo(12, 18);
471		lineTo(12, 12);
472	}
473	inv6._xscale = inv6._yscale = 400;
474	inv6._y = 100; inv6._x = 200;
475	inv6.onRollOver = function() {};
476
477	// Point inside the inner square hits the shape !
478	check( inv6.hitTest(200 + (15*4), 100 + (15*4), true) );
479	// As points on the outer borders
480	check( inv6.hitTest(200 + (11*4), 100 + (11*4), true) );  // Upper-Left
481	check( inv6.hitTest(200 + (11*4), 100 + (14*4), true) );  // Center-Left
482	check( inv6.hitTest(200 + (11*4), 100 + (19*4), true) );  // Lower-Left
483	check( inv6.hitTest(200 + (14*4), 100 + (19*4), true) );  // Lower-Center
484	check( inv6.hitTest(200 + (19*4), 100 + (19*4), true) );  // Lower-Right
485	check( inv6.hitTest(200 + (19*4), 100 + (14*4), true) );  // Center-Right
486	check( inv6.hitTest(200 + (19*4), 100 + (11*4), true) );  // Upper-Right
487	check( inv6.hitTest(200 + (14*4), 100 + (11*4), true) );  // Upper-Center
488
489	// Nested squares, calling beginFill again after the move)
490	// Outer square counterclockwise order, inner in clockwise order
491	createEmptyMovieClip("inv7", 7);
492	with (inv7)
493	{
494		lineStyle(0, 0); // hairline
495		beginFill(0x00FF00);
496
497		moveTo(10, 10);
498		lineTo(10, 20);
499		lineTo(20, 20);
500		lineTo(20, 10);
501		lineTo(10, 10);
502
503		moveTo(12, 12);
504
505		// this forces endFill call, which triggers finalization of previous path (I think)
506		beginFill(0x00FF00);
507
508		lineTo(18, 12);
509		lineTo(18, 18);
510		lineTo(12, 18);
511		lineTo(12, 12);
512	}
513	inv7._xscale = inv7._yscale = 400;
514	inv7._y = 100; inv7._x = 250;
515	inv7.onRollOver = function() {};
516
517	// Point inside the inner square hits the shape !
518	check( inv7.hitTest(250 + (15*4), 100 + (15*4), true) );
519	// As points on the outer borders
520	check( inv7.hitTest(250 + (11*4), 100 + (11*4), true) );  // Upper-Left
521	check( inv7.hitTest(250 + (11*4), 100 + (14*4), true) );  // Center-Left
522	check( inv7.hitTest(250 + (11*4), 100 + (19*4), true) );  // Lower-Left
523	check( inv7.hitTest(250 + (14*4), 100 + (19*4), true) );  // Lower-Center
524	check( inv7.hitTest(250 + (19*4), 100 + (19*4), true) );  // Lower-Right
525	check( inv7.hitTest(250 + (19*4), 100 + (14*4), true) );  // Center-Right
526	check( inv7.hitTest(250 + (19*4), 100 + (11*4), true) );  // Upper-Right
527	check( inv7.hitTest(250 + (14*4), 100 + (11*4), true) );  // Upper-Center
528
529	//------------------------------------------------
530	//
531	//  Single path with complex crossing
532	//
533	//
534	//  10     5----4,0----------1
535	//         |#####|###########|
536	//         |#####|###########|
537	//  20     6-----+----7######|
538	//               |    |######|
539	//               |    |######|
540	//  30           9----8######|
541	//               |###########|
542	//  40           3-----------2
543	//
544	//         10   20    30     40
545	//
546	//------------------------------------------------
547	createEmptyMovieClip("inv8", 8);
548	with (inv8)
549	{
550		beginFill(0xFF0000);
551		moveTo(20, 10);  // 0
552		lineTo(40, 10);  // 1
553		lineTo(40, 40);  // 2
554		lineTo(20, 40);  // 3
555		lineTo(20, 10);  // 4
556
557		lineTo(10, 10);   // 5
558		lineTo(10, 20);   // 6
559		lineTo(30, 20);  // 7
560		lineTo(30, 30);  // 8
561		lineTo(20, 30);  // 9
562
563		// implicit close-up to 0 (aka 4, aka 20,10)
564	}
565
566	inv8._xscale = inv8._yscale = 200;
567	inv8._x = 200;
568	inv8.onRollOver = function() {};
569
570	check(  inv8.hitTest(200 + (15*2), 0 + (15*2), true) );  // Upper-Left
571	check(  inv8.hitTest(200 + (25*2), 0 + (15*2), true) );  // Upper-Center
572	check(  inv8.hitTest(200 + (35*2), 0 + (15*2), true) );  // Upper-Right
573
574	check( !inv8.hitTest(200 + (15*2), 0 + (25*2), true) );  // Center-Left
575	check( !inv8.hitTest(200 + (25*2), 0 + (25*2), true) );  // Center-Center
576	check(  inv8.hitTest(200 + (35*2), 0 + (25*2), true) );  // Center-Right
577
578	check( !inv8.hitTest(200 + (15*2), 0 + (35*2), true) );  // Lower-Left
579	check(  inv8.hitTest(200 + (25*2), 0 + (35*2), true) );  // Lower-Center
580	check(  inv8.hitTest(200 + (35*2), 0 + (35*2), true) );  // Lower-Right
581
582	check( !inv8.hitTest(200 + (20*2), 0 + (25*2), true) );  // On the 0-9 stroke, out of fill
583
584
585	_visible = false;
586}
587
588createEmptyMovieClip("line", 110);
589with(line) {
590
591    col = 0xff0000;
592    colc = 100;
593    x = 20;
594    y = 20;
595    xr = 100;
596    yr = 100;
597    n = 10;
598    alpha = 100;
599
600    // =======================
601    //   Shape 1
602    // =======================
603
604    beginFill(col,colc);
605    lineStyle(n,0x0000ff,alpha);
606
607    moveTo(x,y);
608    lineTo(x+xr,y);
609    lineTo((x+xr),(y+yr));
610
611    // In Gnash, next line forces a new path,
612    // and closeup of the former (shouldn't)
613    //
614    lineStyle(n,0x00ff00,alpha);
615
616    lineTo(x,(y+yr));
617    lineTo(x,y);
618
619    endFill();
620
621    // =======================
622    //   Shape 2
623    // =======================
624
625    x += 200;
626
627    beginFill(col,colc);
628    lineStyle(n,1,alpha);
629
630    moveTo(x,y);
631    lineTo(x+xr,y);
632
633    lineStyle(n,0x0000ff,alpha);
634
635    lineTo((x+xr),(y+yr));
636
637    lineStyle(n,0x00ff00,alpha);
638
639    lineTo(x,(y+yr));
640    lineTo(x,y);
641
642    endFill();
643
644    // =======================
645    //   Shape 3
646    // =======================
647
648    x += 200;
649
650    createEmptyMovieClip("d", 500);
651    with (d)
652    {
653        lineStyle(10, 10, 100);
654        moveTo(x, y);
655        lineTo(x, y + yr);
656        lineTo(x + xr, y + yr);
657        endFill(); // does NOT force closeup
658    }
659
660    // =======================
661    //   Shape 4
662    // =======================
663
664    x = 20;
665    y += 150;
666
667    createEmptyMovieClip("e", 501);
668    with (e)
669    {
670        lineStyle(10, 10, 100);
671        beginFill(); // does NOT start a fill
672        moveTo(x, y);
673        lineTo(x, y + yr);
674        lineTo(x + xr, y + yr);
675        endFill(); // does NOT force closeup
676    }
677
678    // The shape is not closed to form a triangle,
679    // so the only way to hit it is to hit the line.
680    check(!e.hitTest(x + 30, y + 30, true));
681
682    // Top right 'corner'
683    check(e.hitTest(x, y, true));
684
685    // =======================
686    //   Shape 5
687    // =======================
688
689    x += 200;
690
691    createEmptyMovieClip("f", 502);
692    with (f)
693    {
694        lineStyle(10, 10, 100);
695        beginFill(0); // does start a fill
696        moveTo(x, y);
697        lineTo(x, y + yr);
698        lineTo(x + xr, y + yr);
699        endFill(); // DOES force closeup
700    }
701
702    // Somewhere within the closed triangle.
703    check(f.hitTest(x + 30, y + 30, true));
704
705    // =======================
706    //   Shape 6
707    // =======================
708
709    x += 200;
710
711    createEmptyMovieClip("g", 503);
712    with (g)
713    {
714        lineStyle(10, 0xFFFF00, 100);
715        beginFill(0x00ff00); // does start a fill
716        moveTo(x, y);
717        lineTo(x, y + yr);
718        lineTo(x + xr, y + yr);
719        beginFill(0x0000ff); // closes previous fill, opens a new one
720        lineTo(x + xr, y);
721        lineTo(x + xr, y + yr);
722        endFill(); // DOES force closeup
723    }
724
725    // Bottom left
726    check(g.hitTest(x + 20, y + 80, true));
727
728    // Top right
729    // COMPATIBLITY NOTE:
730    // 9,0,115,0 for linux sometimes finds the point to hit
731    // the shape and sometimes it doesn't.
732    // 10,0,12,10 never succeeds the hit test.
733    //
734    // The point is clearly within a fill so we'll take an hit test
735    // success as expected.
736    //
737    check(g.hitTest(x + 80, y + 20, true));
738
739    _visible = false;
740}
741line.onRollOver = function() {};
742
743// Check the the top right diagonal half of Shape 2.
744xcheck(line.hitTest(270, 40, true));
745
746// Check the bottom left diagonal half of Shape 2.
747check(line.hitTest(230, 80, true));
748
749
750// Page 4 ( page[3] )
751
752draw100x100Box = function(x, y, mc) {
753    s = 90;
754    with (mc) {
755        moveTo(x, y);
756        lineTo(x + s, y);
757        lineTo(x + s, y + s);
758        lineTo(x, y + s);
759        lineTo(x, y);
760        endFill();
761    };
762};
763
764
765createEmptyMovieClip("grad", 150);
766
767// Test gradients.
768// The beginGradientFill function works with fake Matrices, but there is no
769// point making more work for ourselves as that testing is already done for
770// the Matrix class.
771// Only the "box" matrixType gets special handling.
772
773with(grad) {
774
775    // Linear gradients
776    fillType = "linear";
777
778    x = 0;
779    y = 0;
780
781    // shape 1
782    colors = [0x0000ff, 0xffffff];
783    alphas = [100, 100];
784    ratios = [0, 0xff];
785    matrix = new flash.geom.Matrix();
786    beginGradientFill(fillType, colors, alphas, ratios, matrix);
787    draw100x100Box(x, y, grad);
788
789    // shape 2
790    x += 100;
791    colors = [0x0000ff, 0xffffff];
792    alphas = [100, 100];
793    ratios = [0, 0xff];
794    matrix.createGradientBox(90, 90, 0, x, y);
795    beginGradientFill(fillType, colors, alphas, ratios, matrix);
796    draw100x100Box(x, y, grad);
797
798    // shape 3
799    x += 100;
800    colors = [0x0000ff, 0xffffff, 0xff00ff];
801    alphas = [100, 100, 100];
802    ratios = [0, 0xff / 2, 0xff];
803    matrix.createGradientBox(90, 90, Math.PI / 4, x, y);
804    beginGradientFill(fillType, colors, alphas, ratios, matrix);
805    draw100x100Box(x, y, grad);
806
807    // shape 4
808    x += 100;
809    colors = [0x0000ff, 0xffffff, 0xff00ff];
810    alphas = [100, 100, 100];
811    ratios = [0, 0xff / 2, 0xff];
812    matrix.createGradientBox(180, 180, Math.PI / 4, x, y);
813    beginGradientFill(fillType, colors, alphas, ratios, matrix);
814    draw100x100Box(x, y, grad);
815
816    // shape 5
817    x += 100;
818    colors = [0x0000ff, 0xffffff, 0x00ff00];
819    alphas = [100, 100, 100];
820    ratios = [0, 0xff / 2, 0xff];
821    matrix.createGradientBox(180, 180, Math.PI / 4 * 3, x - 90, y - 90);
822    beginGradientFill(fillType, colors, alphas, ratios, matrix);
823    draw100x100Box(x, y, grad);
824
825    // shape 6
826    x += 100;
827    colors = [0x0000ff, 0xffffff, 0x00ff00, 0xff00ff, 0x00ffff, 0xffff00 ];
828    alphas = [100, 100, 100, 50, 25, 100];
829    ratios = [0, 0xff / 5, 0xff / 5 * 2, 0xff / 5 * 3, 0xff / 5 * 4, 0xff];
830    matrix.createGradientBox(90, 90, Math.PI / 2, x, y);
831    beginGradientFill(fillType, colors, alphas, ratios, matrix);
832    draw100x100Box(x, y, grad);
833
834    // Radial gradients
835    fillType = "radial";
836
837    x = 0;
838    y += 100;
839
840    // shape 7
841    colors = [0x0000ff, 0xffffff];
842    alphas = [100, 100];
843    ratios = [0, 0xff];
844    matrix = new flash.geom.Matrix();
845    beginGradientFill(fillType, colors, alphas, ratios, matrix);
846    draw100x100Box(x, y, grad);
847
848    // shape 8
849    x += 100;
850    colors = [0x0000ff, 0xffffff];
851    alphas = [100, 100];
852    ratios = [0, 0xff];
853    matrix.createGradientBox(90, 90, 0, x, y);
854    beginGradientFill(fillType, colors, alphas, ratios, matrix);
855    draw100x100Box(x, y, grad);
856
857    // shape 9
858    x += 100;
859    colors = [0x0000ff, 0xffffff, 0xff00ff];
860    alphas = [100, 100, 100];
861    ratios = [0, 0xff / 2, 0xff];
862    matrix.createGradientBox(90, 90, Math.PI / 4, x, y);
863    beginGradientFill(fillType, colors, alphas, ratios, matrix);
864    draw100x100Box(x, y, grad);
865
866    // shape 10
867    x += 100;
868    colors = [0x0000ff, 0xffffff, 0xff00ff];
869    alphas = [100, 100, 100];
870    ratios = [0, 0xff / 2, 0xff];
871    matrix.createGradientBox(180, 180, Math.PI / 4, x, y);
872    beginGradientFill(fillType, colors, alphas, ratios, matrix);
873    draw100x100Box(x, y, grad);
874
875    // shape 11
876    x += 100;
877    colors = [0x0000ff, 0xffffff, 0x00ff00];
878    alphas = [100, 100, 100];
879    ratios = [0, 0xff / 2, 0xff];
880    matrix.createGradientBox(180, 180, Math.PI / 4 * 3, x - 90, y - 90);
881    beginGradientFill(fillType, colors, alphas, ratios, matrix);
882    draw100x100Box(x, y, grad);
883
884    // shape 12
885    x += 100;
886    colors = [0x0000ff, 0xffffff, 0x00ff00, 0xff00ff, 0x00ffff, 0xffff00 ];
887    alphas = [100, 100, 100, 50, 25, 100];
888    ratios = [0, 0xff / 5, 0xff / 5 * 2, 0xff / 5 * 3, 0xff / 5 * 4, 0xff];
889    matrix.createGradientBox(90, 90, Math.PI / 2, x, y);
890    beginGradientFill(fillType, colors, alphas, ratios, matrix);
891    draw100x100Box(x, y, grad);
892
893    y += 100;
894    x = 0;
895
896    // Shape 13
897
898    // Check that ratios are adjusted if they do not get successively larger.
899    fillType = "linear";
900    colors = [0x0000ff, 0xffffff, 0x00ff00];
901    alphas = [100, 100, 100];
902    ratios = [0, 0x10, 0x05];
903    matrix.createGradientBox(90, 90, 0, x, y);
904    beginGradientFill(fillType, colors, alphas, ratios, matrix);
905    draw100x100Box(x, y, grad);
906
907
908    // Shape 14
909    x += 100;
910
911    // Test a linear gradient with one stop
912    fillType = "linear";
913    colors = [0xff0000];
914    alphas = [100];
915    ratios = [0];
916    matrix.createGradientBox(90, 90, 0, x, y);
917    beginGradientFill(fillType, colors, alphas, ratios, matrix);
918    draw100x100Box(x, y, grad);
919
920
921    // Shape 15
922    x += 100;
923
924    // Test a linear gradient with one stop
925    fillType = "radial";
926    colors = [0x00ff00];
927    alphas = [100];
928    ratios = [0];
929    matrix.createGradientBox(90, 90, 0, x, y);
930    beginGradientFill(fillType, colors, alphas, ratios, matrix);
931    draw100x100Box(x, y, grad);
932
933    // Shape 16
934    x += 100;
935
936    // Bad fill style results in no fill.
937    fillType = "rodial";
938    colors = [0x0000ff, 0xffffff, 0x00ff00];
939    alphas = [100, 100, 100];
940    ratios = [0, 0x10, 0x05];
941    matrix.createGradientBox(90, 90, 0, x, y);
942    beginGradientFill(fillType, colors, alphas, ratios, matrix);
943    draw100x100Box(x, y, grad);
944
945    // Shape 17
946    x += 100;
947
948    // Extra arguments result in no fill for SWF6
949    fillType = "radial";
950    colors = [0x0000ff, 0xffffff, 0x00ff00];
951    alphas = [100, 100, 100];
952    ratios = [0, 0x10, 0x05];
953    matrix.createGradientBox(90, 90, 0, x, y);
954    beginGradientFill(fillType, colors, alphas, ratios, matrix, "pad");
955    draw100x100Box(x, y, grad);
956
957    x = 0;
958    y += 100;
959
960    // Shape 18
961
962    // 4 arguments result in no fill for SWF6
963    fillType = "radial";
964    colors = [0x0000ff, 0xffffff, 0x00ff00];
965    alphas = [100, 100, 100];
966    ratios = [0, 0x10, 0x05];
967    matrix.createGradientBox(90, 90, 0, x, y);
968    beginGradientFill(fillType, colors, alphas, ratios);
969    draw100x100Box(x, y, grad);
970
971    _visible = false;
972
973};
974grad.onRollOver = function() {};
975
976//---------------------------------------------------------------------------
977//
978//---------------------------------------------------------------------------
979
980createEmptyMovieClip("hitdetector", 3);
981hitdetector.createEmptyMovieClip("shapeshape", 1);
982with(hitdetector.shapeshape)
983{
984	lineStyle(2, 0x000000);
985	beginFill(0xFFFF00, 100);
986	drawCircle(hitdetector.shapeshape, 0, 0, 20);
987	endFill();
988}
989
990hitdetector.createEmptyMovieClip("bboxpoint", 2);
991with(hitdetector.bboxpoint)
992{
993	lineStyle(2, 0x000000);
994	beginFill(0xFFFF00, 100);
995	drawCircle(hitdetector.bboxpoint, 0, 0, 20);
996	endFill();
997	_x = 60;
998}
999
1000hitdetector.createEmptyMovieClip("shapepoint", 3);
1001with(hitdetector.shapepoint)
1002{
1003	lineStyle(2, 0x000000);
1004	beginFill(0xFFFF00, 100);
1005	drawCircle(hitdetector.shapepoint, 0, 0, 20);
1006	endFill();
1007	_x = 120;
1008}
1009
1010hitdetector._y = 350;
1011
1012
1013createEmptyMovieClip("cursor", 12);
1014with(cursor)
1015{
1016	lineStyle(2, 0x000000);
1017	beginFill(0xFF0000, 100);
1018	drawCircle(_root.cursor, 0, 0, 10);
1019	endFill();
1020	onEnterFrame = function()
1021	{
1022		hd = _root.hitdetector;
1023
1024// don't move the controls for now...
1025#if 0
1026		with(hd)
1027		{
1028			if ( typeof(xshift) == 'undefined' )
1029			{
1030				xshift = 1;
1031			}
1032			else if ( xshift > 0 && _x >= 300 )
1033			{
1034				xshift = -1;
1035			}
1036			else if ( xshift < 0 && _x == 0 )
1037			{
1038				xshift = 1;
1039			}
1040
1041			_x += xshift;
1042		}
1043#endif
1044
1045
1046		_x = _root._xmouse;
1047		_y = _root._ymouse;
1048
1049		var ch = _root.page[_root.visibleIndex];
1050
1051		// Bounding box check
1052		if ( hitTest(ch) ) {
1053			hd.shapeshape._xscale=150;
1054			hd.shapeshape._yscale=150;
1055		} else {
1056			hd.shapeshape._xscale=100;
1057			hd.shapeshape._yscale=100;
1058		}
1059
1060		// Bounding box check with circle center
1061		if ( ch.hitTest(_x, _y) ) {
1062			hd.bboxpoint._xscale=150;
1063			hd.bboxpoint._yscale=150;
1064		} else {
1065			hd.bboxpoint._xscale=100;
1066			hd.bboxpoint._yscale=100;
1067		}
1068
1069		// Shape check with circle center
1070		if ( ch.hitTest(_x, _y, true) ) {
1071			hd.shapepoint._xscale=150;
1072			hd.shapepoint._yscale=150;
1073		} else {
1074			hd.shapepoint._xscale=100;
1075			hd.shapepoint._yscale=100;
1076		}
1077	};
1078}
1079
1080
1081isMask = false;
1082onMouseDown = function()
1083{
1084	var ch = _root.page[_root.visibleIndex];
1085
1086	if ( isMask )
1087	{
1088		ch.setMask(); // no effect !
1089		ch.setMask(true); // no effect !
1090		trace("Disabling cursor mask");
1091		ch.setMask(undefined); // works
1092		//a.setMask(null); // also work
1093	}
1094	else
1095	{
1096		trace("Enabling cursor mask");
1097		ch.setMask(cursor);
1098	}
1099	isMask = !isMask;
1100};
1101
1102
1103
1104visibleIndex = 0;
1105page = new Array;
1106page[0] = a;
1107page[1] = inv;
1108page[2] = line;
1109page[3] = grad;
1110
1111onKeyDown = function()
1112{
1113	var ascii = Key.getAscii();
1114	if ( ascii >= 48 && ascii <= 57 ) // 0..9 - activate corresponding drawing
1115	{
1116		with (page[visibleIndex])
1117		{
1118			_visible = false;
1119			setMask(null);
1120		}
1121
1122		visibleIndex = parseInt(ascii)-49;
1123		trace("Key "+visibleIndex+" hit");
1124
1125		with (page[visibleIndex])
1126		{
1127			_visible = true;
1128		}
1129	}
1130	else if ( ascii == 104 ) // 'h' - toggle visibility
1131	{
1132		page[visibleIndex]._visible = ! page[visibleIndex]._visible;
1133	}
1134	else if ( ascii == 45 ) // '-' - decrease alpha
1135	{
1136		var newAlpha = page[visibleIndex]._alpha - 25;
1137		if ( newAlpha < 0 ) newAlpha = 0;
1138		page[visibleIndex]._alpha = newAlpha;
1139	}
1140	else if ( ascii == 43 ) // '+' - increase alpha
1141	{
1142		var newAlpha = page[visibleIndex]._alpha + 25;
1143		if ( newAlpha > 100 ) newAlpha = 100;
1144		page[visibleIndex]._alpha = newAlpha;
1145	}
1146	else if ( ascii == 100 ) // 'd' - start/stop dragging something :)
1147	{
1148		if ( ! hitdetector.dragging ) {
1149			hitdetector.dragging = true;
1150			hitdetector.startDrag();
1151			// hitdetector.startDrag(true); // lock centered
1152			//hitdetector.startDrag(true, 100, 100, 200, 200); // lock centered, box-constrained
1153		} else {
1154			hitdetector.dragging = flase;
1155			hitdetector.stopDrag();
1156		}
1157	}
1158
1159};
1160Key.addListener(this);
1161
1162stop();
1163
1164
1165