• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 AndroidPlot.com
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.androidplot.util;
18 
19 import android.content.Context;
20 import android.graphics.PointF;
21 import android.graphics.Rect;
22 import android.graphics.RectF;
23 import android.util.DisplayMetrics;
24 import android.util.TypedValue;
25 
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31 
32 public class PixelUtils {
33     private static DisplayMetrics metrics;
34     private static final float FLOAT_INT_AVG_NUDGE = 0.5f;
35     //private static float SCALE = 1;   //  pix per dp
36     //private static int X_PIX = 1;     // total display horizontal pix
37     //private static int Y_PIX = 1;     // total display vertical pix
38 
39     /**
40      * Recalculates scale value etc.  Should be called when an application starts or
41      * whenever the screen is rotated.
42      */
init(Context ctx)43     public static void init(Context ctx) {
44         //DisplayMetrics dm = ctx.getResources().getDisplayMetrics();
45         //SCALE = dm.density;
46         //X_PIX = dm.widthPixels;
47         //Y_PIX = dm.heightPixels;
48         metrics = ctx.getResources().getDisplayMetrics();
49 
50     }
51 
add(PointF lhs, PointF rhs)52     public static PointF add(PointF lhs, PointF rhs) {
53         return new PointF(lhs.x + rhs.x, lhs.y + rhs.y);
54     }
55 
sub(PointF lhs, PointF rhs)56     public static PointF sub(PointF lhs, PointF rhs) {
57         return new PointF(lhs.x - rhs.x, lhs.y - rhs.y);
58     }
59 
60     /**
61      * Converts a sub-pixel accurate RectF to a Rect
62      * using the closest matching full pixel vals.  This is
63      * useful for clipping operations etc.
64      * @param rectIn The rect to be converted
65      * @return
66      */
67     /*public static Rect toRect(RectF rectIn) {
68         return new Rect(
69                 (int) (rectIn.left + FLOAT_INT_AVG_NUDGE),
70                 (int) (rectIn.top + FLOAT_INT_AVG_NUDGE),
71                 (int) (rectIn.right + FLOAT_INT_AVG_NUDGE),
72                 (int) (rectIn.bottom + FLOAT_INT_AVG_NUDGE));
73     }*/
74 
75     /**
76      * Converts a sub-pixel accurate RectF to
77      * a single pixel accurate rect.  This is helpful
78      * for clipping operations which dont do a good job with
79      * subpixel vals.
80      * @param in
81      * @return
82      */
sink(RectF in)83     public static RectF sink(RectF in) {
84         return nearestPixRect(in.left, in.top, in.right, in.bottom);
85     }
86 
nearestPixRect(float left, float top, float right, float bottom)87     public static RectF nearestPixRect(float left, float top, float right, float bottom) {
88         return new RectF(
89                 (int) (left + FLOAT_INT_AVG_NUDGE),
90                 (int) (top + FLOAT_INT_AVG_NUDGE),
91                 (int) (right + FLOAT_INT_AVG_NUDGE),
92                 (int) (bottom + FLOAT_INT_AVG_NUDGE));
93     }
94 
95     /**
96      * Converts a dp value to pixels.
97      * @param dp
98      * @return Pixel value of dp.
99      */
dpToPix(float dp)100     public static float dpToPix(float dp) {
101         //return SCALE * dp + FLOAT_INT_AVG_NUDGE;
102         //InternalDimension id = new InternalDimension(dp, TypedValue.COMPLEX_UNIT_DIP);
103         return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, metrics);
104 
105     }
106 
107     /**
108      * Converts an sp value to pixels.
109      * @param sp
110      * @return Pixel value of sp.
111      */
112     @SuppressWarnings("SameParameterValue")
spToPix(float sp)113     public static float spToPix(float sp) {
114         return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, metrics);
115     }
116 
117 
118     /**
119      *
120      * @param fraction A float value between 0 and 1.
121      * @return Number of pixels fraction represents on the current device's display.
122      */
fractionToPixH(float fraction)123     public static float fractionToPixH(float fraction) {
124         return metrics.heightPixels * fraction;
125 
126     }
127 
128     /**
129      *
130      * @param fraction A float value between 0 and 1.
131      * @return Number of pixels fraction represents on the current device's display.
132      */
fractionToPixW(float fraction)133     public static float fractionToPixW(float fraction) {
134         return metrics.widthPixels * fraction;
135     }
136 
137 
138     /**
139      *
140      * CODE BELOW IS ADAPTED IN PART FROM MINDRIOT'S SAMPLE CODE HERE:
141      * http://stackoverflow.com/questions/8343971/how-to-parse-a-dimension-string-and-convert-it-to-a-dimension-value
142      */
143     // -- Initialize dimension string to constant lookup.
144     public static final Map<String, Integer> dimensionConstantLookup = initDimensionConstantLookup();
145 
initDimensionConstantLookup()146     private static Map<String, Integer> initDimensionConstantLookup() {
147         Map<String, Integer> m = new HashMap<String, Integer>();
148         m.put("px", TypedValue.COMPLEX_UNIT_PX);
149         m.put("dip", TypedValue.COMPLEX_UNIT_DIP);
150         m.put("dp", TypedValue.COMPLEX_UNIT_DIP);
151         m.put("sp", TypedValue.COMPLEX_UNIT_SP);
152         m.put("pt", TypedValue.COMPLEX_UNIT_PT);
153         m.put("in", TypedValue.COMPLEX_UNIT_IN);
154         m.put("mm", TypedValue.COMPLEX_UNIT_MM);
155         return Collections.unmodifiableMap(m);
156     }
157 
158     // -- Initialize pattern for dimension string.
159     private static final Pattern DIMENSION_PATTERN = Pattern.compile("^\\s*(\\d+(\\.\\d+)*)\\s*([a-zA-Z]+)\\s*$");
160 
161     /*public static int stringToDimensionPixelSize(String dimension, DisplayMetrics metrics) {
162         // -- Mimics TypedValue.complexToDimensionPixelSize(int data, DisplayMetrics metrics).
163         InternalDimension internalDimension = stringToInternalDimension(dimension);
164         final float value = internalDimension.value;
165         final float f = TypedValue.applyDimension(internalDimension.unit, value, metrics);
166         final int res = (int) (f + 0.5f);
167         if (res != 0) return res;
168         if (value == 0) return 0;
169         if (value > 0) return 1;
170         return -1;
171     }*/
172 
stringToDimension(String dimension)173     public static float stringToDimension(String dimension) {
174         // -- Mimics TypedValue.complexToDimension(int data, DisplayMetrics metrics).
175         InternalDimension internalDimension = stringToInternalDimension(dimension);
176         return TypedValue.applyDimension(internalDimension.unit, internalDimension.value, metrics);
177     }
178 
stringToInternalDimension(String dimension)179     private static InternalDimension stringToInternalDimension(String dimension) {
180         // -- Match target against pattern.
181         Matcher matcher = DIMENSION_PATTERN.matcher(dimension);
182         if (matcher.matches()) {
183             // -- Match found.
184             // -- Extract value.
185             float value = Float.valueOf(matcher.group(1));
186             // -- Extract dimension units.
187             String unit = matcher.group(3).toLowerCase();
188             // -- Get Android dimension constant.
189             Integer dimensionUnit = dimensionConstantLookup.get(unit);
190             if (dimensionUnit == null) {
191                 // -- Invalid format.
192                 throw new NumberFormatException();
193             } else {
194                 // -- Return valid dimension.
195                 return new InternalDimension(value, dimensionUnit);
196             }
197         } else {
198             // -- Invalid format.
199             throw new NumberFormatException();
200         }
201     }
202 
203     private static class InternalDimension {
204         float value;
205         int unit;
206 
InternalDimension(float value, int unit)207         public InternalDimension(float value, int unit) {
208             this.value = value;
209             this.unit = unit;
210         }
211     }
212 
213 
214 }
215 
216 
217 
218