package yuku.alkitab.base.widget; import android.graphics.Typeface; import android.text.SpannableStringBuilder; import android.text.style.StyleSpan; public class FormattedTextRenderer { /** * Renders a simple formatted text. This is a much simpler version of {@link VerseRenderer}, * only some tags are supported. The supported tags are: * <pre> * @9...@7 for italics * @8 for line break * </pre> * * @param text String with formatting tags. Optionally it can start with "@@". */ public static SpannableStringBuilder render(final String text) { return render(text, null); } /** * Renders a simple formatted text. This is a much simpler version of {@link yuku.alkitab.base.widget.VerseRenderer}, * only some tags are supported. The supported tags are: * <pre> * @9...@7 for italics * @8 for line break * </pre> * * @param text String with formatting tags. Optionally it can start with "@@". * @param appendToThis If not null, the results are appended to this string instead of newly created. Note that * the contents of this parameter will be modified. */ public static SpannableStringBuilder render(final String text, final SpannableStringBuilder appendToThis) { return render(text, false, appendToThis); } /** * Renders a simple formatted text. This is a much simpler version of {@link VerseRenderer}, * only some tags are supported. The supported tags are: * <pre> * @9...@7 for italics * @8 for line break * </pre> * * @param text String with formatting tags * @param mustHaveFormattedHeader when true, the text must start with "@@" to enable formatting, otherwise, the text * is treated as plain. */ public static SpannableStringBuilder render(final String text, final boolean mustHaveFormattedHeader) { return render(text, mustHaveFormattedHeader, null); } /** * Renders a simple formatted text. This is a much simpler version of {@link yuku.alkitab.base.widget.VerseRenderer}, * only some tags are supported. The supported tags are: * <pre> * @9...@7 for italics * @8 for line break * </pre> * * @param text String with formatting tags * @param mustHaveFormattedHeader when true, the text must start with "@@" to enable formatting, otherwise, the text * @param appendToThis If not null, the results are appended to this string instead of newly created. Note that * the contents of this parameter will be modified. */ public static SpannableStringBuilder render(final String text, final boolean mustHaveFormattedHeader, final SpannableStringBuilder appendToThis) { final int text_len = text.length(); if (mustHaveFormattedHeader) { if (text_len < 2 || text.charAt(0) != '@' || text.charAt(1) != '@') { if (appendToThis == null) { return new SpannableStringBuilder(text); } else { appendToThis.append(text); return appendToThis; } } } int pos = 0; if (text_len >= 2 && text.charAt(0) == '@' && text.charAt(1) == '@') { // absorb "@@" at the beginning pos = 2; } int startItalic = -1; final SpannableStringBuilder sb = appendToThis != null? appendToThis: new SpannableStringBuilder(); while (true) { if (pos >= text_len) { break; } int nextAt = text.indexOf('@', pos); if (nextAt == -1) { // no more, just append till the end of everything and exit sb.append(text, pos, text_len); break; } // insert all text until the nextAt if (nextAt != pos) /* optimization */ { sb.append(text, pos, nextAt); pos = nextAt; } pos++; // just in case if (pos >= text_len) { break; } final char marker = text.charAt(pos); switch (marker) { case '9': startItalic = sb.length(); break; case '7': if (startItalic != -1) { sb.setSpan(new StyleSpan(Typeface.ITALIC), startItalic, sb.length(), 0); startItalic = -1; } break; case '8': sb.append("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '^': // known tags but not supported, so let's just be silent break; default: // just print out as-is sb.append("@").append(marker); break; } pos++; } return sb; } }