I'm actually thinking seriously of adding this interface to
nsILineBreaker with an implementation based on the current linebreaker
code and then rolling this into the textframe patch. It fits well with
the new textrun construction code, which is already basically
paragraph-at-a-time, and we can store the computed linebreak
opportunities into the textrun, which means some changes to the textrun
API (mostly, simplification). Might as well do this now, I think.
Rob
/**
* A receiver of line break data.
*/
class nsILineBreakSink {
public:
/**
* Sets the break data for a substring of the associated text chunk.
* One or more of these calls will be performed; the union of all
* substrings will cover the entire text chunk. Substrings may overlap
* (i.e., we may set the break-before state of a character more than
* once).
* @param aBreakBefore the break-before states for the characters in
* the substring.
*/
void SetBreaks(PRUint32 aStart, PRUint32 aLength,
PRPackedBool* aBreakBefore) = 0;
};
/**
* A line-breaking state machine. You feed text into it via AppendText
* calls and it computes the possible line breaks. Because break
* decisions can require a lot of context, the breaks for a piece of
* text are sometimes not known until later text has been seen (or all
* text ends). So breaks are returned via a call to SetBreaks on the
* nsILineBreakSink object passed with each text chunk, which might
* happen during the corresponding AppendText call, or might happen
* during a later AppendText call or even a Reset() call.
*/
class nsLineBreaker {
public:
nsLineBreaker();
~nsLineBreaker();
/**
* Feed Unicode text into the linebreaker for analysis.
*/
void AppendText(nsIAtom* aLangGroup, const PRUnichar* aText,
PRUint32 aLength,
nsILineBreakSink* aSink);
/**
* Feed 8-bit text into the linebreaker for analysis.
*/
void AppendText(nsIAtom* aLangGroup, const unsigned char* aText,
PRUint32 aLength,
nsILineBreakSink* aSink);
/**
* Reset all state. This means the current run has ended; any
* outstanding calls through nsILineBreakSink are made, and all
* outstanding references to nsILineBreakSink objects are dropped.
* After this call, this linebreaker can be reused.
* This must be called at least once between any call to
* AppendText() and destroying the object.
*/
void Reset();
}
Oh yeah --- I also want this to be non-COM and inline-allocatable, so
I'm thinking of putting it content/base instead of intl. The only users
of nsILineBreaker are content, layout and editor so I think this will
work. We can expose a COM-ish wrapper to satisfy non-gklayout consumers.
Rob
Editor unfortunately isn't part of gklayout, so you may need to use a
COM-ish wrapper for that. As much as I hate to say it, maybe we should
consider moving libeditor into gklayout :(
/ Jonas
Why do you hate to say that? it's a great idea and I think I've
suggested it before :-)
Rob
Linking gklayout.dll on windows is really painful as is. On my laptop it
can take up to 15 minutes which is more or less a show stopper for me to
do serious development in that environment.
/ Jonas
That sucks, but I'd rather buy developers bigger laptops so our users
can have smaller ones.
Rob