1/* libs/graphics/animator/SkBuildCondensedInfo.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkTypes.h"
19#if defined SK_BUILD_CONDENSED
20#include "SkMemberInfo.h"
21#if SK_USE_CONDENSED_INFO == 1
22#error "SK_USE_CONDENSED_INFO must be zero to build condensed info"
23#endif
24#if !defined SK_BUILD_FOR_WIN32
25#error "SK_BUILD_FOR_WIN32 must be defined to build condensed info"
26#endif
27#include "SkDisplayType.h"
28#include "SkIntArray.h"
29#include <stdio.h>
30
31SkTDMemberInfoArray gInfos;
32SkTDIntArray gInfosCounts;
33SkTDDisplayTypesArray gInfosTypeIDs;
34SkTDMemberInfoArray gUnknowns;
35SkTDIntArray gUnknownsCounts;
36
37static void AddInfo(SkDisplayTypes type, const SkMemberInfo* info, int infoCount) {
38    SkASSERT(gInfos[type] == NULL);
39    gInfos[type] = info;
40    gInfosCounts[type] = infoCount;
41    *gInfosTypeIDs.append() = type;
42    size_t allStrs = 0;
43    for (int inner = 0; inner < infoCount; inner++) {
44        SkASSERT(info[inner].fCount < 256);
45        int offset = (int) info[inner].fOffset;
46        SkASSERT(offset < 128 && offset > -129);
47        SkASSERT(allStrs < 256);
48        if (info[inner].fType == SkType_BaseClassInfo) {
49            const SkMemberInfo* innerInfo = (const SkMemberInfo*) info[inner].fName;
50            if (gUnknowns.find(innerInfo) == -1) {
51                *gUnknowns.append() = innerInfo;
52                *gUnknownsCounts.append() = info[inner].fCount;
53            }
54        }
55        if (info[inner].fType != SkType_BaseClassInfo && info[inner].fName)
56            allStrs += strlen(info[inner].fName);
57        allStrs += 1;
58        SkASSERT(info[inner].fType < 256);
59    }
60}
61
62static void WriteInfo(FILE* condensed, const SkMemberInfo* info, int infoCount,
63            const char* typeName, bool draw, bool display) {
64    fprintf(condensed, "static const char g%sStrings[] = \n", typeName);
65    int inner;
66    // write strings
67    for (inner = 0; inner < infoCount; inner++) {
68        const char* name = (info[inner].fType != SkType_BaseClassInfo && info[inner].fName) ?
69            info[inner].fName : "";
70        const char* zero = inner < infoCount - 1 ? "\\0" : "";
71        fprintf(condensed, "\t\"%s%s\"\n", name, zero);
72    }
73    fprintf(condensed, ";\n\nstatic const SkMemberInfo g%s", draw ? "Draw" : display ? "Display" : "");
74    fprintf(condensed, "%sInfo[] = {", typeName);
75    size_t nameOffset = 0;
76    // write info tables
77    for (inner = 0; inner < infoCount; inner++) {
78        size_t offset = info[inner].fOffset;
79        if (info[inner].fType == SkType_BaseClassInfo) {
80            offset = (size_t) gInfos.find((const SkMemberInfo* ) info[inner].fName);
81            SkASSERT((int) offset >= 0);
82            offset = gInfosTypeIDs.find((SkDisplayTypes) offset);
83            SkASSERT((int) offset >= 0);
84        }
85        fprintf(condensed, "\n\t{%d, %d, %d, %d}", nameOffset, offset,
86            info[inner].fType, info[inner].fCount);
87        if (inner < infoCount - 1)
88            putc(',', condensed);
89        if (info[inner].fType != SkType_BaseClassInfo && info[inner].fName)
90            nameOffset += strlen(info[inner].fName);
91        nameOffset += 1;
92    }
93    fprintf(condensed, "\n};\n\n");
94}
95
96static void Get3DName(char* scratch, const char* name) {
97    if (strncmp("skia3d:", name, sizeof("skia3d:") - 1) == 0) {
98        strcpy(scratch, "3D_");
99        scratch[3]= name[7] & ~0x20;
100        strcpy(&scratch[4], &name[8]);
101    } else {
102        scratch[0] = name[0] & ~0x20;
103        strcpy(&scratch[1], &name[1]);
104    }
105}
106
107int type_compare(const void* a, const void* b) {
108    SkDisplayTypes first = *(SkDisplayTypes*) a;
109    SkDisplayTypes second = *(SkDisplayTypes*) b;
110    return first < second ? -1 : first == second ? 0 : 1;
111}
112
113void SkDisplayType::BuildCondensedInfo(SkAnimateMaker* maker) {
114    gInfos.setCount(kNumberOfTypes);
115    memset(gInfos.begin(), 0, sizeof(gInfos[0]) * kNumberOfTypes);
116    gInfosCounts.setCount(kNumberOfTypes);
117    memset(gInfosCounts.begin(), -1, sizeof(gInfosCounts[0]) * kNumberOfTypes);
118    // check to see if it is condensable
119    int index, infoCount;
120    for (index = 0; index < kTypeNamesSize; index++) {
121        const SkMemberInfo* info = GetMembers(maker, gTypeNames[index].fType, &infoCount);
122        if (info == NULL)
123            continue;
124        AddInfo(gTypeNames[index].fType, info, infoCount);
125    }
126    const SkMemberInfo* extraInfo =
127        SkDisplayType::GetMembers(maker, SkType_3D_Point, &infoCount);
128    AddInfo(SkType_Point, extraInfo, infoCount);
129    AddInfo(SkType_3D_Point, extraInfo, infoCount);
130//  int baseInfos = gInfos.count();
131    do {
132        SkTDMemberInfoArray oldRefs = gUnknowns;
133        SkTDIntArray oldRefCounts = gUnknownsCounts;
134        gUnknowns.reset();
135        gUnknownsCounts.reset();
136        for (index = 0; index < oldRefs.count(); index++) {
137            const SkMemberInfo* info = oldRefs[index];
138            if (gInfos.find(info) == -1) {
139                int typeIndex = 0;
140                for (; typeIndex < kNumberOfTypes; typeIndex++) {
141                    const SkMemberInfo* temp = SkDisplayType::GetMembers(
142                        maker, (SkDisplayTypes) typeIndex, NULL);
143                    if (temp == info)
144                        break;
145                }
146                SkASSERT(typeIndex < kNumberOfTypes);
147                AddInfo((SkDisplayTypes) typeIndex, info, oldRefCounts[index]);
148            }
149        }
150    } while (gUnknowns.count() > 0);
151    qsort(gInfosTypeIDs.begin(), gInfosTypeIDs.count(), sizeof(gInfosTypeIDs[0]), &type_compare);
152#ifdef SK_DEBUG
153    FILE* condensed = fopen("../../src/animator/SkCondensedDebug.cpp", "w+");
154    fprintf(condensed, "#include \"SkTypes.h\"\n");
155    fprintf(condensed, "#ifdef SK_DEBUG\n");
156#else
157    FILE* condensed = fopen("../../src/animator/SkCondensedRelease.cpp", "w+");
158    fprintf(condensed, "#include \"SkTypes.h\"\n");
159    fprintf(condensed, "#ifdef SK_RELEASE\n");
160#endif
161    // write header
162    fprintf(condensed, "// This file was automatically generated.\n");
163    fprintf(condensed, "// To change it, edit the file with the matching debug info.\n");
164    fprintf(condensed, "// Then execute SkDisplayType::BuildCondensedInfo() to "
165        "regenerate this file.\n\n");
166    // write name of memberInfo
167    int typeNameIndex = 0;
168    int unknown = 1;
169    for (index = 0; index < gInfos.count(); index++) {
170        const SkMemberInfo* info = gInfos[index];
171        if (info == NULL)
172            continue;
173        char scratch[64];
174        bool drawPrefix, displayPrefix;
175        while (gTypeNames[typeNameIndex].fType < index)
176            typeNameIndex++;
177        if (gTypeNames[typeNameIndex].fType == index) {
178            Get3DName(scratch, gTypeNames[typeNameIndex].fName);
179            drawPrefix = gTypeNames[typeNameIndex].fDrawPrefix;
180            displayPrefix = gTypeNames[typeNameIndex].fDisplayPrefix;
181        } else {
182            sprintf(scratch, "Unknown%d", unknown++);
183            drawPrefix = displayPrefix = false;
184        }
185        WriteInfo(condensed, info, gInfosCounts[index], scratch, drawPrefix, displayPrefix);
186    }
187    // write array of table pointers
188//  start here;
189    fprintf(condensed, "static const SkMemberInfo* const gInfoTables[] = {");
190    typeNameIndex = 0;
191    unknown = 1;
192    for (index = 0; index < gInfos.count(); index++) {
193        const SkMemberInfo* info = gInfos[index];
194        if (info == NULL)
195            continue;
196        char scratch[64];
197        bool drawPrefix, displayPrefix;
198        while (gTypeNames[typeNameIndex].fType < index)
199            typeNameIndex++;
200        if (gTypeNames[typeNameIndex].fType == index) {
201            Get3DName(scratch, gTypeNames[typeNameIndex].fName);
202            drawPrefix = gTypeNames[typeNameIndex].fDrawPrefix;
203            displayPrefix = gTypeNames[typeNameIndex].fDisplayPrefix;
204        } else {
205            sprintf(scratch, "Unknown%d", unknown++);
206            drawPrefix = displayPrefix = false;
207        }
208        fprintf(condensed, "\n\tg");
209        if (drawPrefix)
210            fprintf(condensed, "Draw");
211        if (displayPrefix)
212            fprintf(condensed, "Display");
213        fprintf(condensed, "%sInfo", scratch);
214        if (index < gInfos.count() - 1)
215                putc(',', condensed);
216    }
217    fprintf(condensed, "\n};\n\n");
218    // write the array of number of entries in the info table
219    fprintf(condensed, "static const unsigned char gInfoCounts[] = {\n\t");
220    int written = 0;
221    for (index = 0; index < gInfosCounts.count(); index++) {
222        int count = gInfosCounts[index];
223        if (count < 0)
224            continue;
225        if (written > 0)
226            putc(',', condensed);
227        if (written % 20 == 19)
228            fprintf(condensed, "\n\t");
229        fprintf(condensed, "%d",count);
230        written++;
231    }
232    fprintf(condensed, "\n};\n\n");
233    // write array of type ids table entries correspond to
234    fprintf(condensed, "static const unsigned char gTypeIDs[] = {\n\t");
235    int typeIDCount = 0;
236    typeNameIndex = 0;
237    unknown = 1;
238    for (index = 0; index < gInfosCounts.count(); index++) {
239        const SkMemberInfo* info = gInfos[index];
240        if (info == NULL)
241            continue;
242        typeIDCount++;
243        char scratch[64];
244        while (gTypeNames[typeNameIndex].fType < index)
245            typeNameIndex++;
246        if (gTypeNames[typeNameIndex].fType == index) {
247            Get3DName(scratch, gTypeNames[typeNameIndex].fName);
248        } else
249            sprintf(scratch, "Unknown%d", unknown++);
250        fprintf(condensed, "%d%c // %s\n\t", index,
251            index < gInfosCounts.count() ? ',' : ' ', scratch);
252    }
253    fprintf(condensed, "\n};\n\n");
254    fprintf(condensed, "static const int kTypeIDs = %d;\n\n", typeIDCount);
255    // write the array of string pointers
256    fprintf(condensed, "static const char* const gInfoNames[] = {");
257    typeNameIndex = 0;
258    unknown = 1;
259    written = 0;
260    for (index = 0; index < gInfosCounts.count(); index++) {
261        const SkMemberInfo* info = gInfos[index];
262        if (info == NULL)
263            continue;
264        if (written > 0)
265                putc(',', condensed);
266        written++;
267        fprintf(condensed, "\n\tg");
268        char scratch[64];
269        while (gTypeNames[typeNameIndex].fType < index)
270            typeNameIndex++;
271        if (gTypeNames[typeNameIndex].fType == index) {
272            Get3DName(scratch, gTypeNames[typeNameIndex].fName);
273        } else
274            sprintf(scratch, "Unknown%d", unknown++);
275        fprintf(condensed, "%sStrings", scratch);
276    }
277    fprintf(condensed, "\n};\n\n");
278    fprintf(condensed, "#endif\n");
279    fclose(condensed);
280    gInfos.reset();
281    gInfosCounts.reset();
282    gInfosTypeIDs.reset();
283    gUnknowns.reset();
284    gUnknownsCounts.reset();
285}
286
287#elif defined SK_DEBUG
288#include "SkDisplayType.h"
289void SkDisplayType::BuildCondensedInfo(SkAnimateMaker* ) {}
290#endif
291
292
293