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 >
C/C++ Source or Header  |  1998-04-23  |  13KB  |  541 lines

  1. #include <config.h>
  2. #include <signal.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5.  
  6. #include "figlist.h"
  7. #include "error.h"
  8. #include "lyx_main.h"
  9. #include "insetfig.h"
  10. #include "LyXView.h"
  11. #include "procMgr.h"
  12. #include "gsqueue.h"
  13.  
  14. extern FD_form_main *fd_form_main;
  15. extern Colormap color_map;
  16. extern BufferView *current_view;
  17. extern FL_OBJECT *figinset_canvas;
  18. extern bool gs_color;            // do we allocate colors for gs?
  19. extern int bmpinsref;  // number of bitmaps
  20. extern bool gs_gray;            // is grayscale?
  21.  
  22. int GhostscriptMsg(FL_OBJECT *, Window, int, int,
  23.            XEvent *ev, void *);
  24. static void AllocColors(int num);
  25. static void AllocGrays(int num);
  26. static void chpixmap(Pixmap, int, int);
  27. int FindBmpIndex(figdata *tmpdata); // static?
  28. static void addwait(int psx, int psy, int pswid, int pshgh, figdata *data);
  29. static void getbitmap(figdata *p);
  30.  
  31. static char bittable[256];    /* bit reversion table */
  32. static unsigned long gs_pixels[128];    // allocated pixels
  33. static int gs_num_pixels;        // number of pixels allocated
  34. static int figarrsize = 0; // current max number of figures
  35. static int bmparrsize = 0; // current max number of bitmaps
  36. static int gs_allcolors;        // number of all colors
  37. static int gs_spc;            // shades per color
  38.  
  39. const short figallocchunk = 32;
  40.  
  41. // The list of all figures in all documents
  42. FigureList figL;
  43.  
  44. void FigureList::InitFigures()
  45. {
  46.     unsigned int i, j, k;
  47.     Visual *vi;
  48.  
  49.     bmparrsize = figarrsize = figallocchunk;
  50.     figures = (Figref**) malloc(sizeof(Figref*)*figallocchunk);
  51.     bitmaps = (figdata**) malloc(sizeof(figdata*)*figallocchunk);
  52.  
  53.     for (i = 0; i < 256; ++i) {
  54.         k = 0;
  55.         for (j = 0; j < 8; ++j)
  56.             if (i & (1 << (7-j))) k |= 1 << j;
  57.         bittable[i] = char(~k);
  58.     }
  59.  
  60.     fl_add_canvas_handler(figinset_canvas, ClientMessage,
  61.                   GhostscriptMsg, fd_form_main);
  62.  
  63.     // now we have to init color_map
  64.     if (!color_map) color_map = DefaultColormap(fl_display,
  65.                             DefaultScreen(fl_display));
  66.     // allocate color cube on pseudo-color display
  67.     // first get visual
  68.     gs_color = false;
  69.  
  70.     vi = DefaultVisual(fl_display, DefaultScreen(fl_display));
  71.     if (lyxerr.debugging()) {
  72.         //printf("Visual ID: %ld, class: %d, bprgb: %d, mapsz: %d\n", vi->visualid,
  73.         //     vi->c_class, vi->bits_per_rgb, vi->map_entries);
  74.         fprintf(stderr,
  75.             "Visual ID: %ld, class: %d, bprgb: %d, mapsz: %d\n", 
  76.             vi->visualid, vi->c_class, 
  77.             vi->bits_per_rgb, vi->map_entries);
  78.     }
  79.     if ((vi->c_class & 1) == 0) return;
  80.     // now allocate colors
  81.     if (vi->c_class == GrayScale) {
  82.         // allocate grayscale
  83.         AllocGrays(vi->map_entries/2);
  84.     } else {
  85.         // allocate normal color
  86.         int i = 5;
  87.         while (i*i*i*2 > vi->map_entries) --i;
  88.         AllocColors(i);
  89.     }
  90.     gs_allcolors = vi->map_entries;
  91. }
  92.  
  93.  
  94. void FigureList::DoneFigures()
  95. {
  96.     free(figures);
  97.     free(bitmaps);
  98.     figarrsize = 0;
  99.     bmparrsize = 0;
  100.  
  101.     lyxerr.debug("Unregistering figures...");
  102.  
  103.     fl_remove_canvas_handler(figinset_canvas, ClientMessage,
  104.                  GhostscriptMsg);
  105.  
  106.     if (gs_color) {
  107.         lyxerr.debug("Freeing up the colors...");
  108.         XFreeColors(fl_display, color_map, gs_pixels,
  109.                 gs_num_pixels, 0);
  110.         /******????????????????? what's planes in this case ??????***/
  111.     }
  112. }
  113.  
  114. void FigureList::freefigdata(figdata *tmpdata)
  115. {
  116.     int i;
  117.  
  118.     tmpdata->ref--;
  119.     if (tmpdata->ref) return;
  120.  
  121.     if (tmpdata->gspid > 0) {
  122.         int pid = tmpdata->gspid;
  123.         char buf[128];
  124.         // change Pixmap according to our allocated colormap
  125.         chpixmap(tmpdata->bitmap, tmpdata->wid, tmpdata->hgh);
  126.         // kill ghostscript and unlink it's files
  127.         tmpdata->gspid = -1;
  128.         kill(pid, SIGKILL);
  129.         sprintf(buf, "%s/~lyxgs%d.ps", system_tempdir.c_str(), pid);
  130.         unlink(buf);
  131.     }
  132.  
  133.     if (tmpdata->bitmap) XFreePixmap(fl_display, tmpdata->bitmap);
  134.     delete tmpdata;
  135.     i = FindBmpIndex(tmpdata);
  136.     --bmpinsref;
  137.     while (i < bmpinsref) {
  138.         bitmaps[i] = bitmaps[i+1];
  139.         ++i;
  140.     }
  141. }
  142.  
  143. figdata *FigureList::getfigdata(int wid, int hgh, LString const & fname, 
  144.                int psx, int psy, int pswid, int pshgh, 
  145.                int raw_wid, int raw_hgh, float angle, char flags)
  146. {
  147.     /* first search for an exact match with fname and width/height */
  148.     int i = 0;
  149.     figdata *p;
  150.     XWindowAttributes wa;
  151.  
  152.     if (fname.empty()) return NULL;
  153.  
  154.     while (i < bmpinsref) {
  155.         if (bitmaps[i]->wid == wid && bitmaps[i]->hgh == hgh &&
  156.             bitmaps[i]->flags == flags && bitmaps[i]->fname==fname &&
  157.             bitmaps[i]->angle == angle) {
  158.             bitmaps[i]->ref++;
  159.             return bitmaps[i];
  160.         }
  161.         ++i;
  162.     }
  163.     /* not found -> create new record or return NULL if no record */
  164.     ++bmpinsref;
  165.     if (bmpinsref > bmparrsize) {
  166.         // allocate more space
  167.         bmparrsize += figallocchunk;
  168.         figdata **tmp = (figdata**) malloc(sizeof(figdata*)*bmparrsize);
  169.         memcpy(tmp, bitmaps, sizeof(figdata*)*(bmparrsize-figallocchunk));
  170.         free(bitmaps);
  171.         bitmaps = tmp;
  172.     }
  173.     p = new figdata;
  174.     bitmaps[bmpinsref-1] = p;
  175.     p->wid = wid;
  176.     p->hgh = hgh;
  177.     p->raw_wid = raw_wid;
  178.     p->raw_hgh = raw_hgh;
  179.     p->angle = angle;
  180.     p->fname = fname;
  181.     p->flags = flags;
  182.     XGetWindowAttributes(fl_display, fl_get_canvas_id(
  183.         figinset_canvas), &wa);
  184.  
  185.     if (lyxerr.debugging()) {
  186.         printf("Create pixmap disp:%d scr:%d w:%d h:%d depth:%d\n",
  187.                PTR_AS_INT(fl_display), DefaultScreen(fl_display), 
  188.                wid, hgh, wa.depth);
  189.     }
  190.     
  191.     p->ref = 1;
  192.     p->reading = false;
  193.     p->broken = false;
  194.     p->gspid = -1;
  195.     if (flags) {
  196.         p->bitmap = XCreatePixmap(fl_display, fl_get_canvas_id(
  197.             figinset_canvas), wid, hgh, wa.depth);
  198.         p->gsdone = false;
  199.         // initialize reading of .eps file with correct sizes and stuff
  200.         addwait(psx, psy, pswid, pshgh, p);
  201.         p->reading = true;
  202.     } else {
  203.         p->bitmap = None;
  204.         p->gsdone = true;
  205.     }
  206.  
  207.     return p;
  208. }
  209.  
  210.  
  211. void FigureList::getbitmaps()
  212. {
  213.     int i;
  214.     bitmap_waiting = false;
  215.     for (i = 0; i < bmpinsref; ++i)
  216.         if (bitmaps[i]->gspid > 0 && !bitmaps[i]->reading)
  217.             getbitmap(bitmaps[i]);
  218. }
  219.  
  220.  
  221. void FigureList::RegisterFigure(InsetFig *fi)
  222. {
  223.     Figref *tmpfig;
  224.  
  225.     if (figinsref == 0) InitFigures();
  226.     fi->form = NULL;
  227.     ++figinsref;
  228.     if (figinsref > figarrsize) {
  229.         // allocate more space
  230.         figarrsize += figallocchunk;
  231.         Figref **tmp = (Figref**) malloc(sizeof(Figref*)*figarrsize);
  232.         memcpy(tmp, figures, sizeof(Figref*)*(figarrsize-figallocchunk));
  233.         free(figures);
  234.         figures = tmp;
  235.     }
  236.     tmpfig = new Figref;
  237.     tmpfig->data = NULL;
  238.     tmpfig->inset = fi;
  239.     figures[figinsref-1] = tmpfig;
  240.     fi->figure = tmpfig;
  241.  
  242.     if (lyxerr.debugging()) {
  243.         lyxerr.print(LString("Register Figure: buffer:[") + 
  244.                long(current_view->currentBuffer()) + ']');
  245.     }
  246. }
  247.  
  248.  
  249. int FigureList::FindFigIndex(Figref *tmpfig)
  250. {
  251.     int i = 0;
  252.     while (i < figinsref) {
  253.         if (figures[i] == tmpfig) return i;
  254.         ++i;
  255.     }
  256.     return i;
  257. }
  258.  
  259.  
  260. void FigureList::UnregisterFigure(InsetFig *fi)
  261. {
  262.     Figref *tmpfig = fi->figure;
  263.     int i;
  264.  
  265.     if (tmpfig->data) freefigdata(tmpfig->data);
  266.     if (tmpfig->inset->form) {
  267.         if (tmpfig->inset->form->Figure->visible)
  268.             fl_hide_form(tmpfig->inset->form->Figure);
  269.         fl_free_form(tmpfig->inset->form->Figure);
  270.         free(tmpfig->inset->form);
  271.         tmpfig->inset->form = NULL;
  272.     }
  273.     i = FindFigIndex(tmpfig);
  274.     --figinsref;
  275.     while (i < figinsref) {
  276.         figures[i] = figures[i+1];
  277.         ++i;
  278.     }
  279.     delete tmpfig;
  280.  
  281.     if (figinsref == 0) DoneFigures();
  282. }
  283.  
  284. int GhostscriptMsg(FL_OBJECT *, Window, int, int,
  285.            XEvent *ev, void *)
  286. {
  287.     int i;
  288.     char tmp[128];
  289.  
  290.     XClientMessageEvent *e = (XClientMessageEvent*) ev;
  291.  
  292.     if(lyxerr.debugging()) {
  293.         printf("ClientMessage, win:[xx] gs:[%ld] pm:[%ld]\n",
  294.                e->data.l[0], e->data.l[1]);
  295.     }
  296.  
  297.     // just kill gs, that way it will work for sure
  298.     for (i = 0; i < bmpinsref; ++i)
  299.         if (long(figL.bitmaps[i]->bitmap) == long(e->data.l[1])) {
  300.             // found the one
  301.             figdata *p = figL.bitmaps[i];
  302.             p->gsdone = true;
  303.  
  304.             // first update p->bitmap, if necessary
  305.             if (p->bitmap != None && p->flags > (1|8) && gs_color && p->wid) {
  306.                 // query current colormap and re-render
  307.                 // the pixmap with proper colors
  308.                 XColor *cmap;
  309.                 XWindowAttributes wa;
  310.                 register XImage *im;
  311.                 int i, y, wid1, spc1 = gs_spc-1,
  312.                     spc2 = gs_spc*gs_spc, wid = p->wid,
  313.                     forkstat;
  314.                 Display *tmpdisp;
  315.                 GC gc = getGC(gc_copy);
  316.  
  317.                 XGetWindowAttributes(fl_display, fl_get_canvas_id(
  318.                     figinset_canvas), &wa);
  319.                 XFlush(fl_display);
  320.                 if (lyxerr.debugging()) {
  321.                     fprintf(stderr,
  322.                         "Starting image translation %ld %d %dx%d %d %d\n",
  323.                            p->bitmap, p->flags, p->wid, p->hgh, wa.depth,
  324.                            XYPixmap);
  325.                 }
  326.                 // now fork rendering process
  327.                 forkstat = fork();
  328.                 if (forkstat == -1) {
  329.                     lyxerr.debug("Cannot fork, using slow "
  330.                               "method for pixmap translation.");
  331.                     tmpdisp = fl_display;
  332.                 } else if (forkstat > 0) {
  333.                     // register child
  334.                     if (lyxerr.debugging()) {
  335.                         printf("Spawned child %d\n", forkstat);
  336.                     }
  337.                     procMgr.addpidwait(forkstat);
  338.                     break; // in parent process
  339.                 } else {
  340.                     tmpdisp = XOpenDisplay(XDisplayName(NULL));
  341.                     XFlush(tmpdisp);
  342.                 }
  343.                 im = XGetImage(tmpdisp, p->bitmap, 0, 0,
  344.                            p->wid, p->hgh, (1<<wa.depth)-1, XYPixmap);
  345.                 XFlush(tmpdisp);
  346.                 if (lyxerr.debugging()) {
  347.                     printf("Got the image\n");
  348.                 }
  349.                 if (!im) {
  350.                     if (lyxerr.debugging()) {
  351.                         printf("Error getting the image\n");
  352.                     }
  353.                     goto noim;
  354.                 }
  355.                 // query current colormap
  356.                 cmap = (XColor *) malloc(gs_allcolors*sizeof(XColor));
  357.                 for (i = 0; i < gs_allcolors; ++i) cmap[i].pixel = i;
  358.                 XQueryColors(tmpdisp, color_map, cmap, gs_allcolors);
  359.                 XFlush(tmpdisp);
  360.                 wid1 = p->wid - 1;
  361.                 // now we process all the image
  362.                 for (y = 0; y < p->hgh; ++y) {
  363.                     register int x;
  364.                     for (x = 0; x < wid; ++x) {
  365.                         register XColor* pc;
  366.                         pc = cmap + XGetPixel(im, x, y);
  367.                         XFlush(tmpdisp);
  368.                         XPutPixel(im, x, y, gs_pixels[((pc->red+6553)*
  369.                                            spc1/65535)*spc2+((pc->green+6553)*
  370.                                                  spc1/65535)*gs_spc+((pc->blue+6553)*
  371.                                                              spc1/65535)]);
  372.                         XFlush(tmpdisp);
  373.                     }
  374.                 }
  375.                 if (lyxerr.debugging()) {
  376.                     printf("Putting image back\n");
  377.                 }
  378.                 XPutImage(tmpdisp, p->bitmap, gc, im, 0, 0,
  379.                       0, 0, p->wid, p->hgh);
  380.                 XDestroyImage(im);
  381.                 if (lyxerr.debugging()) {
  382.                     printf("Done translation\n");
  383.                 }
  384.               noim:
  385.                 if (lyxerr.debugging()) {
  386.                     printf("Killing gs %d\n", p->gspid);
  387.                 }
  388.                 kill(p->gspid, SIGHUP);
  389.  
  390.                 sprintf(tmp, "%s/~lyxgs%d.ps",
  391.                     system_tempdir.c_str(), 
  392.                     p->gspid);
  393.                 unlink(tmp);
  394.                 if (forkstat == 0) {
  395.                     XCloseDisplay(tmpdisp);
  396.                     _exit(0);
  397.                 }
  398.             } else {
  399.                 if (lyxerr.debugging()) {
  400.                     printf("Killing gs %d\n", p->gspid);
  401.                 }
  402.                 kill(p->gspid, SIGHUP);
  403.  
  404.                 sprintf(tmp, "%s/~lyxgs%d.ps", 
  405.                     system_tempdir.c_str(),
  406.                     p->gspid);
  407.                 unlink(tmp);
  408.             }
  409.             break;
  410.         }
  411.     return 0;
  412. }
  413.  
  414.  
  415. static void AllocColors(int num)
  416. // allocate color cube numxnumxnum, if possible
  417. {
  418.     XColor xcol;
  419.     int i;
  420.  
  421.     if (lyxerr.debugging()) {
  422.         printf("Allocating color cube %dx%dx%d\n", num, num, num);
  423.     }
  424.  
  425.     if (num <= 1) {
  426.         lyxerr.print("Error allocating color colormap.");
  427.         gs_color = false;
  428.         return;
  429.     }
  430.     if (num > 5) num = 5;
  431.     for (i = 0; i < num*num*num; ++i) {
  432.         xcol.red = 65535*(i/(num*num))/(num-1);
  433.         xcol.green = 65535*((i/num) % num)/(num-1);
  434.         xcol.blue = 65535*(i % num)/(num-1);
  435.         xcol.flags = DoRed | DoGreen | DoBlue;
  436.         if (!XAllocColor(fl_display, color_map, &xcol)) {
  437.             if (i) XFreeColors(fl_display, color_map,
  438.                        gs_pixels, i, 0);
  439.             if(lyxerr.debugging()) {
  440.                 printf("Cannot allocate color cube %d\n", num);
  441.             }
  442.             AllocColors(num-1);
  443.             return;
  444.         }
  445.         gs_pixels[i] = xcol.pixel;
  446.     }
  447.     gs_color = true;
  448.     gs_gray = false;
  449.     gs_spc = num;
  450.     gs_num_pixels = num*num*num;
  451. }
  452.  
  453.  
  454. static void AllocGrays(int num)
  455. // allocate grayscale ramp
  456. {
  457.     XColor xcol;
  458.     int i;
  459.  
  460.     if (lyxerr.debugging()) {
  461.         printf("Allocating grayscale ramp %d\n", num);
  462.     }
  463.  
  464.     if (num < 4) {
  465.         lyxerr.print("Error allocating grayscale colormap.");
  466.         gs_color = false;
  467.         return;
  468.     }
  469.     if (num > 128) num = 128;
  470.     for (i = 0; i < num; ++i) {
  471.         xcol.red = xcol.green = xcol.blue = 65535*i/(num-1);
  472.         xcol.flags = DoRed | DoGreen | DoBlue;
  473.         if (!XAllocColor(fl_display, color_map, &xcol)) {
  474.             if (i) XFreeColors(fl_display, color_map,
  475.                        gs_pixels, i, 0);
  476.             if (lyxerr.debugging()) {
  477.                 printf("Cannot allocate grayscale %d\n", num);
  478.             }
  479.             AllocGrays(num/2);
  480.             return;
  481.         }
  482.         gs_pixels[i] = xcol.pixel;
  483.     }
  484.     gs_color = true;
  485.     gs_gray = false;
  486.     gs_num_pixels = num;
  487. }
  488.  
  489.  
  490. static void chpixmap(Pixmap, int, int)
  491. {
  492.     Display* tempdisp = XOpenDisplay(XDisplayName(NULL));
  493.  
  494.     // here read the pixmap and change all colors to those we
  495.     // have allocated
  496.  
  497.     XCloseDisplay(tempdisp);
  498. }
  499.  
  500. int FindBmpIndex(figdata *tmpdata)
  501. {
  502.     int i = 0;
  503.     while (i < bmpinsref) {
  504.         if (figL.bitmaps[i] == tmpdata) return i;
  505.         ++i;
  506.     }
  507.     return i;
  508. }
  509.  
  510.  
  511. static void addwait(int psx, int psy, int pswid, int pshgh, figdata *data)
  512. {
  513.     // recompute the stuff and put in the queue
  514.     GSQueue::Queue *p, *p2;
  515.     p = new GSQueue::Queue;
  516.     p->ofsx = psx;
  517.     p->ofsy = psy;
  518.     p->rx = (float(data->raw_wid*72))/pswid;
  519.     p->ry = (float(data->raw_hgh*72))/pshgh;
  520.  
  521.     p->data = data;
  522.     p->next = NULL;
  523.  
  524.     // now put into queue
  525.     p2 = gsQ.queue;
  526.     if (!gsQ.queue) gsQ.queue = p;
  527.     else {
  528.         while (p2->next) p2 = p2->next;
  529.         p2->next = p;
  530.     }
  531.  
  532.     // if possible, run the queue
  533.     gsQ.runqueue();
  534. }
  535.  
  536.  
  537. static void getbitmap(figdata *p)
  538. {
  539.     p->gspid = -1;
  540. }
  541.