Working with latex plugin
This commit is contained in:
parent
d78b278b86
commit
7af0ead3a3
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
[](https://github.com/noties/Markwon/actions)
|
[](https://github.com/noties/Markwon/actions)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
**Markwon** is a markdown library for Android. It parses markdown
|
**Markwon** is a markdown library for Android. It parses markdown
|
||||||
following [commonmark-spec] with the help of amazing [commonmark-java]
|
following [commonmark-spec] with the help of amazing [commonmark-java]
|
||||||
library and renders result as _Android-native_ Spannables. **No HTML**
|
library and renders result as _Android-native_ Spannables. **No HTML**
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package io.noties.markwon.ext.latex;
|
package io.noties.markwon.ext.latex;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.commonmark.internal.util.Parsing;
|
import org.commonmark.internal.util.Parsing;
|
||||||
import org.commonmark.node.Block;
|
import org.commonmark.node.Block;
|
||||||
import org.commonmark.parser.block.AbstractBlockParser;
|
import org.commonmark.parser.block.AbstractBlockParser;
|
||||||
@ -11,11 +15,21 @@ import org.commonmark.parser.block.ParserState;
|
|||||||
|
|
||||||
public class JLatexMathBlockParser extends AbstractBlockParser {
|
public class JLatexMathBlockParser extends AbstractBlockParser {
|
||||||
|
|
||||||
|
private static final char DOLLAR = '$';
|
||||||
|
private static final char SPACE = ' ';
|
||||||
|
|
||||||
private final JLatexMathBlock block = new JLatexMathBlock();
|
private final JLatexMathBlock block = new JLatexMathBlock();
|
||||||
|
|
||||||
private final StringBuilder builder = new StringBuilder();
|
private final StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
private boolean isClosed;
|
// private boolean isClosed;
|
||||||
|
|
||||||
|
private final int signs;
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
JLatexMathBlockParser(int signs) {
|
||||||
|
this.signs = signs;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Block getBlock() {
|
public Block getBlock() {
|
||||||
@ -24,31 +38,47 @@ public class JLatexMathBlockParser extends AbstractBlockParser {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockContinue tryContinue(ParserState parserState) {
|
public BlockContinue tryContinue(ParserState parserState) {
|
||||||
|
final int nextNonSpaceIndex = parserState.getNextNonSpaceIndex();
|
||||||
|
final CharSequence line = parserState.getLine();
|
||||||
|
final int length = line.length();
|
||||||
|
|
||||||
if (isClosed) {
|
// check for closing
|
||||||
|
if (parserState.getIndent() < Parsing.CODE_BLOCK_INDENT) {
|
||||||
|
Log.e("LTX", String.format("signs: %d, skip dollar: %s", signs, Parsing.skip(DOLLAR, line, nextNonSpaceIndex, length)));
|
||||||
|
// if (Parsing.skip(DOLLAR, line, nextNonSpaceIndex, length) == signs) {
|
||||||
|
if (consume(DOLLAR, line, nextNonSpaceIndex, length) == signs) {
|
||||||
|
// okay, we have our number of signs
|
||||||
|
// let's consume spaces until the end
|
||||||
|
Log.e("LTX", String.format("length; %d, skip spaces: %s", length, Parsing.skip(SPACE, line, nextNonSpaceIndex + signs, length)));
|
||||||
|
if (Parsing.skip(SPACE, line, nextNonSpaceIndex + signs, length) == length) {
|
||||||
return BlockContinue.finished();
|
return BlockContinue.finished();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return BlockContinue.atIndex(parserState.getIndex());
|
return BlockContinue.atIndex(parserState.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addLine(CharSequence line) {
|
public void addLine(CharSequence line) {
|
||||||
|
//
|
||||||
if (builder.length() > 0) {
|
// if (builder.length() > 0) {
|
||||||
builder.append('\n');
|
// builder.append('\n');
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// builder.append(line);
|
||||||
|
//
|
||||||
|
// final int length = builder.length();
|
||||||
|
// if (length > 1) {
|
||||||
|
// isClosed = '$' == builder.charAt(length - 1)
|
||||||
|
// && '$' == builder.charAt(length - 2);
|
||||||
|
// if (isClosed) {
|
||||||
|
// builder.replace(length - 2, length, "");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
Log.e("LTX", "addLine: " + line);
|
||||||
builder.append(line);
|
builder.append(line);
|
||||||
|
builder.append('\n');
|
||||||
final int length = builder.length();
|
|
||||||
if (length > 1) {
|
|
||||||
isClosed = '$' == builder.charAt(length - 1)
|
|
||||||
&& '$' == builder.charAt(length - 2);
|
|
||||||
if (isClosed) {
|
|
||||||
builder.replace(length - 2, length, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -58,37 +88,111 @@ public class JLatexMathBlockParser extends AbstractBlockParser {
|
|||||||
|
|
||||||
public static class Factory extends AbstractBlockParserFactory {
|
public static class Factory extends AbstractBlockParserFactory {
|
||||||
|
|
||||||
|
// private static final Pattern RE = Pattern.compile("(\\${2,}) *$");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser) {
|
public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser) {
|
||||||
|
|
||||||
|
// let's define the spec:
|
||||||
|
// * 0-3 spaces before are allowed (Parsing.CODE_BLOCK_INDENT = 4)
|
||||||
|
// * 2+ subsequent `$` signs
|
||||||
|
// * any optional amount of spaces
|
||||||
|
// * new line
|
||||||
|
// * block is closed when the same amount of opening signs is met
|
||||||
|
|
||||||
final int indent = state.getIndent();
|
final int indent = state.getIndent();
|
||||||
|
|
||||||
// check if it's an indented code block
|
// check if it's an indented code block
|
||||||
if (indent < Parsing.CODE_BLOCK_INDENT) {
|
if (indent >= Parsing.CODE_BLOCK_INDENT) {
|
||||||
|
return BlockStart.none();
|
||||||
|
}
|
||||||
|
|
||||||
final int nextNonSpaceIndex = state.getNextNonSpaceIndex();
|
final int nextNonSpaceIndex = state.getNextNonSpaceIndex();
|
||||||
final CharSequence line = state.getLine();
|
final CharSequence line = state.getLine();
|
||||||
final int length = line.length();
|
final int length = line.length();
|
||||||
// we are looking for 2 `$$` subsequent signs
|
|
||||||
// and immediate new-line or arbitrary number of white spaces (we check for the first one)
|
|
||||||
// so, nextNonSpaceIndex + 2 >= length and both symbols are `$`s
|
|
||||||
final int diff = length - (nextNonSpaceIndex + 2);
|
|
||||||
if (diff >= 0) {
|
|
||||||
// check for both `$`
|
|
||||||
if (line.charAt(nextNonSpaceIndex) == '$'
|
|
||||||
&& line.charAt(nextNonSpaceIndex + 1) == '$') {
|
|
||||||
|
|
||||||
if (diff > 0) {
|
// final int signs = Parsing.skip(DOLLAR, line, nextNonSpaceIndex, length) - 1;
|
||||||
if (!Character.isWhitespace(line.charAt(nextNonSpaceIndex + 2))) {
|
final int signs = consume(DOLLAR, line, nextNonSpaceIndex, length);
|
||||||
|
|
||||||
|
// 2 is minimum
|
||||||
|
if (signs < 2) {
|
||||||
return BlockStart.none();
|
return BlockStart.none();
|
||||||
}
|
}
|
||||||
// consume all until new-line or first not-white-space char
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// consume spaces until the end of the line, if any other content is found -> NONE
|
||||||
|
if (Parsing.skip(SPACE, line, nextNonSpaceIndex + signs, length) != length) {
|
||||||
return BlockStart.none();
|
return BlockStart.none();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.e("LTX", String.format("signs: %s, next: %d, length: %d, line: '%s'", signs, nextNonSpaceIndex, length, line));
|
||||||
|
|
||||||
|
return BlockStart.of(new JLatexMathBlockParser(signs))
|
||||||
|
.atIndex(length + 1);
|
||||||
|
|
||||||
|
|
||||||
|
// // check if it's an indented code block
|
||||||
|
// if (indent < Parsing.CODE_BLOCK_INDENT) {
|
||||||
|
//
|
||||||
|
// final int nextNonSpaceIndex = state.getNextNonSpaceIndex();
|
||||||
|
// final CharSequence line = state.getLine();
|
||||||
|
// final int length = line.length();
|
||||||
|
//
|
||||||
|
// final int signs = Parsing.skip('$', line, nextNonSpaceIndex, length);
|
||||||
|
//
|
||||||
|
// // 2 is minimum
|
||||||
|
// if (signs < 2) {
|
||||||
|
// return BlockStart.none();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // consume spaces until the end of the line, if any other content is found -> NONE
|
||||||
|
// if (Parsing.skip(' ', line, nextNonSpaceIndex + signs, length) != length) {
|
||||||
|
// return BlockStart.none();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//// // consume spaces until the end of the line, if any other content is found -> NONE
|
||||||
|
//// if ((nextNonSpaceIndex + signs) < length) {
|
||||||
|
//// // check if more content is available
|
||||||
|
//// if (Parsing.skip(' ', line,nextNonSpaceIndex + signs, length) != length) {
|
||||||
|
//// return BlockStart.none();
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//
|
||||||
|
//// final Matcher matcher = RE.matcher(line);
|
||||||
|
//// matcher.region(nextNonSpaceIndex, length);
|
||||||
|
//
|
||||||
|
//// Log.e("LATEX", String.format("nonSpace: %d, length: %s, line: '%s'", nextNonSpaceIndex, length, line));
|
||||||
|
//
|
||||||
|
// // we are looking for 2 `$$` subsequent signs
|
||||||
|
// // and immediate new-line or arbitrary number of white spaces (we check for the first one)
|
||||||
|
// // so, nextNonSpaceIndex + 2 >= length and both symbols are `$`s
|
||||||
|
// final int diff = length - (nextNonSpaceIndex + 2);
|
||||||
|
// if (diff >= 0) {
|
||||||
|
// // check for both `$`
|
||||||
|
// if (line.charAt(nextNonSpaceIndex) == '$'
|
||||||
|
// && line.charAt(nextNonSpaceIndex + 1) == '$') {
|
||||||
|
//
|
||||||
|
// if (diff > 0) {
|
||||||
|
// if (!Character.isWhitespace(line.charAt(nextNonSpaceIndex + 2))) {
|
||||||
|
// return BlockStart.none();
|
||||||
|
// }
|
||||||
|
// return BlockStart.of(new JLatexMathBlockParser()).atIndex(nextNonSpaceIndex + 3);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return BlockStart.none();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int consume(char c, @NonNull CharSequence line, int start, int end) {
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
if (c != line.charAt(i)) {
|
||||||
|
return i - start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// all consumed
|
||||||
|
return end - start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.noties.markwon.ext.latex;
|
package io.noties.markwon.ext.latex;
|
||||||
|
|
||||||
|
import android.graphics.Paint;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@ -9,6 +10,7 @@ import android.text.Spanned;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.Px;
|
import androidx.annotation.Px;
|
||||||
@ -26,10 +28,12 @@ import java.util.concurrent.Future;
|
|||||||
import io.noties.markwon.AbstractMarkwonPlugin;
|
import io.noties.markwon.AbstractMarkwonPlugin;
|
||||||
import io.noties.markwon.MarkwonConfiguration;
|
import io.noties.markwon.MarkwonConfiguration;
|
||||||
import io.noties.markwon.MarkwonVisitor;
|
import io.noties.markwon.MarkwonVisitor;
|
||||||
|
import io.noties.markwon.core.MarkwonTheme;
|
||||||
import io.noties.markwon.image.AsyncDrawable;
|
import io.noties.markwon.image.AsyncDrawable;
|
||||||
import io.noties.markwon.image.AsyncDrawableLoader;
|
import io.noties.markwon.image.AsyncDrawableLoader;
|
||||||
import io.noties.markwon.image.AsyncDrawableScheduler;
|
import io.noties.markwon.image.AsyncDrawableScheduler;
|
||||||
import io.noties.markwon.image.AsyncDrawableSpan;
|
import io.noties.markwon.image.AsyncDrawableSpan;
|
||||||
|
import io.noties.markwon.image.ImageSize;
|
||||||
import io.noties.markwon.image.ImageSizeResolver;
|
import io.noties.markwon.image.ImageSizeResolver;
|
||||||
import io.noties.markwon.image.ImageSizeResolverDef;
|
import io.noties.markwon.image.ImageSizeResolverDef;
|
||||||
import io.noties.markwon.inlineparser.MarkwonInlineParser;
|
import io.noties.markwon.inlineparser.MarkwonInlineParser;
|
||||||
@ -129,7 +133,8 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
// if it's $$\n -> block
|
// if it's $$\n -> block
|
||||||
// if it's $$\\dhdsfjh$$ -> inline
|
// if it's $$\\dhdsfjh$$ -> inline
|
||||||
|
|
||||||
// builder.customBlockParserFactory(new JLatexMathBlockParser.Factory());
|
builder.customBlockParserFactory(new JLatexMathBlockParser.Factory());
|
||||||
|
|
||||||
final InlineParserFactory factory = MarkwonInlineParser.factoryBuilder()
|
final InlineParserFactory factory = MarkwonInlineParser.factoryBuilder()
|
||||||
.addInlineProcessor(new JLatexMathInlineProcessor())
|
.addInlineProcessor(new JLatexMathInlineProcessor())
|
||||||
.build();
|
.build();
|
||||||
@ -142,6 +147,8 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void visit(@NonNull MarkwonVisitor visitor, @NonNull JLatexMathBlock jLatexMathBlock) {
|
public void visit(@NonNull MarkwonVisitor visitor, @NonNull JLatexMathBlock jLatexMathBlock) {
|
||||||
|
|
||||||
|
visitor.ensureNewLine();
|
||||||
|
|
||||||
final String latex = jLatexMathBlock.latex();
|
final String latex = jLatexMathBlock.latex();
|
||||||
|
|
||||||
final int length = visitor.length();
|
final int length = visitor.length();
|
||||||
@ -155,15 +162,21 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
final AsyncDrawableSpan span = new AsyncDrawableSpan(
|
final AsyncDrawableSpan span = new AsyncDrawableSpan(
|
||||||
configuration.theme(),
|
configuration.theme(),
|
||||||
new AsyncDrawable(
|
new JLatextAsyncDrawable(
|
||||||
latex,
|
latex,
|
||||||
jLatextAsyncDrawableLoader,
|
jLatextAsyncDrawableLoader,
|
||||||
jLatexImageSizeResolver,
|
jLatexImageSizeResolver,
|
||||||
null),
|
null,
|
||||||
|
true),
|
||||||
AsyncDrawableSpan.ALIGN_CENTER,
|
AsyncDrawableSpan.ALIGN_CENTER,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
visitor.setSpans(length, span);
|
visitor.setSpans(length, span);
|
||||||
|
|
||||||
|
if (visitor.hasNext(jLatexMathBlock)) {
|
||||||
|
visitor.ensureNewLine();
|
||||||
|
visitor.forceNewLine();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
builder.on(JLatexMathNode.class, new MarkwonVisitor.NodeVisitor<JLatexMathNode>() {
|
builder.on(JLatexMathNode.class, new MarkwonVisitor.NodeVisitor<JLatexMathNode>() {
|
||||||
@ -180,13 +193,14 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
final MarkwonConfiguration configuration = visitor.configuration();
|
final MarkwonConfiguration configuration = visitor.configuration();
|
||||||
|
|
||||||
final AsyncDrawableSpan span = new AsyncDrawableSpan(
|
final AsyncDrawableSpan span = new JLatexAsyncDrawableSpan(
|
||||||
configuration.theme(),
|
configuration.theme(),
|
||||||
new AsyncDrawable(
|
new JLatextAsyncDrawable(
|
||||||
latex,
|
latex,
|
||||||
jLatextAsyncDrawableLoader,
|
jLatextAsyncDrawableLoader,
|
||||||
new ImageSizeResolverDef(),
|
new ImageSizeResolverDef(),
|
||||||
null),
|
null,
|
||||||
|
false),
|
||||||
AsyncDrawableSpan.ALIGN_CENTER,
|
AsyncDrawableSpan.ALIGN_CENTER,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
@ -195,77 +209,6 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// private static class LatexInlineProcessor extends InlineProcessor {
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public char specialCharacter() {
|
|
||||||
// return '$';
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Nullable
|
|
||||||
// @Override
|
|
||||||
// protected Node parse() {
|
|
||||||
//
|
|
||||||
// final int start = index;
|
|
||||||
//
|
|
||||||
// index += 1;
|
|
||||||
// if (peek() != '$') {
|
|
||||||
// index = start;
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // must be not $
|
|
||||||
// index += 1;
|
|
||||||
// if (peek() == '$') {
|
|
||||||
// return text("$");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // find next '$$', but not broken with 2(or more) new lines
|
|
||||||
//
|
|
||||||
// boolean dollar = false;
|
|
||||||
// boolean newLine = false;
|
|
||||||
// boolean found = false;
|
|
||||||
//
|
|
||||||
// index += 1;
|
|
||||||
// final int length = input.length();
|
|
||||||
//
|
|
||||||
// while (index < length) {
|
|
||||||
// final char c = peek();
|
|
||||||
// if (c == '\n') {
|
|
||||||
// if (newLine) {
|
|
||||||
// // second new line
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// newLine = true;
|
|
||||||
// dollar = false; // cannot be on another line
|
|
||||||
// } else {
|
|
||||||
// newLine = false;
|
|
||||||
// if (c == '$') {
|
|
||||||
// if (dollar) {
|
|
||||||
// found = true;
|
|
||||||
// // advance
|
|
||||||
// index += 1;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// dollar = true;
|
|
||||||
// } else {
|
|
||||||
// dollar = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// index += 1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (found) {
|
|
||||||
// final JLatexMathBlock block = new JLatexMathBlock();
|
|
||||||
// block.latex(input.substring(start + 2, index - 2));
|
|
||||||
// index += 1;
|
|
||||||
// return block;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown) {
|
public void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown) {
|
||||||
AsyncDrawableScheduler.unschedule(textView);
|
AsyncDrawableScheduler.unschedule(textView);
|
||||||
@ -401,20 +344,53 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
// @since 4.0.1 (background provider can be null)
|
// @since 4.0.1 (background provider can be null)
|
||||||
final BackgroundProvider backgroundProvider = config.backgroundProvider;
|
final BackgroundProvider backgroundProvider = config.backgroundProvider;
|
||||||
|
|
||||||
|
final JLatexMathDrawable jLatexMathDrawable;
|
||||||
|
|
||||||
|
final JLatextAsyncDrawable jLatextAsyncDrawable = (JLatextAsyncDrawable) drawable;
|
||||||
|
if (jLatextAsyncDrawable.isBlock) {
|
||||||
// create JLatexMathDrawable
|
// create JLatexMathDrawable
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
final JLatexMathDrawable jLatexMathDrawable =
|
jLatexMathDrawable =
|
||||||
JLatexMathDrawable.builder(drawable.getDestination())
|
JLatexMathDrawable.builder(drawable.getDestination())
|
||||||
.textSize(config.textSize)
|
.textSize(config.textSize)
|
||||||
.background(backgroundProvider != null ? backgroundProvider.provide() : null)
|
.background(backgroundProvider != null ? backgroundProvider.provide() : null)
|
||||||
.align(config.align)
|
.align(config.align)
|
||||||
.fitCanvas(false /*config.fitCanvas*/)
|
.fitCanvas(config.fitCanvas)
|
||||||
.padding(
|
.padding(
|
||||||
config.paddingHorizontal,
|
config.paddingHorizontal,
|
||||||
config.paddingVertical,
|
config.paddingVertical,
|
||||||
config.paddingHorizontal,
|
config.paddingHorizontal,
|
||||||
config.paddingVertical)
|
config.paddingVertical)
|
||||||
.build();
|
.build();
|
||||||
|
} else {
|
||||||
|
jLatexMathDrawable =
|
||||||
|
JLatexMathDrawable.builder(drawable.getDestination())
|
||||||
|
.textSize(config.textSize)
|
||||||
|
// .background(backgroundProvider != null ? backgroundProvider.provide() : null)
|
||||||
|
// .align(config.align)
|
||||||
|
// .fitCanvas(config.fitCanvas)
|
||||||
|
// .padding(
|
||||||
|
// config.paddingHorizontal,
|
||||||
|
// config.paddingVertical,
|
||||||
|
// config.paddingHorizontal,
|
||||||
|
// config.paddingVertical)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create JLatexMathDrawable
|
||||||
|
// //noinspection ConstantConditions
|
||||||
|
// final JLatexMathDrawable jLatexMathDrawable =
|
||||||
|
// JLatexMathDrawable.builder(drawable.getDestination())
|
||||||
|
// .textSize(config.textSize)
|
||||||
|
// .background(backgroundProvider != null ? backgroundProvider.provide() : null)
|
||||||
|
// .align(config.align)
|
||||||
|
// .fitCanvas(config.fitCanvas)
|
||||||
|
// .padding(
|
||||||
|
// config.paddingHorizontal,
|
||||||
|
// config.paddingVertical,
|
||||||
|
// config.paddingHorizontal,
|
||||||
|
// config.paddingVertical)
|
||||||
|
// .build();
|
||||||
|
|
||||||
// we must post to handler, but also have a way to identify the drawable
|
// we must post to handler, but also have a way to identify the drawable
|
||||||
// for which we are posting (in case of cancellation)
|
// for which we are posting (in case of cancellation)
|
||||||
@ -496,4 +472,66 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
return imageBounds;
|
return imageBounds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class JLatextAsyncDrawable extends AsyncDrawable {
|
||||||
|
|
||||||
|
private final boolean isBlock;
|
||||||
|
|
||||||
|
public JLatextAsyncDrawable(
|
||||||
|
@NonNull String destination,
|
||||||
|
@NonNull AsyncDrawableLoader loader,
|
||||||
|
@NonNull ImageSizeResolver imageSizeResolver,
|
||||||
|
@Nullable ImageSize imageSize,
|
||||||
|
boolean isBlock
|
||||||
|
) {
|
||||||
|
super(destination, loader, imageSizeResolver, imageSize);
|
||||||
|
this.isBlock = isBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class JLatexAsyncDrawableSpan extends AsyncDrawableSpan {
|
||||||
|
|
||||||
|
private final AsyncDrawable drawable;
|
||||||
|
|
||||||
|
public JLatexAsyncDrawableSpan(@NonNull MarkwonTheme theme, @NonNull AsyncDrawable drawable, int alignment, boolean replacementTextIsLink) {
|
||||||
|
super(theme, drawable, alignment, replacementTextIsLink);
|
||||||
|
this.drawable = drawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSize(
|
||||||
|
@NonNull Paint paint,
|
||||||
|
CharSequence text,
|
||||||
|
@IntRange(from = 0) int start,
|
||||||
|
@IntRange(from = 0) int end,
|
||||||
|
@Nullable Paint.FontMetricsInt fm) {
|
||||||
|
|
||||||
|
// if we have no async drawable result - we will just render text
|
||||||
|
|
||||||
|
final int size;
|
||||||
|
|
||||||
|
if (drawable.hasResult()) {
|
||||||
|
|
||||||
|
final Rect rect = drawable.getBounds();
|
||||||
|
|
||||||
|
if (fm != null) {
|
||||||
|
final int half = rect.bottom / 2;
|
||||||
|
fm.ascent = -half;
|
||||||
|
fm.descent = half;
|
||||||
|
|
||||||
|
fm.top = fm.ascent;
|
||||||
|
fm.bottom = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = rect.right;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// NB, no specific text handling (no new lines, etc)
|
||||||
|
size = (int) (paint.measureText(text, start, end) + .5F);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package io.noties.markwon.ext.latex;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.3.0-SNAPSHOT
|
||||||
|
*/
|
||||||
|
public class JLatexMathTheme {
|
||||||
|
|
||||||
|
private float textSize;
|
||||||
|
private float inlineTextSize;
|
||||||
|
private float blockTextSize;
|
||||||
|
|
||||||
|
// TODO: move to a class
|
||||||
|
private JLatexMathPlugin.BackgroundProvider backgroundProvider;
|
||||||
|
private JLatexMathPlugin.BackgroundProvider inlineBackgroundProvider;
|
||||||
|
private JLatexMathPlugin.BackgroundProvider blockBackgroundProvider;
|
||||||
|
|
||||||
|
private boolean blockFitCanvas;
|
||||||
|
// horizontal alignment (when there is additional horizontal space)
|
||||||
|
private int blockAlign;
|
||||||
|
|
||||||
|
private Rect padding;
|
||||||
|
private Rect inlinePadding;
|
||||||
|
private Rect blockPadding;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -4,14 +4,19 @@ import android.app.Activity;
|
|||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.commonmark.node.Node;
|
||||||
|
|
||||||
|
import io.noties.markwon.AbstractMarkwonPlugin;
|
||||||
import io.noties.markwon.Markwon;
|
import io.noties.markwon.Markwon;
|
||||||
import io.noties.markwon.ext.latex.JLatexMathPlugin;
|
import io.noties.markwon.ext.latex.JLatexMathPlugin;
|
||||||
import io.noties.markwon.sample.R;
|
import io.noties.markwon.sample.R;
|
||||||
|
import io.noties.markwon.utils.DumpNodes;
|
||||||
import ru.noties.jlatexmath.JLatexMathDrawable;
|
import ru.noties.jlatexmath.JLatexMathDrawable;
|
||||||
|
|
||||||
public class LatexActivity extends Activity {
|
public class LatexActivity extends Activity {
|
||||||
@ -44,27 +49,33 @@ public class LatexActivity extends Activity {
|
|||||||
// latex += "\\end{array}";
|
// latex += "\\end{array}";
|
||||||
|
|
||||||
final String markdown = "# Example of LaTeX\n\nhello there: $$"
|
final String markdown = "# Example of LaTeX\n\nhello there: $$"
|
||||||
+ latex + "$$\n\n something like **this**";
|
+ latex + "$$ so nice, really?\n\n $$ \n" + latex + "\n$$\n\n $$ \n" + latex + "\n$$";
|
||||||
|
|
||||||
final Markwon markwon = Markwon.builder(this)
|
final Markwon markwon = Markwon.builder(this)
|
||||||
// .usePlugin(JLatexMathPlugin.create(textView.getTextSize(), new JLatexMathPlugin.BuilderConfigure() {
|
.usePlugin(JLatexMathPlugin.create(textView.getTextSize(), new JLatexMathPlugin.BuilderConfigure() {
|
||||||
// @Override
|
@Override
|
||||||
// public void configureBuilder(@NonNull JLatexMathPlugin.Builder builder) {
|
public void configureBuilder(@NonNull JLatexMathPlugin.Builder builder) {
|
||||||
// builder
|
builder
|
||||||
// .backgroundProvider(new JLatexMathPlugin.BackgroundProvider() {
|
.backgroundProvider(new JLatexMathPlugin.BackgroundProvider() {
|
||||||
// @NonNull
|
@NonNull
|
||||||
// @Override
|
@Override
|
||||||
// public Drawable provide() {
|
public Drawable provide() {
|
||||||
// return new ColorDrawable(0x40ff0000);
|
return new ColorDrawable(0x40ff0000);
|
||||||
// }
|
}
|
||||||
// })
|
})
|
||||||
// .fitCanvas(true)
|
.fitCanvas(true)
|
||||||
// .align(JLatexMathDrawable.ALIGN_LEFT)
|
.align(JLatexMathDrawable.ALIGN_CENTER)
|
||||||
// .padding(48)
|
.padding(48)
|
||||||
// ;
|
;
|
||||||
// }
|
}
|
||||||
// }))
|
}))
|
||||||
.usePlugin(JLatexMathPlugin.create(textView.getTextSize()))
|
// .usePlugin(JLatexMathPlugin.create(textView.getTextSize()))
|
||||||
|
.usePlugin(new AbstractMarkwonPlugin() {
|
||||||
|
@Override
|
||||||
|
public void beforeRender(@NonNull Node node) {
|
||||||
|
Log.e("LTX", DumpNodes.dump(node));
|
||||||
|
}
|
||||||
|
})
|
||||||
.build();
|
.build();
|
||||||
//
|
//
|
||||||
// if (true) {
|
// if (true) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user