|
23 | 23 | using namespace std; |
24 | 24 |
|
25 | 25 |
|
26 | | -/// Calculate optimal resolution for a given requested pixel dimension |
27 | | -void View::calculateResolution( const std::vector<unsigned int>& dimensions, |
28 | | - const unsigned int requested_size ){ |
29 | | - |
30 | | - int j; |
31 | | - |
32 | | - // Make sure we have a minimum size |
33 | | - unsigned int rs = (requested_size<min_size) ? min_size : requested_size; |
34 | | - |
35 | | - // Find the resolution level closest but higher than the requested size |
36 | | - for( j=0; j<(int)max_resolutions; j++ ){ |
37 | | - if( dimensions[j] < rs ) break; |
38 | | - } |
39 | | - |
40 | | - // Invert to convert to IIP resolutions (0=smallest) - note that we implicitly add 1 to get resolution higher than |
41 | | - j = max_resolutions-j; |
42 | | - |
43 | | - // Limit j to the maximum resolution |
44 | | - if( j < 0 ) j = 0; |
45 | | - if( j > (int)(max_resolutions-1) ) j = max_resolutions - 1; |
46 | | - |
47 | | - // Only update value of resolution if our calculated resolution is greater than value that has already been set |
48 | | - if( j > resolution ) resolution = j; |
49 | | -} |
50 | | - |
51 | 26 |
|
52 | 27 | /// Calculate the optimal resolution and the size of this resolution for the requested view, |
53 | 28 | /// taking into account any maximum size settings |
54 | 29 | unsigned int View::getResolution( const std::vector<unsigned int>& widths, const std::vector<unsigned int>& heights ){ |
55 | 30 |
|
56 | | - // Initialize our resolution to smallest available before calculating |
57 | | - resolution = 0; |
| 31 | + int level; |
58 | 32 |
|
| 33 | + // Get requested size - takes into account max size |
59 | 34 | vector<unsigned int> requested_size = View::getRequestSize(); |
60 | | - View::calculateResolution( widths, round((float)requested_size[0]/(float)view_width) ); |
61 | | - View::calculateResolution( heights, round((float)requested_size[1]/(float)view_height) ); |
62 | 35 |
|
63 | | - res_width = widths[max_resolutions-resolution-1]; |
64 | | - res_height = heights[max_resolutions-resolution-1]; |
| 36 | + // Start from the smallest resolution size (last item in size array) |
| 37 | + for( level = (int) max_resolutions - 1; level >= 0; level-- ){ |
| 38 | + |
| 39 | + // Scaling factor (assume powers of 2) |
| 40 | + unsigned int factor = 1 << level; |
| 41 | + |
| 42 | + // For some reason, this needs to be done in 2 steps with fw, fh first, otherwise rounding errors occur :-/ |
| 43 | + float fw = (float) width * view_width; |
| 44 | + // For full width or height requests use the real level size. |
| 45 | + // Also add an epsilon to avoid floating-point rounding errors when using floor() |
| 46 | + unsigned int scaled_width = (view_width == 1.0) ? widths[level] : floor( (fw/factor) + numeric_limits<float>::epsilon() ); |
| 47 | + float fh = (float) height * view_height; |
| 48 | + unsigned int scaled_height = (view_height == 1.0) ? heights[level] : floor( (fh/factor) + numeric_limits<float>::epsilon() ); |
| 49 | + |
| 50 | + // Note that we add 1px for the first checks to take into account differences between levels that have rounded up or down |
| 51 | + if( scaled_width <= (widths[level]+1) && scaled_height <= (heights[level]+1) && |
| 52 | + // Skip check and avoid potential rounding errors if only a single dimension has been requested |
| 53 | + ( requested_width == 0 ? true : scaled_width >= requested_size[0] ) && |
| 54 | + ( requested_height == 0 ? true : scaled_height >= requested_size[1] ) ){ |
| 55 | + break; // Lowest resolution where conditions are met |
| 56 | + } |
| 57 | + } |
| 58 | + // Clamp to 0 if no matches |
| 59 | + if( level < 0 ) level = 0; |
| 60 | + |
| 61 | + // Size of image at this level |
| 62 | + res_width = widths[level]; |
| 63 | + res_height = heights[level]; |
| 64 | + |
| 65 | + // Store resolution as IIP resolution (0=smallest) |
| 66 | + resolution = max_resolutions - level - 1; |
65 | 67 |
|
66 | 68 | // Check if we need to limit to a smaller resolution due to our max size limit |
67 | 69 | float scale = getScale(); |
@@ -119,29 +121,29 @@ float View::getScale(){ |
119 | 121 | } |
120 | 122 |
|
121 | 123 |
|
122 | | -void View::setViewLeft( float x ) { |
| 124 | +void View::setViewLeft( double x ) { |
123 | 125 | if( x > 1.0 ) view_left = 1.0; |
124 | 126 | else if( x < 0.0 ) view_left = 0.0; |
125 | 127 | else view_left = x; |
126 | 128 | } |
127 | 129 |
|
128 | 130 |
|
129 | | -void View::setViewTop( float y ) { |
| 131 | +void View::setViewTop( double y ) { |
130 | 132 | if( y > 1.0 ) view_top = 1.0; |
131 | 133 | else if( y < 0.0 ) view_top = 0.0; |
132 | 134 | else view_top = y; |
133 | 135 | } |
134 | 136 |
|
135 | 137 |
|
136 | | -void View::setViewWidth( float w ) { |
| 138 | +void View::setViewWidth( double w ) { |
137 | 139 | // Sanity check |
138 | 140 | if( w > 1.0 ) view_width = 1.0; |
139 | 141 | else if( w < 0.0 ) view_width = 0.0; |
140 | 142 | else view_width = w; |
141 | 143 | } |
142 | 144 |
|
143 | 145 |
|
144 | | -void View::setViewHeight( float h ) { |
| 146 | +void View::setViewHeight( double h ) { |
145 | 147 | // Sanity check |
146 | 148 | if( h > 1.0 ) view_height = 1.0; |
147 | 149 | else if( h < 0.0 ) view_height = 0.0; |
|
0 commit comments