http://bugs.winehq.org/show_bug.cgi?id=5946
Niels Martin Hansen nielsm@indvikleren.dk changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |nielsm@indvikleren.dk
--- Comment #12 from Niels Martin Hansen nielsm@indvikleren.dk 2009-01-24 10:10:39 --- I have some experience hacking the VSFilter/TextSub source, and the cause of this bug is most likely in how Wine stores and returns TrueType text path outlines in metafile canvases. (Sorry if I use some wrong or inconsistent terms, I usually don't work much with Windows GDI.)
TextSub (as I believe the rendering engine in VSFilter is called) does its own rasterisation of text outlines, to be able to add further special effects than the regular GDI is able of. To retrieve the text outlines, it creates a metafile canvas and draws text into that, to extract the outlines afterwards.
The relevant code is in CText::CreatePath() in http://guliverkli.svn.sourceforge.net/viewvc/guliverkli2/src/subtitles/RTS.c...
Two different algorithms are used depending on whether inter-character spacing is non-zero. This is (part of) the cause of the workaround martino describes working, although it probably still has to do with a problem in Wine's implementation of metafile canvases.
In the simple case (as seen by TextSub) where all the text is drawn as a single path, first BeginPath(hdc) is called, then TextOut(hdc, 0, 0, txt, txtlen) is called, followed by CloseFigure(hdc) and EndPath(hdc). After this GetPath(hdc, NULL, NULL, 0) is used to retrieve first the number of points in the path, then memory is allocated, and finally GetPath(hdc, mpPathPoints, mpPathTypes, mPathPoints) is used to get the actual points. I believe it is somewhere here the problem lies. I don't have a machine myself to test on, but either Wine returns too few points, or it returns them in an unexpected form, and it seems to be triggered by space characters in the string to TextOut(). Lastly the path is cleared from the canvas by AbortPath(hdc).
The case where the inter-character spacing is specified to be non-zero, the same sequence of operations is basically performed for each widecharacter in the text that should be rendered. The advance for each character is retrieved with GetTextExtentPoint32W(). The points retrieved for each character in the text are then appended to a list of all points which are used for further rasterisation. This case where each character is treated as a separate string works fine, accordint to reports.