<commit_before>/**
 * Copyright (c) 2015-present, Horcrux.
 * All rights reserved.
 *
 * This source code is licensed under the MIT-style license found in the
 * LICENSE file in the root directory of this source tree.
 */


package com.horcrux.svg;

import javax.annotation.Nullable;

import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RadialGradient;
import android.graphics.RectF;

import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Region;
import android.graphics.Shader;
import android.graphics.Matrix;
import android.util.Log;

import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.uimanager.annotations.ReactProp;

/**
 * Shadow node for virtual RNSVGPath view
 */
public class RNSVGPathShadowNode extends RNSVGVirtualNode {

    private static final int CAP_BUTT = 0;
    private static final int CAP_ROUND = 1;
    private static final int CAP_SQUARE = 2;

    private static final int JOIN_BEVEL = 2;
    private static final int JOIN_MITER = 0;
    private static final int JOIN_ROUND = 1;

    private static final int FILL_RULE_EVENODD = 0;
    private static final int FILL_RULE_NONZERO = 1;

    protected @Nullable Path mPath;
    private @Nullable float[] mStrokeColor;
    private @Nullable float[] mFillColor;
    private @Nullable float[] mStrokeDasharray;
    private float mStrokeWidth = 1;
    private float mStrokeDashoffset = 0;
    private int mStrokeLinecap = CAP_ROUND;
    private int mStrokeLinejoin = JOIN_ROUND;
    private int mFillRule = FILL_RULE_NONZERO;

    private Point mPaint;

    @ReactProp(name = "d")
    public void setPath(@Nullable ReadableArray shapePath) {
        float[] pathData = PropHelper.toFloatArray(shapePath);
        Path path = new Path();
        switch (mFillRule) {
            case FILL_RULE_EVENODD:
                path.setFillType(Path.FillType.EVEN_ODD);
                break;
            case FILL_RULE_NONZERO:
                break;
            default:
                throw new JSApplicationIllegalArgumentException(
                    "fillRule " + mFillRule + " unrecognized");
        }

        mPath = super.createPath(pathData, path);
        markUpdated();
    }

    @ReactProp(name = "stroke")
    public void setStroke(@Nullable ReadableArray strokeColors) {
        mStrokeColor = PropHelper.toFloatArray(strokeColors);
        markUpdated();
    }

    @ReactProp(name = "strokeDasharray")
    public void setStrokeDash(@Nullable ReadableArray strokeDasharray) {

        mStrokeDasharray = PropHelper.toFloatArray(strokeDasharray);
        if (mStrokeDasharray != null && mStrokeDasharray.length > 0) {
            for (int i = 0; i < mStrokeDasharray.length; i++) {
                mStrokeDasharray[i] = mStrokeDasharray[i] * mScale;
            }
        }
        markUpdated();
    }

    @ReactProp(name = "strokeDashoffset", defaultFloat = 0f)
    public void setStrokeDashoffset(float strokeWidth) {
        mStrokeDashoffset = strokeWidth * mScale;
        markUpdated();
    }


    @ReactProp(name = "fill")
    public void setFill(@Nullable ReadableArray fillColors) {
        mFillColor = PropHelper.toFloatArray(fillColors);
        markUpdated();
    }


    @ReactProp(name = "fillRule", defaultInt = FILL_RULE_NONZERO)
    public void setFillRule(int fillRule) {
        mFillRule = fillRule;
        markUpdated();
    }

    @ReactProp(name = "strokeWidth", defaultFloat = 1f)
    public void setStrokeWidth(float strokeWidth) {
        mStrokeWidth = strokeWidth;
        markUpdated();
    }

    @ReactProp(name = "strokeLinecap", defaultInt = CAP_ROUND)
    public void setStrokeLinecap(int strokeLinecap) {
        mStrokeLinecap = strokeLinecap;
        markUpdated();
    }

    @ReactProp(name = "strokeLinejoin", defaultInt = JOIN_ROUND)
    public void setStrokeLinejoin(int strokeLinejoin) {
        mStrokeLinejoin = strokeLinejoin;
        markUpdated();
    }

    @Override
    public void draw(Canvas canvas, Paint paint, float opacity) {
        opacity *= mOpacity;
        if (opacity > MIN_OPACITY_FOR_DRAW) {
            saveAndSetupCanvas(canvas);
            if (mPath == null) {
                throw new JSApplicationIllegalArgumentException(
                    "Paths should have a valid path (d) prop");
            }

            clip(canvas, paint);

            if (setupFillPaint(paint, opacity)) {
                canvas.drawPath(mPath, paint);
            }
            if (setupStrokePaint(paint, opacity)) {
                canvas.drawPath(mPath, paint);
            }

            restoreCanvas(canvas);
        }
        markUpdateSeen();
    }

