@@ -21,65 +21,218 @@
#include <unistd.h>

extern "C" {
void gsdll_draw(unsigned char *device, BView *view, BRect dest, BRect src);
int gsdll_exit();
int gsdll_execute_cont(char *buf, int len);
int gsdll_execute_begin();
int gsdll_execute_end();
int gsdll_init( int fct(int i,char* c,unsigned long ul), int what, int argc, char** argv);
int gsdll_lock_device(unsigned char *dev, int whatever);
int gsdll_unlock_device(unsigned char *dev, int whatever);

struct display_callback {
/* Size of this structure */
/* Used for checking if we have been handed a valid structure */
int size;

/* Major version of this structure */
/* The major version number will change if this structure changes. */
int version_major;

/* Minor version of this structure */
/* The minor version number will change if new features are added
* without changes to this structure. For example, a new color
* format.
*/
int version_minor;

/* New device has been opened */
/* This is the first event from this device. */
int (*display_open)(void *handle, void *device);

/* Device is about to be closed. */
/* Device will not be closed until this function returns. */
int (*display_preclose)(void *handle, void *device);

/* Device has been closed. */
/* This is the last event from this device. */
int (*display_close)(void *handle, void *device);

/* Device is about to be resized. */
/* Resize will only occur if this function returns 0. */
/* raster is byte count of a row. */
int (*display_presize)(void *handle, void *device,
int width, int height, int raster, unsigned int format);

/* Device has been resized. */
/* New pointer to raster returned in pimage */
int (*display_size)(void *handle, void *device, int width, int height,
int raster, unsigned int format, unsigned char *pimage);

/* flushpage */
int (*display_sync)(void *handle, void *device);

/* showpage */
/* If you want to pause on showpage, then don't return immediately */
int (*display_page)(void *handle, void *device, int copies, int flush);

/* Notify the caller whenever a portion of the raster is updated. */
/* This can be used for cooperative multitasking or for
* progressive update of the display.
* This function pointer may be set to NULL if not required.
*/
int (*display_update)(void *handle, void *device, int x, int y,
int w, int h);

/* Allocate memory for bitmap */
/* This is provided in case you need to create memory in a special
* way, e.g. shared. If this is NULL, the Ghostscript memory device
* allocates the bitmap. This will only called to allocate the
* image buffer. The first row will be placed at the address
* returned by display_memalloc.
*/
void *(*display_memalloc)(void *handle, void *device, unsigned long size);

/* Free memory for bitmap */
/* If this is NULL, the Ghostscript memory device will free the bitmap */
int (*display_memfree)(void *handle, void *device, void *mem);

/* Added in V2 */
/* When using separation color space (DISPLAY_COLORS_SEPARATION),
* give a mapping for one separation component.
* This is called for each new component found.
* It may be called multiple times for each component.
* It may be called at any time between display_size
* and display_close.
* The client uses this to map from the separations to CMYK
* and hence to RGB for display.
* GS must only use this callback if version_major >= 2.
* The unsigned short c,m,y,k values are 65535 = 1.0.
* This function pointer may be set to NULL if not required.
*/
#if 0
int (*display_separation)(void *handle, void *device,
int component, const char *component_name,
unsigned short c, unsigned short m,
unsigned short y, unsigned short k);
#endif
};

int gsapi_new_instance(void **pinstance, void *caller_handle);
void gsapi_delete_instance(void *instance);
int gsapi_set_stdio (void *instance, int(*stdin_fn)(void *caller_handle, char *buf, int len), int(*stdout_fn)(void *caller_handle, const char *str, int len), int(*stderr_fn)(void *caller_handle, const char *str, int len));
int gsapi_exit(void* instance);
int gsapi_execute_cont(char *buf, int len);
int gsapi_execute_begin();
int gsapi_execute_end();
int gsapi_init_with_args(void* instance, int argc, const char** argv);
int gsapi_set_display_callback (void *instance, display_callback *callback);
}


char PAGE_FILE[B_FILE_NAME_LENGTH];
bool displayComplete;
float width,height;
BBitmap* gBitmap;

