@@ -27,7 +27,9 @@ import android.graphics.Paint
2727import android.graphics.PointF
2828import android.graphics.Typeface
2929import android.widget.EditText
30+ import android.widget.RelativeLayout
3031import androidx.core.content.res.ResourcesCompat
32+ import androidx.core.view.isVisible
3133import androidx.recyclerview.widget.RecyclerView
3234import androidx.test.espresso.Espresso
3335import androidx.test.espresso.Espresso.onView
@@ -61,6 +63,7 @@ import org.catrobat.paintroid.tools.FontType
6163import org.catrobat.paintroid.tools.ToolReference
6264import org.catrobat.paintroid.tools.ToolType
6365import org.catrobat.paintroid.tools.implementation.BOX_OFFSET
66+ import org.catrobat.paintroid.tools.implementation.DEFAULT_TEXT_OUTLINE_WIDTH
6467import org.catrobat.paintroid.tools.implementation.MARGIN_TOP
6568import org.catrobat.paintroid.tools.implementation.TEXT_SIZE_MAGNIFICATION_FACTOR
6669import org.catrobat.paintroid.tools.implementation.TextTool
@@ -90,6 +93,8 @@ class TextToolIntegrationTest {
9093 private var underlinedToggleButton: MaterialButton ? = null
9194 private var italicToggleButton: MaterialButton ? = null
9295 private var boldToggleButton: MaterialButton ? = null
96+ private var outlineToggleButton: MaterialButton ? = null
97+ private var outlineWidthLayout: RelativeLayout ? = null
9398 private var textSize: EditText ? = null
9499 private var layerModel: LayerContracts .Model ? = null
95100 private lateinit var activity: MainActivity
@@ -116,6 +121,8 @@ class TextToolIntegrationTest {
116121 activity.findViewById(R .id.pocketpaint_text_tool_dialog_toggle_underlined)
117122 italicToggleButton = activity.findViewById(R .id.pocketpaint_text_tool_dialog_toggle_italic)
118123 boldToggleButton = activity.findViewById(R .id.pocketpaint_text_tool_dialog_toggle_bold)
124+ outlineToggleButton = activity.findViewById(R .id.pocketpaint_text_tool_dialog_toggle_outline)
125+ outlineWidthLayout = activity.findViewById(R .id.pocketpaint_outline_width_layout)
119126 textSize = activity.findViewById(R .id.pocketpaint_font_size_text)
120127 textTool?.resetBoxPosition()
121128 }
@@ -125,6 +132,7 @@ class TextToolIntegrationTest {
125132 selectFormatting(FormattingOptions .ITALIC )
126133 selectFormatting(FormattingOptions .BOLD )
127134 selectFormatting(FormattingOptions .UNDERLINE )
135+ selectFormatting(FormattingOptions .OUTLINE )
128136 enterTestText()
129137 onView(withId(R .id.pocketpaint_text_tool_dialog_input_text)).perform(click())
130138 onView(withId(R .id.pocketpaint_text_tool_dialog_input_text)).perform(
@@ -135,12 +143,14 @@ class TextToolIntegrationTest {
135143 italicToggleButton?.let { Assert .assertTrue(it.isChecked) }
136144 boldToggleButton?.let { Assert .assertTrue(it.isChecked) }
137145 underlinedToggleButton?.let { Assert .assertTrue(it.isChecked) }
146+ outlineToggleButton?.let { Assert .assertTrue(it.isChecked) }
138147 Assert .assertEquals(TEST_TEXT_ADVANCED , textEditText?.text?.toString())
139148 onView(withId(R .id.pocketpaint_text_tool_dialog_input_text)).check(matches(isDisplayed()))
140149 onView(withId(R .id.pocketpaint_text_tool_dialog_list_font)).check(matches(isDisplayed()))
141150 onView(withId(R .id.pocketpaint_text_tool_dialog_toggle_underlined)).check(matches(isDisplayed()))
142151 onView(withId(R .id.pocketpaint_text_tool_dialog_toggle_italic)).check(matches(isDisplayed()))
143152 onView(withId(R .id.pocketpaint_text_tool_dialog_toggle_bold)).check(matches(isDisplayed()))
153+ onView(withId(R .id.pocketpaint_text_tool_dialog_toggle_outline)).check(matches(isDisplayed()))
144154 onView(withId(R .id.pocketpaint_font_size_text)).check(matches(isDisplayed()))
145155 }
146156
@@ -149,13 +159,15 @@ class TextToolIntegrationTest {
149159 selectFormatting(FormattingOptions .ITALIC )
150160 selectFormatting(FormattingOptions .BOLD )
151161 selectFormatting(FormattingOptions .UNDERLINE )
162+ selectFormatting(FormattingOptions .OUTLINE )
152163 enterTestText()
153164 onDrawingSurfaceView()
154165 .perform(UiInteractions .touchAt(DrawingSurfaceLocationProvider .MIDDLE ))
155166
156167 italicToggleButton?.let { Assert .assertTrue(it.isChecked) }
157168 boldToggleButton?.let { Assert .assertTrue(it.isChecked) }
158169 underlinedToggleButton?.let { Assert .assertTrue(it.isChecked) }
170+ outlineToggleButton?.let { Assert .assertTrue(it.isChecked) }
159171 Assert .assertEquals(TEST_TEXT , textEditText?.text?.toString())
160172 onView(withId(R .id.pocketpaint_text_tool_dialog_input_text))
161173 .check(matches(not (isDisplayed())))
@@ -167,6 +179,8 @@ class TextToolIntegrationTest {
167179 .check(matches(not (isDisplayed())))
168180 onView(withId(R .id.pocketpaint_text_tool_dialog_toggle_bold))
169181 .check(matches(not (isDisplayed())))
182+ onView(withId(R .id.pocketpaint_text_tool_dialog_toggle_outline))
183+ .check(matches(not (isDisplayed())))
170184 onView(withId(R .id.pocketpaint_font_size_text))
171185 .check(matches(not (isDisplayed())))
172186 }
@@ -247,6 +261,8 @@ class TextToolIntegrationTest {
247261 textTool?.let { Assert .assertFalse(it.underlined) }
248262 textTool?.let { Assert .assertFalse(it.italic) }
249263 textTool?.let { Assert .assertFalse(it.bold) }
264+ textTool?.let { Assert .assertFalse(it.outlined) }
265+ outlineWidthLayout?.let { Assert .assertFalse(it.isVisible) }
250266 }
251267
252268 @Test
@@ -292,6 +308,20 @@ class TextToolIntegrationTest {
292308 Assert .assertFalse(toolMemberBold)
293309 boldToggleButton?.let { Assert .assertFalse(it.isChecked) }
294310 Assert .assertEquals(getFormattingOptionAsString(FormattingOptions .BOLD ), boldToggleButton?.text.toString())
311+ selectFormatting(FormattingOptions .OUTLINE )
312+ textTool?.let { Assert .assertTrue(it.outlined) }
313+ outlineToggleButton?.let { Assert .assertTrue(it.isChecked) }
314+ Assert .assertEquals(
315+ getFormattingOptionAsString(FormattingOptions .OUTLINE ),
316+ outlineToggleButton?.text.toString()
317+ )
318+ selectFormatting(FormattingOptions .OUTLINE )
319+ textTool?.let { Assert .assertFalse(it.outlined) }
320+ outlineToggleButton?.let { Assert .assertFalse(it.isChecked) }
321+ Assert .assertEquals(
322+ getFormattingOptionAsString(FormattingOptions .OUTLINE ),
323+ outlineToggleButton?.text.toString()
324+ )
295325 }
296326
297327 @Test
@@ -301,6 +331,7 @@ class TextToolIntegrationTest {
301331 selectFormatting(FormattingOptions .UNDERLINE )
302332 selectFormatting(FormattingOptions .ITALIC )
303333 selectFormatting(FormattingOptions .BOLD )
334+ selectFormatting(FormattingOptions .OUTLINE )
304335 onToolBarView().performCloseToolOptionsView()
305336
306337 val oldBoxWidth = toolMemberBoxWidth
@@ -318,6 +349,7 @@ class TextToolIntegrationTest {
318349 underlinedToggleButton?.let { Assert .assertTrue(it.isChecked) }
319350 italicToggleButton?.let { Assert .assertTrue(it.isChecked) }
320351 boldToggleButton?.let { Assert .assertTrue(it.isChecked) }
352+ outlineToggleButton?.let { Assert .assertTrue(it.isChecked) }
321353 Assert .assertTrue(oldBoxWidth == toolMemberBoxWidth && oldBoxHeight == toolMemberBoxHeight)
322354 }
323355
@@ -328,6 +360,7 @@ class TextToolIntegrationTest {
328360 selectFormatting(FormattingOptions .UNDERLINE )
329361 selectFormatting(FormattingOptions .ITALIC )
330362 selectFormatting(FormattingOptions .BOLD )
363+ selectFormatting(FormattingOptions .OUTLINE )
331364
332365 val toolMemberBoxPosition = toolMemberBoxPosition
333366 val expectedPosition = toolMemberBoxPosition?.y?.let { PointF (toolMemberBoxPosition.x, it) }
@@ -344,6 +377,7 @@ class TextToolIntegrationTest {
344377 underlinedToggleButton?.let { Assert .assertTrue(it.isChecked) }
345378 italicToggleButton?.let { Assert .assertTrue(it.isChecked) }
346379 boldToggleButton?.let { Assert .assertTrue(it.isChecked) }
380+ outlineToggleButton?.let { Assert .assertTrue(it.isChecked) }
347381 Assert .assertEquals(expectedPosition, toolMemberBoxPosition)
348382 Assert .assertEquals(oldBoxWidth.toDouble(), toolMemberBoxWidth.toDouble(), EQUALS_DELTA )
349383 Assert .assertEquals(oldBoxHeight.toDouble(), toolMemberBoxHeight.toDouble(), EQUALS_DELTA )
@@ -750,6 +784,7 @@ class TextToolIntegrationTest {
750784 selectFormatting(FormattingOptions .ITALIC )
751785 selectFormatting(FormattingOptions .BOLD )
752786 selectFormatting(FormattingOptions .UNDERLINE )
787+ selectFormatting(FormattingOptions .OUTLINE )
753788 }
754789 val boxWidth = toolMemberBoxWidth
755790 val boxHeight = toolMemberBoxHeight
@@ -759,10 +794,120 @@ class TextToolIntegrationTest {
759794 selectFormatting(FormattingOptions .ITALIC )
760795 selectFormatting(FormattingOptions .BOLD )
761796 selectFormatting(FormattingOptions .UNDERLINE )
797+ selectFormatting(FormattingOptions .OUTLINE )
762798 Assert .assertTrue(boxWidth < toolMemberBoxWidth && boxHeight < toolMemberBoxHeight)
763799 }
764800 }
765801
802+ @Test
803+ fun testTextOutlineMode () {
804+ enterTestText()
805+ val canvasPoint = centerBox()
806+ onTopBarView().performClickCheckmark()
807+ val surfaceBitmapWidth = layerModel?.width
808+ val pixelsDrawingSurface = surfaceBitmapWidth?.let { IntArray (it) }
809+ if (surfaceBitmapWidth != null && canvasPoint != null ) {
810+ layerModel?.currentLayer?.bitmap?.getPixels(
811+ pixelsDrawingSurface, 0 , surfaceBitmapWidth, 0 ,
812+ canvasPoint.y.toInt(), surfaceBitmapWidth, 1
813+ )
814+ }
815+ val blackPixelAmountNoOutline = pixelsDrawingSurface?.let { countPixelsWithColor(it, Color .BLACK ) }
816+ val whitePixelAmountNoOutline = pixelsDrawingSurface?.let { countPixelsWithColor(it, Color .WHITE ) }
817+ onTopBarView().performUndo()
818+
819+ selectFormatting(FormattingOptions .OUTLINE )
820+ textTool?.let { Assert .assertTrue(it.outlined) }
821+
822+ onTopBarView().performClickCheckmark()
823+
824+ if (surfaceBitmapWidth != null && canvasPoint != null ) {
825+ layerModel?.currentLayer?.bitmap?.getPixels(
826+ pixelsDrawingSurface, 0 , surfaceBitmapWidth, 0 ,
827+ canvasPoint.y.toInt(), surfaceBitmapWidth, 1
828+ )
829+ }
830+
831+ val blackPixelAmountWithOutline = pixelsDrawingSurface?.let { countPixelsWithColor(it, Color .BLACK ) }
832+ if (blackPixelAmountNoOutline != null && blackPixelAmountWithOutline != null ) {
833+ assert (blackPixelAmountNoOutline > blackPixelAmountWithOutline)
834+ assert (blackPixelAmountWithOutline > 0 )
835+ }
836+
837+ val whitePixelAmountWithOutline = pixelsDrawingSurface?.let { countPixelsWithColor(it, Color .WHITE ) }
838+ if (whitePixelAmountNoOutline != null && whitePixelAmountWithOutline != null ) {
839+ assert (whitePixelAmountNoOutline < whitePixelAmountWithOutline)
840+ }
841+ }
842+
843+ @Test
844+ fun testTextOutlineWidth () {
845+ val canvasPoint = centerBox()
846+ selectFormatting(FormattingOptions .OUTLINE )
847+ textTool?.let { Assert .assertTrue(it.outlined) }
848+ outlineWidthLayout?.let { Assert .assertTrue(it.isVisible) }
849+ val outlineWidthInput = onView(withId(R .id.pocketpaint_outline_width_text))
850+ val outlineWidthSeekbar = onView(withId(R .id.pocketpaint_outline_width_seek_bar))
851+ outlineWidthInput.check(matches(ViewMatchers .withText(DEFAULT_TEXT_OUTLINE_WIDTH .toString())))
852+ outlineWidthSeekbar.check(matches(UiMatcher .withProgress(DEFAULT_TEXT_OUTLINE_WIDTH )))
853+
854+ enterTestText()
855+
856+ var testOutlineWidthText = " 1"
857+
858+ outlineWidthInput.perform(
859+ ViewActions .replaceText(testOutlineWidthText),
860+ ViewActions .closeSoftKeyboard()
861+ )
862+ outlineWidthInput.check(matches(ViewMatchers .withText(testOutlineWidthText)))
863+ outlineWidthSeekbar.check(matches(UiMatcher .withProgress(testOutlineWidthText.toInt())))
864+
865+ onTopBarView().performClickCheckmark()
866+ val surfaceBitmapWidth = layerModel?.width
867+ val pixelsDrawingSurface = surfaceBitmapWidth?.let { IntArray (it) }
868+ if (surfaceBitmapWidth != null && canvasPoint != null ) {
869+ layerModel?.currentLayer?.bitmap?.getPixels(
870+ pixelsDrawingSurface, 0 , surfaceBitmapWidth, 0 ,
871+ canvasPoint.y.toInt(), surfaceBitmapWidth, 1
872+ )
873+ }
874+ val blackPixelAmountThinOutline = pixelsDrawingSurface?.let { countPixelsWithColor(it, Color .BLACK ) }
875+ val whitePixelAmountThinOutline = pixelsDrawingSurface?.let { countPixelsWithColor(it, Color .WHITE ) }
876+ onTopBarView().performUndo()
877+
878+ testOutlineWidthText = " 60"
879+
880+ outlineWidthInput.perform(
881+ ViewActions .replaceText(testOutlineWidthText),
882+ ViewActions .closeSoftKeyboard()
883+ )
884+ outlineWidthInput.check(matches(ViewMatchers .withText(testOutlineWidthText)))
885+ outlineWidthSeekbar.check(matches(UiMatcher .withProgress(testOutlineWidthText.toInt())))
886+
887+ onTopBarView().performClickCheckmark()
888+
889+ if (surfaceBitmapWidth != null && canvasPoint != null ) {
890+ layerModel?.currentLayer?.bitmap?.getPixels(
891+ pixelsDrawingSurface, 0 , surfaceBitmapWidth, 0 ,
892+ canvasPoint.y.toInt(), surfaceBitmapWidth, 1
893+ )
894+ }
895+
896+ val blackPixelAmountThickOutline = pixelsDrawingSurface?.let { countPixelsWithColor(it, Color .BLACK ) }
897+ if (blackPixelAmountThinOutline != null && blackPixelAmountThickOutline != null ) {
898+ assert (blackPixelAmountThinOutline > 0 )
899+ assert (blackPixelAmountThickOutline > 0 )
900+ assert (blackPixelAmountThickOutline > blackPixelAmountThinOutline)
901+ }
902+
903+ val whitePixelAmountThickOutline = pixelsDrawingSurface?.let { countPixelsWithColor(it, Color .WHITE ) }
904+ if (whitePixelAmountThinOutline != null && whitePixelAmountThickOutline != null ) {
905+ assert (whitePixelAmountThinOutline > 0 )
906+ assert (whitePixelAmountThickOutline > 0 )
907+ assert (whitePixelAmountThickOutline < whitePixelAmountThinOutline)
908+ }
909+ }
910+
766911 private fun centerBox (): PointF ? {
767912 val screenPoint =
768913 activityHelper?.displayWidth?.div(2.0f )
@@ -892,6 +1037,7 @@ class TextToolIntegrationTest {
8921037 FormattingOptions .UNDERLINE -> activity.getString(R .string.text_tool_dialog_underline_shortcut)
8931038 FormattingOptions .ITALIC -> activity.getString(R .string.text_tool_dialog_italic_shortcut)
8941039 FormattingOptions .BOLD -> activity.getString(R .string.text_tool_dialog_bold_shortcut)
1040+ FormattingOptions .OUTLINE -> activity.getString(R .string.text_tool_dialog_outline_shortcut)
8951041 }
8961042 }
8971043
@@ -921,7 +1067,7 @@ class TextToolIntegrationTest {
9211067 private val toolMemberMultilineText: Array <String >
9221068 get() = textTool!! .multilineText
9231069
924- private enum class FormattingOptions { UNDERLINE , ITALIC , BOLD }
1070+ private enum class FormattingOptions { UNDERLINE , ITALIC , BOLD , OUTLINE }
9251071
9261072 companion object {
9271073 private const val TEST_TEXT = " 123 www 123"
0 commit comments