1/* 2 * Copyright (C) 2014 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 17package com.android.layoutlib.bridge.bars; 18 19import com.android.resources.Density; 20import com.android.resources.LayoutDirection; 21 22import java.io.InputStream; 23 24public class IconLoader { 25 26 private final String mIconName; 27 private final Density mDesiredDensity; 28 private final int mPlatformVersion; 29 private final LayoutDirection mDirection; 30 31 private Density mCurrentDensity; 32 private StringBuilder mCurrentPath; 33 34 IconLoader(String iconName, Density density, int platformVersion, LayoutDirection direction) { 35 mIconName = iconName; 36 mDesiredDensity = density; 37 mPlatformVersion = platformVersion; 38 mDirection = direction; 39 // An upper bound on the length of the path for the icon: /bars/v21/ldrtl-xxxhdpi/ 40 final int iconPathLength = 24; 41 mCurrentPath = new StringBuilder(iconPathLength + iconName.length()); 42 } 43 44 public InputStream getIcon() { 45 for (String resourceDir : Config.getResourceDirs(mPlatformVersion)) { 46 mCurrentDensity = null; 47 InputStream stream = getIcon(resourceDir); 48 if (stream != null) { 49 return stream; 50 } 51 } 52 return null; 53 } 54 55 /** 56 * Should only be called after {@link #getIcon()}. Returns the density of the icon, if found by 57 * {@code getIcon()}. If no icon was found, then the return value has no meaning. 58 */ 59 public Density getDensity() { 60 return mCurrentDensity; 61 } 62 63 /** 64 * Should only be called after {@link #getIcon()}. Returns the path to the icon, if found by 65 * {@code getIcon()}. If no icon was found, then the return value has no meaning. 66 */ 67 public String getPath() { 68 return mCurrentPath.toString(); 69 } 70 71 /** 72 * Search for icon in the resource directory. This iterates over all densities. 73 * If a match is found, mCurrentDensity will be set to the icon's density. 74 */ 75 private InputStream getIcon(String resourceDir) { 76 // First check for the desired density. 77 InputStream stream = getIcon(resourceDir, mDesiredDensity); 78 if (stream != null) { 79 mCurrentDensity = mDesiredDensity; 80 return stream; 81 } 82 // Didn't find in the desired density. Search in all. 83 for (Density density : Density.values()) { 84 if (density == mDesiredDensity) { 85 // Skip the desired density since it's already been checked. 86 continue; 87 } 88 stream = getIcon(resourceDir, density); 89 if (stream != null) { 90 mCurrentDensity = density; 91 return stream; 92 } 93 } 94 return null; 95 } 96 97 /** 98 * Returns the icon for given density present in the given resource directory, taking layout 99 * direction into consideration. 100 */ 101 private InputStream getIcon(String resourceDir, Density density) { 102 mCurrentPath.setLength(0); 103 // Currently we don't have any LTR only resources and hence the check is skipped. If they 104 // are ever added, change to: 105 // if (mDirection == LayoutDirection.RTL || mDirection == LayoutDirection.LTR) { 106 if (mDirection == LayoutDirection.RTL) { 107 mCurrentPath.append(resourceDir) 108 .append(mDirection.getResourceValue()) 109 .append('-') 110 .append(density.getResourceValue()) 111 .append('/') 112 .append(mIconName); 113 InputStream stream = getClass().getResourceAsStream(mCurrentPath.toString()); 114 if (stream != null) { 115 return stream; 116 } 117 mCurrentPath.setLength(0); 118 } 119 mCurrentPath.append(resourceDir) 120 .append(density.getResourceValue()) 121 .append('/') 122 .append(mIconName); 123 return getClass().getResourceAsStream(mCurrentPath.toString()); 124 } 125} 126