Example #1
0
  /**
   * Create a drawable from an inputstream, using the given resources and value to determine density
   * information.
   */
  public static Drawable createFromResourceStream(
      Resources res, TypedValue value, InputStream is, String srcName, BitmapFactory.Options opts) {
    if (is == null) {
      return null;
    }

    /*  ugh. The decodeStream contract is that we have already allocated
        the pad rect, but if the bitmap does not had a ninepatch chunk,
        then the pad will be ignored. If we could change this to lazily
        alloc/assign the rect, we could avoid the GC churn of making new
        Rects only to drop them on the floor.
    */
    Rect pad = new Rect();

    // Special stuff for compatibility mode: if the target density is not
    // the same as the display density, but the resource -is- the same as
    // the display density, then don't scale it down to the target density.
    // This allows us to load the system's density-correct resources into
    // an application in compatibility mode, without scaling those down
    // to the compatibility density only to have them scaled back up when
    // drawn to the screen.
    if (opts == null) opts = new BitmapFactory.Options();
    opts.inScreenDensity =
        res != null ? res.getDisplayMetrics().noncompatDensityDpi : DisplayMetrics.DENSITY_DEVICE;
    Bitmap bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
    if (bm != null) {
      byte[] np = bm.getNinePatchChunk();
      if (np == null || !NinePatch.isNinePatchChunk(np)) {
        np = null;
        pad = null;
      }

      final Rect opticalInsets = new Rect();
      bm.getOpticalInsets(opticalInsets);
      return drawableFromBitmap(res, bm, np, pad, opticalInsets, srcName);
    }
    return null;
  }
  /** Updates the constant state from the values in the typed array. */
  private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
    final Resources r = a.getResources();
    final NinePatchState state = mNinePatchState;

    // Account for any configuration changes.
    state.mChangingConfigurations |= a.getChangingConfigurations();

    // Extract the theme attributes, if any.
    state.mThemeAttrs = a.extractThemeAttrs();

    state.mDither = a.getBoolean(R.styleable.NinePatchDrawable_dither, state.mDither);

    final int srcResId = a.getResourceId(R.styleable.NinePatchDrawable_src, 0);
    if (srcResId != 0) {
      final BitmapFactory.Options options = new BitmapFactory.Options();
      options.inDither = !state.mDither;
      options.inScreenDensity = r.getDisplayMetrics().noncompatDensityDpi;

      final Rect padding = new Rect();
      final Rect opticalInsets = new Rect();
      Bitmap bitmap = null;

      try {
        final TypedValue value = new TypedValue();
        final InputStream is = r.openRawResource(srcResId, value);

        bitmap = BitmapFactory.decodeResourceStream(r, value, is, padding, options);

        is.close();
      } catch (IOException e) {
        // Ignore
      }

      if (bitmap == null) {
        throw new XmlPullParserException(
            a.getPositionDescription() + ": <nine-patch> requires a valid src attribute");
      } else if (bitmap.getNinePatchChunk() == null) {
        throw new XmlPullParserException(
            a.getPositionDescription() + ": <nine-patch> requires a valid 9-patch source image");
      }

      bitmap.getOpticalInsets(opticalInsets);

      state.mNinePatch = new NinePatch(bitmap, bitmap.getNinePatchChunk());
      state.mPadding = padding;
      state.mOpticalInsets = Insets.of(opticalInsets);
    }

    state.mAutoMirrored =
        a.getBoolean(R.styleable.NinePatchDrawable_autoMirrored, state.mAutoMirrored);
    state.mBaseAlpha = a.getFloat(R.styleable.NinePatchDrawable_alpha, state.mBaseAlpha);

    final int tintMode = a.getInt(R.styleable.NinePatchDrawable_tintMode, -1);
    if (tintMode != -1) {
      state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN);
    }

    final ColorStateList tint = a.getColorStateList(R.styleable.NinePatchDrawable_tint);
    if (tint != null) {
      state.mTint = tint;
    }

    // Update local properties.
    initializeWithState(state, r);

    // Push density applied by setNinePatchState into state.
    state.mTargetDensity = mTargetDensity;
  }