Skip to content

Commit 5e98273

Browse files
committed
Merge branch 'trunk' of github.com:wordpress-mobile/AztecEditor-Android into feature/add-styling-options-to-task-list
� Conflicts: � aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt � aztec/src/main/kotlin/org/wordpress/aztec/formatting/BlockFormatter.kt � aztec/src/main/res/values/styles.xml
2 parents cf638d1 + e91ec10 commit 5e98273

File tree

8 files changed

+238
-44
lines changed

8 files changed

+238
-44
lines changed

aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ import org.wordpress.aztec.handlers.ListItemHandler
7474
import org.wordpress.aztec.handlers.PreformatHandler
7575
import org.wordpress.aztec.handlers.QuoteHandler
7676
import org.wordpress.aztec.plugins.IAztecPlugin
77+
import org.wordpress.aztec.plugins.IOnDrawPlugin
7778
import org.wordpress.aztec.plugins.ITextPastePlugin
7879
import org.wordpress.aztec.plugins.IToolbarButton
7980
import org.wordpress.aztec.source.Format
@@ -315,6 +316,13 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
315316

316317
private lateinit var listItemStyle: BlockFormatter.ListItemStyle
317318

319+
override fun onDraw(canvas: Canvas) {
320+
plugins.filterIsInstance<IOnDrawPlugin>().forEach {
321+
it.onDraw(canvas)
322+
}
323+
super.onDraw(canvas)
324+
}
325+
318326
interface OnSelectionChangedListener {
319327
fun onSelectionChanged(selStart: Int, selEnd: Int)
320328
}
@@ -457,11 +465,13 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
457465
quoteStyle = BlockFormatter.QuoteStyle(
458466
styles.getColor(R.styleable.AztecText_quoteBackground, 0),
459467
styles.getColor(R.styleable.AztecText_quoteColor, 0),
468+
styles.getColor(R.styleable.AztecText_quoteTextColor,
469+
ContextCompat.getColor(context, R.color.text)),
460470
styles.getFraction(R.styleable.AztecText_quoteBackgroundAlpha, 1, 1, 0f),
461471
styles.getDimensionPixelSize(R.styleable.AztecText_quoteMargin, 0),
462472
styles.getDimensionPixelSize(R.styleable.AztecText_quotePadding, 0),
463473
styles.getDimensionPixelSize(R.styleable.AztecText_quoteWidth, 0),
464-
verticalParagraphPadding),
474+
styles.getDimensionPixelSize(R.styleable.AztecText_quoteVerticalPadding, verticalParagraphPadding)),
465475
headerStyle = BlockFormatter.HeaderStyles(verticalHeadingMargin, mapOf(
466476
AztecHeadingSpan.Heading.H1 to BlockFormatter.HeaderStyles.HeadingStyle(
467477
styles.getDimensionPixelSize(R.styleable.AztecText_headingOneFontSize, 0),
@@ -492,7 +502,14 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
492502
styles.getColor(R.styleable.AztecText_preformatBackground, 0),
493503
getPreformatBackgroundAlpha(styles),
494504
styles.getColor(R.styleable.AztecText_preformatColor, 0),
495-
verticalParagraphPadding),
505+
styles.getDimensionPixelSize(R.styleable.AztecText_preformatVerticalPadding, verticalParagraphPadding),
506+
styles.getDimensionPixelSize(R.styleable.AztecText_preformatLeadingMargin,
507+
resources.getDimensionPixelSize(R.dimen.preformat_leading_margin)),
508+
styles.getColor(R.styleable.AztecText_preformatBorderColor, 0),
509+
styles.getDimensionPixelSize(R.styleable.AztecText_preformatBorderRadius, 0),
510+
styles.getDimensionPixelSize(R.styleable.AztecText_preformatBorderThickness, 0),
511+
styles.getDimensionPixelSize(R.styleable.AztecText_preformatTextSize, textSize.toInt())
512+
),
496513
alignmentRendering = alignmentRendering,
497514
exclusiveBlockStyles = BlockFormatter.ExclusiveBlockStyles(styles.getBoolean(R.styleable.AztecText_exclusiveBlocks, false), verticalParagraphPadding),
498515
paragraphStyle = BlockFormatter.ParagraphStyle(verticalParagraphMargin)

aztec/src/main/kotlin/org/wordpress/aztec/formatting/BlockFormatter.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,9 @@ class BlockFormatter(editor: AztecText,
6161
}
6262
}
6363

