diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..224864f --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,101 @@ +WarningsAsErrors: '*' +HeaderFilterRegex: '.*\.hpp' +FormatStyle: 'file' +Checks: > + -*, + bugprone-*, + -bugprone-easily-swappable-parameters, + -bugprone-forward-declaration-namespace, + -bugprone-forward-declaration-namespace, + -bugprone-macro-parentheses, + -bugprone-narrowing-conversions, + -bugprone-branch-clone, + -bugprone-assignment-in-if-condition, + concurrency-*, + -concurrency-mt-unsafe, + cppcoreguidelines-*, + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-avoid-magic-numbers, + -cppcoreguidelines-pro-bounds-constant-array-index, + -cppcoreguidelines-avoid-const-or-ref-data-members, + -cppcoreguidelines-non-private-member-variables-in-classes, + -cppcoreguidelines-avoid-goto, + -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + -cppcoreguidelines-avoid-do-while, + -cppcoreguidelines-avoid-non-const-global-variables, + -cppcoreguidelines-special-member-functions, + -cppcoreguidelines-explicit-virtual-functions, + -cppcoreguidelines-avoid-c-arrays, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-narrowing-conversions, + -cppcoreguidelines-pro-type-union-access, + -cppcoreguidelines-pro-type-member-init, + -cppcoreguidelines-macro-usage, + -cppcoreguidelines-macro-to-enum, + -cppcoreguidelines-init-variables, + -cppcoreguidelines-pro-type-cstyle-cast, + -cppcoreguidelines-pro-type-vararg, + -cppcoreguidelines-pro-type-reinterpret-cast, + google-global-names-in-headers, + -google-readability-casting, + google-runtime-operator, + misc-*, + -misc-unused-parameters, + -misc-no-recursion, + -misc-non-private-member-variables-in-classes, + -misc-include-cleaner, + -misc-use-anonymous-namespace, + -misc-const-correctness, + modernize-*, + -modernize-return-braced-init-list, + -modernize-use-trailing-return-type, + -modernize-use-using, + -modernize-use-override, + -modernize-avoid-c-arrays, + -modernize-macro-to-enum, + -modernize-loop-convert, + -modernize-use-nodiscard, + -modernize-pass-by-value, + -modernize-use-auto, + performance-*, + -performance-avoid-endl, + -performance-unnecessary-value-param, + portability-std-allocator-const, + readability-*, + -readability-function-cognitive-complexity, + -readability-function-size, + -readability-identifier-length, + -readability-magic-numbers, + -readability-uppercase-literal-suffix, + -readability-braces-around-statements, + -readability-redundant-access-specifiers, + -readability-else-after-return, + -readability-container-data-pointer, + -readability-implicit-bool-conversion, + -readability-avoid-nested-conditional-operator, + -readability-redundant-member-init, + -readability-redundant-string-init, + -readability-avoid-const-params-in-decls, + -readability-named-parameter, + -readability-convert-member-functions-to-static, + -readability-qualified-auto, + -readability-make-member-function-const, + -readability-isolate-declaration, + -readability-inconsistent-declaration-parameter-name, + -clang-diagnostic-error, + +CheckOptions: + performance-for-range-copy.WarnOnAllAutoCopies: true + performance-inefficient-string-concatenation.StrictMode: true + readability-braces-around-statements.ShortStatementLines: 0 + readability-identifier-naming.ClassCase: CamelCase + readability-identifier-naming.ClassIgnoredRegexp: I.* + readability-identifier-naming.ClassPrefix: C # We can't use regex here?!?!?!? + readability-identifier-naming.EnumCase: CamelCase + readability-identifier-naming.EnumPrefix: e + readability-identifier-naming.EnumConstantCase: UPPER_CASE + readability-identifier-naming.FunctionCase: camelBack + readability-identifier-naming.NamespaceCase: CamelCase + readability-identifier-naming.NamespacePrefix: N + readability-identifier-naming.StructPrefix: S + readability-identifier-naming.StructCase: CamelCase diff --git a/CMakeLists.txt b/CMakeLists.txt index 958b7c0..9657410 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,16 @@ set(LIBDIR ${CMAKE_INSTALL_FULL_LIBDIR}) configure_file(hyprgraphics.pc.in hyprgraphics.pc @ONLY) set(CMAKE_CXX_STANDARD 26) +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) +# -Wno-missing-braces for clang +add_compile_options( + -Wall + -Wextra + -Wpedantic + -Wno-unused-parameter + -Wno-unused-value + -Wno-missing-field-initializers + -Wno-missing-braces) if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) message(STATUS "Configuring hyprgraphics in Debug") diff --git a/include/hyprgraphics/color/Color.hpp b/include/hyprgraphics/color/Color.hpp index e4f4ee5..70f749a 100644 --- a/include/hyprgraphics/color/Color.hpp +++ b/include/hyprgraphics/color/Color.hpp @@ -34,7 +34,7 @@ namespace Hyprgraphics { // per-component division XYZ operator/(const XYZ& other) const { - return {x / other.x, y / other.y, z / other.z}; + return {.x = x / other.x, .y = y / other.y, .z = z / other.z}; } }; diff --git a/src/color/Color.cpp b/src/color/Color.cpp index d123431..2e39d4b 100644 --- a/src/color/Color.cpp +++ b/src/color/Color.cpp @@ -9,7 +9,7 @@ static double gammaToLinear(const double in) { } static double linearToGamma(const double in) { - return in >= 0.0031308 ? 1.055 * std::pow(in, 0.41666666666) - 0.055 : 12.92 * in; + return in >= 0.0031308 ? (1.055 * std::pow(in, 0.41666666666)) - 0.055 : 12.92 * in; } static double hueToRgb(double p, double q, double t) { @@ -18,11 +18,11 @@ static double hueToRgb(double p, double q, double t) { if (t > 1) t -= 1; if (t < 1.0 / 6.0) - return p + (q - p) * 6.0 * t; + return p + ((q - p) * 6.0 * t); if (t < 1.0 / 2.0) return q; if (t < 2.0 / 3.0) - return p + (q - p) * (2.0 / 3.0 - t) * 6.0; + return p + ((q - p) * (2.0 / 3.0 - t) * 6.0); return p; } @@ -45,9 +45,9 @@ CMatrix3 Hyprgraphics::CMatrix3::invert() const { CColor::XYZ Hyprgraphics::CMatrix3::operator*(const CColor::XYZ& value) const { return CColor::XYZ{ - m[0][0] * value.x + m[0][1] * value.y + m[0][2] * value.z, // - m[1][0] * value.x + m[1][1] * value.y + m[1][2] * value.z, // - m[2][0] * value.x + m[2][1] * value.y + m[2][2] * value.z, // + .x = (m[0][0] * value.x) + (m[0][1] * value.y) + (m[0][2] * value.z), // + .y = (m[1][0] * value.x) + (m[1][1] * value.y) + (m[1][2] * value.z), // + .z = (m[2][0] * value.x) + (m[2][1] * value.y) + (m[2][2] * value.z), // }; } @@ -78,18 +78,18 @@ const CMatrix3& CMatrix3::identity() { CColor::XYZ Hyprgraphics::xy2xyz(const CColor::xy& xy) { if (xy.y == 0.0) - return {0.0, 0.0, 0.0}; + return {.x = 0.0, .y = 0.0, .z = 0.0}; - return {xy.x / xy.y, 1.0, (1.0 - xy.x - xy.y) / xy.y}; + return {.x = xy.x / xy.y, .y = 1.0, .z = (1.0 - xy.x - xy.y) / xy.y}; } -CMatrix3 Bradford = CMatrix3(std::array, 3>{ +static CMatrix3 Bradford = CMatrix3(std::array, 3>{ 0.8951, 0.2664, -0.1614, // -0.7502, 1.7135, 0.0367, // 0.0389, -0.0685, 1.0296, // }); -CMatrix3 BradfordInv = Bradford.invert(); +static CMatrix3 BradfordInv = Bradford.invert(); CMatrix3 Hyprgraphics::adaptWhite(const CColor::xy& src, const CColor::xy& dst) { if (src == dst) @@ -138,10 +138,8 @@ Hyprgraphics::CColor::CColor() { ; } -Hyprgraphics::CColor::CColor(const SSRGB& rgb) { - r = rgb.r; - g = rgb.g; - b = rgb.b; +Hyprgraphics::CColor::CColor(const SSRGB& rgb) : r(rgb.r), g(rgb.g), b(rgb.b) { + ; } Hyprgraphics::CColor::CColor(const SHSL& hsl) { @@ -150,22 +148,22 @@ Hyprgraphics::CColor::CColor(const SHSL& hsl) { g = hsl.l; b = hsl.l; } else { - const double q = hsl.l < 0.5 ? hsl.l * (1.0 + hsl.s) : hsl.l + hsl.s - hsl.l * hsl.s; - const double p = 2.0 * hsl.l - q; - r = hueToRgb(p, q, hsl.h + 1.0 / 3.0); + const double q = hsl.l < 0.5 ? hsl.l * (1.0 + hsl.s) : hsl.l + hsl.s - (hsl.l * hsl.s); + const double p = (2.0 * hsl.l) - q; + r = hueToRgb(p, q, hsl.h + (1.0 / 3.0)); g = hueToRgb(p, q, hsl.h); - b = hueToRgb(p, q, hsl.h - 1.0 / 3.0); + b = hueToRgb(p, q, hsl.h - (1.0 / 3.0)); } } Hyprgraphics::CColor::CColor(const SOkLab& lab) { - const double l = std::pow(lab.l + lab.a * 0.3963377774 + lab.b * 0.2158037573, 3); - const double m = std::pow(lab.l + lab.a * (-0.1055613458) + lab.b * (-0.0638541728), 3); - const double s = std::pow(lab.l + lab.a * (-0.0894841775) + lab.b * (-1.2914855480), 3); + const double l = std::pow(lab.l + (lab.a * 0.3963377774) + (lab.b * 0.2158037573), 3); + const double m = std::pow(lab.l + (lab.a * (-0.1055613458)) + (lab.b * (-0.0638541728)), 3); + const double s = std::pow(lab.l + (lab.a * (-0.0894841775)) + (lab.b * (-1.2914855480)), 3); - r = linearToGamma(l * 4.0767416621 + m * -3.3077115913 + s * 0.2309699292); - g = linearToGamma(l * (-1.2684380046) + m * 2.6097574011 + s * (-0.3413193965)); - b = linearToGamma(l * (-0.0041960863) + m * (-0.7034186147) + s * 1.7076147010); + r = linearToGamma((l * 4.0767416621) + (m * -3.3077115913) + (s * 0.2309699292)); + g = linearToGamma((l * (-1.2684380046)) + (m * 2.6097574011) + (s * (-0.3413193965))); + b = linearToGamma((l * (-0.0041960863)) + (m * (-0.7034186147)) + (s * 1.7076147010)); } Hyprgraphics::CColor::SSRGB Hyprgraphics::CColor::asRgb() const { @@ -177,7 +175,7 @@ Hyprgraphics::CColor::SSRGB Hyprgraphics::CColor::asRgb() const { } Hyprgraphics::CColor::SHSL Hyprgraphics::CColor::asHSL() const { - const double vmax = std::max(std::max(r, g), b), vmin = std::min(std::min(r, g), b); + const double vmax = std::max({r, g, b}), vmin = std::min({r, g, b}); double h = 0, s = 0, l = (vmax + vmin) / 2.0; if (vmax == vmin) { @@ -212,13 +210,13 @@ Hyprgraphics::CColor::SOkLab Hyprgraphics::CColor::asOkLab() const { const double linG = gammaToLinear(g); const double linB = gammaToLinear(b); - const double l = std::cbrtf(0.4122214708 * linR + 0.5363325363 * linG + 0.0514459929 * linB); - const double m = std::cbrtf(0.2119034982 * linR + 0.6806995451 * linG + 0.1073969566 * linB); - const double s = std::cbrtf(0.0883024619 * linR + 0.2817188376 * linG + 0.6299787005 * linB); + const double l = std::cbrtf((0.4122214708 * linR) + (0.5363325363 * linG) + (0.0514459929 * linB)); + const double m = std::cbrtf((0.2119034982 * linR) + (0.6806995451 * linG) + (0.1073969566 * linB)); + const double s = std::cbrtf((0.0883024619 * linR) + (0.2817188376 * linG) + (0.6299787005 * linB)); return Hyprgraphics::CColor::SOkLab{ - .l = l * 0.2104542553 + m * 0.7936177850 + s * (-0.0040720468), - .a = l * 1.9779984951 + m * (-2.4285922050) + s * 0.4505937099, - .b = l * 0.0259040371 + m * 0.7827717662 + s * (-0.8086757660), + .l = (l * 0.2104542553) + (m * 0.7936177850) + (s * (-0.0040720468)), + .a = (l * 1.9779984951) + (m * (-2.4285922050)) + (s * 0.4505937099), + .b = (l * 0.0259040371) + (m * 0.7827717662) + (s * (-0.8086757660)), }; } diff --git a/src/image/Image.cpp b/src/image/Image.cpp index 6844f90..d7aec3e 100644 --- a/src/image/Image.cpp +++ b/src/image/Image.cpp @@ -45,7 +45,7 @@ Hyprgraphics::CImage::CImage(const std::string& path) : filepath(path) { magic_load(handle, nullptr); const auto type_str = std::string(magic_file(handle, path.c_str())); - const auto first_word = type_str.substr(0, type_str.find(" ")); + const auto first_word = type_str.substr(0, type_str.find(' ')); if (first_word == "PNG") { CAIROSURFACE = PNG::createSurfaceFromPNG(path); diff --git a/src/image/formats/Bmp.cpp b/src/image/formats/Bmp.cpp index a2ee0a7..759cb12 100644 --- a/src/image/formats/Bmp.cpp +++ b/src/image/formats/Bmp.cpp @@ -3,11 +3,12 @@ #include #include #include +#include #include #include #include #include -#include +#include class BmpHeader { public: @@ -34,7 +35,7 @@ class BmpHeader { file.seekg(0, std::ios::beg); file.read(reinterpret_cast(&format), sizeof(format)); - if (!(format[0] == 66 && format[1] == 77)) + if (format[0] != 66 || format[1] != 77) return "Unable to parse bitmap header: wrong bmp file type"; file.read(reinterpret_cast(&sizeOfFile), sizeof(sizeOfFile)); @@ -75,9 +76,9 @@ static void reflectImage(unsigned char* image, uint32_t numberOfRows, int stride std::vector temp; temp.resize(stride); while (rowStart < rowEnd) { - memcpy(&temp[0], &image[rowStart * stride], stride); - memcpy(&image[rowStart * stride], &image[rowEnd * stride], stride); - memcpy(&image[rowEnd * stride], &temp[0], stride); + memcpy(&temp[0], &image[static_cast(rowStart * stride)], stride); + memcpy(&image[static_cast(rowStart * stride)], &image[static_cast(rowEnd * stride)], stride); + memcpy(&image[static_cast(rowEnd * stride)], &temp[0], stride); rowStart++; rowEnd--; } @@ -109,7 +110,7 @@ std::expected BMP::createSurfaceFromBMP(const std cairo_format_t format = CAIRO_FORMAT_ARGB32; int stride = cairo_format_stride_for_width(format, bitmapHeader.width); - unsigned char* imageData = (unsigned char*)malloc(bitmapHeader.height * stride); + unsigned char* imageData = (unsigned char*)malloc(static_cast(bitmapHeader.height * stride)); if (bitmapHeader.numberOfBitPerPixel == 24) convertRgbToArgb(bitmapImageStream, imageData, bitmapHeader.height * stride); @@ -122,4 +123,4 @@ std::expected BMP::createSurfaceFromBMP(const std bitmapImageStream.close(); reflectImage(imageData, bitmapHeader.height, stride); return cairo_image_surface_create_for_data(imageData, format, bitmapHeader.width, bitmapHeader.height, stride); -} \ No newline at end of file +} diff --git a/src/image/formats/Jpeg.cpp b/src/image/formats/Jpeg.cpp index 6ba39bc..32e7d52 100644 --- a/src/image/formats/Jpeg.cpp +++ b/src/image/formats/Jpeg.cpp @@ -1,5 +1,6 @@ #include "Jpeg.hpp" +#include #include #include #include @@ -47,7 +48,7 @@ std::expected JPEG::createSurfaceFromJPEG(const s JSAMPROW rowRead; while (decompressStruct.output_scanline < decompressStruct.output_height) { - const auto PROW = CAIRODATA + (decompressStruct.output_scanline * CAIROSTRIDE); + const auto PROW = CAIRODATA + (static_cast(decompressStruct.output_scanline * CAIROSTRIDE)); rowRead = PROW; jpeg_read_scanlines(&decompressStruct, &rowRead, 1); } diff --git a/src/image/formats/Png.cpp b/src/image/formats/Png.cpp index 9651da8..ee2d18b 100644 --- a/src/image/formats/Png.cpp +++ b/src/image/formats/Png.cpp @@ -1,5 +1,6 @@ #include "Png.hpp" #include +#include #include #include #include @@ -30,7 +31,7 @@ std::expected PNG::createSurfaceFromPNG(const std spng_set_png_buffer(ctx, PNGCONTENT.data(), PNGCONTENT.size()); - spng_ihdr ihdr{0}; + spng_ihdr ihdr{.width = 0}; if (int ret = spng_get_ihdr(ctx, &ihdr); ret) return std::unexpected(std::string{"loading png: spng_get_ihdr failed: "} + spng_strerror(ret)); @@ -55,7 +56,7 @@ std::expected PNG::createSurfaceFromPNG(const std if (!succeededDecode && ret == SPNG_EBUFSIZ) { // hack, but I don't know why decoded_image_size is sometimes wrong - imageLength = ihdr.height * ihdr.width * 4 /* FIXME: this is wrong if we doing >32bpp!!!! */; + imageLength = static_cast(ihdr.height * ihdr.width * 4) /* FIXME: this is wrong if we doing >32bpp!!!! */; imageData = (uint8_t*)realloc(imageData, imageLength); ret = spng_decode_image(ctx, imageData, imageLength, SPNG_FMT_RGBA8, 0); @@ -90,4 +91,4 @@ std::expected PNG::createSurfaceFromPNG(const std return std::unexpected("loading png: cairo failed"); return CAIROSURFACE; -} \ No newline at end of file +} diff --git a/src/image/formats/Webp.cpp b/src/image/formats/Webp.cpp index df2710c..b18df75 100644 --- a/src/image/formats/Webp.cpp +++ b/src/image/formats/Webp.cpp @@ -1,5 +1,6 @@ #include "Webp.hpp" +#include #include #include #include @@ -46,7 +47,7 @@ std::expected WEBP::createSurfaceFromWEBP(const s config.options.no_fancy_upsampling = 1; config.output.u.RGBA.rgba = CAIRODATA; config.output.u.RGBA.stride = CAIROSTRIDE; - config.output.u.RGBA.size = CAIROSTRIDE * HEIGHT; + config.output.u.RGBA.size = static_cast(CAIROSTRIDE * HEIGHT); config.output.is_external_memory = 1; config.output.width = WIDTH; config.output.height = HEIGHT; diff --git a/tests/image.cpp b/tests/image.cpp index 42a1082..1c1a654 100644 --- a/tests/image.cpp +++ b/tests/image.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,7 +7,7 @@ using namespace Hyprgraphics; -bool tryLoadImage(const std::string& path) { +static bool tryLoadImage(const std::string& path) { auto image = CImage(path); if (!image.success()) { @@ -23,8 +24,9 @@ bool tryLoadImage(const std::string& path) { std::filesystem::create_directory(TEST_DIR); std::string name = image.getMime(); - std::replace(name.begin(), name.end(), '/', '_'); + std::ranges::replace(name, '/', '_'); + //NOLINTNEXTLINE return cairo_surface_write_to_png(image.cairoSurface()->cairo(), (TEST_DIR + "/" + name + ".png").c_str()) == CAIRO_STATUS_SUCCESS; }