# Custom Drawing

Some features in PinballY let you do your own custom drawing from Javascript code. This lets you create a custom mix of text and graphics with the precise pixel layout you want. Custom drawing can be used in the following places:

- Popups - message boxes displayed in the main window. To do custom drawing in a popup box, provide a custom drawing function in the draw() property of the parameter object when you call the mainWindow.showPopup method. The system will call your custom drawing function as part of the showPopup() processing.
- Drawing layers - custom graphics layers that you can create in any of the windows through scripting code. You can create a drawing layer via the createDrawingLayer() method on any of the system window objects (mainWindow, backglassWindow, etc). That method returns an object representing the new drawing layer, which you can draw custom graphics into using its draw() method.
- Launch overlays - the graphics layers shown during a game launch to provide status updates on the progress of the launch. The system lets you access these layers through objects that you can get through the fg and bg properties of mainWindow.launchOverlay. To display custom graphics in these layers, call the draw() method on the launch overlay layer object, passing a reference to your custom drawing function as the argument.

## Creating a custom drawing function

The procedure to carry out custom drawing is a little indirect. You can't just execute drawing primitives like "draw a rectangle" from anywhere in Javascript code. Instead, all of your custom drawing code has to be contained within a "custom drawing function". This is just an ordinary Javascript function, with the following signature:

