use of com.mta.tehreer.sfnt.WritingDirection in project Tehreer-Android by mta452.
the class ShapeResolver method fillRuns.
public static void fillRuns(@NonNull String text, @NonNull Spanned spanned, @NonNull List<Object> defaultSpans, @NonNull byte[] breaks, @NonNull List<BidiParagraph> paragraphs, @NonNull List<TextRun> runs) {
BidiAlgorithm bidiAlgorithm = null;
ShapingEngine shapingEngine = null;
try {
bidiAlgorithm = new BidiAlgorithm(text);
shapingEngine = new ShapingEngine();
ScriptClassifier scriptClassifier = new ScriptClassifier(text);
ShapingRunLocator locator = new ShapingRunLocator(spanned, defaultSpans);
BaseDirection baseDirection = BaseDirection.DEFAULT_LEFT_TO_RIGHT;
byte forwardType = BreakResolver.typeMode(BreakResolver.PARAGRAPH, true);
byte backwardType = BreakResolver.typeMode(BreakResolver.PARAGRAPH, false);
int paragraphStart = 0;
int suggestedEnd = text.length();
while (paragraphStart != suggestedEnd) {
BidiParagraph paragraph = bidiAlgorithm.createParagraph(paragraphStart, suggestedEnd, baseDirection);
for (BidiRun bidiRun : paragraph.getLogicalRuns()) {
for (ScriptRun scriptRun : scriptClassifier.getScriptRuns(bidiRun.charStart, bidiRun.charEnd)) {
int scriptTag = Script.getOpenTypeTag(scriptRun.script);
WritingDirection writingDirection = ShapingEngine.getScriptDirection(scriptTag);
boolean isOddLevel = ((bidiRun.embeddingLevel & 1) == 1);
boolean isBackward = (isOddLevel && writingDirection == WritingDirection.LEFT_TO_RIGHT) | (!isOddLevel && writingDirection == WritingDirection.RIGHT_TO_LEFT);
ShapingOrder shapingOrder = (isBackward ? ShapingOrder.BACKWARD : ShapingOrder.FORWARD);
locator.reset(scriptRun.charStart, scriptRun.charEnd);
shapingEngine.setScriptTag(scriptTag);
shapingEngine.setWritingDirection(writingDirection);
shapingEngine.setShapingOrder(shapingOrder);
resolveTypefaces(text, spanned, runs, locator, shapingEngine, bidiRun.embeddingLevel);
}
}
paragraphs.add(paragraph);
breaks[paragraph.getCharStart()] |= backwardType;
breaks[paragraph.getCharEnd() - 1] |= forwardType;
paragraphStart = paragraph.getCharEnd();
}
} finally {
if (shapingEngine != null) {
shapingEngine.dispose();
}
if (bidiAlgorithm != null) {
bidiAlgorithm.dispose();
}
}
}
use of com.mta.tehreer.sfnt.WritingDirection in project Tehreer-Android by mta452.
the class Typesetter method resolveBidi.
private void resolveBidi() {
// TODO: Analyze script runs.
BidiAlgorithm bidiAlgorithm = null;
ShapingEngine shapingEngine = null;
try {
bidiAlgorithm = new BidiAlgorithm(mText);
shapingEngine = new ShapingEngine();
BaseDirection baseDirection = BaseDirection.DEFAULT_LEFT_TO_RIGHT;
byte forwardType = specializeBreakType(BREAK_TYPE_PARAGRAPH, true);
byte backwardType = specializeBreakType(BREAK_TYPE_PARAGRAPH, false);
int paragraphStart = 0;
int suggestedEnd = mText.length();
while (paragraphStart != suggestedEnd) {
BidiParagraph paragraph = bidiAlgorithm.createParagraph(paragraphStart, suggestedEnd, baseDirection);
for (BidiRun bidiRun : paragraph.getLogicalRuns()) {
int scriptTag = SfntTag.make(bidiRun.isRightToLeft() ? "arab" : "latn");
WritingDirection writingDirection = ShapingEngine.getScriptDirection(scriptTag);
shapingEngine.setScriptTag(scriptTag);
shapingEngine.setWritingDirection(writingDirection);
resolveTypefaces(bidiRun.charStart, bidiRun.charEnd, bidiRun.embeddingLevel, shapingEngine);
}
mBidiParagraphs.add(paragraph);
mBreakRecord[paragraph.getCharStart()] |= backwardType;
mBreakRecord[paragraph.getCharEnd() - 1] |= forwardType;
paragraphStart = paragraph.getCharEnd();
}
} finally {
if (shapingEngine != null) {
shapingEngine.dispose();
}
if (bidiAlgorithm != null) {
bidiAlgorithm.dispose();
}
}
}
use of com.mta.tehreer.sfnt.WritingDirection in project Tehreer-Android by mta452.
the class ShapeResolver method resolveTypefaces.
private static void resolveTypefaces(@NonNull String text, @NonNull Spanned spanned, @NonNull List<TextRun> runs, @NonNull ShapingRunLocator locator, @NonNull ShapingEngine engine, byte bidiLevel) {
Paint paint = null;
Paint.FontMetricsInt metrics = null;
while (locator.moveNext()) {
int runStart = locator.getRunStart();
int runEnd = locator.getRunEnd();
Typeface typeface = locator.getTypeface();
checkArgument(typeface != null, "No typeface is specified for range [" + runStart + ", " + runEnd + ')');
float typeSize = locator.getTypeSize();
float sizeByEm = typeSize / typeface.getUnitsPerEm();
float ascent = typeface.getAscent() * sizeByEm;
float descent = typeface.getDescent() * sizeByEm;
float leading = typeface.getLeading() * sizeByEm;
ReplacementSpan replacement = locator.getReplacement();
TextRun textRun;
if (replacement == null) {
engine.setTypeface(typeface);
engine.setTypeSize(typeSize);
ShapingResult shapingResult = null;
try {
shapingResult = engine.shapeText(text, runStart, runEnd);
WritingDirection writingDirection = engine.getWritingDirection();
boolean isBackward = shapingResult.isBackward();
int[] glyphIds = shapingResult.getGlyphIds().toArray();
float[] offsets = shapingResult.getGlyphOffsets().toArray();
float[] advances = shapingResult.getGlyphAdvances().toArray();
int[] clusterMap = shapingResult.getClusterMap().toArray();
FloatList caretEdges = shapingResult.getCaretEdges(null);
float scaleX = locator.getScaleX();
if (Float.compare(scaleX, 1.0f) != 0) {
for (int i = 0; i < glyphIds.length; i++) {
offsets[i * 2] *= scaleX;
advances[i] *= scaleX;
}
}
float baselineShift = locator.getBaselineShift();
if (Float.compare(baselineShift, 0.0f) != 0) {
for (int i = 0; i < glyphIds.length; i++) {
offsets[(i * 2) + 1] += baselineShift;
}
}
textRun = new IntrinsicRun(runStart, runEnd, isBackward, bidiLevel, writingDirection, typeface, typeSize, ascent, descent, leading, glyphIds, offsets, advances, clusterMap, caretEdges);
} finally {
if (shapingResult != null) {
shapingResult.dispose();
}
}
} else {
if (paint == null) {
paint = new Paint();
}
if (metrics == null) {
metrics = new Paint.FontMetricsInt();
}
metrics.ascent = (int) -(ascent + 0.5f);
metrics.descent = (int) (descent + 0.5f);
metrics.leading = (int) (leading + 0.5f);
int extent = replacement.getSize(paint, spanned, runStart, runEnd, metrics);
int runLength = runEnd - runStart;
float[] caretEdges = new float[runLength + 1];
if ((bidiLevel & 1) == 0) {
caretEdges[runLength] = extent;
} else {
caretEdges[0] = extent;
}
textRun = new ReplacementRun(spanned, runStart, runEnd, bidiLevel, replacement, paint, typeface, typeSize, metrics.ascent, metrics.descent, metrics.leading, extent, FloatList.of(caretEdges));
}
runs.add(textRun);
}
}
use of com.mta.tehreer.sfnt.WritingDirection in project Tehreer-Android by mta452.
the class OpenTypeInfoActivity method onCreate.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_opentype_info);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
Intent intent = getIntent();
String typefaceName = intent.getStringExtra(TYPEFACE_NAME);
int typeSize = intent.getIntExtra(TYPE_SIZE, 0);
int scriptTag = intent.getIntExtra(SCRIPT_TAG, 0);
int languageTag = intent.getIntExtra(LANGUAGE_TAG, 0);
String sourceText = intent.getCharSequenceExtra(SOURCE_TEXT).toString();
WritingDirection writingDirection = ShapingEngine.getScriptDirection(scriptTag);
Typeface typeface = TypefaceManager.getTypefaceByName(typefaceName);
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
float displaySize = 18.0f * displayMetrics.scaledDensity;
float sizeScale = displaySize / typeSize;
Renderer renderer = new Renderer();
renderer.setTypeface(typeface);
renderer.setTypeSize(typeSize);
renderer.setScaleX(sizeScale);
renderer.setScaleY(sizeScale);
ShapingEngine shapingEngine = ShapingEngine.finalizable(new ShapingEngine());
shapingEngine.setTypeface(typeface);
shapingEngine.setTypeSize(typeSize);
shapingEngine.setScriptTag(scriptTag);
shapingEngine.setLanguageTag(languageTag);
shapingEngine.setWritingDirection(writingDirection);
ShapingResult shapingResult = ShapingResult.finalizable(shapingEngine.shapeText(sourceText, 0, sourceText.length()));
IntList clusterMap = shapingResult.getClusterMap();
int length = clusterMap.size();
int[] initials = new int[length + 1];
int cluster = -1;
int previous = -1;
for (int i = 0; i < length; i++) {
int value = clusterMap.get(i);
if (value != previous) {
initials[++cluster] = i;
}
previous = value;
}
initials[++cluster] = length;
ListView infoListView = findViewById(R.id.list_view_info);
infoListView.setAdapter(new ClusterAdapter(this, renderer, sourceText, shapingResult, IntList.of(initials).subList(0, cluster + 1)));
}
Aggregations