fb0d415d29a5786b48478ef7fb87b8adc8d8af61 kent Sun Feb 17 10:51:11 2013 -0800 Changing way transparency is done so that it shows up in PDF, and also can be normalized when we add more cell lines. diff --git src/hg/hgTracks/multiWig.c src/hg/hgTracks/multiWig.c index 65f4500..9c07c61 100644 --- src/hg/hgTracks/multiWig.c +++ src/hg/hgTracks/multiWig.c @@ -1,56 +1,183 @@ /* A container for multiple wiggles with a couple of options for combining them. */ #include "common.h" #include "hash.h" #include "linefile.h" #include "jksql.h" #include "dystring.h" #include "hdb.h" #include "hgTracks.h" #include "container.h" #include "wiggle.h" #include "wigCommon.h" #include "hui.h" +struct floatPic +/* A picture that stores RGB values in floating point. */ + { + float **lines; /* points to start of each line of image */ + float *image; + int width; /* Width in pixels. */ + int height; /* Heigh in pixels. */ + }; + +struct floatPic *floatPicNew(int width, int height) +/* Return a new floatPic. */ +{ +long lineSize = 3L * width; +long imageSize = lineSize * height; +struct floatPic *pic = needMem(sizeof(struct floatPic)); +pic->width = width; +pic->height = height; +pic->image = needHugeMem(imageSize * sizeof(float)); + +/* Create and initialize line start array */ +AllocArray(pic->lines, height); +int i = height; +float *line = pic->image; +float **lines = pic->lines; +while (--i >= 0) + { + *lines++ = line; + line += lineSize; + } +return pic; +} + +void floatPicFree(struct floatPic **pPic) +/* Free up resources associated with floatPic. */ +{ +struct floatPic *pic = *pPic; +if (pic != NULL) + { + freeMem(pic->lines); + freeMem(pic->image); + freez(pPic); + } +} + +void floatPicSet(struct floatPic *pic, float r, float g, float b) +/* Set full image to a single color */ +{ +long totalSize = pic->width * pic->height; +float *p = pic->image; +while (--totalSize >= 0) + { + *p++ = r; + *p++ = g; + *p++ = b; + } +} + +void vLineViaFloat(void *image, int x, int y, int height, Color color) +/* A vertical line drawer that works via floatPic. */ +{ +struct floatPic *pic = image; + +/* First do some clipping */ +if (x < 0 || x > pic->width) + return; +if (y < 0) + { + height += y; + y = 0; + } +int yEnd = y + height; +if (yEnd > pic->height) + { + yEnd = pic->height; + height = yEnd - y; + } +if (height <= 0) + return; + +int hOffset = x*3; +const float scaleColor = 1/255.9; + +float r = COLOR_32_RED(color) * scaleColor; +float g = COLOR_32_GREEN(color) * scaleColor; +float b = COLOR_32_BLUE(color) * scaleColor; +while (--height >= 0) + { + float *p = pic->lines[y++] + hOffset; + p[0] *= r; + p[1] *= g; + p[2] *= b; + } +} + +struct wigGraphOutput *wigGraphOutputTransparent(struct floatPic *image) +/* Get appropriate wigGraphOutput for non-transparent rendering */ +{ +struct wigGraphOutput *wgo; +AllocVar(wgo); +wgo->image = image; +wgo->vLine = vLineViaFloat; +return wgo; +} + +void floatPicIntoHvg(struct floatPic *pic, int xOff, int yOff, struct hvGfx *hvg) +/* Copy float pic into hvg at given offset. */ +{ +int width = pic->width, height = pic->height; +Color *lineBuf; +AllocArray(lineBuf, width); +int y; +for (y=0; ylines[y]; + Color *cp = lineBuf; + int i = width; + while (--i >= 0) + { + int red = fp[0]*255.9; + int green = fp[1]*255.9; + int blue = fp[2]*255.9; + *cp++ = MAKECOLOR_32(red, green, blue); + fp += 3; + } + hvGfxVerticalSmear(hvg, xOff, y + yOff, width, 1, lineBuf, TRUE); + } +freez(&lineBuf); +} + + static void minMaxVals(struct slRef *refList, double *retMin, double *retMax, enum wiggleAlwaysZeroEnum alwaysZero) /* Figure out min/max of everything in list. The refList contains pointers to * preDrawContainers */ { /* Turns out to be *much* shorter to rewrite than to reuse preDrawAutoScale */ double max = -BIGDOUBLE, min = BIGDOUBLE; struct slRef *ref; for (ref = refList; ref != NULL; ref = ref->next) { - struct preDrawContainer *pre; - for (pre = ref->val; pre != NULL; pre = pre->next) - { + struct preDrawContainer *pre = ref->val; struct preDrawElement *p = pre->preDraw + pre->preDrawZero; int width = pre->width; int i; for (i=0; icount) { if (min > p->min) min = p->min; if (max < p->max) max = p->max; } ++p; } } - } if (alwaysZero == wiggleAlwaysZeroOn) { if ( max < 0) max = 0.0; else if ( min > 0) min = 0.0; } *retMax = max; *retMin = min; } static void multiWigDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw items in multiWig container. */ @@ -100,52 +227,70 @@ minVal = wiggleLogish(minVal); maxVal = wiggleLogish(maxVal); } /* Loop through again setting up the wigCarts of the children to have minY/maxY for * our limits and autoScale off. */ for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next) { struct wigCartOptions *wigCart = subtrack->extraUiData; wigCart->minY = minVal; wigCart->maxY = maxVal; wigCart->autoScale = wiggleScaleManual; } } +/* Deal with tranparency possibly */ +struct wigGraphOutput *wgo; +struct floatPic *floatPic = NULL; +if (wigCart->transparent) + { + int height = tg->lineHeight; + floatPic = floatPicNew(width, height); + floatPicSet(floatPic, 1, 1, 1); + wgo = wigGraphOutputTransparent(floatPic); + } +else + wgo = wigGraphOutputSolid(xOff, yOff, hvg); + for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next) { if (isSubtrackVisible(subtrack)) { if (!subtrack->networkErrMsg || !errMsgShown) { if (subtrack->networkErrMsg) errMsgShown = TRUE; + subtrack->wigGraphOutput = wgo; int height = subtrack->totalHeight(subtrack, vis); hvGfxSetClip(hvg, xOff, y, width, height); - if (sameString(WIG_AGGREGATE_TRANSPARENT, aggregate)) - hvGfxSetWriteMode(hvg, MG_WRITE_MODE_MULTIPLY); if (overlay) subtrack->lineHeight = tg->lineHeight; subtrack->drawItems(subtrack, seqStart, seqEnd, hvg, xOff, y, width, font, color, vis); if (!overlay) y += height + 1; - hvGfxSetWriteMode(hvg, MG_WRITE_MODE_NORMAL); hvGfxUnclip(hvg); } } } + +if (wigCart->transparent) + { + floatPicIntoHvg(floatPic, xOff, yOff, hvg); + floatPicFree(&floatPic); + } + char *url = trackUrl(tg->track, chromName); mapBoxHgcOrHgGene(hvg, seqStart, seqEnd, xOff, y, width, tg->height, tg->track, tg->track, NULL, url, TRUE, NULL); } static int multiWigTotalHeight(struct track *tg, enum trackVisibility vis) /* Return total height of multiWigcontainer. */ { char *aggregate = wigFetchAggregateValWithCart(cart, tg->tdb); boolean overlay = wigIsOverlayTypeAggregate(aggregate); int totalHeight = 0; if (overlay) totalHeight = wigTotalHeight(tg, vis); struct track *subtrack; for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next)