ShaderVariation* Shader::GetVariation(ShaderType type, const char* defines) { StringHash definesHash(defines); HashMap<StringHash, SharedPtr<ShaderVariation> > & variations(type == VS ? vsVariations_ : psVariations_); HashMap<StringHash, SharedPtr<ShaderVariation> >::Iterator i = variations.Find(definesHash); if (i == variations.End()) { // If shader not found, normalize the defines (to prevent duplicates) and check again. In that case make an alias // so that further queries are faster String normalizedDefines = NormalizeDefines(defines); StringHash normalizedHash(normalizedDefines); i = variations.Find(normalizedHash); if (i != variations.End()) variations.Insert(MakePair(definesHash, i->second_)); else { // No shader variation found. Create new i = variations.Insert(MakePair(normalizedHash, SharedPtr<ShaderVariation>(new ShaderVariation(this, type)))); if (definesHash != normalizedHash) variations.Insert(MakePair(definesHash, i->second_)); i->second_->SetName(GetFileName(GetName())); i->second_->SetDefines(normalizedDefines); ++numVariations_; RefreshMemoryUse(); } } return i->second_; }
int main(int argc, char *argv[]) { FILE *src = fopen(argv[1], "r"); FILE *dest = fopen(argv[2], "w"); isSTIX = isMath = 0; if (src == NULL) { fprintf(stderr, "Need %s\n", argv[1]); exit(1); } if (dest == NULL) { fprintf(stderr, "Need to write to %s\n", argv[2]); exit(1); } if (strstr(argv[1], "STIX") != NULL) isSTIX = 1; if (strstr(argv[1], "Math") != NULL) isMath = 1; if (isSTIX) { int private_area = 0; nmoved = 0; for (;;) { int c, i = 0, width; while ((c = getc(src)) != EOF && c != '\n') linebuffer[i++] = c; linebuffer[i] = 0; if (i == 0 && c == EOF) break; adjustuninames(linebuffer, 0); // For the STIX fonts that I am using the glyph that fontforge displays as // if it had been at U+110000 is named ".notdef". Here I collect the // names that have been provided for all those out-of-range glyphs. if (sscanf(linebuffer, "C -1 ; WX %d ; N ", &width) == 1) { char *p = linebuffer + 9; int j = 0; while (*p != ';') p++; p = p + 4; while (*p != ' ') name[j++] = *p++; name[j] = 0; if (strcmp(name, ".notdef") == 0) private_area = 1; if (private_area) { strcpy(movedname[nmoved], name); movedwidth[nmoved] = width; nmoved++; } } } fseek(src, (off_t)0, SEEK_SET); } for (;;) { int c, i = 0; while ((c = getc(src)) != EOF && c != '\n') linebuffer[i++] = c; linebuffer[i] = 0; if (i == 0 && c == EOF) break; if (strcmp(linebuffer, "EndFontMetrics") == 0) continue; adjustuninames(linebuffer, 0); if (strncmp(linebuffer, "C -1 ; ", 7) == 0) { int width, code; if (sscanf(linebuffer, "C -1 ; WX %d ; N u%x ;", &width, &code) == 2) { char *p = linebuffer + 10; while (*p != ';') p++; p++; while (*p == ' ') p++; if (*p != 'N') { printf("Formatting failure\n"); exit(1); } p++; while (*p == ' ') p++; char *q = p; while (*q != ' ') q++; *q = 0; while (*q != ';') q++; *q = 0; const char *r = uniname(code); // If there is an official unicode name for the codepoint I will insert // it. If the codepoint was a copy of one of the STIX glyphs not previously // within the Unicode range I will transfer the name it originally had to the // new position at 0x108xxx. if (r == NULL) { if (code >= 0x108000 && code-0x108000 < nmoved && width == movedwidth[code-0x108000]) r = movedname[code-0x108000]; else r = p; } fprintf(dest, "C %d ; WX %d ; N %s ;%s\n", code, width, r, q+1); } } else fprintf(dest, "%s\n", linebuffer); } fclose(src); if (isMath) { src = fopen("STIXMath.tables", "r"); int topAccent = 0, Variants = 0, offset; int anything = 0, num = 0; int partcount=0, partnumber=0; int start, end, full, flags; if (src == NULL) { fprintf(stderr, "Need STIXMath.tables\n"); exit(1); } for (;;) { int c, i = 0; char *p; // I rather arbitrarily truncate the input lines at 400 characters. Something // like that is needed here because some lines in the "tables" are utterly // and ridiculously long. Specifically the longest line is has almost 28000 // characters on it! That one starts with // "char strings 1476: 597 -273 21 232 20 656 20 176 22 hstemhm 0 60 0 60 0..." // while ((c = getc(src)) != EOF && c != '\n') if (i < 400) linebuffer[i++] = c; linebuffer[i] = 0; if (i == 0 && c == EOF) break; adjustuninames(linebuffer, 1); if (strncmp(linebuffer, " MATH Top Accent", 17) == 0) topAccent = 1; else if (strncmp(linebuffer, " MATH Variants", 14) == 0) { topAccent = 0; Variants = 1; if (anything) fprintf(dest, "EndTopAccent\n"); anything = 0; } if (topAccent && sscanf(linebuffer, " Glyph %s %d", name, &offset) == 2) { if (!anything) { fprintf(dest, "StartTopAccent\n"); anything = 1; } p = strchr(name, '('); if (p != NULL) *p = 0; fprintf(dest, "N %s ; DX %d ;\n", name, offset); } if (Variants) { if (sscanf(linebuffer, " V Glyph %s", name) == 1) { variations(dest, num, n1, n2, n3, n4, n5, p1, p2, p3, p4, p5); num = 0; if (!anything) { fprintf(dest, "StartVariations\n"); anything = 1; } else fprintf(dest, "\n"); p = strchr(name, '('); if (p != NULL) *p = 0; fprintf(dest, "VX %s ;" , name); continue; } if (sscanf(linebuffer, " H Glyph %s", name) == 1) { variations(dest, num, n1, n2, n3, n4, n5, p1, p2, p3, p4, p5); num = 0; if (!anything) { fprintf(dest, "StartVariations\n"); anything = 1; } else fprintf(dest, "\n"); p = strchr(name, '('); if (p != NULL) *p = 0; fprintf(dest, "HX %s ;", name); continue; } if (sscanf(linebuffer, " Variant Count = %d", &num) == 1) continue; switch (num) { case 1: if (sscanf(linebuffer, " Variants: %s", n1) == 1) continue; case 2: if (sscanf(linebuffer, " Variants: %s %s", n1, n2) == 1) continue; case 3: if (sscanf(linebuffer, " Variants: %s %s %s", n1, n2, n3) == 1) continue; case 4: if (sscanf(linebuffer, " Variants: %s %s %s %s", n1, n2, n3, n4) == 1) continue; case 5: if (sscanf(linebuffer, " Variants: %s %s %s %s %s", n1, n2, n3, n4, n5) == 1) continue; } if (sscanf(linebuffer, " Part Count=%d", &partcount) == 1) { partnumber = 0; continue; } if (sscanf(linebuffer, " %s start=%d end=%d full=%d flags=%d(%s", partname, &start, &end, &full, &flags, junk) == 6) { switch (partnumber) { case 0: strcpy(p1, partname); xstart[0] = start; xend[0] = end; xfull[0] = full; xflags[0] = flags; break; case 1: strcpy(p2, partname); xstart[1] = start; xend[1] = end; xfull[1] = full; xflags[1] = flags; break; case 2: strcpy(p3, partname); xstart[2] = start; xend[2] = end; xfull[2] = full; xflags[2] = flags; break; case 3: strcpy(p4, partname); xstart[3] = start; xend[3] = end; xfull[3] = full; xflags[3] = flags; break; case 4: strcpy(p5, partname); xstart[4] = start; xend[4] = end; xfull[4] = full; xflags[4] = flags; break; } printf("Part %4d (%4d %4d %4d %4d %s has name %s \n", ++partnumber, start, end, full, flags, junk, partname); } } } variations(dest, num, n1, n2, n3, n4, n5, p1, p2, p3, p4, p5); if (anything) fprintf(dest, "\nEndVariations\n"); fclose(src); } fprintf(dest, "EndFontMetrics\n"); fclose(dest); return 0; }