home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 52
/
Amiga_Dream_52.iso
/
Linux
/
Divers
/
lyx-0.13.2.tar.gz
/
lyx-0.13.2.tar
/
lyx-0.13.2
/
src
/
figlist.C
< prev
next >
Wrap
C/C++ Source or Header
|
1998-04-23
|
13KB
|
541 lines
#include <config.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include "figlist.h"
#include "error.h"
#include "lyx_main.h"
#include "insetfig.h"
#include "LyXView.h"
#include "procMgr.h"
#include "gsqueue.h"
extern FD_form_main *fd_form_main;
extern Colormap color_map;
extern BufferView *current_view;
extern FL_OBJECT *figinset_canvas;
extern bool gs_color; // do we allocate colors for gs?
extern int bmpinsref; // number of bitmaps
extern bool gs_gray; // is grayscale?
int GhostscriptMsg(FL_OBJECT *, Window, int, int,
XEvent *ev, void *);
static void AllocColors(int num);
static void AllocGrays(int num);
static void chpixmap(Pixmap, int, int);
int FindBmpIndex(figdata *tmpdata); // static?
static void addwait(int psx, int psy, int pswid, int pshgh, figdata *data);
static void getbitmap(figdata *p);
static char bittable[256]; /* bit reversion table */
static unsigned long gs_pixels[128]; // allocated pixels
static int gs_num_pixels; // number of pixels allocated
static int figarrsize = 0; // current max number of figures
static int bmparrsize = 0; // current max number of bitmaps
static int gs_allcolors; // number of all colors
static int gs_spc; // shades per color
const short figallocchunk = 32;
// The list of all figures in all documents
FigureList figL;
void FigureList::InitFigures()
{
unsigned int i, j, k;
Visual *vi;
bmparrsize = figarrsize = figallocchunk;
figures = (Figref**) malloc(sizeof(Figref*)*figallocchunk);
bitmaps = (figdata**) malloc(sizeof(figdata*)*figallocchunk);
for (i = 0; i < 256; ++i) {
k = 0;
for (j = 0; j < 8; ++j)
if (i & (1 << (7-j))) k |= 1 << j;
bittable[i] = char(~k);
}
fl_add_canvas_handler(figinset_canvas, ClientMessage,
GhostscriptMsg, fd_form_main);
// now we have to init color_map
if (!color_map) color_map = DefaultColormap(fl_display,
DefaultScreen(fl_display));
// allocate color cube on pseudo-color display
// first get visual
gs_color = false;
vi = DefaultVisual(fl_display, DefaultScreen(fl_display));
if (lyxerr.debugging()) {
//printf("Visual ID: %ld, class: %d, bprgb: %d, mapsz: %d\n", vi->visualid,
// vi->c_class, vi->bits_per_rgb, vi->map_entries);
fprintf(stderr,
"Visual ID: %ld, class: %d, bprgb: %d, mapsz: %d\n",
vi->visualid, vi->c_class,
vi->bits_per_rgb, vi->map_entries);
}
if ((vi->c_class & 1) == 0) return;
// now allocate colors
if (vi->c_class == GrayScale) {
// allocate grayscale
AllocGrays(vi->map_entries/2);
} else {
// allocate normal color
int i = 5;
while (i*i*i*2 > vi->map_entries) --i;
AllocColors(i);
}
gs_allcolors = vi->map_entries;
}
void FigureList::DoneFigures()
{
free(figures);
free(bitmaps);
figarrsize = 0;
bmparrsize = 0;
lyxerr.debug("Unregistering figures...");
fl_remove_canvas_handler(figinset_canvas, ClientMessage,
GhostscriptMsg);
if (gs_color) {
lyxerr.debug("Freeing up the colors...");
XFreeColors(fl_display, color_map, gs_pixels,
gs_num_pixels, 0);
/******????????????????? what's planes in this case ??????***/
}
}
void FigureList::freefigdata(figdata *tmpdata)
{
int i;
tmpdata->ref--;
if (tmpdata->ref) return;
if (tmpdata->gspid > 0) {
int pid = tmpdata->gspid;
char buf[128];
// change Pixmap according to our allocated colormap
chpixmap(tmpdata->bitmap, tmpdata->wid, tmpdata->hgh);
// kill ghostscript and unlink it's files
tmpdata->gspid = -1;
kill(pid, SIGKILL);
sprintf(buf, "%s/~lyxgs%d.ps", system_tempdir.c_str(), pid);
unlink(buf);
}
if (tmpdata->bitmap) XFreePixmap(fl_display, tmpdata->bitmap);
delete tmpdata;
i = FindBmpIndex(tmpdata);
--bmpinsref;
while (i < bmpinsref) {
bitmaps[i] = bitmaps[i+1];
++i;
}
}
figdata *FigureList::getfigdata(int wid, int hgh, LString const & fname,
int psx, int psy, int pswid, int pshgh,
int raw_wid, int raw_hgh, float angle, char flags)
{
/* first search for an exact match with fname and width/height */
int i = 0;
figdata *p;
XWindowAttributes wa;
if (fname.empty()) return NULL;
while (i < bmpinsref) {
if (bitmaps[i]->wid == wid && bitmaps[i]->hgh == hgh &&
bitmaps[i]->flags == flags && bitmaps[i]->fname==fname &&
bitmaps[i]->angle == angle) {
bitmaps[i]->ref++;
return bitmaps[i];
}
++i;
}
/* not found -> create new record or return NULL if no record */
++bmpinsref;
if (bmpinsref > bmparrsize) {
// allocate more space
bmparrsize += figallocchunk;
figdata **tmp = (figdata**) malloc(sizeof(figdata*)*bmparrsize);
memcpy(tmp, bitmaps, sizeof(figdata*)*(bmparrsize-figallocchunk));
free(bitmaps);
bitmaps = tmp;
}
p = new figdata;
bitmaps[bmpinsref-1] = p;
p->wid = wid;
p->hgh = hgh;
p->raw_wid = raw_wid;
p->raw_hgh = raw_hgh;
p->angle = angle;
p->fname = fname;
p->flags = flags;
XGetWindowAttributes(fl_display, fl_get_canvas_id(
figinset_canvas), &wa);
if (lyxerr.debugging()) {
printf("Create pixmap disp:%d scr:%d w:%d h:%d depth:%d\n",
PTR_AS_INT(fl_display), DefaultScreen(fl_display),
wid, hgh, wa.depth);
}
p->ref = 1;
p->reading = false;
p->broken = false;
p->gspid = -1;
if (flags) {
p->bitmap = XCreatePixmap(fl_display, fl_get_canvas_id(
figinset_canvas), wid, hgh, wa.depth);
p->gsdone = false;
// initialize reading of .eps file with correct sizes and stuff
addwait(psx, psy, pswid, pshgh, p);
p->reading = true;
} else {
p->bitmap = None;
p->gsdone = true;
}
return p;
}
void FigureList::getbitmaps()
{
int i;
bitmap_waiting = false;
for (i = 0; i < bmpinsref; ++i)
if (bitmaps[i]->gspid > 0 && !bitmaps[i]->reading)
getbitmap(bitmaps[i]);
}
void FigureList::RegisterFigure(InsetFig *fi)
{
Figref *tmpfig;
if (figinsref == 0) InitFigures();
fi->form = NULL;
++figinsref;
if (figinsref > figarrsize) {
// allocate more space
figarrsize += figallocchunk;
Figref **tmp = (Figref**) malloc(sizeof(Figref*)*figarrsize);
memcpy(tmp, figures, sizeof(Figref*)*(figarrsize-figallocchunk));
free(figures);
figures = tmp;
}
tmpfig = new Figref;
tmpfig->data = NULL;
tmpfig->inset = fi;
figures[figinsref-1] = tmpfig;
fi->figure = tmpfig;
if (lyxerr.debugging()) {
lyxerr.print(LString("Register Figure: buffer:[") +
long(current_view->currentBuffer()) + ']');
}
}
int FigureList::FindFigIndex(Figref *tmpfig)
{
int i = 0;
while (i < figinsref) {
if (figures[i] == tmpfig) return i;
++i;
}
return i;
}
void FigureList::UnregisterFigure(InsetFig *fi)
{
Figref *tmpfig = fi->figure;
int i;
if (tmpfig->data) freefigdata(tmpfig->data);
if (tmpfig->inset->form) {
if (tmpfig->inset->form->Figure->visible)
fl_hide_form(tmpfig->inset->form->Figure);
fl_free_form(tmpfig->inset->form->Figure);
free(tmpfig->inset->form);
tmpfig->inset->form = NULL;
}
i = FindFigIndex(tmpfig);
--figinsref;
while (i < figinsref) {
figures[i] = figures[i+1];
++i;
}
delete tmpfig;
if (figinsref == 0) DoneFigures();
}
int GhostscriptMsg(FL_OBJECT *, Window, int, int,
XEvent *ev, void *)
{
int i;
char tmp[128];
XClientMessageEvent *e = (XClientMessageEvent*) ev;
if(lyxerr.debugging()) {
printf("ClientMessage, win:[xx] gs:[%ld] pm:[%ld]\n",
e->data.l[0], e->data.l[1]);
}
// just kill gs, that way it will work for sure
for (i = 0; i < bmpinsref; ++i)
if (long(figL.bitmaps[i]->bitmap) == long(e->data.l[1])) {
// found the one
figdata *p = figL.bitmaps[i];
p->gsdone = true;
// first update p->bitmap, if necessary
if (p->bitmap != None && p->flags > (1|8) && gs_color && p->wid) {
// query current colormap and re-render
// the pixmap with proper colors
XColor *cmap;
XWindowAttributes wa;
register XImage *im;
int i, y, wid1, spc1 = gs_spc-1,
spc2 = gs_spc*gs_spc, wid = p->wid,
forkstat;
Display *tmpdisp;
GC gc = getGC(gc_copy);
XGetWindowAttributes(fl_display, fl_get_canvas_id(
figinset_canvas), &wa);
XFlush(fl_display);
if (lyxerr.debugging()) {
fprintf(stderr,
"Starting image translation %ld %d %dx%d %d %d\n",
p->bitmap, p->flags, p->wid, p->hgh, wa.depth,
XYPixmap);
}
// now fork rendering process
forkstat = fork();
if (forkstat == -1) {
lyxerr.debug("Cannot fork, using slow "
"method for pixmap translation.");
tmpdisp = fl_display;
} else if (forkstat > 0) {
// register child
if (lyxerr.debugging()) {
printf("Spawned child %d\n", forkstat);
}
procMgr.addpidwait(forkstat);
break; // in parent process
} else {
tmpdisp = XOpenDisplay(XDisplayName(NULL));
XFlush(tmpdisp);
}
im = XGetImage(tmpdisp, p->bitmap, 0, 0,
p->wid, p->hgh, (1<<wa.depth)-1, XYPixmap);
XFlush(tmpdisp);
if (lyxerr.debugging()) {
printf("Got the image\n");
}
if (!im) {
if (lyxerr.debugging()) {
printf("Error getting the image\n");
}
goto noim;
}
// query current colormap
cmap = (XColor *) malloc(gs_allcolors*sizeof(XColor));
for (i = 0; i < gs_allcolors; ++i) cmap[i].pixel = i;
XQueryColors(tmpdisp, color_map, cmap, gs_allcolors);
XFlush(tmpdisp);
wid1 = p->wid - 1;
// now we process all the image
for (y = 0; y < p->hgh; ++y) {
register int x;
for (x = 0; x < wid; ++x) {
register XColor* pc;
pc = cmap + XGetPixel(im, x, y);
XFlush(tmpdisp);
XPutPixel(im, x, y, gs_pixels[((pc->red+6553)*
spc1/65535)*spc2+((pc->green+6553)*
spc1/65535)*gs_spc+((pc->blue+6553)*
spc1/65535)]);
XFlush(tmpdisp);
}
}
if (lyxerr.debugging()) {
printf("Putting image back\n");
}
XPutImage(tmpdisp, p->bitmap, gc, im, 0, 0,
0, 0, p->wid, p->hgh);
XDestroyImage(im);
if (lyxerr.debugging()) {
printf("Done translation\n");
}
noim:
if (lyxerr.debugging()) {
printf("Killing gs %d\n", p->gspid);
}
kill(p->gspid, SIGHUP);
sprintf(tmp, "%s/~lyxgs%d.ps",
system_tempdir.c_str(),
p->gspid);
unlink(tmp);
if (forkstat == 0) {
XCloseDisplay(tmpdisp);
_exit(0);
}
} else {
if (lyxerr.debugging()) {
printf("Killing gs %d\n", p->gspid);
}
kill(p->gspid, SIGHUP);
sprintf(tmp, "%s/~lyxgs%d.ps",
system_tempdir.c_str(),
p->gspid);
unlink(tmp);
}
break;
}
return 0;
}
static void AllocColors(int num)
// allocate color cube numxnumxnum, if possible
{
XColor xcol;
int i;
if (lyxerr.debugging()) {
printf("Allocating color cube %dx%dx%d\n", num, num, num);
}
if (num <= 1) {
lyxerr.print("Error allocating color colormap.");
gs_color = false;
return;
}
if (num > 5) num = 5;
for (i = 0; i < num*num*num; ++i) {
xcol.red = 65535*(i/(num*num))/(num-1);
xcol.green = 65535*((i/num) % num)/(num-1);
xcol.blue = 65535*(i % num)/(num-1);
xcol.flags = DoRed | DoGreen | DoBlue;
if (!XAllocColor(fl_display, color_map, &xcol)) {
if (i) XFreeColors(fl_display, color_map,
gs_pixels, i, 0);
if(lyxerr.debugging()) {
printf("Cannot allocate color cube %d\n", num);
}
AllocColors(num-1);
return;
}
gs_pixels[i] = xcol.pixel;
}
gs_color = true;
gs_gray = false;
gs_spc = num;
gs_num_pixels = num*num*num;
}
static void AllocGrays(int num)
// allocate grayscale ramp
{
XColor xcol;
int i;
if (lyxerr.debugging()) {
printf("Allocating grayscale ramp %d\n", num);
}
if (num < 4) {
lyxerr.print("Error allocating grayscale colormap.");
gs_color = false;
return;
}
if (num > 128) num = 128;
for (i = 0; i < num; ++i) {
xcol.red = xcol.green = xcol.blue = 65535*i/(num-1);
xcol.flags = DoRed | DoGreen | DoBlue;
if (!XAllocColor(fl_display, color_map, &xcol)) {
if (i) XFreeColors(fl_display, color_map,
gs_pixels, i, 0);
if (lyxerr.debugging()) {
printf("Cannot allocate grayscale %d\n", num);
}
AllocGrays(num/2);
return;
}
gs_pixels[i] = xcol.pixel;
}
gs_color = true;
gs_gray = false;
gs_num_pixels = num;
}
static void chpixmap(Pixmap, int, int)
{
Display* tempdisp = XOpenDisplay(XDisplayName(NULL));
// here read the pixmap and change all colors to those we
// have allocated
XCloseDisplay(tempdisp);
}
int FindBmpIndex(figdata *tmpdata)
{
int i = 0;
while (i < bmpinsref) {
if (figL.bitmaps[i] == tmpdata) return i;
++i;
}
return i;
}
static void addwait(int psx, int psy, int pswid, int pshgh, figdata *data)
{
// recompute the stuff and put in the queue
GSQueue::Queue *p, *p2;
p = new GSQueue::Queue;
p->ofsx = psx;
p->ofsy = psy;
p->rx = (float(data->raw_wid*72))/pswid;
p->ry = (float(data->raw_hgh*72))/pshgh;
p->data = data;
p->next = NULL;
// now put into queue
p2 = gsQ.queue;
if (!gsQ.queue) gsQ.queue = p;
else {
while (p2->next) p2 = p2->next;
p2->next = p;
}
// if possible, run the queue
gsQ.runqueue();
}
static void getbitmap(figdata *p)
{
p->gspid = -1;
}