I worked on this some more and it seems it would be simpler and more
efficient for linebreaking to operate on transformed text (i.e. after
whitespace compression), because then we don't have to translate
possible break points from DOM offsets to transformed-text offsets to
store and use in the textrun. But we don't keep transformed text around,
so we need a new kind of line breaking interface that is more like a
state machine. Something like this:

/**
 * 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
_______________________________________________
dev-tech-layout mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-layout

Reply via email to