Search in sources :

Example 6 with CharacterStyle

use of android.text.style.CharacterStyle in project WordPress-Android by wordpress-mobile.

the class EditPostActivity method updatePostContent.

// TODO: Replace with contents of the updatePostContentNewEditor() method when legacy editor is dropped
/**
     * Updates post object with content of this fragment
     */
public void updatePostContent(boolean isAutoSave) throws IllegalEditorStateException {
    if (mPost == null) {
        return;
    }
    String title = StringUtils.notNullStr((String) mEditorFragment.getTitle());
    SpannableStringBuilder postContent;
    if (mEditorFragment.getSpannedContent() != null) {
        // needed by the legacy editor to save local drafts
        try {
            postContent = new SpannableStringBuilder(mEditorFragment.getSpannedContent());
        } catch (IndexOutOfBoundsException e) {
            // A core android bug might cause an out of bounds exception, if so we'll just use the current editable
            // See https://code.google.com/p/android/issues/detail?id=5164
            postContent = new SpannableStringBuilder(StringUtils.notNullStr((String) mEditorFragment.getContent()));
        }
    } else {
        postContent = new SpannableStringBuilder(StringUtils.notNullStr((String) mEditorFragment.getContent()));
    }
    String content;
    if (mPost.isLocalDraft()) {
        // remove suggestion spans, they cause craziness in WPHtml.toHTML().
        CharacterStyle[] characterStyles = postContent.getSpans(0, postContent.length(), CharacterStyle.class);
        for (CharacterStyle characterStyle : characterStyles) {
            if (characterStyle instanceof SuggestionSpan) {
                postContent.removeSpan(characterStyle);
            }
        }
        content = WPHtml.toHtml(postContent);
        // replace duplicate <p> tags so there's not duplicates, trac #86
        content = content.replace("<p><p>", "<p>");
        content = content.replace("</p></p>", "</p>");
        content = content.replace("<br><br>", "<br>");
        // sometimes the editor creates extra tags
        content = content.replace("</strong><strong>", "").replace("</em><em>", "").replace("</u><u>", "").replace("</strike><strike>", "").replace("</blockquote><blockquote>", "");
    } else {
        if (!isAutoSave) {
            // Add gallery shortcode
            MediaGalleryImageSpan[] gallerySpans = postContent.getSpans(0, postContent.length(), MediaGalleryImageSpan.class);
            for (MediaGalleryImageSpan gallerySpan : gallerySpans) {
                int start = postContent.getSpanStart(gallerySpan);
                postContent.removeSpan(gallerySpan);
                postContent.insert(start, WPHtml.getGalleryShortcode(gallerySpan));
            }
        }
        WPImageSpan[] imageSpans = postContent.getSpans(0, postContent.length(), WPImageSpan.class);
        if (imageSpans.length != 0) {
            for (WPImageSpan wpIS : imageSpans) {
                MediaFile mediaFile = wpIS.getMediaFile();
                if (mediaFile == null) {
                    continue;
                }
                if (mediaFile.getMediaId() != null) {
                    updateMediaFileOnServer(mediaFile);
                } else {
                    mediaFile.setFileName(wpIS.getImageSource().toString());
                    mediaFile.setFilePath(wpIS.getImageSource().toString());
                }
                int tagStart = postContent.getSpanStart(wpIS);
                if (!isAutoSave) {
                    postContent.removeSpan(wpIS);
                    // network image has a mediaId
                    if (mediaFile.getMediaId() != null && mediaFile.getMediaId().length() > 0) {
                        postContent.insert(tagStart, WPHtml.getContent(wpIS));
                    } else {
                        // local image for upload
                        postContent.insert(tagStart, "<img android-uri=\"" + wpIS.getImageSource().toString() + "\" />");
                    }
                }
            }
        }
        content = postContent.toString();
    }
    mPost.setTitle(title);
    mPost.setContent(content);
    if (!mPost.isLocalDraft()) {
        mPost.setIsLocallyChanged(true);
    }
}
Also used : MediaFile(org.wordpress.android.util.helpers.MediaFile) WPImageSpan(org.wordpress.android.util.helpers.WPImageSpan) SuggestionSpan(android.text.style.SuggestionSpan) MediaGalleryImageSpan(org.wordpress.android.util.helpers.MediaGalleryImageSpan) SpannableStringBuilder(android.text.SpannableStringBuilder) CharacterStyle(android.text.style.CharacterStyle)

Example 7 with CharacterStyle

use of android.text.style.CharacterStyle in project platform_frameworks_base by android.

