1 ///////////////////////////////////////////////////////////////////////
2 // File:        scrollview.h
3 // Description: ScrollView
4 // Author:      Joern Wanke
5 //
6 // (C) Copyright 2007, Google Inc.
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 ///////////////////////////////////////////////////////////////////////
18 //
19 // ScrollView is designed as an UI which can be run remotely. This is the
20 // client code for it, the server part is written in java. The client consists
21 // mainly of 2 parts:
22 // The "core" ScrollView which sets up the remote connection,
23 // takes care of event handling etc.
24 // The other part of ScrollView consists of predefined API calls through LUA,
25 // which can basically be used to get a zoomable canvas in which it is possible
26 // to draw lines, text etc.
27 // Technically, thanks to LUA, its even possible to bypass the here defined LUA
28 // API calls at all and generate a java user interface from scratch (or
29 // basically generate any kind of java program, possibly even dangerous ones).
30 
31 #ifndef TESSERACT_VIEWER_SCROLLVIEW_H_
32 #define TESSERACT_VIEWER_SCROLLVIEW_H_
33 
34 #include "image.h"
35 
36 #include <tesseract/export.h>
37 
38 #include <cstdio>
39 #include <mutex>
40 
41 namespace tesseract {
42 
43 #if !defined(__GNUC__) && !defined(__attribute__)
44 # define __attribute__(attr) // compiler without support for __attribute__
45 #endif
46 
47 class ScrollView;
48 class SVNetwork;
49 class SVSemaphore;
50 struct SVPolyLineBuffer;
51 
52 enum SVEventType {
53   SVET_DESTROY,   // Window has been destroyed by user.
54   SVET_EXIT,      // User has destroyed the last window by clicking on the 'X'.
55   SVET_CLICK,     // Left button pressed.
56   SVET_SELECTION, // Left button selection.
57   SVET_INPUT,     // There is some input (single key or a whole string).
58   SVET_MOUSE,     // The mouse has moved with a button pressed.
59   SVET_MOTION,    // The mouse has moved with no button pressed.
60   SVET_HOVER,     // The mouse has stayed still for a second.
61   SVET_POPUP,     // A command selected through a popup menu.
62   SVET_MENU,      // A command selected through the menubar.
63   SVET_ANY,       // Any of the above.
64 
65   SVET_COUNT // Array sizing.
66 };
67 
68 struct SVEvent {
~SVEventSVEvent69   ~SVEvent() {
70     delete[] parameter;
71   }
72   SVEvent *copy() const;
73   SVEventType type = SVET_DESTROY; // What kind of event.
74   ScrollView *window = nullptr;    // Window event relates to.
75   char *parameter = nullptr;       // Any string that might have been passed as argument.
76   int x = 0;                       // Coords of click or selection.
77   int y = 0;
78   int x_size = 0; // Size of selection.
79   int y_size = 0;
80   int command_id = 0; // The ID of the possibly associated event (e.g. MENU)
81   int counter = 0;    // Used to detect which kind of event to process next.
82 
83   SVEvent() = default;
84   SVEvent(const SVEvent &);
85   SVEvent &operator=(const SVEvent &);
86 };
87 
88 // The SVEventHandler class is used for Event handling: If you register your
89 // class as SVEventHandler to a ScrollView Window, the SVEventHandler will be
90 // called whenever an appropriate event occurs.
91 class SVEventHandler {
92 public:
93   virtual ~SVEventHandler();
94 
95   // Gets called by the SV Window. Does nothing on default, overwrite this
96   // to implement the desired behaviour
Notify(const SVEvent * sve)97   virtual void Notify(const SVEvent *sve) {
98     (void)sve;
99   }
100 };
101 
102 // The ScrollView class provides the external API to the scrollviewer process.
103 // The scrollviewer process manages windows and displays images, graphics and
104 // text while allowing the user to zoom and scroll the windows arbitrarily.
105 // Each ScrollView class instance represents one window, and stuff is drawn in
106 // the window through method calls on the class. The constructor is used to
107 // create the class instance (and the window).
108 class TESS_API ScrollView {
109 public:
110   // Color enum for pens and brushes.
111   enum Color {
112     NONE,
113     BLACK,
114     WHITE,
115     RED,
116     YELLOW,
117     GREEN,
118     CYAN,
119     BLUE,
120     MAGENTA,
121     AQUAMARINE,
122     DARK_SLATE_BLUE,
123     LIGHT_BLUE,
124     MEDIUM_BLUE,
125     MIDNIGHT_BLUE,
126     NAVY_BLUE,
127     SKY_BLUE,
128     SLATE_BLUE,
129     STEEL_BLUE,
130     CORAL,
131     BROWN,
132     SANDY_BROWN,
133     GOLD,
134     GOLDENROD,
135     DARK_GREEN,
136     DARK_OLIVE_GREEN,
137     FOREST_GREEN,
138     LIME_GREEN,
139     PALE_GREEN,
140     YELLOW_GREEN,
141     LIGHT_GREY,
142     DARK_SLATE_GREY,
143     DIM_GREY,
144     GREY,
145     KHAKI,
146     MAROON,
147     ORANGE,
148     ORCHID,
149     PINK,
150     PLUM,
151     INDIAN_RED,
152     ORANGE_RED,
153     VIOLET_RED,
154     SALMON,
155     TAN,
156     TURQUOISE,
157     DARK_TURQUOISE,
158     VIOLET,
159     WHEAT,
160     GREEN_YELLOW // Make sure this one is last.
161   };
162 
163   ~ScrollView();
164 
165 #ifndef GRAPHICS_DISABLED
166 
167   // Create a window. The pixel size of the window may be 0,0, in which case
168   // a default size is selected based on the size of your canvas.
169   // The canvas may not be 0,0 in size!
170   ScrollView(const char *name, int x_pos, int y_pos, int x_size, int y_size, int x_canvas_size,
171              int y_canvas_size);
172   // With a flag whether the x axis is reversed.
173   ScrollView(const char *name, int x_pos, int y_pos, int x_size, int y_size, int x_canvas_size,
174              int y_canvas_size, bool y_axis_reversed);
175   // Connect to a server other than localhost.
176   ScrollView(const char *name, int x_pos, int y_pos, int x_size, int y_size, int x_canvas_size,
177              int y_canvas_size, bool y_axis_reversed, const char *server_name);
178   /*******************************************************************************
179    * Event handling
180    * To register as listener, the class has to derive from the SVEventHandler
181    * class, which consists of a notifyMe(SVEvent*) function that should be
182    * overwritten to process the event the way you want.
183    *******************************************************************************/
184 
185   // Add an Event Listener to this ScrollView Window.
186   void AddEventHandler(SVEventHandler *listener);
187 
188   // Block until an event of the given type is received.
189   SVEvent *AwaitEvent(SVEventType type);
190 
191   /*******************************************************************************
192    * Getters and Setters
193    *******************************************************************************/
194 
195   // Returns the title of the window.
GetName()196   const char *GetName() {
197     return window_name_;
198   }
199 
200   // Returns the unique ID of the window.
GetId()201   int GetId() {
202     return window_id_;
203   }
204 
205   /*******************************************************************************
206    * API functions for LUA calls
207    * the implementations for these can be found in svapi.cc
208    * (keep in mind that the window is actually created through the ScrollView
209    * constructor, so this is not listed here)
210    *******************************************************************************/
211 
212   // Draw an image on (x,y).
213   void Draw(Image image, int x_pos, int y_pos);
214 
215   // Flush buffers and update display.
216   static void Update();
217 
218   // Exit the program.
219   static void Exit();
220 
221   // Update the contents of a specific window.
222   void UpdateWindow();
223 
224   // Erase all content from the window, but do not destroy it.
225   void Clear();
226 
227   // Set pen color with an enum.
228   void Pen(Color color);
229 
230   // Set pen color to RGB (0-255).
231   void Pen(int red, int green, int blue);
232 
233   // Set pen color to RGBA (0-255).
234   void Pen(int red, int green, int blue, int alpha);
235 
236   // Set brush color with an enum.
237   void Brush(Color color);
238 
239   // Set brush color to RGB (0-255).
240   void Brush(int red, int green, int blue);
241 
242   // Set brush color to RGBA (0-255).
243   void Brush(int red, int green, int blue, int alpha);
244 
245   // Set attributes for future text, like font name (e.g.
246   // "Times New Roman"), font size etc..
247   // Note: The underlined flag is currently not supported
248   void TextAttributes(const char *font, int pixel_size, bool bold, bool italic, bool underlined);
249 
250   // Draw line from (x1,y1) to (x2,y2) with the current pencolor.
251   void Line(int x1, int y1, int x2, int y2);
252 
253   // Set the stroke width of the pen.
254   void Stroke(float width);
255 
256   // Draw a rectangle given upper left corner and lower right corner.
257   // The current pencolor is used as outline, the brushcolor to fill the shape.
258   void Rectangle(int x1, int y1, int x2, int y2);
259 
260   // Draw an ellipse centered on (x,y).
261   // The current pencolor is used as outline, the brushcolor to fill the shape.
262   void Ellipse(int x, int y, int width, int height);
263 
264   // Draw text with the current pencolor
265   void Text(int x, int y, const char *mystring);
266 
267   // Draw an image from a local filename. This should be faster than
268   // createImage. WARNING: This only works on a local machine. This also only
269   // works image types supported by java (like bmp,jpeg,gif,png) since the image
270   // is opened by the server.
271   void Draw(const char *image, int x_pos, int y_pos);
272 
273   // Set the current position to draw from (x,y). In conjunction with...
274   void SetCursor(int x, int y);
275 
276   // ...this function, which draws a line from the current to (x,y) and then
277   // sets the new position to the new (x,y), this can be used to easily draw
278   // polygons using vertices
279   void DrawTo(int x, int y);
280 
281   // Set the SVWindow visible/invisible.
282   void SetVisible(bool visible);
283 
284   // Set the SVWindow always on top or not always on top.
285   void AlwaysOnTop(bool b);
286 
287   // Shows a modal dialog with "msg" as question and returns 'y' or 'n'.
288   int ShowYesNoDialog(const char *msg);
289 
290   // Shows a modal dialog with "msg" as question and returns a char* string.
291   // Constraint: As return, only words (e.g. no whitespaces etc.) are allowed.
292   char *ShowInputDialog(const char *msg);
293 
294   // Adds a messagebox to the SVWindow. This way, it can show the messages...
295   void AddMessageBox();
296 
297   // ...which can be added by this command.
298   // This is intended as an "debug" output window.
299   void AddMessage(const char *message);
300   void AddMessageF(const char *format, ...) __attribute__((format(printf, 2, 3)));
301 
302   // Zoom the window to the rectangle given upper left corner and
303   // lower right corner.
304   void ZoomToRectangle(int x1, int y1, int x2, int y2);
305 
306   // Custom messages (manipulating java code directly) can be send through this.
307   // Send a message to the server and attach the Id of the corresponding window.
308   // Note: This should only be called if you are know what you are doing, since
309   // you are fiddling with the Java objects on the server directly. Calling
310   // this just for fun will likely break your application!
311   // It is public so you can actually take use of the LUA functionalities, but
312   // be careful!
313   void SendMsg(const char* msg, ...) __attribute__((format(printf, 2, 3)));
314 
315   // Custom messages (manipulating java code directly) can be send through this.
316   // Send a message to the server without adding the
317   // window id. Used for global events like Exit().
318   // Note: This should only be called if you are know what you are doing, since
319   // you are fiddling with the Java objects on the server directly. Calling
320   // this just for fun will likely break your application!
321   // It is public so you can actually take use of the LUA functionalities, but
322   // be careful!
323   static void SendRawMessage(const char *msg);
324 
325   /*******************************************************************************
326    * Add new menu entries to parent. If parent is "", the entry gets added to
327    *the main menubar (toplevel).
328    *******************************************************************************/
329   // This adds a new submenu to the menubar.
330   void MenuItem(const char *parent, const char *name);
331 
332   // This adds a new (normal) menu entry with an associated eventID, which
333   // should be unique among menubar eventIDs.
334   void MenuItem(const char *parent, const char *name, int cmdEvent);
335 
336   // This adds a new checkbox entry, which might initially be flagged.
337   void MenuItem(const char *parent, const char *name, int cmdEvent, bool flagged);
338 
339   // This adds a new popup submenu to the popup menu. If parent is "", the entry
340   // gets added at "toplevel" popupmenu.
341   void PopupItem(const char *parent, const char *name);
342 
343   // This adds a new popup entry with the associated eventID, which should be
344   // unique among popup eventIDs.
345   // If value and desc are given, on a click the server will ask you to modify
346   // the value and return the new value.
347   void PopupItem(const char *parent, const char *name, int cmdEvent, const char *value,
348                  const char *desc);
349 
350   // Returns the correct Y coordinate for a window, depending on whether it
351   // might have to be flipped (by ySize).
352   int TranslateYCoordinate(int y);
353 
354   char Wait();
355 
356 private:
357   // Transfers a binary Image.
358   void TransferBinaryImage(Image image);
359   // Transfers a gray scale Image.
360   void TransferGrayImage(Image image);
361   // Transfers a 32-Bit Image.
362   void Transfer32bppImage(Image image);
363 
364   // Sets up ScrollView, depending on the variables from the constructor.
365   void Initialize(const char *name, int x_pos, int y_pos, int x_size, int y_size, int x_canvas_size,
366                   int y_canvas_size, bool y_axis_reversed, const char *server_name);
367 
368   // Send the current buffered polygon (if any) and clear it.
369   void SendPolygon();
370 
371   // Start the message receiving thread.
372   static void MessageReceiver();
373 
374   // Place an event into the event_table (synchronized).
375   void SetEvent(const SVEvent *svevent);
376 
377   // Wake up the semaphore.
378   void Signal();
379 
380   // Returns the unique, shared network stream.
GetStream()381   static SVNetwork *GetStream() {
382     return stream_;
383   }
384 
385   // Starts a new event handler.
386   // Called asynchronously whenever a new window is created.
387   void StartEventHandler();
388 
389   // Escapes the ' character with a \, so it can be processed by LUA.
390   char *AddEscapeChars(const char *input);
391 
392   // The event handler for this window.
393   SVEventHandler *event_handler_;
394   // The name of the window.
395   const char *window_name_;
396   // The id of the window.
397   int window_id_;
398   // The points of the currently under-construction polyline.
399   SVPolyLineBuffer *points_;
400   // Whether the axis is reversed.
401   bool y_axis_is_reversed_;
402   // Set to true only after the event handler has terminated.
403   bool event_handler_ended_;
404   // If the y axis is reversed, flip all y values by ySize.
405   int y_size_;
406   // # of created windows (used to assign an id to each ScrollView* for svmap).
407   static int nr_created_windows_;
408   // Serial number of sent images to ensure that the viewer knows they
409   // are distinct.
410   static int image_index_;
411 
412   // The stream through which the c++ client is connected to the server.
413   static SVNetwork *stream_;
414 
415   // Table of all the currently queued events.
416   SVEvent *event_table_[SVET_COUNT];
417 
418   // Mutex to access the event_table_ in a synchronized fashion.
419   std::mutex mutex_;
420 
421   // Semaphore to the thread belonging to this window.
422   SVSemaphore *semaphore_;
423 #endif // !GRAPHICS_DISABLED
424 };
425 
426 } // namespace tesseract
427 
428 #endif // TESSERACT_VIEWER_SCROLLVIEW_H_
429