package net.jejer.hipda.ui.textstyle; import android.text.Editable; import android.text.Html; import android.text.Spannable; import android.text.style.RelativeSizeSpan; import android.text.style.StrikethroughSpan; import net.jejer.hipda.utils.Logger; import org.xml.sax.XMLReader; import java.lang.reflect.Field; import java.util.HashMap; /** * TagHandler to process customized tag * Created by GreenSkinMonster on 2015-04-23. */ public class HiHtmlTagHandler implements Html.TagHandler { public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) { if (tag.equalsIgnoreCase("strike") || tag.equals("s")) { processStrike(opening, output); } else if (tag.equals("appmark")) { processAppmark(opening, output); } } private void processStrike(boolean opening, Editable output) { int len = output.length(); if (opening) { output.setSpan(new StrikethroughSpan(), len, len, Spannable.SPAN_MARK_MARK); } else { Object obj = getLast(output, StrikethroughSpan.class); int where = output.getSpanStart(obj); output.removeSpan(obj); if (where != len) { output.setSpan(new StrikethroughSpan(), where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } } private void processAppmark(boolean opening, Editable output) { int len = output.length(); if (opening) { output.setSpan(new RelativeSizeSpan(0.75f), len, len, Spannable.SPAN_MARK_MARK); } else { Object obj = getLast(output, RelativeSizeSpan.class); int where = output.getSpanStart(obj); output.removeSpan(obj); if (where != len) { output.setSpan(new RelativeSizeSpan(0.75f), where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } } private Object getLast(Editable text, Class kind) { Object[] objs = text.getSpans(0, text.length(), kind); if (objs.length == 0) { return null; } else { for (int i = objs.length; i > 0; i--) { if (text.getSpanFlags(objs[i - 1]) == Spannable.SPAN_MARK_MARK) { return objs[i - 1]; } } return null; } } final HashMap<String, String> attributes = new HashMap<>(); private void processAttributes(final XMLReader xmlReader) { try { Field elementField = xmlReader.getClass().getDeclaredField("theNewElement"); elementField.setAccessible(true); Object element = elementField.get(xmlReader); Field attsField = element.getClass().getDeclaredField("theAtts"); attsField.setAccessible(true); Object atts = attsField.get(element); Field dataField = atts.getClass().getDeclaredField("data"); dataField.setAccessible(true); String[] data = (String[]) dataField.get(atts); Field lengthField = atts.getClass().getDeclaredField("length"); lengthField.setAccessible(true); int len = (Integer) lengthField.get(atts); /** * MSH: Look for supported attributes and add to hash map. * This is as tight as things can get :) * The data index is "just" where the keys and values are stored. */ for (int i = 0; i < len; i++) attributes.put(data[i * 5 + 1], data[i * 5 + 4]); } catch (Exception e) { Logger.d("Exception", e); } } }