List of usage examples for android.graphics Path moveTo
public void moveTo(float x, float y)
From source file:de.uni_weimar.mheinz.androidtouchscope.display.ScopeView.java
private void initDrawable(ShapeDrawable drawable, Path path, int color, int width, int height) { path.moveTo(0, 0); drawable.setShape(new PathShape(path, width, height)); drawable.getPaint().setStyle(Paint.Style.STROKE); drawable.getPaint().setColor(color); drawable.setBounds(0, 0, width, height); setLayerType(LAYER_TYPE_SOFTWARE, drawable.getPaint()); }
From source file:org.navitproject.navit.NavitGraphics.java
protected void draw_text(Paint paint, int x, int y, String text, int size, int dx, int dy, int bgcolor) { int oldcolor = paint.getColor(); Path path = null; paint.setTextSize(size / 15);// www.jav a 2 s . com paint.setStyle(Paint.Style.FILL); if (dx != 0x10000 || dy != 0) { path = new Path(); path.moveTo(x, y); path.rLineTo(dx, dy); paint.setTextAlign(android.graphics.Paint.Align.LEFT); } if (bgcolor != 0) { paint.setStrokeWidth(3); paint.setColor(bgcolor); paint.setStyle(Paint.Style.STROKE); if (path == null) { draw_canvas.drawText(text, x, y, paint); } else { draw_canvas.drawTextOnPath(text, path, 0, 0, paint); } paint.setStyle(Paint.Style.FILL); paint.setColor(oldcolor); } if (path == null) { draw_canvas.drawText(text, x, y, paint); } else { draw_canvas.drawTextOnPath(text, path, 0, 0, paint); } paint.clearShadowLayer(); }
From source file:com.breel.wearables.shadowclock.graphics.ShapeShadow.java
public void parseJSON(String jsonFile) { if (jsonFile != null) { // Load all the JSONs with the numbers information try {/*from w ww .j a va 2 s. c o m*/ JSONObject obj = new JSONObject(loadJSONFromAsset(jsonFile)); Log.d(TAG, "SHAPE SHADOW JSON FILE " + jsonFile + ": LOADED"); id = obj.getString("id"); JSONArray jsonPathData; JSONArray jsonShadowData; if (!id.equals("5")) { jsonPathData = obj.getJSONArray("path"); jsonShadowData = obj.getJSONArray("shadow"); Log.d(TAG, "JSON PATH DATA LENGTH: " + jsonPathData.length() + ""); Log.d(TAG, "JSON SHADOW DATA LENGTH: " + jsonShadowData.length() + ""); shapePath.reset(); for (int i = 0; i < jsonPathData.length(); i++) { try { JSONObject elem = jsonPathData.getJSONObject(i); String type = elem.getString("type"); JSONArray data = elem.getJSONArray("data"); if (type.equals("move")) { shapePath.moveTo((float) data.getInt(0), (float) data.getInt(1)); } else if (type.equals("line")) { shapePath.lineTo((float) data.getInt(0), (float) data.getInt(1)); } else if (type.equals("bezier")) { shapePath.cubicTo((float) data.getInt(0), (float) data.getInt(1), (float) data.getInt(2), (float) data.getInt(3), (float) data.getInt(4), (float) data.getInt(5)); } } catch (JSONException e) { Log.d(TAG, "JSON ELEM EXCEPTION" + e.getMessage() + ""); } } shapePath.close(); Random r = new Random(); r.nextGaussian(); JSONArray holesContainer = obj.getJSONArray("holes"); Path holePath = new Path(); for (int i = 0; i < holesContainer.length(); i++) { JSONObject jsonInside = holesContainer.getJSONObject(i); JSONArray hole = jsonInside.getJSONArray("data"); holePath.reset(); for (int j = 0; j < hole.length(); j++) { try { JSONObject elem = hole.getJSONObject(j); String type = elem.getString("type"); JSONArray data = elem.getJSONArray("data"); if (type.equals("move")) { holePath.moveTo((float) data.getInt(0), (float) data.getInt(1)); } else if (type.equals("line")) { holePath.lineTo((float) data.getInt(0), (float) data.getInt(1)); } else if (type.equals("bezier")) { holePath.cubicTo((float) data.getInt(0), (float) data.getInt(1), (float) data.getInt(2), (float) data.getInt(3), (float) data.getInt(4), (float) data.getInt(5)); } } catch (JSONException e) { Log.d(TAG, "JSON HOLE EXCEPTION" + e.getMessage() + ""); } } holePath.close(); shapePath.op(holePath, Path.Op.DIFFERENCE); } pathTransform.reset(); pathTransform.setScale(scale + 0.04f, scale + 0.04f); shapePath.transform(pathTransform); boundsPath.transform(pathTransform); pathTransform.setTranslate(positionX - 0.3f, positionY - 0.3f); shapePath.transform(pathTransform); boundsPath.transform(pathTransform); int shadowTmpX; int shadowTmpY; shadowPaths.clear(); vertexArray.clear(); for (int i = 0; i < jsonShadowData.length(); i += 2) { shadowTmpX = jsonShadowData.getInt(i); shadowTmpY = jsonShadowData.getInt(i + 1); addVertex(shadowTmpX, shadowTmpY); } } else { jsonPathData = obj.getJSONArray("path"); jsonShadowData = obj.getJSONArray("shadow"); Log.d(TAG, "JSON PATH DATA LENGTH: " + jsonPathData.length() + ""); Log.d(TAG, "JSON SHADOW DATA LENGTH: " + jsonShadowData.length() + ""); shapePath.reset(); for (int i = 0; i < jsonPathData.length(); i++) { JSONArray cords = jsonPathData.getJSONArray(i); Path chunk = new Path(); chunk.reset(); for (int j = 0; j < cords.length(); j++) { try { JSONObject elem = cords.getJSONObject(j); String type = elem.getString("type"); JSONArray data = elem.getJSONArray("data"); if (type.equals("move")) { chunk.moveTo((float) data.getInt(0), (float) data.getInt(1)); } else if (type.equals("line")) { chunk.lineTo((float) data.getInt(0), (float) data.getInt(1)); } else if (type.equals("bezier")) { chunk.cubicTo((float) data.getInt(0), (float) data.getInt(1), (float) data.getInt(2), (float) data.getInt(3), (float) data.getInt(4), (float) data.getInt(5)); } } catch (JSONException e) { Log.d(TAG, "JSON 5 NUMBER ELEM EXCEPTION" + e.getMessage() + ""); } } chunk.close(); shapePath.op(chunk, Path.Op.UNION); } pathTransform.reset(); pathTransform.setScale(scale, scale); shapePath.transform(pathTransform); boundsPath.transform(pathTransform); pathTransform.setTranslate(positionX, positionY); shapePath.transform(pathTransform); boundsPath.transform(pathTransform); shadowPaths.clear(); vertexArray.clear(); int shadowTmpX; int shadowTmpY; for (int i = 0; i < jsonShadowData.length(); i++) { JSONArray coords = jsonShadowData.getJSONArray(i); for (int j = 0; j < coords.length(); j += 2) { shadowTmpX = coords.getInt(j); shadowTmpY = coords.getInt(j + 1); addVertex((float) shadowTmpX, (float) shadowTmpY); } } } } catch (JSONException e) { Log.d(TAG, "JSON ROOT EXCEPTION" + e.getMessage() + ""); } } }
From source file:de.uni_weimar.mheinz.androidtouchscope.display.ScopeView.java
private void initGridH(ShapeDrawable drawable, Path path, int color, int width, int height) { path.rewind();//from w ww .ja v a 2 s . com float cellHeight = height / NUM_ROWS; for (int i = 0; i < NUM_ROWS; ++i) { path.moveTo(0, i * cellHeight); path.lineTo(width, i * cellHeight); } float offset = NUM_COLUMNS * 5; drawable.setShape(new PathShape(path, width, height)); drawable.getPaint().setStyle(Paint.Style.STROKE); drawable.getPaint().setColor(color); drawable.getPaint().setPathEffect(new DashPathEffect(new float[] { 1, (width - offset) / offset }, 0)); drawable.setBounds(0, 0, width, height); }
From source file:de.uni_weimar.mheinz.androidtouchscope.display.ScopeView.java
private void initGridV(ShapeDrawable drawable, Path path, int color, int width, int height) { path.rewind();// ww w. j a va2s .c o m float cellWidth = width / NUM_COLUMNS; for (int i = 0; i < NUM_COLUMNS; ++i) { path.moveTo(i * cellWidth, 0); path.lineTo(i * cellWidth, height); } float offset = NUM_ROWS * 5; drawable.setShape(new PathShape(path, width, height)); drawable.getPaint().setStyle(Paint.Style.STROKE); drawable.getPaint().setColor(color); drawable.getPaint().setPathEffect(new DashPathEffect(new float[] { 1, (height - offset) / offset }, 0)); drawable.setBounds(0, 0, width, height); }
From source file:de.uni_weimar.mheinz.androidtouchscope.display.ScopeView.java
private int updatePath(Path path, WaveData waveData) { int retValue = -1; if (waveData == null || waveData.data == null || waveData.data.length == 0) { path.rewind();/*from ww w .j a v a2 s . co m*/ return retValue; } retValue = 0; int length = Math.min(BaseScope.SAMPLE_LENGTH, waveData.data.length) - 10; float widthRatio = (float) (mContentWidth) / (length * DISPLAY_RATIO); double vScale = waveData.voltageScale; if (vScale == 0) vScale = 1.0f; Path newPath = new Path(); double point = manipulatePoint(waveData.voltageOffset, vScale, waveData.data[10]); float j = -(length * (1 - DISPLAY_RATIO)) / 2; newPath.moveTo(j++ * widthRatio, (float) point); for (int i = 11; i < waveData.data.length; ++i, ++j) { point = manipulatePoint(waveData.voltageOffset, vScale, waveData.data[i]); newPath.lineTo(j * widthRatio, (float) point); } if (new PathMeasure(path, false).getLength() == 0) { path.set(newPath); return retValue; } if (mChangeDelay <= 0) { path.set(newPath); retValue = 1; } else { mChangeDelay--; } return retValue; }
From source file:com.github.shareme.gwsmaterialuikit.library.material.drawable.LineMorphingDrawable.java
private void updatePathWithState(Path path, State state) { if (state.links != null) { for (int i = 0; i < state.links.length; i += 2) { int index1 = state.links[i] * 4; int index2 = state.links[i + 1] * 4; float x1 = getX(state.points[index1]); float y1 = getY(state.points[index1 + 1]); float x2 = getX(state.points[index1 + 2]); float y2 = getY(state.points[index1 + 3]); float x3 = getX(state.points[index2]); float y3 = getY(state.points[index2 + 1]); float x4 = getX(state.points[index2 + 2]); float y4 = getY(state.points[index2 + 3]); if (x1 == x3 && y1 == y3) { path.moveTo(x2, y2); path.lineTo(x1, y1);/*from w w w . j a v a 2 s . com*/ path.lineTo(x4, y4); } else if (x1 == x4 && y1 == y4) { path.moveTo(x2, y2); path.lineTo(x1, y1); path.lineTo(x3, y3); } else if (x2 == x3 && y2 == y3) { path.moveTo(x1, y1); path.lineTo(x2, y2); path.lineTo(x4, y4); } else { path.moveTo(x1, y1); path.lineTo(x2, y2); path.lineTo(x3, y3); } } for (int i = 0, count = state.points.length / 4; i < count; i++) { boolean exist = false; for (int j = 0; j < state.links.length; j++) if (state.links[j] == i) { exist = true; break; } if (exist) continue; int index = i * 4; path.moveTo(getX(state.points[index]), getY(state.points[index + 1])); path.lineTo(getX(state.points[index + 2]), getY(state.points[index + 3])); } } else { for (int i = 0, count = state.points.length / 4; i < count; i++) { int index = i * 4; path.moveTo(getX(state.points[index]), getY(state.points[index + 1])); path.lineTo(getX(state.points[index + 2]), getY(state.points[index + 3])); } } }
From source file:cw.kop.autobackground.settings.WearSettingsFragment.java
private void drawAnalog() { if (!AppSettings.getTimeType().equals(AppSettings.ANALOG)) { return;/*from w w w.java 2 s . co m*/ } canvas = surfaceView.getHolder().lockCanvas(); if (canvas == null) { return; } setPaints(); if (imageBitmap != null) { canvas.drawBitmap(imageBitmap, 0, 0, bitmapPaint); } // Time time = new Time(); // time.setToNow(); // time.set(time.toMillis(false) + AppSettings.getTimeOffset()); // // float hour = time.hour + time.minute / 60f; // float minute = time.minute + time.second / 60f; // float second = time.second; float centerX = watchContainer.getWidth() * 0.222f; float centerY = watchContainer.getHeight() * 0.222f; float radius = centerX; // Draw tick marks for (int i = 0; i < 12; i++) { canvas.drawLine((float) (centerX + (radius * tickRadius / 100f) * Math.cos(Math.toRadians(i * 30f))), (float) (centerY + (radius * tickRadius / 100f) * Math.sin(Math.toRadians(i * 30f))), (float) (centerX + (radius) * Math.cos(Math.toRadians(i * 30f))), (float) (centerY + (radius) * Math.sin(Math.toRadians(i * 30f))), tickPaint); } // Draw clock hands // Draw shadows first to prevent outline overlapping other hands Path hourShadowPath = new Path(); hourShadowPath.moveTo((float) (centerX + hourWidth / 1.5f * Math.cos(Math.toRadians(90f))), (float) (centerY + hourWidth / 1.5f * Math.sin(Math.toRadians(90f)))); hourShadowPath.quadTo((float) (centerX - (hourWidth / 1.5f) * Math.cos(Math.toRadians(0f))), (float) (centerY - (hourWidth / 1.5f) * Math.sin(Math.toRadians(0f))), (float) (centerX + hourWidth / 1.5f * Math.cos(Math.toRadians(270f))), (float) (centerY + hourWidth / 1.5f * Math.sin(Math.toRadians(270f)))); hourShadowPath.lineTo( (float) (centerX + (radius * hourRadius / 100f + 2.0f) * Math.cos(Math.toRadians(0f))), (float) (centerY + (radius * hourRadius / 100f + 2.0f) * Math.sin(Math.toRadians(0f)))); hourShadowPath.close(); canvas.drawPath(hourShadowPath, hourShadowPaint); Path minuteShadowPath = new Path(); minuteShadowPath.moveTo((float) (centerX + minuteWidth / 1.5f * Math.cos(Math.toRadians(0f))), (float) (centerY + minuteWidth / 1.5f * Math.sin(Math.toRadians(0f)))); minuteShadowPath.quadTo((float) (centerX - (minuteWidth / 1.5f) * Math.cos(Math.toRadians(-180f))), (float) (centerY - (minuteWidth / 1.5f) * Math.sin(Math.toRadians(-180f))), (float) (centerX + minuteWidth / 1.5f * Math.cos(Math.toRadians(90f))), (float) (centerY + minuteWidth / 1.5f * Math.sin(Math.toRadians(90f)))); minuteShadowPath.lineTo( (float) (centerX + (radius * minuteRadius / 100f + 2.0f) * Math.cos(Math.toRadians(-90f))), (float) (centerY + (radius * minuteRadius / 100f + 2.0f) * Math.sin(Math.toRadians(-90f)))); minuteShadowPath.close(); canvas.drawPath(minuteShadowPath, minuteShadowPaint); Path secondShadowPath = new Path(); secondShadowPath.moveTo((float) (centerX + secondWidth / 1.5f * Math.cos(Math.toRadians(225f))), (float) (centerY + secondWidth / 1.5f * Math.sin(Math.toRadians(225f)))); secondShadowPath.quadTo((float) (centerX - (secondWidth / 1.5f) * Math.cos(Math.toRadians(45f))), (float) (centerY - (secondWidth / 1.5f) * Math.sin(Math.toRadians(45f))), (float) (centerX + secondWidth / 1.5f * Math.cos(Math.toRadians(315f))), (float) (centerY + secondWidth / 1.5f * Math.sin(Math.toRadians(315f)))); secondShadowPath.lineTo( (float) (centerX + (radius * secondRadius / 100f + 2f) * Math.cos(Math.toRadians(135f))), (float) (centerY + (radius * secondRadius / 100f + 2.0f) * Math.sin(Math.toRadians(135f)))); secondShadowPath.close(); canvas.drawPath(secondShadowPath, secondShadowPaint); // Now draw actual hands Path hourPath = new Path(); hourPath.moveTo((float) (centerX + hourWidth / 2f * Math.cos(Math.toRadians(90f))), (float) (centerY + hourWidth / 2f * Math.sin(Math.toRadians(90f)))); hourPath.quadTo((float) (centerX - (hourWidth / 2f) * Math.cos(Math.toRadians(0f))), (float) (centerY - (hourWidth / 2f) * Math.sin(Math.toRadians(0f))), (float) (centerX + hourWidth / 2f * Math.cos(Math.toRadians(270f))), (float) (centerY + hourWidth / 2f * Math.sin(Math.toRadians(270f)))); hourPath.lineTo((float) (centerX + (radius * hourRadius / 100f) * Math.cos(Math.toRadians(0f))), (float) (centerY + (radius * hourRadius / 100f) * Math.sin(Math.toRadians(0f)))); hourPath.close(); canvas.drawPath(hourPath, hourPaint); Path minutePath = new Path(); minutePath.moveTo((float) (centerX + minuteWidth / 2f * Math.cos(Math.toRadians(0f))), (float) (centerY + minuteWidth / 2f * Math.sin(Math.toRadians(0f)))); minutePath.quadTo((float) (centerX - (minuteWidth / 2f) * Math.cos(Math.toRadians(-180f))), (float) (centerY - (minuteWidth / 2f) * Math.sin(Math.toRadians(-180f))), (float) (centerX + minuteWidth / 2f * Math.cos(Math.toRadians(90f))), (float) (centerY + minuteWidth / 2f * Math.sin(Math.toRadians(90f)))); minutePath.lineTo((float) (centerX + (radius * minuteRadius / 100f) * Math.cos(Math.toRadians(-90f))), (float) (centerY + (radius * minuteRadius / 100f) * Math.sin(Math.toRadians(-90f)))); minutePath.close(); canvas.drawPath(minutePath, minutePaint); Path secondPath = new Path(); secondPath.moveTo((float) (centerX + secondWidth / 2f * Math.cos(Math.toRadians(225f))), (float) (centerY + secondWidth / 2f * Math.sin(Math.toRadians(225f)))); secondPath.quadTo((float) (centerX - (secondWidth / 2f) * Math.cos(Math.toRadians(45f))), (float) (centerY - (secondWidth / 2f) * Math.sin(Math.toRadians(45f))), (float) (centerX + secondWidth / 2f * Math.cos(Math.toRadians(315f))), (float) (centerY + secondWidth / 2f * Math.sin(Math.toRadians(315f)))); secondPath.lineTo((float) (centerX + (radius * secondRadius / 100f) * Math.cos(Math.toRadians(135f))), (float) (centerY + (radius * secondRadius / 100f) * Math.sin(Math.toRadians(135f)))); secondPath.close(); canvas.drawPath(secondPath, secondPaint); surfaceView.getHolder().unlockCanvasAndPost(canvas); }
From source file:nu.yona.app.customview.graph.SpreadGraph.java
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); this.mCanvas = canvas; float fullWidth = canvas.getWidth(); float heightOfbar = GraphUtils.convertSizeToDeviceDependent(mContext, graphHeight); //first bar/* www . j av a 2 s. com*/ float mXStart = 0, mYStart = heightOfbar; // basically (X1, Y1) float bottom = heightOfbar; // height (distance from Y1 to Y2) mStartPoint = 0; mMiddlePoint = (fullWidth / 2); float spreadtime = fullWidth; float mPartSize = spreadtime / mNoParts; //todraw text from height float heightDraw = bottom + (GraphUtils.MARGIN_TOP * scaleFactor); //draw graphics of sun and moon Bitmap moonBitmap = drawableToBitmap(ContextCompat.getDrawable(mContext, R.drawable.icon_moon)); float bitmapWidth = moonBitmap.getWidth() / 2; mCanvas.drawBitmap(moonBitmap, mStartPoint - (5 * scaleFactor), bottom + (5 * scaleFactor), null); mCanvas.drawBitmap(drawableToBitmap(ContextCompat.getDrawable(mContext, R.drawable.icn_sun)), mMiddlePoint - bitmapWidth, bottom + (5 * scaleFactor), null); float textPoint = (mMiddlePoint / 2) / 2; mCanvas.drawText(mContext.getString(R.string.four_hours), textPoint, heightDraw + scaleFactor, getFontStyle()); float textPoint2 = textPoint * 2 + ((textPoint / 2)); mCanvas.drawText(mContext.getString(R.string.eight_hours), textPoint2, heightDraw + scaleFactor, getFontStyle()); float textPoint3 = textPoint * 5; mCanvas.drawText(mContext.getString(R.string.sixteen_hours), textPoint3 - bitmapWidth, heightDraw + scaleFactor, getFontStyle()); float textPoint4 = textPoint * 6 + ((textPoint / 2)); mCanvas.drawText(mContext.getString(R.string.twenty_hours), textPoint4 - bitmapWidth, heightDraw + scaleFactor, getFontStyle()); float textPoint5 = textPoint * 7 + ((textPoint / 2)); mCanvas.drawBitmap(drawableToBitmap(ContextCompat.getDrawable(mContext, R.drawable.icon_moon)), textPoint5, bottom + (5 * scaleFactor), null); if (mListZoneSpread != null && mListZoneSpread.size() > 0) { float currentStartPos; float currentEndPos; Paint barGraphPaint = new Paint(); barGraphPaint.setStyle(Paint.Style.STROKE); barGraphPaint.setStrokeWidth(5); boolean skipThis; for (TimeZoneSpread timeZoneSpread : mListZoneSpread) { skipThis = false; currentStartPos = (float) timeZoneSpread.getIndex() * mPartSize; Path barPath = new Path(); if (timeZoneSpread.getColor() == GraphUtils.COLOR_PINK || timeZoneSpread.getColor() == GraphUtils.COLOR_BLUE) { currentEndPos = timeZoneSpread.getUsedValue(); barGraphPaint.setColor(timeZoneSpread.getColor()); } else if (timeZoneSpread.getColor() == GraphUtils.COLOR_GREEN) { if (timeZoneSpread.getUsedValue() == 15) { currentEndPos = startEndPoint; barGraphPaint.setColor(GraphUtils.COLOR_BULLET_DOT); } else { currentEndPos = startEndPoint; barGraphPaint.setColor(GraphUtils.COLOR_BLUE); } } else if (timeZoneSpread.getUsedValue() != 15 && timeZoneSpread.getColor() == GraphUtils.COLOR_BULLET_LIGHT_DOT) { currentEndPos = startEndPoint; barGraphPaint.setColor(timeZoneSpread.getColor()); skipThis = true; } else { currentEndPos = startEndPoint; barGraphPaint.setColor(timeZoneSpread.getColor()); } if (!skipThis) { float newXPos = mXStart + currentStartPos; barPath.moveTo(newXPos + 2, mYStart); float noPartsHeight = heightOfbar / 15; barPath.lineTo(currentStartPos + 2, mYStart - (currentEndPos * noPartsHeight) - 1); canvas.drawPath(barPath, barGraphPaint); } } } }
From source file:org.onebusaway.android.map.googlemapsv2.StopOverlay.java
/** * Creates a bus stop icon with the given direction arrow, or without a direction arrow if * the direction is NO_DIRECTION/*from w w w.j av a 2 s . co m*/ * * @param direction Bus stop direction, obtained from ObaStop.getDirection() and defined in * constants in this class, or NO_DIRECTION if the stop icon shouldn't have a * direction arrow * @return a bus stop icon bitmap with the arrow pointing the given direction, or with no arrow * if direction is NO_DIRECTION */ private static Bitmap createBusStopIcon(String direction) throws NullPointerException { if (direction == null) { throw new IllegalArgumentException(direction); } Resources r = Application.get().getResources(); Context context = Application.get(); Float directionAngle = null; // 0-360 degrees Bitmap bm; Canvas c; Drawable shape; Float rotationX = null, rotationY = null; // Point around which to rotate the arrow Paint arrowPaintFill = new Paint(); arrowPaintFill.setStyle(Paint.Style.FILL); arrowPaintFill.setAntiAlias(true); if (direction.equals(NO_DIRECTION)) { // Don't draw the arrow bm = Bitmap.createBitmap(mPx, mPx, Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds(0, 0, bm.getWidth(), bm.getHeight()); } else if (direction.equals(NORTH)) { directionAngle = 0f; bm = Bitmap.createBitmap(mPx, (int) (mPx + mBuffer), Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds(0, (int) mBuffer, mPx, bm.getHeight()); // Shade with darkest color at tip of arrow arrowPaintFill.setShader(new LinearGradient(bm.getWidth() / 2, 0, bm.getWidth() / 2, mArrowHeightPx, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); // For NORTH, no rotation occurs - use center of image anyway so we have some value rotationX = bm.getWidth() / 2f; rotationY = bm.getHeight() / 2f; } else if (direction.equals(NORTH_WEST)) { directionAngle = 315f; // Arrow is drawn N, rotate 315 degrees bm = Bitmap.createBitmap((int) (mPx + mBuffer), (int) (mPx + mBuffer), Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds((int) mBuffer, (int) mBuffer, bm.getWidth(), bm.getHeight()); // Shade with darkest color at tip of arrow arrowPaintFill.setShader(new LinearGradient(0, 0, mBuffer, mBuffer, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); // Rotate around below coordinates (trial and error) rotationX = mPx / 2f + mBuffer / 2f; rotationY = bm.getHeight() / 2f - mBuffer / 2f; } else if (direction.equals(WEST)) { directionAngle = 0f; // Arrow is drawn pointing West, so no rotation bm = Bitmap.createBitmap((int) (mPx + mBuffer), mPx, Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds((int) mBuffer, 0, bm.getWidth(), bm.getHeight()); arrowPaintFill.setShader(new LinearGradient(0, bm.getHeight() / 2, mArrowHeightPx, bm.getHeight() / 2, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); // For WEST rotationX = bm.getHeight() / 2f; rotationY = bm.getHeight() / 2f; } else if (direction.equals(SOUTH_WEST)) { directionAngle = 225f; // Arrow is drawn N, rotate 225 degrees bm = Bitmap.createBitmap((int) (mPx + mBuffer), (int) (mPx + mBuffer), Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds((int) mBuffer, 0, bm.getWidth(), mPx); arrowPaintFill.setShader(new LinearGradient(0, bm.getHeight(), mBuffer, bm.getHeight() - mBuffer, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); // Rotate around below coordinates (trial and error) rotationX = bm.getWidth() / 2f - mBuffer / 4f; rotationY = mPx / 2f + mBuffer / 4f; } else if (direction.equals(SOUTH)) { directionAngle = 180f; // Arrow is drawn N, rotate 180 degrees bm = Bitmap.createBitmap(mPx, (int) (mPx + mBuffer), Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds(0, 0, bm.getWidth(), (int) (bm.getHeight() - mBuffer)); arrowPaintFill.setShader(new LinearGradient(bm.getWidth() / 2, bm.getHeight(), bm.getWidth() / 2, bm.getHeight() - mArrowHeightPx, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); rotationX = bm.getWidth() / 2f; rotationY = bm.getHeight() / 2f; } else if (direction.equals(SOUTH_EAST)) { directionAngle = 135f; // Arrow is drawn N, rotate 135 degrees bm = Bitmap.createBitmap((int) (mPx + mBuffer), (int) (mPx + mBuffer), Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds(0, 0, mPx, mPx); arrowPaintFill.setShader(new LinearGradient(bm.getWidth(), bm.getHeight(), bm.getWidth() - mBuffer, bm.getHeight() - mBuffer, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); // Rotate around below coordinates (trial and error) rotationX = (mPx + mBuffer / 2) / 2f; rotationY = bm.getHeight() / 2f; } else if (direction.equals(EAST)) { directionAngle = 180f; // Arrow is drawn pointing West, so rotate 180 bm = Bitmap.createBitmap((int) (mPx + mBuffer), mPx, Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds(0, 0, mPx, bm.getHeight()); arrowPaintFill.setShader(new LinearGradient(bm.getWidth(), bm.getHeight() / 2, bm.getWidth() - mArrowHeightPx, bm.getHeight() / 2, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); rotationX = bm.getWidth() / 2f; rotationY = bm.getHeight() / 2f; } else if (direction.equals(NORTH_EAST)) { directionAngle = 45f; // Arrow is drawn pointing N, so rotate 45 degrees bm = Bitmap.createBitmap((int) (mPx + mBuffer), (int) (mPx + mBuffer), Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds(0, (int) mBuffer, mPx, bm.getHeight()); // Shade with darkest color at tip of arrow arrowPaintFill.setShader(new LinearGradient(bm.getWidth(), 0, bm.getWidth() - mBuffer, mBuffer, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); // Rotate around middle of circle rotationX = (float) mPx / 2; rotationY = bm.getHeight() - (float) mPx / 2; } else { throw new IllegalArgumentException(direction); } shape.draw(c); if (direction.equals(NO_DIRECTION)) { // Everything after this point is for drawing the arrow image, so return the bitmap as-is for no arrow return bm; } /** * Draw the arrow - all dimensions should be relative to px so the arrow is drawn the same * size for all orientations */ // Height of the cutout in the bottom of the triangle that makes it an arrow (0=triangle) final float CUTOUT_HEIGHT = mPx / 12; Path path = new Path(); float x1 = 0, y1 = 0; // Tip of arrow float x2 = 0, y2 = 0; // lower left float x3 = 0, y3 = 0; // cutout in arrow bottom float x4 = 0, y4 = 0; // lower right if (direction.equals(NORTH) || direction.equals(SOUTH) || direction.equals(NORTH_EAST) || direction.equals(SOUTH_EAST) || direction.equals(NORTH_WEST) || direction.equals(SOUTH_WEST)) { // Arrow is drawn pointing NORTH // Tip of arrow x1 = mPx / 2; y1 = 0; // lower left x2 = (mPx / 2) - (mArrowWidthPx / 2); y2 = mArrowHeightPx; // cutout in arrow bottom x3 = mPx / 2; y3 = mArrowHeightPx - CUTOUT_HEIGHT; // lower right x4 = (mPx / 2) + (mArrowWidthPx / 2); y4 = mArrowHeightPx; } else if (direction.equals(EAST) || direction.equals(WEST)) { // Arrow is drawn pointing WEST // Tip of arrow x1 = 0; y1 = mPx / 2; // lower left x2 = mArrowHeightPx; y2 = (mPx / 2) - (mArrowWidthPx / 2); // cutout in arrow bottom x3 = mArrowHeightPx - CUTOUT_HEIGHT; y3 = mPx / 2; // lower right x4 = mArrowHeightPx; y4 = (mPx / 2) + (mArrowWidthPx / 2); } path.setFillType(Path.FillType.EVEN_ODD); path.moveTo(x1, y1); path.lineTo(x2, y2); path.lineTo(x3, y3); path.lineTo(x4, y4); path.lineTo(x1, y1); path.close(); // Rotate arrow around (rotationX, rotationY) point Matrix matrix = new Matrix(); matrix.postRotate(directionAngle, rotationX, rotationY); path.transform(matrix); c.drawPath(path, arrowPaintFill); c.drawPath(path, mArrowPaintStroke); return bm; }