From 8171ad65cd9f170dd9f72d1256415ebd34979d36 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Fri, 28 May 2021 07:14:14 -0400
Subject: [PATCH 1/2] common: Extract point into a common struct

This is generic enough that it can be moved into the Common class for
reuse.
---
 src/common/CMakeLists.txt                     |  1 +
 src/common/point.h                            | 57 +++++++++++++++++++
 .../hle/service/hid/controllers/gesture.h     | 36 +++---------
 3 files changed, 65 insertions(+), 29 deletions(-)
 create mode 100644 src/common/point.h

diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index eafb96b0b..7a4d9e354 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -154,6 +154,7 @@ add_library(common STATIC
     param_package.cpp
     param_package.h
     parent_of_member.h
+    point.h
     quaternion.h
     ring_buffer.h
     scm_rev.cpp
diff --git a/src/common/point.h b/src/common/point.h
new file mode 100644
index 000000000..c0a52ad8d
--- /dev/null
+++ b/src/common/point.h
@@ -0,0 +1,57 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <type_traits>
+
+namespace Common {
+
+// Represents a point within a 2D space.
+template <typename T>
+struct Point {
+    static_assert(std::is_arithmetic_v<T>, "T must be an arithmetic type!");
+
+    T x{};
+    T y{};
+
+#define ARITHMETIC_OP(op, compound_op)                                                             \
+    friend constexpr Point operator op(const Point& lhs, const Point& rhs) noexcept {              \
+        return {                                                                                   \
+            .x = static_cast<T>(lhs.x op rhs.x),                                                   \
+            .y = static_cast<T>(lhs.y op rhs.y),                                                   \
+        };                                                                                         \
+    }                                                                                              \
+    friend constexpr Point operator op(const Point& lhs, T value) noexcept {                       \
+        return {                                                                                   \
+            .x = static_cast<T>(lhs.x op value),                                                   \
+            .y = static_cast<T>(lhs.y op value),                                                   \
+        };                                                                                         \
+    }                                                                                              \
+    friend constexpr Point operator op(T value, const Point& rhs) noexcept {                       \
+        return {                                                                                   \
+            .x = static_cast<T>(value op rhs.x),                                                   \
+            .y = static_cast<T>(value op rhs.y),                                                   \
+        };                                                                                         \
+    }                                                                                              \
+    friend constexpr Point& operator compound_op(Point& lhs, const Point& rhs) noexcept {          \
+        lhs.x = static_cast<T>(lhs.x op rhs.x);                                                    \
+        lhs.y = static_cast<T>(lhs.y op rhs.y);                                                    \
+        return lhs;                                                                                \
+    }                                                                                              \
+    friend constexpr Point& operator compound_op(Point& lhs, T value) noexcept {                   \
+        lhs.x = static_cast<T>(lhs.x op value);                                                    \
+        lhs.y = static_cast<T>(lhs.y op value);                                                    \
+        return lhs;                                                                                \
+    }
+    ARITHMETIC_OP(+, +=)
+    ARITHMETIC_OP(-, -=)
+    ARITHMETIC_OP(*, *=)
+    ARITHMETIC_OP(/, /=)
+#undef ARITHMETIC_OP
+
+    friend constexpr bool operator==(const Point&, const Point&) = default;
+};
+
+} // namespace Common
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index eecfeaad5..7e7ae6625 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -7,6 +7,7 @@
 #include <array>
 #include "common/bit_field.h"
 #include "common/common_types.h"
+#include "common/point.h"
 #include "core/frontend/input.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
 
@@ -63,44 +64,21 @@ private:
     };
     static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size");
 
