Updating viewer code to latest

git-svn-id: https://tesseract-ocr.googlecode.com/svn/trunk@337 d0cd1f9f-072b-0410-8dd7-cf729c803f20
This commit is contained in:
theraysmith 2010-05-19 21:19:00 +00:00
parent 821b151267
commit 208f24ea04
4 changed files with 184 additions and 84 deletions

View File

@ -44,10 +44,6 @@ const int kMaxIntPairSize = 45; // Holds %d,%d, for upto 64 bit.
#include "svutil.h"
// Include automatically generated configuration file if running autoconf.
#ifdef HAVE_CONFIG_H
#include "config_auto.h"
#endif
#ifdef HAVE_LIBLEPT
#include "allheaders.h"
#endif
@ -60,10 +56,11 @@ struct SVPolyLineBuffer {
// A map between the window IDs and their corresponding pointers.
static std::map<int, ScrollView*> svmap;
static SVMutex* 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*, SVEvent*> > waiting_for_events;
SVMutex* mutex_waiting;
static SVMutex* waiting_for_events_mu;
SVEvent* SVEvent::copy() {
SVEvent* any = new SVEvent;
@ -110,6 +107,7 @@ void* ScrollView::MessageReceiver(void* a) {
&cur->y, &cur->x_size, &cur->y_size, &cur->command_id, &n);
char* p = (message + n);
svmap_mu->Lock();
cur->window = svmap[window_id];
if (cur->window != NULL) {
@ -139,7 +137,7 @@ void* ScrollView::MessageReceiver(void* a) {
SVET_ANY);
std::pair<ScrollView*, SVEventType> awaiting_list_any_window(NULL,
SVET_ANY);
mutex_waiting->Lock();
waiting_for_events_mu->Lock();
if (waiting_for_events.count(awaiting_list) > 0) {
waiting_for_events[awaiting_list].second = cur;
waiting_for_events[awaiting_list].first->Signal();
@ -153,7 +151,7 @@ void* ScrollView::MessageReceiver(void* a) {
// No one wanted it, so delete it.
delete cur;
}
mutex_waiting->Unlock();
waiting_for_events_mu->Unlock();
// Signal the corresponding semaphore twice (for both copies).
ScrollView* sv = svmap[window_id];
if (sv != NULL) {
@ -161,6 +159,7 @@ void* ScrollView::MessageReceiver(void* a) {
sv->Signal();
}
}
svmap_mu->Unlock();
// Wait until a new message appears in the input stream_.
do {
@ -262,7 +261,8 @@ void ScrollView::Initialize(const char* name, int x_pos, int y_pos, int x_size,
if (stream_ == NULL) {
nr_created_windows_ = 0;
stream_ = new SVNetwork(server_name, kSvPort);
mutex_waiting = new SVMutex();
waiting_for_events_mu = new SVMutex();
svmap_mu = new SVMutex();
SendRawMessage(
"svmain = luajava.bindClass('com.google.scrollview.ScrollView')\n");
SVSync::StartThread(MessageReceiver, NULL);
@ -271,6 +271,7 @@ void ScrollView::Initialize(const char* name, int x_pos, int y_pos, int x_size,
// Set up the variables on the clientside.
nr_created_windows_++;
event_handler_ = NULL;
event_handler_ended_ = false;
y_axis_is_reversed_ = y_axis_reversed;
y_size_ = y_canvas_size;
window_name_ = name;
@ -279,7 +280,9 @@ void ScrollView::Initialize(const char* name, int x_pos, int y_pos, int x_size,
points_ = new SVPolyLineBuffer;
points_->empty = true;
svmap_mu->Lock();
svmap[window_id_] = this;
svmap_mu->Unlock();
for (int i = 0; i < SVET_COUNT; i++) {
event_table_[i] = NULL;
@ -327,7 +330,11 @@ void* ScrollView::StartEventHandler(void* a) {
sv->event_table_[k] = NULL;
sv->mutex_->Unlock();
if (sv->event_handler_ != NULL) { sv->event_handler_->Notify(new_event); }
if (new_event->type == SVET_DESTROY) { sv = NULL; }
if (new_event->type == SVET_DESTROY) {
// Signal the destructor that it is safe to terminate.
sv->event_handler_ended_ = true;
sv = NULL;
}
delete new_event; // Delete the pointer after it has been processed.
} else { sv->mutex_->Unlock(); }
// The thread should run as long as its associated window is alive.
@ -336,18 +343,28 @@ void* ScrollView::StartEventHandler(void* a) {
}
ScrollView::~ScrollView() {
svmap_mu->Lock();
if (svmap[window_id_] != NULL) {
svmap_mu->Unlock();
// So the event handling thread can quit.
SendMsg("destroy()");
SVEvent* sve = AwaitEvent(SVET_DESTROY);
delete sve;
svmap_mu->Lock();
svmap[window_id_] = NULL;
svmap_mu->Unlock();
// The event handler thread for this window *must* receive the
// destroy event and set its pointer to this to NULL before we allow
// the destructor to exit.
while (!event_handler_ended_)
Update();
} else {
svmap_mu->Unlock();
}
delete mutex_;
delete semaphore_;
delete points_;
svmap.erase(window_id_);
}
// Send a message to the server, attaching the window id.
@ -409,17 +426,18 @@ SVEvent* ScrollView::AwaitEvent(SVEventType type) {
// Initialize the waiting semaphore.
SVSemaphore* sem = new SVSemaphore();
std::pair<ScrollView*, SVEventType> ea(this, type);
mutex_waiting->Lock();
waiting_for_events_mu->Lock();
waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, NULL);
mutex_waiting->Unlock();
waiting_for_events_mu->Unlock();
// Wait on it, but first flush.
stream_->Flush();
sem->Wait();
// Process the event we got woken up for (its in waiting_for_events pair).
mutex_waiting->Lock();
waiting_for_events_mu->Lock();
SVEvent* ret = waiting_for_events[ea].second;
waiting_for_events.erase(ea);
mutex_waiting->Unlock();
delete sem;
waiting_for_events_mu->Unlock();
return ret;
}
@ -429,17 +447,17 @@ SVEvent* ScrollView::AwaitEventAnyWindow() {
// Initialize the waiting semaphore.
SVSemaphore* sem = new SVSemaphore();
std::pair<ScrollView*, SVEventType> ea(NULL, SVET_ANY);
mutex_waiting->Lock();
waiting_for_events_mu->Lock();
waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, NULL);
mutex_waiting->Unlock();
waiting_for_events_mu->Unlock();
// Wait on it.
stream_->Flush();
sem->Wait();
// Process the event we got woken up for (its in waiting_for_events pair).
mutex_waiting->Lock();
waiting_for_events_mu->Lock();
SVEvent* ret = waiting_for_events[ea].second;
waiting_for_events.erase(ea);
mutex_waiting->Unlock();
waiting_for_events_mu->Unlock();
return ret;
}
@ -562,6 +580,8 @@ void ScrollView::Stroke(float width) {
// Draw a rectangle using the current pen color.
// The rectangle is filled with the current brush color.
void ScrollView::Rectangle(int x1, int y1, int x2, int y2) {
if (x1 == x2 && y1 == y2)
return; // Scrollviewer locks up.
SendMsg("drawRectangle(%d,%d,%d,%d)",
x1, TranslateYCoordinate(y1), x2, TranslateYCoordinate(y2));
}
@ -669,11 +689,13 @@ void ScrollView::UpdateWindow() {
// Note: this is an update to all windows
void ScrollView::Update() {
svmap_mu->Lock();
for (std::map<int, ScrollView*>::iterator iter = svmap.begin();
iter != svmap.end(); ++iter) {
if (iter->second != NULL)
iter->second->UpdateWindow();
}
svmap_mu->Unlock();
}
// Set the pen color, using an enum value (e.g. ScrollView::ORANGE)
@ -723,9 +745,9 @@ void ScrollView::ZoomToRectangle(int x1, int y1, int x2, int y2) {
MIN(x1, x2), MIN(y1, y2), MAX(x1, x2), MAX(y1, y2));
}
// Send an image of type PIX.
void ScrollView::Image(Pix* image, int x_pos, int y_pos) {
#ifdef HAVE_LIBLEPT
// Send an image of type PIX.
void ScrollView::Image(PIX* image, int x_pos, int y_pos) {
int width = image->w;
int height = image->h;
l_uint32 bpp = image->d;
@ -741,12 +763,10 @@ void ScrollView::Image(Pix* image, int x_pos, int y_pos) {
}
// PIX* do not have a unique identifier/name associated, so name them "lept".
SendMsg("drawImage('%s',%d,%d)", "lept", x_pos, y_pos);
#endif
}
// Sends each pixel as hex value like html, e.g. #00FF00 for green.
void ScrollView::Transfer32bppImage(Pix* image) {
#ifdef HAVE_LIBLEPT
void ScrollView::Transfer32bppImage(PIX* image) {
int ppL = pixGetWidth(image);
int h = pixGetHeight(image);
int wpl = pixGetWpl(image);
@ -765,12 +785,10 @@ void ScrollView::Transfer32bppImage(Pix* image) {
SendRawMessage(pixel_data);
}
delete[] pixel_data;
#endif
}
// Sends for each pixel either '1' or '0'.
void ScrollView::TransferGrayImage(Pix* image) {
#ifdef HAVE_LIBLEPT
void ScrollView::TransferGrayImage(PIX* image) {
char* pixel_data = new char[image->w * 2 + 2];
for (int y = 0; y < image->h; y++) {
l_uint32* data = pixGetData(image) + y * pixGetWpl(image);
@ -782,12 +800,10 @@ void ScrollView::TransferGrayImage(Pix* image) {
}
}
delete [] pixel_data;
#endif
}
// Sends for each pixel either '1' or '0'.
void ScrollView::TransferBinaryImage(Pix* image) {
#ifdef HAVE_LIBLEPT
void ScrollView::TransferBinaryImage(PIX* image) {
char* pixel_data = new char[image->w + 2];
for (int y = 0; y < image->h; y++) {
l_uint32* data = pixGetData(image) + y * pixGetWpl(image);
@ -802,8 +818,8 @@ void ScrollView::TransferBinaryImage(Pix* image) {
SendRawMessage(pixel_data);
}
delete [] pixel_data;
#endif
}
#endif
// Escapes the ' character with a \, so it can be processed by LUA.
// Note: The caller will have to make sure he deletes the newly allocated item.

View File

@ -201,8 +201,10 @@ class ScrollView {
* constructor, so this is not listed here)
*******************************************************************************/
#ifdef HAVE_LIBLEPT
// Draw a Pix on (x,y).
void Image(struct Pix* image, int x_pos, int y_pos);
#endif
// Flush buffers and update display.
static void Update();
@ -345,12 +347,14 @@ class ScrollView {
int TranslateYCoordinate(int y);
private:
#ifdef HAVE_LIBLEPT
// Transfers a binary Image.
void TransferBinaryImage(struct Pix* image);
// Transfers a gray scale Image.
void TransferGrayImage(struct Pix* image);
// Transfers a 32-Bit Image.
void Transfer32bppImage(struct Pix* image);
#endif
// Sets up ScrollView, depending on the variables from the constructor.
void Initialize(const char* name, int x_pos, int y_pos, int x_size,
@ -388,6 +392,8 @@ class ScrollView {
SVPolyLineBuffer* points_;
// Whether the axis is reversed.
bool y_axis_is_reversed_;
// Set to true only after the event handler has terminated.
bool event_handler_ended_;
// If the y axis is reversed, flip all y values by ySize.
int y_size_;
// # of created windows (used to assign an id to each ScrollView* for svmap).

View File

@ -24,9 +24,17 @@
#include "svutil.h"
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#include <winsock.h>
struct addrinfo {
struct sockaddr* ai_addr;
int ai_addrlen;
int ai_family;
int ai_socktype;
int ai_protocol;
};
#else
#include <arpa/inet.h>
#include <netinet/in.h>
@ -39,13 +47,11 @@
#include <sys/socket.h>
#ifdef __linux__
#include <sys/prctl.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#endif
#include <stdio.h>
#include <iostream>
#include <string>
const int kBufferSize = 65536;
const int kMaxMsgSize = 4096;
@ -252,44 +258,133 @@ void SVNetwork::Close() {
#endif
}
// Set up a connection to hostname on port.
SVNetwork::SVNetwork(const char* hostname, int port) {
mutex_send_ = new SVMutex();
struct sockaddr_in address;
struct hostent *name;
msg_buffer_in_ = new char[kMaxMsgSize + 1];
msg_buffer_in_[0] = '\0';
// The program to invoke to start ScrollView
static const char* ScrollViewProg() {
#ifdef WIN32
const char* prog = "java -Xms512m -Xmx1024m";
#else
const char* prog = "sh";
#endif
return prog;
}
has_content = false;
buffer_ptr_ = NULL;
// The arguments to the program to invoke to start ScrollView
static std::string ScrollViewCommand(std::string scrollview_path) {
// The following ugly ifdef is to enable the output of the java runtime
// to be sent down a black hole on non-windows to ignore all the
// exceptions in piccolo. Ideally piccolo would be debugged to make
// this unnecessary.
// Also the path has to be separated by ; on windows and : otherwise.
#ifdef WIN32
const char* cmd_template = "-Djava.library.path=%s -cp %s/ScrollView.jar;"
"%s/piccolo-1.2.jar;%s/piccolox-1.2.jar"
" com.google.scrollview.ScrollView";
#else
const char* cmd_template = "-c \"trap 'kill %1' 0 1 2 ; java "
"-Xms1024m -Xmx2048m -Djava.library.path=%s -cp %s/ScrollView.jar:"
"%s/piccolo-1.2.jar:%s/piccolox-1.2.jar"
" com.google.scrollview.ScrollView"
" >/dev/null 2>&1 & wait\"";
#endif
int cmdlen = strlen(cmd_template) + 4*strlen(scrollview_path.c_str()) + 1;
char* cmd = new char[cmdlen];
const char* sv_path = scrollview_path.c_str();
snprintf(cmd, cmdlen, cmd_template, sv_path, sv_path, sv_path, sv_path);
std::string command(cmd);
delete [] cmd;
return command;
}
// Platform-independent freeaddrinfo()
static void FreeAddrInfo(struct addrinfo* addr_info) {
#if defined(__linux__)
freeaddrinfo(addr_info);
#else
delete addr_info->ai_addr;
delete addr_info;
#endif
}
// Non-linux version of getaddrinfo()
#if !defined(__linux__)
static int GetAddrInfoNonLinux(const char* hostname, int port,
struct addrinfo** addr_info) {
// Get the host data depending on the OS.
struct sockaddr_in* address;
*addr_info = new struct addrinfo;
memset(*addr_info, 0, sizeof(struct addrinfo));
address = new struct sockaddr_in;
memset(address, 0, sizeof(struct sockaddr_in));
(*addr_info)->ai_addr = (struct sockaddr*) address;
(*addr_info)->ai_addrlen = sizeof(struct sockaddr);
(*addr_info)->ai_family = AF_INET;
(*addr_info)->ai_socktype = SOCK_STREAM;
struct hostent *name;
#ifdef WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(1, 1), &wsaData);
name = gethostbyname(hostname);
#elif defined(__linux__)
struct hostent hp;
int herr;
char *buffer = new char[kBufferSize];
gethostbyname_r(hostname, &hp, buffer, kBufferSize, &name, &herr);
delete[] buffer;
#else
name = gethostbyname(hostname);
#endif
// Fill in the appropriate variables to be able to connect to the server.
address.sin_family = name->h_addrtype;
memcpy((char *) &address.sin_addr.s_addr,
name->h_addr_list[0], name->h_length);
address.sin_port = htons(port);
if (name == NULL) {
FreeAddrInfo(*addr_info);
*addr_info = NULL;
return -1;
}
stream_ = socket(AF_INET, SOCK_STREAM, 0);
// Fill in the appropriate variables to be able to connect to the server.
address->sin_family = name->h_addrtype;
memcpy((char *) &address->sin_addr.s_addr,
name->h_addr_list[0], name->h_length);
address->sin_port = htons(port);
return 0;
}
#endif
// Platform independent version of getaddrinfo()
// Given a hostname:port, produce an addrinfo struct
static int GetAddrInfo(const char* hostname, int port,
struct addrinfo** address) {
#if defined(__linux__)
char port_str[40];
snprintf(port_str, 40, "%d", port);
return getaddrinfo(hostname, port_str, NULL, address);
#else
return GetAddrInfoNonLinux(hostname, port, address);
#endif
}
// Set up a connection to a ScrollView on hostname:port.
SVNetwork::SVNetwork(const char* hostname, int port) {
mutex_send_ = new SVMutex();
msg_buffer_in_ = new char[kMaxMsgSize + 1];
msg_buffer_in_[0] = '\0';
has_content = false;
buffer_ptr_ = NULL;
struct addrinfo *addr_info = NULL;
if (GetAddrInfo(hostname, port, &addr_info) != 0) {
std::cerr << "Error resolving name for ScrollView host "
<< std::string(hostname) << ":" << port << std::endl;
}
stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
addr_info->ai_protocol);
// If server is not there, we will start a new server as local child process.
if (connect(stream_, (struct sockaddr *) &address, sizeof(address)) < 0) {
if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) < 0) {
const char* scrollview_path = getenv("SCROLLVIEW_PATH");
if (scrollview_path == NULL) {
#ifdef SCROLLVIEW_PATH
@ -302,36 +397,14 @@ SVNetwork::SVNetwork(const char* hostname, int port) {
scrollview_path = ".";
#endif
}
// The following ugly ifdef is to enable the output of the java runtime
// to be sent down a black hole on non-windows to ignore all the
// exceptions in piccolo. Ideally piccolo would be debugged to make
// this unnecessary.
// Also the path has to be separated by ; on windows and : otherwise.
#ifdef WIN32
const char* prog = "java -Xms512m -Xmx1024m";
const char* cmd_template = "-Djava.library.path=%s -cp %s/ScrollView.jar;"
"%s/piccolo-1.2.jar;%s/piccolox-1.2.jar"
" com.google.scrollview.ScrollView";
#else
const char* prog = "sh";
const char* cmd_template = "-c \"trap 'kill %1' 0 1 2 ; java "
"-Xms1024m -Xmx2048m -Djava.library.path=%s -cp %s/ScrollView.jar:"
"%s/piccolo-1.2.jar:%s/piccolox-1.2.jar"
" com.google.scrollview.ScrollView"
" >/dev/null 2>&1 & wait\"";
#endif
int cmdlen = strlen(cmd_template) + 4*strlen(scrollview_path) + 1;
char* cmd = new char[cmdlen];
snprintf(cmd, cmdlen, cmd_template, scrollview_path, scrollview_path,
scrollview_path, scrollview_path);
SVSync::StartProcess(prog, cmd);
delete [] cmd;
const char *prog = ScrollViewProg();
std::string command = ScrollViewCommand(scrollview_path);
SVSync::StartProcess(prog, command.c_str());
// Wait for server to show up.
// Note: There is no exception handling in case the server never turns up.
while (connect(stream_, (struct sockaddr *) &address,
sizeof(address)) < 0) {
while (connect(stream_, (struct sockaddr *) addr_info->ai_addr,
addr_info->ai_addrlen) < 0) {
std::cout << "ScrollView: Waiting for server...\n";
#ifdef WIN32
Sleep(1000);
@ -340,6 +413,7 @@ SVNetwork::SVNetwork(const char* hostname, int port) {
#endif
}
}
FreeAddrInfo(addr_info);
}
SVNetwork::~SVNetwork() {

View File

@ -105,13 +105,17 @@
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
WholeProgramOptimization="false"
AdditionalIncludeDirectories="..\include"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;__MSW32__;_CRT_SECURE_NO_WARNINGS;HAVE_LIBLEPT;LEPTONLIB_IMPORTS"
StringPooling="true"
MinimalRebuild="true"
ExceptionHandling="0"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
DebugInformationFormat="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"