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; } } }
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; }
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; }