Better default values + ObjectsPool
This commit is contained in:
parent
6f5fd08de4
commit
d280095281
@ -7,6 +7,7 @@ import ru.noties.markwon.spans.BlockQuoteSpan;
|
|||||||
import ru.noties.markwon.spans.BulletListItemSpan;
|
import ru.noties.markwon.spans.BulletListItemSpan;
|
||||||
import ru.noties.markwon.spans.CodeSpan;
|
import ru.noties.markwon.spans.CodeSpan;
|
||||||
import ru.noties.markwon.spans.HeadingSpan;
|
import ru.noties.markwon.spans.HeadingSpan;
|
||||||
|
import ru.noties.markwon.spans.ThematicBreakSpan;
|
||||||
|
|
||||||
public class SpannableConfiguration {
|
public class SpannableConfiguration {
|
||||||
|
|
||||||
@ -23,12 +24,14 @@ public class SpannableConfiguration {
|
|||||||
private final CodeSpan.Config codeConfig;
|
private final CodeSpan.Config codeConfig;
|
||||||
private final BulletListItemSpan.Config bulletListConfig;
|
private final BulletListItemSpan.Config bulletListConfig;
|
||||||
private final HeadingSpan.Config headingConfig;
|
private final HeadingSpan.Config headingConfig;
|
||||||
|
private final ThematicBreakSpan.Config thematicConfig;
|
||||||
|
|
||||||
private SpannableConfiguration(Builder builder) {
|
private SpannableConfiguration(Builder builder) {
|
||||||
this.blockQuoteConfig = builder.blockQuoteConfig;
|
this.blockQuoteConfig = builder.blockQuoteConfig;
|
||||||
this.codeConfig = builder.codeConfig;
|
this.codeConfig = builder.codeConfig;
|
||||||
this.bulletListConfig = builder.bulletListConfig;
|
this.bulletListConfig = builder.bulletListConfig;
|
||||||
this.headingConfig = builder.headingConfig;
|
this.headingConfig = builder.headingConfig;
|
||||||
|
this.thematicConfig = builder.thematicConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockQuoteSpan.Config getBlockQuoteConfig() {
|
public BlockQuoteSpan.Config getBlockQuoteConfig() {
|
||||||
@ -47,6 +50,10 @@ public class SpannableConfiguration {
|
|||||||
return headingConfig;
|
return headingConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ThematicBreakSpan.Config getThematicConfig() {
|
||||||
|
return thematicConfig;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
@ -54,6 +61,7 @@ public class SpannableConfiguration {
|
|||||||
private CodeSpan.Config codeConfig;
|
private CodeSpan.Config codeConfig;
|
||||||
private BulletListItemSpan.Config bulletListConfig;
|
private BulletListItemSpan.Config bulletListConfig;
|
||||||
private HeadingSpan.Config headingConfig;
|
private HeadingSpan.Config headingConfig;
|
||||||
|
private ThematicBreakSpan.Config thematicConfig;
|
||||||
|
|
||||||
public Builder(Context context) {
|
public Builder(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@ -79,13 +87,18 @@ public class SpannableConfiguration {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setThematicConfig(@NonNull ThematicBreakSpan.Config thematicConfig) {
|
||||||
|
this.thematicConfig = thematicConfig;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// todo, change to something more reliable
|
// todo, change to something more reliable
|
||||||
public SpannableConfiguration build() {
|
public SpannableConfiguration build() {
|
||||||
if (blockQuoteConfig == null) {
|
if (blockQuoteConfig == null) {
|
||||||
blockQuoteConfig = new BlockQuoteSpan.Config(
|
blockQuoteConfig = new BlockQuoteSpan.Config(
|
||||||
px(16),
|
px(16),
|
||||||
px(4),
|
0,
|
||||||
0xFFcccccc
|
0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (codeConfig == null) {
|
if (codeConfig == null) {
|
||||||
@ -99,6 +112,9 @@ public class SpannableConfiguration {
|
|||||||
if (headingConfig == null) {
|
if (headingConfig == null) {
|
||||||
headingConfig = new HeadingSpan.Config(px(1), 0);
|
headingConfig = new HeadingSpan.Config(px(1), 0);
|
||||||
}
|
}
|
||||||
|
if (thematicConfig == null) {
|
||||||
|
thematicConfig = new ThematicBreakSpan.Config(0, px(2));
|
||||||
|
}
|
||||||
return new SpannableConfiguration(this);
|
return new SpannableConfiguration(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,10 +194,9 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
|||||||
|
|
||||||
newLine();
|
newLine();
|
||||||
|
|
||||||
// todo, new lines...
|
|
||||||
final int length = builder.length();
|
final int length = builder.length();
|
||||||
builder.append(' '); // without space it won't render
|
builder.append(' '); // without space it won't render
|
||||||
builder.setSpan(new ThematicBreakSpan(), length, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
setSpan(length, new ThematicBreakSpan(configuration.getThematicConfig()));
|
||||||
|
|
||||||
newLine();
|
newLine();
|
||||||
}
|
}
|
||||||
|
@ -11,15 +11,17 @@ import android.text.style.LeadingMarginSpan;
|
|||||||
|
|
||||||
public class BlockQuoteSpan implements LeadingMarginSpan {
|
public class BlockQuoteSpan implements LeadingMarginSpan {
|
||||||
|
|
||||||
|
private static final int DEF_COLOR_ALPHA = 50;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
public static class Config {
|
public static class Config {
|
||||||
|
|
||||||
final int totalWidth;
|
final int totalWidth;
|
||||||
final int quoteWidth;
|
final int quoteWidth; // by default 1/4 of width
|
||||||
final int quoteColor; // by default textColor with 0.1 alpha
|
final int quoteColor; // by default textColor with 0.2 alpha
|
||||||
|
|
||||||
public Config(
|
public Config(
|
||||||
@IntRange(from = 0) int totalWidth,
|
@IntRange(from = 1) int totalWidth,
|
||||||
@IntRange(from = 0) int quoteWidth,
|
@IntRange(from = 0) int quoteWidth,
|
||||||
@ColorInt int quoteColor) {
|
@ColorInt int quoteColor) {
|
||||||
this.totalWidth = totalWidth;
|
this.totalWidth = totalWidth;
|
||||||
@ -29,16 +31,13 @@ public class BlockQuoteSpan implements LeadingMarginSpan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Config config;
|
private final Config config;
|
||||||
private final Rect rect = new Rect();
|
private final Rect rect = ObjectsPool.rect();
|
||||||
private final Paint paint = new Paint();
|
private final Paint paint = ObjectsPool.paint();
|
||||||
private final int indent;
|
private final int indent;
|
||||||
|
|
||||||
public BlockQuoteSpan(@NonNull Config config, int indent) {
|
public BlockQuoteSpan(@NonNull Config config, int indent) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.indent = indent;
|
this.indent = indent;
|
||||||
|
|
||||||
paint.setStyle(Paint.Style.FILL);
|
|
||||||
paint.setColor(config.quoteColor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -61,13 +60,25 @@ public class BlockQuoteSpan implements LeadingMarginSpan {
|
|||||||
boolean first,
|
boolean first,
|
||||||
Layout layout) {
|
Layout layout) {
|
||||||
|
|
||||||
final int save = c.save();
|
final int width;
|
||||||
try {
|
if (config.quoteWidth == 0) {
|
||||||
|
width = (int) (config.totalWidth / 4.F + .5F);
|
||||||
|
} else {
|
||||||
|
width = config.quoteWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int color;
|
||||||
|
if (config.quoteColor != 0) {
|
||||||
|
color = config.quoteColor;
|
||||||
|
} else {
|
||||||
|
color = ColorUtils.applyAlpha(p.getColor(), DEF_COLOR_ALPHA);
|
||||||
|
}
|
||||||
|
paint.setStyle(Paint.Style.FILL);
|
||||||
|
paint.setColor(color);
|
||||||
|
|
||||||
final int left = config.totalWidth * (indent - 1);
|
final int left = config.totalWidth * (indent - 1);
|
||||||
rect.set(left, top, left + config.quoteWidth, bottom);
|
rect.set(left, top, left + width, bottom);
|
||||||
|
|
||||||
c.drawRect(rect, paint);
|
c.drawRect(rect, paint);
|
||||||
} finally {
|
|
||||||
c.restoreToCount(save);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,10 @@ public class BulletListItemSpan implements LeadingMarginSpan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Config config;
|
private final Config config;
|
||||||
private final Paint paint = new Paint();
|
|
||||||
|
|
||||||
private RectF circle;
|
private final Paint paint = ObjectsPool.paint();
|
||||||
private Rect rectangle;
|
private final RectF circle = ObjectsPool.rectF();
|
||||||
|
private final Rect rectangle = ObjectsPool.rect();
|
||||||
|
|
||||||
private final int blockIndent;
|
private final int blockIndent;
|
||||||
private final int level;
|
private final int level;
|
||||||
@ -101,11 +101,6 @@ public class BulletListItemSpan implements LeadingMarginSpan {
|
|||||||
if (level == 0
|
if (level == 0
|
||||||
|| level == 1) {
|
|| level == 1) {
|
||||||
|
|
||||||
// ensure we have circle rectF
|
|
||||||
if (circle == null) {
|
|
||||||
circle = new RectF();
|
|
||||||
}
|
|
||||||
|
|
||||||
circle.set(l, t, r, b);
|
circle.set(l, t, r, b);
|
||||||
|
|
||||||
final Paint.Style style = level == 0
|
final Paint.Style style = level == 0
|
||||||
@ -116,11 +111,6 @@ public class BulletListItemSpan implements LeadingMarginSpan {
|
|||||||
c.drawOval(circle, paint);
|
c.drawOval(circle, paint);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// ensure rectangle
|
|
||||||
if (rectangle == null) {
|
|
||||||
rectangle = new Rect();
|
|
||||||
}
|
|
||||||
|
|
||||||
rectangle.set(l, t, r, b);
|
rectangle.set(l, t, r, b);
|
||||||
|
|
||||||
paint.setStyle(Paint.Style.FILL);
|
paint.setStyle(Paint.Style.FILL);
|
||||||
|
@ -14,14 +14,7 @@ import android.text.style.MetricAffectingSpan;
|
|||||||
|
|
||||||
public class CodeSpan extends MetricAffectingSpan implements LeadingMarginSpan {
|
public class CodeSpan extends MetricAffectingSpan implements LeadingMarginSpan {
|
||||||
|
|
||||||
// the thing is.. we cannot use replacementSpan, because it won't let us create multiline code..
|
private static final int DEF_COLOR_ALPHA = 25;
|
||||||
// and we want new lines when we do not fit the width
|
|
||||||
// plus it complicates the copying
|
|
||||||
|
|
||||||
// replacement span is great because we can have additional paddings & can actually get a hold
|
|
||||||
// of Canvas to draw background, but it implies a lot of manual text handling
|
|
||||||
|
|
||||||
// also, we can reuse Rect instance as long as we apply our dimensions in each draw call
|
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
public static class Config {
|
public static class Config {
|
||||||
@ -87,17 +80,14 @@ public class CodeSpan extends MetricAffectingSpan implements LeadingMarginSpan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Config config;
|
private final Config config;
|
||||||
private final Rect rect = new Rect();
|
private final Rect rect = ObjectsPool.rect();
|
||||||
private final Paint paint = new Paint();
|
private final Paint paint = ObjectsPool.paint();
|
||||||
|
|
||||||
private final boolean multiline;
|
private final boolean multiline;
|
||||||
|
|
||||||
public CodeSpan(@NonNull Config config, boolean multiline) {
|
public CodeSpan(@NonNull Config config, boolean multiline) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.multiline = multiline;
|
this.multiline = multiline;
|
||||||
|
|
||||||
paint.setStyle(Paint.Style.FILL);
|
|
||||||
paint.setTypeface(config.typeface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -111,7 +101,7 @@ public class CodeSpan extends MetricAffectingSpan implements LeadingMarginSpan {
|
|||||||
if (!multiline) {
|
if (!multiline) {
|
||||||
final int color;
|
final int color;
|
||||||
if (config.backgroundColor == 0) {
|
if (config.backgroundColor == 0) {
|
||||||
color = applyAlpha(ds.getColor(), 25);
|
color = ColorUtils.applyAlpha(ds.getColor(), DEF_COLOR_ALPHA);
|
||||||
} else {
|
} else {
|
||||||
color = config.backgroundColor;
|
color = config.backgroundColor;
|
||||||
}
|
}
|
||||||
@ -141,167 +131,16 @@ public class CodeSpan extends MetricAffectingSpan implements LeadingMarginSpan {
|
|||||||
|
|
||||||
final int color;
|
final int color;
|
||||||
if (config.backgroundColor == 0) {
|
if (config.backgroundColor == 0) {
|
||||||
color = applyAlpha(p.getColor(), 25);
|
color = ColorUtils.applyAlpha(p.getColor(), DEF_COLOR_ALPHA);
|
||||||
} else {
|
} else {
|
||||||
color = config.backgroundColor;
|
color = config.backgroundColor;
|
||||||
}
|
}
|
||||||
|
paint.setStyle(Paint.Style.FILL);
|
||||||
paint.setColor(color);
|
paint.setColor(color);
|
||||||
|
|
||||||
rect.set(x, top, c.getWidth(), bottom);
|
rect.set(x, top, c.getWidth(), bottom);
|
||||||
|
|
||||||
c.drawRect(rect, paint);
|
c.drawRect(rect, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// paint.setTextSize(p.getTextSize());
|
|
||||||
//
|
|
||||||
// final int left = (int) (x + .5F);
|
|
||||||
//
|
|
||||||
// final int right;
|
|
||||||
// if (multiline) {
|
|
||||||
// right = c.getWidth();
|
|
||||||
// } else {
|
|
||||||
// final int width = (config.paddingHorizontal * 2) + (int) (paint.measureText(text, start, end) + .5F);
|
|
||||||
// right = left + width;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// rect.set(left, top, right, bottom);
|
|
||||||
//
|
|
||||||
// // okay, draw background first
|
|
||||||
// drawBackground(c);
|
|
||||||
|
|
||||||
// then, if any, draw borders
|
|
||||||
// drawBorders(c, this.start == start, this.end == end);
|
|
||||||
|
|
||||||
// final int color;
|
|
||||||
// if (config.textColor == 0) {
|
|
||||||
// color = p.getColor();
|
|
||||||
// } else {
|
|
||||||
// color = config.textColor;
|
|
||||||
// }
|
|
||||||
// paint.setColor(color);
|
|
||||||
//
|
|
||||||
// // draw text
|
|
||||||
// // y center position
|
|
||||||
// final int b = bottom - ((bottom - top) / 2) - (int) ((paint.descent() + paint.ascent()) / 2);
|
|
||||||
// canvas.drawText(text, start, end, x + config.paddingHorizontal, b, paint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int applyAlpha(int color, int alpha) {
|
|
||||||
return (color & 0x00FFFFFF) | (alpha << 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public int getSize(
|
|
||||||
// @NonNull Paint p,
|
|
||||||
// CharSequence text,
|
|
||||||
// @IntRange(from = 0) int start,
|
|
||||||
// @IntRange(from = 0) int end,
|
|
||||||
// @Nullable Paint.FontMetricsInt fm
|
|
||||||
// ) {
|
|
||||||
//
|
|
||||||
// paint.setTextSize(p.getTextSize());
|
|
||||||
//
|
|
||||||
// final int width = (config.paddingHorizontal * 2) + (int) (paint.measureText(text, start, end) + .5F);
|
|
||||||
//
|
|
||||||
// if (fm != null) {
|
|
||||||
// // we add a padding top & bottom
|
|
||||||
// final float ratio = .62F; // golden ratio, there is no much point of moving this to config... it seems a bit `specific`...
|
|
||||||
// fm.ascent = fm.ascent - (config.paddingVertical);
|
|
||||||
// fm.descent = (int) (-fm.ascent * ratio);
|
|
||||||
// fm.top = fm.ascent;
|
|
||||||
// fm.bottom = fm.descent;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return width;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public void draw(
|
|
||||||
// @NonNull Canvas canvas,
|
|
||||||
// CharSequence text,
|
|
||||||
// @IntRange(from = 0) int start,
|
|
||||||
// @IntRange(from = 0) int end,
|
|
||||||
// float x,
|
|
||||||
// int top,
|
|
||||||
// int y,
|
|
||||||
// int bottom,
|
|
||||||
// @NonNull Paint p
|
|
||||||
// ) {
|
|
||||||
//
|
|
||||||
// paint.setTextSize(p.getTextSize());
|
|
||||||
//
|
|
||||||
// final int left = (int) (x + .5F);
|
|
||||||
//
|
|
||||||
// final int right;
|
|
||||||
// if (multiline) {
|
|
||||||
// right = canvas.getWidth();
|
|
||||||
// } else {
|
|
||||||
// final int width = (config.paddingHorizontal * 2) + (int) (paint.measureText(text, start, end) + .5F);
|
|
||||||
// right = left + width;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// rect.set(left, top, right, bottom);
|
|
||||||
//
|
|
||||||
// // okay, draw background first
|
|
||||||
// drawBackground(canvas);
|
|
||||||
//
|
|
||||||
// // then, if any, draw borders
|
|
||||||
// drawBorders(canvas, this.start == start, this.end == end);
|
|
||||||
//
|
|
||||||
// final int color;
|
|
||||||
// if (config.textColor == 0) {
|
|
||||||
// color = p.getColor();
|
|
||||||
// } else {
|
|
||||||
// color = config.textColor;
|
|
||||||
// }
|
|
||||||
// paint.setColor(color);
|
|
||||||
//
|
|
||||||
// // draw text
|
|
||||||
// // y center position
|
|
||||||
// final int b = bottom - ((bottom - top) / 2) - (int) ((paint.descent() + paint.ascent()) / 2);
|
|
||||||
// canvas.drawText(text, start, end, x + config.paddingHorizontal, b, paint);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private void drawBackground(Canvas canvas) {
|
|
||||||
// final int color = config.backgroundColor;
|
|
||||||
// if (color != 0) {
|
|
||||||
// paint.setColor(color);
|
|
||||||
// canvas.drawRect(rect, paint);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private void drawBorders(Canvas canvas, boolean top, boolean bottom) {
|
|
||||||
//
|
|
||||||
// final int color = config.borderColor;
|
|
||||||
// final int width = config.borderWidth;
|
|
||||||
// if (color == 0
|
|
||||||
// || width == 0) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// paint.setColor(color);
|
|
||||||
//
|
|
||||||
// // left and right are always drawn
|
|
||||||
//
|
|
||||||
// // LEFT
|
|
||||||
// borderRect.set(rect.left, rect.top, rect.left + width, rect.bottom);
|
|
||||||
// canvas.drawRect(borderRect, paint);
|
|
||||||
//
|
|
||||||
// // RIGHT
|
|
||||||
// borderRect.set(rect.right - width, rect.top, rect.right, rect.bottom);
|
|
||||||
// canvas.drawRect(borderRect, paint);
|
|
||||||
//
|
|
||||||
// // TOP
|
|
||||||
// if (top) {
|
|
||||||
// borderRect.set(rect.left, rect.top, rect.right, rect.top + width);
|
|
||||||
// canvas.drawRect(borderRect, paint);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // BOTTOM
|
|
||||||
// if (bottom) {
|
|
||||||
// borderRect.set(rect.left, rect.bottom - width, rect.right, rect.bottom);
|
|
||||||
// canvas.drawRect(borderRect, paint);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package ru.noties.markwon.spans;
|
||||||
|
|
||||||
|
class ColorUtils {
|
||||||
|
|
||||||
|
static int applyAlpha(int color, int alpha) {
|
||||||
|
return (color & 0x00FFFFFF) | (alpha << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ColorUtils() {
|
||||||
|
}
|
||||||
|
}
|
@ -18,10 +18,12 @@ public class HeadingSpan extends MetricAffectingSpan implements LeadingMarginSpa
|
|||||||
2.F, 1.5F, 1.17F, 1.F, .83F, .67F,
|
2.F, 1.5F, 1.17F, 1.F, .83F, .67F,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static final int DEF_BREAK_COLOR_ALPHA = 127;
|
||||||
|
|
||||||
public static class Config {
|
public static class Config {
|
||||||
|
|
||||||
final int breakHeight; // by default stroke width
|
final int breakHeight; // by default stroke width
|
||||||
final int breakColor; // by default -> textColor
|
final int breakColor; // by default -> textColor with 0.5 alpha
|
||||||
|
|
||||||
public Config(@IntRange(from = 0) int breakHeight, @ColorInt int breakColor) {
|
public Config(@IntRange(from = 0) int breakHeight, @ColorInt int breakColor) {
|
||||||
this.breakHeight = breakHeight;
|
this.breakHeight = breakHeight;
|
||||||
@ -30,8 +32,8 @@ public class HeadingSpan extends MetricAffectingSpan implements LeadingMarginSpa
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Config config;
|
private final Config config;
|
||||||
private final Rect rect = new Rect();
|
private final Rect rect = ObjectsPool.rect();
|
||||||
private final Paint paint = new Paint();
|
private final Paint paint = ObjectsPool.paint();
|
||||||
private final int level;
|
private final int level;
|
||||||
private final int end;
|
private final int end;
|
||||||
|
|
||||||
@ -39,8 +41,6 @@ public class HeadingSpan extends MetricAffectingSpan implements LeadingMarginSpa
|
|||||||
this.config = config;
|
this.config = config;
|
||||||
this.level = level - 1;
|
this.level = level - 1;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
|
|
||||||
paint.setStyle(Paint.Style.FILL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -77,7 +77,7 @@ public class HeadingSpan extends MetricAffectingSpan implements LeadingMarginSpa
|
|||||||
final int color;
|
final int color;
|
||||||
final int breakHeight;
|
final int breakHeight;
|
||||||
if (config.breakColor == 0) {
|
if (config.breakColor == 0) {
|
||||||
color = p.getColor();
|
color = ColorUtils.applyAlpha(p.getColor(), DEF_BREAK_COLOR_ALPHA);
|
||||||
} else {
|
} else {
|
||||||
color = config.breakColor;
|
color = config.breakColor;
|
||||||
}
|
}
|
||||||
@ -86,6 +86,7 @@ public class HeadingSpan extends MetricAffectingSpan implements LeadingMarginSpa
|
|||||||
} else {
|
} else {
|
||||||
breakHeight = config.breakHeight;
|
breakHeight = config.breakHeight;
|
||||||
}
|
}
|
||||||
|
paint.setStyle(Paint.Style.FILL);
|
||||||
paint.setColor(color);
|
paint.setColor(color);
|
||||||
|
|
||||||
rect.set(x, bottom - breakHeight, c.getWidth(), bottom);
|
rect.set(x, bottom - breakHeight, c.getWidth(), bottom);
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package ru.noties.markwon.spans;
|
||||||
|
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
|
||||||
|
class ObjectsPool {
|
||||||
|
|
||||||
|
// maybe it's premature optimization, but as all the drawing is done in one thread
|
||||||
|
// and we apply needed values before actual drawing it's (I assume) safe to reuse some frequently used objects
|
||||||
|
|
||||||
|
// if one of the spans need some really specific handling for Paint object (like colorFilters, masks, etc)
|
||||||
|
// it should instantiate own instance of it
|
||||||
|
|
||||||
|
private static final Rect RECT = new Rect();
|
||||||
|
private static final RectF RECT_F = new RectF();
|
||||||
|
private static final Paint PAINT = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
|
||||||
|
static Rect rect() {
|
||||||
|
return RECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static RectF rectF() {
|
||||||
|
return RECT_F;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Paint paint() {
|
||||||
|
return PAINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObjectsPool() {
|
||||||
|
}
|
||||||
|
}
|
@ -3,23 +3,62 @@ package ru.noties.markwon.spans;
|
|||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.support.annotation.ColorInt;
|
||||||
|
import android.support.annotation.IntRange;
|
||||||
import android.text.Layout;
|
import android.text.Layout;
|
||||||
import android.text.style.LeadingMarginSpan;
|
import android.text.style.LeadingMarginSpan;
|
||||||
|
|
||||||
public class ThematicBreakSpan implements LeadingMarginSpan {
|
public class ThematicBreakSpan implements LeadingMarginSpan {
|
||||||
|
|
||||||
|
private static final int DEF_COLOR_ALPHA = 127;
|
||||||
|
|
||||||
|
public static class Config {
|
||||||
|
|
||||||
|
final int color; // by default textColor with 0.5 alpha
|
||||||
|
final int height; // by default strokeWidth of paint
|
||||||
|
|
||||||
|
public Config(@ColorInt int color, @IntRange(from = 0) int height) {
|
||||||
|
this.color = color;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Config config;
|
||||||
|
private final Rect rect = ObjectsPool.rect();
|
||||||
|
private final Paint paint = ObjectsPool.paint();
|
||||||
|
|
||||||
|
public ThematicBreakSpan(Config config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getLeadingMargin(boolean first) {
|
public int getLeadingMargin(boolean first) {
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) {
|
public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) {
|
||||||
final int middle = (bottom - top) / 2;
|
|
||||||
final Rect rect = new Rect(0, top + middle - 2, c.getWidth(), top + middle + 2);
|
final int middle = top + ((bottom - top) / 2);
|
||||||
final Paint paint = new Paint();
|
|
||||||
|
final int color;
|
||||||
|
if (config.color == 0) {
|
||||||
|
color = ColorUtils.applyAlpha(p.getColor(), DEF_COLOR_ALPHA);
|
||||||
|
} else {
|
||||||
|
color = config.color;
|
||||||
|
}
|
||||||
|
paint.setColor(color);
|
||||||
paint.setStyle(Paint.Style.FILL);
|
paint.setStyle(Paint.Style.FILL);
|
||||||
paint.setColor(0x80000000);
|
|
||||||
|
final int height;
|
||||||
|
if (config.height == 0) {
|
||||||
|
height = (int) (p.getStrokeWidth() + .5F);
|
||||||
|
} else {
|
||||||
|
height = config.height;
|
||||||
|
}
|
||||||
|
final int halfHeight = (int) (height / 2.F + .5F);
|
||||||
|
|
||||||
|
rect.set(x, middle - halfHeight, c.getWidth(), middle + halfHeight);
|
||||||
c.drawRect(rect, paint);
|
c.drawRect(rect, paint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user