diff options
-rw-r--r-- | goo/GooCheckedOps.h | 11 | ||||
-rw-r--r-- | poppler/Gfx.cc | 21 |
2 files changed, 22 insertions, 10 deletions
diff --git a/goo/GooCheckedOps.h b/goo/GooCheckedOps.h index 3da6b337..5eedf34b 100644 --- a/goo/GooCheckedOps.h +++ b/goo/GooCheckedOps.h @@ -5,6 +5,7 @@ // This file is licensed under the GPLv2 or later // // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de> +// Copyright (C) 2019 LE GARREC Vincent <legarrec.vincent@gmail.com> // //======================================================================== @@ -12,6 +13,7 @@ #define GOO_CHECKED_OPS_H #include <climits> +#include <limits> inline bool checkedAssign(long long lz, int *z) { static_assert(LLONG_MAX > INT_MAX, "Need type larger than int to perform overflow checks."); @@ -46,4 +48,13 @@ inline bool checkedMultiply(int x, int y, int *z) { #endif } +template<typename T> inline T safeAverage(T a, T b) { + static_assert(std::numeric_limits<long long>::max() > std::numeric_limits<T>::max(), + "The max of long long type must be larger to perform overflow checks."); + static_assert(std::numeric_limits<long long>::min() < std::numeric_limits<T>::min(), + "The min of long long type must be smaller to perform overflow checks."); + + return static_cast<T>((static_cast<long long>(a) + static_cast<long long>(b)) / 2); +} + #endif // GOO_CHECKED_OPS_H diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc index ef57e512..8bf141e9 100644 --- a/poppler/Gfx.cc +++ b/poppler/Gfx.cc @@ -41,6 +41,7 @@ // Copyright (C) 2017, 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich // Copyright (C) 2018, 2019 Adam Reichold <adam.reichold@t-online.de> // Copyright (C) 2018 Denis Onishchenko <denis.onischenko@gmail.com> +// Copyright (C) 2019 LE GARREC Vincent <legarrec.vincent@gmail.com> // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git @@ -2809,7 +2810,7 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) { // use the average of the colors of the two sides of the region for (k = 0; k < nComps; ++k) { - color0.c[k] = (color0.c[k] + color1.c[k]) / 2; + color0.c[k] = safeAverage(color0.c[k], color1.c[k]); } // compute the coordinates of the point on the t axis; then @@ -3114,7 +3115,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) { // use the average of the colors at the two circles for (k = 0; k < nComps; ++k) { - colorA.c[k] = (colorA.c[k] + colorB.c[k]) / 2; + colorA.c[k] = safeAverage(colorA.c[k], colorB.c[k]); } state->setFillColor(&colorA); if (out->useFillColorStop()) @@ -3357,9 +3358,9 @@ void Gfx::gouraudFillTriangle(double x0, double y0, GfxColor *color0, x20 = 0.5 * (x2 + x0); y20 = 0.5 * (y2 + y0); for (i = 0; i < nComps; ++i) { - color01.c[i] = (color0->c[i] + color1->c[i]) / 2; - color12.c[i] = (color1->c[i] + color2->c[i]) / 2; - color20.c[i] = (color2->c[i] + color0->c[i]) / 2; + color01.c[i] = safeAverage(color0->c[i], color1->c[i]); + color12.c[i] = safeAverage(color1->c[i], color2->c[i]); + color20.c[i] = safeAverage(color2->c[i], color0->c[i]); } gouraudFillTriangle(x0, y0, color0, x01, y01, &color01, x20, y20, &color20, nComps, depth + 1, path); @@ -3584,22 +3585,22 @@ void Gfx::fillPatch(const GfxPatch *patch, int colorComps, int patchColorComps, for (i = 0; i < patchColorComps; ++i) { patch00.color[0][0].c[i] = patch->color[0][0].c[i]; patch00.color[0][1].c[i] = (patch->color[0][0].c[i] + - patch->color[0][1].c[i]) / 2; + patch->color[0][1].c[i]) / 2.; patch01.color[0][0].c[i] = patch00.color[0][1].c[i]; patch01.color[0][1].c[i] = patch->color[0][1].c[i]; patch01.color[1][1].c[i] = (patch->color[0][1].c[i] + - patch->color[1][1].c[i]) / 2; + patch->color[1][1].c[i]) / 2.; patch11.color[0][1].c[i] = patch01.color[1][1].c[i]; patch11.color[1][1].c[i] = patch->color[1][1].c[i]; patch11.color[1][0].c[i] = (patch->color[1][1].c[i] + - patch->color[1][0].c[i]) / 2; + patch->color[1][0].c[i]) / 2.; patch10.color[1][1].c[i] = patch11.color[1][0].c[i]; patch10.color[1][0].c[i] = patch->color[1][0].c[i]; patch10.color[0][0].c[i] = (patch->color[1][0].c[i] + - patch->color[0][0].c[i]) / 2; + patch->color[0][0].c[i]) / 2.; patch00.color[1][0].c[i] = patch10.color[0][0].c[i]; patch00.color[1][1].c[i] = (patch00.color[1][0].c[i] + - patch01.color[1][1].c[i]) / 2; + patch01.color[1][1].c[i]) / 2.; patch01.color[1][0].c[i] = patch00.color[1][1].c[i]; patch11.color[0][0].c[i] = patch00.color[1][1].c[i]; patch10.color[0][1].c[i] = patch00.color[1][1].c[i]; |