Adobe
Products
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
Student and Teacher Editions
More products
Solutions
Creative tools for business
Digital marketing
Digital media
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Buy
Home use for personal and home office
Education for students, educators, and staff
Business for small and medium businesses
Licensing programs for businesses, schools, and government
Special offers
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
My products and services
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out My orders My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Review and Checkout
Adobe Developer Connection / Flash Developer Center /

Creating self-voicing puzzles in Flash

by Thea Eaton

Thea Eaton
  • DoodleDoo

Content

  • Examining the Life Cycle of a Frog puzzle
  • Making the puzzle click-and-drop accessible
  • Setting the tab order
  • Adding sound
  • Using the access button

Modified

24 July 2006

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
accessibility animation Flash Professional

Requirements

Prerequisite knowledge

Basic knowledge of Flash and ActionScript 2.0.

User Level

Intermediate

Required products

  • Flash Professional 8 (Download trial)

Sample files

  • frog_life_cycle.zip (5007 KB)

You're probably asking yourself: What is a self-voicing Flash application? An application is self-voicing when it relies on system-level voices, rather than an external tool—like a screen reader—to read the content aloud.

A screen reader is a type of assistive technology that makes content accessible to users with visual impairments. Screen readers read the content of an HTML page with help from software running inside the web browser (Microsoft Internet Explorer 5.5 and later) called Microsoft Active Accessibility (MSAA). MSAA pulls the content out of the SWF file and puts it in what is called a data tree. From there, the screen reader sounds out the content in a linear fashion.

Because screen readers need the browser to be able to read the content, they cannot read stand-alone applications, such as executables in kiosk presentations. Screen-reader software also comes with a learning curve, so children usually do not start using them until fourth grade or later. Therefore, if you want to make an application truly accessible for young children, or for stand-alone applications, self-voicing is a great solution.

Macromedia Director MX has a built-in text-to-speech solution (TTS) called Speech Xtra. It allows you to author accessible, stand-alone media because the voice inside Director reads the content much as a screen reader would, and the content does not have to be in a web browser. Flash, however, does not have a built-in TTS tool yet.

In this article, you will learn how to make a Flash puzzle accessible by using self-voicing techniques.

Examining the Life Cycle of a Frog puzzle

This article concerns a puzzle called Life Cycle of a Frog (see Figure 1), which you are going to build. You solve this puzzle by using click and drop with the mouse: You click a piece to pick it up, move it to the proper hit area, and then click again to place it.

Life Cycle of a Frog puzzle with five pieces corresponding to the five stages of the life cycle of a frog.
Figure 1. Life Cycle of a Frog puzzle with five pieces corresponding to the five stages of the life cycle of a frog.

Mobility-impaired users can also solve the puzzle by tabbing to the puzzle pieces, pressing Enter to pick one up, tabbing to a hit area, and then pressing Enter again to place it. Similarly, visually impaired users can tab to the puzzle pieces, press Enter to pick one up, tab to a hit area, and press Enter to place it.

The blue access button in the lower right corner comes up on tabbing only. It provides a description of the images on the screen, instructions on how to play the game, and a keypress overlay of available keyboard shortcuts. The self-voicing features and audio come up only when tabbing, not using the mouse.

Setting up the puzzle pieces

You can start by downloading the sample files linked to at the beginning of this article, or have your own vector image ready that you want to make into a puzzle.

Launch Flash Professional 8 and open the FrogLifeCycle_starter.fla file you downloaded. You will find the complete Life Cycle of the Frog image as well as a grid that will aid in cutting out the puzzle pieces.

Press Control+ B (or choose Modify > Break Apart from the main menu) to break down the vector image into its pieces.

Tip: You don't have to break down the entire illustration in order to be able to cut out the pieces. Sometimes with vector images that were created in Adobe Illustrator this does not always work the way you expect. For the Lifecycle of the Frog image, I left the frogs in separate movie clips and broke down only the areas that will be cut by the lines.

With lines set to a different color that offsets well and set to hairline width, draw the outlines of the pieces on a layer above the flat image, or use the red grid provided in the starter file. Once they are in the right position, copy and paste the lines onto the flat image. The lines will cut the image into pieces, which you can then extract (see Figure 2).

Cutting out the pieces of the puzzle after dividing them by the lines
Figure 2. Cutting out the pieces of the puzzle after dividing them by the lines

Make sure you select all small elements close to the lines as well by zooming into the movie (press Control+ +/= or choose View > Zoom In from the main menu). Select the flat pieces and press F8 (or choose Modify > Convert to Symbol in the menu) to turn them into movie clips called, respectively, pp1, pp2, and so on.

