Update sample configuration for latex block_and_inline renderMode
This commit is contained in:
parent
c7494a9225
commit
a80ff09e15
@ -0,0 +1,50 @@
|
|||||||
|
package io.noties.markwon.ext.latex;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import io.noties.markwon.image.AsyncDrawable;
|
||||||
|
import io.noties.markwon.image.ImageSizeResolver;
|
||||||
|
|
||||||
|
// we must make drawable fit canvas (if specified), but do not keep the ratio whilst scaling up
|
||||||
|
// @since 4.0.0
|
||||||
|
class JLatexBlockImageSizeResolver extends ImageSizeResolver {
|
||||||
|
|
||||||
|
private final boolean fitCanvas;
|
||||||
|
|
||||||
|
JLatexBlockImageSizeResolver(boolean fitCanvas) {
|
||||||
|
this.fitCanvas = fitCanvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Rect resolveImageSize(@NonNull AsyncDrawable drawable) {
|
||||||
|
|
||||||
|
final Rect imageBounds = drawable.getResult().getBounds();
|
||||||
|
final int canvasWidth = drawable.getLastKnownCanvasWidth();
|
||||||
|
|
||||||
|
if (fitCanvas) {
|
||||||
|
|
||||||
|
// we modify bounds only if `fitCanvas` is true
|
||||||
|
final int w = imageBounds.width();
|
||||||
|
|
||||||
|
if (w < canvasWidth) {
|
||||||
|
// increase width and center formula (keep height as-is)
|
||||||
|
return new Rect(0, 0, canvasWidth, imageBounds.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
// @since 4.0.2 we additionally scale down the resulting formula (keeping the ratio)
|
||||||
|
// the thing is - JLatexMathDrawable will do it anyway, but it will modify its own
|
||||||
|
// bounds (which AsyncDrawable won't catch), thus leading to an empty space after the formula
|
||||||
|
if (w > canvasWidth) {
|
||||||
|
// here we must scale it down (keeping the ratio)
|
||||||
|
final float ratio = (float) w / imageBounds.height();
|
||||||
|
final int h = (int) (canvasWidth / ratio + .5F);
|
||||||
|
return new Rect(0, 0, canvasWidth, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return imageBounds;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package io.noties.markwon.ext.latex;
|
||||||
|
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import io.noties.markwon.core.MarkwonTheme;
|
||||||
|
import io.noties.markwon.image.AsyncDrawable;
|
||||||
|
import io.noties.markwon.image.AsyncDrawableSpan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.3.0-SNAPSHOT
|
||||||
|
*/
|
||||||
|
class JLatexInlineAsyncDrawableSpan extends AsyncDrawableSpan {
|
||||||
|
|
||||||
|
private final AsyncDrawable drawable;
|
||||||
|
|
||||||
|
JLatexInlineAsyncDrawableSpan(@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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,5 @@
|
|||||||
package io.noties.markwon.ext.latex;
|
package io.noties.markwon.ext.latex;
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.commonmark.internal.util.Parsing;
|
import org.commonmark.internal.util.Parsing;
|
||||||
@ -13,6 +11,10 @@ import org.commonmark.parser.block.BlockStart;
|
|||||||
import org.commonmark.parser.block.MatchedBlockParser;
|
import org.commonmark.parser.block.MatchedBlockParser;
|
||||||
import org.commonmark.parser.block.ParserState;
|
import org.commonmark.parser.block.ParserState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.3.0-SNAPSHOT (although there was a class with the same name,
|
||||||
|
* which is renamed now to {@link JLatexMathBlockParserLegacy})
|
||||||
|
*/
|
||||||
public class JLatexMathBlockParser extends AbstractBlockParser {
|
public class JLatexMathBlockParser extends AbstractBlockParser {
|
||||||
|
|
||||||
private static final char DOLLAR = '$';
|
private static final char DOLLAR = '$';
|
||||||
@ -22,8 +24,6 @@ public class JLatexMathBlockParser extends AbstractBlockParser {
|
|||||||
|
|
||||||
private final StringBuilder builder = new StringBuilder();
|
private final StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
// private boolean isClosed;
|
|
||||||
|
|
||||||
private final int signs;
|
private final int signs;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
@ -44,12 +44,9 @@ public class JLatexMathBlockParser extends AbstractBlockParser {
|
|||||||
|
|
||||||
// check for closing
|
// check for closing
|
||||||
if (parserState.getIndent() < Parsing.CODE_BLOCK_INDENT) {
|
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) {
|
if (consume(DOLLAR, line, nextNonSpaceIndex, length) == signs) {
|
||||||
// okay, we have our number of signs
|
// okay, we have our number of signs
|
||||||
// let's consume spaces until the end
|
// 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) {
|
if (Parsing.skip(SPACE, line, nextNonSpaceIndex + signs, length) == length) {
|
||||||
return BlockContinue.finished();
|
return BlockContinue.finished();
|
||||||
}
|
}
|
||||||
@ -61,22 +58,6 @@ public class JLatexMathBlockParser extends AbstractBlockParser {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addLine(CharSequence line) {
|
public void addLine(CharSequence line) {
|
||||||
//
|
|
||||||
// if (builder.length() > 0) {
|
|
||||||
// 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');
|
builder.append('\n');
|
||||||
}
|
}
|
||||||
@ -88,8 +69,6 @@ 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) {
|
||||||
|
|
||||||
@ -111,7 +90,6 @@ public class JLatexMathBlockParser extends AbstractBlockParser {
|
|||||||
final CharSequence line = state.getLine();
|
final CharSequence line = state.getLine();
|
||||||
final int length = line.length();
|
final int length = line.length();
|
||||||
|
|
||||||
// final int signs = Parsing.skip(DOLLAR, line, nextNonSpaceIndex, length) - 1;
|
|
||||||
final int signs = consume(DOLLAR, line, nextNonSpaceIndex, length);
|
final int signs = consume(DOLLAR, line, nextNonSpaceIndex, length);
|
||||||
|
|
||||||
// 2 is minimum
|
// 2 is minimum
|
||||||
@ -120,73 +98,16 @@ public class JLatexMathBlockParser extends AbstractBlockParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// consume spaces until the end of the line, if any other content is found -> NONE
|
// consume spaces until the end of the line, if any other content is found -> NONE
|
||||||
// TODO: here we can check mode in which we operate (legacy or not)
|
|
||||||
if (Parsing.skip(SPACE, line, nextNonSpaceIndex + signs, length) != length) {
|
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))
|
return BlockStart.of(new JLatexMathBlockParser(signs))
|
||||||
.atIndex(length + 1);
|
.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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("SameParameterValue")
|
||||||
private static int consume(char c, @NonNull CharSequence line, int start, int end) {
|
private static int consume(char c, @NonNull CharSequence line, int start, int end) {
|
||||||
for (int i = start; i < end; i++) {
|
for (int i = start; i < end; i++) {
|
||||||
if (c != line.charAt(i)) {
|
if (c != line.charAt(i)) {
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
package io.noties.markwon.ext.latex;
|
||||||
|
|
||||||
|
import org.commonmark.node.Block;
|
||||||
|
import org.commonmark.parser.block.AbstractBlockParser;
|
||||||
|
import org.commonmark.parser.block.AbstractBlockParserFactory;
|
||||||
|
import org.commonmark.parser.block.BlockContinue;
|
||||||
|
import org.commonmark.parser.block.BlockStart;
|
||||||
|
import org.commonmark.parser.block.MatchedBlockParser;
|
||||||
|
import org.commonmark.parser.block.ParserState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.3.0-SNAPSHOT (although it is just renamed parser from previous versions)
|
||||||
|
*/
|
||||||
|
public class JLatexMathBlockParserLegacy extends AbstractBlockParser {
|
||||||
|
|
||||||
|
private final JLatexMathBlock block = new JLatexMathBlock();
|
||||||
|
|
||||||
|
private final StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
private boolean isClosed;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block getBlock() {
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockContinue tryContinue(ParserState parserState) {
|
||||||
|
|
||||||
|
if (isClosed) {
|
||||||
|
return BlockContinue.finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
return BlockContinue.atIndex(parserState.getIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLine(CharSequence line) {
|
||||||
|
|
||||||
|
if (builder.length() > 0) {
|
||||||
|
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, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeBlock() {
|
||||||
|
block.latex(builder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Factory extends AbstractBlockParserFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser) {
|
||||||
|
|
||||||
|
final CharSequence line = state.getLine();
|
||||||
|
final int length = line != null
|
||||||
|
? line.length()
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
if (length > 1) {
|
||||||
|
if ('$' == line.charAt(0)
|
||||||
|
&& '$' == line.charAt(1)) {
|
||||||
|
return BlockStart.of(new JLatexMathBlockParserLegacy())
|
||||||
|
.atIndex(state.getIndex() + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BlockStart.none();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
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;
|
||||||
@ -10,7 +9,6 @@ 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;
|
||||||
@ -28,14 +26,11 @@ 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.inlineparser.MarkwonInlineParser;
|
import io.noties.markwon.inlineparser.MarkwonInlineParser;
|
||||||
import ru.noties.jlatexmath.JLatexMathDrawable;
|
import ru.noties.jlatexmath.JLatexMathDrawable;
|
||||||
|
|
||||||
@ -68,7 +63,6 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
BLOCKS_AND_INLINES
|
BLOCKS_AND_INLINES
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: inlines are not moved to a new line when exceed available width.. (api 23, emulator)
|
|
||||||
public interface BuilderConfigure {
|
public interface BuilderConfigure {
|
||||||
void configureBuilder(@NonNull Builder builder);
|
void configureBuilder(@NonNull Builder builder);
|
||||||
}
|
}
|
||||||
@ -78,52 +72,65 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
return new JLatexMathPlugin(builder(textSize).build());
|
return new JLatexMathPlugin(builder(textSize).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.3.0-SNAPSHOT
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static JLatexMathPlugin create(@Px float inlineTextSize, @Px float blockTextSize) {
|
||||||
|
return new JLatexMathPlugin(builder(inlineTextSize, blockTextSize).build());
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static JLatexMathPlugin create(@NonNull Config config) {
|
public static JLatexMathPlugin create(@NonNull Config config) {
|
||||||
return new JLatexMathPlugin(config);
|
return new JLatexMathPlugin(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static JLatexMathPlugin create(float textSize, @NonNull BuilderConfigure builderConfigure) {
|
public static JLatexMathPlugin create(@Px float textSize, @NonNull BuilderConfigure builderConfigure) {
|
||||||
final Builder builder = new Builder(textSize);
|
final Builder builder = builder(textSize);
|
||||||
|
builderConfigure.configureBuilder(builder);
|
||||||
|
return new JLatexMathPlugin(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.3.0-SNAPSHOT
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static JLatexMathPlugin create(
|
||||||
|
@Px float inlineTextSize,
|
||||||
|
@Px float blockTextSize,
|
||||||
|
@NonNull BuilderConfigure builderConfigure) {
|
||||||
|
final Builder builder = builder(inlineTextSize, blockTextSize);
|
||||||
builderConfigure.configureBuilder(builder);
|
builderConfigure.configureBuilder(builder);
|
||||||
return new JLatexMathPlugin(builder.build());
|
return new JLatexMathPlugin(builder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static JLatexMathPlugin.Builder builder(float textSize) {
|
public static JLatexMathPlugin.Builder builder(@Px float textSize) {
|
||||||
return new Builder(textSize);
|
return new Builder(JLatexMathTheme.builder(textSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.3.0-SNAPSHOT
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static JLatexMathPlugin.Builder builder(@Px float inlineTextSize, @Px float blockTextSize) {
|
||||||
|
return new Builder(JLatexMathTheme.builder(inlineTextSize, blockTextSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Config {
|
public static class Config {
|
||||||
|
|
||||||
private final float textSize;
|
// @since 4.3.0-SNAPSHOT
|
||||||
|
private final JLatexMathTheme theme;
|
||||||
|
|
||||||
// @since 4.0.0
|
// @since 4.3.0-SNAPSHOT
|
||||||
private final JLatexMathTheme.BackgroundProvider backgroundProvider;
|
private final RenderMode renderMode;
|
||||||
|
|
||||||
@JLatexMathDrawable.Align
|
|
||||||
private final int align;
|
|
||||||
|
|
||||||
private final boolean fitCanvas;
|
|
||||||
|
|
||||||
// @since 4.0.0
|
|
||||||
private final int paddingHorizontal;
|
|
||||||
|
|
||||||
// @since 4.0.0
|
|
||||||
private final int paddingVertical;
|
|
||||||
|
|
||||||
// @since 4.0.0
|
|
||||||
private final ExecutorService executorService;
|
private final ExecutorService executorService;
|
||||||
|
|
||||||
Config(@NonNull Builder builder) {
|
Config(@NonNull Builder builder) {
|
||||||
this.textSize = builder.textSize;
|
this.theme = builder.theme.build();
|
||||||
this.backgroundProvider = builder.backgroundProvider;
|
this.renderMode = builder.renderMode;
|
||||||
this.align = builder.align;
|
|
||||||
this.fitCanvas = builder.fitCanvas;
|
|
||||||
this.paddingHorizontal = builder.paddingHorizontal;
|
|
||||||
this.paddingVertical = builder.paddingVertical;
|
|
||||||
|
|
||||||
// @since 4.0.0
|
// @since 4.0.0
|
||||||
ExecutorService executorService = builder.executorService;
|
ExecutorService executorService = builder.executorService;
|
||||||
if (executorService == null) {
|
if (executorService == null) {
|
||||||
@ -133,29 +140,46 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Config config;
|
||||||
private final JLatextAsyncDrawableLoader jLatextAsyncDrawableLoader;
|
private final JLatextAsyncDrawableLoader jLatextAsyncDrawableLoader;
|
||||||
private final JLatexImageSizeResolver jLatexImageSizeResolver;
|
private final JLatexBlockImageSizeResolver jLatexBlockImageSizeResolver;
|
||||||
|
private final ImageSizeResolver inlineImageSizeResolver;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
JLatexMathPlugin(@NonNull Config config) {
|
JLatexMathPlugin(@NonNull Config config) {
|
||||||
|
this.config = config;
|
||||||
this.jLatextAsyncDrawableLoader = new JLatextAsyncDrawableLoader(config);
|
this.jLatextAsyncDrawableLoader = new JLatextAsyncDrawableLoader(config);
|
||||||
this.jLatexImageSizeResolver = new JLatexImageSizeResolver(config.fitCanvas);
|
this.jLatexBlockImageSizeResolver = new JLatexBlockImageSizeResolver(config.theme.blockFitCanvas());
|
||||||
|
this.inlineImageSizeResolver = new InlineImageSizeResolver();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configureParser(@NonNull Parser.Builder builder) {
|
public void configureParser(@NonNull Parser.Builder builder) {
|
||||||
|
|
||||||
// what we can do:
|
// TODO: depending on renderMode we should register our parsing here
|
||||||
// [0-3] spaces before block start/end
|
// * for LEGACY -> just add custom block parser
|
||||||
// if it's $$\n -> block
|
// * for INLINE.. -> require InlinePlugin, add inline processor + add block parser
|
||||||
// if it's $$\\dhdsfjh$$ -> inline
|
|
||||||
|
|
||||||
builder.customBlockParserFactory(new JLatexMathBlockParser.Factory());
|
switch (config.renderMode) {
|
||||||
|
|
||||||
final InlineParserFactory factory = MarkwonInlineParser.factoryBuilder()
|
case LEGACY: {
|
||||||
.addInlineProcessor(new JLatexMathInlineProcessor())
|
builder.customBlockParserFactory(new JLatexMathBlockParserLegacy.Factory());
|
||||||
.build();
|
}
|
||||||
builder.inlineParserFactory(factory);
|
break;
|
||||||
|
|
||||||
|
case BLOCKS_AND_INLINES: {
|
||||||
|
builder.customBlockParserFactory(new JLatexMathBlockParser.Factory());
|
||||||
|
|
||||||
|
final InlineParserFactory factory = MarkwonInlineParser.factoryBuilder()
|
||||||
|
.addInlineProcessor(new JLatexMathInlineProcessor())
|
||||||
|
.build();
|
||||||
|
builder.inlineParserFactory(factory);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Unexpected `renderMode`: " + config.renderMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -182,7 +206,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
new JLatextAsyncDrawable(
|
new JLatextAsyncDrawable(
|
||||||
latex,
|
latex,
|
||||||
jLatextAsyncDrawableLoader,
|
jLatextAsyncDrawableLoader,
|
||||||
jLatexImageSizeResolver,
|
jLatexBlockImageSizeResolver,
|
||||||
null,
|
null,
|
||||||
true),
|
true),
|
||||||
AsyncDrawableSpan.ALIGN_CENTER,
|
AsyncDrawableSpan.ALIGN_CENTER,
|
||||||
@ -196,34 +220,39 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
builder.on(JLatexMathNode.class, new MarkwonVisitor.NodeVisitor<JLatexMathNode>() {
|
|
||||||
@Override
|
|
||||||
public void visit(@NonNull MarkwonVisitor visitor, @NonNull JLatexMathNode jLatexMathNode) {
|
|
||||||
final String latex = jLatexMathNode.latex();
|
|
||||||
|
|
||||||
final int length = visitor.length();
|
|
||||||
|
|
||||||
// @since 4.0.2 we cannot append _raw_ latex as a placeholder-text,
|
if (RenderMode.BLOCKS_AND_INLINES == config.renderMode) {
|
||||||
// because Android will draw formula for each line of text, thus
|
|
||||||
// leading to formula duplicated (drawn on each line of text)
|
|
||||||
visitor.builder().append(prepareLatexTextPlaceholder(latex));
|
|
||||||
|
|
||||||
final MarkwonConfiguration configuration = visitor.configuration();
|
builder.on(JLatexMathNode.class, new MarkwonVisitor.NodeVisitor<JLatexMathNode>() {
|
||||||
|
@Override
|
||||||
|
public void visit(@NonNull MarkwonVisitor visitor, @NonNull JLatexMathNode jLatexMathNode) {
|
||||||
|
final String latex = jLatexMathNode.latex();
|
||||||
|
|
||||||
final AsyncDrawableSpan span = new JLatexAsyncDrawableSpan(
|
final int length = visitor.length();
|
||||||
configuration.theme(),
|
|
||||||
new JLatextAsyncDrawable(
|
|
||||||
latex,
|
|
||||||
jLatextAsyncDrawableLoader,
|
|
||||||
new ImageSizeResolverDef(),
|
|
||||||
null,
|
|
||||||
false),
|
|
||||||
AsyncDrawableSpan.ALIGN_CENTER,
|
|
||||||
false);
|
|
||||||
|
|
||||||
visitor.setSpans(length, span);
|
// @since 4.0.2 we cannot append _raw_ latex as a placeholder-text,
|
||||||
}
|
// because Android will draw formula for each line of text, thus
|
||||||
});
|
// leading to formula duplicated (drawn on each line of text)
|
||||||
|
visitor.builder().append(prepareLatexTextPlaceholder(latex));
|
||||||
|
|
||||||
|
final MarkwonConfiguration configuration = visitor.configuration();
|
||||||
|
|
||||||
|
final AsyncDrawableSpan span = new JLatexInlineAsyncDrawableSpan(
|
||||||
|
configuration.theme(),
|
||||||
|
new JLatextAsyncDrawable(
|
||||||
|
latex,
|
||||||
|
jLatextAsyncDrawableLoader,
|
||||||
|
inlineImageSizeResolver,
|
||||||
|
null,
|
||||||
|
false),
|
||||||
|
AsyncDrawableSpan.ALIGN_CENTER,
|
||||||
|
false);
|
||||||
|
|
||||||
|
visitor.setSpans(length, span);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -245,61 +274,30 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
private final float textSize;
|
// @since 4.3.0-SNAPSHOT
|
||||||
|
private final JLatexMathTheme.Builder theme;
|
||||||
|
|
||||||
// @since 4.0.0
|
// @since 4.3.0-SNAPSHOT
|
||||||
private JLatexMathTheme.BackgroundProvider backgroundProvider;
|
private RenderMode renderMode = RenderMode.BLOCKS_AND_INLINES;
|
||||||
|
|
||||||
@JLatexMathDrawable.Align
|
|
||||||
private int align = JLatexMathDrawable.ALIGN_CENTER;
|
|
||||||
|
|
||||||
private boolean fitCanvas = false;
|
|
||||||
|
|
||||||
// @since 4.0.0
|
|
||||||
private int paddingHorizontal;
|
|
||||||
|
|
||||||
// @since 4.0.0
|
|
||||||
private int paddingVertical;
|
|
||||||
|
|
||||||
// @since 4.0.0
|
// @since 4.0.0
|
||||||
private ExecutorService executorService;
|
private ExecutorService executorService;
|
||||||
|
|
||||||
Builder(float textSize) {
|
Builder(@NonNull JLatexMathTheme.Builder builder) {
|
||||||
this.textSize = textSize;
|
this.theme = builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder backgroundProvider(@NonNull JLatexMathTheme.BackgroundProvider backgroundProvider) {
|
public JLatexMathTheme.Builder theme() {
|
||||||
this.backgroundProvider = backgroundProvider;
|
return theme;
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public Builder align(@JLatexMathDrawable.Align int align) {
|
|
||||||
this.align = align;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public Builder fitCanvas(boolean fitCanvas) {
|
|
||||||
this.fitCanvas = fitCanvas;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public Builder padding(@Px int padding) {
|
|
||||||
this.paddingHorizontal = padding;
|
|
||||||
this.paddingVertical = padding;
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0
|
* @since 4.3.0-SNAPSHOT
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder builder(@Px int paddingHorizontal, @Px int paddingVertical) {
|
public Builder renderMode(@NonNull RenderMode renderMode) {
|
||||||
this.paddingHorizontal = paddingHorizontal;
|
this.renderMode = renderMode;
|
||||||
this.paddingVertical = paddingVertical;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +317,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @since 4.0.0
|
// @since 4.0.0
|
||||||
private static class JLatextAsyncDrawableLoader extends AsyncDrawableLoader {
|
static class JLatextAsyncDrawableLoader extends AsyncDrawableLoader {
|
||||||
|
|
||||||
private final Config config;
|
private final Config config;
|
||||||
private final Handler handler = new Handler(Looper.getMainLooper());
|
private final Handler handler = new Handler(Looper.getMainLooper());
|
||||||
@ -358,57 +356,15 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
private void execute() {
|
private void execute() {
|
||||||
|
|
||||||
// @since 4.0.1 (background provider can be null)
|
|
||||||
final JLatexMathTheme.BackgroundProvider backgroundProvider = config.backgroundProvider;
|
|
||||||
|
|
||||||
final JLatexMathDrawable jLatexMathDrawable;
|
final JLatexMathDrawable jLatexMathDrawable;
|
||||||
|
|
||||||
// TODO: obtain real values from theme (for blocks and inlines)
|
|
||||||
final JLatextAsyncDrawable jLatextAsyncDrawable = (JLatextAsyncDrawable) drawable;
|
final JLatextAsyncDrawable jLatextAsyncDrawable = (JLatextAsyncDrawable) drawable;
|
||||||
if (jLatextAsyncDrawable.isBlock) {
|
|
||||||
// create JLatexMathDrawable
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
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();
|
|
||||||
} 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
|
if (jLatextAsyncDrawable.isBlock()) {
|
||||||
// //noinspection ConstantConditions
|
jLatexMathDrawable = createBlockDrawable(jLatextAsyncDrawable.getDestination());
|
||||||
// final JLatexMathDrawable jLatexMathDrawable =
|
} else {
|
||||||
// JLatexMathDrawable.builder(drawable.getDestination())
|
jLatexMathDrawable = createInlineDrawable(jLatextAsyncDrawable.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)
|
||||||
@ -447,109 +403,63 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
public Drawable placeholder(@NonNull AsyncDrawable drawable) {
|
public Drawable placeholder(@NonNull AsyncDrawable drawable) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @since 4.3.0-SNAPSHOT
|
||||||
|
@NonNull
|
||||||
|
private JLatexMathDrawable createBlockDrawable(@NonNull String latex) {
|
||||||
|
|
||||||
|
final JLatexMathTheme theme = config.theme;
|
||||||
|
|
||||||
|
final JLatexMathTheme.BackgroundProvider backgroundProvider = theme.blockBackgroundProvider();
|
||||||
|
final JLatexMathTheme.Padding padding = theme.blockPadding();
|
||||||
|
|
||||||
|
final JLatexMathDrawable.Builder builder = JLatexMathDrawable.builder(latex)
|
||||||
|
.textSize(theme.blockTextSize())
|
||||||
|
.align(theme.blockHorizontalAlignment())
|
||||||
|
.fitCanvas(theme.blockFitCanvas());
|
||||||
|
|
||||||
|
if (backgroundProvider != null) {
|
||||||
|
builder.background(backgroundProvider.provide());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding != null) {
|
||||||
|
builder.padding(padding.left, padding.top, padding.right, padding.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @since 4.3.0-SNAPSHOT
|
||||||
|
@NonNull
|
||||||
|
private JLatexMathDrawable createInlineDrawable(@NonNull String latex) {
|
||||||
|
|
||||||
|
final JLatexMathTheme theme = config.theme;
|
||||||
|
|
||||||
|
final JLatexMathTheme.BackgroundProvider backgroundProvider = theme.inlineBackgroundProvider();
|
||||||
|
final JLatexMathTheme.Padding padding = theme.inlinePadding();
|
||||||
|
|
||||||
|
final JLatexMathDrawable.Builder builder = JLatexMathDrawable.builder(latex)
|
||||||
|
.textSize(theme.inlineTextSize())
|
||||||
|
.fitCanvas(false);
|
||||||
|
|
||||||
|
if (backgroundProvider != null) {
|
||||||
|
builder.background(backgroundProvider.provide());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding != null) {
|
||||||
|
builder.padding(padding.left, padding.top, padding.right, padding.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we must make drawable fit canvas (if specified), but do not keep the ratio whilst scaling up
|
private static class InlineImageSizeResolver extends ImageSizeResolver {
|
||||||
// @since 4.0.0
|
|
||||||
private static class JLatexImageSizeResolver extends ImageSizeResolver {
|
|
||||||
|
|
||||||
private final boolean fitCanvas;
|
|
||||||
|
|
||||||
JLatexImageSizeResolver(boolean fitCanvas) {
|
|
||||||
this.fitCanvas = fitCanvas;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Rect resolveImageSize(@NonNull AsyncDrawable drawable) {
|
public Rect resolveImageSize(@NonNull AsyncDrawable drawable) {
|
||||||
|
return drawable.getResult().getBounds();
|
||||||
final Rect imageBounds = drawable.getResult().getBounds();
|
|
||||||
final int canvasWidth = drawable.getLastKnownCanvasWidth();
|
|
||||||
|
|
||||||
if (fitCanvas) {
|
|
||||||
|
|
||||||
// we modify bounds only if `fitCanvas` is true
|
|
||||||
final int w = imageBounds.width();
|
|
||||||
|
|
||||||
if (w < canvasWidth) {
|
|
||||||
// increase width and center formula (keep height as-is)
|
|
||||||
return new Rect(0, 0, canvasWidth, imageBounds.height());
|
|
||||||
}
|
|
||||||
|
|
||||||
// @since 4.0.2 we additionally scale down the resulting formula (keeping the ratio)
|
|
||||||
// the thing is - JLatexMathDrawable will do it anyway, but it will modify its own
|
|
||||||
// bounds (which AsyncDrawable won't catch), thus leading to an empty space after the formula
|
|
||||||
if (w > canvasWidth) {
|
|
||||||
// here we must scale it down (keeping the ratio)
|
|
||||||
final float ratio = (float) w / imageBounds.height();
|
|
||||||
final int h = (int) (canvasWidth / ratio + .5F);
|
|
||||||
return new Rect(0, 0, canvasWidth, h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,9 +128,9 @@ public abstract class JLatexMathTheme {
|
|||||||
private BackgroundProvider inlineBackgroundProvider;
|
private BackgroundProvider inlineBackgroundProvider;
|
||||||
private BackgroundProvider blockBackgroundProvider;
|
private BackgroundProvider blockBackgroundProvider;
|
||||||
|
|
||||||
private boolean blockFitCanvas;
|
private boolean blockFitCanvas = true;
|
||||||
// horizontal alignment (when there is additional horizontal space)
|
// horizontal alignment (when there is additional horizontal space)
|
||||||
private int blockHorizontalAlignment;
|
private int blockHorizontalAlignment = JLatexMathDrawable.ALIGN_CENTER;
|
||||||
|
|
||||||
private Padding padding;
|
private Padding padding;
|
||||||
private Padding inlinePadding;
|
private Padding inlinePadding;
|
||||||
@ -196,7 +196,7 @@ public abstract class JLatexMathTheme {
|
|||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public JLatexMathTheme build() {
|
public JLatexMathTheme build() {
|
||||||
return null;
|
return new Impl(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
package io.noties.markwon.ext.latex;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import io.noties.markwon.image.AsyncDrawable;
|
||||||
|
import io.noties.markwon.image.AsyncDrawableLoader;
|
||||||
|
import io.noties.markwon.image.ImageSize;
|
||||||
|
import io.noties.markwon.image.ImageSizeResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.3.0-SNAPSHOT
|
||||||
|
*/
|
||||||
|
class JLatextAsyncDrawable extends AsyncDrawable {
|
||||||
|
|
||||||
|
private final boolean isBlock;
|
||||||
|
|
||||||
|
JLatextAsyncDrawable(
|
||||||
|
@NonNull String destination,
|
||||||
|
@NonNull AsyncDrawableLoader loader,
|
||||||
|
@NonNull ImageSizeResolver imageSizeResolver,
|
||||||
|
@Nullable ImageSize imageSize,
|
||||||
|
boolean isBlock
|
||||||
|
) {
|
||||||
|
super(destination, loader, imageSizeResolver, imageSize);
|
||||||
|
this.isBlock = isBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBlock() {
|
||||||
|
return isBlock;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package io.noties.markwon.sample.latex;
|
package io.noties.markwon.sample.latex;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@ -14,7 +14,6 @@ import io.noties.markwon.ext.latex.JLatexMathTheme;
|
|||||||
import io.noties.markwon.sample.ActivityWithMenuOptions;
|
import io.noties.markwon.sample.ActivityWithMenuOptions;
|
||||||
import io.noties.markwon.sample.MenuOptions;
|
import io.noties.markwon.sample.MenuOptions;
|
||||||
import io.noties.markwon.sample.R;
|
import io.noties.markwon.sample.R;
|
||||||
import ru.noties.jlatexmath.JLatexMathDrawable;
|
|
||||||
|
|
||||||
public class LatexActivity extends ActivityWithMenuOptions {
|
public class LatexActivity extends ActivityWithMenuOptions {
|
||||||
|
|
||||||
@ -87,7 +86,7 @@ public class LatexActivity extends ActivityWithMenuOptions {
|
|||||||
private static String wrapLatexInSampleMarkdown(@NonNull String latex) {
|
private static String wrapLatexInSampleMarkdown(@NonNull String latex) {
|
||||||
return "" +
|
return "" +
|
||||||
"# Example of LaTeX\n\n" +
|
"# Example of LaTeX\n\n" +
|
||||||
"(inline): $$" + latex + "$$ so nice, really? Now, (block):\n\n" +
|
"(inline): $$" + latex + "$$ so nice, really-really really-really really-really? Now, (block):\n\n" +
|
||||||
"$$\n" +
|
"$$\n" +
|
||||||
"" + latex + "\n" +
|
"" + latex + "\n" +
|
||||||
"$$\n\n" +
|
"$$\n\n" +
|
||||||
@ -95,23 +94,22 @@ public class LatexActivity extends ActivityWithMenuOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void render(@NonNull String markdown) {
|
private void render(@NonNull String markdown) {
|
||||||
|
|
||||||
|
final float textSize = textView.getTextSize();
|
||||||
|
final Resources r = getResources();
|
||||||
|
|
||||||
final Markwon markwon = Markwon.builder(this)
|
final Markwon markwon = Markwon.builder(this)
|
||||||
.usePlugin(JLatexMathPlugin.create(textView.getTextSize(), new JLatexMathPlugin.BuilderConfigure() {
|
.usePlugin(JLatexMathPlugin.create(textSize, textSize * 1.25F, builder -> {
|
||||||
@Override
|
builder.theme()
|
||||||
public void configureBuilder(@NonNull JLatexMathPlugin.Builder builder) {
|
.inlineBackgroundProvider(() -> new ColorDrawable(0x1000ff00))
|
||||||
builder
|
.blockBackgroundProvider(() -> new ColorDrawable(0x10ff0000))
|
||||||
.backgroundProvider(new JLatexMathTheme.BackgroundProvider() {
|
.blockPadding(JLatexMathTheme.Padding.symmetric(
|
||||||
@NonNull
|
r.getDimensionPixelSize(R.dimen.latex_block_padding_vertical),
|
||||||
@Override
|
r.getDimensionPixelSize(R.dimen.latex_block_padding_horizontal)
|
||||||
public Drawable provide() {
|
));
|
||||||
return new ColorDrawable(0x40ff0000);
|
|
||||||
}
|
// explicitly request LEGACY rendering mode
|
||||||
})
|
// builder.renderMode(JLatexMathPlugin.RenderMode.LEGACY);
|
||||||
.fitCanvas(true)
|
|
||||||
.align(JLatexMathDrawable.ALIGN_CENTER)
|
|
||||||
.padding(48)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}))
|
}))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
5
sample/src/main/res/values/dimens.xml
Normal file
5
sample/src/main/res/values/dimens.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<dimen name="latex_block_padding_vertical">8dip</dimen>
|
||||||
|
<dimen name="latex_block_padding_horizontal">16dip</dimen>
|
||||||
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user