aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/pixart/messenger/ui/widget/ScannerView.java
blob: 25b1f9f259a1f21f186858064f7034618431da64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * Copyright 2012-2015 the original author or authors.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.pixart.messenger.ui.widget;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Matrix.ScaleToFit;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import com.google.zxing.ResultPoint;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import de.pixart.messenger.R;

/**
 * @author Andreas Schildbach
 */

public class ScannerView extends View {
    private static final long LASER_ANIMATION_DELAY_MS = 100l;
    private static final int DOT_OPACITY = 0xa0;
    private static final int DOT_TTL_MS = 500;

    private final Paint maskPaint;
    private final Paint laserPaint;
    private final Paint dotPaint;
    private final int maskColor, maskResultColor;
    private final int laserColor;
    private final int dotColor, dotResultColor;
    private final Map<float[], Long> dots = new HashMap<float[], Long>(16);
    private final Matrix matrix = new Matrix();
    private boolean isResult;
    private Rect frame;

    public ScannerView(final Context context, final AttributeSet attrs) {
        super(context, attrs);

        final Resources res = getResources();
        maskColor = res.getColor(R.color.black54);
        maskResultColor = res.getColor(R.color.black87);
        laserColor = res.getColor(R.color.red500);
        dotColor = res.getColor(R.color.orange500);
        dotResultColor = res.getColor(R.color.scan_result_dots);

        maskPaint = new Paint();
        maskPaint.setStyle(Style.FILL);

        laserPaint = new Paint();
        laserPaint.setStrokeWidth(res.getDimensionPixelSize(R.dimen.scan_laser_width));
        laserPaint.setStyle(Style.STROKE);

        dotPaint = new Paint();
        dotPaint.setAlpha(DOT_OPACITY);
        dotPaint.setStyle(Style.STROKE);
        dotPaint.setStrokeWidth(res.getDimension(R.dimen.scan_dot_size));
        dotPaint.setAntiAlias(true);
    }

    public void setFraming(final Rect frame, final RectF framePreview, final int displayRotation,
                           final int cameraRotation, final boolean cameraFlip) {
        this.frame = frame;
        matrix.setRectToRect(framePreview, new RectF(frame), ScaleToFit.FILL);
        matrix.postRotate(-displayRotation, frame.exactCenterX(), frame.exactCenterY());
        matrix.postScale(cameraFlip ? -1 : 1, 1, frame.exactCenterX(), frame.exactCenterY());
        matrix.postRotate(cameraRotation, frame.exactCenterX(), frame.exactCenterY());

        invalidate();
    }

    public void setIsResult(final boolean isResult) {
        this.isResult = isResult;

        invalidate();
    }

    public void addDot(final ResultPoint dot) {
        dots.put(new float[]{dot.getX(), dot.getY()}, System.currentTimeMillis());

        invalidate();
    }

    @Override
    public void onDraw(final Canvas canvas) {
        if (frame == null)
            return;

        final long now = System.currentTimeMillis();

        final int width = canvas.getWidth();
        final int height = canvas.getHeight();

        final float[] point = new float[2];

        // draw mask darkened
        maskPaint.setColor(isResult ? maskResultColor : maskColor);
        canvas.drawRect(0, 0, width, frame.top, maskPaint);
        canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, maskPaint);
        canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, maskPaint);
        canvas.drawRect(0, frame.bottom + 1, width, height, maskPaint);

        if (isResult) {
            laserPaint.setColor(dotResultColor);
            laserPaint.setAlpha(160);

            dotPaint.setColor(dotResultColor);
        } else {
            laserPaint.setColor(laserColor);
            final boolean laserPhase = (now / 600) % 2 == 0;
            laserPaint.setAlpha(laserPhase ? 160 : 255);

            dotPaint.setColor(dotColor);

            // schedule redraw
            postInvalidateDelayed(LASER_ANIMATION_DELAY_MS);
        }

        canvas.drawRect(frame, laserPaint);

        // draw points
        for (final Iterator<Map.Entry<float[], Long>> i = dots.entrySet().iterator(); i.hasNext(); ) {
            final Map.Entry<float[], Long> entry = i.next();
            final long age = now - entry.getValue();
            if (age < DOT_TTL_MS) {
                dotPaint.setAlpha((int) ((DOT_TTL_MS - age) * 256 / DOT_TTL_MS));

                matrix.mapPoints(point, entry.getKey());
                canvas.drawPoint(point[0], point[1], dotPaint);
            } else {
                i.remove();
            }
        }
    }
}