Go into each puzzle piece movie clip and move the piece so that the registration point falls somewhat in the middle (see Figure 3).

Tip: The transformation point (white circle in a symbol) is not the same in Flash as the registration point. After having moved the registration point to the middle of the puzzle piece, you can reset the transformation point by double-clicking it.

Moving the puzzle piece's registration point to the middle
Figure 3. Moving the puzzle piece's registration point to the middle

Setting up the hit areas

The hit areas are the places where the puzzle pieces are supposed to go. Make a copy of all the puzzle piece movie clips and assemble them correctly on the Stage. Select all of the pieces and change their alpha values to 0% in the Property inspector. Give each one an instance name that matches the actual puzzle pieces: hitarea1 for pp1, hitarea2 for pp2, and so on (see Figure 4).

Giving the hit areas instance names and setting the alpha values to 0%
Figure 4. Giving the hit areas instance names and setting the alpha values to 0%

Now that you have set up the hit areas, you also need an indication of where the user can place the pieces. In the background, draw the outlines of the pieces so that the user can see where the pieces can be placed. For this puzzle, make a gray outline of each piece and number them from 1 to 5, corresponding to the stages in the life cycle of a frog. Place the outlines behind the invisible hitareas on the Stage. Figure 5 shows the final assembly.

Setting up the hit areas
Figure 5. Setting up the hit areas

Making the puzzle click-and-drop accessible

Now you are ready to add some code. You want to program the pieces in such a way that they can be placed not only by using the mouse but also by the keyboard. You want users to be able to click a piece to make it "stick" to the mouse until they click again to release it. You also want to be able to tab to a piece, press Enter to pick it up, then tab to the proper hit area, and press Enter again to release the piece in place.

Start by writing all this down in pseudocode. Describe how you are going to tackle this combination between tabbing to a puzzle piece and using the mouse:

On pressing a puzzle piece: If the piece was not picked up yet: pick up piece Else stop dragging the piece and place the piece If the piece is over the right hit area, then place piece Else make piece spring back to its original location On pressing a hit area: If the user is tabbing only If there was no piece selected, play warning "select a piece first" If selected piece corresponds to that hit area, then place piece Else make piece spring back to its original location On moving the mouse: Alert the game that the user is no longer tabbing When a piece is selected, turn on dragging On pressing the Tab key Alert the game that the user is tabbing

Clicking a puzzle piece with the mouse is equal either to picking it up or trying to place it because the piece is under the mouse when it is dragged. Of course, when someone is not using the mouse, the piece stays in its place and the user has to press Enter in the hit area to place the piece.

You also have to keep in mind that someone might switch from tabbing to using the mouse. Therefore, keep checking for an onMouseMove event.

To detect whether or not the user is tabbing, add this code on the main Timeline to detect a Tab keypress:

// global variables var tabbingON = false; // track to see if user is tabbing function down( ) { if (x = Key.isDown(Key.TAB)) { tabbingON = true; } delete this.onKeyDown; this.onKeyUp = up; } function up( ) { this.onKeyUp = undefined; this.onKeyDown = down; } var keyListener:Object = new Object( ); keyListener.onKeyDown = down; Key.addListener(keyListener);

Tip: Check the above keyListener code by adding a trace statement. Also you can tab through your Flash content in preview mode after first selecting Control > Disable Keyboard Shortcuts to turn off keyboard shortcuts.

Fill in the pseudocode on the puzzle pieces and enter functions where you might be reusing code somewhere else:

// puzzle pieces pp1.onPress = pp2.onPress = pp3.onPress = pp4.onPress = pp5.onPress = function() { stopDrag(); if (tabbingON || !draggingON) { pickupPiece(this._name); } // if puzzle piece is in right spot, then place else if (eval(_root[this._name]._droptarget) == _root["hitarea" + selectedPiece]) { placePiece(this._name); // if puzzle piece is not in right spot, then return it } else { returnPiece(this._name); } }

Also fill in the pseudocode for the hit areas:

// hitareas hitarea1.onPress = hitarea2.onPress = hitarea3.onPress = hitarea4.onPress = hitarea5.onPress = function() { n1 = Number(subString(this._name,8,9)); if (tabbingON) { // when no piece is picked up if (selectedPiece == 0) { playSound("nopiece"); // when it is in the right place, place it } else if (_root.selectedPiece == n1) { placePiece("pp" + selectedPiece); // when it is in the wrong place, play message } else { returnPiece("pp" + selectedPiece); } } }

Next, add an onMouseMove event that checks when the user starts to move the mouse. You want to start the dragging not on clicking a puzzle piece, but when the mouse starts moving:

