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); }
public boolean onTouch(View view, MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: path.moveTo(x, y); return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_MOVE: l = x; r = x; t = y; b = y; for (int i = 0; i < event.getHistorySize(); i++) { float newX = event.getHistoricalX(i); float newY = event.getHistoricalY(i); path.lineTo(newX, newY); l = newX < l ? newX : l; t = newY < t ? newY : t; r = newX > r ? newX : r; b = newY > b ? newY : b; } rect.set(l, t, r, b); Log.d("TAG", rect.toShortString()); invalidate( (int) rect.left - 5, (int) rect.top - 5, (int) rect.right + 5, (int) rect.bottom + 5); break; default: } return super.onTouchEvent(event); }
/** * Drawing src bitmap to dest bitmap with rounded corners * * @param src source bitmap * @param dest destination bitmap * @param radius radius in destination bitmap scale * @param clearColor clear color */ public static void drawRoundedCorners(Bitmap src, Bitmap dest, int radius, int clearColor) { clearBitmap(dest, clearColor); Canvas canvas = new Canvas(dest); Rect sourceRect = WorkCache.RECT1.get(); Rect destRect = WorkCache.RECT2.get(); sourceRect.set(0, 0, src.getWidth(), src.getHeight()); destRect.set(0, 0, dest.getWidth(), dest.getHeight()); RectF roundRect = WorkCache.RECTF1.get(); roundRect.set(0, 0, dest.getWidth(), dest.getHeight()); Paint paint = WorkCache.PAINT.get(); paint.reset(); paint.setStyle(Paint.Style.FILL); paint.setColor(Color.RED); paint.setAntiAlias(true); canvas.drawRoundRect(roundRect, radius, radius, paint); paint.reset(); paint.setFilterBitmap(true); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(src, sourceRect, destRect, paint); canvas.setBitmap(null); }
@Override public void onDraw(Canvas canvas) { int margeLeft, margeRight, margeTop, margeBot, line, calcLine, part; if (canvas.getWidth() > canvas.getHeight()) { ref = (int) (canvas.getHeight() * 0.85); margin = (int) (canvas.getHeight() * 0.15); } else { ref = (int) (canvas.getWidth() * 0.85); margin = (int) (canvas.getWidth() * 0.15); } part = ref / NB_SQUARE_PAR_LINE; line = -1; int size = (int) Math.pow(NB_SQUARE_PAR_LINE, 2); for (int i = 0; i < size; i++) { ISquare square = chessboard.get(i); calcLine = (i - i % NB_SQUARE_PAR_LINE) / NB_SQUARE_PAR_LINE; margeTop = calcLine * part + margin / 2; if (calcLine != line) { line = calcLine; margeLeft = margin / 2; } else { margeLeft = margin / 2 + part * (i % NB_SQUARE_PAR_LINE); } margeBot = margeTop + part; margeRight = margeLeft + part; if ((line + i) % 2 == 1) { paintSquare.setColor(Color.parseColor("#a7823d")); } else { paintSquare.setColor(Color.parseColor("#e6e6ff")); } Rect rect = new Rect(margeLeft, margeTop, margeRight, margeBot); canvas.drawRect(rect, paintSquare); int status = square.getStatus(); if (status != ISquare.STATUS_DEFAULT) { int border_margin = (int) (part * 0.08); int inner_margin; switch (status) { case (ISquare.STATUS_SELECTED): paintStatus.setColor(Color.parseColor("#0034E1")); // "#FFA200")); paintStatus.setStyle(Paint.Style.STROKE); paintStatus.setStrokeWidth(border_margin); inner_margin = border_margin / 2; rectF.set( margeLeft + inner_margin, margeTop + inner_margin, margeRight - inner_margin, margeBot - inner_margin); canvas.drawRect(rectF, paintStatus); break; case (ISquare.STATUS_TARGETABLE): paintStatus.setColor(Color.parseColor("#D23939")); paintStatus.setStyle(Paint.Style.FILL); paintStatus.setStrokeWidth(0); inner_margin = (int) (border_margin / 1.5); rectF.set( margeLeft + inner_margin, margeTop + inner_margin, margeRight - inner_margin, margeBot - inner_margin); canvas.drawRect(rectF, paintStatus); break; case (ISquare.STATUS_MOVE): paintStatus.setColor(Color.parseColor("#3899D1")); paintStatus.setStyle(Paint.Style.FILL); paintStatus.setStrokeWidth(0); inner_margin = (int) (border_margin / 1.5); rectF.set( margeLeft + inner_margin, margeTop + inner_margin, margeRight - inner_margin, margeBot - inner_margin); canvas.drawRect(rectF, paintStatus); break; } } if (!square.isEmpty()) { IPiece piece = square.getPiece(); int marginDrawable = (int) (part * 0.2); RelativeLayout myLayout = (RelativeLayout) this.getParent(); int width = (margeRight - marginDrawable) - (margeLeft + marginDrawable); int height = (margeBot - marginDrawable) - (margeTop + marginDrawable); int left = margeLeft + marginDrawable; int top = margeTop + marginDrawable; piece.setImage(getContext(), myLayout, width, height, left, top); } } }
@Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { // Reset paint opacity paint.setAlpha(255); // Ignore everything but rectangles in bounds mode if (boundsMode) { if (localName.equals("rect")) { Float x = getFloatAttr("x", atts); if (x == null) { x = 0f; } Float y = getFloatAttr("y", atts); if (y == null) { y = 0f; } Float width = getFloatAttr("width", atts); Float height = getFloatAttr("height", atts); bounds = new RectF(x, y, x + width, y + height); } return; } if (localName.equals("svg")) { int width = (int) Math.ceil(getFloatAttr("width", atts)); int height = (int) Math.ceil(getFloatAttr("height", atts)); canvas = picture.beginRecording(width, height); } else if (localName.equals("defs")) { // Ignore } else if (localName.equals("linearGradient")) { gradient = doGradient(true, atts); } else if (localName.equals("radialGradient")) { gradient = doGradient(false, atts); } else if (localName.equals("stop")) { if (gradient != null) { float offset = getFloatAttr("offset", atts); String styles = getStringAttr("style", atts); StyleSet styleSet = new StyleSet(styles); String colorStyle = styleSet.getStyle("stop-color"); int color = Color.BLACK; if (colorStyle != null) { if (colorStyle.startsWith("#")) { color = Integer.parseInt(colorStyle.substring(1), 16); } else { color = Integer.parseInt(colorStyle, 16); } } String opacityStyle = styleSet.getStyle("stop-opacity"); if (opacityStyle != null) { float alpha = Float.parseFloat(opacityStyle); int alphaInt = Math.round(255 * alpha); color |= (alphaInt << 24); } else { color |= 0xFF000000; } gradient.positions.add(offset); gradient.colors.add(color); } } else if (localName.equals("g")) { // Check to see if this is the "bounds" layer if ("bounds".equalsIgnoreCase(getStringAttr("id", atts))) { boundsMode = true; } if (hidden) { hiddenLevel++; // Util.debug("Hidden up: " + hiddenLevel); } // Go in to hidden mode if display is "none" if ("none".equals(getStringAttr("display", atts))) { if (!hidden) { hidden = true; hiddenLevel = 1; // Util.debug("Hidden up: " + hiddenLevel); } } pushTransform(atts); } else if (!hidden && localName.equals("rect")) { Float x = getFloatAttr("x", atts); if (x == null) { x = 0f; } Float y = getFloatAttr("y", atts); if (y == null) { y = 0f; } Float width = getFloatAttr("width", atts); Float height = getFloatAttr("height", atts); Float rx = getFloatAttr("rx", atts); Float ry = getFloatAttr("ry", atts); if (rx == null) { if (ry == null) rx = ry = 0f; else rx = ry; } else { if (ry == null) ry = rx; } if (rx > width / 2) rx = width * 0.5f; if (ry > height / 2) ry = height * 0.5f; pushTransform(atts); Properties props = new Properties(atts); if (doFill(props, gradientMap)) { doLimits(x, y, width, height); if (rx > 0 && ry > 0) canvas.drawRoundRect(new RectF(x, y, x + width, y + height), rx, ry, paint); else canvas.drawRect(x, y, x + width, y + height, paint); } if (doStroke(props, gradientMap)) { if (rx > 0 && ry > 0) canvas.drawRoundRect(new RectF(x, y, x + width, y + height), rx, ry, paint); else canvas.drawRect(x, y, x + width, y + height, paint); } popTransform(); } else if (!hidden && localName.equals("line")) { Float x1 = getFloatAttr("x1", atts); Float x2 = getFloatAttr("x2", atts); Float y1 = getFloatAttr("y1", atts); Float y2 = getFloatAttr("y2", atts); Properties props = new Properties(atts); if (doStroke(props, gradientMap)) { pushTransform(atts); doLimits(x1, y1); doLimits(x2, y2); canvas.drawLine(x1, y1, x2, y2, paint); popTransform(); } } else if (!hidden && localName.equals("circle")) { Float centerX = getFloatAttr("cx", atts); Float centerY = getFloatAttr("cy", atts); Float radius = getFloatAttr("r", atts); if (centerX != null && centerY != null && radius != null) { pushTransform(atts); Properties props = new Properties(atts); if (doFill(props, gradientMap)) { doLimits(centerX - radius, centerY - radius); doLimits(centerX + radius, centerY + radius); canvas.drawCircle(centerX, centerY, radius, paint); } if (doStroke(props, gradientMap)) { canvas.drawCircle(centerX, centerY, radius, paint); } popTransform(); } } else if (!hidden && localName.equals("ellipse")) { Float centerX = getFloatAttr("cx", atts); Float centerY = getFloatAttr("cy", atts); Float radiusX = getFloatAttr("rx", atts); Float radiusY = getFloatAttr("ry", atts); if (centerX != null && centerY != null && radiusX != null && radiusY != null) { pushTransform(atts); Properties props = new Properties(atts); rect.set(centerX - radiusX, centerY - radiusY, centerX + radiusX, centerY + radiusY); if (doFill(props, gradientMap)) { doLimits(centerX - radiusX, centerY - radiusY); doLimits(centerX + radiusX, centerY + radiusY); canvas.drawOval(rect, paint); } if (doStroke(props, gradientMap)) { canvas.drawOval(rect, paint); } popTransform(); } } else if (!hidden && (localName.equals("polygon") || localName.equals("polyline"))) { NumberParse numbers = getNumberParseAttr("points", atts); if (numbers != null) { Path p = new Path(); ArrayList<Float> points = numbers.numbers; if (points.size() > 1) { pushTransform(atts); Properties props = new Properties(atts); p.moveTo(points.get(0), points.get(1)); for (int i = 2; i < points.size(); i += 2) { float x = points.get(i); float y = points.get(i + 1); p.lineTo(x, y); } // Don't close a polyline if (localName.equals("polygon")) { p.close(); } if (doFill(props, gradientMap)) { doLimits(p); canvas.drawPath(p, paint); } if (doStroke(props, gradientMap)) { canvas.drawPath(p, paint); } popTransform(); } } } else if (!hidden && localName.equals("path")) { Path p = doPath(getStringAttr("d", atts)); pushTransform(atts); Properties props = new Properties(atts); if (doFill(props, gradientMap)) { doLimits(p); canvas.drawPath(p, paint); } if (doStroke(props, gradientMap)) { canvas.drawPath(p, paint); } popTransform(); } else if (!hidden) { // Log.d(TAG, "UNRECOGNIZED SVG COMMAND: " + localName); } }
public void build(DialogWireframe description, int w, int h, TelegramApplication application) { layoutH = h; layoutW = w; if (description.getPeerType() == PeerType.PEER_USER) { if (description.getPeerId() == 333000) { isHighlighted = false; } else { User user = description.getDialogUser(); isHighlighted = user.getLinkType() == LinkType.FOREIGN; } isGroup = false; isEncrypted = false; } else if (description.getPeerType() == PeerType.PEER_CHAT) { isHighlighted = false; isGroup = true; isEncrypted = false; } else if (description.getPeerType() == PeerType.PEER_USER_ENCRYPTED) { isHighlighted = false; isGroup = false; isEncrypted = true; } isBodyHighlighted = description.getContentType() != ContentType.MESSAGE_TEXT; if (description.getUnreadCount() != 0 && !description.isMine()) { isUnreadIn = true; } else { isUnreadIn = false; } time = org.telegram.android.ui.TextUtil.formatDate(description.getDate(), application); isRtl = application.isRTL(); if (IS_LARGE) { layoutAvatarWidth = px(64); layoutPadding = application.getResources().getDimensionPixelSize(R.dimen.dialogs_padding); layoutBodyPadding = layoutAvatarWidth + layoutPadding + px(12); layoutAvatarTop = px(8); layoutTitleTop = px(34); layoutMainTop = px(60); layoutTimeTop = px(34); layoutMarkTop = px(44); layoutMarkBottom = layoutMarkTop + px(22); layoutMarkTextTop = layoutMarkTop + px(18); } else { layoutAvatarWidth = px(54); layoutPadding = application.getResources().getDimensionPixelSize(R.dimen.dialogs_padding); layoutBodyPadding = layoutAvatarWidth + layoutPadding + px(12); layoutAvatarTop = px(8); layoutTitleTop = px(30); layoutMainTop = px(54); layoutTimeTop = px(30); layoutMarkTop = px(38); layoutMarkBottom = layoutMarkTop + px(22); layoutMarkTextTop = layoutMarkTop + px(18); } layoutMainContentTop = (int) (layoutMainTop + bodyPaint.getFontMetrics().ascent); layoutTitleLayoutTop = (int) (layoutTitleTop + titlePaint.getFontMetrics().ascent); layoutStateTop = layoutTimeTop - px(10); layoutClockTop = layoutTimeTop - px(12); layoutEncryptedTop = layoutTimeTop - px(14); if (isRtl) { layoutAvatarLeft = w - layoutPadding - layoutAvatarWidth; } else { layoutAvatarLeft = layoutPadding; } int timeWidth = (int) unreadClockPaint.measureText(time); if (isRtl) { layoutTimeLeft = layoutPadding; layoutStateLeftDouble = layoutPadding + timeWidth + px(2); layoutStateLeft = layoutStateLeftDouble + px(6); layoutClockLeft = layoutPadding + timeWidth + px(2); } else { layoutTimeLeft = w - layoutPadding - timeWidth; layoutClockLeft = w - layoutPadding - timeWidth - px(14); layoutStateLeft = w - layoutPadding - timeWidth - px(16); layoutStateLeftDouble = w - layoutPadding - timeWidth - px(6 + 16); } layoutMarkRadius = px(2); if (description.isErrorState() || (description.getMessageState() == MessageState.FAILURE && description.isMine())) { layoutMarkWidth = px(22); if (isRtl) { layoutMarkLeft = layoutPadding; // getMeasuredWidth() - layoutMarkWidth - getPx(80); } else { layoutMarkLeft = w - layoutMarkWidth - layoutPadding; } } else { if (description.getUnreadCount() > 0) { if (description.getUnreadCount() >= 1000) { unreadCountText = I18nUtil.getInstance().correctFormatNumber(description.getUnreadCount() / 1000) + "K"; } else { unreadCountText = I18nUtil.getInstance().correctFormatNumber(description.getUnreadCount()); } int width = (int) counterTitlePaint.measureText(unreadCountText); Rect r = new Rect(); counterTitlePaint.getTextBounds(unreadCountText, 0, unreadCountText.length(), r); layoutMarkTextTop = layoutMarkTop + (layoutMarkBottom - layoutMarkTop + r.top) / 2 - r.top; if (width < px(22 - 14)) { layoutMarkWidth = px(22); } else { layoutMarkWidth = px(14) + width; } layoutMarkTextLeft = (layoutMarkWidth - width) / 2; if (isRtl) { layoutMarkLeft = layoutPadding; // getMeasuredWidth() - layoutMarkWidth - getPx(80); } else { layoutMarkLeft = w - layoutMarkWidth - layoutPadding; } } else { layoutMarkLeft = 0; layoutMarkWidth = 0; } } layoutMarkRect.set( layoutMarkLeft, layoutMarkTop, layoutMarkLeft + layoutMarkWidth, layoutMarkBottom); if (description.getPeerType() == PeerType.PEER_USER_ENCRYPTED) { if (isRtl) { if (description.isMine()) { layoutTitleLeft = timeWidth + px(16) + px(16); } else { layoutTitleLeft = timeWidth + px(12); } layoutTitleWidth = w - layoutTitleLeft - layoutBodyPadding - px(14) - px(6); layoutEncryptedLeft = w - layoutBodyPadding - px(12); } else { layoutTitleLeft = layoutBodyPadding + px(16); if (description.isMine()) { layoutTitleWidth = w - layoutTitleLeft - timeWidth - px(24); } else { layoutTitleWidth = w - layoutTitleLeft - timeWidth - px(12); } layoutEncryptedLeft = layoutBodyPadding + px(2); } } else { if (isRtl) { if (description.isMine()) { layoutTitleLeft = timeWidth + px(16) + px(16); } else { layoutTitleLeft = timeWidth + px(12); } layoutTitleWidth = w - layoutTitleLeft - layoutBodyPadding; } else { layoutTitleLeft = layoutBodyPadding; if (description.isMine()) { layoutTitleWidth = w - layoutTitleLeft - timeWidth - px(24) - px(12); } else { layoutTitleWidth = w - layoutTitleLeft - timeWidth - px(12); } } } layoutMainWidth = w - layoutBodyPadding - layoutPadding; if (isRtl) { layoutMainLeft = w - layoutMainWidth - layoutBodyPadding; if (layoutMarkWidth != 0) { layoutMainLeft += layoutMarkWidth + px(8); layoutMainWidth -= layoutMarkWidth + px(8); } } else { layoutMainLeft = layoutBodyPadding; if (layoutMarkWidth != 0) { layoutMainWidth -= layoutMarkWidth + px(8); } } avatarRect.set( layoutAvatarLeft, layoutAvatarTop, layoutAvatarLeft + layoutAvatarWidth, layoutAvatarTop + layoutAvatarWidth); // Building text layouts { String message = description.getMessage(); if (message.length() > 150) { message = message.substring(0, 150) + "..."; } message = message.replace("\n", " "); TextPaint bodyTextPaint; if (isBodyHighlighted) { bodyTextPaint = bodyHighlightPaint; } else { if (HIGHLIGHT_UNDEAD) { if (isUnreadIn) { bodyTextPaint = bodyUnreadPaint; } else { bodyTextPaint = bodyPaint; } } else { bodyTextPaint = bodyPaint; } } int nameLength = 0; if (description.getContentType() != ContentType.MESSAGE_SYSTEM) { if (description.isMine()) { String name = application.getResources().getString(R.string.st_dialog_you); nameLength = BidiFormatter.getInstance().unicodeWrap(name).length(); message = BidiFormatter.getInstance().unicodeWrap(name) + ": " + BidiFormatter.getInstance().unicodeWrap(message); } else { if (isGroup) { User user = description.getSender(); nameLength = BidiFormatter.getInstance().unicodeWrap(user.getFirstName()).length(); message = BidiFormatter.getInstance().unicodeWrap(user.getFirstName().replace("\n", " ")) + ": " + BidiFormatter.getInstance().unicodeWrap(message); } } } String preSequence = TextUtils.ellipsize(message, bodyTextPaint, layoutMainWidth, TextUtils.TruncateAt.END) .toString(); // Spannable sequence = // application.getEmojiProcessor().processEmojiCutMutable(preSequence, // EmojiProcessor.CONFIGURATION_DIALOGS); // if (nameLength != 0) { // sequence.setSpan(new ForegroundColorSpan(HIGHLIGHT_COLOR), 0, // Math.min(nameLength, sequence.length()), Spanned.SPAN_EXCLUSIVE_INCLUSIVE); // } // CharSequence resSequence = TextUtils.ellipsize(sequence, bodyTextPaint, // layoutMainWidth, TextUtils.TruncateAt.END); // bodyLayout = new StaticLayout(resSequence, bodyTextPaint, layoutMainWidth, // Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); // bodyString = null; Spannable sequence = application .getEmojiProcessor() .processEmojiCutMutable(preSequence, EmojiProcessor.CONFIGURATION_DIALOGS); if (nameLength != 0) { sequence.setSpan( new ForegroundColorSpan(HIGHLIGHT_COLOR), 0, Math.min(nameLength, sequence.length()), Spanned.SPAN_EXCLUSIVE_INCLUSIVE); } CharSequence resSequence = TextUtils.ellipsize(sequence, bodyTextPaint, layoutMainWidth, TextUtils.TruncateAt.END); bodyLayout = new StaticLayout( resSequence, bodyTextPaint, layoutMainWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); bodyString = null; // if (EmojiProcessor.containsEmoji(message)) { // Spannable sequence = // application.getEmojiProcessor().processEmojiCutMutable(preSequence, // EmojiProcessor.CONFIGURATION_DIALOGS); // if (nameLength != 0) { // sequence.setSpan(new ForegroundColorSpan(HIGHLIGHT_COLOR), 0, // Math.min(nameLength, sequence.length()), Spanned.SPAN_EXCLUSIVE_INCLUSIVE); // } // // CharSequence resSequence = TextUtils.ellipsize(sequence, // bodyTextPaint, layoutMainWidth, TextUtils.TruncateAt.END); // bodyLayout = new StaticLayout(resSequence, bodyTextPaint, // layoutMainWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); // bodyString = null; // } else { // bodyString = preSequence; // bodyLayout = null; // } } // Title { String title = description.getDialogTitle(); if (title.length() > 150) { title = title.substring(150) + "..."; } title = title.replace("\n", " "); TextPaint paint = isEncrypted ? titleEncryptedPaint : (isHighlighted ? titleHighlightPaint : titlePaint); // Spannable preSequence = // application.getEmojiProcessor().processEmojiCutMutable(title, // EmojiProcessor.CONFIGURATION_DIALOGS); // CharSequence sequence = TextUtils.ellipsize(preSequence, paint, // layoutTitleWidth, TextUtils.TruncateAt.END); // titleLayout = new StaticLayout(sequence, paint, layoutTitleWidth, // Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); // titleString = null; if (EmojiProcessor.containsEmoji(title)) { Spannable preSequence = application .getEmojiProcessor() .processEmojiCutMutable(title, EmojiProcessor.CONFIGURATION_DIALOGS); CharSequence sequence = TextUtils.ellipsize(preSequence, paint, layoutTitleWidth, TextUtils.TruncateAt.END); titleLayout = new StaticLayout( sequence, paint, layoutTitleWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); titleString = null; } else { titleString = TextUtils.ellipsize(title, paint, layoutTitleWidth, TextUtils.TruncateAt.END) .toString(); titleLayout = null; } } // Placeholder placeHolderName = description.getDialogName(); placeHolderColor = Placeholders.getBgColor(description.getPeerId()); if (placeHolderName.length() > 0) { usePlaceholder = true; placeholderLeft = layoutAvatarLeft + layoutAvatarWidth / 2; Rect rect = new Rect(); placeholderTextPaint.getTextBounds(placeHolderName, 0, placeHolderName.length(), rect); placeholderTop = layoutAvatarTop + (layoutAvatarWidth / 2 + ((rect.bottom - rect.top) / 2)); } else { usePlaceholder = false; } }