src/hg/lib/hvGfx.c 1.5

1.5 2009/08/19 22:28:37 angie
Added option to mgSaveToGif and its call stack, to use GIF's Graphic Control Extension to make memgfx's background color (0) transparent. Also corrected terminology for PNG in .h files: useAlpha -> useTransparency.
Index: src/hg/lib/hvGfx.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/lib/hvGfx.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -b -B -U 1000000 -r1.4 -r1.5
--- src/hg/lib/hvGfx.c	5 Aug 2009 23:34:31 -0000	1.4
+++ src/hg/lib/hvGfx.c	19 Aug 2009 22:28:37 -0000	1.5
@@ -1,253 +1,253 @@
 /* hvGfx - browser graphics interface.  This is a thin layer on top of vGfx
  * providing genome browser-specific features.  It was added to handle
  * reverse-complement display. */
 
 #include "common.h"
 #include "hvGfx.h"
 
 static char const rcsid[] = "$Id$";
 
 static struct hvGfx *hvGfxAlloc(struct vGfx *vg)
 /* allocate a hvgGfx object */
 {
 struct hvGfx *hvg;
 AllocVar(hvg);
 hvg->vg = vg;
 hvg->pixelBased = vg->pixelBased;
 hvg->width = vg->width;
 hvg->height = vg->height;
 hvg->clipMaxX = vg->width;
 hvg->clipMaxY = vg->height;
 return hvg;
 }
 
-struct hvGfx *hvGfxOpenGif(int width, int height, char *fileName)
+struct hvGfx *hvGfxOpenGif(int width, int height, char *fileName, boolean useTransparency)
 /* Open up something that we'll write out as a gif someday. */
 {
-return hvGfxAlloc(vgOpenGif(width, height, fileName));
+return hvGfxAlloc(vgOpenGif(width, height, fileName, useTransparency));
 }
 
 #ifdef USE_PNG
