b8180d9f6d41dc708a2f249ba892cbca311e7a06 jcasper Mon Feb 27 11:38:55 2023 -0800 Adding transparency support for colors refs #30569 diff --git src/lib/basicBed.c src/lib/basicBed.c index fa0db23..5d46a6f 100644 --- src/lib/basicBed.c +++ src/lib/basicBed.c @@ -10,31 +10,31 @@ /* Copyright (C) 2014 The Regents of the University of California * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ #include "common.h" #include "hash.h" #include "linefile.h" #include "dystring.h" #include "sqlNum.h" #include "sqlList.h" #include "rangeTree.h" #include "binRange.h" #include "asParse.h" #include "htmlColor.h" #include "basicBed.h" - +#include "memgfx.h" void bedStaticLoad(char **row, struct bed *ret) /* Load a row from bed table into ret. The contents of ret will * be replaced at the next call to this function. */ { ret->chrom = row[0]; ret->chromStart = sqlUnsigned(row[1]); ret->chromEnd = sqlUnsigned(row[2]); ret->name = row[3]; } struct bed *bedLoad(char **row) /* Load a bed from row fetched with select * from bed * from database. Dispose of this with bedFree(). */ { @@ -1014,62 +1014,95 @@ assert(size > 1); hashAdd(hash, name, bk); } } while (lineFileNextRow(bf, row, ArraySize(row))) { bed = bedLoadN(row, wordCount); bk = hashMustFindVal(hash, bed->chrom); binKeeperAdd(bk, bed->chromStart, bed->chromEnd, bed); } lineFileClose(&bf); lineFileClose(&lf); return hash; } +struct rgbColor bedColorToRgb(unsigned int color) +/* Convert from the bed concept of a color uint, where the rgb bits + * are always in the same order, to a memgfx color structure. */ +{ + Color gfxColor = bedColorToGfxColor(color); + return colorIxToRgb(gfxColor); +} + +Color bedColorToGfxColor(unsigned int color) +/* Convert from the bed concept of a color uint, where the rgb bits + * are always in the same order, to a memgfx concept of color where + * the bit order depends on architecture. Assumes that a bed color + * will never have 0 alpha. */ +{ + int r,g,b,a; + a = (color & 0xff000000) >> 24; + if (a == 0) + a = 0xff; + r = (color & 0xff0000) >> 16; + g = (color & 0xff00) >> 8; + b = (color & 0xff); + return MAKECOLOR_32_A(r,g,b,a); +} + void bedOutputRgb(FILE *f, unsigned int color) -/* Output a string: "r,g,b" for 24 bit number */ +/* Output a string: "r,g,b" for 24 bit number. Note + * that this ignores any associated alpha value. */ { -int colorIx = (int)color; -struct rgbColor rgb = colorIxToRgb(colorIx); -//fprintf(f, "%d,%d,%d", rgb.r, rgb.g, rgb.b); -// FIXME: endian issue ?? -fprintf(f, "%d,%d,%d", rgb.b, rgb.g, rgb.r); +struct rgbColor rgb = bedColorToRgb(color); +fprintf(f, "%d,%d,%d", rgb.r, rgb.g, rgb.b); } -int bedParseRgb(char *itemRgb) -/* parse a string: "r,g,b" into three unsigned char values - returned as 24 bit number, or -1 for failure */ +unsigned int bedParseRgb(char *itemRgb) +/* parse a string: "r,g,b" with optional ",a" into three or four unsigned + * char values returned as 32 bit number, or -1 for failure. Byte order + * has alpha in the highest-order byte, then r, then g, then b in the + * lowest-order byte. This is a "bed" concept of an unsigned color, + * which may not match the way the graphics libraries handle color bytes. */ { char dupe[64]; int wordCount; char *row[4]; strncpy(dupe, itemRgb, sizeof(dupe)); wordCount = chopString(dupe, ",", row, ArraySize(row)); -if ((wordCount != 3) || (!isdigit(row[0][0]) || - !isdigit(row[1][0]) || !isdigit(row[2][0]))) - return (-1); +if ((wordCount == 3) && (isdigit(row[0][0]) && + isdigit(row[1][0]) && isdigit(row[2][0]))) + return ( ((atoi(row[0]) & 0xff) << 16) | + ((atoi(row[1]) & 0xff) << 8) | + (atoi(row[2]) & 0xff) | + (0xff << 24)); +if ((wordCount == 4) && (isdigit(row[0][0]) && + isdigit(row[1][0]) && isdigit(row[2][0]) && isdigit(row[3][0]))) return ( ((atoi(row[0]) & 0xff) << 16) | ((atoi(row[1]) & 0xff) << 8) | - (atoi(row[2]) & 0xff) ); + (atoi(row[2]) & 0xff) | + ((atoi(row[3]) & 0xff) << 24) ); + +return (-1); } -int bedParseColor(char *colorSpec) -/* Parse an HTML color string, a string of 3 comma-sep unsigned color values 0-255, +unsigned int bedParseColor(char *colorSpec) +/* Parse an HTML color string, a string of 3 or 4 comma-sep unsigned color values 0-255, * or a 6-digit hex string preceded by #. * O/w return unsigned integer value. Return -1 on error */ { if (strchr(colorSpec,',')) return bedParseRgb(colorSpec); unsigned rgb; if (htmlColorForCode(colorSpec, &rgb)) return rgb; if (htmlColorForName(colorSpec, &rgb)) return rgb; return sqlUnsigned(colorSpec); } long long bedTotalSize(struct bed *bedList) /* Add together sizes of all beds in list. */ @@ -1474,34 +1507,41 @@ bed->name, bed->chromStart, bed->chromEnd, bed->thickStart, bed->thickEnd); } else bed->thickEnd = bed->chromEnd; if (bedFieldCount > 8) { if (strchr(row[8],',')) { unsigned char colors[4]; char *saveColorString = cloneString(row[8]); int numColors = lineFileAllIntsArray(lf, row, 8, colors, sizeof colors, FALSE, 1, "integer", FALSE); if (numColors == 3) { - bed->itemRgb = (((unsigned)colors[0]) << 2*8) | (((unsigned)colors[1]) << 1*8) | (unsigned)colors[2]; + bed->itemRgb = (0xff << 3*8) | (((unsigned)colors[0]) << 2*8) | (((unsigned)colors[1]) << 1*8) | (unsigned)colors[2]; + } + else + { + if (numColors == 4) + { + bed->itemRgb = (((unsigned)colors[3]) << 3*8) | (((unsigned)colors[0]) << 2*8) | (((unsigned)colors[1]) << 1*8) | (unsigned)colors[2]; } else lineFileAbort(lf, "Expecting color to consist of r,g,b values from 0 to 255. Got [%s]", saveColorString); + } freeMem(saveColorString); } else { lineFileAllInts(lf, row, 8, &bed->itemRgb, FALSE, 4, "integer", FALSE); } } int tempArraySize = 1; // How big arrays are below if (bedFieldCount > 9) { lineFileAllInts(lf, row, 9, &bed->blockCount, FALSE, 4, "integer", FALSE); if (!(bed->blockCount >= 1)) lineFileAbort(lf, "Expecting blockCount (%d) to be 1 or more.", bed->blockCount); tempArraySize = bed->blockCount;