Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
B
BigDataViewer_Core_Extension
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
BioinformaticDataCompression
BigDataViewer_Core_Extension
Commits
266160b8
Commit
266160b8
authored
Jul 6, 2020
by
Tobias Pietzsch
Browse files
Options
Downloads
Patches
Plain Diff
WIP ScreenScales class manages resizing, interval requests, and scale suggestion
parent
d5dadbf1
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/main/java/bdv/viewer/render/MultiResolutionRenderer.java
+26
-165
26 additions, 165 deletions
src/main/java/bdv/viewer/render/MultiResolutionRenderer.java
src/main/java/bdv/viewer/render/ScreenScales.java
+198
-0
198 additions, 0 deletions
src/main/java/bdv/viewer/render/ScreenScales.java
with
224 additions
and
165 deletions
src/main/java/bdv/viewer/render/MultiResolutionRenderer.java
+
26
−
165
View file @
266160b8
...
@@ -31,9 +31,8 @@ package bdv.viewer.render;
...
@@ -31,9 +31,8 @@ package bdv.viewer.render;
import
bdv.cache.CacheControl
;
import
bdv.cache.CacheControl
;
import
bdv.util.MovingAverage
;
import
bdv.util.MovingAverage
;
import
bdv.viewer.ViewerState
;
import
bdv.viewer.ViewerState
;
import
bdv.viewer.render.ScreenScales.ScreenScale
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.ExecutorService
;
import
net.imglib2.Dimensions
;
import
net.imglib2.FinalDimensions
;
import
net.imglib2.Interval
;
import
net.imglib2.Interval
;
import
net.imglib2.RandomAccessibleInterval
;
import
net.imglib2.RandomAccessibleInterval
;
import
net.imglib2.Volatile
;
import
net.imglib2.Volatile
;
...
@@ -44,7 +43,6 @@ import net.imglib2.ui.PainterThread;
...
@@ -44,7 +43,6 @@ import net.imglib2.ui.PainterThread;
import
net.imglib2.ui.RenderTarget
;
import
net.imglib2.ui.RenderTarget
;
import
net.imglib2.util.Intervals
;
import
net.imglib2.util.Intervals
;
/**
/**
* A renderer that uses a coarse-to-fine rendering scheme. First, a small target
* A renderer that uses a coarse-to-fine rendering scheme. First, a small target
* image at a fraction of the canvas resolution is rendered. Then, increasingly
* image at a fraction of the canvas resolution is rendered. Then, increasingly
...
@@ -115,84 +113,9 @@ public class MultiResolutionRenderer
...
@@ -115,84 +113,9 @@ public class MultiResolutionRenderer
private
final
long
[]
iobudget
=
new
long
[]
{
100
l
*
1000000
l
,
10
l
*
1000000
l
};
private
final
long
[]
iobudget
=
new
long
[]
{
100
l
*
1000000
l
,
10
l
*
1000000
l
};
/**
/**
* Scale factors from the {@link #display viewer canvas} to the
* TODO javadoc
* {@code screenImages}.
*
* A scale factor of 1 means 1 pixel in the screen image is displayed as 1
* pixel on the canvas, a scale factor of 0.5 means 1 pixel in the screen
* image is displayed as 2 pixel on the canvas, etc.
*/
private
final
double
[]
screenScaleFactors
;
static
class
ScreenScale
{
/**
* The width of the target image at this ScreenScale.
*/
final
int
w
;
/**
* The height of the target image at this ScreenScale.
*/
*/
final
int
h
;
private
final
ScreenScales
screenScales
;
/**
* The transformation from viewer to target image coordinates at this ScreenScale.
*/
final
AffineTransform3D
scale
;
private
final
double
screenToViewerScale
;
public
ScreenScale
(
final
int
screenW
,
final
int
screenH
,
final
double
screenToViewerScale
)
{
this
.
screenToViewerScale
=
screenToViewerScale
;
w
=
(
int
)
Math
.
ceil
(
screenToViewerScale
*
screenW
);
h
=
(
int
)
Math
.
ceil
(
screenToViewerScale
*
screenH
);
scale
=
new
AffineTransform3D
();
scale
.
set
(
screenToViewerScale
,
0
,
0
);
scale
.
set
(
screenToViewerScale
,
1
,
1
);
scale
.
set
(
0.5
*
screenToViewerScale
-
0.5
,
0
,
3
);
scale
.
set
(
0.5
*
screenToViewerScale
-
0.5
,
1
,
3
);
}
Interval
requestedScreenInterval
=
null
;
public
void
requestInterval
(
final
Interval
screenInterval
)
{
requestedScreenInterval
=
requestedScreenInterval
==
null
?
screenInterval
:
Intervals
.
union
(
requestedScreenInterval
,
screenInterval
);
}
public
Interval
pullScreenInterval
()
{
final
Interval
interval
=
requestedScreenInterval
;
requestedScreenInterval
=
null
;
return
interval
;
}
public
double
estimateIntervalRenderNanos
(
final
double
renderNanosPerPixel
)
{
return
renderNanosPerPixel
*
Intervals
.
numElements
(
scaleScreenInterval
(
requestedScreenInterval
)
);
}
public
Interval
scaleScreenInterval
(
final
Interval
requestedScreenInterval
)
{
// This is equivalent to
// Intervals.intersect( new FinalInterval( w, h ), Intervals.smallestContainingInterval( Intervals.scale( requestedScreenInterval, screenToViewerScale ) ) );
return
Intervals
.
createMinMax
(
Math
.
max
(
0
,
(
int
)
Math
.
floor
(
requestedScreenInterval
.
min
(
0
)
*
screenToViewerScale
)
),
Math
.
max
(
0
,
(
int
)
Math
.
floor
(
requestedScreenInterval
.
min
(
1
)
*
screenToViewerScale
)
),
Math
.
min
(
w
-
1
,
(
int
)
Math
.
ceil
(
requestedScreenInterval
.
max
(
0
)
*
screenToViewerScale
)
),
Math
.
min
(
h
-
1
,
(
int
)
Math
.
ceil
(
requestedScreenInterval
.
max
(
1
)
*
screenToViewerScale
)
)
);
}
}
private
final
ScreenScale
[]
screenScales
;
private
int
screenW
;
private
int
screenH
;
/**
/**
* Maintains arrays for intermediate per-source render images and masks.
* Maintains arrays for intermediate per-source render images and masks.
...
@@ -321,15 +244,14 @@ public class MultiResolutionRenderer
...
@@ -321,15 +244,14 @@ public class MultiResolutionRenderer
this
.
painterThread
=
painterThread
;
this
.
painterThread
=
painterThread
;
projector
=
null
;
projector
=
null
;
currentScreenScaleIndex
=
-
1
;
currentScreenScaleIndex
=
-
1
;
this
.
screenScaleFactors
=
screenScaleFactors
.
clone
();
screenScales
=
new
ScreenScales
(
screenScaleFactors
);
this
.
screenScales
=
new
ScreenScale
[
screenScaleFactors
.
length
];
renderStorage
=
new
RenderStorage
();
renderStorage
=
new
RenderStorage
();
this
.
targetRenderNanos
=
targetRenderNanos
;
this
.
targetRenderNanos
=
targetRenderNanos
;
renderNanosPerPixelAndSource
=
new
MovingAverage
(
3
);
renderNanosPerPixelAndSource
=
new
MovingAverage
(
3
);
renderNanosPerPixelAndSource
.
init
(
500
);
renderNanosPerPixelAndSource
.
init
(
500
);
requestedScreenScaleIndex
=
screenScales
.
length
-
1
;
requestedScreenScaleIndex
=
screenScales
.
size
()
-
1
;
renderingMayBeCancelled
=
false
;
renderingMayBeCancelled
=
false
;
this
.
cacheControl
=
cacheControl
;
this
.
cacheControl
=
cacheControl
;
newFrameRequest
=
false
;
newFrameRequest
=
false
;
...
@@ -343,26 +265,6 @@ public class MultiResolutionRenderer
...
@@ -343,26 +265,6 @@ public class MultiResolutionRenderer
accumulateProjectorFactory
);
accumulateProjectorFactory
);
}
}
/**
* Check whether the size of the display component was changed and
* recreate {@link #screenScales} accordingly.
*
* @return whether the size was changed.
*/
private
boolean
checkResize
()
{
final
int
newScreenW
=
display
.
getWidth
();
final
int
newScreenH
=
display
.
getHeight
();
if
(
newScreenW
!=
screenW
||
newScreenH
!=
screenH
)
{
screenW
=
newScreenW
;
screenH
=
newScreenH
;
for
(
int
i
=
0
;
i
<
screenScales
.
length
;
++
i
)
screenScales
[
i
]
=
new
ScreenScale
(
screenW
,
screenH
,
screenScaleFactors
[
i
]
);
return
true
;
}
return
false
;
}
/**
/**
* Render image at the {@link #requestedScreenScaleIndex requested screen
* Render image at the {@link #requestedScreenScaleIndex requested screen
...
@@ -370,10 +272,12 @@ public class MultiResolutionRenderer
...
@@ -370,10 +272,12 @@ public class MultiResolutionRenderer
*/
*/
public
boolean
paint
(
final
ViewerState
viewerState
)
public
boolean
paint
(
final
ViewerState
viewerState
)
{
{
if
(
display
.
getWidth
()
<=
0
||
display
.
getHeight
()
<=
0
)
int
screenW
=
display
.
getWidth
();
int
screenH
=
display
.
getHeight
();
if
(
screenW
<=
0
||
screenH
<=
0
)
return
false
;
return
false
;
final
boolean
resized
=
checkResize
(
);
final
boolean
resized
=
screenScales
.
checkResize
(
screenW
,
screenH
);
final
boolean
newFrame
;
final
boolean
newFrame
;
final
boolean
newInterval
;
final
boolean
newInterval
;
...
@@ -405,7 +309,8 @@ public class MultiResolutionRenderer
...
@@ -405,7 +309,8 @@ public class MultiResolutionRenderer
cacheControl
.
prepareNextFrame
();
cacheControl
.
prepareNextFrame
();
currentViewerState
=
viewerState
.
snapshot
();
currentViewerState
=
viewerState
.
snapshot
();
currentNumVisibleSources
=
currentViewerState
.
getVisibleAndPresentSources
().
size
();
currentNumVisibleSources
=
currentViewerState
.
getVisibleAndPresentSources
().
size
();
requestedScreenScaleIndex
=
suggestScreenScale
(
new
FinalDimensions
(
screenW
,
screenH
),
currentNumVisibleSources
);
final
double
renderNanosPerPixel
=
renderNanosPerPixelAndSource
.
getAverage
()
*
currentNumVisibleSources
;
requestedScreenScaleIndex
=
screenScales
.
suggestScreenScale
(
renderNanosPerPixel
,
targetRenderNanos
);
}
}
final
boolean
createProjector
=
newFrame
||
(
requestedScreenScaleIndex
!=
currentScreenScaleIndex
);
final
boolean
createProjector
=
newFrame
||
(
requestedScreenScaleIndex
!=
currentScreenScaleIndex
);
...
@@ -423,13 +328,13 @@ public class MultiResolutionRenderer
...
@@ -423,13 +328,13 @@ public class MultiResolutionRenderer
{
{
if
(
createProjector
)
if
(
createProjector
)
{
{
final
ScreenScale
screenScale
=
screenScales
[
requestedScreenScaleIndex
]
;
final
ScreenScale
screenScale
=
screenScales
.
get
(
requestedScreenScaleIndex
)
;
renderResult
=
display
.
getReusableRenderResult
();
renderResult
=
display
.
getReusableRenderResult
();
renderResult
.
init
(
screenScale
.
w
,
screenScale
.
h
);
renderResult
.
init
(
screenScale
.
w
idth
()
,
screenScale
.
h
eight
()
);
renderResult
.
setScaleFactor
(
screenScale
Factors
[
requestedScreenScaleIndex
]
);
renderResult
.
setScaleFactor
(
screenScale
.
scale
()
);
renderStorage
.
checkRenewData
(
screenScales
[
0
]
.
w
,
screenScales
[
0
]
.
h
,
currentNumVisibleSources
);
renderStorage
.
checkRenewData
(
screenScales
.
get
(
0
)
.
w
idth
()
,
screenScales
.
get
(
0
)
.
h
eight
()
,
currentNumVisibleSources
);
projector
=
createProjector
(
currentViewerState
,
requestedScreenScaleIndex
,
renderResult
.
getScreenImage
(),
0
,
0
);
projector
=
createProjector
(
currentViewerState
,
requestedScreenScaleIndex
,
renderResult
.
getScreenImage
(),
0
,
0
);
requestNewFrameIfIncomplete
=
projectorFactory
.
requestNewFrameIfIncomplete
();
requestNewFrameIfIncomplete
=
projectorFactory
.
requestNewFrameIfIncomplete
();
renderingMayBeCancelled
=
!
newFrame
;
renderingMayBeCancelled
=
!
newFrame
;
...
@@ -514,9 +419,7 @@ public class MultiResolutionRenderer
...
@@ -514,9 +419,7 @@ public class MultiResolutionRenderer
{
{
if
(
renderingMayBeCancelled
&&
projector
!=
null
)
if
(
renderingMayBeCancelled
&&
projector
!=
null
)
projector
.
cancel
();
projector
.
cancel
();
for
(
ScreenScale
screenScale
:
screenScales
)
screenScales
.
clearRequestedIntervals
();
if
(
screenScale
!=
null
)
screenScale
.
pullScreenInterval
();
intervalMode
=
false
;
intervalMode
=
false
;
newFrameRequest
=
true
;
newFrameRequest
=
true
;
painterThread
.
requestRepaint
();
painterThread
.
requestRepaint
();
...
@@ -528,8 +431,7 @@ public class MultiResolutionRenderer
...
@@ -528,8 +431,7 @@ public class MultiResolutionRenderer
{
{
if
(
projector
!=
null
)
if
(
projector
!=
null
)
projector
.
cancel
();
projector
.
cancel
();
for
(
final
ScreenScale
screenScale
:
screenScales
)
screenScales
.
requestInterval
(
screenInterval
);
screenScale
.
requestInterval
(
screenInterval
);
intervalMode
=
true
;
intervalMode
=
true
;
newIntervalRequest
=
true
;
newIntervalRequest
=
true
;
painterThread
.
requestRepaint
();
painterThread
.
requestRepaint
();
...
@@ -538,20 +440,6 @@ public class MultiResolutionRenderer
...
@@ -538,20 +440,6 @@ public class MultiResolutionRenderer
requestRepaint
();
requestRepaint
();
}
}
private
int
suggestScreenScale
(
final
Dimensions
screenSize
,
final
int
numSources
)
{
final
double
intervalRenderNanos
=
renderNanosPerPixelAndSource
.
getAverage
()
*
Intervals
.
numElements
(
screenSize
)
*
numSources
;
for
(
int
i
=
0
;
i
<
screenScaleFactors
.
length
-
1
;
i
++
)
{
final
double
s
=
screenScaleFactors
[
i
];
final
double
renderTime
=
intervalRenderNanos
*
s
*
s
;
if
(
renderTime
<=
targetRenderNanos
)
return
i
;
}
return
screenScaleFactors
.
length
-
1
;
}
/**
/**
* DON'T USE THIS.
* DON'T USE THIS.
* <p>
* <p>
...
@@ -579,7 +467,7 @@ public class MultiResolutionRenderer
...
@@ -579,7 +467,7 @@ public class MultiResolutionRenderer
*/
*/
// CacheIoTiming.getIoTimeBudget().clear(); // clear time budget such that prefetching doesn't wait for loading blocks.
// CacheIoTiming.getIoTimeBudget().clear(); // clear time budget such that prefetching doesn't wait for loading blocks.
final
AffineTransform3D
screenScaleTransform
=
screenScales
[
screenScaleIndex
]
.
scale
;
final
AffineTransform3D
screenScaleTransform
=
screenScales
.
get
(
screenScaleIndex
)
.
scale
Transform
()
;
final
AffineTransform3D
screenTransform
=
viewerState
.
getViewerTransform
();
final
AffineTransform3D
screenTransform
=
viewerState
.
getViewerTransform
();
screenTransform
.
preConcatenate
(
screenScaleTransform
);
screenTransform
.
preConcatenate
(
screenScaleTransform
);
screenTransform
.
translate
(
-
offsetX
,
-
offsetY
,
0
);
screenTransform
.
translate
(
-
offsetX
,
-
offsetY
,
0
);
...
@@ -593,12 +481,7 @@ public class MultiResolutionRenderer
...
@@ -593,12 +481,7 @@ public class MultiResolutionRenderer
return
projector
;
return
projector
;
}
}
// =========== intervals ==========================================================================================
// =========== intervals =============
private
RenderResult
currentRenderResult
;
private
RenderResult
currentRenderResult
;
...
@@ -636,20 +519,12 @@ public class MultiResolutionRenderer
...
@@ -636,20 +519,12 @@ public class MultiResolutionRenderer
if
(
newInterval
)
if
(
newInterval
)
{
{
cacheControl
.
prepareNextFrame
();
cacheControl
.
prepareNextFrame
();
final
double
renderNanosPerPixel
=
currentNumVisibleSources
*
renderNanosPerPixelAndSource
.
getAverage
();
final
double
renderNanosPerPixel
=
renderNanosPerPixelAndSource
.
getAverage
()
*
currentNumVisibleSources
;
for
(
int
i
=
currentScreenScaleIndex
;
i
<
screenScales
.
length
;
i
++
)
requestedIntervalScaleIndex
=
screenScales
.
suggestIntervalScreenScale
(
renderNanosPerPixel
,
targetRenderNanos
,
currentScreenScaleIndex
);
{
final
double
renderTime
=
screenScales
[
i
].
estimateIntervalRenderNanos
(
renderNanosPerPixel
);
if
(
renderTime
<=
targetRenderNanos
)
{
requestedIntervalScaleIndex
=
i
;
break
;
}
}
}
}
createProjector
=
newInterval
||
(
requestedIntervalScaleIndex
!=
currentIntervalScaleIndex
);
createProjector
=
newInterval
||
(
requestedIntervalScaleIndex
!=
currentIntervalScaleIndex
);
screenScale
=
screenScales
[
requestedIntervalScaleIndex
]
;
screenScale
=
screenScales
.
get
(
requestedIntervalScaleIndex
)
;
requestedScreenInterval
=
screenScale
.
pullScreenInterval
();
requestedScreenInterval
=
screenScale
.
pullScreenInterval
();
if
(
createProjector
)
if
(
createProjector
)
...
@@ -658,14 +533,14 @@ public class MultiResolutionRenderer
...
@@ -658,14 +533,14 @@ public class MultiResolutionRenderer
intervalResult
.
init
(
intervalResult
.
init
(
(
int
)
interval
.
dimension
(
0
),
(
int
)
interval
.
dimension
(
0
),
(
int
)
interval
.
dimension
(
1
)
);
(
int
)
interval
.
dimension
(
1
)
);
final
double
intervalScale
=
screenScale
.
sc
reenToViewerSc
ale
;
final
double
intervalScale
=
screenScale
.
scale
()
;
intervalResult
.
setScaleFactor
(
intervalScale
);
intervalResult
.
setScaleFactor
(
intervalScale
);
final
double
offsetX
=
interval
.
min
(
0
);
final
double
offsetX
=
interval
.
min
(
0
);
final
double
offsetY
=
interval
.
min
(
1
);
final
double
offsetY
=
interval
.
min
(
1
);
projector
=
createProjector
(
currentViewerState
,
requestedIntervalScaleIndex
,
intervalResult
.
getScreenImage
(),
offsetX
,
offsetY
);
projector
=
createProjector
(
currentViewerState
,
requestedIntervalScaleIndex
,
intervalResult
.
getScreenImage
(),
offsetX
,
offsetY
);
final
Interval
targetInterval
=
screenScales
[
currentScreenScaleIndex
]
.
scaleScreenInterval
(
requestedScreenInterval
);
final
Interval
targetInterval
=
screenScales
.
get
(
currentScreenScaleIndex
)
.
scaleScreenInterval
(
requestedScreenInterval
);
final
double
relativeScale
=
screenScale
Factors
[
currentScreenScaleIndex
]
/
intervalScale
;
final
double
relativeScale
=
screenScale
s
.
get
(
currentScreenScaleIndex
).
scale
()
/
intervalScale
;
final
double
tx
=
interval
.
min
(
0
)
*
relativeScale
;
final
double
tx
=
interval
.
min
(
0
)
*
relativeScale
;
final
double
ty
=
interval
.
min
(
1
)
*
relativeScale
;
final
double
ty
=
interval
.
min
(
1
)
*
relativeScale
;
intervalRenderData
=
new
IntervalRenderData
(
targetInterval
,
tx
,
ty
);
intervalRenderData
=
new
IntervalRenderData
(
targetInterval
,
tx
,
ty
);
...
@@ -679,6 +554,7 @@ public class MultiResolutionRenderer
...
@@ -679,6 +554,7 @@ public class MultiResolutionRenderer
synchronized
(
this
)
synchronized
(
this
)
{
{
// if rendering was not cancelled...
if
(
success
)
if
(
success
)
{
{
if
(
createProjector
)
if
(
createProjector
)
...
@@ -729,19 +605,4 @@ public class MultiResolutionRenderer
...
@@ -729,19 +605,4 @@ public class MultiResolutionRenderer
requestedIntervalScaleIndex
=
intervalScaleIndex
;
requestedIntervalScaleIndex
=
intervalScaleIndex
;
painterThread
.
requestRepaint
();
painterThread
.
requestRepaint
();
}
}
private
Interval
scaleScreenInterval
(
final
Interval
requestedScreenInterval
,
final
int
intervalScaleIndex
)
{
final
int
clipW
=
screenScales
[
intervalScaleIndex
].
w
;
final
int
clipH
=
screenScales
[
intervalScaleIndex
].
h
;
final
double
scale
=
screenScaleFactors
[
intervalScaleIndex
];
// This is equivalent to
// Intervals.intersect( new FinalInterval( clipW, clipH ), Intervals.smallestContainingInterval( Intervals.scale( requestedScreenInterval, scale ) ) );
return
Intervals
.
createMinMax
(
Math
.
max
(
0
,
(
int
)
Math
.
floor
(
requestedScreenInterval
.
min
(
0
)
*
scale
)
),
Math
.
max
(
0
,
(
int
)
Math
.
floor
(
requestedScreenInterval
.
min
(
1
)
*
scale
)
),
Math
.
min
(
clipW
-
1
,
(
int
)
Math
.
ceil
(
requestedScreenInterval
.
max
(
0
)
*
scale
)
),
Math
.
min
(
clipH
-
1
,
(
int
)
Math
.
ceil
(
requestedScreenInterval
.
max
(
1
)
*
scale
)
)
);
}
}
}
This diff is collapsed.
Click to expand it.
src/main/java/bdv/viewer/render/ScreenScales.java
0 → 100644
+
198
−
0
View file @
266160b8
package
bdv.viewer.render
;
import
java.util.ArrayList
;
import
java.util.List
;
import
net.imglib2.Interval
;
import
net.imglib2.realtransform.AffineTransform3D
;
import
net.imglib2.util.Intervals
;
public
class
ScreenScales
{
private
final
List
<
ScreenScale
>
screenScales
;
private
int
screenW
=
0
;
private
int
screenH
=
0
;
/**
* @param screenScaleFactors
* Scale factors from the viewer canvas to screen images of
* different resolutions. A scale factor of 1 means 1 pixel in
* the screen image is displayed as 1 pixel on the canvas, a
* scale factor of 0.5 means 1 pixel in the screen image is
* displayed as 2 pixel on the canvas, etc.
*/
public
ScreenScales
(
final
double
[]
screenScaleFactors
)
{
screenScales
=
new
ArrayList
<>();
for
(
double
scale
:
screenScaleFactors
)
screenScales
.
add
(
new
ScreenScale
(
scale
)
);
}
/**
* Check whether the screen size was changed and revise {@link #screenScales} accordingly.
*
* @return whether the size was changed.
*/
public
boolean
checkResize
(
final
int
newScreenW
,
final
int
newScreenH
)
{
if
(
newScreenW
!=
screenW
||
newScreenH
!=
screenH
)
{
screenW
=
newScreenW
;
screenH
=
newScreenH
;
screenScales
.
forEach
(
s
->
s
.
resize
(
screenW
,
screenH
)
);
return
true
;
}
return
false
;
}
public
ScreenScale
get
(
final
int
index
)
{
return
screenScales
.
get
(
index
);
}
public
int
size
()
{
return
screenScales
.
size
();
}
public
int
suggestScreenScale
(
final
double
renderNanosPerPixel
,
final
double
targetRenderNanos
)
{
for
(
int
i
=
0
;
i
<
screenScales
.
size
()
-
1
;
i
++
)
{
final
double
renderTime
=
screenScales
.
get
(
i
).
estimateRenderNanos
(
renderNanosPerPixel
);
if
(
renderTime
<=
targetRenderNanos
)
return
i
;
}
return
screenScales
.
size
()
-
1
;
}
public
int
suggestIntervalScreenScale
(
final
double
renderNanosPerPixel
,
final
double
targetRenderNanos
,
final
int
minScreenScaleIndex
)
{
for
(
int
i
=
minScreenScaleIndex
;
i
<
screenScales
.
size
()
-
1
;
i
++
)
{
final
double
renderTime
=
screenScales
.
get
(
i
).
estimateIntervalRenderNanos
(
renderNanosPerPixel
);
if
(
renderTime
<=
targetRenderNanos
)
return
i
;
}
return
screenScales
.
size
()
-
1
;
}
public
void
requestInterval
(
final
Interval
screenInterval
)
{
screenScales
.
forEach
(
s
->
s
.
requestInterval
(
screenInterval
)
);
}
public
void
clearRequestedIntervals
()
{
screenScales
.
forEach
(
ScreenScale:
:
pullScreenInterval
);
}
public
static
class
ScreenScale
{
/**
* Scale factor from the viewer coordinates to target image of this screen scale.
*/
private
final
double
scale
;
/**
* The width of the target image at this ScreenScale.
*/
private
int
w
=
0
;
/**
* The height of the target image at this ScreenScale.
*/
private
int
h
=
0
;
/**
* The transformation from viewer to target image coordinates at this ScreenScale.
*/
private
final
AffineTransform3D
scaleTransform
=
new
AffineTransform3D
();
/**
* Pending interval request.
* This is in viewer coordinates.
* To transform to target coordinates of this scale, use {@link #scaleScreenInterval}.
*/
private
Interval
requestedScreenInterval
=
null
;
/**
* @param scale
* Scale factor from the viewer coordinates to target image of this screen scale/
*/
ScreenScale
(
final
double
scale
)
{
this
.
scale
=
scale
;
}
void
resize
(
final
int
screenW
,
final
int
screenH
)
{
w
=
(
int
)
Math
.
ceil
(
scale
*
screenW
);
h
=
(
int
)
Math
.
ceil
(
scale
*
screenH
);
scaleTransform
.
set
(
scale
,
0
,
0
);
scaleTransform
.
set
(
scale
,
1
,
1
);
scaleTransform
.
set
(
0.5
*
scale
-
0.5
,
0
,
3
);
scaleTransform
.
set
(
0.5
*
scale
-
0.5
,
1
,
3
);
requestedScreenInterval
=
null
;
}
double
estimateRenderNanos
(
final
double
renderNanosPerPixel
)
{
return
renderNanosPerPixel
*
w
*
h
;
}
public
void
requestInterval
(
final
Interval
screenInterval
)
{
requestedScreenInterval
=
requestedScreenInterval
==
null
?
screenInterval
:
Intervals
.
union
(
requestedScreenInterval
,
screenInterval
);
}
public
Interval
pullScreenInterval
()
{
final
Interval
interval
=
requestedScreenInterval
;
requestedScreenInterval
=
null
;
return
interval
;
}
public
double
estimateIntervalRenderNanos
(
final
double
renderNanosPerPixel
)
{
return
renderNanosPerPixel
*
Intervals
.
numElements
(
scaleScreenInterval
(
requestedScreenInterval
)
);
}
public
Interval
scaleScreenInterval
(
final
Interval
requestedScreenInterval
)
{
// This is equivalent to
// Intervals.intersect( new FinalInterval( w, h ), Intervals.smallestContainingInterval( Intervals.scale( requestedScreenInterval, screenToViewerScale ) ) );
return
Intervals
.
createMinMax
(
Math
.
max
(
0
,
(
int
)
Math
.
floor
(
requestedScreenInterval
.
min
(
0
)
*
scale
)
),
Math
.
max
(
0
,
(
int
)
Math
.
floor
(
requestedScreenInterval
.
min
(
1
)
*
scale
)
),
Math
.
min
(
w
-
1
,
(
int
)
Math
.
ceil
(
requestedScreenInterval
.
max
(
0
)
*
scale
)
),
Math
.
min
(
h
-
1
,
(
int
)
Math
.
ceil
(
requestedScreenInterval
.
max
(
1
)
*
scale
)
)
);
}
public
int
width
()
{
return
w
;
}
public
int
height
()
{
return
h
;
}
public
double
scale
()
{
return
scale
;
}
public
AffineTransform3D
scaleTransform
()
{
return
scaleTransform
;
}
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment