Skip to content

Commit

Permalink
Images support inside table cells
Browse files Browse the repository at this point in the history
  • Loading branch information
noties committed Apr 28, 2020
1 parent b497f87 commit bc38768
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* `TextLayoutSpan` to obtain `Layout` in which markdown is displayed (applied by `TablePlugin`, more specifically `TableRowSpan` to propagate layout in which cell content is displayed)
* `HtmlEmptyTagReplacement` now is configurable by `HtmlPlugin`, `iframe` handling ([#235])
* `AsyncDrawableLoader` now uses `TextView` width without padding instead of width of canvas
* Support for images inside table cells (`ext-tables` module)

[#235]: https://github.com/noties/Markwon/issues/235

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,20 @@ private static class InlineImageSizeResolver extends ImageSizeResolver {
@NonNull
@Override
public Rect resolveImageSize(@NonNull AsyncDrawable drawable) {
return drawable.getResult().getBounds();

// @since $nap; resolve inline size (scale down if exceed available width)
final Rect imageBounds = drawable.getResult().getBounds();
final int canvasWidth = drawable.getLastKnownCanvasWidth();
final int w = imageBounds.width();

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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableString;
Expand All @@ -23,6 +24,8 @@
import java.util.List;

import io.noties.markwon.core.spans.TextLayoutSpan;
import io.noties.markwon.image.AsyncDrawable;
import io.noties.markwon.image.AsyncDrawableSpan;
import io.noties.markwon.utils.LeadingMarginUtils;
import io.noties.markwon.utils.SpanUtils;

Expand Down Expand Up @@ -71,7 +74,7 @@ public String toString() {

private final TableTheme theme;
private final List<Cell> cells;
private final List<StaticLayout> layouts;
private final List<Layout> layouts;
private final TextPaint textPaint;
private final boolean header;
private final boolean odd;
Expand Down Expand Up @@ -112,7 +115,7 @@ public int getSize(
if (fm != null) {

int max = 0;
for (StaticLayout layout : layouts) {
for (Layout layout : layouts) {
final int height = layout.getHeight();
if (height > max) {
max = height;
Expand Down Expand Up @@ -240,7 +243,7 @@ public void draw(
final int borderTop = isFirstTableRow ? borderWidth : 0;
final int borderBottom = bottom - top - borderWidth;

StaticLayout layout;
Layout layout;
for (int i = 0; i < size; i++) {
layout = layouts.get(i);
final int save = canvas.save();
Expand Down Expand Up @@ -297,34 +300,76 @@ private void makeNewLayouts() {
final int w = (width / columns) - padding;

this.layouts.clear();
Cell cell;
StaticLayout layout;
Spannable spannable;

for (int i = 0, size = cells.size(); i < size; i++) {
makeLayout(i, w, cells.get(i));
}
}

cell = cells.get(i);
private void makeLayout(final int index, final int width, @NonNull final Cell cell) {

if (cell.text instanceof Spannable) {
spannable = (Spannable) cell.text;
} else {
spannable = new SpannableString(cell.text);
final Runnable recreate = new Runnable() {
@Override
public void run() {
final Invalidator invalidator = TableRowSpan.this.invalidator;
if (invalidator != null) {
layouts.remove(index);
makeLayout(index, width, cell);
invalidator.invalidate();
}
}
};

final Spannable spannable;

if (cell.text instanceof Spannable) {
spannable = (Spannable) cell.text;
} else {
spannable = new SpannableString(cell.text);
}

final Layout layout = new StaticLayout(
spannable,
textPaint,
width,
alignment(cell.alignment),
1.0F,
0.0F,
false
);

// @since $nap;
TextLayoutSpan.applyTo(spannable, layout);

// @since $nap;
scheduleAsyncDrawables(spannable, recreate);

layouts.add(index, layout);
}

private void scheduleAsyncDrawables(@NonNull Spannable spannable, @NonNull final Runnable recreate) {

final AsyncDrawableSpan[] spans = spannable.getSpans(0, spannable.length(), AsyncDrawableSpan.class);
if (spans != null
&& spans.length > 0) {

for (AsyncDrawableSpan span : spans) {

layout = new StaticLayout(
spannable,
textPaint,
w,
alignment(cell.alignment),
1.0F,
0.0F,
false
);
final AsyncDrawable drawable = span.getDrawable();

// @since $nap;
TextLayoutSpan.applyTo(spannable, layout);
// it is absolutely crucial to check if drawable is already attached,
// otherwise we would end up with a loop
if (drawable.isAttached()) {
continue;
}

layouts.add(layout);
drawable.setCallback2(new CallbackAdapter() {
@Override
public void invalidateDrawable(@NonNull Drawable who) {
recreate.run();
}
});
}
}
}

Expand All @@ -348,4 +393,21 @@ private static Layout.Alignment alignment(@Alignment int alignment) {
public void invalidator(@Nullable Invalidator invalidator) {
this.invalidator = invalidator;
}

private static abstract class CallbackAdapter implements Drawable.Callback {
@Override
public void invalidateDrawable(@NonNull Drawable who) {

}

@Override
public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {

}

@Override
public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ public MenuOptions menuOptions() {
.add("textColor", this::textColor)
.add("defaultTextColor", this::defaultTextColor)
.add("inlineAndBlock", this::inlineAndBlock)
.add("dark", this::dark);
.add("dark", this::dark)
.add("omega", this::omega);
}

@Override
Expand Down Expand Up @@ -221,6 +222,18 @@ private void dark() {
renderWithBlocksAndInlines(md);
}

private void omega() {
final String md = "" +
"# Block\n\n" +
"$$\n" +
"\\Omega\n" +
"$$\n\n" +
"# Inline\n\n" +
"$$\\Omega$$";

renderWithBlocksAndInlines(md);
}

@NonNull
private static String wrapLatexInSampleMarkdown(@NonNull String latex) {
return "" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import io.noties.debug.Debug;
import io.noties.markwon.Markwon;
import io.noties.markwon.ext.latex.JLatexMathPlugin;
import io.noties.markwon.ext.tables.TablePlugin;
import io.noties.markwon.ext.tables.TableTheme;
import io.noties.markwon.image.ImagesPlugin;
import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin;
import io.noties.markwon.linkify.LinkifyPlugin;
import io.noties.markwon.sample.ActivityWithMenuOptions;
import io.noties.markwon.sample.MenuOptions;
Expand All @@ -25,7 +26,9 @@ public class TableActivity extends ActivityWithMenuOptions {
public MenuOptions menuOptions() {
return MenuOptions.create()
.add("customize", this::customize)
.add("tableAndLinkify", this::tableAndLinkify);
.add("tableAndLinkify", this::tableAndLinkify)
.add("withImages", this::withImages)
.add("withLatex", this::withLatex);
}

private TextView textView;
Expand Down Expand Up @@ -86,4 +89,47 @@ private void tableAndLinkify() {

markwon.setMarkdown(textView, md);
}

private void withImages() {

final String md = "" +
"| HEADER | HEADER |\n" +
"|:----:|:----:|\n" +
"| ![Build](https://github.com/noties/Markwon/workflows/Build/badge.svg) | Build |\n" +
"| Stable | ![stable](https://img.shields.io/maven-central/v/io.noties.markwon/core.svg?label=stable) |\n" +
"| BIG | ![image](https://images.pexels.com/photos/41171/brussels-sprouts-sprouts-cabbage-grocery-41171.jpeg) |\n" +
"\n";

final Markwon markwon = Markwon.builder(this)
.usePlugin(ImagesPlugin.create())
.usePlugin(TablePlugin.create(this))
.build();

markwon.setMarkdown(textView, md);
}

private void withLatex() {

String latex = "\\begin{array}{cc}";
latex += "\\fbox{\\text{A framed box with \\textdbend}}&\\shadowbox{\\text{A shadowed box}}\\cr";
latex += "\\doublebox{\\text{A double framed box}}&\\ovalbox{\\text{An oval framed box}}\\cr";
latex += "\\end{array}";

final String md = "" +
"| HEADER | HEADER |\n" +
"|:----:|:----:|\n" +
"| ![Build](https://github.com/noties/Markwon/workflows/Build/badge.svg) | Build |\n" +
"| Stable | ![stable](https://img.shields.io/maven-central/v/io.noties.markwon/core.svg?label=stable) |\n" +
"| BIG | $$" + latex + "$$ |\n" +
"\n";

final Markwon markwon = Markwon.builder(this)
.usePlugin(MarkwonInlineParserPlugin.create())
.usePlugin(ImagesPlugin.create())
.usePlugin(JLatexMathPlugin.create(textView.getTextSize(), builder -> builder.inlinesEnabled(true)))
.usePlugin(TablePlugin.create(this))
.build();

markwon.setMarkdown(textView, md);
}
}

0 comments on commit bc38768

Please sign in to comment.