[buffer] Save pre/post textual context

To be used for a variety of purposes.  We save up to five characters
in each direction.  No public API changes, everything is taken care
of already.  All clients need to do is to call hb_buffer_add_utf* with
the full text + segment info (or at least some context) instead of
just passing in the segment.

Various operations (hb_buffer_reset, hb_buffer_set_length,
hb_buffer_add*) automatically reset the relevant contexts.
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 6da196f..2f8f511 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -1,7 +1,7 @@
 /*
  * Copyright © 1998-2004  David Turner and Werner Lemberg
  * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
- * Copyright © 2011  Google, Inc.
+ * Copyright © 2011,2012  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -158,6 +158,9 @@
   serial = 0;
   memset (allocated_var_bytes, 0, sizeof allocated_var_bytes);
   memset (allocated_var_owner, 0, sizeof allocated_var_owner);
+
+  memset (context, 0, sizeof context);
+  memset (context_len, 0, sizeof context_len);
 }
 
 void
@@ -570,6 +573,8 @@
     true, /* in_error */
     true, /* have_output */
     true  /* have_positions */
+
+    /* Zero is good enough for everything else. */
   };
 
   return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
@@ -723,6 +728,7 @@
 	       unsigned int    cluster)
 {
   buffer->add (codepoint, mask, cluster);
+  buffer->clear_context (1);
 }
 
 hb_bool_t
@@ -743,6 +749,11 @@
   }
 
   buffer->len = length;
+
+  if (!length)
+    buffer->clear_context (0);
+  buffer->clear_context (1);
+
   return true;
 }
 
@@ -817,13 +828,38 @@
 
   buffer->ensure (buffer->len + item_length * sizeof (T) / 4);
 
-  const T *next = (const T *) text + item_offset;
+  if (!buffer->len)
+  {
+    /* Add pre-context */
+    buffer->clear_context (0);
+    const T *prev = text + item_offset;
+    const T *start = text;
+    while (start < prev && buffer->context_len[0] < buffer->CONTEXT_LENGTH)
+    {
+      hb_codepoint_t u;
+      prev = hb_utf_prev (prev, start, &u);
+      buffer->context[0][buffer->context_len[0]++] = u;
+    }
+  }
+
+  const T *next = text + item_offset;
   const T *end = next + item_length;
-  while (next < end) {
+  while (next < end)
+  {
     hb_codepoint_t u;
     const T *old_next = next;
     next = hb_utf_next (next, end, &u);
-    hb_buffer_add (buffer, u, 1,  old_next - (const T *) text);
+    buffer->add (u, 1,  old_next - (const T *) text);
+  }
+
+  /* Add post-context */
+  buffer->clear_context (1);
+  end = text + text_length;
+  while (next < end && buffer->context_len[1] < buffer->CONTEXT_LENGTH)
+  {
+    hb_codepoint_t u;
+    next = hb_utf_next (next, end, &u);
+    buffer->context[1][buffer->context_len[1]++] = u;
   }
 
   buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE;