1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.graphics.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertTrue; 21 22 import android.graphics.Bitmap; 23 import android.graphics.Bitmap.Config; 24 import android.graphics.Canvas; 25 import android.graphics.Color; 26 import android.graphics.Paint; 27 import android.graphics.Paint.Align; 28 import android.graphics.PaintFlagsDrawFilter; 29 import android.graphics.Rect; 30 31 import androidx.test.filters.SmallTest; 32 import androidx.test.runner.AndroidJUnit4; 33 34 import org.junit.Test; 35 import org.junit.runner.RunWith; 36 37 @SmallTest 38 @RunWith(AndroidJUnit4.class) 39 public class PaintFlagsDrawFilterTest { 40 private static final float TEXT_SIZE = 20; 41 private static final float TEXT_X = 50; 42 private static final float TEXT_Y = 50; 43 private static final String TEXT = "Test"; 44 private static final int BITMAP_WIDTH = 100; 45 private static final int BITMAP_HEIGHT = 100; 46 47 private float mTextWidth; 48 49 @Test testPaintFlagsDrawFilter()50 public void testPaintFlagsDrawFilter() { 51 Bitmap bitmapWithoutFilter = drawText(null); 52 53 PaintFlagsDrawFilter filter = new PaintFlagsDrawFilter(Paint.UNDERLINE_TEXT_FLAG, 0); 54 Bitmap bitmapWithFilter = drawText(filter); 55 56 Bitmap combined = delta(bitmapWithoutFilter, bitmapWithFilter); 57 verifyUnderline(combined); 58 } 59 drawText(PaintFlagsDrawFilter filter)60 private Bitmap drawText(PaintFlagsDrawFilter filter) { 61 Paint p = new Paint(Paint.UNDERLINE_TEXT_FLAG); 62 p.setColor(Color.RED); 63 p.setTextSize(TEXT_SIZE); 64 p.setTextAlign(Align.CENTER); 65 mTextWidth = p.measureText(TEXT); 66 Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888); 67 Canvas c = new Canvas(b); 68 c.setDrawFilter(filter); 69 c.drawColor(Color.BLACK); 70 c.drawText(TEXT, TEXT_X, TEXT_Y, p); 71 return b; 72 } 73 delta(Bitmap bitmapWithoutFilter, Bitmap bitmapWithFilter)74 private Bitmap delta(Bitmap bitmapWithoutFilter, Bitmap bitmapWithFilter) { 75 Bitmap combinedBitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888); 76 combinedBitmap.eraseColor(Color.BLACK); 77 int pixelWithoutFilter; 78 int pixelWithFilter; 79 for (int i = 0; i < BITMAP_WIDTH; i++) { 80 for (int j = 0; j < BITMAP_HEIGHT; j++) { 81 pixelWithoutFilter = bitmapWithoutFilter.getPixel(i, j); 82 pixelWithFilter = bitmapWithFilter.getPixel(i, j); 83 if (pixelWithoutFilter != pixelWithFilter) { 84 assertEquals(Color.RED, pixelWithoutFilter); 85 assertEquals(Color.BLACK, pixelWithFilter); 86 combinedBitmap.setPixel(i, j, Color.RED); 87 } 88 } 89 } 90 return combinedBitmap; 91 } 92 verifyUnderline(Bitmap bitmap)93 private void verifyUnderline(Bitmap bitmap) { 94 // Find smallest rectangle containing all RED pixels 95 Rect rect = new Rect(BITMAP_WIDTH, BITMAP_HEIGHT, 0, 0); 96 for (int y = 0; y < BITMAP_HEIGHT; y++) { 97 for (int x = 0; x < BITMAP_WIDTH; x++) { 98 int pixel = bitmap.getPixel(x, y); 99 if (pixel == Color.RED) { 100 rect.left = Math.min(rect.left, x); 101 rect.right = Math.max(rect.right, x); 102 rect.top = Math.min(rect.top, y); 103 rect.bottom = Math.max(rect.bottom, y); 104 } 105 } 106 } 107 // underline is at least one pixel high 108 assertTrue(rect.top <= rect.bottom); 109 // underline is roughly the same length at the text (5% tolerance) 110 assertEquals(mTextWidth, rect.right - rect.left, mTextWidth * 0.053); 111 // underline is under the text or at least at the bottom of it 112 assertTrue(rect.top >= TEXT_Y); 113 } 114 115 // Tests that FILTER_BITMAP_FLAG is handled properly. 116 @Test testPaintFlagsDrawFilter2()117 public void testPaintFlagsDrawFilter2() { 118 // Create a bitmap with alternating black and white pixels. 119 int kWidth = 5; 120 int kHeight = 5; 121 int colors[] = new int [] { Color.WHITE, Color.BLACK }; 122 int k = 0; 123 Bitmap grid = Bitmap.createBitmap(kWidth, kHeight, Config.ARGB_8888); 124 for (int i = 0; i < kWidth; ++i) { 125 for (int j = 0; j < kHeight; ++j) { 126 grid.setPixel(i, j, colors[k]); 127 k = (k + 1) % 2; 128 } 129 } 130 131 // Setup a scaled canvas for drawing the bitmap, with and without FILTER_BITMAP_FLAG set. 132 // When the flag is set, there will be gray pixels. When the flag is not set, all pixels 133 // will be either black or white. 134 int kScale = 5; 135 Bitmap dst = Bitmap.createBitmap(kWidth * kScale, kHeight * kScale, Config.ARGB_8888); 136 Canvas canvas = new Canvas(dst); 137 canvas.scale(kScale, kScale); 138 139 // Drawn without FILTER_BITMAP_FLAG, all pixels will be black or white. 140 Paint simplePaint = new Paint(); 141 simplePaint.setFilterBitmap(false); 142 canvas.drawBitmap(grid, 0, 0, simplePaint); 143 144 verifyContainsOnlyBlackAndWhite(dst); 145 146 // Drawn with FILTER_BITMAP_FLAG, some pixels will be somewhere in between. 147 Paint filterBitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG); 148 canvas.drawBitmap(grid, 0, 0, filterBitmapPaint); 149 150 verifyContainsNonBW(dst); 151 152 // Drawing with a paint that FILTER_BITMAP_FLAG set and a DrawFilter that removes 153 // FILTER_BITMAP_FLAG should remove the effect of the flag, resulting in all pixels being 154 // either black or white. 155 canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0)); 156 canvas.drawBitmap(grid, 0, 0, filterBitmapPaint); 157 158 verifyContainsOnlyBlackAndWhite(dst); 159 160 // Likewise, drawing with a DrawFilter that sets FILTER_BITMAP_FLAG should filter, 161 // resulting in gray pixels. 162 canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG)); 163 canvas.drawBitmap(grid, 0, 0, simplePaint); 164 165 verifyContainsNonBW(dst); 166 } 167 168 // Assert that at least one pixel is neither black nor white. This is used to verify that 169 // filtering was done, since the original bitmap only contained black and white pixels. verifyContainsNonBW(Bitmap bitmap)170 private void verifyContainsNonBW(Bitmap bitmap) { 171 for (int i = 0; i < bitmap.getWidth(); ++i) { 172 for (int j = 0; j < bitmap.getHeight(); ++j) { 173 int color = bitmap.getPixel(i, j); 174 if (color != Color.BLACK && color != Color.WHITE) { 175 // Filtering must have been done. 176 return; 177 } 178 } 179 } 180 // Filtering did not happen. 181 assertTrue(false); 182 } 183 184 // Assert that every pixel is either black or white. Used to verify that no filtering was 185 // done, since the original bitmap contained only black and white pixels. verifyContainsOnlyBlackAndWhite(Bitmap bitmap)186 private void verifyContainsOnlyBlackAndWhite(Bitmap bitmap) { 187 for (int i = 0; i < bitmap.getWidth(); ++i) { 188 for (int j = 0; j < bitmap.getHeight(); ++j) { 189 int color = bitmap.getPixel(i, j); 190 assertTrue(color == Color.BLACK || color == Color.WHITE); 191 } 192 } 193 } 194 } 195