/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.react.views.art; import javax.annotation.Nullable; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Typeface; import android.text.TextUtils; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.annotations.ReactProp; /** * Shadow node for virtual ARTText view */ public class ARTTextShadowNode extends ARTShapeShadowNode { private static final String PROP_LINES = "lines"; private static final String PROP_FONT = "font"; private static final String PROP_FONT_FAMILY = "fontFamily"; private static final String PROP_FONT_SIZE = "fontSize"; private static final String PROP_FONT_STYLE = "fontStyle"; private static final String PROP_FONT_WEIGHT = "fontWeight"; private static final int DEFAULT_FONT_SIZE = 12; private static final int TEXT_ALIGNMENT_CENTER = 2; private static final int TEXT_ALIGNMENT_LEFT = 0; private static final int TEXT_ALIGNMENT_RIGHT = 1; private @Nullable ReadableMap mFrame; private int mTextAlignment = TEXT_ALIGNMENT_LEFT; @ReactProp(name = "frame") public void setFrame(@Nullable ReadableMap frame) { mFrame = frame; } @ReactProp(name = "alignment", defaultInt = TEXT_ALIGNMENT_LEFT) public void setAlignment(int alignment) { mTextAlignment = alignment; } @Override public void draw(Canvas canvas, Paint paint, float opacity) { if (mFrame == null) { return; } opacity *= mOpacity; if (opacity <= MIN_OPACITY_FOR_DRAW) { return; } if (!mFrame.hasKey(PROP_LINES)) { return; } ReadableArray linesProp = mFrame.getArray(PROP_LINES); if (linesProp == null || linesProp.size() == 0) { return; } // only set up the canvas if we have something to draw saveAndSetupCanvas(canvas); String[] lines = new String[linesProp.size()]; for (int i = 0; i < lines.length; i++) { lines[i] = linesProp.getString(i); } String text = TextUtils.join("\n", lines); if (setupStrokePaint(paint, opacity)) { applyTextPropertiesToPaint(paint); if (mPath == null) { canvas.drawText(text, 0, -paint.ascent(), paint); } else { canvas.drawTextOnPath(text, mPath, 0, 0, paint); } } if (setupFillPaint(paint, opacity)) { applyTextPropertiesToPaint(paint); if (mPath == null) { canvas.drawText(text, 0, -paint.ascent(), paint); } else { canvas.drawTextOnPath(text, mPath, 0, 0, paint); } } restoreCanvas(canvas); markUpdateSeen(); } private void applyTextPropertiesToPaint(Paint paint) { int alignment = mTextAlignment; switch (alignment) { case TEXT_ALIGNMENT_LEFT: paint.setTextAlign(Paint.Align.LEFT); break; case TEXT_ALIGNMENT_RIGHT: paint.setTextAlign(Paint.Align.RIGHT); break; case TEXT_ALIGNMENT_CENTER: paint.setTextAlign(Paint.Align.CENTER); break; } if (mFrame != null) { if (mFrame.hasKey(PROP_FONT)) { ReadableMap font = mFrame.getMap(PROP_FONT); if (font != null) { float fontSize = DEFAULT_FONT_SIZE; if (font.hasKey(PROP_FONT_SIZE)) { fontSize = (float) font.getDouble(PROP_FONT_SIZE); } paint.setTextSize(fontSize * mScale); boolean isBold = font.hasKey(PROP_FONT_WEIGHT) && "bold".equals(font.getString(PROP_FONT_WEIGHT)); boolean isItalic = font.hasKey(PROP_FONT_STYLE) && "italic".equals(font.getString(PROP_FONT_STYLE)); int fontStyle; if (isBold && isItalic) { fontStyle = Typeface.BOLD_ITALIC; } else if (isBold) { fontStyle = Typeface.BOLD; } else if (isItalic) { fontStyle = Typeface.ITALIC; } else { fontStyle = Typeface.NORMAL; } // NB: if the font family is null / unsupported, the default one will be used paint.setTypeface(Typeface.create(font.getString(PROP_FONT_FAMILY), fontStyle)); } } } } }