BPSWidget *painter;
unsigned char *bdev = NULL;
int gsdll_call(int message, char *str, unsigned long count) {
switch (message) {
case 1:
strcpy(str,"\n");
painter->SetPaperSize(width,height);
release_sem(painter->painter_sem); // signal that interpreter is ready to paint
acquire_sem(painter->keepup_sem); // wait for signal to quit
acquire_sem(painter->painter_sem); // interpreter should not paint during shutdown
displayComplete=true;
return strlen(str);
break;
case 2:
if (!displayComplete) painter->printOnConsole(str);
return count;
break;
case 3:
bdev = (unsigned char *) str;
break;
case 4:
break;
case 5:
break;
case 6:
width=(float)(count & 0xffff);
height=(float)((count>>16) & 0xffff);
break;
case 7:
return 0; break;
default:
break;
}
return 0;
}
static void *bdev = NULL;

int gsapi_display_open(void *handle, void *device)
{
return 0;
}

int gsapi_display_preclose(void *handle, void *device)
{
bdev = 0;
return 0;
}

int gsapi_display_close(void *handle, void *device)
{
return 0;
}

int gsapi_display_presize(void *handle, void *device,
int w, int h, int r, unsigned int f)
{
acquire_sem(painter->painter_sem); // lock our painter stuff until "sync"
width = w;
height = h;
bdev = device;
return 0;
}

int gsapi_display_size(void* handle, void* d, int w, int h, int r, unsigned int f,
unsigned char* i)
{
return 0;
}

int gsapi_display_sync(void* h, void* d)
{
return 0;
}

int gsapi_display_page(void *handle, void *device, int copies, int flush)
{
painter->SetPaperSize(width,height);
// Also invalidates the window to trigger redraw
displayComplete=true;
release_sem(painter->painter_sem); // now it's ok for painter to draw

// Wait and keep the bitmap in memory
acquire_sem(painter->keepup_sem);
return 0;
}


void* gsapi_memalloc(void *handle, void *device, unsigned long size)
{
gBitmap = new BBitmap(BRect(0, 0, width - 1, height - 1), B_RGB32);
return gBitmap->Bits();
}

int gsapi_memfree(void *handle, void *device, void *mem)
{
delete gBitmap;
gBitmap = NULL;
return 0;
}


int gsapi_stdin(void *caller_handle, char *buf, int len)
{
strcpy(buf,"\n");
return 1;
}


int gsapi_stdout(void *caller_handle, const char *str, int len)
{
fprintf(stderr, "\x1b[33m%*.*s\x1b[0m", len, len, str);
painter->printOnConsole(str, len);
return len;
}


int gsapi_stderr(void *caller_handle, const char *str, int len)
{
fprintf(stderr, "\x1b[32m%*.*s\x1b[0m", len, len, str);
painter->printOnConsole(str, len);
return len;
}


display_callback cb;
void* instance;

