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 
20 import android.graphics.Bitmap;
21 import android.graphics.Canvas;
22 import android.graphics.Color;
23 import android.graphics.Paint;
24 import android.graphics.PaintFlagsDrawFilter;
25 import android.graphics.Rect;
26 import android.graphics.Bitmap.Config;
27 import android.graphics.Paint.Align;
28 import android.test.AndroidTestCase;
29 
30 public class PaintFlagsDrawFilterTest extends AndroidTestCase {
31 
32     private static final float TEXT_SIZE = 20;
33     private static final float TEXT_X = 50;
34     private static final float TEXT_Y = 50;
35     private static final String TEXT = "Test";
36     private static final int BITMAP_WIDTH = 100;
37     private static final int BITMAP_HEIGHT = 100;
38     private float mTextWidth;
39 
40     @Override
setUp()41     protected void setUp() throws Exception {
42         super.setUp();
43     }
44 
testPaintFlagsDrawFilter()45     public void testPaintFlagsDrawFilter() {
46 
47         Bitmap bitmapWithoutFilter = drawText(null);
48 
49         PaintFlagsDrawFilter filter = new PaintFlagsDrawFilter(Paint.UNDERLINE_TEXT_FLAG, 0);
50         Bitmap bitmapWithFilter = drawText(filter);
51 
52         Bitmap combined = delta(bitmapWithoutFilter, bitmapWithFilter);
53         assertUnderline(combined);
54     }
55 
drawText(PaintFlagsDrawFilter filter)56     private Bitmap drawText(PaintFlagsDrawFilter filter) {
57         Paint p = new Paint(Paint.UNDERLINE_TEXT_FLAG);
58         p.setColor(Color.RED);
59         p.setTextSize(TEXT_SIZE);
60         p.setTextAlign(Align.CENTER);
61         mTextWidth = p.measureText(TEXT);
62         Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888);
63         Canvas c = new Canvas(b);
64         c.setDrawFilter(filter);
65         c.drawColor(Color.BLACK);
66         c.drawText(TEXT, TEXT_X, TEXT_Y, p);
67         return b;
68     }
69 
delta(Bitmap bitmapWithoutFilter, Bitmap bitmapWithFilter)70     private Bitmap delta(Bitmap bitmapWithoutFilter, Bitmap bitmapWithFilter) {
71         Bitmap combinedBitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888);
72         combinedBitmap.eraseColor(Color.BLACK);
73         int pixelWithoutFilter;
74         int pixelWithFilter;
75         for (int i = 0; i < BITMAP_WIDTH; i++) {
76             for (int j = 0; j < BITMAP_HEIGHT; j++) {
77                 pixelWithoutFilter = bitmapWithoutFilter.getPixel(i, j);
78                 pixelWithFilter = bitmapWithFilter.getPixel(i, j);
79                 if (pixelWithoutFilter != pixelWithFilter) {
80                     assertEquals(Color.RED, pixelWithoutFilter);
81                     assertEquals(Color.BLACK, pixelWithFilter);
82                     combinedBitmap.setPixel(i, j, Color.RED);
83                 }
84             }
85         }
86         return combinedBitmap;
87     }
88 
assertUnderline(Bitmap bitmap)89     private void assertUnderline(Bitmap bitmap) {
90         // Find smallest rectangle containing all RED pixels
91         Rect rect = new Rect(BITMAP_WIDTH, BITMAP_HEIGHT, 0, 0);
92         for (int y = 0; y < BITMAP_HEIGHT; y++) {
93             for (int x = 0; x < BITMAP_WIDTH; x++) {
94                 int pixel = bitmap.getPixel(x, y);
95                 if (pixel == Color.RED) {
96                     rect.left = Math.min(rect.left, x);
97                     rect.right = Math.max(rect.right, x);
98                     rect.top = Math.min(rect.top, y);
99                     rect.bottom = Math.max(rect.bottom, y);
100                 }
101             }
102         }
103         // underline is at least one pixel high
104         assertTrue(rect.top <= rect.bottom);
105         // underline is roughly the same length at the text (5% tolerance)
106         assertEquals(mTextWidth, rect.right - rect.left, mTextWidth * 0.053);
107         // underline is under the text or at least at the bottom of it
108         assertTrue(rect.top >= TEXT_Y);
109     }
110 
111     // Tests that FILTER_BITMAP_FLAG is handled properly.
testPaintFlagsDrawFilter2()112     public void testPaintFlagsDrawFilter2() {
113         // Create a bitmap with alternating black and white pixels.
114         int kWidth = 5;
115         int kHeight = 5;
116         int colors[] = new int [] { Color.WHITE, Color.BLACK };
117         int k = 0;
118         Bitmap grid = Bitmap.createBitmap(kWidth, kHeight, Config.ARGB_8888);
119         for (int i = 0; i < kWidth; ++i) {
120             for (int j = 0; j < kHeight; ++j) {
121                 grid.setPixel(i, j, colors[k]);
122                 k = (k + 1) % 2;
123             }
124         }
125 
126         // Setup a scaled canvas for drawing the bitmap, with and without FILTER_BITMAP_FLAG set.
127         // When the flag is set, there will be gray pixels. When the flag is not set, all pixels
128         // will be either black or white.
129         int kScale = 5;
130         Bitmap dst = Bitmap.createBitmap(kWidth * kScale, kHeight * kScale, Config.ARGB_8888);
131         Canvas canvas = new Canvas(dst);
132         canvas.scale(kScale, kScale);
133 
134         // Drawn without FILTER_BITMAP_FLAG, all pixels will be black or white.
135         Paint simplePaint = new Paint();
136         canvas.drawBitmap(grid, 0, 0, simplePaint);
137 
138         assertContainsOnlyBlackAndWhite(dst);
139 
140         // Drawn with FILTER_BITMAP_FLAG, some pixels will be somewhere in between.
141         Paint filterBitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
142         canvas.drawBitmap(grid, 0, 0, filterBitmapPaint);
143 
144         assertContainsNonBW(dst);
145 
146         // Drawing with a paint that FILTER_BITMAP_FLAG set and a DrawFilter that removes
147         // FILTER_BITMAP_FLAG should remove the effect of the flag, resulting in all pixels being
148         // either black or white.
149         canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0));
150         canvas.drawBitmap(grid, 0, 0, filterBitmapPaint);
151 
152         assertContainsOnlyBlackAndWhite(dst);
153 
154         // Likewise, drawing with a DrawFilter that sets FILTER_BITMAP_FLAG should filter,
155         // resulting in gray pixels.
156         canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG));
157         canvas.drawBitmap(grid, 0, 0, simplePaint);
158 
159         assertContainsNonBW(dst);
160     }
161 
162     // Assert that at least one pixel is neither black nor white. This is used to verify that
163     // filtering was done, since the original bitmap only contained black and white pixels.
assertContainsNonBW(Bitmap bitmap)164     private void assertContainsNonBW(Bitmap bitmap) {
165         for (int i = 0; i < bitmap.getWidth(); ++i) {
166             for (int j = 0; j < bitmap.getHeight(); ++j) {
167                 int color = bitmap.getPixel(i, j);
168                 if (color != Color.BLACK && color != Color.WHITE) {
169                     // Filtering must have been done.
170                     return;
171                 }
172             }
173         }
174         // Filtering did not happen.
175         assertTrue(false);
176     }
177 
178     // Assert that every pixel is either black or white. Used to verify that no filtering was
179     // done, since the original bitmap contained only black and white pixels.
assertContainsOnlyBlackAndWhite(Bitmap bitmap)180     private void assertContainsOnlyBlackAndWhite(Bitmap bitmap) {
181         for (int i = 0; i < bitmap.getWidth(); ++i) {
182             for (int j = 0; j < bitmap.getHeight(); ++j) {
183                 int color = bitmap.getPixel(i, j);
184                 assertTrue(color == Color.BLACK || color == Color.WHITE);
185             }
186         }
187     }
188 }
189