-
Notifications
You must be signed in to change notification settings - Fork 12
Internal Documentation
This page documents the internal structure.
-
Calling
tr := TextRender()calls __New() and sets thepending_flushflag to true. -
When Draw() is first called, it will Flush() the graphics buffer.
-
Flush() calls UpdateMemory()
-
Since the graphics buffer does not exist, FreeMemory() returns and LoadMemory() creates the graphics buffer.
-
The user can call FreeMemory() at any time to destroy the graphics buffer and free up RAM. The graphics buffer will be recreated automatically when needed.
this.Hash() - A 32-bit CRC32 hash of the bitmap pixels. Slow.
this.status - A 32-bit integer generated after every change in the canvas state. Avoid checking this value and use OnEvent("CanvasChange", callback) instead.
this.pending_flush - True if Draw() has been called at least once. False after a rendering action takes place.
To determine if the bitmap has been changed, use Hash() which returns a CRC32 hash of the underlying pixels. As this is very slow, it is recommended to use the status property instead, which is a 32-bit random number that is generated after every edit of the canvas. Objects that are drawn off screen will change this.status despite making no visible changes.
Finally pending_flush contains the publishing state of the window. After every render, if the canvas needs to be flushed and pending_flush is set to true. The next call to Draw() will clean the internal canvas by calling Flush().
To set the window title, window style, window extended style and window parent call new.
tr := new TextRender(title, style, styleEx, parent) ; AutoHotkey v1 only
- Default window title is the empty string.
- Default window style is 0x80000000 which is
WS_POPUP. - Default window extended style is 0x80088, a combination of
WS_EX_TOPMOST,WS_EX_TOOLWINDOW, andWS_EX_LAYERED. - Default window parent is
A_ScriptHwnd.
As the new keyword only exists on AutoHotkey v1, the object must be manually instantiated on AutoHotkey v2. The following works in one line because __New() returns this.
tr := {base: TextRender.prototype}.__New(title, style, styleEx, parent) ; AutoHotkey v2 only
this.ptr - A pointer to the bitmap pixels from CreateDIBSection.
this.size - The size of the pointer to the bitmap pixels.
this.hwnd - A window handle that uniquely identifies the window.
this.hdc - A handle to a GDI device context.
this.hbm - A handle to a device independent bitmap. Use CopyToHBitmap() for a separate copy.
this.obm - The mysterious stock bitmap.
this.gfx - A GDI+ graphics handle.

Bitmap = Virtual Screen (Pixel Array, hdc, hbm, ptr)
Canvas = Infinite Graphics (GDI+ pointer)
Window = Visible Area (Can be seen with Window Spy, hwnd)
The bitmap is exactly the size of the user's screen (or the virtual screen consisting of all monitors combined). It is fully backed by memory. Normally many of these pixels are transparent as the render is usually smaller than the user's entire screen. The bitmap is also known as the back buffer, since it buffers the drawings in backing memory. The window is what the user can interact with on screen. The window is sometimes called the front buffer as it normally lives in the VRAM corresponding to your display. It is faster to edit the back buffer repeatedly and send the image to the front buffer once, than it is to constantly edit the front buffer. There are multiple reasons why including (1) the CPU can access the RAM faster than the VRAM and (2) giving applications access to the user's screen is generally a security risk. The canvas is infinite. It extends the bitmap and contains coordinates that lie outside of the screen. When TextRender receives instructions to draw off the screen, it simply doesn't change any pixels. However, it is important to remember this operation, as the screen size can change for example, and what was formerly off the screen can now be rendered on the screen. You can think of the canvas as containing visible in-bounds pixels and invisible out-of-bounds pixels from -∞ to ∞.
Window ⊆ Bitmap ⊆ Canvas
If a graphics element is rendered partially on screen, the part that lies within the bitmap is rendered by the graphics engine, and the part that lies outside the bitmap will be ignored. In the example above, the right side of the red rectangle will be discarded. Only the blue portion of the visible window is kept. Therefore, the pixels of the bitmap are a real subset of an infinite canvas. The window is the visible subset of the bitmap that has been edited.
Why is the bitmap the size of the virtual screen? Shouldn't the graphics buffer be equal to the window size? Constantly resizing the pixel array is a CPU intensive operation that reduces speed. For fastest performance, the screen is double buffered, therefore the graphics buffer must be the same size as the screen!
FreeMemory() can be called anytime to discard the graphics buffer. When Draw() or Render() is subsequently called, the graphics buffer will be reinitialized, and all past actions will be repainted from this.layers.
The back buffer or backing memory. Previous names in the documentation were graphics buffer and internal canvas.
this.BitmapLeft
this.BitmapTop
this.BitmapRight
this.BitmapBottom
this.BitmapWidth
this.BitmapHeight
Stride should be manually calculated as 4 (# of color channels) × this.BitmapWidth.
The visible window area.
this.WindowLeft
this.WindowTop
this.WindowRight
this.WindowBottom
this.WindowWidth
this.WindowHeight
Describes the drawn image, regardless if it is off screen and cannot be rendered.
this.t - Time to show text on screen. If zero, then it will show indefinitely.
this.x
this.y
this.x2
this.y2
this.w
this.h
this.chars
this.words
this.lines
this.events - Used by OnEvent().
this.layers - A history of all Draw() calls. Refreshed after Render().
this.data - The first parameter of Draw().
this.styles - The second and third parameters of Draw().
this.friend1 - An instance of TextRender() used by EventShowCoordinates.
this.friend2 - An instance of TextRender() used by EventCopyText.
TextRender.gdiplus() - Get the current number of gdiplus instances.
TextRender.gdiplusStartup() - Increase the number of gdiplus instances by 1.
TextRender.gdiplusShutdown() - Decrease the number of gdiplus instances by 1.
Call GetWindowLongPtr at offset 0 to get a pointer (address) to the associated AutoHotkey object.