-    template <typename T>
-    struct Point {
-        T x{};
-        T y{};
-
-        friend Point operator+(const Point& lhs, const Point& rhs) {
-            return {
-                .x = lhs.x + rhs.x,
-                .y = lhs.y + rhs.y,
-            };
-        }
-
-        friend Point operator-(const Point& lhs, const Point& rhs) {
-            return {
-                .x = lhs.x - rhs.x,
-                .y = lhs.y - rhs.y,
-            };
-        }
-
-        friend bool operator==(const Point&, const Point&) = default;
-    };
-    static_assert(sizeof(Point<s32_le>) == 8, "Point is an invalid size");
-
     struct GestureState {
         s64_le sampling_number;
         s64_le sampling_number2;
         s64_le detection_count;
         TouchType type;
         Direction direction;
-        Point<s32_le> pos;
-        Point<s32_le> delta;
+        Common::Point<s32_le> pos;
+        Common::Point<s32_le> delta;
         f32 vel_x;
         f32 vel_y;
         Attribute attributes;
         f32 scale;
         f32 rotation_angle;
         s32_le point_count;
-        std::array<Point<s32_le>, 4> points;
+        std::array<Common::Point<s32_le>, 4> points;
     };
     static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size");
 
@@ -111,14 +89,14 @@ private:
     static_assert(sizeof(SharedMemory) == 0x708, "SharedMemory is an invalid size");
 
     struct Finger {
-        Point<f32> pos{};
+        Common::Point<f32> pos{};
         bool pressed{};
     };
 
     struct GestureProperties {
-        std::array<Point<s32_le>, MAX_POINTS> points{};
+        std::array<Common::Point<s32_le>, MAX_POINTS> points{};
         std::size_t active_points{};
-        Point<s32_le> mid_point{};
+        Common::Point<s32_le> mid_point{};
         s64_le detection_count{};
         u64_le delta_time{};
         f32 average_distance{};

From 5554de39332cb2647406a3159b5fefc409affb54 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Fri, 28 May 2021 07:58:55 -0400
Subject: [PATCH 2/2] touchscreen: Make use of common point struct

---
 .../hle/service/hid/controllers/touchscreen.cpp     | 13 +++++++------
 src/core/hle/service/hid/controllers/touchscreen.h  |  7 +++----
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index ac9112c40..6ef17acc5 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -74,8 +74,11 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
     for (std::size_t id = 0; id < MAX_FINGERS; ++id) {
         auto& touch_entry = cur_entry.states[id];
         if (id < active_fingers_count) {
-            touch_entry.x = static_cast<u16>(active_fingers[id].x * Layout::ScreenUndocked::Width);
-            touch_entry.y = static_cast<u16>(active_fingers[id].y * Layout::ScreenUndocked::Height);
+            const auto& [active_x, active_y] = active_fingers[id].position;
+            touch_entry.position = {
+                .x = static_cast<u16>(active_x * Layout::ScreenUndocked::Width),
+                .y = static_cast<u16>(active_y * Layout::ScreenUndocked::Height),
+            };
             touch_entry.diameter_x = Settings::values.touchscreen.diameter_x;
             touch_entry.diameter_y = Settings::values.touchscreen.diameter_y;
             touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle;
@@ -86,8 +89,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
         } else {
             // Clear touch entry
             touch_entry.attribute.raw = 0;
-            touch_entry.x = 0;
-            touch_entry.y = 0;
+            touch_entry.position = {};
             touch_entry.diameter_x = 0;
             touch_entry.diameter_y = 0;
             touch_entry.rotation_angle = 0;
@@ -140,8 +142,7 @@ std::size_t Controller_Touchscreen::UpdateTouchInputEvent(
             fingers[finger_id].id = static_cast<u32_le>(finger_id);
             attribute.start_touch.Assign(1);
         }
-        fingers[finger_id].x = x;
-        fingers[finger_id].y = y;
+        fingers[finger_id].position = {x, y};
         fingers[finger_id].attribute = attribute;
         return finger_id;
     }
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index 2869d0cfd..ef2becefd 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -7,6 +7,7 @@
 #include "common/bit_field.h"
 #include "common/common_funcs.h"
 #include "common/common_types.h"
+#include "common/point.h"
 #include "common/swap.h"
 #include "core/frontend/input.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
@@ -55,8 +56,7 @@ private:
         u64_le delta_time;
         Attributes attribute;
         u32_le finger;
-        u32_le x;
-        u32_le y;
+        Common::Point<u32_le> position;
         u32_le diameter_x;
         u32_le diameter_y;
         u32_le rotation_angle;
@@ -81,8 +81,7 @@ private:
 
     struct Finger {
         u64_le last_touch{};
-        float x{};
-        float y{};
+        Common::Point<float> position;
         u32_le id{};
         bool pressed{};
         Attributes attribute;