I am trying to make a teleprompter application that’s more flexible than the one we currently use at our public access TV station. In a teleprompter their are two displays of scrolling text: one for the person controlling it and another for the person reading. Often the display of the person reading must be mirrored in the x or y axis. The biggest challenge is that, other than mirroring, the controller must be able to see exactly what is on the reader’s display. While most widget toolkits have efficient ways of creating scrolled text, it can be difficult to prove that the wrapping points for text are identical when scaling occurs.
In my naive approach, I’m trying to short-circuit the difficulty of ensuring wrap points by grabbing a bitmap image of everything painted to the reader’s window and blitting a scaled copy back on the controller’s window. While this works really well in my test windows that are 300x300 pixels, when I scale up the reader’s window to the monitor’s full resolution of 1920x1080, I’m unable to animate smoothly. I’m using a very naive painting technique right now:
def paint(self, event):
dc = wx.ClientDC(self)
dc.SetBackground(self.background_brush)
dc.Clear()
dc.SetTextForeground(self.text_color)
dc.SetFont(self.font)
text = wordwrap(self.script, self.GetSize()[0], dc)
dc.DrawText(text, 0, self.y_scroll)
My initial thought was that because the script was so long, drawing tons of text that isn't even seen was wasteful. However, if I make the text only a few lines long, I have the same delays. It seems to me that the painting time is based more on the number of pixels, rather than the actual drawing occurring.
I've been thinking of less naive ways to approach this. One was to create a big bitmap containing all of the text once, then just blit the currently viewed portion to the screen. However, for a high resolution, this bitmap rapidly gets too large to store in memory. Since that won't work, I could create bitmaps for the current screenful of text and the next and previous screenfuls, and blit those in, only creating a new bitmap when a screenful of text has exited the viewable region. Alternatively, I could make each line of text a bitmap, creating them when necessary.
I am trying to keep whatever technique I use fairly generic, since I'd like to add other graphics to the screen like highlighted regions and countdown timers. I was thinking that switching to OpenGL is somewhat a nuclear option, but that would at least let hardware do positioning and scaling of images. Is there a better way to figure out which parts of paint are bogging down the framerate? My goal is to achieve 60 fps or better, because any jitter puts strain on the reader.
I'm open to any ideas, and I wanted to make sure I wasn't reinventing the wheel, or missing something in the drawing API specifically to make this sort of high resolution drawing task faster. The [github repository](https://github.com/superlou/flexcue) should work fine on Linux, though I am getting some flickering on Windows.
Thanks,
Louis