by Michael S. Kaplan, published on 2006/02/07 11:01 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2006/02/07/526359.aspx
James Brown asked in the microsoft.public.win32.programmer.international newsgroup:
I have a fully working Uniscribe wrapper which renders a line of Unicode text, using the low-level ScriptItemize /Layout/Shape/Place/TextOut calls. Its working pretty well (very well in fact) but there is still one area I am not happy with. For a regular string of "english" text (i.e. non-complex), ScriptItemize always breaks the string into individual words. For a long line of text, containing much white-space and punctuation, this can result in quite a number of SCRIPT_ITEMs being returned.
This results in a large number of calls to ScriptTextOut to render the text, which is where the problem is - because I am required to call ScriptTextOut for each "item-run" in the text, this results in a fairly slow mode of operation - alot slower than calling ExtTextOut for the whole line for example. It's not that ScriptTextOut itself is slow, it is just the shear number of calls to the OS that is causing the problem.
So my idea is as follows:
After Shaping, all of the returned glyph-data for every item-run in the string is stored consecutively in a large buffer. Ordinarily I isolate each run in this buffer and draw the runs individually with ScriptTextOut.
However for a "simple" string of text (i.e one that ScriptIsComplex recognizes as such), I am proposing to pass the entire buffer of glyph/widths etc to ScriptTextOut in one go - so even if there was 30 runs of text, I would just treat this as one run and call ScriptTextOut just once - in essence, recombining all script-items into one single unit.
Assuming for the moment that I am using just one font, does anyone see any problem in this approach? The only issue I can see is specifying a correct SCRIPT_ANALYSIS structure (there is a unique structure per run so which would I specify?)
I have seen hints that maybe ScriptTextOut performs some trickery prior to calling ExtTextOut (for complex scripts) and that combining runs prior to calling it would be bad.....but for regular english text (code-points < 255 for example) would this be ok?
I have tested this method, and it does seem to work - and it is *much* faster this way... it would be nice for a Microsoft uniscribe/typography rep to comment on this approach.
The method itself should be sound (this type of use of ScriptIsComplex is very similar to the method that LPK.DLL (discussed previously) uses to determine whether to forward text rendering calls to Uniscribe or not.
(Of course in the case of LPK.DLL, Uniscribe is not called in the non-complex case, ExtTextOutW is; there may be a performance benefit to doing this since ScriptTextOut must evetually call ExtTextOutW to do the actual rendering -- so eliminating the extra overhead may be everyone's advantage).
No I am not entirely clear on why non-complex text would be broken into separate runs (especially text for which ScriptIsComplex resturns FALSE), so I will probably try to dig a little deeper on that point.
Does anyone have any theories? :-)
This post brought to you by "ཛྷ" (U+0f5c, a.k.a. TIBETAN LETTER DZHA)
# Robert on 7 Feb 2006 8:13 PM:
# Michael S. Kaplan on 7 Feb 2006 10:02 PM:
# James Brown on 8 Feb 2006 12:01 PM:
referenced by
2007/03/13 We need to be optimizing for more than just the simple cases
2006/07/10 The PUA isn't complex enough