64+
data class QuoteStyle(val quoteBackground: Int, val quoteColor: Int, val quoteTextColor: Int, val quoteBackgroundAlpha: Float, val quoteMargin: Int, val quotePadding: Int, val quoteWidth: Int, val verticalPadding: Int)
65+
data class PreformatStyle(val preformatBackground: Int, val preformatBackgroundAlpha: Float, val preformatColor: Int, val verticalPadding: Int, val leadingMargin: Int, val preformatBorderColor: Int, val preformatBorderRadius: Int, val preformatBorderThickness: Int, val preformatTextSize: Int)
6466
data class ListItemStyle(val strikeThroughCheckedItems: Boolean, val checkedItemsTextColor: Int)
65-
66-
data class QuoteStyle(val quoteBackground: Int, val quoteColor: Int, val quoteBackgroundAlpha: Float, val quoteMargin: Int, val quotePadding: Int, val quoteWidth: Int, val verticalPadding: Int)
67-
data class PreformatStyle(val preformatBackground: Int, val preformatBackgroundAlpha: Float, val preformatColor: Int, val verticalPadding: Int)
6867
data class HeaderStyles(val verticalPadding: Int, val styles: Map<AztecHeadingSpan.Heading, HeadingStyle>) {
6968
data class HeadingStyle(val fontSize: Int, val fontColor: Int)
7069
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.wordpress.aztec.plugins
2+
3+
import android.graphics.Canvas
4+
5+
/**
6+
* Use this plugin in order to get access to canvas during drawing cycle of AztecText
7+
*/
8+
interface IOnDrawPlugin : IAztecPlugin {
9+
/**
10+
* This method is called when onDraw method of AztecText is called but before the super call.
11+
* @param canvas canvas of AztecText
12+
*/
13+
fun onDraw(canvas: Canvas)
14+
}

aztec/src/main/kotlin/org/wordpress/aztec/spans/AztecPreformatSpan.kt

Lines changed: 123 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package org.wordpress.aztec.spans
22

33
import android.graphics.Canvas
44
import android.graphics.Color
5+
import android.graphics.CornerPathEffect
56
import android.graphics.Paint
6-
import android.graphics.Rect
7+
import android.graphics.Path
78
import android.text.Layout
89
import android.text.Spanned
10+
import android.text.TextPaint
911
import android.text.style.LeadingMarginSpan
1012
import android.text.style.LineBackgroundSpan
1113
import android.text.style.LineHeightSpan
@@ -20,7 +22,7 @@ fun createPreformatSpan(
2022
nestingLevel: Int,
2123
alignmentRendering: AlignmentRendering,
2224
attributes: AztecAttributes = AztecAttributes(),
23-
preformatStyle: BlockFormatter.PreformatStyle = BlockFormatter.PreformatStyle(0, 0f, 0, 0)
25+
preformatStyle: BlockFormatter.PreformatStyle = BlockFormatter.PreformatStyle(0, 0f, 0, 0, 0, 0, 0, 0, 0)
2426
): AztecPreformatSpan =
2527
when (alignmentRendering) {
2628
AlignmentRendering.SPAN_LEVEL -> AztecPreformatSpanAligned(nestingLevel, attributes, preformatStyle)
@@ -56,55 +58,150 @@ open class AztecPreformatSpan(
5658
override var endBeforeBleed: Int = -1
5759
override var startBeforeCollapse: Int = -1
5860

59-
val rect = Rect()
61+
private var originalAscent: Int = 0
62+
private var originalTop: Int = 0
63+
private var originalDescent: Int = 0
64+
private var originalBottom: Int = 0
6065

61-
private val MARGIN = 16
62-
63-
override fun chooseHeight(text: CharSequence, start: Int, end: Int, spanstartv: Int, v: Int, fm: Paint.FontMetricsInt) {
66+
// this method adds extra padding to the top and bottom lines of the text while removing it from middle lines
67+
override fun chooseHeight(text: CharSequence, start: Int, end: Int, spanstartv: Int, v: Int,
68+
fm: Paint.FontMetricsInt) {
6469
val spanned = text as Spanned
6570
val spanStart = spanned.getSpanStart(this)
6671
val spanEnd = spanned.getSpanEnd(this)
72+
val isFirstLine = start <= spanStart
73+
val isLastLine = spanEnd <= end
74+
75+
if (isFirstLine) {
76+
originalAscent = fm.ascent
77+
originalTop = fm.top
78+
originalDescent = fm.descent
79+
originalBottom = fm.bottom
6780

68-
if (start == spanStart || start < spanStart) {
6981
fm.ascent -= preformatStyle.verticalPadding
7082
fm.top -= preformatStyle.verticalPadding
71-
}
7283

73-
if (end == spanEnd || spanEnd < end) {
84+
if (!isLastLine) {
85+
fm.descent = originalDescent
86+
fm.bottom = originalBottom
87+
}
88+
}
89+
if (isLastLine) {
7490
fm.descent += preformatStyle.verticalPadding
7591
fm.bottom += preformatStyle.verticalPadding
92+
93+
if (!isFirstLine) {
94+
fm.ascent = originalAscent
95+
fm.top = originalTop
96+
}
97+
}
98+
99+
if (!isFirstLine && !isLastLine) {
100+
fm.ascent = originalAscent
101+
fm.top = originalTop
102+
fm.descent = originalDescent
103+
fm.bottom = originalBottom
76104
}
77105
}
78106

79-
override fun drawBackground(canvas: Canvas, paint: Paint, left: Int, right: Int, top: Int, baseline: Int, bottom: Int, text: CharSequence?, start: Int, end: Int, lnum: Int) {
80-
val color = paint.color
107+
override fun updateDrawState(ds: TextPaint) {
108+
super.updateDrawState(ds)
109+
ds.textSize = preformatStyle.preformatTextSize.toFloat()
110+
}
111+
112+
override fun updateMeasureState(paint: TextPaint) {
113+
super.updateMeasureState(paint)
114+
paint.textSize = preformatStyle.preformatTextSize.toFloat()
115+
}
116+
117+
private val strokePaint = Paint().apply {
118+
isAntiAlias = true
119+
style = Paint.Style.STROKE
120+
}
121+
122+
private val fillPaint = Paint().apply {
123+
isAntiAlias = true
124+
strokeCap = Paint.Cap.ROUND
125+
}
126+
127+
override fun drawBackground(canvas: Canvas, paint: Paint, left: Int, right: Int, top: Int, baseline: Int,
128+
bottom: Int, text: CharSequence?, start: Int, end: Int, lnum: Int) {
129+
val spanned = text as Spanned
130+
val spanStart = spanned.getSpanStart(this)
131+
val spanEnd = spanned.getSpanEnd(this)
132+
133+
val isFirstLine = spanStart == start
134+
val isLastLine = spanEnd == end
135+
81136
val alpha: Int = (preformatStyle.preformatBackgroundAlpha * 255).toInt()
82-
paint.color = Color.argb(
137+
fillPaint.color = Color.argb(
83138
alpha,
84139
Color.red(preformatStyle.preformatBackground),
85140
Color.green(preformatStyle.preformatBackground),
86141
Color.blue(preformatStyle.preformatBackground)
87142
)
88-
rect.set(left, top, right, bottom)
89-
canvas.drawRect(rect, paint)
90-
paint.color = color
91-
}
92-
93-
override fun drawLeadingMargin(canvas: Canvas, paint: Paint, x: Int, dir: Int, top: Int, baseline: Int, bottom: Int, text: CharSequence, start: Int, end: Int, first: Boolean, layout: Layout) {
94-
val style = paint.style
95-
val color = paint.color
96143

97-
paint.style = Paint.Style.FILL
98-
paint.color = preformatStyle.preformatColor
144+
fillPaint.pathEffect = CornerPathEffect(preformatStyle.preformatBorderRadius.toFloat())
145+
strokePaint.pathEffect = CornerPathEffect(preformatStyle.preformatBorderRadius.toFloat())
146+
147+
strokePaint.color = preformatStyle.preformatBorderColor
148+
strokePaint.strokeWidth = preformatStyle.preformatBorderThickness.toFloat()
149+
150+
val fillPath = Path().apply {
151+
if (isFirstLine) {
152+
moveTo(left.toFloat(), bottom.toFloat())
153+
lineTo(left.toFloat(), top.toFloat())
154+
lineTo(right.toFloat(), top.toFloat())
155+
lineTo(right.toFloat(), bottom.toFloat())
156+
} else if (isLastLine) {
157+
moveTo(left.toFloat(), top.toFloat())
158+
lineTo(left.toFloat(), bottom.toFloat())
159+
lineTo(right.toFloat(), bottom.toFloat())
160+
lineTo(right.toFloat(), top.toFloat())
161+
} else {
162+
fillPaint.pathEffect = null
163+
moveTo(left.toFloat(), top.toFloat())
164+
lineTo(right.toFloat(), top.toFloat())
165+
lineTo(right.toFloat(), bottom.toFloat())
166+
lineTo(left.toFloat(), bottom.toFloat())
167+
lineTo(left.toFloat(), top.toFloat())
168+
169+
}
170+
}
99171

100-
canvas.drawRect(x.toFloat() + MARGIN, top.toFloat(), (x + MARGIN).toFloat(), bottom.toFloat(), paint)
172+
canvas.drawPath(fillPath, fillPaint)
173+
174+
val borderPath = Path().apply {
175+
if (isFirstLine) {
176+
moveTo(left.toFloat(), bottom.toFloat())
177+
lineTo(left.toFloat(), top.toFloat())
178+
lineTo(right.toFloat(), top.toFloat())
179+
lineTo(right.toFloat(), bottom.toFloat())
180+
if (isLastLine) {
181+
lineTo(left.toFloat(), bottom.toFloat())
182+
}
183+
} else if (isLastLine) {
184+
moveTo(left.toFloat(), top.toFloat())
185+
lineTo(left.toFloat(), bottom.toFloat())
186+
lineTo(right.toFloat(), bottom.toFloat())
187+
lineTo(right.toFloat(), top.toFloat())
188+
} else {
189+
moveTo(left.toFloat(), top.toFloat())
190+
lineTo(left.toFloat(), bottom.toFloat())
191+
moveTo(right.toFloat(), top.toFloat())
192+
lineTo(right.toFloat(), bottom.toFloat())
193+
}
194+
}
101195

102-
paint.style = style
103-
paint.color = color
196+
canvas.drawPath(borderPath, strokePaint)
104197
}
105198

199+
override fun drawLeadingMargin(canvas: Canvas, paint: Paint, x: Int, dir: Int, top: Int, baseline: Int,
200+
bottom: Int, text: CharSequence, start: Int, end: Int, first: Boolean,
201+
layout: Layout) = Unit
202+
106203
override fun getLeadingMargin(first: Boolean): Int {
107-
return MARGIN
204+
return preformatStyle.leadingMargin
108205
}
109206

110207
override val textFormat: ITextFormat = AztecTextFormat.FORMAT_PREFORMAT

aztec/src/main/kotlin/org/wordpress/aztec/spans/AztecQuoteSpan.kt

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@ import androidx.core.view.ViewCompat
2828
import android.text.Editable
2929
import android.text.Layout
3030
import android.text.Spanned
31+
import android.text.TextPaint
32+
import android.text.style.CharacterStyle
33+
import android.text.style.LeadingMarginSpan
3134
import android.text.style.LineBackgroundSpan
3235
import android.text.style.LineHeightSpan
33-
import android.text.style.QuoteSpan
36+
import android.text.style.UpdateAppearance
3437
import android.text.style.UpdateLayout
3538
import androidx.collection.ArrayMap
3639
import org.wordpress.aztec.AlignmentRendering
@@ -44,7 +47,7 @@ fun createAztecQuoteSpan(
4447
nestingLevel: Int,
4548
attributes: AztecAttributes = AztecAttributes(),
4649
alignmentRendering: AlignmentRendering,
47-
quoteStyle: BlockFormatter.QuoteStyle = BlockFormatter.QuoteStyle(0, 0, 0f, 0, 0, 0, 0)
50+
quoteStyle: BlockFormatter.QuoteStyle = BlockFormatter.QuoteStyle(0, 0, 0, 0f, 0, 0, 0, 0)
4851
) = when (alignmentRendering) {
4952
AlignmentRendering.SPAN_LEVEL -> AztecQuoteSpanAligned(nestingLevel, attributes, quoteStyle, null)
5053
AlignmentRendering.VIEW_LEVEL -> AztecQuoteSpan(nestingLevel, attributes, quoteStyle)
@@ -69,11 +72,12 @@ open class AztecQuoteSpan(
6972
override var nestingLevel: Int,
7073
override var attributes: AztecAttributes,
7174
var quoteStyle: BlockFormatter.QuoteStyle
72-
) : QuoteSpan(),
75+
) : CharacterStyle(), LeadingMarginSpan,
7376
LineBackgroundSpan,
7477
IAztecBlockSpan,
7578
LineHeightSpan,
76-
UpdateLayout {
79+
UpdateLayout,
80+
UpdateAppearance {
7781

7882
override var endBeforeBleed: Int = -1
7983
override var startBeforeCollapse: Int = -1
@@ -84,18 +88,49 @@ open class AztecQuoteSpan(
8488

8589
override val TAG: String = "blockquote"
8690

87-
override fun chooseHeight(text: CharSequence, start: Int, end: Int, spanstartv: Int, v: Int, fm: Paint.FontMetricsInt) {
91+
private var originalAscent: Int = 0
92+
private var originalTop: Int = 0
93+
private var originalDescent: Int = 0
94+
private var originalBottom: Int = 0
95+
96+
// this method adds extra padding to the top and bottom lines of the text while removing it from middle lines
97+
override fun chooseHeight(text: CharSequence, start: Int, end: Int, spanstartv: Int, v: Int,
98+
fm: Paint.FontMetricsInt) {
8899
val spanned = text as Spanned
89100
val spanStart = spanned.getSpanStart(this)
90101
val spanEnd = spanned.getSpanEnd(this)
102+
val isFirstLine = start <= spanStart
103+
val isLastLine = spanEnd <= end
104+
105+
if (isFirstLine) {
106+
originalAscent = fm.ascent
107+
originalTop = fm.top
108+
originalDescent = fm.descent
109+
originalBottom = fm.bottom
91110

92-
if (start == spanStart || start < spanStart) {
93111
fm.ascent -= quoteStyle.verticalPadding
94112
fm.top -= quoteStyle.verticalPadding
113+
114+
if (!isLastLine) {
115+
fm.descent = originalDescent
116+
fm.bottom = originalBottom
117+
}
95118
}
96-
if (end == spanEnd || spanEnd < end) {
119+
if (isLastLine) {
97120
fm.descent += quoteStyle.verticalPadding
98121
fm.bottom += quoteStyle.verticalPadding
122+
123+
if (!isFirstLine) {
124+
fm.ascent = originalAscent
125+
fm.top = originalTop
126+
}
127+
}
128+
129+
if (!isFirstLine && !isLastLine) {
130+
fm.ascent = originalAscent
131+
fm.top = originalTop
132+
fm.descent = originalDescent
133+
fm.bottom = originalBottom
99134
}
100135
}
101136

@@ -199,4 +234,8 @@ open class AztecQuoteSpan(
199234
}
200235

201236
override val textFormat: ITextFormat = AztecTextFormat.FORMAT_QUOTE
237+
238+
override fun updateDrawState(tp: TextPaint?) {
239+
tp?.color = quoteStyle.quoteTextColor
240+
}
202241
}

aztec/src/main/res/values/attrs.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,20 @@
2727
<attr name="preformatBackground" format="reference|color" />
2828
<attr name="preformatBackgroundAlpha" format="reference|fraction" />
2929
<attr name="preformatColor" format="reference|color" />
30+
<attr name="preformatBorderColor" format="reference|color" />
31+
<attr name="preformatBorderRadius" format="reference|dimension" />
32+
<attr name="preformatBorderThickness" format="reference|dimension" />
33+
<attr name="preformatLeadingMargin" format="reference|dimension" />
34+
<attr name="preformatTextSize" format="reference|dimension" />
35+
<attr name="preformatVerticalPadding" format="reference|dimension" />
3036
<attr name="quoteBackground" format="reference|color" />
3137
<attr name="quoteBackgroundAlpha" format="reference|fraction" />
3238
<attr name="quoteColor" format="reference|color" />
39+
<attr name="quoteTextColor" format="reference|color" />
3340
<attr name="quoteMargin" format="reference|dimension" />
3441
<attr name="quotePadding" format="reference|dimension" />
3542
<attr name="quoteWidth" format="reference|dimension" />
43+
<attr name="quoteVerticalPadding" format="reference|dimension" />
3644
<attr name="textColor" format="reference|color" />
3745
<attr name="textColorHint" format="reference|color" />
3846
<attr name="exclusiveBlocks" format="reference|boolean" />

0 commit comments

Comments
 (0)