package org.emdev.common.textmarkup; import org.ebookdroid.droids.fb2.codec.FB2Page; import android.graphics.Paint; import android.text.TextPaint; import org.emdev.common.fonts.typeface.TypefaceEx; import org.emdev.common.textmarkup.line.LineFixedWhiteSpace; import org.emdev.common.textmarkup.line.LineWhiteSpace; public class CustomTextPaint extends TextPaint { private static final ThreadLocal<char[]> chars = new ThreadLocal<char[]>(); public final int key; public final LineWhiteSpace space; public final LineFixedWhiteSpace fixedSpace; public final LineFixedWhiteSpace emptyLine; public final LineFixedWhiteSpace pOffset; public final LineFixedWhiteSpace vOffset; private final float[] standard = new float[256]; private final float[] latin1 = new float[256]; private final float[] rus = new float[256]; private final float[] punct = new float[256]; public CustomTextPaint(final int key, final TypefaceEx face, final int textSize) { super(); this.key = key; setTextSize(textSize); setTypeface(face.typeface); setFakeBoldText(face.fakeBold); setAntiAlias(true); setFilterBitmap(true); setDither(true); initMeasures(); space = new LineWhiteSpace(standard[0x20], textSize); fixedSpace = new LineFixedWhiteSpace(standard[0x20], textSize); emptyLine = new LineFixedWhiteSpace(FB2Page.PAGE_WIDTH - 2 * FB2Page.MARGIN_X, textSize); pOffset = new LineFixedWhiteSpace(textSize * 3, textSize); vOffset = new LineFixedWhiteSpace(FB2Page.PAGE_WIDTH / 8, textSize); } public CustomTextPaint(final Paint parent, final int key, final TypefaceEx face, final int textSize) { super(parent); this.key = key; setTextSize(textSize); setTypeface(face.typeface); setFakeBoldText(face.fakeBold); setAntiAlias(parent.isAntiAlias()); setFilterBitmap(parent.isFilterBitmap()); setDither(parent.isDither()); initMeasures(); space = new LineWhiteSpace(standard[0x20], textSize); fixedSpace = new LineFixedWhiteSpace(standard[0x20], textSize); emptyLine = new LineFixedWhiteSpace(FB2Page.PAGE_WIDTH - 2 * FB2Page.MARGIN_X, textSize); pOffset = new LineFixedWhiteSpace(textSize * 3, textSize); vOffset = new LineFixedWhiteSpace(FB2Page.PAGE_WIDTH / 8, textSize); } private void initMeasures() { initMeasures(0x0000, standard, 0x20, 0xFF); initMeasures(0x0100, latin1); initMeasures(0x0400, rus); initMeasures(0x2000, punct, 0x00, 0x0B); initMeasures(0x2000, punct, 0x10, 0x27); initMeasures(0x2000, punct, 0x30, 0x3F); initMeasures(0x2000, punct, 0x40, 0x4F); initMeasures(0x2000, punct, 0x50, 0x5F); initMeasures(0x2000, punct, 0xD0, 0xDF); initMeasures(0x2000, punct, 0xE0, 0xEF); initMeasures(0x2000, punct, 0xF0, 0xF0); } private void initMeasures(final int codepage, final float[] widths) { final char[] chars = new char[256]; for (int i = 0; i < 256; i++) { chars[i] = (char) (i + codepage); } this.getTextWidths(chars, 0, chars.length, widths); } private void initMeasures(final int codepage, final float[] widths, final int start, final int end) { final int length = end - start + 1; final char[] chars = new char[length]; for (int i = 0; i < length; i++) { chars[i] = (char) (i + start + codepage); } final float[] w = new float[length]; this.getTextWidths(chars, 0, length, w); System.arraycopy(w, 0, widths, start, length); } @Override public float measureText(final char[] text, final int index, final int count) { float sum = 0; int tempIndex = 0; char[] temp = chars.get(); for (int i = index, n = 0; n < count; i++, n++) { final char ch = text[i]; final int code = ch; final int enc = code & 0xFFFFFF00; switch (enc) { case 0x0000: sum += standard[code & 0x00FF]; break; case 0x0100: sum += latin1[code & 0x00FF]; break; case 0x0400: sum += rus[code & 0x00FF]; break; case 0x2000: float w = punct[code & 0x00FF]; if (w == 0) { w = punct[code & 0x00FF] = super.measureText(text, i, 1); if (w == 0) { w = punct[code & 0x00FF] = standard[0x20]; } } sum += w; break; default: if (temp == null) { temp = new char[256]; chars.set(temp); } if (tempIndex < temp.length) { temp[tempIndex++] = ch; } else { sum += super.measureText(temp, 0, temp.length); tempIndex = 0; } } } if (tempIndex > 0) { sum += super.measureText(temp, 0, tempIndex); } return sum; } }