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 
17 package com.android.tv.settings.util;
18 
19 import android.graphics.Matrix;
20 import android.graphics.RectF;
21 import android.graphics.drawable.Drawable;
22 import android.view.View;
23 import android.view.ViewParent;
24 import android.widget.ImageView;
25 
26 /**
27  * Utility class for View/ImageView locations and clip bounds etc.
28  */
29 public 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      */
getLocationsInWindow(View view, float[] points)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      */
getLocationsInWindow(View view, RectF rect)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      */
getImageLocationsInWindow(ImageView view, RectF clippedBounds, RectF unclippedBitmapRect)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