long gsloop(void* psview) {
BPSWidget *ps = (BPSWidget *) psview;
int code;
int gs_arg;
char *gs_call[128];
const char *gs_call[128];
gs_arg=0;
gs_call[gs_arg++] = "gs";
gs_call[gs_arg++] = "-dQUIET";
gs_call[gs_arg++] = "-sDEVICE=display";
gs_call[gs_arg++] = "-dDisplayFormat=2180";
gs_call[gs_arg++] = "-dDisplayHandle=0";
gs_call[gs_arg++] = "-dTextAlphaBits=4";
gs_call[gs_arg++] = "-dGraphicsAlphaBits=4";
if (ps->pagemedia) {
printf("using fixed media\n");
gs_call[gs_arg++] = "-dFIXEDMEDIA";
@@ -92,19 +245,46 @@ long gsloop(void* psview) {
else
gs_call[gs_arg++] = PAGE_FILE;
displayComplete=false;
code = gsdll_init(gsdll_call,NULL, gs_arg, gs_call);
if (code==0) {
if (displayComplete) gsdll_exit();
else {
painter->SetPaperSize(width,height);
release_sem(painter->painter_sem);

cb.size = sizeof(display_callback);
cb.version_major = 1;
cb.version_minor = 0;
cb.display_open = gsapi_display_open;
cb.display_preclose = gsapi_display_preclose;
cb.display_close = gsapi_display_close;
cb.display_presize = gsapi_display_presize;
cb.display_size = gsapi_display_size;
cb.display_sync = gsapi_display_sync;
cb.display_page = gsapi_display_page;
cb.display_memalloc = gsapi_memalloc;
cb.display_memfree = gsapi_memfree;

code = gsapi_new_instance(&instance, NULL);
if (code != 0)
fprintf(stderr, "Fail to create instance: %d\n", code);
gsapi_set_stdio(instance, gsapi_stdin, gsapi_stdout, gsapi_stderr);

code = gsapi_set_display_callback(instance, &cb);
if (code != 0)
fprintf(stderr, "Fail to set display callback: %d\n", code);

code = gsapi_init_with_args(instance, gs_arg, gs_call);
if (code==0) {
if (displayComplete)
gsapi_exit(instance);
else {
painter->SetPaperSize(width,height);
acquire_sem(painter->keepup_sem);
acquire_sem(painter->painter_sem);
gsdll_exit();
}}
gsapi_exit(instance);
}
} else {
fprintf(stderr, "Fail to initialize ghostscript: %d\n", code);
}
release_sem(painter->shutdown_sem); // signal that interpreter has shut down
gsapi_delete_instance(instance);
return 0; // no errors
};
}


bool writePS( FILE *in, FILE *out, long begin, unsigned int len){
int rr;
@@ -113,22 +293,23 @@ bool writePS( FILE *in, FILE *out, long begin, unsigned int len){
while (len>BUFSIZ) {
rr = fread(buffer, sizeof(char), BUFSIZ, in);
fwrite(buffer, sizeof(char), rr, out);
len -=rr;};
len -=rr;
}
rr = fread(buffer, sizeof(char), len, in);
fwrite(buffer, sizeof(char), rr, out);
fflush(out);
return true;
}

BPSWidget::BPSWidget( BRect frame, const char *name, const char *tempDir)
:BView(frame, name , B_FOLLOW_ALL_SIDES, B_WILL_DRAW)
:BView(frame, name , B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS)
{
gs_thread=0;
buf = (char *)malloc(BUFSIZ);
xdpi=75.0;
ydpi=75.0;
painter=this;
bdev=0;
painter=this;
bdev=0;
startup_sem = create_sem(1,"gs_startup_protector");
shutdown_sem = create_sem(1,"gs_shutdown_protector");
painter_sem = create_sem(1,"gs_paintlock");
@@ -137,14 +318,13 @@ BPSWidget::BPSWidget( BRect frame, const char *name, const char *tempDir)
strcpy(PAGE_FILE,"/boot/home/tmp/bgv.tmp");
else
sprintf(PAGE_FILE,"%s/%s",tempDir,"bgv.tmp");
out = fopen(PAGE_FILE,"w");
out = fopen(PAGE_FILE,"w");
acquire_sem(keepup_sem);
acquire_sem(shutdown_sem);
acquire_sem(painter_sem);
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
console=new BPSConsole(BRect(20,40,400,300),"GS Console");
console->Show();
console->Hide();
console->Show();
}

void BPSWidget::showConsole() {
@@ -171,56 +351,73 @@ BPSWidget::~BPSWidget()
}


void BPSWidget::printOnConsole(const char* text) {
console->addText(text);
}

void BPSWidget::TargetedByScrollView(BScrollView *viewer) {
scrollView=viewer;};

void BPSWidget::SetPaperSize(float width, float height) {
printf("dim %f, %f\n",width,height);
BScrollBar *hbar = scrollView->ScrollBar(B_HORIZONTAL);
BScrollBar *vbar = scrollView->ScrollBar(B_VERTICAL);
int scrollWidth, scrollHeight;
if (Window()->LockWithTimeout(100000)==B_OK) {
scrollWidth = (int) (width- Bounds().Width()-1);
scrollHeight= (int) (height- Bounds().Height()-1);
void BPSWidget::printOnConsole(const char* text, int len)
{
console->addText(text, len);
}

void BPSWidget::TargetedByScrollView(BScrollView *viewer)
{
scrollView=viewer;
}

void BPSWidget::FrameResized(float viewWidth, float viewHeight)
{
int scrollWidth, scrollHeight;
BScrollBar *hbar = scrollView->ScrollBar(B_HORIZONTAL);
BScrollBar *vbar = scrollView->ScrollBar(B_VERTICAL);
scrollWidth = (int) (width - viewWidth);
scrollHeight= (int) (height - viewHeight);
if (scrollWidth<0) scrollWidth=0;
if (scrollHeight<0) scrollHeight=0;
hbar->SetRange(0,scrollWidth);
vbar->SetRange(0,scrollHeight);
hbar->SetSteps(20,100);
vbar->SetSteps(20,100);
hbar->Invalidate();
vbar->Invalidate();
Invalidate();
Window()->Unlock();};
};
hbar->SetProportion(viewWidth / width);
vbar->SetProportion(viewHeight / height);
}

void BPSWidget::SetPaperSize(float width, float height)
{
if (Window()->LockWithTimeout(100000)==B_OK) {
FrameResized(Bounds().Width() - 1, Bounds().Height() - 1);
Invalidate();
Window()->Unlock();
}
}


void BPSWidget::Draw(BRect area) {
void BPSWidget::Draw(BRect area) {
if(bdev) {
if (acquire_sem_etc(painter_sem,1,B_TIMEOUT,0)==B_NO_ERROR) {
// draw only if interpreter is up and running, block shutdown while drawing
gsdll_lock_device(bdev, 1);
gsdll_draw(bdev, this, area, area);
gsdll_lock_device(bdev, 0);
release_sem(painter_sem);};
};
}
DrawBitmap(gBitmap);
release_sem(painter_sem);
}
}
}