// check to see if the mouse is moved onMouseMove = function () { tabbingON = false; if (selectedPiece > 0) { _root["pp" + selectedPiece].startDrag(true); } }

When players pick up a piece, you want several things to happen. You want to elevate the piece so that, while being dragged, it will not move behind any of the other puzzle pieces. You can do this by swapping its depth and putting the selected puzzle piece always onto level 10:

_root[ppName].swapDepths(10);

You want to alert the game that players are now dragging a piece, even though the piece is left in place when tabbing. Do this by creating a global variable called draggingON:

draggingON = true;

Keep track of the current selected piece by creating another global variable and getting the piece number from the puzzle piece's instance name:

selectedPiece = Number(subString(ppName,3,4));

Play a sound to alert the visually impaired user that the puzzle piece was indeed picked up. Later on, you will write the playSound function because you will use it a lot.

The final function looks like this:

function pickupPiece(ppName) { _root[ppName].swapDepths(10); draggingON = true; selectedPiece = Number(subString(ppName,3,4)); if (tabbingON) { playSound("yourturn03"); } }

When placing a piece, you want players to match the pieces with the x and y coordinates of the hit areas:

_root[ppName]._x = _root["hitarea" + selectedPiece]._x; _root[ppName]._y = _root["hitarea" + selectedPiece]._y;

Set the dragging variable to false and change the selectedPiece variable to 0, because no piece is now selected. Also keep a running tally of how many pieces have been placed just in case you want to add feedback to the user—such as "Great Job!"—at the end of the puzzle. Increase the global variable total by 1:

draggingON = false; total += 1; selectedPiece = 0;

The final function would look like this:

function placePiece(ppName) { if (tabbingON) { playSound("right"); } _root[ppName]._x = _root["hitarea" + selectedPiece]._x; _root[ppName]._y = _root["hitarea" + selectedPiece]._y; draggingON = false; total += 1; selectedPiece = 0; }

When a player places a piece incorrectly, you want the piece to spring back to its original spot. In order to do this, capture the original x and y coordinates of each puzzle piece into an array before game start. If you do this dynamically, you can always move the pieces around later as well, or have them be shuffled by some ActionScript:

// global variables var origPos:Array = new Array(); function initGame() { // initialize array with original x and y positions of the puzzle pieces for (i = 1; i <= totalPieces; i++) { origPos[i] = new Array(2); origPos[i][0] = _root["pp" + (i)]._x; origPos[i][1] = _root["pp" + (i)]._y; } }

Use this array when you write the function for returning a piece.

To play a sound indicating the piece cannot be placed, set draggingON back to false, and selectedPiece back to 0:

function returnPiece(ppName) { if (tabbingON) { playSound("wrong"); } _root[ppName]._x = origPos[selectedPiece][0]; _root[ppName]._y = origPos[selectedPiece][1]; draggingON = false; selectedPiece = 0; }

Setting the tab order

The tab order in Flash does not follow a predictable order from left to right or top to bottom. Instead, Flash calculates the order around the top-left corner of the Flash content. For good game flow, you want the user to tab through all the puzzle pieces first before tabbing through the drop spots in order, from 1 to 5. In Flash, assign all the selectable elements a tab order:

// accessibility btn_access.tabIndex = 1; pp2.tabIndex = 2; pp3.tabIndex = 3; pp5.tabIndex = 4; pp4.tabIndex = 5; pp1.tabIndex = 6; hitarea1.tabIndex = 7; hitarea2.tabIndex = 8; hitarea3.tabIndex = 9; hitarea4.tabIndex = 10; hitarea5.tabIndex = 11;

The tab order on the puzzle pieces is scrambled, just like the pieces are mixed up on the Stage. If you put this code into the initGame() function, it will be executed before the user starts the game. You want the user who tabs through the game to tab to the accessibility button first to get instructions on how to play the game. (More on the accessibility button and its functions later.)

With all this code, you should now have a puzzle where you can pick up and place pieces not only by using the mouse, but also by using the keyboard and tabbing (no audio yet).

One more thing. After a player places a piece, you want that puzzle piece and its hit area to stay out of the tab order. This helps distinguish between the pieces that still need to be placed and the ones that have already been placed. You could, of course, just place the following code in the placePiece() function:

_root[ppName].tabIndex = -1; _root[ppName].enabled = false; _root["hitarea" + selectedPiece].tabIndex = -1; _root["hitarea" + selectedPiece].enabled = false;

But when you try this out, you will notice that, after placing a piece, the focus jumps to another piece in the tab order. The focus jumps because after you set the tab order to a negative value—which leaves it out of the tab order—it cannot hold its focus. When you install the audio onRollOver in the next section, this will become confusing because the audio will start playing without the user having tabbed to this item.