the class Clock method getSmallTime.

private final CharSequence getSmallTime() {
    Context context = getContext();
    boolean is24 = DateFormat.is24HourFormat(context, ActivityManager.getCurrentUser());
    LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale);
    final char MAGIC1 = '';
    final char MAGIC2 = '';
    SimpleDateFormat sdf;
    String format = mShowSeconds ? is24 ? d.timeFormat_Hms : d.timeFormat_hms : is24 ? d.timeFormat_Hm : d.timeFormat_hm;
    if (!format.equals(mClockFormatString)) {
        mContentDescriptionFormat = new SimpleDateFormat(format);
        /*
             * Search for an unquoted "a" in the format string, so we can
             * add dummy characters around it to let us find it again after
             * formatting and change its size.
             */
        if (mAmPmStyle != AM_PM_STYLE_NORMAL) {
            int a = -1;
            boolean quoted = false;
            for (int i = 0; i < format.length(); i++) {
                char c = format.charAt(i);
                if (c == '\'') {
                    quoted = !quoted;
                }
                if (!quoted && c == 'a') {
                    a = i;
                    break;
                }
            }
            if (a >= 0) {
                // Move a back so any whitespace before AM/PM is also in the alternate size.
                final int b = a;
                while (a > 0 && Character.isWhitespace(format.charAt(a - 1))) {
                    a--;
                }
                format = format.substring(0, a) + MAGIC1 + format.substring(a, b) + "a" + MAGIC2 + format.substring(b + 1);
            }
        }
        mClockFormat = sdf = new SimpleDateFormat(format);
        mClockFormatString = format;
    } else {
        sdf = mClockFormat;
    }
    String result = sdf.format(mCalendar.getTime());
    if (mAmPmStyle != AM_PM_STYLE_NORMAL) {
        int magic1 = result.indexOf(MAGIC1);
        int magic2 = result.indexOf(MAGIC2);
        if (magic1 >= 0 && magic2 > magic1) {
            SpannableStringBuilder formatted = new SpannableStringBuilder(result);
            if (mAmPmStyle == AM_PM_STYLE_GONE) {
                formatted.delete(magic1, magic2 + 1);
            } else {
                if (mAmPmStyle == AM_PM_STYLE_SMALL) {
                    CharacterStyle style = new RelativeSizeSpan(0.7f);
                    formatted.setSpan(style, magic1, magic2, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
                }
                formatted.delete(magic2, magic2 + 1);
                formatted.delete(magic1, magic1 + 1);
            }
            return formatted;
        }
    }
    return result;
}
Also used : Context(android.content.Context) LocaleData(libcore.icu.LocaleData) RelativeSizeSpan(android.text.style.RelativeSizeSpan) SimpleDateFormat(java.text.SimpleDateFormat) SpannableStringBuilder(android.text.SpannableStringBuilder) CharacterStyle(android.text.style.CharacterStyle)

Example 8 with CharacterStyle

use of android.text.style.CharacterStyle in project WordPress-Android by wordpress-mobile.

the class WPHtml method withinParagraph.