    /*
   * sorting stops and stopsColors from array
   */
    private static void parseGradientStops(float[] value, int stopsCount, float[] stops, int[] stopsColors, int startColorsPosition) {
        int startStops = value.length - stopsCount;
        for (int i = 0; i < stopsCount; i++) {
            stops[i] = value[startStops + i];
            stopsColors[i] = Color.argb(
                    (int) (value[startColorsPosition + i * 4 + 3] * 255),
                    (int) (value[startColorsPosition + i * 4] * 255),
                    (int) (value[startColorsPosition + i * 4 + 1] * 255),
                    (int) (value[startColorsPosition + i * 4 + 2] * 255));
<commit_msg>fix fillrule bug on Android<commit_after>/**
 * Copyright (c) 2015-present, Horcrux.
 * All rights reserved.
 *
 * This source code is licensed under the MIT-style license found in the
 * LICENSE file in the root directory of this source tree.
 */


package com.horcrux.svg;

import javax.annotation.Nullable;

import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RadialGradient;
import android.graphics.RectF;

import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Region;
import android.graphics.Shader;
import android.graphics.Matrix;
import android.util.Log;

import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.uimanager.annotations.ReactProp;

/**
 * Shadow node for virtual RNSVGPath view
 */
public class RNSVGPathShadowNode extends RNSVGVirtualNode {

    private static final int CAP_BUTT = 0;
    private static final int CAP_ROUND = 1;
    private static final int CAP_SQUARE = 2;

    private static final int JOIN_BEVEL = 2;
    private static final int JOIN_MITER = 0;
    private static final int JOIN_ROUND = 1;

    private static final int FILL_RULE_EVENODD = 0;
    private static final int FILL_RULE_NONZERO = 1;

    protected @Nullable Path mPath;
    private @Nullable float[] mStrokeColor;
    private @Nullable float[] mFillColor;
    private @Nullable float[] mStrokeDasharray;
    private float mStrokeWidth = 1;
    private float mStrokeDashoffset = 0;
    private int mStrokeLinecap = CAP_ROUND;
    private int mStrokeLinejoin = JOIN_ROUND;
    private int mFillRule = FILL_RULE_NONZERO;
    private boolean mFillRuleSet;
    private boolean mPathSet;
    private float[] mShapePath;
    private Point mPaint;

    @ReactProp(name = "d")
    public void setPath(@Nullable ReadableArray shapePath) {
        mShapePath = PropHelper.toFloatArray(shapePath);
        mPathSet = true;
        setupPath();
        markUpdated();
    }

    @ReactProp(name = "fill")
    public void setFill(@Nullable ReadableArray fillColors) {
        mFillColor = PropHelper.toFloatArray(fillColors);
        markUpdated();
    }


    @ReactProp(name = "fillRule", defaultInt = FILL_RULE_NONZERO)
    public void setFillRule(int fillRule) {
        mFillRule = fillRule;
        mFillRuleSet = true;
        setupPath();
        markUpdated();
    }

    @ReactProp(name = "stroke")
    public void setStroke(@Nullable ReadableArray strokeColors) {
        mStrokeColor = PropHelper.toFloatArray(strokeColors);
        markUpdated();
    }

    @ReactProp(name = "strokeDasharray")
    public void setStrokeDash(@Nullable ReadableArray strokeDasharray) {

        mStrokeDasharray = PropHelper.toFloatArray(strokeDasharray);
        if (mStrokeDasharray != null && mStrokeDasharray.length > 0) {
            for (int i = 0; i < mStrokeDasharray.length; i++) {
                mStrokeDasharray[i] = mStrokeDasharray[i] * mScale;
            }
        }
        markUpdated();
    }

    @ReactProp(name = "strokeDashoffset", defaultFloat = 0f)
    public void setStrokeDashoffset(float strokeWidth) {
        mStrokeDashoffset = strokeWidth * mScale;
        markUpdated();
    }

    @ReactProp(name = "strokeWidth", defaultFloat = 1f)
    public void setStrokeWidth(float strokeWidth) {
        mStrokeWidth = strokeWidth;
        markUpdated();
    }

    @ReactProp(name = "strokeLinecap", defaultInt = CAP_ROUND)
    public void setStrokeLinecap(int strokeLinecap) {
        mStrokeLinecap = strokeLinecap;
        markUpdated();
    }

    @ReactProp(name = "strokeLinejoin", defaultInt = JOIN_ROUND)
    public void setStrokeLinejoin(int strokeLinejoin) {
        mStrokeLinejoin = strokeLinejoin;
        markUpdated();
    }

    @Override
    public void draw(Canvas canvas, Paint paint, float opacity) {
        opacity *= mOpacity;
        if (opacity > MIN_OPACITY_FOR_DRAW) {
            saveAndSetupCanvas(canvas);
            if (mPath == null) {
                throw new JSApplicationIllegalArgumentException(
                    "Paths should have a valid path (d) prop");
            }

            clip(canvas, paint);

            if (setupFillPaint(paint, opacity)) {
                canvas.drawPath(mPath, paint);
            }
            if (setupStrokePaint(paint, opacity)) {
                canvas.drawPath(mPath, paint);
            }

            restoreCanvas(canvas);
        }
        markUpdateSeen();
    }

    private void setupPath() {
        // init path after both fillRule and path have been set
        if (mFillRuleSet && mPathSet) {
            Path path = new Path();

            switch (mFillRule) {
                case FILL_RULE_EVENODD:
                    path.setFillType(Path.FillType.EVEN_ODD);
                    break;
                case FILL_RULE_NONZERO:
                    break;
                default:
                    throw new JSApplicationIllegalArgumentException(
                        "fillRule " + mFillRule + " unrecognized");
            }

            mPath = super.createPath(mShapePath, path);
        }
    }

    /*
   * sorting stops and stopsColors from array
   */
    private static void parseGradientStops(float[] value, int stopsCount, float[] stops, int[] stopsColors, int startColorsPosition) {
        int startStops = value.length - stopsCount;
        for (int i = 0; i < stopsCount; i++) {
            stops[i] = value[startStops + i];
            stopsColors[i] = Color.argb(
                    (int) (value[startColorsPosition + i * 4 + 3] * 255),
                    (int) (value[startColorsPosition + i * 4] * 255),
                    (int) (value[startColorsPosition + i * 4 + 1] * 255),
                    (int) (value[startColorsPosition + i * 4 + 2] * 255));

{'fraction_non_alphanumeric': 0.09084681907697577, 'fraction_numerical': 0.006507406456032195, 'mean_word_length': 2.6194607995041834, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5450340', 'n_tokens_mistral': 3504, 'n_tokens_neox': 3364, 'n_words': 842}