Commit 61596ce6 for tesseract

commit 61596ce668c9455bc3464f23c6456bbae7df868c
Author: Stefan Weil <sw@weilnetz.de>
Date:   Thu Jun 18 17:57:03 2026 +0200

    Modernize ScrollView memory management with smart pointers

    Replace raw pointer allocations with std::unique_ptr for:
    - Global static mutex pointers (svmap_mu, waiting_for_events_mu)
    - Stream_ (SVNetwork)
    - points_ (SVPolyLineBuffer)
    - semaphore_ (SVSemaphore)

    This eliminates manual memory management, potential memory leaks,
    and provides RAII-based resource management.

    Updated GetStream() to return a reference instead of pointer
    for a cleaner API.

    Assisted-by: minimax-m2.7 (MiniMax)
    Signed-off-by: Stefan Weil <sw@weilnetz.de>

diff --git a/src/viewer/scrollview.cpp b/src/viewer/scrollview.cpp
index 4b4f6113..054880b5 100644
--- a/src/viewer/scrollview.cpp
+++ b/src/viewer/scrollview.cpp
@@ -53,11 +53,11 @@ struct SVPolyLineBuffer {

 // A map between the window IDs and their corresponding pointers.
 static std::map<int, ScrollView *> svmap;
-static std::mutex *svmap_mu;
+static std::unique_ptr<std::mutex> svmap_mu;
 // A map of all semaphores waiting for a specific event on a specific window.
 static std::map<std::pair<ScrollView *, SVEventType>,
                 std::pair<SVSemaphore *, std::unique_ptr<SVEvent>>> waiting_for_events;
-static std::mutex *waiting_for_events_mu;
+static std::unique_ptr<std::mutex> waiting_for_events_mu;

 std::unique_ptr<SVEvent> SVEvent::copy() const {
   auto any = std::unique_ptr<SVEvent>(new SVEvent);
@@ -89,7 +89,7 @@ void ScrollView::MessageReceiver() {
   char *message = nullptr;
   // Wait until a new message appears in the input stream_.
   do {
-    message = ScrollView::GetStream()->Receive();
+    message = ScrollView::GetStream().Receive();
   } while (message == nullptr);

   // This is the main loop which iterates until the server is dead (strlen =
@@ -177,7 +177,7 @@ void ScrollView::MessageReceiver() {

     // Wait until a new message appears in the input stream_.
     do {
-      message = ScrollView::GetStream()->Receive();
+      message = ScrollView::GetStream().Receive();
     } while (message == nullptr);
   }
 }
@@ -239,7 +239,7 @@ static const uint8_t table_colors[ScrollView::GREEN_YELLOW + 1][4] = {
  * Scrollview implementation.
  *******************************************************************************/

-SVNetwork *ScrollView::stream_ = nullptr;
+std::unique_ptr<SVNetwork> ScrollView::stream_;
 int ScrollView::nr_created_windows_ = 0;
 int ScrollView::image_index_ = 0;

@@ -272,9 +272,9 @@ void ScrollView::Initialize(const char *name, int x_pos, int y_pos, int x_size,
   // network connection yet and we have to set it up in a different thread.
   if (stream_ == nullptr) {
     nr_created_windows_ = 0;
-    stream_ = new SVNetwork(server_name, kSvPort);
-    waiting_for_events_mu = new std::mutex();
-    svmap_mu = new std::mutex();
+    stream_ = std::make_unique<SVNetwork>(server_name, kSvPort);
+    waiting_for_events_mu = std::make_unique<std::mutex>();
+    svmap_mu = std::make_unique<std::mutex>();
     SendRawMessage("svmain = luajava.bindClass('com.google.scrollview.ScrollView')\n");
     std::thread t(&ScrollView::MessageReceiver);
     t.detach();
@@ -289,7 +289,7 @@ void ScrollView::Initialize(const char *name, int x_pos, int y_pos, int x_size,
   window_name_ = name;
   window_id_ = nr_created_windows_;
   // Set up polygon buffering.
-  points_ = new SVPolyLineBuffer;
+  points_ = std::make_unique<SVPolyLineBuffer>();
   points_->empty = true;

   svmap_mu->lock();
@@ -300,7 +300,7 @@ void ScrollView::Initialize(const char *name, int x_pos, int y_pos, int x_size,
     i = nullptr;
   }

-  semaphore_ = new SVSemaphore();
+  semaphore_ = std::make_unique<SVSemaphore>();

   // Set up an actual Window on the client side.
   char message[kMaxMsgSize];
@@ -372,8 +372,6 @@ ScrollView::~ScrollView() {
   } else {
     svmap_mu->unlock();
   }
-  delete semaphore_;
-  delete points_;
 #endif // !GRAPHICS_DISABLED
 }

diff --git a/src/viewer/scrollview.h b/src/viewer/scrollview.h
index 7e4f22e5..b2dc9b2f 100644
--- a/src/viewer/scrollview.h
+++ b/src/viewer/scrollview.h
@@ -378,8 +378,8 @@ private:
   void Signal();

   // Returns the unique, shared network stream.
-  static SVNetwork *GetStream() {
-    return stream_;
+  static SVNetwork &GetStream() {
+    return *stream_;
   }

   // Starts a new event handler.
@@ -396,7 +396,7 @@ private:
   // The id of the window.
   int window_id_;
   // The points of the currently under-construction polyline.
-  SVPolyLineBuffer *points_;
+  std::unique_ptr<SVPolyLineBuffer> points_;
   // Whether the axis is reversed.
   bool y_axis_is_reversed_;
   // Set to true only after the event handler has terminated.
@@ -410,7 +410,7 @@ private:
   static int image_index_;

   // The stream through which the c++ client is connected to the server.
-  static SVNetwork *stream_;
+  static std::unique_ptr<SVNetwork> stream_;

   // Table of all the currently queued events.
   std::unique_ptr<SVEvent> event_table_[SVET_COUNT];
@@ -419,7 +419,7 @@ private:
   std::mutex mutex_;

   // Semaphore to the thread belonging to this window.
-  SVSemaphore *semaphore_;
+  std::unique_ptr<SVSemaphore> semaphore_;
 #endif // !GRAPHICS_DISABLED
 };