private static void withinParagraph(StringBuilder out, Spanned text, int start, int end, int nl, boolean last) {
    int next;
    for (int i = start; i < end; i = next) {
        next = text.nextSpanTransition(i, end, CharacterStyle.class);
        CharacterStyle[] style = text.getSpans(i, next, CharacterStyle.class);
        for (int j = 0; j < style.length; j++) {
            if (style[j] instanceof StyleSpan) {
                int s = ((StyleSpan) style[j]).getStyle();
                if ((s & Typeface.BOLD) != 0) {
                    out.append("<strong>");
                }
                if ((s & Typeface.ITALIC) != 0) {
                    out.append("<em>");
                }
            }
            if (style[j] instanceof TypefaceSpan) {
                String s = ((TypefaceSpan) style[j]).getFamily();
                if (s.equals("monospace")) {
                    out.append("<tt>");
                }
            }
            if (style[j] instanceof SuperscriptSpan) {
                out.append("<sup>");
            }
            if (style[j] instanceof SubscriptSpan) {
                out.append("<sub>");
            }
            if (style[j] instanceof WPUnderlineSpan) {
                out.append("<u>");
            }
            if (style[j] instanceof StrikethroughSpan) {
                out.append("<strike>");
            }
            if (style[j] instanceof URLSpan) {
                out.append("<a href=\"");
                out.append(((URLSpan) style[j]).getURL());
                out.append("\">");
            }
            if (style[j] instanceof MediaGalleryImageSpan) {
                out.append(getGalleryShortcode((MediaGalleryImageSpan) style[j]));
            } else if (style[j] instanceof WPImageSpan && ((WPImageSpan) style[j]).getMediaFile().getMediaId() != null) {
                out.append(getContent((WPImageSpan) style[j]));
            } else if (style[j] instanceof WPImageSpan) {
                out.append("<img src=\"");
                out.append(((WPImageSpan) style[j]).getSource());
                out.append("\" android-uri=\"" + ((WPImageSpan) style[j]).getImageSource().toString() + "\"");
                out.append(" />");
                // Don't output the dummy character underlying the image.
                i = next;
            }
            if (style[j] instanceof AbsoluteSizeSpan) {
                out.append("<font size =\"");
                out.append(((AbsoluteSizeSpan) style[j]).getSize() / 6);
                out.append("\">");
            }
            if (style[j] instanceof ForegroundColorSpan) {
                out.append("<font color =\"#");
                String color = Integer.toHexString(((ForegroundColorSpan) style[j]).getForegroundColor() + 0x01000000);
                while (color.length() < 6) {
                    color = "0" + color;
                }
                out.append(color);
                out.append("\">");
            }
        }
        processWPImage(out, text, i, next);
        for (int j = style.length - 1; j >= 0; j--) {
            if (style[j] instanceof ForegroundColorSpan) {
                out.append("</font>");
            }
            if (style[j] instanceof AbsoluteSizeSpan) {
                out.append("</font>");
            }
            if (style[j] instanceof URLSpan) {
                out.append("</a>");
            }
            if (style[j] instanceof StrikethroughSpan) {
                out.append("</strike>");
            }
            if (style[j] instanceof WPUnderlineSpan) {
                out.append("</u>");
            }
            if (style[j] instanceof SubscriptSpan) {
                out.append("</sub>");
            }
            if (style[j] instanceof SuperscriptSpan) {
                out.append("</sup>");
            }
            if (style[j] instanceof TypefaceSpan) {
                String s = ((TypefaceSpan) style[j]).getFamily();
                if (s.equals("monospace")) {
                    out.append("</tt>");
                }
            }
            if (style[j] instanceof StyleSpan) {
                int s = ((StyleSpan) style[j]).getStyle();
                if ((s & Typeface.BOLD) != 0) {
                    out.append("</strong>");
                }
                if ((s & Typeface.ITALIC) != 0) {
                    out.append("</em>");
                }
            }
        }
    }
    String p = last ? "" : "</p>\n<p>";
    if (nl == 1) {
        out.append("<br>\n");
    } else if (nl == 2) {
        out.append(p);
    } else {
        for (int i = 2; i < nl; i++) {
            out.append("<br>");
        }
        out.append(p);
    }
}
Also used : SuperscriptSpan(android.text.style.SuperscriptSpan) ForegroundColorSpan(android.text.style.ForegroundColorSpan) WPUnderlineSpan(org.wordpress.android.util.helpers.WPUnderlineSpan) WPImageSpan(org.wordpress.android.util.helpers.WPImageSpan) SpannableString(android.text.SpannableString) URLSpan(android.text.style.URLSpan) CharacterStyle(android.text.style.CharacterStyle) AbsoluteSizeSpan(android.text.style.AbsoluteSizeSpan) StyleSpan(android.text.style.StyleSpan) SubscriptSpan(android.text.style.SubscriptSpan) MediaGalleryImageSpan(org.wordpress.android.util.helpers.MediaGalleryImageSpan) TypefaceSpan(android.text.style.TypefaceSpan) StrikethroughSpan(android.text.style.StrikethroughSpan)

Example 9 with CharacterStyle

use of android.text.style.CharacterStyle in project platform_frameworks_base by android.

the class TextLine method handleRun.

/**
     * Utility function for handling a unidirectional run.  The run must not
     * contain tabs but can contain styles.
     *
     *
     * @param start the line-relative start of the run
     * @param measureLimit the offset to measure to, between start and limit inclusive
     * @param limit the limit of the run
     * @param runIsRtl true if the run is right-to-left
     * @param c the canvas, can be null
     * @param x the end of the run closest to the leading margin
     * @param top the top of the line
     * @param y the baseline
     * @param bottom the bottom of the line
     * @param fmi receives metrics information, can be null
     * @param needWidth true if the width is required
     * @return the signed width of the run based on the run direction; only
     * valid if needWidth is true
     */
