void
NS_GetComplexLineBreaks(const char16_t* aText, uint32_t aLength,
                        uint8_t* aBreakBefore)
{
  NS_ASSERTION(aText, "aText shouldn't be null"); 

  int outItems = 0;
  HRESULT result;
  AutoTArray<SCRIPT_ITEM, 64> items;
  char16ptr_t text = aText;

  memset(aBreakBefore, false, aLength);

  if (!items.AppendElements(64))
    return;

  do {
    result = ScriptItemize(text, aLength, items.Length(), nullptr, nullptr,
                           items.Elements(), &outItems);

    if (result == E_OUTOFMEMORY) {
      if (!items.AppendElements(items.Length()))
        return;
    }
  } while (result == E_OUTOFMEMORY);

  for (int iItem = 0; iItem < outItems; ++iItem)  {
    uint32_t endOffset = (iItem + 1 == outItems ? aLength : items[iItem + 1].iCharPos);
    uint32_t startOffset = items[iItem].iCharPos;
    AutoTArray<SCRIPT_LOGATTR, 64> sla;
    
    if (!sla.AppendElements(endOffset - startOffset))
      return;

    if (ScriptBreak(text + startOffset, endOffset - startOffset,
                    &items[iItem].a,  sla.Elements()) < 0) 
      return;

    for (uint32_t j=0; j+startOffset < endOffset; ++j) {
       aBreakBefore[j+startOffset] = sla[j].fSoftBreak;
    }
  }
}
void
NS_GetComplexLineBreaks(const PRUnichar* aText, PRUint32 aLength,
                        PRPackedBool* aBreakBefore)
{
  NS_ASSERTION(aText, "aText shouldn't be null"); 
  int outItems = 0;
  HRESULT result;
  nsAutoTArray<SCRIPT_ITEM, 64> items;

  memset(aBreakBefore, PR_FALSE, aLength);

  if (!items.AppendElements(64))
    return;

  do {
    result = ScriptItemize(aText, aLength, items.Length(), NULL, NULL, items.Elements(), &outItems);

    if (result == E_OUTOFMEMORY) {
      if (!items.AppendElements(items.Length()))
        return;
    }
  } while (result == E_OUTOFMEMORY);

  for (int iItem = 0; iItem < outItems; ++iItem)  {
    PRUint32 endOffset = (iItem + 1 == outItems ? aLength : items[iItem + 1].iCharPos);
    PRUint32 startOffset = items[iItem].iCharPos;
    nsAutoTArray<SCRIPT_LOGATTR, 64> sla;
    
    if (!sla.AppendElements(endOffset - startOffset))
      return;

    if (ScriptBreak(aText + startOffset, endOffset - startOffset,
                    &items[iItem].a,  sla.Elements()) < 0) 
      return;

    for (PRUint32 j=0; j+startOffset < endOffset; ++j) {
       aBreakBefore[j+startOffset] = sla[j].fSoftBreak;
    }
  }
  
}
Exemple #3
0
size_t *graphemes(WCHAR *msg)
{
	size_t len;
	SCRIPT_ITEM *items;
	int i, n;
	size_t *out;
	size_t *op;
	SCRIPT_LOGATTR *logattr;
	int j, nn;
	HRESULT hr;

	len = wcslen(msg);
	hr = itemize(msg, len, &items, &n);
	if (hr != S_OK)
		logHRESULT(L"error itemizing string for finding grapheme cluster boundaries", hr);

	// should be enough; 2 more just to be safe
	out = (size_t *) uiAlloc((len + 2) * sizeof (size_t), "size_t[]");
	op = out;

	// note that there are actually n + 1 elements in items
	for (i = 0; i < n; i++) {
		nn = items[i + 1].iCharPos - items[i].iCharPos;
		logattr = new SCRIPT_LOGATTR[nn];
		hr = ScriptBreak(msg + items[i].iCharPos, nn,
			&(items[i].a), logattr);
		if (hr != S_OK)
			logHRESULT(L"error breaking string for finding grapheme cluster boundaries", hr);
		for (j = 0; j < nn; j++)
			if (logattr[j].fCharStop != 0)
				*op++ = items[i].iCharPos + j;
		delete[] logattr;
	}
	// and handle the last item for the end of the string
	*op++ = items[i].iCharPos;

	delete[] items;
	return out;
}
Exemple #4
0
static bool MCTextLayoutLinkItem(MCTextLayoutState& self, SCRIPT_ANALYSIS p_analysis, const unichar_t *p_chars, uint32_t p_char_count, MCTextLayoutFont *p_font)
{
	bool t_success;
	t_success = true;

	// If the font is not linked, we can move directly to shaping
	if (p_font -> linking == nil)
		return MCTextLayoutShapeItem(self, p_analysis, p_chars, p_char_count, p_font, nil);

	// Otherwise we need to split up the run further into font ranges resulting
	// from font linking. Unfortunately, this is more complex than just looking
	// up each UTF-16 codepoint in the fonts support since we need to handle
	// combining cases and surrogates.

	// Make an array to hold cached text layout fonts, we get these as needed.
	MCTextLayoutFont **t_fonts;
	t_fonts = nil;
	if (t_success)
		t_success = MCMemoryNewArray(p_font -> linking -> entry_count + 1, t_fonts);

	// The first entry in the array is always the font we start with.
	if (t_success)
		t_fonts[0] = p_font;

	// We shape cluster by cluster, so determine the cluster boundaries using
	// ScriptBreak.
	SCRIPT_LOGATTR *t_breaks;
	t_breaks = nil;
	if (t_success)
		t_success = MCMemoryNewArray(p_char_count, t_breaks);

	if (t_success)
		if (ScriptBreak(p_chars, p_char_count, &p_analysis, t_breaks) != S_OK)
			t_success = false;

	// Now loop cluster by cluster, determining the font of each one. Note that
	// we can't use the results of shaping individual clusters to build up the
	// glyphs of the item since adjacent clusters may interact. For example, in
	// Sylfaen 'f' and 'i' and elide to form a proper 'fi' ligature.
	if (t_success)
	{
		MCTextLayoutFont *t_span_font;
		uint32_t t_span_start, t_span_finish;
		t_span_start = t_span_finish = 0;
		t_span_font = nil;
		while(t_success && t_span_finish < p_char_count)
		{
			// Compute bounds of next cluster
			uint32_t t_cluster_start, t_cluster_finish;
			t_cluster_start = t_span_finish;
			t_cluster_finish = t_cluster_start + 1;
			while(t_cluster_finish < p_char_count && !t_breaks[t_cluster_finish] . fCharStop)
				t_cluster_finish++;

			// Now try to shape the cluster in each font successively.
			MCTextLayoutFont *t_cluster_font;
			t_cluster_font = nil;
			for(uint32_t i = 0; i < p_font -> linking -> entry_count + 1 && t_success; i++)
			{
				// Get the font, if it doesn't already exist
				if (t_fonts[i] == nil)
					t_success = MCTextLayoutFontWithLink(p_font, &p_font -> linking -> entries[i - 1], t_fonts[i]);

				// Now try to shape the cluster with it
				bool t_shaped;
				if (t_success)
					t_success = MCTextLayoutShapeItem(self, p_analysis, p_chars + t_cluster_start, t_cluster_finish - t_cluster_start, t_fonts[i], &t_shaped);

				// If the shaping was successful we are done
				if (t_success && t_shaped)
				{
					t_cluster_font = t_fonts[i];
					break;
				}
			}

			// If the cluster's font is not the same as the span's font then we
			// have a run to shape.
			if (t_success && t_cluster_font != t_span_font)
			{
				if (t_span_start != t_span_finish)
					t_success = MCTextLayoutShapeItem(self, p_analysis, p_chars + t_span_start, t_span_finish - t_span_start, t_span_font, nil);

				// The next span starts where the previous one finishes and has
				// the font of the cluster we just shaped.
				if (t_success)
				{
					t_span_start = t_span_finish;
					t_span_font = t_cluster_font;
				}
			}
			
			// End of span is end of cluster
			t_span_finish = t_cluster_finish;
		}

		// Shape the trailing span
		if (t_success)
			t_success = MCTextLayoutShapeItem(self, p_analysis, p_chars + t_span_start, t_span_finish - t_span_start, t_span_font, nil);
	}

	MCMemoryDeleteArray(t_breaks);
	MCMemoryDeleteArray(t_fonts);

	return t_success;
}