char *BPSWidget::GetPaperSwitch() {
char *BPSWidget::GetPaperSwitch()
{
if (pagemedia) {
int len=strlen(pagemedia);
char *lcmedia = (char *)malloc(len+1);
for (int i=0; i<=len; i++) lcmedia[i] = tolower(pagemedia[i]);
sprintf(pswitch,"-sPAPERSIZE=%s",lcmedia);};
return pswitch; };
sprintf(pswitch,"-sPAPERSIZE=%s",lcmedia);
}
return pswitch;
}

char *BPSWidget::GetResolutionSwitch() {

char *BPSWidget::GetResolutionSwitch()
{
sprintf(rswitch,"-r%fx%f",xdpi,ydpi);
return rswitch; };

return rswitch;
}


bool BPSWidget::isInterpreterRunning() {
if (acquire_sem_etc(startup_sem,1,B_TIMEOUT,0)==B_NO_ERROR) {
release_sem(startup_sem);
@@ -27,6 +27,7 @@ class BPSWidget : public BView
BPSWidget(BRect frame, const char* name, const char *tempDir);
~BPSWidget();
void Draw(BRect frame);
void FrameResized(float, float);
void TargetedByScrollView(BScrollView *v);
void SetPaperSize(float width, float height);
char *GetPaperSwitch();
@@ -39,7 +40,7 @@ class BPSWidget : public BView
void showConsole();
void hideConsole();
void toggleConsole();
void printOnConsole(const char *text);
void printOnConsole(const char *text, int len);
void quitInterpreter();
bool isInterpreterRunning();
FILE* out;
@@ -64,7 +64,7 @@ LIBS = gs prefs be translation tracker stdc++
# to the Makefile. The paths included are not parsed recursively, so
# include all of the paths where libraries must be found. Directories where
# source files were specified are automatically included.
LIBPATHS = /boot/apps/Ghostscript/lib
LIBPATHS =

# Additional paths to look for system headers. These use the form
# "#include <header>". Directories that contain the files in SRCS are
1,495 src/ps.c

Large diffs are not rendered by default.