| Log In | Not a Member? |
Contact ADC
|
|
![]() |
|
|
| Previous Section | Table of Contents | Next Section |
Module 3- Working with TextContents
Overview In this module, we will learn how to specify font characteristics such as font, size, face, and color, and will also explore how to use graphics modes of the compositor. NOTE: This feature requires QuickTime for Java 4.1. It will not work with previous versions. Introduction to Drawing Text in QuickTime for Java QuickTime for Java has a built-in text engine that is based on QuickDraw's text support. This approach is extremely simple and allows us great control over text sizes, faces, and fonts. Unfortunately, this simplicity comes at a bit of a price- it up to the developer to make sure that the specified font exists and to perform any necessary scaling as needed by the native platform. If you need robust, cross-platform font support, consider using Java to do text drawing. This project is based on the previous module and assumes that you have completed it. If you would like to download a completed copy of the module 2, you may do so. Before proceeding, we have renamed the main class to "Zoo3" and changed all instances to prevent confusion. Other than that, we do not need to modify the main class file. Click here to see the main source file Zoo3.java. We will need to create a new source file for our class that will contain all of our text drawing code. We will call this class TextPresenter. Create a new source file and save it as TextPresenter.java. Now we will create a skeleton for our class:
We provide two different constructors for convenience. We allow the user to either specify the text data to be drawn as an array of strings, or specify a text file to be used for the data. The first constructor simply calls the second constructor with the results of the call to readTextFile( ) as the constructor parameter. Importing Packages and Creating an Offscreen Graphics Context Now we are ready to start fleshing out our second constructor. In our constructor, we will need to do three different things. The first is to create an offscreen drawing area large enough for the specified dimension. Secondly, we need to take the string array and draw it in the offscreen drawing area. Lastly, we need to take our offscreen drawing area and put it into a format that we can draw into the compositor. Let's start to flesh out the constructor to do the first of these three tasks:
We then import the QDRect class that defines a QuickDraw Rectangle structure. Lastly, we import the QTException class. This type of exception may be thrown by many of the routines that we will be using. Once we import the necessary classes, we are ready to implement the body of our TextPresenter constructor. We start our body with the declaration of a QDRect variable named area. This is declared so that we can have a QuickDraw representation of the dimension object that is passed in to our constructor. Next we declare a try( ) block. This will allow us to catch any QuickTime errors thrown by the various methods that we will be calling. Within our try( ) block, we create a new QDGraphics object and pass it the area QDRect data member. This QDGraphics object named gw, declared down at the end of the file, contains a 32-bit per pixel offscreen graphics world and all of the associated QuickDraw data structures such as the color table and the PixMap. The constructor we used specifies a default set of creation flags and locks the GWorld into memory. The parameter we pass specifies the size of the offscreen GWorld. Finally, we close the try( ) block and make a catch( ) block that handles any QTExceptions thrown and prints a stack trace if an exception occurs. Note that this is extremely rudimentary error handling and is simplified for the purpose of this tutorial. Real applications should provide more robust error and exception handling. So far, we have created a QDRect to represent the size of the offscreen area (based on the dimension parameter of our constructor) and created a QDGraphics object that encapsulates our GWorld we will be drawing in. Now it's time to perform the actual text drawing.
First we import the QDDrawer package. Next, we call beginDraw( ) from the QDGraphics object and pass a new QDDrawer( ) anonymous class that we declare inline. Our anonymous class overrides the draw( ) method and declares that it throws a QTException. (Now it is evident why we need the try/catch block around our code.) The beginDraw method is called whenever the QDGraphics object needs to update the contents of its offscreen gWorld. This typically only occurs once (at initialization). Now we can place any drawing code directly in the draw method and it will be transferred into the contents of the offscreen GWorld. QuickDraw Text Drawing Operations Drawing in a QuickTime graphics context is accomplished by means of calling standard QuickDraw commands. All operations are called via methods of a QDGraphics object:
Now, we need to set up our graphics environment. We set the size of the font we will be using by calling the textSize( ) method. This allows us to specify the font size in points to be used by subsequent drawing operations. In the same manner, we set the font, style, and color. Next, we specify the background graphics color (the color that will be used for erasing operations), and erase the entire contents of the QDGraphics. It is very important that we perform this erase operation because when the QDGraphics object is created it is a chunk of uninitialized memory which would translate to randomly colored pixels. This erase operation gives us a clean "canvas" to draw on. Now we need to get the text to draw. We create a temporary String object and initialize it to the first item in the String array that is passed in to our constructor. Once we have this string, we check the width in pixels of the string and compare it to the width of our drawing area. If the text is too long to fit in the specified space, we decrease the font size. This adjustment is designed to account for font size differences between the Macintosh platform and windows. This rough adjustment works for this particular scenario, but is not a robust way to perform cross-platform font adjustment. Finally, we declare a for loop: for ( int i = 0; i < theText.length; ++i ) { We will take one trip through our loop for each String in our array. Since we have already assigned the first item in our String array constructor parameter to our aLine data member, we skip this first item. All subsequent items will be assigned to this temporary variable in sequence. if ( i != 0 ) aLine = theText[ i ]; We now have the string that we are going to draw. Now it is time to specify
the location where the line of text will be drawn. This is done with a
moveTo( ) call. This does not actually draw the text. Drawing text is
accomplished via the drawTextScaled( ) method: The drawTextScaled( ) method takes four parameters. The first is the length of the string to draw and the second String parameter is the line that we will be drawing. The final two float parameters specify scaling. The first variable specifies horizontal scaling, while the second scaling variable specifies vertical scaling. A value of 1.0 represents 100% scaling while a value of .5 would specify 50% (half size) and 2.0 would represent 200% scaling (double size). This completes our text drawing operations. Now we need to provide the graphics context in a format that the compositor can use for drawing. Setting the Graphics Mode of the QDGraphics Object Now that we have drawn the text, we need to prepare the graphics object for drawing by the compositor:
Next, we set the graphics mode of the ImagePresenter object. The graphics mode is the QuickDraw transfer mode used to draw the graphics. We have specified a transparent mode and used white as the transparent index. This will treat all white pixels with an RGB value of 255, 255, 255 as transparent pixels. This enables us to draw our text on top of the background without obscuring the image. Since the ImagePresenter object is protected, we will need to add an accessor routine that external classes can use. We add a method called getPresenter( ) that simply returns our imagePres data member. This is a better object-oriented programming technique than simply making the imagePres object public. All that remains is to write the method that reads in the text file:
Now, we will return to the Animal Pane file for minor modifications to add the ImagePresenter to the compositor:
Lastly, we make a call (which we will implement later) to add our text item to the compositor. This method will retrieve the ImagePresenter object from our TextPresenter class and position it in the compositor in a specific layer and at a specific location. This routine will take the path of the text to display, the layer number to display in the compositor, the x and y location within the compositor, and the height and width of the text area. We will implement this routine next. Implementing the addText Routine The addText( ) routine is responsible for imaging our TextPresenter at a specific location in the compositor:
All of our code is placed in a try block so that we can
catch any exceptions that might be thrown by the TextPresenter constructor,
or any subsequent routines. Now we will need to get the ImagePresenter object from our TextPresenter. The ImagePresenter used by the TextPresenter is protected, so we will need to call a method to retrieve it. We call the getPresenter( ) method of the TextPresenter class for this purpose and store the result in a local object reference. Our constructor has parameters for specifying the location of the text display area within the compositor. Offsetting the location of our TextPresenter is accomplished by using a matrix. QuickTime's Matrix classes are standard 3x3 matrices that allow us to specify translation (offsetting an object on the x and/or y axis in the cartesian coordinate system), scaling, or rotation of an object. We use the Matrix to specify a translation. First, we create a new Matrix by calling the default constructor. This creates a new instance of the identity matrix. If we were to apply the identity matrix to an object, there would be no visible change. (For more information on Matrices, see this QuickTime document). Next, we call the translate method of the matrix object to offset the text based on the x and y positions that are passed in to the routine as parameters. Once the translation matrix is calculated, we set the matrix of the presenter to the one we just created. Finally, we add the text presenter to the compositor in the correct layer and perform any needed exception handling. This completes source modifications for this module. If you would like to see completed source code for Zoo3.java, AnimalPane.java, or TextPresenter.java, please click on the appropriate link.
This module introduced the basics of dealing with text using the QuickTime text engine. We learned how to create a graphics context for drawing using basic QuickDraw commands and used QuickDraw transfer modes to modify the appearance of the drawn image. Finally, we used an intermediary ImagePresenter object to display our rendered text area in a compositor. We covered a lot of material, and in our next section, we will switch gears and learn about how to add sound playback to our application. The clever reader will realize quickly that the information that was presented here only scratches the surface of what could be done using QuickTime for Java. Although we will expand this example in future modules, there are few things that you could do on your own as exploration that will help you better understand how QuickTime for Java works. Each one of these examples has a source code solution, so if you have trouble, feel free to consult it. Experiment with one or more of the following:
|
| Previous Section | Table of Contents | Next Section |