1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.tv.settings.util;
18
19import android.graphics.Matrix;
20import android.graphics.RectF;
21import android.graphics.drawable.Drawable;
22import android.view.View;
23import android.view.ViewParent;
24import android.widget.ImageView;
25
26/**
27 * Utility class for View/ImageView locations and clip bounds etc.
28 */
29public class WindowLocationUtil {
30
31    private static final float[] sTmpFloat4 = new float[4];
32    private static final float[] sTmpFloat8 = new float[8];
33
34    /**
35     * map points inside view into locations of a screen
36     * The function is an extension of {@link View#getLocationInWindow } and can map
37     * multiple points.
38     *
39     * @param points x[0], y[0], x[1], y[1], ...
40     */
41    public static void getLocationsInWindow(View view, float[] points) {
42
43        if (points == null || (points.length & 1) != 0) {
44            throw new IllegalArgumentException();
45        }
46        int length = points.length;
47        Matrix matrix = view.getMatrix();
48        if (matrix != null && !matrix.isIdentity()) {
49            matrix.mapPoints(points);
50        }
51
52        int deltax = view.getLeft();
53        int deltay = view.getTop();
54        for (int i = 0; i < length; ) {
55            points[i] += deltax;
56            i++;
57            points[i] += deltay;
58            i++;
59        }
60
61        ViewParent viewParent = view.getParent();
62        while (viewParent instanceof View) {
63            view = (View) viewParent;
64
65            deltax = view.getScrollX();
66            deltay = view.getScrollY();
67            for (int i = 0; i < length; ) {
68                points[i] -= deltax;
69                i++;
70                points[i] -= deltay;
71                i++;
72            }
73
74            matrix = view.getMatrix();
75            if (matrix != null && !matrix.isIdentity()) {
76                matrix.mapPoints(points);
77            }
78
79            deltax = view.getLeft();
80            deltay = view.getTop();
81            for (int i = 0; i < length; ) {
82                points[i] += deltax;
83                i++;
84                points[i] += deltay;
85                i++;
86            }
87
88            viewParent = view.getParent();
89        }
90    }
91
92    /**
93     * get locations of view bounds in Window
94     */
95    public static void getLocationsInWindow(View view, RectF rect) {
96        sTmpFloat4[0] = rect.left;
97        sTmpFloat4[1] = rect.top;
98        sTmpFloat4[2] = rect.right;
99        sTmpFloat4[3] = rect.bottom;
100        getLocationsInWindow(view, sTmpFloat4);
101        rect.left = sTmpFloat4[0];
102        rect.top = sTmpFloat4[1];
103        rect.right = sTmpFloat4[2];
104        rect.bottom = sTmpFloat4[3];
105    }
106
107    /**
108     * get clip and unclipped bounds of ImageView inside a window
109     */
110    public static void getImageLocationsInWindow(ImageView view,
111            RectF clippedBounds, RectF unclippedBitmapRect) {
112        // get bounds exclude padding, bitmap will be clipped by this bounds
113        clippedBounds.set(view.getPaddingLeft(), view.getPaddingTop(),
114                view.getWidth() - view.getPaddingRight(),
115                view.getHeight() - view.getPaddingBottom());
116        Matrix matrix = view.getImageMatrix();
117
118        Drawable drawable = view.getDrawable();
119
120        if (drawable != null) {
121            unclippedBitmapRect.set(drawable.getBounds());
122            matrix.mapRect(unclippedBitmapRect);
123            unclippedBitmapRect.offset(view.getPaddingLeft(), view.getPaddingTop());
124            sTmpFloat8[0] = clippedBounds.left;
125            sTmpFloat8[1] = clippedBounds.top;
126            sTmpFloat8[2] = clippedBounds.right;
127            sTmpFloat8[3] = clippedBounds.bottom;
128            sTmpFloat8[4] = unclippedBitmapRect.left;
129            sTmpFloat8[5] = unclippedBitmapRect.top;
130            sTmpFloat8[6] = unclippedBitmapRect.right;
131            sTmpFloat8[7] = unclippedBitmapRect.bottom;
132            getLocationsInWindow(view, sTmpFloat8);
133            clippedBounds.left = sTmpFloat8[0];
134            clippedBounds.top = sTmpFloat8[1];
135            clippedBounds.right = sTmpFloat8[2];
136            clippedBounds.bottom = sTmpFloat8[3];
137            unclippedBitmapRect.left = sTmpFloat8[4];
138            unclippedBitmapRect.top = sTmpFloat8[5];
139            unclippedBitmapRect.right = sTmpFloat8[6];
140            unclippedBitmapRect.bottom = sTmpFloat8[7];
141            clippedBounds.intersect(unclippedBitmapRect);
142        } else {
143            sTmpFloat4[0] = clippedBounds.left;
144            sTmpFloat4[1] = clippedBounds.top;
145            sTmpFloat4[2] = clippedBounds.right;
146            sTmpFloat4[3] = clippedBounds.bottom;
147            getLocationsInWindow(view, sTmpFloat4);
148            clippedBounds.left = sTmpFloat4[0];
149            clippedBounds.top = sTmpFloat4[1];
150            clippedBounds.right = sTmpFloat4[2];
151            clippedBounds.bottom = sTmpFloat4[3];
152            unclippedBitmapRect.set(clippedBounds);
153        }
154    }
155}
156