diff --git a/README.md b/README.md
index 876af5e9..14b41586 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,8 @@
# Markwon
+
+
[](http://search.maven.org/#search|ga|1|g%3A%22ru.noties%22%20AND%20a%3A%markwon%22)
[](http://search.maven.org/#search|ga|1|g%3A%22ru.noties%22%20AND%20a%3A%markwon-image-loader%22)
[](http://search.maven.org/#search|ga|1|g%3A%22ru.noties%22%20AND%20a%3A%markwon-view%22)
diff --git a/app/build.gradle b/app/build.gradle
index bc2bca96..7e6606e9 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -36,4 +36,6 @@ dependencies {
compile 'com.google.dagger:dagger:2.10'
annotationProcessor 'com.google.dagger:dagger-compiler:2.10'
+
+ implementation "com.android.support:appcompat-v7:27.0.2"
}
diff --git a/app/proguard.pro b/app/proguard.pro
index 9eee5753..e69de29b 100644
--- a/app/proguard.pro
+++ b/app/proguard.pro
@@ -1,5 +0,0 @@
--dontwarn okhttp3.**
--dontwarn okio.**
-
--keep class com.caverock.androidsvg.** { *; }
--dontwarn com.caverock.androidsvg.**
\ No newline at end of file
diff --git a/app/src/main/java/ru/noties/markwon/AppModule.java b/app/src/main/java/ru/noties/markwon/AppModule.java
index 09c5e230..70c40707 100644
--- a/app/src/main/java/ru/noties/markwon/AppModule.java
+++ b/app/src/main/java/ru/noties/markwon/AppModule.java
@@ -16,6 +16,9 @@ import okhttp3.Cache;
import okhttp3.OkHttpClient;
import ru.noties.markwon.il.AsyncDrawableLoader;
import ru.noties.markwon.spans.AsyncDrawable;
+import ru.noties.markwon.spans.configuration.image.ImageConfig;
+import ru.noties.markwon.spans.configuration.image.ImageGravity;
+import ru.noties.markwon.spans.configuration.image.ImageWidth;
@Module
class AppModule {
diff --git a/app/src/main/java/ru/noties/markwon/MarkdownRenderer.java b/app/src/main/java/ru/noties/markwon/MarkdownRenderer.java
index f276dfe2..119ba82c 100644
--- a/app/src/main/java/ru/noties/markwon/MarkdownRenderer.java
+++ b/app/src/main/java/ru/noties/markwon/MarkdownRenderer.java
@@ -1,11 +1,15 @@
package ru.noties.markwon;
import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Typeface;
import android.net.Uri;
import android.os.Handler;
import android.os.SystemClock;
+import android.support.annotation.FontRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.v4.content.res.ResourcesCompat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
@@ -14,13 +18,14 @@ import javax.inject.Inject;
import ru.noties.debug.Debug;
import ru.noties.markwon.spans.AsyncDrawable;
+import ru.noties.markwon.spans.SpannableTheme;
+import ru.noties.markwon.spans.configuration.heading.HeadingConfig;
+import ru.noties.markwon.spans.configuration.heading.HeadingTypeConfig;
@ActivityScope
public class MarkdownRenderer {
- interface MarkdownReadyListener {
- void onMarkdownReady(CharSequence markdown);
- }
+ private final Context context;
@Inject
AsyncDrawable.Loader loader;
@@ -34,14 +39,15 @@ public class MarkdownRenderer {
private Future> task;
@Inject
- MarkdownRenderer() {
+ MarkdownRenderer(Context context) {
+ this.context = context;
}
public void render(
- @NonNull final Context context,
- @Nullable final Uri uri,
- @NonNull final String markdown,
- @NonNull final MarkdownReadyListener listener) {
+ @NonNull final Context context,
+ @Nullable final Uri uri,
+ @NonNull final String markdown,
+ @NonNull final MarkdownReadyListener listener) {
cancel();
task = service.submit(new Runnable() {
@Override
@@ -55,9 +61,10 @@ public class MarkdownRenderer {
}
final SpannableConfiguration configuration = SpannableConfiguration.builder(context)
- .asyncDrawableLoader(loader)
- .urlProcessor(urlProcessor)
- .build();
+ .theme(getSpannableTheme())
+ .asyncDrawableLoader(loader)
+ .urlProcessor(urlProcessor)
+ .build();
final long start = SystemClock.uptimeMillis();
@@ -92,4 +99,25 @@ public class MarkdownRenderer {
private boolean isCancelled() {
return task == null || task.isCancelled();
}
+
+ private HeadingConfig getHeadingConfig() {
+ final HeadingTypeConfig h1 = new HeadingTypeConfig(-1, Color.RED, getTypeface(R.font.opensans_semibold));
+ final HeadingTypeConfig h2 = new HeadingTypeConfig(-1, Color.BLUE, getTypeface(R.font.opensans_regular));
+
+ return new HeadingConfig(h1, h2);
+ }
+
+ private SpannableTheme getSpannableTheme() {
+ return SpannableTheme.builderWithDefaults(context)
+ .headingConfig(getHeadingConfig(), context.getResources().getDisplayMetrics().density)
+ .build();
+ }
+
+ private Typeface getTypeface(@FontRes int font){
+ return ResourcesCompat.getFont(context, font);
+ }
+
+ interface MarkdownReadyListener {
+ void onMarkdownReady(CharSequence markdown);
+ }
}
diff --git a/app/src/main/res/font/app_font.xml b/app/src/main/res/font/app_font.xml
new file mode 100644
index 00000000..ddf98b6b
--- /dev/null
+++ b/app/src/main/res/font/app_font.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/font/opensans_regular.ttf b/app/src/main/res/font/opensans_regular.ttf
new file mode 100755
index 00000000..db433349
Binary files /dev/null and b/app/src/main/res/font/opensans_regular.ttf differ
diff --git a/app/src/main/res/font/opensans_semibold.ttf b/app/src/main/res/font/opensans_semibold.ttf
new file mode 100644
index 00000000..1a7679e3
Binary files /dev/null and b/app/src/main/res/font/opensans_semibold.ttf differ
diff --git a/artifactory-mvn-push.gradle b/artifactory-mvn-push.gradle
new file mode 100644
index 00000000..934ddba3
--- /dev/null
+++ b/artifactory-mvn-push.gradle
@@ -0,0 +1,44 @@
+apply plugin: 'com.jfrog.artifactory'
+apply plugin: 'digital.wup.android-maven-publish'
+
+publishing {
+ publications {
+ aar(MavenPublication) {
+ groupId "${GROUP}.auto1"
+ version VERSION_NAME
+ artifactId POM_ARTIFACT_ID
+
+ from components.android
+ }
+ }
+}
+
+artifactory {
+ contextUrl = artifactory_repository_url
+ publish {
+ repository {
+ repoKey = artifactory_repository_name
+
+ username = artifactory_username
+ password = artifactory_password
+ }
+ defaults {
+ publications('aar')
+ publishArtifacts = true
+
+ properties = ['qa.level': 'basic', 'q.os': 'android', 'dev.team': 'mobile-android']
+ publishPom = true
+ }
+ }
+}
+
+afterEvaluate {
+ task cleanBuildPublish {
+ dependsOn 'clean'
+ dependsOn 'assembleRelease'
+ dependsOn 'artifactoryPublish'
+ tasks.findByName('assembleRelease').mustRunAfter 'clean'
+ tasks.findByName('artifactoryPublish').dependsOn 'generatePomFileForAarPublication'
+ tasks.findByName('artifactoryPublish').mustRunAfter 'assembleRelease'
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 036e147b..5e37b3a8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,10 +1,14 @@
buildscript {
+ ext.kotlin_version = '1.2.10'
repositories {
jcenter()
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.3'
+ classpath 'com.android.tools.build:gradle:3.0.1'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.4.12"
+ classpath 'digital.wup:android-maven-publish:3.1.1'
}
}
@@ -27,14 +31,13 @@ task wrapper(type: Wrapper) {
}
ext {
-
// Config
- BUILD_TOOLS = '26.0.3'
+ BUILD_TOOLS = '27.0.1'
TARGET_SDK = 26
MIN_SDK = 16
// Dependencies
- final def supportVersion = '26.1.0'
+ final def supportVersion = '27.0.2'
SUPPORT_ANNOTATIONS = "com.android.support:support-annotations:$supportVersion"
SUPPORT_APP_COMPAT = "com.android.support:appcompat-v7:$supportVersion"
diff --git a/library-image-loader/build.gradle b/library-image-loader/build.gradle
index 3a909101..a7fd1266 100644
--- a/library-image-loader/build.gradle
+++ b/library-image-loader/build.gradle
@@ -10,6 +10,8 @@ android {
targetSdkVersion TARGET_SDK
versionCode 1
versionName version
+
+ consumerProguardFiles 'lib-proguard-rules.pro'
}
lintOptions {
@@ -19,12 +21,10 @@ android {
}
dependencies {
- compile project(':library')
- compile ANDROID_SVG
- compile ANDROID_GIF
- compile OK_HTTP
+ implementation project(':library')
+ implementation ANDROID_SVG
+ implementation ANDROID_GIF
+ implementation OK_HTTP
}
-if (project.hasProperty('release')) {
- apply from: 'https://raw.githubusercontent.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle'
-}
\ No newline at end of file
+apply from: '../artifactory-mvn-push.gradle'
\ No newline at end of file
diff --git a/library-image-loader/lib-proguard-rules.pro b/library-image-loader/lib-proguard-rules.pro
new file mode 100644
index 00000000..9eee5753
--- /dev/null
+++ b/library-image-loader/lib-proguard-rules.pro
@@ -0,0 +1,5 @@
+-dontwarn okhttp3.**
+-dontwarn okio.**
+
+-keep class com.caverock.androidsvg.** { *; }
+-dontwarn com.caverock.androidsvg.**
\ No newline at end of file
diff --git a/library-image-loader/src/main/java/ru/noties/markwon/il/AsyncDrawableLoader.java b/library-image-loader/src/main/java/ru/noties/markwon/il/AsyncDrawableLoader.java
index a9574d13..03530899 100644
--- a/library-image-loader/src/main/java/ru/noties/markwon/il/AsyncDrawableLoader.java
+++ b/library-image-loader/src/main/java/ru/noties/markwon/il/AsyncDrawableLoader.java
@@ -36,6 +36,7 @@ import okhttp3.Response;
import okhttp3.ResponseBody;
import pl.droidsonroids.gif.GifDrawable;
import ru.noties.markwon.spans.AsyncDrawable;
+import ru.noties.markwon.spans.configuration.image.ImageConfig;
public class AsyncDrawableLoader implements AsyncDrawable.Loader {
@@ -58,6 +59,7 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
private final ExecutorService executorService;
private final Handler mainThread;
private final Drawable errorDrawable;
+ private final ImageConfig imageConfig;
private final Map> requests;
@@ -67,6 +69,7 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
this.executorService = builder.executorService;
this.mainThread = new Handler(Looper.getMainLooper());
this.errorDrawable = builder.errorDrawable;
+ this.imageConfig = builder.imageConfig;
this.requests = new HashMap<>(3);
}
@@ -146,7 +149,7 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
public void run() {
final AsyncDrawable asyncDrawable = reference.get();
if (asyncDrawable != null && asyncDrawable.isAttached()) {
- asyncDrawable.setResult(out);
+ asyncDrawable.setResult(out, imageConfig);
}
}
});
@@ -345,6 +348,7 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
private Resources resources;
private ExecutorService executorService;
private Drawable errorDrawable;
+ private ImageConfig imageConfig;
public Builder client(@NonNull OkHttpClient client) {
this.client = client;
@@ -366,6 +370,11 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
return this;
}
+ public Builder imageConfig(ImageConfig imageConfig) {
+ this.imageConfig = imageConfig;
+ return this;
+ }
+
public AsyncDrawableLoader build() {
if (client == null) {
client = new OkHttpClient();
@@ -377,6 +386,9 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
// we will use executor from okHttp
executorService = client.dispatcher().executorService();
}
+ if(imageConfig == null){
+ imageConfig = new ImageConfig();
+ }
return new AsyncDrawableLoader(this);
}
}
diff --git a/library/build.gradle b/library/build.gradle
index c384c1b6..28d4c12d 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -1,4 +1,5 @@
apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
android {
@@ -11,15 +12,24 @@ android {
versionCode 1
versionName version
}
+
+ libraryVariants.all { variant ->
+ variant.outputs.all {
+ outputFileName = "${POM_ARTIFACT_ID}-release.aar"
+ }
+ }
}
dependencies {
- compile SUPPORT_ANNOTATIONS
- compile COMMON_MARK
- compile COMMON_MARK_STRIKETHROUGHT
- compile COMMON_MARK_TABLE
+ api SUPPORT_ANNOTATIONS
+ implementation COMMON_MARK
+ implementation COMMON_MARK_STRIKETHROUGHT
+ implementation COMMON_MARK_TABLE
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
-if (project.hasProperty('release')) {
- apply from: 'https://raw.githubusercontent.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle'
+repositories {
+ mavenCentral()
}
+
+apply from: '../artifactory-mvn-push.gradle'
\ No newline at end of file
diff --git a/library/src/main/java/ru/noties/markwon/spans/AsyncDrawable.java b/library/src/main/java/ru/noties/markwon/spans/AsyncDrawable.java
index 2253a5ba..42dce54a 100644
--- a/library/src/main/java/ru/noties/markwon/spans/AsyncDrawable.java
+++ b/library/src/main/java/ru/noties/markwon/spans/AsyncDrawable.java
@@ -12,25 +12,26 @@ import android.support.annotation.Nullable;
import ru.noties.markwon.renderer.html.ImageSize;
import ru.noties.markwon.renderer.html.ImageSizeResolver;
+import ru.noties.markwon.spans.configuration.image.ImageConfig;
+import ru.noties.markwon.spans.configuration.image.ImageGravity;
+import ru.noties.markwon.spans.configuration.image.ImageWidth;
public class AsyncDrawable extends Drawable {
- public interface Loader {
-
- void load(@NonNull String destination, @NonNull AsyncDrawable drawable);
-
- void cancel(@NonNull String destination);
- }
-
private final String destination;
+
private final Loader loader;
+
private final ImageSize imageSize;
+
private final ImageSizeResolver imageSizeResolver;
private Drawable result;
+
private Callback callback;
private int canvasWidth;
+
private float textSize;
public AsyncDrawable(@NonNull String destination, @NonNull Loader loader) {
@@ -41,10 +42,10 @@ public class AsyncDrawable extends Drawable {
* @since 1.0.1
*/
public AsyncDrawable(
- @NonNull String destination,
- @NonNull Loader loader,
- @Nullable ImageSizeResolver imageSizeResolver,
- @Nullable ImageSize imageSize
+ @NonNull String destination,
+ @NonNull Loader loader,
+ @Nullable ImageSizeResolver imageSizeResolver,
+ @Nullable ImageSize imageSize
) {
this.destination = destination;
this.loader = loader;
@@ -91,7 +92,7 @@ public class AsyncDrawable extends Drawable {
}
}
- public void setResult(@NonNull Drawable result) {
+ public void setResult(@NonNull Drawable result, @NonNull ImageConfig imageConfig) {
// if we have previous one, detach it
if (this.result != null) {
@@ -101,7 +102,7 @@ public class AsyncDrawable extends Drawable {
this.result = result;
this.result.setCallback(callback);
- final Rect bounds = resolveBounds();
+ final Rect bounds = resolveBounds(imageConfig);
result.setBounds(bounds);
setBounds(bounds);
@@ -168,17 +169,55 @@ public class AsyncDrawable extends Drawable {
}
/**
+ * @param imageConfig
* @since 1.0.1
*/
@NonNull
- private Rect resolveBounds() {
+ private Rect resolveBounds(@NonNull ImageConfig imageConfig) {
final Rect rect;
if (imageSizeResolver == null
- || imageSize == null) {
+ || imageSize == null) {
rect = result.getBounds();
} else {
rect = imageSizeResolver.resolveImageSize(imageSize, result.getBounds(), canvasWidth, textSize);
}
- return rect;
+ return adjustBounds(rect, imageConfig);
+ }
+
+ private Rect adjustBounds(Rect bounds, ImageConfig imageConfig) {
+ final ImageGravity gravity = imageConfig.getGravity();
+ final ImageWidth imageWidth = imageConfig.getImageWidth();
+
+ if (imageWidth == ImageWidth.MatchParent) {
+ final float growthRatio = (float) canvasWidth / bounds.width();
+ bounds.left = 0;
+ bounds.right = canvasWidth;
+ bounds.bottom = (int) (bounds.top + bounds.height() * growthRatio);
+ } else {
+ switch (gravity) {
+ case Left:
+ //left is unchanged
+ break;
+ case Right:
+ bounds.left = canvasWidth - bounds.width();
+ bounds.right = canvasWidth;
+ break;
+ case Center:
+ final int center = canvasWidth / 2;
+ final int imageRadius = bounds.width() / 2;
+ bounds.left = center - imageRadius;
+ bounds.right = center + imageRadius;
+ break;
+ }
+ }
+
+ return bounds;
+ }
+
+ public interface Loader {
+
+ void load(@NonNull String destination, @NonNull AsyncDrawable drawable);
+
+ void cancel(@NonNull String destination);
}
}
diff --git a/library/src/main/java/ru/noties/markwon/spans/HeadingSpan.java b/library/src/main/java/ru/noties/markwon/spans/HeadingSpan.java
index 6293d554..85b339c8 100644
--- a/library/src/main/java/ru/noties/markwon/spans/HeadingSpan.java
+++ b/library/src/main/java/ru/noties/markwon/spans/HeadingSpan.java
@@ -10,12 +10,14 @@ import android.text.TextPaint;
import android.text.style.LeadingMarginSpan;
import android.text.style.MetricAffectingSpan;
+import ru.noties.markwon.spans.configuration.heading.HeadingType;
+
public class HeadingSpan extends MetricAffectingSpan implements LeadingMarginSpan {
private final SpannableTheme theme;
private final Rect rect = ObjectsPool.rect();
private final Paint paint = ObjectsPool.paint();
- private final int level;
+ @HeadingType private final int level;
public HeadingSpan(@NonNull SpannableTheme theme, @IntRange(from = 1, to = 6) int level) {
this.theme = theme;
diff --git a/library/src/main/java/ru/noties/markwon/spans/SpannableTheme.java b/library/src/main/java/ru/noties/markwon/spans/SpannableTheme.java
index c402e24f..39b85a06 100644
--- a/library/src/main/java/ru/noties/markwon/spans/SpannableTheme.java
+++ b/library/src/main/java/ru/noties/markwon/spans/SpannableTheme.java
@@ -9,12 +9,15 @@ import android.support.annotation.AttrRes;
import android.support.annotation.ColorInt;
import android.support.annotation.Dimension;
import android.support.annotation.FloatRange;
-import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextPaint;
import android.util.TypedValue;
+import ru.noties.markwon.spans.configuration.heading.HeadingConfig;
+import ru.noties.markwon.spans.configuration.heading.HeadingType;
+import ru.noties.markwon.spans.configuration.heading.HeadingTypeConfig;
+
@SuppressWarnings("WeakerAccess")
public class SpannableTheme {
@@ -78,16 +81,16 @@ public class SpannableTheme {
final Dip dip = new Dip(context);
return new Builder()
- .linkColor(linkColor)
- .codeMultilineMargin(dip.toPx(8))
- .blockMargin(dip.toPx(24))
- .blockQuoteWidth(dip.toPx(4))
- .bulletListItemStrokeWidth(dip.toPx(1))
- .headingBreakHeight(dip.toPx(1))
- .thematicBreakHeight(dip.toPx(4))
- .tableCellPadding(dip.toPx(4))
- .tableBorderWidth(dip.toPx(1))
- .taskListDrawable(new TaskListDrawable(linkColor, linkColor, backgroundColor));
+ .linkColor(linkColor)
+ .codeMultilineMargin(dip.toPx(8))
+ .blockMargin(dip.toPx(24))
+ .blockQuoteWidth(dip.toPx(4))
+ .bulletListItemStrokeWidth(dip.toPx(1))
+ .headingConfig(new HeadingConfig(), dip.density)
+ .thematicBreakHeight(dip.toPx(4))
+ .tableCellPadding(dip.toPx(4))
+ .tableBorderWidth(dip.toPx(1))
+ .taskListDrawable(new TaskListDrawable(linkColor, linkColor, backgroundColor));
}
private static int resolve(Context context, @AttrRes int attr) {
@@ -104,14 +107,15 @@ public class SpannableTheme {
protected static final int BLOCK_QUOTE_DEF_COLOR_ALPHA = 25;
protected static final int CODE_DEF_BACKGROUND_COLOR_ALPHA = 25;
+
protected static final float CODE_DEF_TEXT_SIZE_RATIO = .87F;
protected static final int HEADING_DEF_BREAK_COLOR_ALPHA = 75;
// taken from html spec (most browsers render headings like that)
// is not exposed via protected modifier in order to disallow modification
- private static final float[] HEADING_SIZES = {
- 2.F, 1.5F, 1.17F, 1.F, .83F, .67F,
+ private static final float[] HEADING_SCALES = {
+ 2.F, 1.5F, 1.17F, 1.F, .83F, .67F,
};
protected static final float SCRIPT_DEF_TEXT_SIZE_RATIO = .75F;
@@ -159,11 +163,7 @@ public class SpannableTheme {
// applied ONLY if default typeface was used, otherwise, not applied
protected final int codeTextSize;
- // by default paint.getStrokeWidth
- protected final int headingBreakHeight;
-
- // by default, text color with `HEADING_DEF_BREAK_COLOR_ALPHA` applied alpha
- protected final int headingBreakColor;
+ protected final HeadingConfig headingConfig;
// by default `SCRIPT_DEF_TEXT_SIZE_RATIO`
protected final float scriptTextSizeRatio;
@@ -202,8 +202,7 @@ public class SpannableTheme {
this.codeMultilineMargin = builder.codeMultilineMargin;
this.codeTypeface = builder.codeTypeface;
this.codeTextSize = builder.codeTextSize;
- this.headingBreakHeight = builder.headingBreakHeight;
- this.headingBreakColor = builder.headingBreakColor;
+ this.headingConfig = builder.headingConfig;
this.scriptTextSizeRatio = builder.scriptTextSizeRatio;
this.thematicBreakColor = builder.thematicBreakColor;
this.thematicBreakHeight = builder.thematicBreakHeight;
@@ -214,7 +213,6 @@ public class SpannableTheme {
this.taskListDrawable = builder.taskListDrawable;
}
-
public void applyLinkStyle(@NonNull Paint paint) {
paint.setUnderlineText(true);
if (linkColor != 0) {
@@ -269,7 +267,7 @@ public class SpannableTheme {
final int width;
if (bulletWidth == 0
- || bulletWidth > min) {
+ || bulletWidth > min) {
width = min;
} else {
width = bulletWidth;
@@ -322,13 +320,51 @@ public class SpannableTheme {
return color;
}
- public void applyHeadingTextStyle(@NonNull Paint paint, @IntRange(from = 1, to = 6) int level) {
+ public void applyHeadingTextStyle(@NonNull Paint paint, @HeadingType int level) {
+ HeadingTypeConfig headingTypeConfig;
+ switch (level) {
+ case HeadingType.H1:
+ headingTypeConfig = headingConfig.getH1Config();
+ break;
+ case HeadingType.H2:
+ headingTypeConfig = headingConfig.getH2Config();
+ break;
+ case HeadingType.H3:
+ headingTypeConfig = headingConfig.getH3Config();
+ break;
+ case HeadingType.H4:
+ headingTypeConfig = headingConfig.getH4Config();
+ break;
+ case HeadingType.H5:
+ headingTypeConfig = headingConfig.getH5Config();
+ break;
+ case HeadingType.H6:
+ headingTypeConfig = headingConfig.getH6Config();
+ break;
+ default:
+ headingTypeConfig = new HeadingTypeConfig();
+ }
+
paint.setFakeBoldText(true);
- paint.setTextSize(paint.getTextSize() * HEADING_SIZES[level - 1]);
+
+ final float textSize = headingTypeConfig.getTextScale() > 0 ?
+ headingTypeConfig.getTextScale() : HEADING_SCALES[level - 1];
+ paint.setTextSize(paint.getTextSize() * textSize);
+
+ final int textColor = headingTypeConfig.getTextColor();
+ if (textColor != -1) {
+ paint.setColor(textColor);
+ }
+
+ final Typeface typeface = headingTypeConfig.getTypeface();
+ if(typeface != null){
+ paint.setTypeface(typeface);
+ }
}
public void applyHeadingBreakStyle(@NonNull Paint paint) {
final int color;
+ final int headingBreakColor = headingConfig.getHeadingBreakConfig().getHeadingBreakColor();
if (headingBreakColor != 0) {
color = headingBreakColor;
} else {
@@ -336,6 +372,7 @@ public class SpannableTheme {
}
paint.setColor(color);
paint.setStyle(Paint.Style.FILL);
+ final float headingBreakHeight = headingConfig.getHeadingBreakConfig().getHeadingBreakStrokeWidth();
if (headingBreakHeight >= 0) {
//noinspection SuspiciousNameCombination
paint.setStrokeWidth(headingBreakHeight);
@@ -441,8 +478,7 @@ public class SpannableTheme {
private int codeMultilineMargin;
private Typeface codeTypeface;
private int codeTextSize;
- private int headingBreakHeight = -1;
- private int headingBreakColor;
+ private HeadingConfig headingConfig;
private float scriptTextSizeRatio;
private int thematicBreakColor;
private int thematicBreakHeight = -1;
@@ -468,8 +504,7 @@ public class SpannableTheme {
this.codeMultilineMargin = theme.codeMultilineMargin;
this.codeTypeface = theme.codeTypeface;
this.codeTextSize = theme.codeTextSize;
- this.headingBreakHeight = theme.headingBreakHeight;
- this.headingBreakColor = theme.headingBreakColor;
+ this.headingConfig = theme.headingConfig;
this.scriptTextSizeRatio = theme.scriptTextSizeRatio;
this.thematicBreakColor = theme.thematicBreakColor;
this.thematicBreakHeight = theme.thematicBreakHeight;
@@ -553,14 +588,9 @@ public class SpannableTheme {
}
@NonNull
- public Builder headingBreakHeight(@Dimension int headingBreakHeight) {
- this.headingBreakHeight = headingBreakHeight;
- return this;
- }
-
- @NonNull
- public Builder headingBreakColor(@ColorInt int headingBreakColor) {
- this.headingBreakColor = headingBreakColor;
+ public Builder headingConfig(HeadingConfig headingConfig, float density) {
+ headingConfig.setDensityFactor(density);
+ this.headingConfig = headingConfig;
return this;
}
@@ -630,7 +660,7 @@ public class SpannableTheme {
private static class Dip {
- private final float density;
+ protected final float density;
Dip(@NonNull Context context) {
this.density = context.getResources().getDisplayMetrics().density;
diff --git a/library/src/main/java/ru/noties/markwon/spans/configuration/heading/HeadingConfig.kt b/library/src/main/java/ru/noties/markwon/spans/configuration/heading/HeadingConfig.kt
new file mode 100644
index 00000000..7b58feb6
--- /dev/null
+++ b/library/src/main/java/ru/noties/markwon/spans/configuration/heading/HeadingConfig.kt
@@ -0,0 +1,80 @@
+package ru.noties.markwon.spans.configuration.heading
+
+import android.graphics.Typeface
+import android.support.annotation.ColorInt
+import android.support.annotation.Dimension
+
+/**
+ * Configuration for heading type (H1, H2, ..., H6)
+ *
+ * Can define different configurations for all six types of headings,
+ * plus an extra configuration for the line breaks (only applies to H1 and H2)
+ *
+ * @property h1Config Config for H1 heading
+ * @property h2Config Config for H2 heading
+ * @property h3Config Config for H3 heading
+ * @property h4Config Config for H4 heading
+ * @property h5Config Config for H5 heading
+ * @property h6Config Config for H6 heading
+ * @property headingBreakConfig Config for line breaks (for H1 and H2)
+ */
+class HeadingConfig @JvmOverloads constructor(
+ val h1Config: HeadingTypeConfig = HeadingTypeConfig(),
+ val h2Config: HeadingTypeConfig = HeadingTypeConfig(),
+ val h3Config: HeadingTypeConfig = HeadingTypeConfig(),
+ val h4Config: HeadingTypeConfig = HeadingTypeConfig(),
+ val h5Config: HeadingTypeConfig = HeadingTypeConfig(),
+ val h6Config: HeadingTypeConfig = HeadingTypeConfig(),
+ val headingBreakConfig: HeadingBreakConfig = HeadingBreakConfig()
+) {
+ fun setDensityFactor(factor: Float) {
+ h1Config.densityFactor = factor
+ h2Config.densityFactor = factor
+ h3Config.densityFactor = factor
+ h4Config.densityFactor = factor
+ h5Config.densityFactor = factor
+ h6Config.densityFactor = factor
+ headingBreakConfig.densityFactor = factor
+ }
+}
+
+/**
+ * Configuration for given heading type (H1, H2, ..., H6)
+ *
+ * Can set text size, text color and font (typeface)
+ *
+ * @property textScale Text scale for heading
+ * @property textColor Text color for heading
+ * @property typeface Typeface for heading
+ */
+class HeadingTypeConfig @JvmOverloads constructor(
+ //Standard sizes available at #SpannableTheme.java:HEADING_SIZES
+ val textScale: Float = -1F,
+
+ @ColorInt val textColor: Int = -1,
+
+ val typeface: Typeface? = null
+) {
+ internal var densityFactor: Float = -1F
+}
+
+/**
+ * Configuration for given heading type (H1, H2, ..., H6)
+ *
+ * Can set text size, text color and font (typeface)
+ *
+ * @property headingBreakStrokeWidth Stroke width for heading's line break
+ * @property headingBreakColor Color for heading's line break
+ */
+class HeadingBreakConfig @JvmOverloads constructor(
+ // by default paint.getStrokeWidth
+ @Dimension headingBreakStrokeWidth: Int = -1,
+
+ // by default, text color with `HEADING_DEF_BREAK_COLOR_ALPHA` applied alpha
+ @ColorInt val headingBreakColor: Int = 0
+) {
+ internal var densityFactor: Float = -1F
+
+ val headingBreakStrokeWidth: Float = headingBreakStrokeWidth.toFloat()
+ get() = field * densityFactor
+}
\ No newline at end of file
diff --git a/library/src/main/java/ru/noties/markwon/spans/configuration/heading/HeadingType.java b/library/src/main/java/ru/noties/markwon/spans/configuration/heading/HeadingType.java
new file mode 100644
index 00000000..69e151e1
--- /dev/null
+++ b/library/src/main/java/ru/noties/markwon/spans/configuration/heading/HeadingType.java
@@ -0,0 +1,27 @@
+package ru.noties.markwon.spans.configuration.heading;
+
+import android.support.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import static ru.noties.markwon.spans.configuration.heading.HeadingType.H1;
+import static ru.noties.markwon.spans.configuration.heading.HeadingType.H2;
+import static ru.noties.markwon.spans.configuration.heading.HeadingType.H3;
+import static ru.noties.markwon.spans.configuration.heading.HeadingType.H4;
+import static ru.noties.markwon.spans.configuration.heading.HeadingType.H5;
+import static ru.noties.markwon.spans.configuration.heading.HeadingType.H6;
+
+/**
+ * Created by daniel.leal on 13.12.17.
+ */
+@Retention(RetentionPolicy.SOURCE)
+@IntDef({H1, H2, H3, H4, H5, H6})
+public @interface HeadingType {
+ int H1 = 1;
+ int H2 = 2;
+ int H3 = 3;
+ int H4 = 4;
+ int H5 = 5;
+ int H6 = 6;
+}
diff --git a/library/src/main/java/ru/noties/markwon/spans/configuration/image/ImageConfig.kt b/library/src/main/java/ru/noties/markwon/spans/configuration/image/ImageConfig.kt
new file mode 100644
index 00000000..b46bfe41
--- /dev/null
+++ b/library/src/main/java/ru/noties/markwon/spans/configuration/image/ImageConfig.kt
@@ -0,0 +1,25 @@
+package ru.noties.markwon.spans.configuration.image
+
+/**
+ * Configuration for images
+ *
+ * Can set two parameters: image width style and horizontal gravity
+ *
+ * @property imageWidth Width of the image to be displayed (WRAP_CONTENT or MATCH_PARENT)
+ * @property gravity Horizontal gravity (left, right or center)
+ */
+class ImageConfig @JvmOverloads constructor(
+ val imageWidth: ImageWidth = ImageWidth.Wrap,
+ val gravity: ImageGravity = ImageGravity.Left
+)
+
+enum class ImageGravity {
+ Left,
+ Center,
+ Right
+}
+
+enum class ImageWidth {
+ Wrap,
+ MatchParent
+}
\ No newline at end of file