function myDrawingFunction(dc) { // carry out the drawing primitives here }

The name of the function is arbitrary - you can call it anything you want, and you can create as many different drawing functions as you want, all with different names. What's important is that it's a function that takes one parameter, which we've called dc here for "drawing context". The parameter name (like the function name) is up to you, though - you can call it anything you want.

The dc or drawing context argument is a special system object that the system creates and passes to your drawing function when it invokes the function. The drawing context contains the system methods that let you carry out the actual graphic operations, such as drawing rectangles, text, and images. This object is only valid for the duration of the function call to the drawing function, so you shouldn't store it in a global variable or otherwise hang onto it. Treat it as a temporary object that exists for the duration of the function call only.

The system calls this function after setting up the graphics area for the drawing. The argument to the function is a "drawing context" object, which has methods that let you draw text and graphics into the popup area.

## Return value from the drawing function

The return value from the drawing function depends on the context where you're using the function:

- For popups, the return value indicates the desired height in pixels for the popup. This is only needed if you create the popup with an indeterminate height. Using an indeterminate height allows you to precisely size the overall popup according to the actual contents, by measuring the sizes of the items you draw within the box.
- For launch overlays (foreground or background layers), the return value isn't used.

## Color values

Several of the drawing context methods take color values as arguments. You can specify these in several ways:

- As a hex integer value, in the format 0xAARRGGBB, where AA is the alpha (transparency) value, RR is the red component, GG is the green component, and BB is the blue component. Each can range from 00 to FF hex. For example, 0xFF0000FF represents opaque red (FF for the alpha component, or completely opaque, and FF for the red component, for maximum brightness in that component).

  If you're familiar with HTML "#rrggbb" color values, these values will look almost the same, with the differences that you replace the "#" sign with the Javascript "hex" prefix 0x, and you always have to add an FF at the beginning to indicate that the color is opaque. For example, the HTML color code #123456 would be written in your custom drawing code as 0xFF123456.

  In this format, if the alpha component (AA) is zero, the defaultAlpha property of the drawing context is automatically used. See "Default alpha values" below.

- As an HTML-style "#RGB" color string. For example, #00F represents solid red. For HTML-style colors, the opacity is always fully opaque.
- As an HTML-style "#RRGGBB" color string. The opacity with this format is always fully opaque.
- As a pseudo-HTML string in the format "#AARRGGBB". In other words, the normal HTML color format, with the addition of an alpha component (the "AA" portion), to let you specify an alpha value explicitly.
- As the name of a configuration variable from the settings file. This lets you refer to color from the settings rather than having to look it up as a separate step.

## Default alpha value

For convenience, you don't have to specify the alpha value in each individual color parameter.

- For a color parameter passed as a hex integer value, if the alpha component is zero, the default alpha value from the drawing context is automatically used.
- For a color passed as an HTML-style "#RGB" or "#RRGGBB" string, full opacity (alpha FF) is always used, regardless of the default alpha in the drawing context.

The default alpha value is given by the defaultAlpha property of the drawing context. You can read this property to get the current default, and write it to set the new default that will apply to subsequent method calls on the drawing context.

The system always sets defaultAlpha to 0xFF before calling your custom drawing function. (This happens on every call to a custom drawing function, so you don't have to worry about whether other drawing functions that were called before the current one might have changed it.)

Note that if you explicitly want to draw an area with an alpha of 00, meaning fully transparent, you must set defaultAlpha to zero first. Since the system always replaces a zero alpha in a color parameter with the default alpha value, the only way to actually get a zero alpha in the final color setting is to set the default to zero. That will replace the 00 alpha you specify in the color parameter with the 00 in the defaultAlpha property, leaving the zero alpha unchanged for the final coloring.

## Drawing context methods

The drawing context has the following methods:

- defaultAlpha: A property giving the default alpha component to apply to any color parameter passed to fillRect(), frameRect(), or setTextColor() that has a zero alpha. For example, if defaultAlpha is 0x80 (meaning 50% transparency), and you pass color code 0x0000ff (blue) to fillRect(), the system will notice the zero alpha in your color code and substitute the 0x80 default, for a final rectangle fill color of 0x800000ff (blue with 50% transparency). On the other hand, if you pass a color code of 0xFF0000FF, the alpha in the color code is already non-zero, so the default is not applied and the actual drawing color is the same as the value you specify. Note that you must set defaultAlpha to zero if you actually want to be able to draw fully transparent areas, since any other value would override a zero alpha you specify in a color parameter. The system always sets this to 0xFF (fully opaque) before each call to a custom drawing function, so that all drawing is fully opaque by default.
- drawImage(file, x, y, width, height): Draw an image. file is the name of the image file (JPEG and PNG formats are supported); this can be an absolute path, or can be a path relative to the PinballY program folder. x and y give the top left coordinates in pixels within the popup drawing area.
- drawText(string): Draws the text in string, starting at the current text origin, within the current text area boundaries, using the current text font and color. This automatically moves the text origin so that the next drawText() call will place its text after this text. If string ends in a newline character ("\n"), the text origin is advanced to the start of the next "line", vertically just below the drawn text and at the left edge of the text area. If string doesn't end in a newline, the text origin is positioned immediately to the right of the drawn text.

  This function automatically word-wraps the text if it exceeds the width of the current text area. However, this accesses a low-level Windows drawing function with a primitive line-wrapping algorithm that wraps each line to the horizontal position of the current origin, not the current text area bounds. This means that you can't use drawText() to draw a mixture of styles with word wrapping, since each segment will wrap from its own origin. If you need to use word-wrapping with styled text, you'll have to implement a higher level layout algorithm in Javascript.

- fillRect(x, y, width, height, color): Fills a rectangle at the given position and dimensions with the given color. The coordinates are in pixels relative to the popup drawing area, and the dimensions are in pixels. The color is given as an 0xAARRGGBB value, where AA is the alpha transparency (00 for fully transparent, FF for fully opaque), RR is the red component (00 to FF), GG is the green component, and BB is the blue component.
- frameRect(x, y, width, height, frameWidth, color): Draws an outline of the given width in pixels around the specified rectangle. The color is an 0xAARRGGBB value with alpha transparency, as with fillRect(). The frame is drawn such that each frame line is centered on the edge of the specified rectangle. For example, if you draw a 4-pixel frame, two of the pixels of each edge will be drawn outside the given rectangle area and two of the pixels will be inside the rectangle area.
- getImageSize(filename): Returns an object with properties {width: integer, height: integer} giving the dimensions in pixels of the given image file.
- getSize(): Returns an object with properties {width: integer, height: integer} giving the dimensions in pixels of the popup drawing area.

  For popup boxes, if you use the "dynamic layout height" option to figure the popup's height based on its contents, the reported height will be invalid during the first pass, because the whole point of the first pass is to calculate the required height. See Dynamic layout height in Popups.

- getTextOrigin(): Returns an object with properties {x: integer, y: integer} giving the current text origin, in pixel coordinates within the popup drawing area. This reflects the updates to the origin made by any drawText() calls, so it's helpful when laying out text across multiple lines. It's also useful for calculating the layout height of a popup box dynamically; see Dynamic layout height in Popups.
- measureText(string): Figures the pixel area required to display the given text. Returns an object with properties {left: integer, top: integer, right: integer, bottom: integer, width: integer, height: integer}, giving the pixel positions and dimensions of the bounding box the text would occupy if drawn at the current text origin. Note that this doesn't take into account line wrapping; it measures the text as though it were going to be laid out in an infinitely widely boundary area.
- setFont(name, pointSize, weight, italic): Sets the text font to use for subsequent drawText() and measureText() calls. Any of the arguments can be passed as undefined to keep the values for the current font; for example, you can change just the point size, keeping the current weight, by calling `dc.setFont(undefined, 24)`. The weight value is from 100 to 900; for most fonts, 400 is the normal weight and 700 is bold. (Some fonts have extra-light and extra-bold variations, which is why the range is wider than 400-700, and some have semi-bold variations between normal and bold.)
- setFontFromPrefs(str): Sets the text font for subsequent drawText() and measureText() calls to a font specified in the current user settings. str is a string giving the name of a configuration variable that refers to a font. This can be any variable name in the settings, including custom variables. The standard font option variable names are:
  - MenuFont: menu items
  - PopupFont: base font for popup dialogs and messages
  - PopupTitleFont: large font for title text in popups
  - PopupSmallerFont: smaller text font in popups
  - PopupDetailFont: even smaller detail text font in popups
  - MediaDetailFont: small font for line items in media file listings
  - WheelFont: game titles in the wheel when logos aren't available
  - HighScoreFont: font for the high score list in the info box
  - InfoBoxTitleFont: large font for title text in info box displays
  - InfoBoxFont: font for main text in info box displays
  - InfoBoxDetailFont: small font for fine print in info box displays
  - StatusFont: status line font
  - CreditsFont: credits message font

  Alternatively, you can use the string to specify the font information using the format that's used in the font preference settings, without actually looking in the setting for a variable. The format is "pointSize weight/style family", where pointSize is an integer giving the size in points of the text; weight/style is a combination of weight (100 to 900, or one of the standard weight names: thin, extralight, light, normal, medium, semibold, bold, ultrabold, black) and/or style ("regular" or "italic"), with a slash "/" separating them if both are included; and family is the font name as its appears in the Windows Fonts control panel. For example, "24 bold/italic Tahoma".

- setTextAlign(horz, vert): Sets the text alignment for drawText(). Either parameter can be set to undefined to keep the current alignment for that dimension. For horz, -1 means left alignment, 0 is center alignment, and 1 is right alignment. For vert, -1 is top alignment, 0 is vertically centered, and 1 is bottom alignment. When drawing, the alignments are relative to the current text area and the current text origin.
- setTextArea(x, y, width, height): Sets the boundaries of the current text area. The coordinates and dimensions are specified in pixels relative to the popup drawing area. The text boundaries are used for word-wrapping and alignment in drawText().
- setTextColor(color): Sets the color for text drawn with drawText(), as an 0xAARRGGBB value, with alpha transparency (the AA component), the same as in fillRect().
- setTextOrigin(x, y): Sets the text origin for the next call to drawText(). The coordinates are in pixels relative to the popup drawing area.