/** * Draw underline * * @param canvas The canvas */ private void drawUnderline(Canvas canvas) { if (mShowUnderline) { View parent = (View) getParent(); if (parent != null && (parent.getPaddingLeft() != 0 || parent.getPaddingRight() != 0)) { final int pPaddingLeft = parent.getPaddingLeft(); final int pPaddingRight = parent.getPaddingRight(); canvas.save(); // allow drawing out of bounds Rect clipBounds = canvas.getClipBounds(); clipBounds.inset(-(pPaddingLeft + pPaddingRight), 0); canvas.clipRect(clipBounds, Region.Op.REPLACE); if (mUnderlineGravity == UnderlineGravity.TOP) { // If on top ignore bottom padding canvas.drawRect( -pPaddingLeft, mUnderlinePaddingTop, getWidth() + pPaddingLeft + pPaddingRight, mUnderlineHeight + mUnderlinePaddingTop, mUnderlinePaint); } else { // If on bottom ignore top padding canvas.drawRect( -pPaddingLeft, getHeight() - mUnderlineHeight - mUnderlinePaddingBottom, getWidth() + pPaddingLeft + pPaddingRight, getHeight() - mUnderlinePaddingBottom, mUnderlinePaint); } canvas.restore(); } else { if (mUnderlineGravity == UnderlineGravity.TOP) { // If on top ignore bottom padding canvas.drawRect( 0, mUnderlinePaddingTop, getWidth(), mUnderlineHeight + mUnderlinePaddingTop, mUnderlinePaint); } else { // If on bottom ignore top padding canvas.drawRect( 0, getHeight() - mUnderlineHeight - mUnderlinePaddingBottom, getWidth(), getHeight() - mUnderlinePaddingBottom, mUnderlinePaint); } } } }
private void updateThumbPos(int posX) { int thumbWidth = mThumb.getIntrinsicWidth(); int halfThumb = thumbWidth / 2; int start; if (isRtl()) { start = getWidth() - getPaddingRight() - mAddedTouchBounds; posX = start - posX - thumbWidth; } else { start = getPaddingLeft() + mAddedTouchBounds; posX = start + posX; } mThumb.copyBounds(mInvalidateRect); mThumb.setBounds(posX, mInvalidateRect.top, posX + thumbWidth, mInvalidateRect.bottom); if (isRtl()) { mScrubber.getBounds().right = start - halfThumb; mScrubber.getBounds().left = posX + halfThumb; } else { mScrubber.getBounds().left = start + halfThumb; mScrubber.getBounds().right = posX + halfThumb; } final Rect finalBounds = mTempRect; mThumb.copyBounds(finalBounds); if (!isInEditMode()) { mIndicator.move(finalBounds.centerX()); } mInvalidateRect.inset(-mAddedTouchBounds, -mAddedTouchBounds); finalBounds.inset(-mAddedTouchBounds, -mAddedTouchBounds); mInvalidateRect.union(finalBounds); SeekBarCompat.setHotspotBounds( mRipple, finalBounds.left, finalBounds.top, finalBounds.right, finalBounds.bottom); invalidate(mInvalidateRect); }
private boolean startDragging(MotionEvent ev, boolean ignoreTrackIfInScrollContainer) { final Rect bounds = mTempRect; mThumb.copyBounds(bounds); // Grow the current thumb rect for a bigger touch area bounds.inset(-mAddedTouchBounds, -mAddedTouchBounds); mIsDragging = (bounds.contains((int) ev.getX(), (int) ev.getY())); if (!mIsDragging && mAllowTrackClick && !ignoreTrackIfInScrollContainer) { // If the user clicked outside the thumb, we compute the current position // and force an immediate drag to it. mIsDragging = true; mDragOffset = (bounds.width() / 2) - mAddedTouchBounds; updateDragging(ev); // As the thumb may have moved, get the bounds again mThumb.copyBounds(bounds); bounds.inset(-mAddedTouchBounds, -mAddedTouchBounds); } if (mIsDragging) { setPressed(true); attemptClaimDrag(); setHotspot(ev.getX(), ev.getY()); mDragOffset = (int) (ev.getX() - bounds.left - mAddedTouchBounds); if (mPublicChangeListener != null) { mPublicChangeListener.onStartTrackingTouch(this); } } return mIsDragging; }
@Override public void draw(@NonNull final Canvas canvas) { super.draw(canvas); // Only recalculate the close bounds if they are dirty if (mCloseBoundChanged) { mCloseBoundChanged = false; mClosableLayoutRect.set(0, 0, getWidth(), getHeight()); // Create the bounds for our close regions. applyCloseRegionBounds(mClosePosition, mClosableLayoutRect, mCloseRegionBounds); // The inset rect applies padding around the visible closeButton. mInsetCloseRegionBounds.set(mCloseRegionBounds); mInsetCloseRegionBounds.inset(mCloseButtonPadding, mCloseButtonPadding); // The close button sits inside the close region with padding and gravity // in the same way the close region sits inside the whole ClosableLayout applyCloseButtonBounds(mClosePosition, mInsetCloseRegionBounds, mCloseButtonBounds); mCloseDrawable.setBounds(mCloseButtonBounds); } // Draw last so that this gets drawn as the top layer. This is also why we override // draw instead of onDraw. if (mCloseDrawable.isVisible()) { mCloseDrawable.draw(canvas); } }
private Bitmap extentSnapshot(int doc, int gs, int spaceAround, boolean transparent) { final LogHelper log = new LogHelper(); final Rect extent = getDisplayExtent(); if (!extent.isEmpty()) { extent.inset(-spaceAround, -spaceAround); extent.intersect(0, 0, mView.getView().getWidth(), mView.getView().getHeight()); } if (extent.isEmpty()) { return null; } final Bitmap viewBitmap = mView.snapshot(doc, gs, transparent); if (viewBitmap == null) { return null; } if (extent.width() == mView.getView().getWidth() && extent.height() == mView.getView().getHeight()) { log.r(viewBitmap.getByteCount()); return viewBitmap; } final Bitmap realBitmap = Bitmap.createBitmap(viewBitmap, extent.left, extent.top, extent.width(), extent.height()); viewBitmap.recycle(); log.r(realBitmap.getByteCount()); return realBitmap; }
private void init() { if (mPaint == null) { mPaint = new Paint(); mPaint.setColor(Color.WHITE); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.FILL); } int count = (mPoints - 1) * 4; posX = new float[count]; posY = new float[count]; Rect bounds = new Rect(); bounds.set(getBounds()); bounds.inset(mPadding, mPadding); // circumference float circ = (float) (Math.PI * (float) Math.min(bounds.width(), bounds.height())); float arcLength = circ / count; mSize = (float) ((arcLength) / (2 * Math.PI)); double degrees = Math.toRadians((float) 360 / (float) count); for (int i = 0; i < count; i++) { posX[i] = (float) (bounds.exactCenterX() - (bounds.width() / 2) * Math.sin(degrees * i)); posY[i] = (float) (bounds.exactCenterY() + (bounds.height() / 2) * Math.cos(degrees * i)); } }
private void drawBlurBackground(Canvas canvas) { if (mBlurredView != null) { if (prepare()) { if (mBlurredBackgroundColor != 0) { mBitmapToBlur.eraseColor(mBlurredBackgroundColor); } mBlurredView.draw(mBlurringCanvas); blur(); NiceTabLayout tabLayout = (NiceTabLayout) getParent(); if (tabLayout != null) { final int pPaddingLeft = tabLayout.getPaddingLeft(); final int pPaddingRight = tabLayout.getPaddingRight(); canvas.save(); if (tabLayout.getPaddingLeft() != 0 || tabLayout.getPaddingRight() != 0) { // allow drawing out of bounds Rect clipBounds = canvas.getClipBounds(); clipBounds.inset(-(pPaddingLeft + pPaddingRight), 0); canvas.clipRect(clipBounds, Region.Op.REPLACE); } canvas.translate( mBlurredView.getLeft() - getLeft() + tabLayout.getScrollX(), mBlurredView.getTop() - getTop()); canvas.scale(mDownSampleFactor, mDownSampleFactor); canvas.drawBitmap(mBlurredBitmap, 0, 0, null); canvas.drawColor(mOverlayColor); canvas.restore(); } } } }
private void computeGlyphPath() { drawableArea.set(getBounds()); drawableArea.inset(padding, padding); glyphPaint.getTextPath(glyph, 0, 1, 0, 0, glyphPath); // Add an extra path point to fix the icon remaining blank on a Galaxy Note 2 running 4.1.2. glyphPath.computeBounds(glyphPathBounds, false); final float centerX = glyphPathBounds.centerX(); final float centerY = glyphPathBounds.centerY(); glyphPath.moveTo(centerX, centerY); glyphPath.lineTo(centerX + 0.001f, centerY + 0.001f); final float areaWidthF = (float) drawableArea.width(); final float areaHeightF = (float) drawableArea.height(); final float scaleX = areaWidthF / glyphPathBounds.width(); final float scaleY = areaHeightF / glyphPathBounds.height(); final float scaleFactor = Math.min(scaleX, scaleY); glyphPathTransform.setScale(scaleFactor, scaleFactor); glyphPath.transform(glyphPathTransform); // TODO this two pass calculation irks me. // It has to be possible to push this into a single Matrix transform; what makes it hard is // that the origin of Text is not top-left, but baseline-left so need to account for that. glyphPath.computeBounds(glyphPathBounds, false); final float areaLeftF = (float) drawableArea.left; final float areaTopF = (float) drawableArea.top; float transX = areaLeftF - glyphPathBounds.left; transX += 0.5f * Math.abs(areaWidthF - glyphPathBounds.width()); float transY = areaTopF - glyphPathBounds.top; transY += 0.5f * Math.abs(areaHeightF - glyphPathBounds.height()); glyphPath.offset(transX, transY); invalidateSelf(); }
@Override public int getSize( Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { paint.getTextBounds(mText, 0, mText.length(), mRect); mRect.inset(-1, -1); return (int) (paint.measureText(mText) + 0.5); }
void updateDstRect() { if (mApplyGravity) { if (mIsCircular) { final int minDimen = Math.min(mBitmapWidth, mBitmapHeight); gravityCompatApply(mGravity, minDimen, minDimen, getBounds(), mDstRect); // inset the drawing rectangle to the largest contained square, // so that a circle will be drawn final int minDrawDimen = Math.min(mDstRect.width(), mDstRect.height()); final int insetX = Math.max(0, (mDstRect.width() - minDrawDimen) / 2); final int insetY = Math.max(0, (mDstRect.height() - minDrawDimen) / 2); mDstRect.inset(insetX, insetY); mCornerRadius = 0.5f * minDrawDimen; } else { gravityCompatApply(mGravity, mBitmapWidth, mBitmapHeight, getBounds(), mDstRect); } mDstRectF.set(mDstRect); if (mBitmapShader != null) { // setup shader matrix mShaderMatrix.setTranslate(mDstRectF.left, mDstRectF.top); mShaderMatrix.preScale( mDstRectF.width() / mBitmap.getWidth(), mDstRectF.height() / mBitmap.getHeight()); mBitmapShader.setLocalMatrix(mShaderMatrix); mPaint.setShader(mBitmapShader); } mApplyGravity = false; } }
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (mScrollDisabled) return true; View v = mChildViews.get(mCurrent); if (v != null) { Rect bounds = getScrollBounds(v); switch (directionOfTravel(velocityX, velocityY)) { case MOVING_LEFT: if (bounds.left >= 0) { // Fling off to the left bring next view onto screen View vl = mChildViews.get(mCurrent + 1); if (vl != null) { slideViewOntoScreen(vl); return true; } } break; case MOVING_RIGHT: if (bounds.right <= 0) { // Fling off to the right bring previous view onto screen View vr = mChildViews.get(mCurrent - 1); if (vr != null) { slideViewOntoScreen(vr); return true; } } break; } mScrollerLastX = mScrollerLastY = 0; // If the page has been dragged out of bounds then we want to spring back // nicely. fling jumps back into bounds instantly, so we don't want to use // fling in that case. On the other hand, we don't want to forgo a fling // just because of a slightly off-angle drag taking us out of bounds other // than in the direction of the drag, so we test for out of bounds only // in the direction of travel. // // Also don't fling if out of bounds in any direction by more than fling // margin Rect expandedBounds = new Rect(bounds); expandedBounds.inset(-FLING_MARGIN, -FLING_MARGIN); if (withinBoundsInDirectionOfTravel(bounds, velocityX, velocityY) && expandedBounds.contains(0, 0)) { mScroller.fling( 0, 0, (int) velocityX, (int) velocityY, bounds.left, bounds.right, bounds.top, bounds.bottom); post(this); } } return true; }
@Override protected void onBoundsChange(Rect bounds) { mIcon.setBounds(bounds); if (mBgDrawable != null) { sTempRect.set(bounds); sTempRect.inset(-mRingOutset, -mRingOutset); mBgDrawable.setBounds(sTempRect); } mIndicatorRectDirty = true; }
void b(float paramFloat1, float paramFloat2) { Rect localRect = new Rect(this.d); this.e.offset(paramFloat1, paramFloat2); this.e.offset(Math.max(0.0F, this.i.left - this.e.left), Math.max(0.0F, this.i.top - this.e.top)); this.e.offset(Math.min(0.0F, this.i.right - this.e.right), Math.min(0.0F, this.i.bottom - this.e.bottom)); this.d = e(); localRect.union(this.d); localRect.inset(-10, -10); this.a.invalidate(localRect); }
/** * Adds padding to the given size rectangle * * @param size The size where the padding should be added to * @return The size with the padding */ protected Rect sizeAddPadding(Rect size) { // Copy the rectangle Rect out = new Rect(size); // Add the padding out.inset(-(int) (Expression.lineWidth * 2.5), -(int) (Expression.lineWidth * 2.5)); out.offsetTo(0, 0); // Return the result return out; }
protected void inflateData( int LineNumber, int Margin, int Width, int Height, float MinLengthPercentage, float MinAngle) { Rect bounds = new Rect(0, 0, Width, Height); bounds.inset(Margin, Margin); inflateData(LineNumber, MinLengthPercentage, MinAngle, bounds); }
private void updateBounds(Rect bounds) { if (bounds == null) { bounds = getBounds(); } mBoundsF.set(bounds.left, bounds.top, bounds.right, bounds.bottom); mBoundsI.set(bounds); if (mInsetForPadding) { float vInset = calculateVerticalPadding(mPadding, mRadius, mInsetForRadius); float hInset = calculateHorizontalPadding(mPadding, mRadius, mInsetForRadius); mBoundsI.inset((int) Math.ceil(hInset), (int) Math.ceil(vInset)); // to make sure they have same bounds. mBoundsF.set(mBoundsI); } }
private void updateLayoutMatrix() { synchronized (updateLayoutLock) { if (!updateLayoutProperties) { return; } // Initialize to maximum allowed area. Round to integer coordinates inwards the layout // bounding box (ceil left/top and floor right/bottom) to not break constraints. displayLayout.set( (screenWidth * layoutInPercentage.left + 99) / 100, (screenHeight * layoutInPercentage.top + 99) / 100, (screenWidth * layoutInPercentage.right) / 100, (screenHeight * layoutInPercentage.bottom) / 100); Logging.d( TAG, "ID: " + id + ". AdjustTextureCoords. Allowed display size: " + displayLayout.width() + " x " + displayLayout.height() + ". Video: " + videoWidth + " x " + videoHeight + ". Rotation: " + rotationDegree + ". Mirror: " + mirror); final float videoAspectRatio = (rotationDegree % 180 == 0) ? (float) videoWidth / videoHeight : (float) videoHeight / videoWidth; // Adjust display size based on |scalingType|. final Point displaySize = RendererCommon.getDisplaySize( scalingType, videoAspectRatio, displayLayout.width(), displayLayout.height()); displayLayout.inset( (displayLayout.width() - displaySize.x) / 2, (displayLayout.height() - displaySize.y) / 2); Logging.d( TAG, " Adjusted display size: " + displayLayout.width() + " x " + displayLayout.height()); layoutMatrix = RendererCommon.getLayoutMatrix( mirror, videoAspectRatio, (float) displayLayout.width() / displayLayout.height()); updateLayoutProperties = false; Logging.d(TAG, " AdjustTextureCoords done"); } }
// Grows the cropping rectange by (dx, dy) in image space. void moveBy(float dx, float dy) { Rect invalRect = new Rect(mDrawRect); mCropRect.offset(dx, dy); // Put the cropping rectangle inside image rectangle. mCropRect.offset( Math.max(0, mImageRect.left - mCropRect.left), Math.max(0, mImageRect.top - mCropRect.top)); mCropRect.offset( Math.min(0, mImageRect.right - mCropRect.right), Math.min(0, mImageRect.bottom - mCropRect.bottom)); mDrawRect = computeLayout(); invalRect.union(mDrawRect); invalRect.inset(-10, -10); mContext.invalidate(invalRect); }
// Grows the cropping rectangle by (dx, dy) in image space void moveBy(float dx, float dy) { Rect invalRect = new Rect(drawRect); cropRect.offset(dx, dy); // Put the cropping rectangle inside image rectangle cropRect.offset( Math.max(0, imageRect.left - cropRect.left), Math.max(0, imageRect.top - cropRect.top)); cropRect.offset( Math.min(0, imageRect.right - cropRect.right), Math.min(0, imageRect.bottom - cropRect.bottom)); drawRect = computeLayout(); invalRect.union(drawRect); invalRect.inset(-(int) handleRadius, -(int) handleRadius); viewContext.invalidate(invalRect); }
/** NOTE: This has to be called within a surface transaction. */ public void drawIfNeeded() { synchronized (mWindowManagerService.mWindowMap) { if (!mInvalidated) { return; } mInvalidated = false; Canvas canvas = null; try { // Empty dirty rectangle means unspecified. if (mDirtyRect.isEmpty()) { mBounds.getBounds(mDirtyRect); } mDirtyRect.inset(-mHalfBorderWidth, -mHalfBorderWidth); canvas = mSurface.lockCanvas(mDirtyRect); if (DEBUG_VIEWPORT_WINDOW) { Slog.i(LOG_TAG, "Dirty rect: " + mDirtyRect); } } catch (IllegalArgumentException iae) { /* ignore */ } catch (Surface.OutOfResourcesException oore) { /* ignore */ } if (canvas == null) { return; } if (DEBUG_VIEWPORT_WINDOW) { Slog.i(LOG_TAG, "Bounds: " + mBounds); } canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR); mPaint.setAlpha(mAlpha); Path path = mBounds.getBoundaryPath(); canvas.drawPath(path, mPaint); mSurface.unlockCanvasAndPost(canvas); if (mAlpha > 0) { mSurfaceControl.show(); } else { mSurfaceControl.hide(); } } }
/** Computes the stack and task rects */ public void computeRects(int windowWidth, int windowHeight, Rect taskStackBounds) { // Compute the stack rects mViewRect.set(0, 0, windowWidth, windowHeight); mStackRect.set(taskStackBounds); mStackVisibleRect.set(taskStackBounds); mStackVisibleRect.bottom = mViewRect.bottom; int widthPadding = (int) (mConfig.taskStackWidthPaddingPct * mStackRect.width()); int heightPadding = mConfig.taskStackTopPaddingPx; mStackRect.inset(widthPadding, heightPadding); // Compute the task rect int size = mStackRect.width(); int left = mStackRect.left + (mStackRect.width() - size) / 2; mTaskRect.set(left, mStackRect.top, left + size, mStackRect.top + size); // Update the affiliation offsets float visibleTaskPct = 0.5f; mWithinAffiliationOffset = mConfig.taskBarHeight; mBetweenAffiliationOffset = (int) (visibleTaskPct * mTaskRect.height()); }
@Override public void draw(Canvas canvas) { // Draw the bounding boxes drawBoundingBoxes(canvas); // Get the bounding box final Rect operator = getOperatorBoundingBoxes()[0]; // Draw the operator operator.inset(operator.width() / 10, operator.height() / 10); // Padding canvas.save(); canvas.translate(operator.left, operator.top); operatorPaint.setStrokeWidth(lineWidth); operatorPaint.setColor(this.getColor()); canvas.drawLine( 0, operator.height() / 2, operator.width(), operator.height() / 2, operatorPaint); canvas.drawLine( operator.width() / 2, 0, operator.width() / 2, operator.height(), operatorPaint); canvas.restore(); // Draw the children drawChildren(canvas); }
@Override public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow) { super.draw(canvas, mapView, shadow); // go through all OverlayItems and draw title for each of them for (OverlayItem item : mOverlays) { /* Converts latitude & longitude of this overlay item to coordinates on screen. * As we have called boundCenterBottom() in constructor, so these coordinates * will be of the bottom center position of the displayed marker. */ GeoPoint point = item.getPoint(); Point markerBottomCenterCoords = new Point(); mapView.getProjection().toPixels(point, markerBottomCenterCoords); /* Find the width and height of the title*/ TextPaint paintText = new TextPaint(); Paint paintRect = new Paint(); Rect rect = new Rect(); paintText.setTextSize(FONT_SIZE); paintText.getTextBounds(item.getTitle(), 0, item.getTitle().length(), rect); rect.inset(-TITLE_MARGIN, -TITLE_MARGIN); rect.offsetTo( markerBottomCenterCoords.x - rect.width() / 2, markerBottomCenterCoords.y - markerHeight - rect.height()); paintText.setTextAlign(Paint.Align.CENTER); paintText.setTextSize(FONT_SIZE); paintText.setARGB(255, 255, 255, 255); paintRect.setARGB(130, 0, 0, 0); canvas.drawRoundRect(new RectF(rect), 2, 2, paintRect); canvas.drawText( item.getTitle(), rect.left + rect.width() / 2, rect.bottom - TITLE_MARGIN, paintText); } }
/* * Use to signal that there's a portion of this view that wants to be * visible to the user on the screen. This method will place the sub * view on the screen, and will also place as much of this view as possible * on the screen. If this view is smaller than the viewable area available, it * will be fully visible in addition to the subview. */ private void requestChildViewOnScreen(View child) { // Take focus so the user can be prepared to interact with this question, since // they will need to be fixing the input acceptFocus(); // Get the rectangle that wants to put itself on the screen Rect vitalPortion = new Rect(); child.getDrawingRect(vitalPortion); // Save a reference to it in case we have to manipulate it later. Rect vitalPortionSaved = new Rect(); child.getDrawingRect(vitalPortionSaved); // Then get the bounding rectangle for this whole view. Rect wholeView = new Rect(); this.getDrawingRect(wholeView); // If we don't know enough about the screen, just default to asking to see the // subview that was requested. if (mFrameHeight == -1) { child.requestRectangleOnScreen(vitalPortion); return; } // If the whole view fits, just request that we display the whole thing. if (wholeView.height() < mFrameHeight) { this.requestRectangleOnScreen(wholeView); return; } // The whole view will not fit, we need to scale down our requested focus. // Trying to construct the "ideal" rectangle here is actually pretty hard // but the base case is just to see if we can get the view onto the screen from // the bottom or the top int topY = wholeView.top; int bottomY = wholeView.bottom; // shrink the view to contain only the current frame size. wholeView.inset(0, (wholeView.height() - mFrameHeight) / 2); wholeView.offsetTo(wholeView.left, topY); // The view is now the size of the frame and anchored back at the top. // Now let's contextualize where the child view actually is in this frame. this.offsetDescendantRectToMyCoords(child, vitalPortion); // If the newly transformed view now contains the child portion, we're good if (wholeView.contains(vitalPortion)) { this.requestRectangleOnScreen(wholeView); return; } // otherwise, move to the requested frame to be at the bottom of this view wholeView.offsetTo(wholeView.left, bottomY - wholeView.height()); // now see if the transformed view contains the vital portion if (wholeView.contains(vitalPortion)) { this.requestRectangleOnScreen(wholeView); return; } // Otherwise the child is hidden in the frame, so it won't matter which // we choose. child.requestRectangleOnScreen(vitalPortionSaved); }
private void onSaveClicked() { // TODO this code needs to change to use the decode/crop/encode single // step api so that we don't require that the whole (possibly large) // bitmap doesn't have to be read into memory if (mCrop == null) { return; } if (mSaving) return; mSaving = true; Bitmap croppedImage; // If the output is required to a specific size, create an new image // with the cropped image in the center and the extra space filled. if (mOutputX != 0 && mOutputY != 0 && !mScale) { // Don't scale the image but instead fill it so it's the // required dimension croppedImage = Bitmap.createBitmap(mOutputX, mOutputY, Bitmap.Config.RGB_565); Canvas canvas = new Canvas(croppedImage); Rect srcRect = mCrop.getCropRect(); Rect dstRect = new Rect(0, 0, mOutputX, mOutputY); int dx = (srcRect.width() - dstRect.width()) / 2; int dy = (srcRect.height() - dstRect.height()) / 2; // If the srcRect is too big, use the center part of it. srcRect.inset(Math.max(0, dx), Math.max(0, dy)); // If the dstRect is too big, use the center part of it. dstRect.inset(Math.max(0, -dx), Math.max(0, -dy)); // Draw the cropped bitmap in the center canvas.drawBitmap(mBitmap, srcRect, dstRect, null); // Release bitmap memory as soon as possible mImageView.clear(); mBitmap.recycle(); } else { Rect r = mCrop.getCropRect(); int width = r.width(); int height = r.height(); // If we are circle cropping, we want alpha channel, which is the // third param here. croppedImage = Bitmap.createBitmap( width, height, mCircleCrop ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); Canvas canvas = new Canvas(croppedImage); Rect dstRect = new Rect(0, 0, width, height); canvas.drawBitmap(mBitmap, r, dstRect, null); // Release bitmap memory as soon as possible mImageView.clear(); mBitmap.recycle(); if (mCircleCrop) { // OK, so what's all this about? // Bitmaps are inherently rectangular but we want to return // something that's basically a circle. So we fill in the // area around the circle with alpha. Note the all important // PortDuff.Mode.CLEAR. Canvas c = new Canvas(croppedImage); Path p = new Path(); p.addCircle(width / 2F, height / 2F, width / 2F, Path.Direction.CW); c.clipPath(p, Region.Op.DIFFERENCE); c.drawColor(0x00000000, PorterDuff.Mode.CLEAR); } // If the required dimension is specified, scale the image. if (mOutputX != 0 && mOutputY != 0 && mScale) { croppedImage = Util.transform( new Matrix(), croppedImage, mOutputX, mOutputY, mScaleUp, Util.RECYCLE_INPUT); } } mImageView.setImageBitmapResetBase(croppedImage, true); mImageView.center(true, true); mImageView.mHighlightViews.clear(); // Return the cropped image directly or save it to the specified URI. Bundle myExtras = getIntent().getExtras(); if (myExtras != null && (myExtras.getParcelable("data") != null || myExtras.getBoolean("return-data"))) { Bundle extras = new Bundle(); extras.putParcelable("data", croppedImage); setResult(RESULT_OK, (new Intent()).setAction("inline-data").putExtras(extras)); finish(); } else { final Bitmap b = croppedImage; final int msdId = mSetWallpaper ? R.string.wallpaper : R.string.savingImage; Util.startBackgroundJob( this, this, null, getResources().getString(msdId), new Runnable() { public void run() { saveOutput(b); } }, mHandler); } }
private void onSaveClicked() throws Exception { // TODO this code needs to change to use the decode/crop/encode single // step api so that we don't require that the whole (possibly large) // bitmap doesn't have to be read into memory if (mSaving) return; if (mCrop == null) { return; } mSaving = true; Rect r = mCrop.getCropRect(); int width = r.width(); int height = r.height(); // If we are circle cropping, we want alpha channel, which is the // third param here. Bitmap croppedImage; try { croppedImage = Bitmap.createBitmap( width, height, mCircleCrop ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); } catch (Exception e) { throw e; } if (croppedImage == null) { return; } { Canvas canvas = new Canvas(croppedImage); Rect dstRect = new Rect(0, 0, width, height); canvas.drawBitmap(mBitmap, r, dstRect, null); } if (mCircleCrop) { // OK, so what's all this about? // Bitmaps are inherently rectangular but we want to return // something that's basically a circle. So we fill in the // area around the circle with alpha. Note the all important // PortDuff.Mode.CLEAR. Canvas c = new Canvas(croppedImage); Path p = new Path(); p.addCircle(width / 2F, height / 2F, width / 2F, Path.Direction.CW); c.clipPath(p, Region.Op.DIFFERENCE); c.drawColor(0x00000000, PorterDuff.Mode.CLEAR); } /* If the output is required to a specific size then scale or fill */ if (mOutputX != 0 && mOutputY != 0) { if (mScale) { /* Scale the image to the required dimensions */ Bitmap old = croppedImage; croppedImage = Util.transform(new Matrix(), croppedImage, mOutputX, mOutputY, mScaleUp); if (old != croppedImage) { old.recycle(); } } else { /* Don't scale the image crop it to the size requested. * Create an new image with the cropped image in the center and * the extra space filled. */ // Don't scale the image but instead fill it so it's the // required dimension Bitmap b = Bitmap.createBitmap(mOutputX, mOutputY, Bitmap.Config.RGB_565); Canvas canvas = new Canvas(b); Rect srcRect = mCrop.getCropRect(); Rect dstRect = new Rect(0, 0, mOutputX, mOutputY); int dx = (srcRect.width() - dstRect.width()) / 2; int dy = (srcRect.height() - dstRect.height()) / 2; /* If the srcRect is too big, use the center part of it. */ srcRect.inset(Math.max(0, dx), Math.max(0, dy)); /* If the dstRect is too big, use the center part of it. */ dstRect.inset(Math.max(0, -dx), Math.max(0, -dy)); /* Draw the cropped bitmap in the center */ canvas.drawBitmap(mBitmap, srcRect, dstRect, null); /* Set the cropped bitmap as the new bitmap */ croppedImage.recycle(); croppedImage = b; } } // Return the cropped image directly or save it to the specified URI. Bundle myExtras = getIntent().getExtras(); if (myExtras != null && (myExtras.getParcelable("data") != null || myExtras.getBoolean(RETURN_DATA))) { Bundle extras = new Bundle(); extras.putParcelable(RETURN_DATA_AS_BITMAP, croppedImage); setResult(RESULT_OK, (new Intent()).setAction(ACTION_INLINE_DATA).putExtras(extras)); finish(); } else { final Bitmap b = croppedImage; Util.startBackgroundJob( this, null, getString(R.string.saving_image), new Runnable() { public void run() { saveOutput(b); } }, mHandler); } }
@Override public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow) { super.draw(canvas, mapView, shadow); Paint mPaint = new Paint(); mPaint.setDither(true); mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(2); List<Clue> clues = huntedService.getDataProvider().getTrackLog(); Clue prevClue = null; for (Clue clue : clues) { if (prevClue != null) { GeoPoint prevCluePoint = Map.getPointForClue(prevClue); GeoPoint currentCluePoint = Map.getPointForClue(clue); Point fromPoint = new Point(); mapView.getProjection().toPixels(prevCluePoint, fromPoint); Point toPoint = new Point(); mapView.getProjection().toPixels(currentCluePoint, toPoint); canvas.drawLine(fromPoint.x, fromPoint.y, toPoint.x, toPoint.y, mPaint); } prevClue = clue; } // go through all OverlayItems and draw title for each of them List<OverlayItem> overlaysCopy = new ArrayList<OverlayItem>(overlays); for (OverlayItem item : overlaysCopy) { /* Converts latitude & longitude of this overlay item to coordinates on screen. * As we have called boundCenterBottom() in constructor, so these coordinates * will be of the bottom center position of the displayed marker. */ GeoPoint point = item.getPoint(); Point markerBottomCenterCoords = new Point(); mapView.getProjection().toPixels(point, markerBottomCenterCoords); /* Find the width and height of the title*/ TextPaint paintText = new TextPaint(); Paint paintRect = new Paint(); Rect rect = new Rect(); paintText.setTextSize(FONT_SIZE); paintText.getTextBounds(item.getTitle(), 0, item.getTitle().length(), rect); rect.inset(-TITLE_MARGIN, -TITLE_MARGIN); rect.offsetTo( markerBottomCenterCoords.x - rect.width() / 2, markerBottomCenterCoords.y - 15 - rect.height()); paintText.setTextAlign(Paint.Align.CENTER); paintText.setTextSize(FONT_SIZE); paintText.setARGB(255, 255, 255, 255); paintRect.setARGB(130, 0, 0, 0); canvas.drawRoundRect(new RectF(rect), 2, 2, paintRect); canvas.drawText( item.getTitle(), rect.left + rect.width() / 2, rect.bottom - TITLE_MARGIN, paintText); } }
private void onSaveClicked() { if (!mNeedCrop) { Bitmap nocropBitmap = createNoCropBitmap(); mImageView.clear(); if (nocropBitmap != mBitmap) { mBitmap.recycle(); mBitmap = null; } if (null != nocropBitmap) { // Return the cropped image directly or save it to the specified // URI. Bundle myExtras = getIntent().getExtras(); if (myExtras != null && (myExtras.getParcelable("data") != null || myExtras.getBoolean("return-data"))) { Bundle extras = new Bundle(); extras.putParcelable("data", nocropBitmap); setResult( RESULT_OK, (new Intent()).setAction(ICustomAction.ACTION_INLINE_DATA).putExtras(extras)); finish(); } else { final Bitmap b = nocropBitmap; final int msdId = mSetWallpaper ? R.string.wallpaper : R.string.savingImage; Util.startBackgroundJob( this, null, getResources().getString(msdId), new Runnable() { @Override public void run() { saveOutput(b); } }, mHandler); } } else { setResult(RESULT_CANCELED); finish(); } return; } // TODO this code needs to change to use the decode/crop/encode single // step api so that we don't require that the whole (possibly large) // bitmap doesn't have to be read into memory if (mCrop == null) { return; } if (mSaving) { return; } mSaving = true; Bitmap croppedImage = null; Bitmap.Config bmpConfig = mHasApha ? Bitmap.Config.ARGB_8888 : Bitmap.Config.ARGB_8888; // If the output is required to a specific size, create an new image // with the cropped image in the center and the extra space filled. if (mOutputX != 0 && mOutputY != 0 && !mScale) { // Don't scale the image but instead fill it so it's the // required dimension try { croppedImage = Bitmap.createBitmap(mOutputX, mOutputY, bmpConfig); } catch (OutOfMemoryError e) { // 创建失败 e.printStackTrace(); OutOfMemoryHandler.handle(); Toast.makeText(this, getString(R.string.err_out_of_memory), Toast.LENGTH_SHORT); // Release bitmap memory as soon as possible mImageView.clear(); mBitmap.recycle(); mBitmap = null; setResult(RESULT_CANCELED); finish(); return; } Canvas canvas = new Canvas(croppedImage); Rect srcRect = mCrop.getCropRect(); Rect dstRect = new Rect(0, 0, mOutputX, mOutputY); int dx = (srcRect.width() - dstRect.width()) / 2; int dy = (srcRect.height() - dstRect.height()) / 2; // If the srcRect is too big, use the center part of it. srcRect.inset(Math.max(0, dx), Math.max(0, dy)); // If the dstRect is too big, use the center part of it. dstRect.inset(Math.max(0, -dx), Math.max(0, -dy)); // Draw the cropped bitmap in the center canvas.drawBitmap(mBitmap, srcRect, dstRect, null); // Release bitmap memory as soon as possible mImageView.clear(); mBitmap.recycle(); } else { Rect r = mCrop.getCropRect(); // int width = r.width(); // int height = r.height(); // If we are circle cropping, we want alpha channel, which is the // third param here. try { croppedImage = Bitmap.createBitmap(mOutputX, mOutputY, bmpConfig); } catch (OutOfMemoryError e) { e.printStackTrace(); OutOfMemoryHandler.handle(); // 创建失败 // Toast.makeText(this, getString(R.string.err_out_of_memory), // Toast.LENGTH_SHORT).show(); // Release bitmap memory as soon as possible mImageView.clear(); mBitmap.recycle(); setResult(RESULT_CANCELED); finish(); return; } Canvas canvas = new Canvas(croppedImage); canvas.setDrawFilter( new PaintFlagsDrawFilter( 0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); // 在有缩放的情况下需要提高绘图质量 Rect dstRect = new Rect(0, 0, mOutputX, mOutputY); canvas.drawBitmap(mBitmap, r, dstRect, null); // Release bitmap memory as soon as possible mImageView.clear(); mBitmap.recycle(); // if (mCircleCrop) { // // OK, so what's all this about? // // Bitmaps are inherently rectangular but we want to return // // something that's basically a circle. So we fill in the // // area around the circle with alpha. Note the all important // // PortDuff.Mode.CLEAR. // Canvas c = new Canvas(croppedImage); // Path p = new Path(); // p.addCircle(width / 2F, height / 2F, width / 2F, // Path.Direction.CW); // c.clipPath(p, Region.Op.DIFFERENCE); // c.drawColor(0x00000000, PorterDuff.Mode.CLEAR); // } // If the required dimension is specified, scale the image. // if (mOutputX != 0 && mOutputY != 0 && mScale) { // croppedImage = Util.transform(new Matrix(), croppedImage, // mOutputX, mOutputY, mScaleUp, Util.RECYCLE_INPUT); // } } mImageView.setImageBitmapResetBase(croppedImage, true); mImageView.center(true, true); mImageView.mHighlightViews.clear(); // Return the cropped image directly or save it to the specified URI. Bundle myExtras = getIntent().getExtras(); if (myExtras != null && (myExtras.getParcelable("data") != null || myExtras.getBoolean("return-data"))) { Bundle extras = new Bundle(); extras.putParcelable("data", croppedImage); setResult( RESULT_OK, (new Intent()).setAction(ICustomAction.ACTION_INLINE_DATA).putExtras(extras)); finish(); } else { final Bitmap b = croppedImage; final int msdId = mSetWallpaper ? R.string.wallpaper : R.string.savingImage; Util.startBackgroundJob( this, null, getResources().getString(msdId), new Runnable() { @Override public void run() { saveOutput(b); } }, mHandler); } }