private float handleRun(int start, int measureLimit, int limit, boolean runIsRtl, Canvas c, float x, int top, int y, int bottom, FontMetricsInt fmi, boolean needWidth) {
    // Case of an empty line, make sure we update fmi according to mPaint
    if (start == measureLimit) {
        TextPaint wp = mWorkPaint;
        wp.set(mPaint);
        if (fmi != null) {
            expandMetricsFromPaint(fmi, wp);
        }
        return 0f;
    }
    if (mSpanned == null) {
        TextPaint wp = mWorkPaint;
        wp.set(mPaint);
        final int mlimit = measureLimit;
        return handleText(wp, start, limit, start, limit, runIsRtl, c, x, top, y, bottom, fmi, needWidth || mlimit < measureLimit, mlimit);
    }
    mMetricAffectingSpanSpanSet.init(mSpanned, mStart + start, mStart + limit);
    mCharacterStyleSpanSet.init(mSpanned, mStart + start, mStart + limit);
    // Shaping needs to take into account context up to metric boundaries,
    // but rendering needs to take into account character style boundaries.
    // So we iterate through metric runs to get metric bounds,
    // then within each metric run iterate through character style runs
    // for the run bounds.
    final float originalX = x;
    for (int i = start, inext; i < measureLimit; i = inext) {
        TextPaint wp = mWorkPaint;
        wp.set(mPaint);
        inext = mMetricAffectingSpanSpanSet.getNextTransition(mStart + i, mStart + limit) - mStart;
        int mlimit = Math.min(inext, measureLimit);
        ReplacementSpan replacement = null;
        for (int j = 0; j < mMetricAffectingSpanSpanSet.numberOfSpans; j++) {
            // empty by construction. This special case in getSpans() explains the >= & <= tests
            if ((mMetricAffectingSpanSpanSet.spanStarts[j] >= mStart + mlimit) || (mMetricAffectingSpanSpanSet.spanEnds[j] <= mStart + i))
                continue;
            MetricAffectingSpan span = mMetricAffectingSpanSpanSet.spans[j];
            if (span instanceof ReplacementSpan) {
                replacement = (ReplacementSpan) span;
            } else {
                // We might have a replacement that uses the draw
                // state, otherwise measure state would suffice.
                span.updateDrawState(wp);
            }
        }
        if (replacement != null) {
            x += handleReplacement(replacement, wp, i, mlimit, runIsRtl, c, x, top, y, bottom, fmi, needWidth || mlimit < measureLimit);
            continue;
        }
        for (int j = i, jnext; j < mlimit; j = jnext) {
            jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + inext) - mStart;
            int offset = Math.min(jnext, mlimit);
            wp.set(mPaint);
            for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) {
                // Intentionally using >= and <= as explained above
                if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + offset) || (mCharacterStyleSpanSet.spanEnds[k] <= mStart + j))
                    continue;
                CharacterStyle span = mCharacterStyleSpanSet.spans[k];
                span.updateDrawState(wp);
            }
            // Only draw hyphen on last run in line
            if (jnext < mLen) {
                wp.setHyphenEdit(0);
            }
            x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x, top, y, bottom, fmi, needWidth || jnext < measureLimit, offset);
        }
    }
    return x - originalX;
}
Also used : ReplacementSpan(android.text.style.ReplacementSpan) Paint(android.graphics.Paint) MetricAffectingSpan(android.text.style.MetricAffectingSpan) CharacterStyle(android.text.style.CharacterStyle)

Example 10 with CharacterStyle

use of android.text.style.CharacterStyle in project android_frameworks_base by crdroidandroid.

the class TextLine method handleRun.

/**
     * Utility function for handling a unidirectional run.  The run must not
     * contain tabs but can contain styles.
     *
     *
     * @param start the line-relative start of the run
     * @param measureLimit the offset to measure to, between start and limit inclusive
     * @param limit the limit of the run
     * @param runIsRtl true if the run is right-to-left
     * @param c the canvas, can be null
     * @param x the end of the run closest to the leading margin
     * @param top the top of the line
     * @param y the baseline
     * @param bottom the bottom of the line
     * @param fmi receives metrics information, can be null
     * @param needWidth true if the width is required
     * @return the signed width of the run based on the run direction; only
     * valid if needWidth is true
     */
