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