-struct hvGfx *hvGfxOpenPng(int width, int height, char *fileName, boolean useAlpha)
+struct hvGfx *hvGfxOpenPng(int width, int height, char *fileName, boolean useTransparency)
 /* Open up something that we'll write out as a PNG someday. */
 {
-return hvGfxAlloc(vgOpenPng(width, height, fileName, useAlpha));
+return hvGfxAlloc(vgOpenPng(width, height, fileName, useTransparency));
 }
 #endif//def USE_PNG
 
 struct hvGfx *hvGfxOpenPostScript(int width, int height, char *fileName)
 /* Open up something that will someday be a PostScript file. */
 {
 return hvGfxAlloc(vgOpenPostScript(width, height, fileName));
 }
 
 void hvGfxClose(struct hvGfx **pHvg)
 /* Close down virtual graphics object, and finish writing it to file. */
 {
 struct hvGfx *hvg = *pHvg;
 if (hvg != NULL)
     {
     vgClose(&hvg->vg);
     freez(pHvg);
     }
 }
 
 void hvGfxMakeColorGradient(struct hvGfx *hvg, 
                             struct rgbColor *start, struct rgbColor *end,
                             int steps, Color *colorIxs)
 /* Make a color gradient that goes smoothly from start to end colors in given
  * number of steps.  Put indices in color table in colorIxs */
 {
 double scale = 0, invScale;
 double invStep;
 int i;
 int r,g,b;
 
 steps -= 1;	/* Easier to do the calculation in an inclusive way. */
 invStep = 1.0/steps;
 for (i=0; i<=steps; ++i)
     {
     invScale = 1.0 - scale;
     r = invScale * start->r + scale * end->r;
     g = invScale * start->g + scale * end->g;
     b = invScale * start->b + scale * end->b;
     colorIxs[i] = hvGfxFindColorIx(hvg, r, g, b);
     scale += invStep;
     }
 }
 
 static long figureTickSpan(long totalLength, int maxNumTicks)
 /* Figure out whether ticks on ruler should be 1, 5, 10, 50, 100, 500, 
  * 1000, etc. units apart.  */
 {
 int roughTickLen = totalLength/maxNumTicks;
 int i;
 int tickLen = 1;
 
 for (i=0; i<9; ++i)
     {
     if (roughTickLen < tickLen)
     	return tickLen;
     tickLen *= 5;
     if (roughTickLen < tickLen)
 	return tickLen;
     tickLen *= 2;
     }
 return 1000000000;
 }
 
 static void numLabelString(int num, char *label)
 /* Returns a numerical labeling string. */
 {
 char *sign = "";
 if (num < 0)
     {
     num = -num;
     sign = "-";
     }
 sprintf(label, "%s%d", sign, num);
 }
 
 void hvGfxDrawRulerBumpText(struct hvGfx *hvg, int xOff, int yOff, 
 	int height, int width,
         Color color, MgFont *font,
         int startNum, int range, int bumpX, int bumpY)
 /* Draw a ruler inside the indicated part of mg with numbers that start at
  * startNum and span range.  Bump text positions slightly. */
 {
 int tickSpan;
 int tickPos;
 double scale;
 int firstTick;
 int remainder;
 int end = startNum + range;
 int x;
 char tbuf[14];
 int numWid;
 int goodNumTicks;
 int niceNumTicks = width/35;
 
 numLabelString(startNum+range, tbuf);
 numWid = mgFontStringWidth(font, tbuf)+4+bumpX;
 goodNumTicks = width/numWid;
 if (goodNumTicks < 1) goodNumTicks = 1;
 if (goodNumTicks > niceNumTicks) goodNumTicks = niceNumTicks;
 
 tickSpan = figureTickSpan(range, goodNumTicks);
 
 scale = (double)width / range;
 
 firstTick = startNum + tickSpan;
 remainder = firstTick % tickSpan;
 firstTick -= remainder;
 for (tickPos=firstTick; tickPos<end; tickPos += tickSpan)
     {
     numLabelString(tickPos, tbuf);
     numWid = mgFontStringWidth(font, tbuf)+4;
     x = (int)((tickPos-startNum) * scale) + xOff;
     hvGfxBox(hvg, x, yOff, 1, height, color);
     if (x - numWid >= xOff)
         {
         hvGfxTextCentered(hvg, x-numWid + bumpX, yOff + bumpY, numWid, 
                           height, color, font, tbuf);
         }
     }
 }
 
 void hvGfxDrawRuler(struct hvGfx *hvg, int xOff, int yOff, int height, int width,
         Color color, MgFont *font,
         int startNum, int range)
 /* Draw a ruler inside the indicated part of mg with numbers that start at
  * startNum and span range.  */
 {
 hvGfxDrawRulerBumpText(hvg, xOff, yOff, height, width, color, font,
                        startNum, range, 0, 0);
 }
 
 
 void hvGfxBarbedHorizontalLine(struct hvGfx *hvg, int x, int y, 
 	int width, int barbHeight, int barbSpacing, int barbDir, Color color,
 	boolean needDrawMiddle)
 /* Draw a horizontal line starting at xOff, yOff of given width.  Will
  * put barbs (successive arrowheads) to indicate direction of line.  
  * BarbDir of 1 points barbs to right, of -1 points them to left. */
 {
 barbDir = (hvg->rc) ? -barbDir : barbDir;
 if (barbDir == 0)
     return;  // fully clipped, or no barbs
 x = hvGfxAdjXW(hvg, x, width);
 int x1, x2;
 int yHi, yLo;
 int offset, startOffset, endOffset, barbAdd;
 int scrOff = (barbSpacing - 1) - (x % (barbSpacing));
 
 yHi = y + barbHeight;
 yLo = y - barbHeight;
 if (barbDir < 0)
     {
     startOffset = scrOff - barbHeight;
     startOffset = (startOffset >= 0) ?startOffset : 0;
     endOffset = width - barbHeight;
     barbAdd = barbHeight;
     }
 else
     {
     startOffset = scrOff + barbHeight;
     endOffset = width;
     barbAdd = -barbHeight;
     }
 
 for (offset = startOffset; offset < endOffset; offset += barbSpacing)
     {
     x1 = x + offset;
     x2 = x1 + barbAdd;
     vgLine(hvg->vg, x1, y, x2, yHi, color);
     vgLine(hvg->vg, x1, y, x2, yLo, color);
     }
 }
 
 void hvGfxNextItemButton(struct hvGfx *hvg, int x, int y, int w, int h, 
 		      Color color, Color hvgColor, boolean nextItem)
 /* Draw a button that looks like a fast-forward or rewind button on */
 /* a remote control. If nextItem is TRUE, it points right, otherwise */
 /* left. color is the outline color, and hvgColor is the fill color. */
 {
 x = hvGfxAdjXW(hvg, x, w);
 if (hvg->rc)
     nextItem = !nextItem;
 
 struct gfxPoly *t1, *t2;
 /* Make the triangles */
 t1 = gfxPolyNew();
 t2 = gfxPolyNew();
 if (nextItem)
     /* point right. */
     {
     gfxPolyAddPoint(t1, x, y);
     gfxPolyAddPoint(t1, x+w/2, y+h/2);
     gfxPolyAddPoint(t1, x, y+h);
     gfxPolyAddPoint(t2, x+w/2, y);
     gfxPolyAddPoint(t2, x+w, y+h/2);
     gfxPolyAddPoint(t2, x+w/2, y+h);    
     }
 else
     /* point left. */
     {
     gfxPolyAddPoint(t1, x, y+h/2);
     gfxPolyAddPoint(t1, x+w/2, y);
     gfxPolyAddPoint(t1, x+w/2, y+h);
     gfxPolyAddPoint(t2, x+w/2, y+h/2);
     gfxPolyAddPoint(t2, x+w, y);
     gfxPolyAddPoint(t2, x+w, y+h);
     }
 /* The two filled triangles. */
 vgDrawPoly(hvg->vg, t1, hvgColor, TRUE);
 vgDrawPoly(hvg->vg, t2, hvgColor, TRUE);
 /* The two outline triangles. */
 vgDrawPoly(hvg->vg, t1, color, FALSE);
 vgDrawPoly(hvg->vg, t2, color, FALSE);
 gfxPolyFree(&t1);
 gfxPolyFree(&t2);
 }