private float handleRun(int start, int measureLimit, int limit, boolean runIsRtl, Canvas c, float x, int top, int y, int bottom, FontMetricsInt fmi, boolean needWidth) {
    // Case of an empty line, make sure we update fmi according to mPaint
    if (start == measureLimit) {
        TextPaint wp = mWorkPaint;
        wp.set(mPaint);
        if (fmi != null) {
            expandMetricsFromPaint(fmi, wp);
        }
        return 0f;
    }
    if (mSpanned == null) {
        TextPaint wp = mWorkPaint;
        wp.set(mPaint);
        final int mlimit = measureLimit;
        return handleText(wp, start, limit, start, limit, runIsRtl, c, x, top, y, bottom, fmi, needWidth || mlimit < measureLimit, mlimit);
    }
    mMetricAffectingSpanSpanSet.init(mSpanned, mStart + start, mStart + limit);
    mCharacterStyleSpanSet.init(mSpanned, mStart + start, mStart + limit);
    // Shaping needs to take into account context up to metric boundaries,
    // but rendering needs to take into account character style boundaries.
    // So we iterate through metric runs to get metric bounds,
    // then within each metric run iterate through character style runs
    // for the run bounds.
    final float originalX = x;
    for (int i = start, inext; i < measureLimit; i = inext) {
        TextPaint wp = mWorkPaint;
        wp.set(mPaint);
        inext = mMetricAffectingSpanSpanSet.getNextTransition(mStart + i, mStart + limit) - mStart;
        int mlimit = Math.min(inext, measureLimit);
        ReplacementSpan replacement = null;
        for (int j = 0; j < mMetricAffectingSpanSpanSet.numberOfSpans; j++) {
            // empty by construction. This special case in getSpans() explains the >= & <= tests
            if ((mMetricAffectingSpanSpanSet.spanStarts[j] >= mStart + mlimit) || (mMetricAffectingSpanSpanSet.spanEnds[j] <= mStart + i))
                continue;
            MetricAffectingSpan span = mMetricAffectingSpanSpanSet.spans[j];
            if (span instanceof ReplacementSpan) {
                replacement = (ReplacementSpan) span;
            } else {
                // We might have a replacement that uses the draw
                // state, otherwise measure state would suffice.
                span.updateDrawState(wp);
            }
        }
        if (replacement != null) {
            x += handleReplacement(replacement, wp, i, mlimit, runIsRtl, c, x, top, y, bottom, fmi, needWidth || mlimit < measureLimit);
            continue;
        }
        for (int j = i, jnext; j < mlimit; j = jnext) {
            jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + inext) - mStart;
            int offset = Math.min(jnext, mlimit);
            wp.set(mPaint);
            for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) {
                // Intentionally using >= and <= as explained above
                if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + offset) || (mCharacterStyleSpanSet.spanEnds[k] <= mStart + j))
                    continue;
                CharacterStyle span = mCharacterStyleSpanSet.spans[k];
                span.updateDrawState(wp);
            }
            // Only draw hyphen on last run in line
            if (jnext < mLen) {
                wp.setHyphenEdit(0);
            }
            x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x, top, y, bottom, fmi, needWidth || jnext < measureLimit, offset);
        }
    }
    return x - originalX;
}
Also used : ReplacementSpan(android.text.style.ReplacementSpan) Paint(android.graphics.Paint) MetricAffectingSpan(android.text.style.MetricAffectingSpan) CharacterStyle(android.text.style.CharacterStyle)

Aggregations

CharacterStyle (android.text.style.CharacterStyle)58 SpannableStringBuilder (android.text.SpannableStringBuilder)22 ForegroundColorSpan (android.text.style.ForegroundColorSpan)18 RelativeSizeSpan (android.text.style.RelativeSizeSpan)18 Paint (android.graphics.Paint)16 AbsoluteSizeSpan (android.text.style.AbsoluteSizeSpan)14 StyleSpan (android.text.style.StyleSpan)13 TextPaint (android.text.TextPaint)12 ParcelableSpan (android.text.ParcelableSpan)9 SpannableString (android.text.SpannableString)9 Spanned (android.text.Spanned)9 StrikethroughSpan (android.text.style.StrikethroughSpan)9 TypefaceSpan (android.text.style.TypefaceSpan)9 UnderlineSpan (android.text.style.UnderlineSpan)9 BackgroundColorSpan (android.text.style.BackgroundColorSpan)8 ReplacementSpan (android.text.style.ReplacementSpan)8 SubscriptSpan (android.text.style.SubscriptSpan)8 SuperscriptSpan (android.text.style.SuperscriptSpan)8 URLSpan (android.text.style.URLSpan)8 ImageSpan (android.text.style.ImageSpan)7