1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 package org
.mozilla
.gecko
.gfx
;
8 import android
.graphics
.PointF
;
9 import android
.graphics
.RectF
;
10 import android
.util
.DisplayMetrics
;
12 import org
.mozilla
.gecko
.util
.FloatUtils
;
15 * ImmutableViewportMetrics are used to store the viewport metrics
16 * in way that we can access a version of them from multiple threads
17 * without having to take a lock
19 public class ImmutableViewportMetrics
{
21 // We need to flatten the RectF and FloatSize structures
22 // because Java doesn't have the concept of const classes
23 public final float pageRectLeft
;
24 public final float pageRectTop
;
25 public final float pageRectRight
;
26 public final float pageRectBottom
;
27 public final float cssPageRectLeft
;
28 public final float cssPageRectTop
;
29 public final float cssPageRectRight
;
30 public final float cssPageRectBottom
;
31 public final float viewportRectLeft
;
32 public final float viewportRectTop
;
33 public final float viewportRectRight
;
34 public final float viewportRectBottom
;
35 public final float zoomFactor
;
37 public ImmutableViewportMetrics(DisplayMetrics metrics
) {
38 viewportRectLeft
= pageRectLeft
= cssPageRectLeft
= 0;
39 viewportRectTop
= pageRectTop
= cssPageRectTop
= 0;
40 viewportRectRight
= pageRectRight
= cssPageRectRight
= metrics
.widthPixels
;
41 viewportRectBottom
= pageRectBottom
= cssPageRectBottom
= metrics
.heightPixels
;
45 private ImmutableViewportMetrics(float aPageRectLeft
, float aPageRectTop
,
46 float aPageRectRight
, float aPageRectBottom
, float aCssPageRectLeft
,
47 float aCssPageRectTop
, float aCssPageRectRight
, float aCssPageRectBottom
,
48 float aViewportRectLeft
, float aViewportRectTop
, float aViewportRectRight
,
49 float aViewportRectBottom
, float aZoomFactor
)
51 pageRectLeft
= aPageRectLeft
;
52 pageRectTop
= aPageRectTop
;
53 pageRectRight
= aPageRectRight
;
54 pageRectBottom
= aPageRectBottom
;
55 cssPageRectLeft
= aCssPageRectLeft
;
56 cssPageRectTop
= aCssPageRectTop
;
57 cssPageRectRight
= aCssPageRectRight
;
58 cssPageRectBottom
= aCssPageRectBottom
;
59 viewportRectLeft
= aViewportRectLeft
;
60 viewportRectTop
= aViewportRectTop
;
61 viewportRectRight
= aViewportRectRight
;
62 viewportRectBottom
= aViewportRectBottom
;
63 zoomFactor
= aZoomFactor
;
66 public float getWidth() {
67 return viewportRectRight
- viewportRectLeft
;
70 public float getHeight() {
71 return viewportRectBottom
- viewportRectTop
;
74 public PointF
getOrigin() {
75 return new PointF(viewportRectLeft
, viewportRectTop
);
78 public FloatSize
getSize() {
79 return new FloatSize(viewportRectRight
- viewportRectLeft
, viewportRectBottom
- viewportRectTop
);
82 public RectF
getViewport() {
83 return new RectF(viewportRectLeft
,
89 public RectF
getCssViewport() {
90 return RectUtils
.scale(getViewport(), 1/zoomFactor
);
93 public RectF
getPageRect() {
94 return new RectF(pageRectLeft
, pageRectTop
, pageRectRight
, pageRectBottom
);
97 public float getPageWidth() {
98 return pageRectRight
- pageRectLeft
;
101 public float getPageHeight() {
102 return pageRectBottom
- pageRectTop
;
105 public RectF
getCssPageRect() {
106 return new RectF(cssPageRectLeft
, cssPageRectTop
, cssPageRectRight
, cssPageRectBottom
);
109 public float getZoomFactor() {
114 * Returns the viewport metrics that represent a linear transition between "this" and "to" at
115 * time "t", which is on the scale [0, 1). This function interpolates all values stored in
116 * the viewport metrics.
118 public ImmutableViewportMetrics
interpolate(ImmutableViewportMetrics to
, float t
) {
119 return new ImmutableViewportMetrics(
120 FloatUtils
.interpolate(pageRectLeft
, to
.pageRectLeft
, t
),
121 FloatUtils
.interpolate(pageRectTop
, to
.pageRectTop
, t
),
122 FloatUtils
.interpolate(pageRectRight
, to
.pageRectRight
, t
),
123 FloatUtils
.interpolate(pageRectBottom
, to
.pageRectBottom
, t
),
124 FloatUtils
.interpolate(cssPageRectLeft
, to
.cssPageRectLeft
, t
),
125 FloatUtils
.interpolate(cssPageRectTop
, to
.cssPageRectTop
, t
),
126 FloatUtils
.interpolate(cssPageRectRight
, to
.cssPageRectRight
, t
),
127 FloatUtils
.interpolate(cssPageRectBottom
, to
.cssPageRectBottom
, t
),
128 FloatUtils
.interpolate(viewportRectLeft
, to
.viewportRectLeft
, t
),
129 FloatUtils
.interpolate(viewportRectTop
, to
.viewportRectTop
, t
),
130 FloatUtils
.interpolate(viewportRectRight
, to
.viewportRectRight
, t
),
131 FloatUtils
.interpolate(viewportRectBottom
, to
.viewportRectBottom
, t
),
132 FloatUtils
.interpolate(zoomFactor
, to
.zoomFactor
, t
));
135 public ImmutableViewportMetrics
setViewportSize(float width
, float height
) {
136 return new ImmutableViewportMetrics(
137 pageRectLeft
, pageRectTop
, pageRectRight
, pageRectBottom
,
138 cssPageRectLeft
, cssPageRectTop
, cssPageRectRight
, cssPageRectBottom
,
139 viewportRectLeft
, viewportRectTop
, viewportRectLeft
+ width
, viewportRectTop
+ height
,
143 public ImmutableViewportMetrics
setViewportOrigin(float newOriginX
, float newOriginY
) {
144 return new ImmutableViewportMetrics(
145 pageRectLeft
, pageRectTop
, pageRectRight
, pageRectBottom
,
146 cssPageRectLeft
, cssPageRectTop
, cssPageRectRight
, cssPageRectBottom
,
147 newOriginX
, newOriginY
, newOriginX
+ getWidth(), newOriginY
+ getHeight(),
151 public ImmutableViewportMetrics
setZoomFactor(float newZoomFactor
) {
152 return new ImmutableViewportMetrics(
153 pageRectLeft
, pageRectTop
, pageRectRight
, pageRectBottom
,
154 cssPageRectLeft
, cssPageRectTop
, cssPageRectRight
, cssPageRectBottom
,
155 viewportRectLeft
, viewportRectTop
, viewportRectRight
, viewportRectBottom
,
159 public ImmutableViewportMetrics
offsetViewportBy(float dx
, float dy
) {
160 return setViewportOrigin(viewportRectLeft
+ dx
, viewportRectTop
+ dy
);
163 public ImmutableViewportMetrics
setPageRect(RectF pageRect
, RectF cssPageRect
) {
164 return new ImmutableViewportMetrics(
165 pageRect
.left
, pageRect
.top
, pageRect
.right
, pageRect
.bottom
,
166 cssPageRect
.left
, cssPageRect
.top
, cssPageRect
.right
, cssPageRect
.bottom
,
167 viewportRectLeft
, viewportRectTop
, viewportRectRight
, viewportRectBottom
,
171 /* This will set the zoom factor and re-scale page-size and viewport offset
172 * accordingly. The given focus will remain at the same point on the screen
175 public ImmutableViewportMetrics
scaleTo(float newZoomFactor
, PointF focus
) {
176 // cssPageRect* is invariant, since we're setting the scale factor
177 // here. The page rect is based on the CSS page rect.
178 float newPageRectLeft
= cssPageRectLeft
* newZoomFactor
;
179 float newPageRectTop
= cssPageRectTop
* newZoomFactor
;
180 float newPageRectRight
= cssPageRectLeft
+ ((cssPageRectRight
- cssPageRectLeft
) * newZoomFactor
);
181 float newPageRectBottom
= cssPageRectTop
+ ((cssPageRectBottom
- cssPageRectTop
) * newZoomFactor
);
183 PointF origin
= getOrigin();
184 origin
.offset(focus
.x
, focus
.y
);
185 origin
= PointUtils
.scale(origin
, newZoomFactor
/ zoomFactor
);
186 origin
.offset(-focus
.x
, -focus
.y
);
188 return new ImmutableViewportMetrics(
189 newPageRectLeft
, newPageRectTop
, newPageRectRight
, newPageRectBottom
,
190 cssPageRectLeft
, cssPageRectTop
, cssPageRectRight
, cssPageRectBottom
,
191 origin
.x
, origin
.y
, origin
.x
+ getWidth(), origin
.y
+ getHeight(),
195 /** Clamps the viewport to remain within the page rect. */
196 public ImmutableViewportMetrics
clamp() {
197 RectF newViewport
= getViewport();
199 // The viewport bounds ought to never exceed the page bounds.
200 if (newViewport
.right
> pageRectRight
)
201 newViewport
.offset(pageRectRight
- newViewport
.right
, 0);
202 if (newViewport
.left
< pageRectLeft
)
203 newViewport
.offset(pageRectLeft
- newViewport
.left
, 0);
205 if (newViewport
.bottom
> pageRectBottom
)
206 newViewport
.offset(0, pageRectBottom
- newViewport
.bottom
);
207 if (newViewport
.top
< pageRectTop
)
208 newViewport
.offset(0, pageRectTop
- newViewport
.top
);
210 return new ImmutableViewportMetrics(
211 pageRectLeft
, pageRectTop
, pageRectRight
, pageRectBottom
,
212 cssPageRectLeft
, cssPageRectTop
, cssPageRectRight
, cssPageRectBottom
,
213 newViewport
.left
, newViewport
.top
, newViewport
.right
, newViewport
.bottom
,
217 public boolean fuzzyEquals(ImmutableViewportMetrics other
) {
218 return FloatUtils
.fuzzyEquals(pageRectLeft
, other
.pageRectLeft
)
219 && FloatUtils
.fuzzyEquals(pageRectTop
, other
.pageRectTop
)
220 && FloatUtils
.fuzzyEquals(pageRectRight
, other
.pageRectRight
)
221 && FloatUtils
.fuzzyEquals(pageRectBottom
, other
.pageRectBottom
)
222 && FloatUtils
.fuzzyEquals(cssPageRectLeft
, other
.cssPageRectLeft
)
223 && FloatUtils
.fuzzyEquals(cssPageRectTop
, other
.cssPageRectTop
)
224 && FloatUtils
.fuzzyEquals(cssPageRectRight
, other
.cssPageRectRight
)
225 && FloatUtils
.fuzzyEquals(cssPageRectBottom
, other
.cssPageRectBottom
)
226 && FloatUtils
.fuzzyEquals(viewportRectLeft
, other
.viewportRectLeft
)
227 && FloatUtils
.fuzzyEquals(viewportRectTop
, other
.viewportRectTop
)
228 && FloatUtils
.fuzzyEquals(viewportRectRight
, other
.viewportRectRight
)
229 && FloatUtils
.fuzzyEquals(viewportRectBottom
, other
.viewportRectBottom
)
230 && FloatUtils
.fuzzyEquals(zoomFactor
, other
.zoomFactor
);
234 public String
toString() {
235 return "ImmutableViewportMetrics v=(" + viewportRectLeft
+ "," + viewportRectTop
+ ","
236 + viewportRectRight
+ "," + viewportRectBottom
+ ") p=(" + pageRectLeft
+ ","
237 + pageRectTop
+ "," + pageRectRight
+ "," + pageRectBottom
+ ") c=("
238 + cssPageRectLeft
+ "," + cssPageRectTop
+ "," + cssPageRectRight
+ ","
239 + cssPageRectBottom
+ ") z=" + zoomFactor
;