12c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu/* 22c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * Copyright (C) 2015 The Android Open Source Project 32c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * 42c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * Licensed under the Apache License, Version 2.0 (the "License"); 52c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * you may not use this file except in compliance with the License. 62c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * You may obtain a copy of the License at 72c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * 82c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * http://www.apache.org/licenses/LICENSE-2.0 92c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * 102c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * Unless required by applicable law or agreed to in writing, software 112c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * distributed under the License is distributed on an "AS IS" BASIS, 122c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * See the License for the specific language governing permissions and 142c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * limitations under the License. 152c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu */ 162c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 172c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhupackage android.support.graphics.drawable.tests; 182c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 19d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikovimport android.content.Context; 202c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhuimport android.content.res.Resources; 212c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhuimport android.content.res.Resources.Theme; 221f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhuimport android.graphics.Bitmap; 231f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhuimport android.graphics.BitmapFactory; 241f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhuimport android.graphics.Canvas; 251f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhuimport android.graphics.Color; 265f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhuimport android.graphics.Rect; 272c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhuimport android.graphics.drawable.Drawable; 282c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhuimport android.support.graphics.drawable.VectorDrawableCompat; 292c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhuimport android.support.graphics.drawable.test.R; 30d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikovimport android.support.test.InstrumentationRegistry; 31d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikovimport android.support.test.runner.AndroidJUnit4; 32daea069fe33cc750bcb733ebcb6206d2dcedae76Chris Banesimport android.test.suitebuilder.annotation.MediumTest; 332c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhuimport android.util.Log; 34d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikovimport org.junit.Before; 35d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikovimport org.junit.Test; 36d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikovimport org.junit.runner.RunWith; 372c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhuimport org.xmlpull.v1.XmlPullParserException; 382c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 392c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhuimport java.io.File; 402c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhuimport java.io.FileOutputStream; 412c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhuimport java.io.IOException; 422c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 43d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikovimport static org.junit.Assert.*; 44d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikov 45d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikov@RunWith(AndroidJUnit4.class) 46daea069fe33cc750bcb733ebcb6206d2dcedae76Chris Banes@MediumTest 47d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikovpublic class VectorDrawableTest { 482c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private static final String LOGTAG = "VectorDrawableTest"; 492c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 502c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private static final int[] ICON_RES_IDS = new int[]{ 512c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_create, 522c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_delete, 532c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_heart, 542c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_schedule, 552c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_settings, 562c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_random_path_1, 572c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_random_path_2, 582c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_repeated_cq, 592c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_repeated_st, 602c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_repeated_a_1, 612c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_repeated_a_2, 622c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_clip_path_1, 632c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_transformation_1, 642c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_transformation_4, 652c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_transformation_5, 662c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_transformation_6, 672c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_render_order_1, 682c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_render_order_2, 692c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_stroke_1, 702c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_stroke_2, 712c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_stroke_3, 722c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_scale_1, 7304027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu R.drawable.vector_icon_group_clip, 74c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu R.drawable.vector_icon_share, 75c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu R.drawable.vector_icon_wishlist, 766a1b3c0484827f986524666cc017561616c4b1dbTeng-Hui Zhu R.drawable.vector_icon_five_bars, 772c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu }; 782c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 792c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private static final int[] GOLDEN_IMAGES = new int[]{ 802c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_create_golden, 812c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_delete_golden, 822c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_heart_golden, 832c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_schedule_golden, 842c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_settings_golden, 852c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_random_path_1_golden, 862c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_random_path_2_golden, 872c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_repeated_cq_golden, 882c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_repeated_st_golden, 892c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_repeated_a_1_golden, 902c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_repeated_a_2_golden, 912c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_clip_path_1_golden, 922c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_transformation_1_golden, 932c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_transformation_4_golden, 942c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_transformation_5_golden, 952c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_transformation_6_golden, 962c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_render_order_1_golden, 972c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_render_order_2_golden, 982c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_stroke_1_golden, 992c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_stroke_2_golden, 1002c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_stroke_3_golden, 1012c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu R.drawable.vector_icon_scale_1_golden, 10204027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu R.drawable.vector_icon_group_clip_golden, 103c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu R.drawable.vector_icon_share_golden, 104c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu R.drawable.vector_icon_wishlist_golden, 1056a1b3c0484827f986524666cc017561616c4b1dbTeng-Hui Zhu R.drawable.vector_icon_five_bars_golden, 1062c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu }; 1072c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 1082c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private static final int TEST_ICON = R.drawable.vector_icon_create; 1092c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 1102c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private static final int IMAGE_WIDTH = 64; 1112c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private static final int IMAGE_HEIGHT = 64; 1122c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // A small value is actually making sure that the values are matching 1132c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // exactly with the golden image. 1142c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // We can increase the threshold if the Skia is drawing with some variance 1152c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // on different devices. So far, the tests show they are matching correctly. 1162c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private static final float PIXEL_ERROR_THRESHOLD = 0.3f; 11722eca99cc198a41db5c72ad6fb981f2bd4d59313Teng-Hui Zhu private static final float PIXEL_DIFF_COUNT_THRESHOLD = 0.1f; 1182c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private static final float PIXEL_DIFF_THRESHOLD = 0.025f; 1192c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 1202c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private static final boolean DBG_DUMP_PNG = false; 1212c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 122d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikov private Context mContext; 1232c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private Resources mResources; 1242c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private VectorDrawableCompat mVectorDrawable; 1252c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private Bitmap mBitmap; 1262c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private Canvas mCanvas; 1272c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private Theme mTheme; 1282c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 129d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikov @Before 130d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikov public void setup() { 1312c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu final int width = IMAGE_WIDTH; 1322c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu final int height = IMAGE_HEIGHT; 1332c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 1342c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 1352c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu mCanvas = new Canvas(mBitmap); 1362c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 137d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikov mContext = InstrumentationRegistry.getContext(); 1382c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu mResources = mContext.getResources(); 1392c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu mTheme = mContext.getTheme(); 1402c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 1412c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 142d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikov @Test 143d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikov public void testSimpleVectorDrawables() throws Exception { 1442c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu verifyVectorDrawables(ICON_RES_IDS, GOLDEN_IMAGES, null); 1452c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 1462c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 1472c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private void verifyVectorDrawables(int[] resIds, int[] goldenImages, int[] stateSet) 1482c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu throws XmlPullParserException, IOException { 1492c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu for (int i = 0; i < resIds.length; i++) { 1502c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // Setup VectorDrawable from xml file and draw into the bitmap. 1512c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu mVectorDrawable = VectorDrawableCompat.create(mResources, resIds[i], mTheme); 1522c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu mVectorDrawable.setBounds(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); 1532c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if (stateSet != null) { 1542c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu mVectorDrawable.setState(stateSet); 1552c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 1562c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 1572c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu mBitmap.eraseColor(0); 1582c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu mVectorDrawable.draw(mCanvas); 1592c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 1602c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if (DBG_DUMP_PNG) { 1612c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu saveVectorDrawableIntoPNG(mBitmap, resIds, i, stateSet); 1622c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } else { 1632c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // Start to compare 1642c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu Bitmap golden = BitmapFactory.decodeResource(mResources, goldenImages[i]); 1652c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu compareImages(mBitmap, golden, mResources.getString(resIds[i])); 1662c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 1672c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 1682c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 1692c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 1702c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // This is only for debugging or golden image (re)generation purpose. 1712c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private void saveVectorDrawableIntoPNG(Bitmap bitmap, int[] resIds, int index, int[] stateSet) 1722c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu throws IOException { 1732c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // Save the image to the disk. 1742c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu FileOutputStream out = null; 1752c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu try { 1762c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu String outputFolder = "/sdcard/temp/"; 1772c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu File folder = new File(outputFolder); 1782c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if (!folder.exists()) { 1792c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu folder.mkdir(); 1802c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 1812c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu String originalFilePath = mResources.getString(resIds[index]); 1822c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu File originalFile = new File(originalFilePath); 1832c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu String fileFullName = originalFile.getName(); 1842c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu String fileTitle = fileFullName.substring(0, fileFullName.lastIndexOf(".")); 1852c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu String stateSetTitle = getTitleForStateSet(stateSet); 1862c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu String outputFilename = outputFolder + fileTitle + "_golden" + stateSetTitle + ".png"; 1872c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu File outputFile = new File(outputFilename); 1882c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if (!outputFile.exists()) { 1892c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu outputFile.createNewFile(); 1902c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 1912c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 1922c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu out = new FileOutputStream(outputFile, false); 1932c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); 1942c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu Log.v(LOGTAG, "Write test No." + index + " to file successfully."); 1952c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } catch (Exception e) { 1962c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu e.printStackTrace(); 1972c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } finally { 1982c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if (out != null) { 1992c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu out.close(); 2002c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2012c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2022c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2032c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2042c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu /** 2052c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * Generates an underline-delimited list of states in a given state set. 2062c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * <p/> 2072c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * For example, the array {@code {R.attr.state_pressed}} would return 2082c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * {@code "_pressed"}. 2092c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * 2102c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * @param stateSet a state set 2112c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * @return a string representing the state set, or the empty string if the 2122c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * state set is empty or {@code null} 2132c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu */ 2142c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private String getTitleForStateSet(int[] stateSet) { 2152c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if (stateSet == null || stateSet.length == 0) { 2162c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return ""; 2172c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2182c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2192c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu final StringBuilder builder = new StringBuilder(); 2202c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu for (int i = 0; i < stateSet.length; i++) { 2212c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu builder.append('_'); 2222c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 223d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikov final String state = mResources.getResourceName(stateSet[i]); 2242c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu final int stateIndex = state.indexOf("state_"); 2252c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if (stateIndex >= 0) { 2262c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu builder.append(state.substring(stateIndex + 6)); 2272c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } else { 2282c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu builder.append(stateSet[i]); 2292c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2302c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2312c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2322c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return builder.toString(); 2332c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2342c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2352c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private void compareImages(Bitmap ideal, Bitmap given, String filename) { 2362c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu int idealWidth = ideal.getWidth(); 2372c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu int idealHeight = ideal.getHeight(); 2382c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2392c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertTrue(idealWidth == given.getWidth()); 2402c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertTrue(idealHeight == given.getHeight()); 2412c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2422c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu int totalDiffPixelCount = 0; 2432c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu float totalPixelCount = idealWidth * idealHeight; 2442c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu for (int x = 0; x < idealWidth; x++) { 2452c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu for (int y = 0; y < idealHeight; y++) { 2462c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu int idealColor = ideal.getPixel(x, y); 2472c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu int givenColor = given.getPixel(x, y); 2482c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if (idealColor == givenColor) 2492c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu continue; 2502c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2512c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu float totalError = 0; 2522c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu totalError += Math.abs(Color.red(idealColor) - Color.red(givenColor)); 2532c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu totalError += Math.abs(Color.green(idealColor) - Color.green(givenColor)); 2542c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu totalError += Math.abs(Color.blue(idealColor) - Color.blue(givenColor)); 2552c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu totalError += Math.abs(Color.alpha(idealColor) - Color.alpha(givenColor)); 2562c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2572c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if ((totalError / 1024.0f) >= PIXEL_ERROR_THRESHOLD) { 2582c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu fail((filename + ": totalError is " + totalError)); 2592c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2602c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2612c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if ((totalError / 1024.0f) >= PIXEL_DIFF_THRESHOLD) { 2622c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu totalDiffPixelCount++; 2632c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2642c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2652c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 26622eca99cc198a41db5c72ad6fb981f2bd4d59313Teng-Hui Zhu if ((totalDiffPixelCount / totalPixelCount) >= PIXEL_DIFF_COUNT_THRESHOLD) { 2672c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu fail((filename + ": totalDiffPixelCount is " + totalDiffPixelCount)); 2682c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2692c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2702c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2712c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 272d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikov @Test 2732c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu public void testGetChangingConfigurations() { 2742c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu VectorDrawableCompat vectorDrawable = 2752c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu VectorDrawableCompat.create(mResources, TEST_ICON, mTheme); 2762c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu Drawable.ConstantState constantState = vectorDrawable.getConstantState(); 2772c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2782c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // default 2792c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0, constantState.getChangingConfigurations()); 2802c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0, vectorDrawable.getChangingConfigurations()); 2812c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2822c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // change the drawable's configuration does not affect the state's configuration 2832c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu vectorDrawable.setChangingConfigurations(0xff); 2842c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0xff, vectorDrawable.getChangingConfigurations()); 2852c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0, constantState.getChangingConfigurations()); 2862c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2872c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // the state's configuration get refreshed 2882c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu constantState = vectorDrawable.getConstantState(); 2892c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0xff, constantState.getChangingConfigurations()); 2902c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 2912c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // set a new configuration to drawable 2922c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu vectorDrawable.setChangingConfigurations(0xff00); 2932c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0xff, constantState.getChangingConfigurations()); 2942c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0xffff, vectorDrawable.getChangingConfigurations()); 2952c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 2962c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 297d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikov @Test 2982c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu public void testGetConstantState() { 2992c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu VectorDrawableCompat vectorDrawable = 30041d51ba40d85609cc9abe45922279da5d700a654Teng-Hui Zhu VectorDrawableCompat.create(mResources, R.drawable.vector_icon_delete, mTheme); 3012c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu Drawable.ConstantState constantState = vectorDrawable.getConstantState(); 3022c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertNotNull(constantState); 3032c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0, constantState.getChangingConfigurations()); 3042c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 3052c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu vectorDrawable.setChangingConfigurations(1); 3062c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu constantState = vectorDrawable.getConstantState(); 3072c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertNotNull(constantState); 3082c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(1, constantState.getChangingConfigurations()); 3092c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 3102c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 311d5bac09cd05be314f4c38435572a3fc01c2c8d4fKirill Grouchnikov @Test 3122c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu public void testMutate() { 3132c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu VectorDrawableCompat d1 = 3142c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu VectorDrawableCompat.create(mResources, TEST_ICON, mTheme); 3152c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu VectorDrawableCompat d2 = 3162c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu (VectorDrawableCompat) d1.getConstantState().newDrawable(mResources); 3172c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu VectorDrawableCompat d3 = 3182c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu (VectorDrawableCompat) d1.getConstantState().newDrawable(mResources); 3192c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 3202c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // d1 will be mutated, while d2 / d3 will not. 3212c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu int originalAlpha = d2.getAlpha(); 3222c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 3232c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu d1.setAlpha(0x80); 3242c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0x80, d1.getAlpha()); 3252c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0x80, d2.getAlpha()); 3262c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0x80, d3.getAlpha()); 3272c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 3282c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu d1.mutate(); 3292c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu d1.setAlpha(0x40); 3302c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0x40, d1.getAlpha()); 3312c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0x80, d2.getAlpha()); 3322c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0x80, d3.getAlpha()); 3332c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 3342c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu d2.setAlpha(0x20); 3352c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0x40, d1.getAlpha()); 3362c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0x20, d2.getAlpha()); 3372c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu assertEquals(0x20, d3.getAlpha()); 3382c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 3392c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu d2.setAlpha(originalAlpha); 3402c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 3415f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu 3425f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu public void testBounds() { 3435f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu VectorDrawableCompat vectorDrawable = 3445f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu VectorDrawableCompat.create(mResources, R.drawable.vector_icon_delete, mTheme); 3455f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu Rect expectedRect = new Rect(0, 0, 100, 100); 3465f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu vectorDrawable.setBounds(0, 0, 100, 100); 3475f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu Rect rect = vectorDrawable.getBounds(); 3485f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu assertEquals("Bounds should be same value for setBound(int ...)", rect, expectedRect); 3495f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu 3505f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu vectorDrawable.setBounds(expectedRect); 3515f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu rect = vectorDrawable.getBounds(); 3525f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu assertEquals("Bounds should be same value for setBound(Rect)", rect, expectedRect); 3535f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu 3545f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu vectorDrawable.copyBounds(rect); 3555f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu assertEquals("Bounds should be same value for copyBounds", rect, expectedRect); 3565f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu } 3572c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu} 358