opt: draw only visible chars for a line

This commit is contained in:
hyb1996
2018-02-21 23:22:21 +08:00
parent ea5f80b437
commit 6ca73623a2
4 changed files with 72 additions and 47 deletions

View File

@@ -8,8 +8,8 @@ android {
applicationId "com.stardust.scriptdroid" applicationId "com.stardust.scriptdroid"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 23 targetSdkVersion 23
versionCode 250 versionCode 251
versionName "3.0.0 Alpha50" versionName "3.1.0 Alpha"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
ndk { ndk {

View File

@@ -23,11 +23,10 @@ import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.support.v7.widget.AppCompatEditText; import android.support.v7.widget.AppCompatEditText;
import android.text.Editable;
import android.text.Layout; import android.text.Layout;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity; import android.view.Gravity;
import android.view.View;
import com.stardust.scriptdroid.ui.edit.theme.Theme; import com.stardust.scriptdroid.ui.edit.theme.Theme;
@@ -128,7 +127,9 @@ public class CodeEditText extends AppCompatEditText {
int fontCount = 0; int fontCount = 0;
int previousColor = mHighlightTokens.getCharColor(lineStart); int previousColor = mHighlightTokens.getCharColor(lineStart);
int previousColorPos = lineStart; int previousColorPos = lineStart;
for (int i = lineStart; i < lineEnd; i++) { int visibleCharStart = getVisibleCharIndex(paint, getScrollX(), lineStart, lineEnd);
int visibleCharEnd = getVisibleCharIndex(paint, getScrollX() + getWidth(), lineStart, lineEnd) + 1;
for (int i = visibleCharStart; i < visibleCharEnd && i < lineEnd; i++) {
fontCount++; fontCount++;
int color = mHighlightTokens.getCharColor(i); int color = mHighlightTokens.getCharColor(i);
if (previousColor != color) { if (previousColor != color) {
@@ -137,13 +138,30 @@ public class CodeEditText extends AppCompatEditText {
previousColorPos = i; previousColorPos = i;
fontCount = 1; fontCount = 1;
} }
if (i == lineEnd - 1) { if (i == visibleCharEnd - 1) {
drawText(canvas, paint, paddingLeft, lineBaseline, lineStart, previousColorPos, previousColorPos + fontCount, previousColor); drawText(canvas, paint, paddingLeft, lineBaseline, lineStart, previousColorPos, previousColorPos + fontCount, previousColor);
} }
} }
} }
private int getVisibleCharIndex(Paint paint, int x, int lineStart, int lineEnd) {
if (x == 0)
return lineStart;
int low = lineStart;
int high = lineEnd - 1;
while (low < high) {
int mid = (high + low) >>> 1;
float midX = paint.measureText(getText(), lineStart, mid + 1);
if (x < midX) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return low;
}
private void drawText(Canvas canvas, Paint paint, int paddingLeft, int lineBaseline, int lineStart, int start, int end, int color) { private void drawText(Canvas canvas, Paint paint, int paddingLeft, int lineBaseline, int lineStart, int start, int end, int color) {
if (start >= end) { if (start >= end) {
return; return;
@@ -162,16 +180,23 @@ public class CodeEditText extends AppCompatEditText {
private long getLineRangeForDraw(Layout layout, Canvas canvas) { private long getLineRangeForDraw(Layout layout, Canvas canvas) {
canvas.save(); canvas.save();
float clipTop = (mScrollView.getScrollY() == 0) ? 0 int scrollY = getRealScrollY();
: getExtendedPaddingTop() + mScrollView.getScrollY() float clipTop = (scrollY == 0) ? 0
: getExtendedPaddingTop() + scrollY
- mScrollView.getPaddingTop(); - mScrollView.getPaddingTop();
canvas.clipRect(0, clipTop, getWidth(), mScrollView.getScrollY() canvas.clipRect(0, clipTop, getWidth(), scrollY
+ mScrollView.getHeight()); + mScrollView.getHeight());
long lineRangeForDraw = LayoutHelper.getLineRangeForDraw(layout, canvas); long lineRangeForDraw = LayoutHelper.getLineRangeForDraw(layout, canvas);
canvas.restore(); canvas.restore();
return lineRangeForDraw; return lineRangeForDraw;
} }
private int getRealScrollY() {
int scrollY = mScrollView.getScrollY();
View parent = (View) mScrollView.getParent();
return scrollY + parent.getScrollY();
}
@Override @Override
protected void onSelectionChanged(int selStart, int selEnd) { protected void onSelectionChanged(int selStart, int selEnd) {
super.onSelectionChanged(selStart, selEnd); super.onSelectionChanged(selStart, selEnd);
@@ -206,7 +231,6 @@ public class CodeEditText extends AppCompatEditText {
public void updateHighlightTokens(JavaScriptHighlighter.HighlightTokens highlightTokens) { public void updateHighlightTokens(JavaScriptHighlighter.HighlightTokens highlightTokens) {
mHighlightTokens = highlightTokens; mHighlightTokens = highlightTokens;
Log.d(LOG_TAG, "tokens = " + highlightTokens); postInvalidate();
invalidate();
} }
} }

View File

@@ -35,10 +35,41 @@ import io.reactivex.Observable;
*/ */
public class CodeEditor extends HVScrollView { public class CodeEditor extends HVScrollView {
public interface CursorChangeCallback {
void onCursorChange(String line, int ch);
}
private CharSequence mReplacement = ""; private CharSequence mReplacement = "";
private String mKeywords; private String mKeywords;
private int mFoundIndex = -1; private int mFoundIndex = -1;
private CodeEditText mCodeEditText;
private PreformEdit mPreformEdit;
private JavaScriptHighlighter mJavaScriptHighlighter;
private Theme mTheme;
public CodeEditor(Context context) {
super(context);
init();
}
public CodeEditor(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setFillViewport(true);
inflate(getContext(), R.layout.code_editor, this);
mCodeEditText = (CodeEditText) findViewById(R.id.code_edit_text);
mPreformEdit = new PreformEdit(mCodeEditText);
mJavaScriptHighlighter = new JavaScriptHighlighter(mTheme, mCodeEditText);
setTheme(Theme.getDefault(getContext()));
}
public Observable<Integer> getLineCount() { public Observable<Integer> getLineCount() {
return Observable.just(mCodeEditText.getLayout().getLineCount()); return Observable.just(mCodeEditText.getLayout().getLineCount());
@@ -100,39 +131,6 @@ public class CodeEditor extends HVScrollView {
} }
public interface CursorChangeCallback {
void onCursorChange(String line, int ch);
}
private CodeEditText mCodeEditText;
private PreformEdit mPreformEdit;
private JavaScriptHighlighter mJavaScriptHighlighter;
private Theme mTheme;
public CodeEditor(Context context) {
super(context);
init();
}
public CodeEditor(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setFillViewport(true);
inflate(getContext(), R.layout.code_editor, this);
mCodeEditText = (CodeEditText) findViewById(R.id.code_edit_text);
mPreformEdit = new PreformEdit(mCodeEditText);
mJavaScriptHighlighter = new JavaScriptHighlighter(mTheme, mCodeEditText);
setTheme(Theme.getDefault(getContext()));
}
public void setTheme(Theme theme) { public void setTheme(Theme theme) {
mTheme = theme; mTheme = theme;
mJavaScriptHighlighter.setTheme(theme); mJavaScriptHighlighter.setTheme(theme);

View File

@@ -24,6 +24,7 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
private int[] mColors; private int[] mColors;
private String mText; private String mText;
private int mCount;
public HighlightTokens(String text) { public HighlightTokens(String text) {
mColors = new int[text.length()]; mColors = new int[text.length()];
@@ -40,6 +41,7 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
for (int i = tokenStart; i < tokenEnd; i++) { for (int i = tokenStart; i < tokenEnd; i++) {
mColors[i] = color; mColors[i] = color;
} }
mCount = tokenEnd;
} }
@Override @Override
@@ -50,7 +52,7 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
} }
public int getCharCount() { public int getCharCount() {
return mColors.length; return mCount;
} }
public String getText() { public String getText() {
@@ -101,9 +103,10 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
int color = mTheme.getColorForToken(token); int color = mTheme.getColorForToken(token);
highlightTokens.addToken(ts.getTokenBeg(), ts.getTokenEnd(), color); highlightTokens.addToken(ts.getTokenBeg(), ts.getTokenEnd(), color);
} }
if (highlightTokens.getCharCount() < sourceString.length()) {
highlightTokens.addToken(highlightTokens.getCharCount(), sourceString.length(), mTheme.getColorForToken(Token.NAME));
}
mCodeEditText.updateHighlightTokens(highlightTokens); mCodeEditText.updateHighlightTokens(highlightTokens);
Log.d("Highlighter", "code = " + sourceString);
Log.d("Highlighter", "tokens = " + highlightTokens);
} }