diff options
-rw-r--r-- | gyp/common.gypi | 7 | ||||
-rw-r--r-- | gyp/core.gyp | 1 | ||||
-rw-r--r-- | gyp/gpu.gyp | 2 | ||||
-rw-r--r-- | gyp/utils.gyp | 2 | ||||
-rw-r--r-- | include/core/SkOSFile.h | 16 | ||||
-rw-r--r-- | include/core/SkString.h | 24 | ||||
-rw-r--r-- | include/core/SkTDArray.h | 4 | ||||
-rw-r--r-- | include/utils/SkRTConf.h | 135 | ||||
-rw-r--r-- | src/core/SkGraphics.cpp | 9 | ||||
-rw-r--r-- | src/core/SkStream.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 29 | ||||
-rw-r--r-- | src/ports/SkOSFile_stdio.cpp | 17 | ||||
-rw-r--r-- | src/utils/SkRTConf.cpp | 325 |
13 files changed, 556 insertions, 19 deletions
diff --git a/gyp/common.gypi b/gyp/common.gypi index 7dc27da143..810a0f81f5 100644 --- a/gyp/common.gypi +++ b/gyp/common.gypi @@ -82,6 +82,7 @@ 'defines': [ 'SK_DEBUG', 'GR_DEBUG=1', + 'SK_DEVELOPER=1', ], }, 'Release': { @@ -90,6 +91,12 @@ 'GR_RELEASE=1', ], }, + 'Release_Developer': { + 'inherit_from': ['Release'], + 'defines': [ + 'SK_DEVELOPER=1', + ], + }, }, }, # end 'target_defaults' } diff --git a/gyp/core.gyp b/gyp/core.gyp index eddb9400c7..7e7640c639 100644 --- a/gyp/core.gyp +++ b/gyp/core.gyp @@ -17,6 +17,7 @@ '../include/core', '../include/pipe', '../include/ports', + '../include/utils', '../include/xml', '../src/core', '../src/image', diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp index 7438babe59..6c599e162a 100644 --- a/gyp/gpu.gyp +++ b/gyp/gpu.gyp @@ -127,6 +127,7 @@ 'include_dirs': [ '../include/config', '../include/core', + '../include/utils', '../src/core', '../include/gpu', '../src/gpu', @@ -177,6 +178,7 @@ 'include_dirs': [ '../include/core', '../include/config', + '../include/utils', '../include/gpu', '../src/core', # SkRasterClip.h '../src/gpu' diff --git a/gyp/utils.gyp b/gyp/utils.gyp index cd44769fbe..d4942d781a 100644 --- a/gyp/utils.gyp +++ b/gyp/utils.gyp @@ -47,6 +47,7 @@ '../include/utils/SkParsePaint.h', '../include/utils/SkParsePath.h', '../include/utils/SkPictureUtils.h', + '../include/utils/SkRTConf.h', '../include/utils/SkProxyCanvas.h', '../include/utils/SkUnitMappers.h', '../include/utils/SkWGL.h', @@ -81,6 +82,7 @@ '../src/utils/SkParsePath.cpp', '../src/utils/SkPictureUtils.cpp', '../src/utils/SkProxyCanvas.cpp', + '../src/utils/SkRTConf.cpp', '../src/utils/SkThreadUtils.h', '../src/utils/SkThreadUtils_pthread.cpp', '../src/utils/SkThreadUtils_pthread.h', diff --git a/include/core/SkOSFile.h b/include/core/SkOSFile.h index 79551ae206..685248cd00 100644 --- a/include/core/SkOSFile.h +++ b/include/core/SkOSFile.h @@ -18,6 +18,8 @@ #include <dirent.h> #endif +#include <stddef.h> // ptrdiff_t + struct SkFILE; enum SkFILE_Flags { @@ -43,8 +45,8 @@ size_t sk_fread(void* buffer, size_t byteCount, SkFILE*); size_t sk_fwrite(const void* buffer, size_t byteCount, SkFILE*); void sk_fflush(SkFILE*); -int sk_fseek( SkFILE*, size_t, int ); -size_t sk_ftell( SkFILE* ); +int sk_fseek(SkFILE*, size_t, int); +size_t sk_ftell(SkFILE*); // Returns true if something (file, directory, ???) exists at this path. bool sk_exists(const char *path); @@ -52,6 +54,16 @@ bool sk_exists(const char *path); // Returns true if a directory exists at this path. bool sk_isdir(const char *path); +// Get a single line of input from a file. Returns -1 on failure. +// passing NULL for lineptr will allocate memory for the line with +// sk_malloc; make sure to use sk_free to get rid of it when you're +// done. +ptrdiff_t sk_getline(char **lineptr, size_t *n, SkFILE *stream); + +// Have we reached the end of the file? +int sk_feof(SkFILE *); + + // Create a new directory at this path; returns true if successful. // If the directory already existed, this will return true. // Description of the error, if any, will be written to stderr. diff --git a/include/core/SkString.h b/include/core/SkString.h index 94dcf8b438..7ea3969082 100644 --- a/include/core/SkString.h +++ b/include/core/SkString.h @@ -30,16 +30,33 @@ bool SkStrEndsWith(const char string[], const char suffixChar); int SkStrStartsWithOneOf(const char string[], const char prefixes[]); +static int SkStrFind(const char string[], const char substring[]) { + char *first = strstr(string, substring); + if (NULL == first) return -1; + return first - &(string[0]); +} + static bool SkStrContains(const char string[], const char substring[]) { SkASSERT(string); SkASSERT(substring); - return (NULL != strstr(string, substring)); + return (-1 != SkStrFind(string, substring)); } static bool SkStrContains(const char string[], const char subchar) { SkASSERT(string); - return (NULL != strchr(string, subchar)); + char tmp[2]; + tmp[0] = subchar; + tmp[1] = '\0'; + return (-1 != SkStrFind(string, tmp)); +} + +static inline char *SkStrDup(const char string[]) { + char *ret = (char *) sk_malloc_throw(strlen(string)+1); + memcpy(ret,string,strlen(string)); + return ret; } + + #define SkStrAppendS32_MaxSize 11 char* SkStrAppendS32(char buffer[], int32_t); #define SkStrAppendS64_MaxSize 20 @@ -112,6 +129,9 @@ public: bool contains(const char subchar) const { return SkStrContains(fRec->data(), subchar); } + int find(const char substring[]) const { + return SkStrFind(fRec->data(), substring); + } friend bool operator==(const SkString& a, const SkString& b) { return a.equals(b); diff --git a/include/core/SkTDArray.h b/include/core/SkTDArray.h index eaf25c67ae..6f7a60e9ba 100644 --- a/include/core/SkTDArray.h +++ b/include/core/SkTDArray.h @@ -108,6 +108,10 @@ public: SkASSERT((unsigned)index < fCount); return fArray[index]; } + + T& getAt(int index) const { + return (*this)[index]; + } void reset() { if (fArray) { diff --git a/include/utils/SkRTConf.h b/include/utils/SkRTConf.h new file mode 100644 index 0000000000..22d7e606ee --- /dev/null +++ b/include/utils/SkRTConf.h @@ -0,0 +1,135 @@ +/* + * Copyright 2013 Google, Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef SkRTConf_DEFINED +#define SkRTConf_DEFINED + +#include "SkString.h" +#include "SkStream.h" + +#include "SkTDict.h" +#include "SkTArray.h" + +/** \class SkRTConfBase + Non-templated base class for the runtime configs +*/ + +class SkRTConfBase { +public: + SkRTConfBase(const char *name) : fName(name) {} + virtual ~SkRTConfBase() {} + virtual const char *getName() const { return fName.c_str(); } + virtual bool isDefault() const = 0; + virtual void print(SkWStream *o) const = 0; + virtual bool equals(const SkRTConfBase *conf) const = 0; +protected: + SkString fName; +}; + +/** \class SkRTConf + A class to provide runtime configurability. +*/ +template<typename T> class SkRTConf: public SkRTConfBase { +public: + SkRTConf(const char *name, const T &defaultValue, const char *description); + operator const T&() const { return fValue; } + void print(SkWStream *o) const; + bool equals(const SkRTConfBase *conf) const; + bool isDefault() const { return fDefault == fValue; } + void set(const T& value) { fValue = value; } +protected: + void doPrint(char *s) const; + + SkString fDescription; + T fDefault; + T fValue; +}; + +#ifdef SK_DEVELOPER +#define SK_CONF_DECLARE(confType, varName, confName, defaultValue, description) static SkRTConf<confType> varName(confName, defaultValue, description) +#define SK_CONF_SET(confname, value) skRTConfRegistry().set(confname, value) +#else +#define SK_CONF_DECLARE(confType, varName, confName, defaultValue, description) static const confType varName = defaultValue +#define SK_CONF_SET(confname, value) (void) confname, (void) value +#endif + +/** \class SkRTConfRegistry + A class that maintains a systemwide registry of all runtime configuration + parameters. Mainly used for printing them out and handling multiply-defined + knobs. +*/ + +class SkRTConfRegistry { +public: + SkRTConfRegistry(); + void printAll(const char *fname = NULL) const; + void printNonDefault(const char *fname = NULL) const; + const char *configFileLocation() const; + void possiblyDumpFile() const; + void validate() const; + template <typename T> void set(const char *confname, T value); +private: + template<typename T> friend class SkRTConf; + + void registerConf(SkRTConfBase *conf); + template <typename T> bool parse(const char *name, T* value); + + SkTDArray<SkString *> fConfigFileKeys, fConfigFileValues; + typedef SkTDict< SkTDArray<SkRTConfBase *> * > ConfMap; + ConfMap fConfs; +}; + +// our singleton registry + +SkRTConfRegistry &skRTConfRegistry(); + +template<typename T> +SkRTConf<T>::SkRTConf(const char *name, const T &defaultValue, const char *description) + : SkRTConfBase(name) + , fValue(defaultValue) + , fDefault(defaultValue) + , fDescription(description) { + + T value; + if (skRTConfRegistry().parse(fName.c_str(), &value)) { + fValue = value; + } + skRTConfRegistry().registerConf(this); +} + +template<typename T> +void SkRTConf<T>::print(SkWStream *o) const { + char outline[200]; // should be ok because we specify a max. width for everything here. + + sprintf(outline, "%-30.30s", getName()); + doPrint(&(outline[30])); + sprintf(&(outline[60]), " %.128s", fDescription.c_str()); + if (' ' == outline[strlen(outline)-1]) { + for (int i = strlen(outline)-1 ; ' ' == outline[i] ; i--) { + outline[i] = '\0'; + } + } + o->writeText(outline); +} + +template<typename T> +void SkRTConf<T>::doPrint(char *s) const { + sprintf(s, "%-30.30s", "How do I print myself??"); +} + +template<typename T> +bool SkRTConf<T>::equals(const SkRTConfBase *conf) const { + const SkRTConf<T> *child_pointer = dynamic_cast<const SkRTConf<T> *>(conf); + return child_pointer && + fName == child_pointer->fName && + fDescription == child_pointer->fDescription && + fValue == child_pointer->fValue && + fDefault == child_pointer->fDefault; +} + +#endif diff --git a/src/core/SkGraphics.cpp b/src/core/SkGraphics.cpp index 53d0318251..d0d64dece0 100644 --- a/src/core/SkGraphics.cpp +++ b/src/core/SkGraphics.cpp @@ -21,6 +21,7 @@ #include "SkPixelRef.h" #include "SkRandom.h" #include "SkRefCnt.h" +#include "SkRTConf.h" #include "SkScalerContext.h" #include "SkShader.h" #include "SkStream.h" @@ -52,6 +53,13 @@ void SkGraphics::GetVersion(int32_t* major, int32_t* minor, int32_t* patch) { #endif void SkGraphics::Init() { +#ifdef SK_DEVELOPER + skRTConfRegistry().possiblyDumpFile(); + skRTConfRegistry().validate(); + SkDebugf("Non-default runtime configuration options:\n"); + skRTConfRegistry().printNonDefault( ); +#endif + SkFlattenable::InitializeFlattenables(); #ifdef BUILD_EMBOSS_TABLE SkEmbossMask_BuildTable(); @@ -116,6 +124,7 @@ void SkGraphics::Init() { GetFontCacheLimit() >> 10); #endif + } void SkGraphics::Term() { diff --git a/src/core/SkStream.cpp b/src/core/SkStream.cpp index 59b5da3304..fb343ea76a 100644 --- a/src/core/SkStream.cpp +++ b/src/core/SkStream.cpp @@ -773,14 +773,14 @@ void SkDynamicMemoryWStream::invalidateCopy() { void SkDebugWStream::newline() { -#ifdef SK_DEBUG +#if defined(SK_DEBUG) || defined(SK_DEVELOPER) SkDebugf("\n"); #endif } bool SkDebugWStream::write(const void* buffer, size_t size) { -#ifdef SK_DEBUG +#if defined(SK_DEBUG) || defined(SK_DEVELOPER) char* s = new char[size+1]; memcpy(s, buffer, size); s[size] = 0; diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 63e991f654..1b472020c1 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -16,12 +16,14 @@ #include "SkTrace.h" #include "SkXfermode.h" +#include "SkRTConf.h" + SK_DEFINE_INST_COUNT(GrGLProgram) #define GL_CALL(X) GR_GL_CALL(fContextInfo.interface(), X) #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fContextInfo.interface(), R, X) -#define PRINT_SHADERS 0 +SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, "Print the source code for all shaders generated."); #define COL_ATTR_NAME "aColor" #define COV_ATTR_NAME "aCoverage" @@ -457,20 +459,21 @@ bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) { SkString shader; builder.getShader(GrGLShaderBuilder::kVertex_ShaderType, &shader); -#if PRINT_SHADERS - GrPrintf(shader.c_str()); - GrPrintf("\n"); -#endif + if (c_PrintShaders) { + GrPrintf(shader.c_str()); + GrPrintf("\n"); + } + if (!(fVShaderID = compile_shader(fContextInfo, GR_GL_VERTEX_SHADER, shader))) { return false; } if (builder.fUsesGS) { builder.getShader(GrGLShaderBuilder::kGeometry_ShaderType, &shader); -#if PRINT_SHADERS - GrPrintf(shader.c_str()); - GrPrintf("\n"); -#endif + if (c_PrintShaders) { + GrPrintf(shader.c_str()); + GrPrintf("\n"); + } if (!(fGShaderID = compile_shader(fContextInfo, GR_GL_GEOMETRY_SHADER, shader))) { return false; } @@ -479,10 +482,10 @@ bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) { } builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader); -#if PRINT_SHADERS - GrPrintf(shader.c_str()); - GrPrintf("\n"); -#endif + if (c_PrintShaders) { + GrPrintf(shader.c_str()); + GrPrintf("\n"); + } if (!(fFShaderID = compile_shader(fContextInfo, GR_GL_FRAGMENT_SHADER, shader))) { return false; } diff --git a/src/ports/SkOSFile_stdio.cpp b/src/ports/SkOSFile_stdio.cpp index 9100f6d122..e7f65cd499 100644 --- a/src/ports/SkOSFile_stdio.cpp +++ b/src/ports/SkOSFile_stdio.cpp @@ -41,6 +41,23 @@ SkFILE* sk_fopen(const char path[], SkFILE_Flags flags) return f; } +ptrdiff_t sk_getline(char **lineptr, size_t *n, SkFILE *f) { + bool make_private_copy = (NULL == *lineptr); + + ptrdiff_t ret = ::getline(lineptr, n, (FILE *) f); + if (make_private_copy) { + char *local_copy = (char *) sk_malloc_throw(strlen(*lineptr) + 1); + ::memcpy(local_copy, *lineptr, strlen(*lineptr)); + ::free(*lineptr); + *lineptr = local_copy; + } + return ret; +} + +int sk_feof(SkFILE *f) { + return ::feof((FILE *)f); +} + size_t sk_fgetsize(SkFILE* f) { SkASSERT(f); diff --git a/src/utils/SkRTConf.cpp b/src/utils/SkRTConf.cpp new file mode 100644 index 0000000000..fcc51c33c3 --- /dev/null +++ b/src/utils/SkRTConf.cpp @@ -0,0 +1,325 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkRTConf.h" +#include "SkOSFile.h" + +SkRTConfRegistry::SkRTConfRegistry(): fConfs(100) { + + SkFILE *fp = sk_fopen(configFileLocation(), kRead_SkFILE_Flag); + + if (!fp) { + return; + } + + char *line = NULL; + size_t n = 0; + + while (!sk_feof(fp)) { + if (line) { + sk_free(line); + } + line = NULL; + + if (sk_getline(&line, &n, fp) == -1) break; + + char *commentptr = strchr(line, '#'); + if (commentptr == line) { + continue; + } + if (NULL != commentptr) { + char *tmp = (char *) sk_malloc_throw(commentptr-line+1); + strncpy(tmp, line, commentptr-line); + sk_free(line); + line = tmp; + } + + char sep[] = " \t"; + + char *keyptr = strtok(line, sep); + if (!keyptr) { + continue; + } + + char *valptr = strtok(NULL, sep); + if (!valptr) { + continue; + } + + SkString* key = new SkString(keyptr); + SkString* val = new SkString(valptr); + + fConfigFileKeys.append(1, &key); + fConfigFileValues.append(1, &val); + } + sk_fclose(fp); +} + +const char *SkRTConfRegistry::configFileLocation() const { + return "skia.conf"; // for now -- should probably do something fancier like home directories or whatever. +} + +// dump all known runtime config options to the file with their default values. +// to trigger this, make a config file of zero size. +void SkRTConfRegistry::possiblyDumpFile() const { + const char *path = configFileLocation(); + SkFILE *fp = sk_fopen(path, kRead_SkFILE_Flag); + if (!fp) { + return; + } + size_t configFileSize = sk_fgetsize(fp); + if (configFileSize == 0) { + printAll(path); + } + sk_fclose(fp); +} + +// Run through every provided configuration option and print a warning if the user hasn't +// declared a correponding configuration object somewhere. +void SkRTConfRegistry::validate() const { + for (int i = 0 ; i < fConfigFileKeys.count() ; i++) { + if (fConfs.find(fConfigFileKeys[i]->c_str()) == -1) { + SkDebugf("WARNING: You have config value %s in your configuration file, but I've never heard of that.\n", fConfigFileKeys[i]->c_str()); + } + } +} + +void SkRTConfRegistry::printAll(const char *fname) const { + SkWStream *o; + + if (NULL != fname) { + o = new SkFILEWStream(fname); + } else { + o = new SkDebugWStream(); + } + + ConfMap::Iter iter(fConfs); + SkTDArray<SkRTConfBase *> *confArray; + + while (iter.next(&confArray)) { + if (confArray->getAt(0)->isDefault()) { + o->writeText("# "); + } + confArray->getAt(0)->print(o); + o->newline(); + } + + delete o; +} + +void SkRTConfRegistry::printNonDefault(const char *fname) const { + SkWStream *o; + + if (NULL != fname) { + o = new SkFILEWStream(fname); + } else { + o = new SkDebugWStream(); + } + ConfMap::Iter iter(fConfs); + SkTDArray<SkRTConfBase *> *confArray; + + while (iter.next(&confArray)) { + if (!confArray->getAt(0)->isDefault()) { + confArray->getAt(0)->print(o); + o->newline(); + } + } + + delete o; +} + +// register a configuration variable after its value has been set by the parser. +// we maintain a vector of these things instead of just a single one because the +// user might set the value after initialization time and we need to have +// all the pointers lying around, not just one. +void SkRTConfRegistry::registerConf(SkRTConfBase *conf) { + SkTDArray<SkRTConfBase *> *confArray; + if (fConfs.find(conf->getName(), &confArray)) { + if (!conf->equals(confArray->getAt(0))) { + SkDebugf("WARNING: Skia config \"%s\" was registered more than once in incompatible ways.\n", conf->getName()); + } else { + confArray->append(1, &conf); + } + } else { + confArray = new SkTDArray<SkRTConfBase *>; + confArray->append(1, &conf); + fConfs.set(conf->getName(),confArray); + } +} + +template <typename T> T doParse(const char *s, bool *success ) { + SkDebugf("WARNING: Invoked non-specialized doParse function...\n"); + if (success) { + *success = false; + } + return (T) 0; +} + +template<> bool doParse<bool>(const char *s, bool *success) { + if (success) { + *success = true; + } + if (!strcmp(s,"1") || !strcmp(s,"true")) { + return true; + } + if (!strcmp(s,"0") || !strcmp(s,"false")) { + return false; + } + if (success) { + *success = false; + } + return false; +} + +template<> const char * doParse<const char *>(const char * s, bool *success) { + if (success) { + *success = true; + } + return s; +} + +template<> int doParse<int>(const char * s, bool *success) { + return atoi(s); +} + +template<> unsigned int doParse<unsigned int>(const char * s, bool *success) { + return (unsigned int) atoi(s); +} + +template<> float doParse<float>(const char * s, bool *success) { + return (float) atof(s); +} + +template<> double doParse<double>(const char * s, bool *success) { + return atof(s); +} + +static inline void str_replace(char *s, char search, char replace) { + for (char *ptr = s ; *ptr ; ptr++) { + if (*ptr == search) { + *ptr = replace; + } + } +} + +template<typename T> bool SkRTConfRegistry::parse(const char *name, T* value) { + SkString *str = NULL; + + for (int i = 0 ; i < fConfigFileKeys.count() ; i++) { + if (fConfigFileKeys[i]->equals(name)) { + str = fConfigFileValues[i]; + } + } + + SkString environment_variable("skia."); + environment_variable.append(name); + + const char *environment_value = getenv(environment_variable.c_str()); + if (environment_value) { + str->set(environment_value); + } else { + // apparently my shell doesn't let me have environment variables that + // have periods in them, so also let the user substitute underscores. + SkString underscore_environment_variable("skia_"); + char *underscore_name = SkStrDup(name); + str_replace(underscore_name,'.','_'); + underscore_environment_variable.append(underscore_name); + sk_free(underscore_name); + environment_value = getenv(underscore_environment_variable.c_str()); + if (environment_value) { + str->set(environment_value); + } + } + + if (!str) { + return false; + } + + bool success; + T new_value = doParse<T>(str->c_str(),&success); + if (success) { + *value = new_value; + } else { + SkDebugf("WARNING: Couldn't parse value \'%s\' for variable \'%s\'\n", str->c_str(), name); + } + return success; +} + +// need to explicitly instantiate the parsing function for every config type we might have... + +template bool SkRTConfRegistry::parse(const char *name, bool *value); +template bool SkRTConfRegistry::parse(const char *name, int *value); +template bool SkRTConfRegistry::parse(const char *name, unsigned int *value); +template bool SkRTConfRegistry::parse(const char *name, float *value); +template bool SkRTConfRegistry::parse(const char *name, double *value); +template bool SkRTConfRegistry::parse(const char *name, const char **value); + +template <typename T> void SkRTConfRegistry::set(const char *name, T value) { + + SkTDArray<SkRTConfBase *> *confArray; + if (!fConfs.find(name, &confArray)) { + SkDebugf("WARNING: Attempting to set configuration value \"%s\", but I've never heard of that.\n", name); + return; + } + + for (SkRTConfBase **confBase = confArray->begin(); confBase != confArray->end(); confBase++) { + + SkRTConf<bool> *concrete = dynamic_cast<SkRTConf<bool> *>(*confBase); + + if (concrete) { + concrete->set(value); + } + } +} + +template void SkRTConfRegistry::set(const char *name, bool value); +template void SkRTConfRegistry::set(const char *name, int value); +template void SkRTConfRegistry::set(const char *name, unsigned int value); +template void SkRTConfRegistry::set(const char *name, float value); +template void SkRTConfRegistry::set(const char *name, double value); +template void SkRTConfRegistry::set(const char *name, char * value); + +template<> void SkRTConf<bool>::doPrint(char *s) const { + char tmp[30]; + sprintf(tmp, "%s # [%s]", fValue ? "true" : "false", fDefault ? "true" : "false"); + sprintf(s, "%-30.30s", tmp); +} + +template<> void SkRTConf<int>::doPrint(char *s) const { + char tmp[30]; + sprintf(tmp, "%d # [%d]", fValue, fDefault); + sprintf(s, "%-30.30s", tmp); +} + +template<> void SkRTConf<unsigned int>::doPrint(char *s) const { + char tmp[30]; + sprintf(tmp, "%u # [%u]", fValue, fDefault); + sprintf(s, "%-30.30s", tmp); +} + +template<> void SkRTConf<float>::doPrint(char *s) const { + char tmp[30]; + sprintf(tmp, "%6.6f # [%6.6f]", fValue, fDefault); + sprintf(s, "%-30.30s", tmp); +} + +template<> void SkRTConf<double>::doPrint(char *s) const { + char tmp[30]; + sprintf(tmp, "%6.6f # [%6.6f]", fValue, fDefault); + sprintf(s, "%-30.30s", tmp); +} + +template<> void SkRTConf<const char *>::doPrint(char *s) const { + char tmp[30]; + sprintf(tmp, "%s # [%s]", fValue, fDefault); + sprintf(s, "%-30.30s", tmp); +} + +SkRTConfRegistry &skRTConfRegistry() { + static SkRTConfRegistry r; + return r; +} |