In order to get around this problem, you still want to execute this code—but not until the user tabs away from the hit area. To do this, set a new global variable, called justHit, that you set to true when you have just placed a piece. Also create a new function, called takeOut(), that disables and takes the puzzle piece and the hit area out of the tab order by assigning it a negative value. Then you want to add the following code to all the hit areas and puzzle pieces onRollOut:

hitarea1.onRollOut = hitarea2.onRollOut = hitarea3.onRollOut = hitarea4.onRollOut = hitarea5.onRollOut = function() { n1 = Number(subString(this._name,8,9)); takeOut(n1); } pp1.onRollOut = pp2.onRollOut = pp3.onRollOut = pp4.onRollOut = pp5.onRollOut = function() { n1 = Number(subString(this._name,3,4)); takeOut(n1); } function takeOut(n1) { if (justHit) { trace("pp" + n1+ "justHit"); _root["pp" + n1].tabIndex = -1; _root["pp" + n1].enabled = false; _root["hitarea" + n1].tabIndex = -1; _root["hitarea" + n1].enabled = false; justHit = false; } }

Place this line of code in the placePiece function for each hit area:

// when it is in the right place, place it } else if (_root.selectedPiece == n1) { placePiece("pp" + selectedPiece); justHit = true;

Now when the player places a piece, the focus will not jump away until the user tabs away. After tabbing away, the placed puzzle piece and its hit area will be left out of the tab order and will be disabled for the mouse.

Adding sound

In order to make this puzzle game self-voicing, you want to add the following audio:

  • Rollovers on all selectable elements
  • Text equivalents (or alt text) for all images and movie clips
  • Instructions on how to play the game by pressing Tab

Because games usually contain various similar-looking screens or just one game screen, this example has bundled the description of the images on the screen, with the instructions on how to play the game, and has added this audio to a button called the access button (see the next section). Table 1 shows the rollover audio for each puzzle piece and hit area.

Table 1. Game object and corresponding rollover audio
Object Rollover audio
Puzzle piece 1 "Eggs, puzzle piece"
Puzzle piece 2 "Tadpole, puzzle piece"
Puzzle piece 3 "Tadpole with legs, puzzle piece"
Puzzle piece 4 "Froglet, puzzle piece"
Puzzle piece 5 "Frog, puzzle piece"
Hit area 1 "Spot 1"
Hit area 2 "Spot 2"
Hit area 3 "Spot 3"
Hit area 4 "Spot 4"
Hit area 5 "Spot 5"

The audio elements are first written down in an audio script, which can then be sent to a professional voiceover talent. Most voiceover professionals have their own studio equipment and can deliver their recordings in compressed MP3 format. You can then attach these rollover audio files to the puzzle pieces and the hit areas as follows:

pp1.onRollOver = pp2.onRollOver = pp3.onRollOver = pp4.onRollOver = pp5.onRollOver = function() { if (tabbingON) { n1 = Number(subString(this._name,3,4)); playSound("pp" + n1); } }

Tip: Instead of having your audio recorded by a professional voiceover artist, you can also record your own self-voicing audio.

Using the access button

The access button provides one go-to point for both visually and mobility impaired users to receive visual descriptions and instructions on how to play the game (see Figure 6). For this button I chose the Universal Access symbol by Apple Computer.

Universal Access symbol
Figure 6. Universal Access symbol

By including visual descriptions in this manner, you take the alt text out of the game flow of the game. Users can go to the access button once to get the overall game description and instructions on how to play by tabbing. Then they can easily tab through the selectable elements needed to play the game without having to hear the same alt text over and over again.

Both visually and mobility-impaired users can use the Tab key to navigate through a Flash application. Therefore, you want to include instructions on how to play the game using the keyboard, both in audio and in a visual format. For mobility-impaired users, you can include a keypress overlay that appears when users press the access button (see Figure 7).

Keypress overlay
Figure 7. Keypress overlay

A keypress overlay can also be helpful in displaying any keyboard shortcuts you might have programmed into your game. In the Library of FrogLifeCycle.fla, you will find this keypress overlay as the movie clip mc_keypress. Move it into the starter file and then export the movie clip by right-clicking it in the Library and selecting the Export for ActionScript option in the Linkage Properties dialog box (see Figure 8).

Linkage Properties dialog box
Figure 8. Linkage Properties dialog box

You want the overlay to appear when users press the access button. You also want the audio to come up, which will give users a visual description of the game as well as instructions on how to play it. When all the pieces have been placed, the visual description can change to one that describes the finished puzzle:

