package com.mozz.htmlnative.utils; import android.content.Context; import android.graphics.Color; import android.support.annotation.NonNull; import android.util.TypedValue; import com.mozz.htmlnative.common.PixelValue; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * @author Yang Tao, 17/2/24. */ public final class ParametersUtils { private static final String TAG = ParametersUtils.class.getSimpleName(); private static final Set<String> sColorNameMap; static { sColorNameMap = new HashSet<>(); sColorNameMap.add("black"); sColorNameMap.add("darkgray"); sColorNameMap.add("gray"); sColorNameMap.add("lightgray"); sColorNameMap.add("white"); sColorNameMap.add("red"); sColorNameMap.add("green"); sColorNameMap.add("blue"); sColorNameMap.add("yellow"); sColorNameMap.add("cyan"); sColorNameMap.add("magenta"); sColorNameMap.add("aqua"); sColorNameMap.add("fuchsia"); sColorNameMap.add("darkgrey"); sColorNameMap.add("grey"); sColorNameMap.add("lightgrey"); sColorNameMap.add("lime"); sColorNameMap.add("maroon"); sColorNameMap.add("navy"); sColorNameMap.add("olive"); sColorNameMap.add("purple"); sColorNameMap.add("silver"); sColorNameMap.add("teal"); } private ParametersUtils() { } private static float screenDensity = -1.f; public static void init(Context context) { float density = context.getResources().getDisplayMetrics().density; updateScreenDensity(density); } private static void updateScreenDensity(float density) { screenDensity = density; } public static int toInt(Object object) throws IllegalArgumentException { if (object instanceof Integer) { return (int) object; } else { return Integer.valueOf(object.toString()); } } public static float toFloat(Object object) throws IllegalArgumentException { if (object instanceof Float) { return (float) object; } else { String fStr = object.toString(); boolean isPercentage = false; if (fStr.endsWith("%")) { fStr = fStr.substring(0, fStr.length() - 1); isPercentage = true; } float f = Float.valueOf(fStr); return isPercentage ? f / 100 : f; } } public static PixelValue toPixel(Object object) throws IllegalArgumentException { int unit = TypedValue.COMPLEX_UNIT_PX; if (object instanceof String) { String string = (String) object; StringBuilder unitString = new StringBuilder(); int i = string.length() - 1; for (; i > 0; i--) { char c = string.charAt(i); if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { unitString.append(c); } else { break; } } unit = getUnit(unitString.reverse().toString()); float value = toFloat(string.substring(0, i + 1)); return new PixelValue(value, unit); } else { return new PixelValue(toFloat(object), unit); } } @PixelValue.PixelUnit public static int getUnit(String s) { switch (s.toLowerCase()) { case "px": return TypedValue.COMPLEX_UNIT_PX; case "dp": case "dip": return TypedValue.COMPLEX_UNIT_DIP; case "sp": return TypedValue.COMPLEX_UNIT_SP; case "em": return PixelValue.EM; default: return PixelValue.UNSET; } } public static float getPercent(String s) throws IllegalArgumentException { if (s.endsWith("%")) { return toInt(s.substring(0, s.length() - 1)) / 100.f; } else { throw new IllegalArgumentException("not a percent format " + s); } } public static PixelValue[] toPixels(String ss) throws IllegalArgumentException { String[] single = splitByEmpty(ss); PixelValue[] pixelValues = new PixelValue[single.length]; int i = 0; for (String s : single) { String trimS = s.trim(); pixelValues[i++] = toPixel(trimS); } return pixelValues; } public static boolean toBoolean(Object object) throws IllegalArgumentException { if (object instanceof Boolean) { return (boolean) object; } else { return Boolean.valueOf(object.toString().trim()); } } public static int toColor(@NonNull Object colorObj) throws IllegalArgumentException { String colorString = colorObj.toString().trim(); if (colorString.length() == 0) { throw new IllegalArgumentException("empty color string for parse"); } // handle the #* like color if (colorString.charAt(0) == '#') { // handle the #000000 like color string if (colorString.length() > 4) { return Color.parseColor(colorString); } else if (colorString.length() == 4) { long color = 0; for (int i = 0; i < 3; i++) { char c = colorString.charAt(i + 1); int cI; if (c >= 'a' && c <= 'z') { cI = c - 'a' + 10; } else if (c >= 'A' && c <= 'Z') { cI = c - 'A' + 10; } else if (c >= '0' && c <= '9') { cI = c - '0'; } else { throw new IllegalArgumentException("unknown color string " + colorString); } color |= (cI * 16 + cI) << (3 - i - 1) * 8; } return (int) (color | 0x00000000ff000000); } else { throw new IllegalArgumentException("unknown color string " + colorString); } } else { /** handle the color like 'red', 'green' ect. see {@link https://www.w3.org/TR/CSS2/syndata .html#tokenization} */ return Color.parseColor(colorString); } } public static String toHtmlColorString(int color) { return "#" + Integer.toHexString(color & 0x00ffffff); } public static boolean isHtmlColorString(String string) { return sColorNameMap.contains(string); } public static Map<String, String> parseStyle(@NonNull String styleString) { Map<String, String> pas = new HashMap<>(); StringBuilder sb = new StringBuilder(); String key = null; for (int i = 0; i < styleString.length(); i++) { char c = styleString.charAt(i); if (c == ';') { pas.put(key, sb.toString()); sb.setLength(0); } else if (c == ':') { key = sb.toString(); sb.setLength(0); } else { if (c == ' ' || c == '\r' || c == '\n' || c == '\t' || c == '\f' || c == '\b') { continue; } sb.append(c); } } if (key != null) { pas.put(key, sb.toString()); } return pas; } public static float dpToPx(float px) { if (screenDensity == -1.f) { throw new IllegalStateException("you must call init() first"); } return (int) (screenDensity * px + 0.5f); } public static float pxToDp(float dp) { if (screenDensity == -1.f) { throw new IllegalStateException("you must call init() first"); } return dp / screenDensity; } public static int emToPx(float em) { return (int) (em * 16.f); } public static float pxToEm(int px) { return px / 16.f; } public static String[] splitByEmpty(String s) { return s.trim().split("\\s+"); } }