/** * build an accented character out of two pre-defined glyphs. * * @param x the x offset of the accent * @param y the y offset of the accent * @param b the index of the base glyph * @param a the index of the accent glyph * @param gp the GeneralPath into which the combined glyph will be written. */ private void buildAccentChar(float x, float y, char b, char a, Path gp) { // get the outline of the accent Path pathA = getOutline(a, getWidth(a, null)); // undo the effect of the transform applied in read Matrix xformA = new Matrix(); xformA.setTranslate(x, y); Matrix tmp = new Matrix(at); if (at.invert(tmp)) { xformA.preConcat(tmp); } else { // oh well ... } pathA.transform(xformA); Path pathB = getOutline(b, getWidth(b, null)); Matrix xformB = new Matrix(); if (at.invert(xformB)) { pathB.transform(xformB); } else { // ignore } gp.addPath(pathB); gp.addPath(pathA); }
private void computePath(Rect bounds) { final float currentScale = mCurrentScale; final Path path = mPath; final RectF rect = mRect; final Matrix matrix = mMatrix; path.reset(); int totalSize = Math.min(bounds.width(), bounds.height()); float initial = mClosedStateSize; float destination = totalSize; float currentSize = initial + (destination - initial) * currentScale; float halfSize = currentSize / 2f; float inverseScale = 1f - currentScale; float cornerSize = halfSize * inverseScale; float[] corners = new float[] { halfSize, halfSize, halfSize, halfSize, halfSize, halfSize, cornerSize, cornerSize }; rect.set(bounds.left, bounds.top, bounds.left + currentSize, bounds.top + currentSize); path.addRoundRect(rect, corners, Path.Direction.CCW); matrix.reset(); matrix.postRotate(-45, bounds.left + halfSize, bounds.top + halfSize); matrix.postTranslate((bounds.width() - currentSize) / 2, 0); float hDiff = (bounds.bottom - currentSize - mExternalOffset) * inverseScale; matrix.postTranslate(0, hDiff); path.transform(matrix); }
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 protected void onBoundsChange(Rect bounds) { if (pathForTurn != null) { Matrix m = new Matrix(); m.setScale(bounds.width() / 72f, bounds.height() / 72f); pathForTurn.transform(m, pathForTurn); } }
private void drawArrow(Canvas c) { int height = getHeight(); int width = getWidth(); // Create a buffer around the arrow so when it rotates it doesn't get clipped by view edge final float BUFFER = width / 5; // Height of the cutout in the bottom of the triangle that makes it an arrow (0=triangle) final float CUTOUT_HEIGHT = getHeight() / 5; float x1, y1; // Tip of arrow x1 = width / 2; y1 = BUFFER; float x2, y2; // lower left x2 = BUFFER; y2 = height - BUFFER; float x3, y3; // cutout in arrow bottom x3 = width / 2; y3 = height - CUTOUT_HEIGHT - BUFFER; float x4, y4; // lower right x4 = width - BUFFER; y4 = height - BUFFER; Path path = new Path(); 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(); float direction = mHeading - mBearingToStop; // Make sure value is between 0-360 direction = MathUtils.mod(direction, 360.0f); // Rotate arrow around center point Matrix matrix = new Matrix(); matrix.postRotate((float) -direction, width / 2, height / 2); path.transform(matrix); c.drawPath(path, mArrowPaint); c.drawPath(path, mArrowFillPaint); // Update content description, so screen readers can announce direction to stop String[] spokenDirections = getResources().getStringArray(R.array.spoken_compass_directions); String directionName = spokenDirections[MathUtils.getHalfWindIndex(direction)]; setContentDescription(directionName); }
@Override public void draw(Canvas canvas) { String file = getEnvObject().getCurrentRepresentation().getIcon(); Path objectPath = DrawingUtils.freedomPolygonToPath( (FreedomPolygon) getEnvObject().getCurrentRepresentation().getShape()); RectF box = new RectF(); objectPath.computeBounds(box, true); System.out.print("GPT box: box widht:" + box.width() + " box heigh" + box.height()); drawingMatrix = new Matrix(); float rotation = (float) getEnvObject().getCurrentRepresentation().getRotation(); drawingMatrix.postRotate(rotation); drawingMatrix.postTranslate( getEnvObject().getCurrentRepresentation().getOffset().getX(), getEnvObject().getCurrentRepresentation().getOffset().getY()); Bitmap bmp = null; if (file != null) { // TODO: Asign the bmp in the setEnvObject bmp = BitmapUtils.getImage(file, (int) box.width(), (int) box.height()); } if (bmp != null) { ghostBitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Config.ARGB_8888); canvas.drawBitmap(bmp, drawingMatrix, null); } else { // TODO: Cache path Paint paint = new Paint(); paint.setStyle(Style.FILL); ghostPath = new Path(); objectPath.transform(drawingMatrix, ghostPath); int fillColor = -1; try { fillColor = Color.parseColor(getEnvObject().getCurrentRepresentation().getFillColor()); paint.setColor(fillColor); canvas.drawPath(ghostPath, paint); } catch (IllegalArgumentException ex) { System.out.println("ParseColor exception in fill"); } int borderColor = -1; try { borderColor = Color.parseColor(getEnvObject().getCurrentRepresentation().getBorderColor()); paint.setColor(borderColor); paint.setStyle(Style.STROKE); canvas.drawPath(ghostPath, paint); } catch (IllegalArgumentException ex) { System.out.println("ParseColor exception in border"); } } }
Path smoothPath(Coordinate[] coords) { Path path = new Path(); path.moveTo((float) coords[0].x, (float) coords[0].y); Iterator<Coordinate> ctrl = cubicSplineControlPoints(coords, 0).iterator(); for (int i = 1; i < coords.length; i++) { Coordinate c = coords[i]; Coordinate ctrl1 = ctrl.next(); Coordinate ctrl2 = ctrl.next(); path.cubicTo( (float) ctrl1.x, (float) ctrl1.y, (float) ctrl2.x, (float) ctrl2.y, (float) c.x, (float) c.y); } path.transform(tx.worldToCanvas); return path; }
/** * Read the data for a glyph from the glyph table, and transform it based on the current * transform. * * @param base the start of the glyph table * @param offset the index of this glyph in the glyph table */ private synchronized Path readGlyph(int base, int offset) { FlPoint pt = new FlPoint(); // find this entry Range r = getIndexEntry(base, offset); // create a path Path gp = new Path(); // rember the start position (for recursive calls due to seac) int hold = pos; // read the glyph itself stackptr = 0; parseGlyph(r, gp, pt); // restore the start position pos = hold; gp.transform(at); return gp; }
/** * Creates a bus stop icon with the given direction arrow, or without a direction arrow if the * direction is NO_DIRECTION * * @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; }
// draw path 96x96 public static void calcTurnPath(Path pathForTurn, TurnType turnType, Matrix transform) { if (turnType == null) { return; } pathForTurn.reset(); int c = 48; int w = 16; pathForTurn.moveTo(c, 94); float sarrowL = 30; // side of arrow float harrowL = (float) Math.sqrt(2) * sarrowL; // hypotenuse of arrow float spartArrowL = (float) ((sarrowL - w / Math.sqrt(2)) / 2); float hpartArrowL = (float) (harrowL - w) / 2; if (TurnType.C.equals(turnType.getValue())) { int h = 65; pathForTurn.rMoveTo(w / 2, 0); pathForTurn.rLineTo(0, -h); pathForTurn.rLineTo(hpartArrowL, 0); pathForTurn.rLineTo(-harrowL / 2, -harrowL / 2); // center pathForTurn.rLineTo(-harrowL / 2, harrowL / 2); pathForTurn.rLineTo(hpartArrowL, 0); pathForTurn.rLineTo(0, h); } else if (TurnType.TR.equals(turnType.getValue()) || TurnType.TL.equals(turnType.getValue())) { int b = TurnType.TR.equals(turnType.getValue()) ? 1 : -1; int h = 36; float quadShiftX = 22; float quadShiftY = 22; pathForTurn.rMoveTo(-b * 8, 0); pathForTurn.rLineTo(0, -h); pathForTurn.rQuadTo(0, -quadShiftY, b * quadShiftX, -quadShiftY); pathForTurn.rLineTo(0, hpartArrowL); pathForTurn.rLineTo(b * harrowL / 2, -harrowL / 2); // center pathForTurn.rLineTo(-b * harrowL / 2, -harrowL / 2); pathForTurn.rLineTo(0, hpartArrowL); pathForTurn.rQuadTo(-b * (quadShiftX + w), 0, -b * (quadShiftX + w), quadShiftY + w); pathForTurn.rLineTo(0, h); } else if (TurnType.TSLR.equals(turnType.getValue()) || TurnType.TSLL.equals(turnType.getValue())) { int b = TurnType.TSLR.equals(turnType.getValue()) ? 1 : -1; int h = 40; int quadShiftY = 22; float quadShiftX = (float) (quadShiftY / (1 + Math.sqrt(2))); float nQuadShiftX = (sarrowL - 2 * spartArrowL) - quadShiftX - w; float nQuadShifty = quadShiftY + (sarrowL - 2 * spartArrowL); pathForTurn.rMoveTo(-b * 4, 0); pathForTurn.rLineTo(0, -h /* + partArrowL */); pathForTurn.rQuadTo( 0, -quadShiftY + quadShiftX /*- partArrowL*/, b * quadShiftX, -quadShiftY /*- partArrowL*/); pathForTurn.rLineTo(b * spartArrowL, spartArrowL); pathForTurn.rLineTo(0, -sarrowL); // center pathForTurn.rLineTo(-b * sarrowL, 0); pathForTurn.rLineTo(b * spartArrowL, spartArrowL); pathForTurn.rQuadTo(b * nQuadShiftX, -nQuadShiftX, b * nQuadShiftX, nQuadShifty); pathForTurn.rLineTo(0, h); } else if (TurnType.TSHR.equals(turnType.getValue()) || TurnType.TSHL.equals(turnType.getValue())) { int b = TurnType.TSHR.equals(turnType.getValue()) ? 1 : -1; int h = 45; float quadShiftX = 22; float quadShiftY = -(float) (quadShiftX / (1 + Math.sqrt(2))); float nQuadShiftX = -(sarrowL - 2 * spartArrowL) - quadShiftX - w; float nQuadShiftY = -quadShiftY + (sarrowL - 2 * spartArrowL); pathForTurn.rMoveTo(-b * 8, 0); pathForTurn.rLineTo(0, -h); pathForTurn.rQuadTo(0, -(quadShiftX - quadShiftY), b * quadShiftX, quadShiftY); pathForTurn.rLineTo(-b * spartArrowL, spartArrowL); pathForTurn.rLineTo(b * sarrowL, 0); // center pathForTurn.rLineTo(0, -sarrowL); pathForTurn.rLineTo(-b * spartArrowL, spartArrowL); pathForTurn.rCubicTo( b * nQuadShiftX / 2, nQuadShiftX / 2, b * nQuadShiftX, nQuadShiftX / 2, b * nQuadShiftX, nQuadShiftY); pathForTurn.rLineTo(0, h); } else if (TurnType.TU.equals(turnType.getValue())) { int h = 54; float quadShiftX = 13; float quadShiftY = 13; pathForTurn.rMoveTo(28, 0); pathForTurn.rLineTo(0, -h); pathForTurn.rQuadTo(0, -(quadShiftY + w), -(quadShiftX + w), -(quadShiftY + w)); pathForTurn.rQuadTo(-(quadShiftX + w), 0, -(quadShiftX + w), (quadShiftY + w)); pathForTurn.rLineTo(-hpartArrowL, 0); pathForTurn.rLineTo(harrowL / 2, harrowL / 2); // center pathForTurn.rLineTo(harrowL / 2, -harrowL / 2); pathForTurn.rLineTo(-hpartArrowL, 0); pathForTurn.rQuadTo(0, -quadShiftX, quadShiftX, -quadShiftY); pathForTurn.rQuadTo(quadShiftX, 0, quadShiftX, quadShiftY); pathForTurn.rLineTo(0, h); } else if (turnType != null && turnType.isRoundAbout()) { float t = turnType.getTurnAngle(); if (t >= 170 && t < 220) { t = 220; } else if (t > 160 && t < 170) { t = 160; } float sweepAngle = (t - 360) - 180; if (sweepAngle < -360) { sweepAngle += 360; } float r1 = 32f; float r2 = 24f; float angleToRot = 0.3f; pathForTurn.moveTo(48, 48 + r1 + 8); pathForTurn.lineTo(48, 48 + r1); RectF r = new RectF(48 - r1, 48 - r1, 48 + r1, 48 + r1); pathForTurn.arcTo(r, 90, sweepAngle); float angleRad = (float) ((180 + sweepAngle) * Math.PI / 180f); pathForTurn.lineTo( 48 + (r1 + 4) * FloatMath.sin(angleRad), 48 - (r1 + 4) * FloatMath.cos(angleRad)); pathForTurn.lineTo( 48 + (r1 + 6) * FloatMath.sin(angleRad + angleToRot / 2), 48 - (r1 + 6) * FloatMath.cos(angleRad + angleToRot / 2)); pathForTurn.lineTo( 48 + (r1 + 12) * FloatMath.sin(angleRad - angleToRot / 2), 48 - (r1 + 12) * FloatMath.cos(angleRad - angleToRot / 2)); pathForTurn.lineTo( 48 + (r1 + 6) * FloatMath.sin(angleRad - 3 * angleToRot / 2), 48 - (r1 + 6) * FloatMath.cos(angleRad - 3 * angleToRot / 2)); pathForTurn.lineTo( 48 + (r1 + 4) * FloatMath.sin(angleRad - angleToRot), 48 - (r1 + 4) * FloatMath.cos(angleRad - angleToRot)); pathForTurn.lineTo( 48 + r2 * FloatMath.sin(angleRad - angleToRot), 48 - r2 * FloatMath.cos(angleRad - angleToRot)); r.set(48 - r2, 48 - r2, 48 + r2, 48 + r2); pathForTurn.arcTo(r, 360 + sweepAngle + 90, -sweepAngle); pathForTurn.lineTo(40, 48 + r2); pathForTurn.lineTo(40, 48 + r1 + 8); pathForTurn.close(); } pathForTurn.close(); if (transform != null) { pathForTurn.transform(transform); } }
/** * transform a path with all the given matrices VERY IMPORTANT: keep order to value-touch-offset * * @param path */ public void pathValueToPixel(Path path) { path.transform(mMatrixValueToPx); path.transform(mViewPortHandler.getMatrixTouch()); path.transform(mMatrixOffset); }