btn_access.onRelease = function() { if (total <5) { playSound("expl"); _root.attachMovie("mc_keypress", "mc_keypress",11); mc_keypress._x += offset; mc_keypress._y += offset; } else { playSound("expl2"); } }

When you press the access button now, the overlay appears in thetop-left corner. Adjust it so that it appears more in the middle of thescreen:

var offset = 50; btn_access.onRelease = function() { playSound("expl"); _root.attachMovie("mc_keypress", "mc_keypress",11); mc_keypress._x += offset; mc_keypress._y += offset; }

When you roll away from a button, you want the audio to stop. On rollover, you want the rollover audio to play:

btn_access.onRollOver = function() { playSound("access"); } btn_access.onRollOut = function() { stopAllSounds(); mc_keypress.removeMovieClip(); }

Finally, add a checkFinal() method to the placePiece() method to check whether or not all pieces have been placed. If they have all been placed, you can play an end message:

function checkFinal() { if (total >= 5) { if (tabbingON) { playSound("final"); } } }

Now the Life Cycle of the Frog game is a complete, self-voicing activity, accessible to everyone.

Where to go from here

There are several ways you could extend this game. You could build an on/off button for mobility-impaired users who may not want to listen to the sound and cannot turn off their computer's sound externally. You would have to make sure that there is always a rollover on the sound on/off button, so that visually impaired users avoid an audio trap. An audio trap can form when users turn off the audio button—and therefore also the self-voicing audio. Because they can't hear the button rollovers, they would be unable to turn the audio back on.

After we at Snert Studios tested this game for usability, one visually impaired student came up with the idea of switching the focus to the drop spots after selecting a puzzle piece. This was to prevent players from having to cycle through the other puzzle pieces after picking one up. You can implement this change with the Selection.setFocus() method, which resets the focus rectangle in Flash.

Visually, you can add a "selected" state to the puzzle pieces so that users with low vision who are selecting through tabbing can see which puzzle piece they have selected.

Accessible click and drop can be turned into accessible drag and drop by changing the onPress/onPress events on the movie clips to an onPress/onRelease event. We chose click and drop for this game because younger users have usability issues with drag and drop—which requires holding the mouse button down while moving the mouse at the same time.

For puzzles like this one, it might be beneficial to give players feedback as to which puzzle pieces have been placed and where. You can accomplish this by using a different rollover on the pieces that have been placed, instead of leaving them out of the tab order.

Finally, you can program keyboard shortcuts to facilitate access to buttons that are often used. In this puzzle game, you could add a keyboard shortcut to the access button, for example, so that users could press A (for "access") to hear the instructions again without having to tab to the button itself. You could add an A to the keypress overlay, near the button, to indicate the shortcut visually. The shortcut can also be added to the auditory instructions that the access button plays.

Visit snertstudios.com to read more about accessible Flash.

More Like This

  • Five demos of Flash CS4 Professional
  • Motion migration guide for Flash Professional
  • Exploring the new 3D features in Flash CS4 Professional
  • Combining animation and ActionScript using Flash Professional CS5 and Flash Builder 4
  • Flash CS4 Missing Manual excerpts: Video, testing and debugging, optimization, and sound
  • Designing and animating characters in Flash – Part 2: 2.5D animation
  • Easy animation with the Motion Editor in Flash
  • Advanced character animation in Flash
  • Augmented reality with animated avatars using the 3D drawing API
  • Creating a simple animation in Flash

Flash User Forum

More
04/23/2012 Auto-Save and Auto-Recovery
04/23/2012 Open hyperlinks in new window/tab/pop-up ?
04/21/2012 PNG transparencies glitched
04/01/2010 Workaround for JSFL shape selection bug?

Flash Cookbooks

More
02/13/2012 Randomize an array
02/11/2012 How to create a Facebook fan page with Flash
02/08/2012 Digital Clock
01/18/2012 Recording webcam video & audio in a flv file on local drive

Products

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • Mobile Apps
  • Photoshop
  • Touch Apps
  • Student and Teacher Editions

Solutions

  • Digital marketing
  • Digital media
  • Web Experience Management

Industries

  • Education
  • Financial services
  • Government

Help

  • Product help centers
  • Orders and returns
  • Downloading and installing
  • My Adobe

Learning

  • Adobe Developer Connection
  • Adobe TV
  • Training and certification
  • Forums
  • Design Center

Ways to buy

  • For personal and home office
  • For students, educators, and staff
  • For small and medium businesses
  • For businesses, schools, and government
  • Special offers

Downloads

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy Policy and Cookies (Updated)

Ad Choices

Reviewed by TRUSTe: site privacy statement