| /* | |
| * Copyright 2006 The Android Open Source Project | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "SkTypes.h" | |
| #if defined SK_BUILD_CONDENSED | |
| #include "SkMemberInfo.h" | |
| #if SK_USE_CONDENSED_INFO == 1 | |
| #error "SK_USE_CONDENSED_INFO must be zero to build condensed info" | |
| #endif | |
| #if !defined SK_BUILD_FOR_WIN32 | |
| #error "SK_BUILD_FOR_WIN32 must be defined to build condensed info" | |
| #endif | |
| #include "SkDisplayType.h" | |
| #include "SkIntArray.h" | |
| #include <stdio.h> | |
| SkTDMemberInfoArray gInfos; | |
| SkTDIntArray gInfosCounts; | |
| SkTDDisplayTypesArray gInfosTypeIDs; | |
| SkTDMemberInfoArray gUnknowns; | |
| SkTDIntArray gUnknownsCounts; | |
| static void AddInfo(SkDisplayTypes type, const SkMemberInfo* info, int infoCount) { | |
| SkASSERT(gInfos[type] == nullptr); | |
| gInfos[type] = info; | |
| gInfosCounts[type] = infoCount; | |
| *gInfosTypeIDs.append() = type; | |
| size_t allStrs = 0; | |
| for (int inner = 0; inner < infoCount; inner++) { | |
| SkASSERT(info[inner].fCount < 256); | |
| int offset = (int) info[inner].fOffset; | |
| SkASSERT(offset < 128 && offset > -129); | |
| SkASSERT(allStrs < 256); | |
| if (info[inner].fType == SkType_BaseClassInfo) { | |
| const SkMemberInfo* innerInfo = (const SkMemberInfo*) info[inner].fName; | |
| if (gUnknowns.find(innerInfo) == -1) { | |
| *gUnknowns.append() = innerInfo; | |
| *gUnknownsCounts.append() = info[inner].fCount; | |
| } | |
| } | |
| if (info[inner].fType != SkType_BaseClassInfo && info[inner].fName) | |
| allStrs += strlen(info[inner].fName); | |
| allStrs += 1; | |
| SkASSERT(info[inner].fType < 256); | |
| } | |
| } | |
| static void WriteInfo(FILE* condensed, const SkMemberInfo* info, int infoCount, | |
| const char* typeName, bool draw, bool display) { | |
| fprintf(condensed, "static const char g%sStrings[] = \n", typeName); | |
| int inner; | |
| // write strings | |
| for (inner = 0; inner < infoCount; inner++) { | |
| const char* name = (info[inner].fType != SkType_BaseClassInfo && info[inner].fName) ? | |
| info[inner].fName : ""; | |
| const char* zero = inner < infoCount - 1 ? "\\0" : ""; | |
| fprintf(condensed, "\t\"%s%s\"\n", name, zero); | |
| } | |
| fprintf(condensed, ";\n\nstatic const SkMemberInfo g%s", draw ? "Draw" : display ? "Display" : ""); | |
| fprintf(condensed, "%sInfo[] = {", typeName); | |
| size_t nameOffset = 0; | |
| // write info tables | |
| for (inner = 0; inner < infoCount; inner++) { | |
| size_t offset = info[inner].fOffset; | |
| if (info[inner].fType == SkType_BaseClassInfo) { | |
| offset = (size_t) gInfos.find((const SkMemberInfo* ) info[inner].fName); | |
| SkASSERT((int) offset >= 0); | |
| offset = gInfosTypeIDs.find((SkDisplayTypes) offset); | |
| SkASSERT((int) offset >= 0); | |
| } | |
| fprintf(condensed, "\n\t{%d, %d, %d, %d}", nameOffset, offset, | |
| info[inner].fType, info[inner].fCount); | |
| if (inner < infoCount - 1) | |
| putc(',', condensed); | |
| if (info[inner].fType != SkType_BaseClassInfo && info[inner].fName) | |
| nameOffset += strlen(info[inner].fName); | |
| nameOffset += 1; | |
| } | |
| fprintf(condensed, "\n};\n\n"); | |
| } | |
| static void Get3DName(char* scratch, const char* name) { | |
| if (strncmp("skia3d:", name, sizeof("skia3d:") - 1) == 0) { | |
| strcpy(scratch, "3D_"); | |
| scratch[3]= name[7] & ~0x20; | |
| strcpy(&scratch[4], &name[8]); | |
| } else { | |
| scratch[0] = name[0] & ~0x20; | |
| strcpy(&scratch[1], &name[1]); | |
| } | |
| } | |
| int type_compare(const void* a, const void* b) { | |
| SkDisplayTypes first = *(SkDisplayTypes*) a; | |
| SkDisplayTypes second = *(SkDisplayTypes*) b; | |
| return first < second ? -1 : first == second ? 0 : 1; | |
| } | |
| void SkDisplayType::BuildCondensedInfo(SkAnimateMaker* maker) { | |
| gInfos.setCount(kNumberOfTypes); | |
| memset(gInfos.begin(), 0, sizeof(gInfos[0]) * kNumberOfTypes); | |
| gInfosCounts.setCount(kNumberOfTypes); | |
| memset(gInfosCounts.begin(), -1, sizeof(gInfosCounts[0]) * kNumberOfTypes); | |
| // check to see if it is condensable | |
| int index, infoCount; | |
| for (index = 0; index < kTypeNamesSize; index++) { | |
| const SkMemberInfo* info = GetMembers(maker, gTypeNames[index].fType, &infoCount); | |
| if (info == nullptr) | |
| continue; | |
| AddInfo(gTypeNames[index].fType, info, infoCount); | |
| } | |
| const SkMemberInfo* extraInfo = | |
| SkDisplayType::GetMembers(maker, SkType_3D_Point, &infoCount); | |
| AddInfo(SkType_Point, extraInfo, infoCount); | |
| AddInfo(SkType_3D_Point, extraInfo, infoCount); | |
| // int baseInfos = gInfos.count(); | |
| do { | |
| SkTDMemberInfoArray oldRefs = gUnknowns; | |
| SkTDIntArray oldRefCounts = gUnknownsCounts; | |
| gUnknowns.reset(); | |
| gUnknownsCounts.reset(); | |
| for (index = 0; index < oldRefs.count(); index++) { | |
| const SkMemberInfo* info = oldRefs[index]; | |
| if (gInfos.find(info) == -1) { | |
| int typeIndex = 0; | |
| for (; typeIndex < kNumberOfTypes; typeIndex++) { | |
| const SkMemberInfo* temp = SkDisplayType::GetMembers( | |
| maker, (SkDisplayTypes) typeIndex, nullptr); | |
| if (temp == info) | |
| break; | |
| } | |
| SkASSERT(typeIndex < kNumberOfTypes); | |
| AddInfo((SkDisplayTypes) typeIndex, info, oldRefCounts[index]); | |
| } | |
| } | |
| } while (gUnknowns.count() > 0); | |
| qsort(gInfosTypeIDs.begin(), gInfosTypeIDs.count(), sizeof(gInfosTypeIDs[0]), &type_compare); | |
| #ifdef SK_DEBUG | |
| FILE* condensed = fopen("../../src/animator/SkCondensedDebug.cpp", "w+"); | |
| fprintf(condensed, "#include \"SkTypes.h\"\n"); | |
| fprintf(condensed, "#ifdef SK_DEBUG\n"); | |
| #else | |
| FILE* condensed = fopen("../../src/animator/SkCondensedRelease.cpp", "w+"); | |
| fprintf(condensed, "#include \"SkTypes.h\"\n"); | |
| fprintf(condensed, "#ifdef SK_RELEASE\n"); | |
| #endif | |
| // write header | |
| fprintf(condensed, "// This file was automatically generated.\n"); | |
| fprintf(condensed, "// To change it, edit the file with the matching debug info.\n"); | |
| fprintf(condensed, "// Then execute SkDisplayType::BuildCondensedInfo() to " | |
| "regenerate this file.\n\n"); | |
| // write name of memberInfo | |
| int typeNameIndex = 0; | |
| int unknown = 1; | |
| for (index = 0; index < gInfos.count(); index++) { | |
| const SkMemberInfo* info = gInfos[index]; | |
| if (info == nullptr) | |
| continue; | |
| char scratch[64]; | |
| bool drawPrefix, displayPrefix; | |
| while (gTypeNames[typeNameIndex].fType < index) | |
| typeNameIndex++; | |
| if (gTypeNames[typeNameIndex].fType == index) { | |
| Get3DName(scratch, gTypeNames[typeNameIndex].fName); | |
| drawPrefix = gTypeNames[typeNameIndex].fDrawPrefix; | |
| displayPrefix = gTypeNames[typeNameIndex].fDisplayPrefix; | |
| } else { | |
| sprintf(scratch, "Unknown%d", unknown++); | |
| drawPrefix = displayPrefix = false; | |
| } | |
| WriteInfo(condensed, info, gInfosCounts[index], scratch, drawPrefix, displayPrefix); | |
| } | |
| // write array of table pointers | |
| // start here; | |
| fprintf(condensed, "static const SkMemberInfo* const gInfoTables[] = {"); | |
| typeNameIndex = 0; | |
| unknown = 1; | |
| for (index = 0; index < gInfos.count(); index++) { | |
| const SkMemberInfo* info = gInfos[index]; | |
| if (info == nullptr) | |
| continue; | |
| char scratch[64]; | |
| bool drawPrefix, displayPrefix; | |
| while (gTypeNames[typeNameIndex].fType < index) | |
| typeNameIndex++; | |
| if (gTypeNames[typeNameIndex].fType == index) { | |
| Get3DName(scratch, gTypeNames[typeNameIndex].fName); | |
| drawPrefix = gTypeNames[typeNameIndex].fDrawPrefix; | |
| displayPrefix = gTypeNames[typeNameIndex].fDisplayPrefix; | |
| } else { | |
| sprintf(scratch, "Unknown%d", unknown++); | |
| drawPrefix = displayPrefix = false; | |
| } | |
| fprintf(condensed, "\n\tg"); | |
| if (drawPrefix) | |
| fprintf(condensed, "Draw"); | |
| if (displayPrefix) | |
| fprintf(condensed, "Display"); | |
| fprintf(condensed, "%sInfo", scratch); | |
| if (index < gInfos.count() - 1) | |
| putc(',', condensed); | |
| } | |
| fprintf(condensed, "\n};\n\n"); | |
| // write the array of number of entries in the info table | |
| fprintf(condensed, "static const unsigned char gInfoCounts[] = {\n\t"); | |
| int written = 0; | |
| for (index = 0; index < gInfosCounts.count(); index++) { | |
| int count = gInfosCounts[index]; | |
| if (count < 0) | |
| continue; | |
| if (written > 0) | |
| putc(',', condensed); | |
| if (written % 20 == 19) | |
| fprintf(condensed, "\n\t"); | |
| fprintf(condensed, "%d",count); | |
| written++; | |
| } | |
| fprintf(condensed, "\n};\n\n"); | |
| // write array of type ids table entries correspond to | |
| fprintf(condensed, "static const unsigned char gTypeIDs[] = {\n\t"); | |
| int typeIDCount = 0; | |
| typeNameIndex = 0; | |
| unknown = 1; | |
| for (index = 0; index < gInfosCounts.count(); index++) { | |
| const SkMemberInfo* info = gInfos[index]; | |
| if (info == nullptr) | |
| continue; | |
| typeIDCount++; | |
| char scratch[64]; | |
| while (gTypeNames[typeNameIndex].fType < index) | |
| typeNameIndex++; | |
| if (gTypeNames[typeNameIndex].fType == index) { | |
| Get3DName(scratch, gTypeNames[typeNameIndex].fName); | |
| } else | |
| sprintf(scratch, "Unknown%d", unknown++); | |
| fprintf(condensed, "%d%c // %s\n\t", index, | |
| index < gInfosCounts.count() ? ',' : ' ', scratch); | |
| } | |
| fprintf(condensed, "\n};\n\n"); | |
| fprintf(condensed, "static const int kTypeIDs = %d;\n\n", typeIDCount); | |
| // write the array of string pointers | |
| fprintf(condensed, "static const char* const gInfoNames[] = {"); | |
| typeNameIndex = 0; | |
| unknown = 1; | |
| written = 0; | |
| for (index = 0; index < gInfosCounts.count(); index++) { | |
| const SkMemberInfo* info = gInfos[index]; | |
| if (info == nullptr) | |
| continue; | |
| if (written > 0) | |
| putc(',', condensed); | |
| written++; | |
| fprintf(condensed, "\n\tg"); | |
| char scratch[64]; | |
| while (gTypeNames[typeNameIndex].fType < index) | |
| typeNameIndex++; | |
| if (gTypeNames[typeNameIndex].fType == index) { | |
| Get3DName(scratch, gTypeNames[typeNameIndex].fName); | |
| } else | |
| sprintf(scratch, "Unknown%d", unknown++); | |
| fprintf(condensed, "%sStrings", scratch); | |
| } | |
| fprintf(condensed, "\n};\n\n"); | |
| fprintf(condensed, "#endif\n"); | |
| fclose(condensed); | |
| gInfos.reset(); | |
| gInfosCounts.reset(); | |
| gInfosTypeIDs.reset(); | |
| gUnknowns.reset(); | |
| gUnknownsCounts.reset(); | |
| } | |
| #elif defined SK_DEBUG | |
| #include "SkDisplayType.h" | |
| void SkDisplayType::BuildCondensedInfo(SkAnimateMaker* ) {} | |
| #endif |