That fuck shit the fascists are using
at master 338 lines 11 kB view raw
1package org.tm.archive.util; 2 3import android.graphics.Path; 4import android.graphics.Rect; 5import android.graphics.RectF; 6import android.os.Build; 7import android.view.View; 8import android.view.ViewGroup; 9 10import androidx.annotation.NonNull; 11import androidx.annotation.Nullable; 12import androidx.core.util.Pools; 13 14import java.util.Arrays; 15import java.util.Collections; 16import java.util.List; 17import java.util.Objects; 18 19/** 20 * Describes the position, size, and corner masking of a given view relative to a parent. 21 */ 22public final class Projection { 23 24 private float x; 25 private float y; 26 private int width; 27 private int height; 28 private Corners corners; 29 private Path path; 30 private RectF rect; 31 32 private Projection() { 33 x = 0f; 34 y = 0f; 35 width = 0; 36 height = 0; 37 corners = null; 38 path = new Path(); 39 rect = new RectF(); 40 } 41 42 private Projection set(float x, float y, int width, int height, @Nullable Corners corners) { 43 this.x = x; 44 this.y = y; 45 this.width = width; 46 this.height = height; 47 this.corners = corners; 48 49 rect.set(x, y, x + width, y + height); 50 path.reset(); 51 52 if (corners != null) { 53 path.addRoundRect(rect, corners.toRadii(), Path.Direction.CW); 54 } else { 55 path.addRect(rect, Path.Direction.CW); 56 } 57 58 return this; 59 } 60 61 public float getX() { 62 return x; 63 } 64 65 public float getY() { 66 return y; 67 } 68 69 public int getWidth() { 70 return width; 71 } 72 73 public int getHeight() { 74 return height; 75 } 76 77 public @Nullable Corners getCorners() { 78 return corners; 79 } 80 81 public @NonNull Path getPath() { 82 return path; 83 } 84 85 public void applyToPath(@NonNull Path path) { 86 if (corners == null) { 87 path.addRect(rect, Path.Direction.CW); 88 } else { 89 path.addRoundRect(rect, corners.toRadii(), Path.Direction.CW); 90 } 91 } 92 93 @Override public String toString() { 94 return "Projection{" + 95 "x=" + x + 96 ", y=" + y + 97 ", width=" + width + 98 ", height=" + height + 99 ", corners=" + corners + 100 ", path=" + path + 101 ", rect=" + rect + 102 '}'; 103 } 104 105 public @NonNull Projection translateX(float xTranslation) { 106 return set(x + xTranslation, y, width, height, corners); 107 } 108 109 public @NonNull Projection translateY(float yTranslation) { 110 return set(x, y + yTranslation, width, height, corners); 111 } 112 113 public @NonNull Projection scale(float scale) { 114 Corners newCorners = this.corners == null ? null : new Corners(this.corners.topLeft * scale, 115 this.corners.topRight * scale, 116 this.corners.bottomRight * scale, 117 this.corners.bottomLeft * scale); 118 return set(x, y, (int) (width * scale), (int) (height * scale), newCorners); 119 } 120 121 public @NonNull Projection insetTop(int boundary) { 122 Corners newCorners = this.corners == null ? null : new Corners(0, 123 0, 124 this.corners.bottomRight, 125 this.corners.bottomLeft); 126 127 return set(x, y + boundary, width, height - boundary, newCorners); 128 } 129 130 public @NonNull Projection insetBottom(int boundary) { 131 Corners newCorners = this.corners == null ? null : new Corners(this.corners.topLeft, 132 this.corners.topRight, 133 0, 134 0); 135 136 return set(x, y, width, height - boundary, newCorners); 137 } 138 139 public static @NonNull Projection relativeToParent(@NonNull ViewGroup parent, @NonNull View view, @Nullable Corners corners) { 140 Rect viewBounds = new Rect(); 141 142 view.getDrawingRect(viewBounds); 143 parent.offsetDescendantRectToMyCoords(view, viewBounds); 144 return acquireAndSet(viewBounds.left, viewBounds.top, view.getWidth(), view.getHeight(), corners); 145 } 146 147 public static @NonNull Projection relativeToViewRoot(@NonNull View view, @Nullable Corners corners) { 148 Rect viewBounds = new Rect(); 149 ViewGroup root = (ViewGroup) view.getRootView(); 150 151 view.getDrawingRect(viewBounds); 152 root.offsetDescendantRectToMyCoords(view, viewBounds); 153 154 return acquireAndSet(viewBounds.left, viewBounds.top, view.getWidth(), view.getHeight(), corners); 155 } 156 157 public static @NonNull Projection relativeToViewWithCommonRoot(@NonNull View toProject, @NonNull View viewWithCommonRoot, @Nullable Corners corners) { 158 Rect viewBounds = new Rect(); 159 ViewGroup root = (ViewGroup) toProject.getRootView(); 160 161 toProject.getDrawingRect(viewBounds); 162 root.offsetDescendantRectToMyCoords(toProject, viewBounds); 163 root.offsetRectIntoDescendantCoords(viewWithCommonRoot, viewBounds); 164 165 return acquireAndSet(viewBounds.left, viewBounds.top, toProject.getWidth(), toProject.getHeight(), corners); 166 } 167 168 public static @NonNull Projection translateFromDescendantToParentCoords(@NonNull Projection descendantProjection, @NonNull View descendant, @NonNull ViewGroup parent) { 169 Rect viewBounds = new Rect(); 170 171 viewBounds.set((int) descendantProjection.x, (int) descendantProjection.y, (int) descendantProjection.x + descendantProjection.width, (int) descendantProjection.y + descendantProjection.height); 172 173 parent.offsetDescendantRectToMyCoords(descendant, viewBounds); 174 175 return acquireAndSet(viewBounds.left, viewBounds.top, descendantProjection.width, descendantProjection.height, descendantProjection.corners); 176 } 177 178 public static @NonNull List<Projection> getCapAndTail(@NonNull Projection parentProjection, @NonNull Projection childProjection) { 179 if (parentProjection.equals(childProjection)) { 180 return Collections.emptyList(); 181 } 182 183 float topX = parentProjection.x; 184 float topY = parentProjection.y; 185 int topWidth = parentProjection.getWidth(); 186 int topHeight = (int) (childProjection.y - parentProjection.y); 187 188 final Corners topCorners; 189 Corners parentCorners = parentProjection.getCorners(); 190 if (parentCorners != null) { 191 topCorners = new Corners(parentCorners.topLeft, parentCorners.topRight, 0f, 0f); 192 } else { 193 topCorners = null; 194 } 195 196 float bottomX = parentProjection.x; 197 float bottomY = parentProjection.y + topHeight + childProjection.getHeight(); 198 int bottomWidth = parentProjection.getWidth(); 199 int bottomHeight = (int) ((parentProjection.y + parentProjection.getHeight()) - bottomY); 200 201 final Corners bottomCorners; 202 if (parentCorners != null) { 203 bottomCorners = new Corners(0f, 0f, parentCorners.bottomRight, parentCorners.bottomLeft); 204 } else { 205 bottomCorners = null; 206 } 207 208 return Arrays.asList( 209 acquireAndSet(topX, topY, topWidth, topHeight, topCorners), 210 acquireAndSet(bottomX, bottomY, bottomWidth, bottomHeight, bottomCorners) 211 ); 212 } 213 214 /** 215 * We keep a maximum of 125 Projections around at any one time. 216 */ 217 private static final Pools.SimplePool<Projection> projectionPool = new Pools.SimplePool<>(125); 218 219 /** 220 * Acquire a projection. This will try to grab one from the pool, and, upon failure, will 221 * allocate a new one instead. 222 */ 223 private static @NonNull Projection acquire() { 224 Projection fromPool = projectionPool.acquire(); 225 if (fromPool != null) { 226 return fromPool; 227 } else { 228 return new Projection(); 229 } 230 } 231 232 /** 233 * Acquire a projection and set its fields as specified. 234 */ 235 private static @NonNull Projection acquireAndSet(float x, float y, int width, int height, @Nullable Corners corners) { 236 Projection projection = acquire(); 237 projection.set(x, y, width, height, corners); 238 239 return projection; 240 } 241 242 /** 243 * Projections should only be kept around for the absolute maximum amount of time they are needed. 244 */ 245 public void release() { 246 projectionPool.release(this); 247 } 248 249 250 public static final class Corners { 251 252 public static final Corners NONE = new Corners(0f); 253 254 private final float topLeft; 255 private final float topRight; 256 private final float bottomRight; 257 private final float bottomLeft; 258 259 public Corners(float topLeft, float topRight, float bottomRight, float bottomLeft) { 260 this.topLeft = topLeft; 261 this.topRight = topRight; 262 this.bottomRight = bottomRight; 263 this.bottomLeft = bottomLeft; 264 } 265 266 public Corners(float[] radii) { 267 this.topLeft = radii[0]; 268 this.topRight = radii[2]; 269 this.bottomRight = radii[4]; 270 this.bottomLeft = radii[6]; 271 } 272 273 public Corners(float radius) { 274 this(radius, radius, radius, radius); 275 } 276 277 public float getTopLeft() { 278 return topLeft; 279 } 280 281 public float getTopRight() { 282 return topRight; 283 } 284 285 public float getBottomLeft() { 286 return bottomLeft; 287 } 288 289 public float getBottomRight() { 290 return bottomRight; 291 } 292 293 public float[] toRelativeRadii(boolean isLTR) { 294 float[] radii = new float[8]; 295 296 radii[0] = radii[1] = isLTR ? topLeft : topRight; 297 radii[2] = radii[3] = isLTR ? topRight : topLeft; 298 radii[4] = radii[5] = isLTR ? bottomRight : bottomLeft; 299 radii[6] = radii[7] = isLTR ? bottomLeft : bottomRight; 300 301 return radii; 302 } 303 304 public float[] toRadii() { 305 float[] radii = new float[8]; 306 307 radii[0] = radii[1] = topLeft; 308 radii[2] = radii[3] = topRight; 309 radii[4] = radii[5] = bottomRight; 310 radii[6] = radii[7] = bottomLeft; 311 312 return radii; 313 } 314 315 @Override public boolean equals(Object o) { 316 if (this == o) return true; 317 if (o == null || getClass() != o.getClass()) return false; 318 final Corners corners = (Corners) o; 319 return Float.compare(corners.topLeft, topLeft) == 0 && 320 Float.compare(corners.topRight, topRight) == 0 && 321 Float.compare(corners.bottomRight, bottomRight) == 0 && 322 Float.compare(corners.bottomLeft, bottomLeft) == 0; 323 } 324 325 @Override public int hashCode() { 326 return Objects.hash(topLeft, topRight, bottomRight, bottomLeft); 327 } 328 329 @Override public String toString() { 330 return "Corners{" + 331 "topLeft=" + topLeft + 332 ", topRight=" + topRight + 333 ", bottomRight=" + bottomRight + 334 ", bottomLeft=" + bottomLeft + 335 '}'; 336 } 337 } 338}