diff options
| author | Paul Eggert | 2019-06-29 16:46:16 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-06-29 16:49:19 -0700 |
| commit | f5b2fd5e46505d68850fb8532357d4218f067c48 (patch) | |
| tree | 42ed471fc063a552e84a49a42d31e192b1d4fa21 /src | |
| parent | 0b2841f9fb0ffd8514b0fb99c5673adad6b07abb (diff) | |
| download | emacs-f5b2fd5e46505d68850fb8532357d4218f067c48.tar.gz emacs-f5b2fd5e46505d68850fb8532357d4218f067c48.zip | |
Pacify gcc and other image rotation tweaks
* src/image.c: No need to include <float.h> as lisp.h does that.
(matrix3x3_copy): Remove; no longer needed.
(divide_double): New function, to avoid undefined behavior
when dividing by zero on non-IEEE hosts.
(image_set_transform): Simplify transformation computation
by avoiding the need to copy a matrix. Pacify
gcc 9 -Wdouble-promotion and -Wmaybe-uninitialized.
Avoid unnecessary assignment of width and height.
Improve error reporting for unsupported native image rotation.
Diffstat (limited to 'src')
| -rw-r--r-- | src/image.c | 153 |
1 files changed, 79 insertions, 74 deletions
diff --git a/src/image.c b/src/image.c index 02dd95caeda..5b02c6a9534 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -57,10 +57,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 57 | #include <sys/types.h> | 57 | #include <sys/types.h> |
| 58 | #endif /* HAVE_SYS_TYPES_H */ | 58 | #endif /* HAVE_SYS_TYPES_H */ |
| 59 | 59 | ||
| 60 | #ifdef HAVE_NATIVE_TRANSFORMS | ||
| 61 | #include <float.h> /* for FLT_MIN */ | ||
| 62 | #endif | ||
| 63 | |||
| 64 | #ifdef HAVE_WINDOW_SYSTEM | 60 | #ifdef HAVE_WINDOW_SYSTEM |
| 65 | #include TERM_HEADER | 61 | #include TERM_HEADER |
| 66 | #endif /* HAVE_WINDOW_SYSTEM */ | 62 | #endif /* HAVE_WINDOW_SYSTEM */ |
| @@ -2054,12 +2050,6 @@ compute_image_size (size_t width, size_t height, | |||
| 2054 | typedef double matrix3x3[3][3]; | 2050 | typedef double matrix3x3[3][3]; |
| 2055 | 2051 | ||
| 2056 | static void | 2052 | static void |
| 2057 | matrix3x3_copy (matrix3x3 a, matrix3x3 b) | ||
| 2058 | { | ||
| 2059 | memcpy (b, a, sizeof (matrix3x3)); | ||
| 2060 | } | ||
| 2061 | |||
| 2062 | static void | ||
| 2063 | matrix3x3_mult (matrix3x3 a, matrix3x3 b, matrix3x3 result) | 2053 | matrix3x3_mult (matrix3x3 a, matrix3x3 b, matrix3x3 result) |
| 2064 | { | 2054 | { |
| 2065 | for (int i = 0; i < 3; i++) | 2055 | for (int i = 0; i < 3; i++) |
| @@ -2089,6 +2079,16 @@ compute_image_rotation (struct image *img, double *rotation) | |||
| 2089 | *rotation = XFIXNUM (reduced_angle); | 2079 | *rotation = XFIXNUM (reduced_angle); |
| 2090 | } | 2080 | } |
| 2091 | 2081 | ||
| 2082 | static double | ||
| 2083 | divide_double (double a, double b) | ||
| 2084 | { | ||
| 2085 | #if !IEEE_FLOATING_POINT | ||
| 2086 | if (b == 0) | ||
| 2087 | return DBL_MAX; | ||
| 2088 | #endif | ||
| 2089 | return a / b; | ||
| 2090 | } | ||
| 2091 | |||
| 2092 | static void | 2092 | static void |
| 2093 | image_set_transform (struct frame *f, struct image *img) | 2093 | image_set_transform (struct frame *f, struct image *img) |
| 2094 | { | 2094 | { |
| @@ -2103,8 +2103,6 @@ image_set_transform (struct frame *f, struct image *img) | |||
| 2103 | return; | 2103 | return; |
| 2104 | # endif | 2104 | # endif |
| 2105 | 2105 | ||
| 2106 | matrix3x3 matrix = { [0][0] = 1, [1][1] = 1, [2][2] = 1 }; | ||
| 2107 | |||
| 2108 | /* Determine size. */ | 2106 | /* Determine size. */ |
| 2109 | int width, height; | 2107 | int width, height; |
| 2110 | compute_image_size (img->width, img->height, img->spec, &width, &height); | 2108 | compute_image_size (img->width, img->height, img->spec, &width, &height); |
| @@ -2115,99 +2113,106 @@ image_set_transform (struct frame *f, struct image *img) | |||
| 2115 | 2113 | ||
| 2116 | /* Perform scale transformation. */ | 2114 | /* Perform scale transformation. */ |
| 2117 | 2115 | ||
| 2118 | double xscale = (double) width / img->width; | 2116 | matrix3x3 matrix |
| 2119 | double yscale = (double) height / img->height; | 2117 | = { |
| 2120 | |||
| 2121 | # if defined USE_CAIRO || defined HAVE_XRENDER | 2118 | # if defined USE_CAIRO || defined HAVE_XRENDER |
| 2122 | /* Avoid division by zero. */ | 2119 | [0][0] = divide_double (img->width, width), |
| 2123 | xscale = max (xscale, FLT_MIN); | 2120 | [1][1] = divide_double (img->height, height), |
| 2124 | matrix3x3 tmp, rm = | ||
| 2125 | { [0][0] = 1.0 / xscale, [1][1] = 1.0 / yscale, [2][2] = 1 }; | ||
| 2126 | matrix3x3_mult (rm, matrix, tmp); | ||
| 2127 | # elif defined HAVE_NTGUI || defined HAVE_NS | 2121 | # elif defined HAVE_NTGUI || defined HAVE_NS |
| 2128 | matrix3x3 tmp, rm = { [0][0] = xscale, [1][1] = yscale, [2][2] = 1 }; | 2122 | [0][0] = divide_double (width, img->width), |
| 2129 | matrix3x3_mult (matrix, rm, tmp); | 2123 | [1][1] = divide_double (height, img->height), |
| 2124 | # else | ||
| 2125 | [0][0] = 1, [1][1] = 1, | ||
| 2130 | # endif | 2126 | # endif |
| 2127 | [2][2] = 1 }; | ||
| 2131 | img->width = width; | 2128 | img->width = width; |
| 2132 | img->height = height; | 2129 | img->height = height; |
| 2133 | 2130 | ||
| 2134 | /* Perform rotation transformation. */ | 2131 | /* Perform rotation transformation. */ |
| 2135 | 2132 | ||
| 2136 | int cos_r, sin_r; | 2133 | int rotate_flag = -1; |
| 2137 | if (rotation == 0) | 2134 | if (rotation == 0) |
| 2138 | matrix3x3_copy (tmp, matrix); | 2135 | rotate_flag = 0; |
| 2139 | else if (rotation == 90 || rotation == 180 || rotation == 270) | 2136 | else |
| 2140 | { | 2137 | { |
| 2138 | # if (defined USE_CAIRO || defined HAVE_XRENDER \ | ||
| 2139 | || defined HAVE_NTGUI || defined HAVE_NS) | ||
| 2140 | int cos_r, sin_r; | ||
| 2141 | if (rotation == 90) | 2141 | if (rotation == 90) |
| 2142 | { | 2142 | { |
| 2143 | width = img->height; | 2143 | width = img->height; |
| 2144 | height = img->width; | 2144 | height = img->width; |
| 2145 | |||
| 2146 | cos_r = 0; | 2145 | cos_r = 0; |
| 2147 | sin_r = 1; | 2146 | sin_r = 1; |
| 2147 | rotate_flag = 1; | ||
| 2148 | } | 2148 | } |
| 2149 | else if (rotation == 180) | 2149 | else if (rotation == 180) |
| 2150 | { | 2150 | { |
| 2151 | width = img->width; | ||
| 2152 | height = img->height; | ||
| 2153 | |||
| 2154 | cos_r = -1; | 2151 | cos_r = -1; |
| 2155 | sin_r = 0; | 2152 | sin_r = 0; |
| 2153 | rotate_flag = 1; | ||
| 2156 | } | 2154 | } |
| 2157 | else if (rotation == 270) | 2155 | else if (rotation == 270) |
| 2158 | { | 2156 | { |
| 2159 | width = img->height; | 2157 | width = img->height; |
| 2160 | height = img->width; | 2158 | height = img->width; |
| 2161 | |||
| 2162 | cos_r = 0; | 2159 | cos_r = 0; |
| 2163 | sin_r = -1; | 2160 | sin_r = -1; |
| 2161 | rotate_flag = 1; | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | if (0 < rotate_flag) | ||
| 2165 | { | ||
| 2166 | # if defined USE_CAIRO || defined HAVE_XRENDER | ||
| 2167 | /* 1. Translate so (0, 0) is in the center of the image. */ | ||
| 2168 | matrix3x3 t | ||
| 2169 | = { [0][0] = 1, | ||
| 2170 | [1][1] = 1, | ||
| 2171 | [2][0] = img->width*.5, [2][1] = img->height*.5, [2][2] = 1 }; | ||
| 2172 | matrix3x3 u; | ||
| 2173 | matrix3x3_mult (t, matrix, u); | ||
| 2174 | |||
| 2175 | /* 2. Rotate. */ | ||
| 2176 | matrix3x3 rot = { [0][0] = cos_r, [0][1] = -sin_r, | ||
| 2177 | [1][0] = sin_r, [1][1] = cos_r, | ||
| 2178 | [2][2] = 1 }; | ||
| 2179 | matrix3x3 v; | ||
| 2180 | matrix3x3_mult (rot, u, v); | ||
| 2181 | |||
| 2182 | /* 3. Translate back. */ | ||
| 2183 | t[2][0] = width * -.5; | ||
| 2184 | t[2][1] = height * -.5; | ||
| 2185 | matrix3x3_mult (t, v, matrix); | ||
| 2186 | # else | ||
| 2187 | /* 1. Translate so (0, 0) is in the center of the image. */ | ||
| 2188 | matrix3x3 t | ||
| 2189 | = { [0][0] = 1, | ||
| 2190 | [1][1] = 1, | ||
| 2191 | [2][0] = img->width*-.5, [2][1] = img->height*-.5, [2][2] = 1 }; | ||
| 2192 | matrix3x3 u; | ||
| 2193 | matrix3x3_mult (matrix, t, u); | ||
| 2194 | |||
| 2195 | /* 2. Rotate. */ | ||
| 2196 | matrix3x3 rot = { [0][0] = cos_r, [0][1] = sin_r, | ||
| 2197 | [1][0] = -sin_r, [1][1] = cos_r, | ||
| 2198 | [2][2] = 1 }; | ||
| 2199 | matrix3x3 v; | ||
| 2200 | matrix3x3_mult (u, rot, v); | ||
| 2201 | |||
| 2202 | /* 3. Translate back. */ | ||
| 2203 | t[2][0] = width * .5; | ||
| 2204 | t[2][1] = height * .5; | ||
| 2205 | matrix3x3_mult (v, t, matrix); | ||
| 2206 | # endif | ||
| 2207 | img->width = width; | ||
| 2208 | img->height = height; | ||
| 2164 | } | 2209 | } |
| 2165 | # if defined USE_CAIRO || defined HAVE_XRENDER | ||
| 2166 | /* 1. Translate so (0, 0) is in the center of the image. */ | ||
| 2167 | matrix3x3 t | ||
| 2168 | = { [0][0] = 1, | ||
| 2169 | [1][1] = 1, | ||
| 2170 | [2][0] = img->width * .5, [2][1] = img->height * .5, [2][2] = 1 }; | ||
| 2171 | matrix3x3 tmp2; | ||
| 2172 | matrix3x3_mult (t, tmp, tmp2); | ||
| 2173 | |||
| 2174 | /* 2. Rotate. */ | ||
| 2175 | matrix3x3 rot = { [0][0] = cos_r, [0][1] = -sin_r, | ||
| 2176 | [1][0] = sin_r, [1][1] = cos_r, | ||
| 2177 | [2][2] = 1 }; | ||
| 2178 | matrix3x3 tmp3; | ||
| 2179 | matrix3x3_mult (rot, tmp2, tmp3); | ||
| 2180 | |||
| 2181 | /* 3. Translate back. */ | ||
| 2182 | t[2][0] = width * -.5; | ||
| 2183 | t[2][1] = height * -.5; | ||
| 2184 | matrix3x3_mult (t, tmp3, matrix); | ||
| 2185 | # elif defined HAVE_NTGUI || defined HAVE_NS | ||
| 2186 | /* 1. Translate so (0, 0) is in the center of the image. */ | ||
| 2187 | matrix3x3 t | ||
| 2188 | = { [0][0] = 1, | ||
| 2189 | [1][1] = 1, | ||
| 2190 | [2][0] = -img->width * .5, [2][1] = -img->height * .5, [2][2] = 1 }; | ||
| 2191 | matrix3x3 tmp2; | ||
| 2192 | matrix3x3_mult (tmp, t, tmp2); | ||
| 2193 | |||
| 2194 | /* 2. Rotate. */ | ||
| 2195 | matrix3x3 rot = { [0][0] = cos_r, [0][1] = sin_r, | ||
| 2196 | [1][0] = -sin_r, [1][1] = cos_r, | ||
| 2197 | [2][2] = 1 }; | ||
| 2198 | matrix3x3 tmp3; | ||
| 2199 | matrix3x3_mult (tmp2, rot, tmp3); | ||
| 2200 | |||
| 2201 | /* 3. Translate back. */ | ||
| 2202 | t[2][0] = width * .5; | ||
| 2203 | t[2][1] = height * .5; | ||
| 2204 | matrix3x3_mult (tmp3, t, matrix); | ||
| 2205 | # endif | 2210 | # endif |
| 2206 | img->width = width; | ||
| 2207 | img->height = height; | ||
| 2208 | } | 2211 | } |
| 2209 | else | 2212 | |
| 2210 | image_error ("Native image rotation supports only multiples of 90 degrees"); | 2213 | if (rotate_flag < 0) |
| 2214 | image_error ("No native support for rotation by %g degrees", | ||
| 2215 | make_float (rotation)); | ||
| 2211 | 2216 | ||
| 2212 | # if defined (HAVE_NS) | 2217 | # if defined (HAVE_NS) |
| 2213 | /* Under NS the transform is applied to the drawing surface at | 2218 | /* Under NS the transform is applied to the drawing surface at |