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 
23 SkTDMemberInfoArray gInfos;
24 SkTDIntArray gInfosCounts;
25 SkTDDisplayTypesArray gInfosTypeIDs;
26 SkTDMemberInfoArray gUnknowns;
27 SkTDIntArray gUnknownsCounts;
28 
AddInfo(SkDisplayTypes type,const SkMemberInfo * info,int infoCount)29 static 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 
WriteInfo(FILE * condensed,const SkMemberInfo * info,int infoCount,const char * typeName,bool draw,bool display)54 static 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 
Get3DName(char * scratch,const char * name)88 static 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 
type_compare(const void * a,const void * b)99 int 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 
BuildCondensedInfo(SkAnimateMaker * maker)105 void 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"
BuildCondensedInfo(SkAnimateMaker *)281 void SkDisplayType::BuildCondensedInfo(SkAnimateMaker* ) {}
282 #endif
283