@@ -2,10 +2,12 @@ package org.wordpress.aztec.spans
22
33import android.graphics.Canvas
44import android.graphics.Color
5+ import android.graphics.CornerPathEffect
56import android.graphics.Paint
6- import android.graphics.Rect
7+ import android.graphics.Path
78import android.text.Layout
89import android.text.Spanned
10+ import android.text.TextPaint
911import android.text.style.LeadingMarginSpan
1012import android.text.style.LineBackgroundSpan
1113import 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
0 commit comments