bool ParagraphLayout::_AppendGlyphInfos(const TextSpan& span) { int charCount = span.CharCount(); if (charCount == 0) return true; const BString& text = span.Text(); const BFont& font = span.Style().Font(); // Allocate arrays float* escapementArray = new (std::nothrow) float[charCount]; if (escapementArray == NULL) return false; ArrayDeleter<float> escapementDeleter(escapementArray); // Fetch glyph spacing information font.GetEscapements(text, charCount, escapementArray); // Append to glyph buffer and convert escapement scale float size = font.Size(); const char* c = text.String(); for (int i = 0; i < charCount; i++) { if (!_AppendGlyphInfo(UTF8ToCharCode(&c), escapementArray[i] * size, span.Style())) { return false; } } return true; }
bool Paragraph::Insert(int32 offset, const TextSpan& newSpan) { int32 index = 0; while (index < fTextSpans.CountItems()) { const TextSpan& span = fTextSpans.ItemAtFast(index); if (offset - span.CharCount() < 0) break; offset -= span.CharCount(); } if (fTextSpans.CountItems() == index) return Append(newSpan); // Try to merge with span at index if the TextStyles are equal TextSpan span = fTextSpans.ItemAtFast(index); if (span.Style() == newSpan.Style()) { span.Insert(offset, newSpan.Text()); return fTextSpans.Replace(index, span); } if (offset == 0) { if (index > 0) { // Try to merge with TextSpan before if offset == 0 && index > 0 TextSpan span = fTextSpans.ItemAtFast(index - 1); if (span.Style() == newSpan.Style()) { span.Insert(span.CharCount(), newSpan.Text()); return fTextSpans.Replace(index - 1, span); } } // Just insert the new span before the one at index return fTextSpans.Add(newSpan, index); } // Split the span, TextSpan spanBefore = span.SubSpan(0, offset); TextSpan spanAfter = span.SubSpan(offset, span.CharCount() - offset); return fTextSpans.Replace(index, spanBefore) && fTextSpans.Add(newSpan, index + 1) && fTextSpans.Add(spanAfter, index + 2); }