Search in sources :

Example 1 with WritingDirection

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();
        }
    }
}
Also used : ShapingEngine(com.mta.tehreer.sfnt.ShapingEngine) BidiRun(com.mta.tehreer.unicode.BidiRun) ScriptClassifier(com.mta.tehreer.unicode.ScriptClassifier) Paint(android.graphics.Paint) ShapingOrder(com.mta.tehreer.sfnt.ShapingOrder) BaseDirection(com.mta.tehreer.unicode.BaseDirection) ScriptRun(com.mta.tehreer.unicode.ScriptRun) BidiParagraph(com.mta.tehreer.unicode.BidiParagraph) WritingDirection(com.mta.tehreer.sfnt.WritingDirection) BidiAlgorithm(com.mta.tehreer.unicode.BidiAlgorithm)

Example 2 with WritingDirection

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();
        }
    }
}
Also used : ShapingEngine(com.mta.tehreer.sfnt.ShapingEngine) BaseDirection(com.mta.tehreer.unicode.BaseDirection) BidiRun(com.mta.tehreer.unicode.BidiRun) BidiParagraph(com.mta.tehreer.unicode.BidiParagraph) WritingDirection(com.mta.tehreer.sfnt.WritingDirection) BidiAlgorithm(com.mta.tehreer.unicode.BidiAlgorithm)

Example 3 with WritingDirection

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);
    }
}
Also used : Typeface(com.mta.tehreer.graphics.Typeface) Paint(android.graphics.Paint) ReplacementSpan(android.text.style.ReplacementSpan) ShapingResult(com.mta.tehreer.sfnt.ShapingResult) Paint(android.graphics.Paint) FloatList(com.mta.tehreer.collections.FloatList) WritingDirection(com.mta.tehreer.sfnt.WritingDirection)

Example 4 with WritingDirection

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)));
}
Also used : ShapingEngine(com.mta.tehreer.sfnt.ShapingEngine) Typeface(com.mta.tehreer.graphics.Typeface) Intent(android.content.Intent) SpannableString(android.text.SpannableString) DisplayMetrics(android.util.DisplayMetrics) ShapingResult(com.mta.tehreer.sfnt.ShapingResult) Paint(android.graphics.Paint) IntList(com.mta.tehreer.collections.IntList) ListView(android.widget.ListView) Renderer(com.mta.tehreer.graphics.Renderer) WritingDirection(com.mta.tehreer.sfnt.WritingDirection) ActionBar(androidx.appcompat.app.ActionBar)

Aggregations

WritingDirection (com.mta.tehreer.sfnt.WritingDirection)4 Paint (android.graphics.Paint)3 ShapingEngine (com.mta.tehreer.sfnt.ShapingEngine)3 Typeface (com.mta.tehreer.graphics.Typeface)2 ShapingResult (com.mta.tehreer.sfnt.ShapingResult)2 BaseDirection (com.mta.tehreer.unicode.BaseDirection)2 BidiAlgorithm (com.mta.tehreer.unicode.BidiAlgorithm)2 BidiParagraph (com.mta.tehreer.unicode.BidiParagraph)2 BidiRun (com.mta.tehreer.unicode.BidiRun)2 Intent (android.content.Intent)1 SpannableString (android.text.SpannableString)1 ReplacementSpan (android.text.style.ReplacementSpan)1 DisplayMetrics (android.util.DisplayMetrics)1 ListView (android.widget.ListView)1 ActionBar (androidx.appcompat.app.ActionBar)1 FloatList (com.mta.tehreer.collections.FloatList)1 IntList (com.mta.tehreer.collections.IntList)1 Renderer (com.mta.tehreer.graphics.Renderer)1 ShapingOrder (com.mta.tehreer.sfnt.ShapingOrder)1 ScriptClassifier (com.mta.tehreer.unicode.ScriptClassifier)1